From 61e2ffe56b1bca26a21d0a3934e751ab27414bed Mon Sep 17 00:00:00 2001 From: Michael Elrom Date: Thu, 24 Sep 2026 21:21:13 -0400 Subject: [PATCH] feat(salt): add Salt Integration Model and Studio Project --- README.md | 1 + Salt/OpenAPIs/salt-3008.1.json | 666 +++++++++++++ Salt/OpenAPIs/salt-latest.json | 667 +++++++++++++ Salt/README.md | 110 +++ Salt/Studio Projects/Salt.project.json | 1227 ++++++++++++++++++++++++ 5 files changed, 2671 insertions(+) create mode 100644 Salt/OpenAPIs/salt-3008.1.json create mode 100644 Salt/OpenAPIs/salt-latest.json create mode 100644 Salt/README.md create mode 100644 Salt/Studio Projects/Salt.project.json diff --git a/README.md b/README.md index 238a0d6..1c2b259 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ Assets are organized by vendor and product. Each folder may contain one or more | **Ruckus** | Fastiron | | **Rundeck** | Job automation & orchestration | | **Salesforce** | CRM (REST API · Tooling API) | +| **Salt** | salt-api (rest_cherrypy netapi) | | **ScienceLogic** | Skylar One (formerly SL1) | | **Sectigo** | Certificate Manager · SCM Admin | | **Selector** | AIOps | diff --git a/Salt/OpenAPIs/salt-3008.1.json b/Salt/OpenAPIs/salt-3008.1.json new file mode 100644 index 0000000..bffbbda --- /dev/null +++ b/Salt/OpenAPIs/salt-3008.1.json @@ -0,0 +1,666 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Salt", + "description": "Salt is an open-source infrastructure automation and remote execution engine. Its salt-api service exposes the master's execution, runner, and wheel functions over a REST interface (the rest_cherrypy netapi module), so external systems can run commands against minions, manage minion authentication keys, and track jobs without a local Salt client.", + "version": "3008.1", + "x-itential-curated": "Reviewed against the repo's common-CRUD-for-automation policy: all 9 upstream rest_cherrypy operations (command execution, job tracking, minion inventory, and key management) are already in scope, so the full documented spec is carried through as -latest. See the repo README for the operation breakdown and the full spec." + }, + "servers": [ + { + "url": "{protocol}://{host}:{port}", + "description": "Salt master running the rest_cherrypy netapi module.", + "variables": { + "protocol": { + "default": "https", + "enum": [ + "http", + "https" + ], + "description": "Scheme the netapi module is served over." + }, + "host": { + "default": "salt-master.example.com", + "description": "Salt master hostname or IP." + }, + "port": { + "default": "8000", + "description": "Port the rest_cherrypy netapi module listens on." + } + } + } + ], + "security": [ + { + "SaltToken": [] + } + ], + "tags": [ + { + "name": "Execution", + "description": "Run execution-module, runner, or wheel functions against the Salt master or targeted minions." + }, + { + "name": "Minions", + "description": "Minion inventory and grain data known to the master." + }, + { + "name": "Jobs", + "description": "Tracking of published jobs and their per-minion results." + }, + { + "name": "Keys", + "description": "Minion authentication key management." + } + ], + "paths": { + "/": { + "post": { + "tags": [ + "Execution" + ], + "summary": "Run Command", + "description": "Publish one or more lowstate commands (client/tgt/fun/arg) and wait for the result. Supports the local, runner, wheel, and ssh clients.", + "operationId": "runCommand", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LowstateCommand" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReturnEnvelope" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/minions": { + "get": { + "tags": [ + "Minions" + ], + "summary": "List Minions", + "description": "List all known minions and their full grain data.", + "operationId": "listMinions", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MinionsListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + }, + "post": { + "tags": [ + "Execution" + ], + "summary": "Run Command Async", + "description": "Start an execution-module function against targeted minions asynchronously (client is forced to local_async). Returns a job ID immediately instead of waiting for minion replies.", + "operationId": "runCommandAsync", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LowstateCommand" + } + } + } + } + }, + "responses": { + "202": { + "description": "Job accepted.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncJobResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/minions/{mid}": { + "get": { + "tags": [ + "Minions" + ], + "summary": "Get Minion", + "description": "Retrieve grain data for a single minion.", + "operationId": "getMinion", + "parameters": [ + { + "name": "mid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Minion ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MinionDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/jobs": { + "get": { + "tags": [ + "Jobs" + ], + "summary": "List Jobs", + "description": "List all jobs the master has published, from the job cache.", + "operationId": "listJobs", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobsListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/jobs/{jid}": { + "get": { + "tags": [ + "Jobs" + ], + "summary": "Get Job", + "description": "Retrieve metadata and per-minion results for a job, by job ID.", + "operationId": "getJob", + "parameters": [ + { + "name": "jid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Job ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/keys": { + "get": { + "tags": [ + "Keys" + ], + "summary": "List Keys", + "description": "List all minion authentication keys known to the master, grouped by accepted, pending, rejected, and denied.", + "operationId": "listKeys", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KeysListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + }, + "post": { + "tags": [ + "Keys" + ], + "summary": "Generate Key", + "description": "Generate a new minion keypair on the master, automatically accept it, and return it as a tarball.", + "operationId": "generateKey", + "requestBody": { + "required": true, + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/GenerateKeyRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Tarball containing the new minion keypair.", + "content": {} + }, + "default": { + "description": "Error response." + } + } + } + }, + "/keys/{mid}": { + "get": { + "tags": [ + "Keys" + ], + "summary": "Get Key", + "description": "Retrieve the fingerprint of a single minion's key.", + "operationId": "getKey", + "parameters": [ + { + "name": "mid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Minion ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KeyDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + } + }, + "components": { + "securitySchemes": { + "SaltToken": { + "type": "apiKey", + "in": "header", + "name": "X-Auth-Token", + "description": "Session token obtained by POSTing form-urlencoded eauth credentials to /login; replayed on the X-Auth-Token header of every subsequent request.", + "x-itential-dynamic-retrieval": { + "method": "POST", + "url": "{protocol}://{host}:{port}/login", + "responsePointer": "/return/0/token" + }, + "x-itential-parameters": [ + { + "name": "username", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string" + }, + "description": "Salt eauth username." + }, + { + "name": "password", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string" + }, + "description": "Salt eauth password." + }, + { + "name": "eauth", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string", + "default": "pam" + }, + "description": "External authentication module to validate the credentials against, e.g. 'pam', 'ldap', 'auto'." + } + ] + } + }, + "schemas": { + "LowstateCommand": { + "type": "object", + "required": [ + "fun" + ], + "properties": { + "client": { + "type": "string", + "description": "Salt netapi client to dispatch through. Defaults to 'local' (synchronous execution-module call against targeted minions) when omitted.", + "enum": [ + "local", + "local_async", + "runner", + "runner_async", + "wheel", + "wheel_async", + "ssh" + ] + }, + "tgt": { + "type": "string", + "description": "Target expression (minion ID, glob, grain/compound match, etc.). Required for local/local_async/ssh clients; not used by runner/wheel clients." + }, + "tgt_type": { + "type": "string", + "description": "How to interpret tgt.", + "enum": [ + "glob", + "pcre", + "list", + "grain", + "grain_pcre", + "pillar", + "pillar_pcre", + "compound", + "nodegroup", + "ipcidr" + ] + }, + "fun": { + "type": "string", + "description": "Execution module function (local/ssh clients), runner function (runner client), or wheel function (wheel client) to call, e.g. 'test.ping', 'jobs.list_jobs', 'key.list_all'." + }, + "arg": { + "type": "array", + "items": {}, + "description": "Positional arguments passed to fun." + }, + "kwarg": { + "type": "object", + "additionalProperties": true, + "description": "Keyword arguments passed to fun." + }, + "timeout": { + "type": "integer", + "description": "Seconds to wait for minion replies (local/ssh clients)." + } + } + }, + "ReturnEnvelope": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "One result object per lowstate command submitted, keyed by minion ID (local/ssh) or containing the runner/wheel function's return value." + } + } + }, + "MinionsListResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": true + }, + "description": "Map of minion ID to its full grain set." + } + } + } + }, + "MinionDetailResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "AsyncJobResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "properties": { + "jid": { + "type": "string", + "description": "Job ID assigned to the async execution." + }, + "minions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Minion IDs the job was published to." + } + } + } + }, + "_links": { + "type": "object", + "description": "HATEOAS links, including the /jobs/ URL for polling the result." + } + } + }, + "JobsListResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Function": { + "type": "string" + }, + "Arguments": { + "type": "array", + "items": {} + }, + "Target": { + "type": "string" + }, + "Target-type": { + "type": "string" + }, + "User": { + "type": "string" + }, + "StartTime": { + "type": "string" + } + }, + "additionalProperties": true + }, + "description": "Map of job ID to job summary." + } + } + } + }, + "JobDetailResponse": { + "type": "object", + "properties": { + "info": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "Job metadata (function, arguments, target, jid)." + }, + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "Per-minion return values for the job." + } + } + }, + "KeysListResponse": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "local": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Master's own key files." + }, + "minions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Accepted minion keys." + }, + "minions_pre": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Pending (unaccepted) minion keys." + }, + "minions_rejected": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Rejected minion keys." + }, + "minions_denied": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Denied minion keys." + } + } + } + } + }, + "KeyDetailResponse": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "minions": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Map of minion ID to its key fingerprint." + } + } + } + } + }, + "GenerateKeyRequest": { + "type": "object", + "required": [ + "mid" + ], + "properties": { + "mid": { + "type": "string", + "description": "Minion ID to generate and accept a keypair for." + }, + "keysize": { + "type": "integer", + "description": "RSA key size in bits." + }, + "force": { + "type": "boolean", + "description": "Overwrite an existing key of the same minion ID." + } + } + } + } + } +} diff --git a/Salt/OpenAPIs/salt-latest.json b/Salt/OpenAPIs/salt-latest.json new file mode 100644 index 0000000..98270b3 --- /dev/null +++ b/Salt/OpenAPIs/salt-latest.json @@ -0,0 +1,667 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Salt", + "description": "Salt is an open-source infrastructure automation and remote execution engine. Its salt-api service exposes the master's execution, runner, and wheel functions over a REST interface (the rest_cherrypy netapi module), so external systems can run commands against minions, manage minion authentication keys, and track jobs without a local Salt client.", + "version": "latest", + "x-vendor-api-version": "3008.1", + "x-itential-curated": "Reviewed against the repo's common-CRUD-for-automation policy: all 9 upstream rest_cherrypy operations (command execution, job tracking, minion inventory, and key management) are already in scope, so the full documented spec is carried through as -latest. See the repo README for the operation breakdown and the full spec." + }, + "servers": [ + { + "url": "{protocol}://{host}:{port}", + "description": "Salt master running the rest_cherrypy netapi module.", + "variables": { + "protocol": { + "default": "https", + "enum": [ + "http", + "https" + ], + "description": "Scheme the netapi module is served over." + }, + "host": { + "default": "salt-master.example.com", + "description": "Salt master hostname or IP." + }, + "port": { + "default": "8000", + "description": "Port the rest_cherrypy netapi module listens on." + } + } + } + ], + "security": [ + { + "SaltToken": [] + } + ], + "tags": [ + { + "name": "Execution", + "description": "Run execution-module, runner, or wheel functions against the Salt master or targeted minions." + }, + { + "name": "Minions", + "description": "Minion inventory and grain data known to the master." + }, + { + "name": "Jobs", + "description": "Tracking of published jobs and their per-minion results." + }, + { + "name": "Keys", + "description": "Minion authentication key management." + } + ], + "paths": { + "/": { + "post": { + "tags": [ + "Execution" + ], + "summary": "Run Command", + "description": "Publish one or more lowstate commands (client/tgt/fun/arg) and wait for the result. Supports the local, runner, wheel, and ssh clients.", + "operationId": "runCommand", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LowstateCommand" + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReturnEnvelope" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/minions": { + "get": { + "tags": [ + "Minions" + ], + "summary": "List Minions", + "description": "List all known minions and their full grain data.", + "operationId": "listMinions", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MinionsListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + }, + "post": { + "tags": [ + "Execution" + ], + "summary": "Run Command Async", + "description": "Start an execution-module function against targeted minions asynchronously (client is forced to local_async). Returns a job ID immediately instead of waiting for minion replies.", + "operationId": "runCommandAsync", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LowstateCommand" + } + } + } + } + }, + "responses": { + "202": { + "description": "Job accepted.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncJobResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/minions/{mid}": { + "get": { + "tags": [ + "Minions" + ], + "summary": "Get Minion", + "description": "Retrieve grain data for a single minion.", + "operationId": "getMinion", + "parameters": [ + { + "name": "mid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Minion ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MinionDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/jobs": { + "get": { + "tags": [ + "Jobs" + ], + "summary": "List Jobs", + "description": "List all jobs the master has published, from the job cache.", + "operationId": "listJobs", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobsListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/jobs/{jid}": { + "get": { + "tags": [ + "Jobs" + ], + "summary": "Get Job", + "description": "Retrieve metadata and per-minion results for a job, by job ID.", + "operationId": "getJob", + "parameters": [ + { + "name": "jid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Job ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + }, + "/keys": { + "get": { + "tags": [ + "Keys" + ], + "summary": "List Keys", + "description": "List all minion authentication keys known to the master, grouped by accepted, pending, rejected, and denied.", + "operationId": "listKeys", + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KeysListResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + }, + "post": { + "tags": [ + "Keys" + ], + "summary": "Generate Key", + "description": "Generate a new minion keypair on the master, automatically accept it, and return it as a tarball.", + "operationId": "generateKey", + "requestBody": { + "required": true, + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/GenerateKeyRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Tarball containing the new minion keypair.", + "content": {} + }, + "default": { + "description": "Error response." + } + } + } + }, + "/keys/{mid}": { + "get": { + "tags": [ + "Keys" + ], + "summary": "Get Key", + "description": "Retrieve the fingerprint of a single minion's key.", + "operationId": "getKey", + "parameters": [ + { + "name": "mid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Minion ID." + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KeyDetailResponse" + } + } + } + }, + "default": { + "description": "Error response." + } + } + } + } + }, + "components": { + "securitySchemes": { + "SaltToken": { + "type": "apiKey", + "in": "header", + "name": "X-Auth-Token", + "description": "Session token obtained by POSTing form-urlencoded eauth credentials to /login; replayed on the X-Auth-Token header of every subsequent request.", + "x-itential-dynamic-retrieval": { + "method": "POST", + "url": "{protocol}://{host}:{port}/login", + "responsePointer": "/return/0/token" + }, + "x-itential-parameters": [ + { + "name": "username", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string" + }, + "description": "Salt eauth username." + }, + { + "name": "password", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string" + }, + "description": "Salt eauth password." + }, + { + "name": "eauth", + "in": "body", + "x-itential-use-in": [ + "key" + ], + "schema": { + "type": "string", + "default": "pam" + }, + "description": "External authentication module to validate the credentials against, e.g. 'pam', 'ldap', 'auto'." + } + ] + } + }, + "schemas": { + "LowstateCommand": { + "type": "object", + "required": [ + "fun" + ], + "properties": { + "client": { + "type": "string", + "description": "Salt netapi client to dispatch through. Defaults to 'local' (synchronous execution-module call against targeted minions) when omitted.", + "enum": [ + "local", + "local_async", + "runner", + "runner_async", + "wheel", + "wheel_async", + "ssh" + ] + }, + "tgt": { + "type": "string", + "description": "Target expression (minion ID, glob, grain/compound match, etc.). Required for local/local_async/ssh clients; not used by runner/wheel clients." + }, + "tgt_type": { + "type": "string", + "description": "How to interpret tgt.", + "enum": [ + "glob", + "pcre", + "list", + "grain", + "grain_pcre", + "pillar", + "pillar_pcre", + "compound", + "nodegroup", + "ipcidr" + ] + }, + "fun": { + "type": "string", + "description": "Execution module function (local/ssh clients), runner function (runner client), or wheel function (wheel client) to call, e.g. 'test.ping', 'jobs.list_jobs', 'key.list_all'." + }, + "arg": { + "type": "array", + "items": {}, + "description": "Positional arguments passed to fun." + }, + "kwarg": { + "type": "object", + "additionalProperties": true, + "description": "Keyword arguments passed to fun." + }, + "timeout": { + "type": "integer", + "description": "Seconds to wait for minion replies (local/ssh clients)." + } + } + }, + "ReturnEnvelope": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "One result object per lowstate command submitted, keyed by minion ID (local/ssh) or containing the runner/wheel function's return value." + } + } + }, + "MinionsListResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": true + }, + "description": "Map of minion ID to its full grain set." + } + } + } + }, + "MinionDetailResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "AsyncJobResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "properties": { + "jid": { + "type": "string", + "description": "Job ID assigned to the async execution." + }, + "minions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Minion IDs the job was published to." + } + } + } + }, + "_links": { + "type": "object", + "description": "HATEOAS links, including the /jobs/ URL for polling the result." + } + } + }, + "JobsListResponse": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Function": { + "type": "string" + }, + "Arguments": { + "type": "array", + "items": {} + }, + "Target": { + "type": "string" + }, + "Target-type": { + "type": "string" + }, + "User": { + "type": "string" + }, + "StartTime": { + "type": "string" + } + }, + "additionalProperties": true + }, + "description": "Map of job ID to job summary." + } + } + } + }, + "JobDetailResponse": { + "type": "object", + "properties": { + "info": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "Job metadata (function, arguments, target, jid)." + }, + "return": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + }, + "description": "Per-minion return values for the job." + } + } + }, + "KeysListResponse": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "local": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Master's own key files." + }, + "minions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Accepted minion keys." + }, + "minions_pre": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Pending (unaccepted) minion keys." + }, + "minions_rejected": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Rejected minion keys." + }, + "minions_denied": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Denied minion keys." + } + } + } + } + }, + "KeyDetailResponse": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "minions": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Map of minion ID to its key fingerprint." + } + } + } + } + }, + "GenerateKeyRequest": { + "type": "object", + "required": [ + "mid" + ], + "properties": { + "mid": { + "type": "string", + "description": "Minion ID to generate and accept a keypair for." + }, + "keysize": { + "type": "integer", + "description": "RSA key size in bits." + }, + "force": { + "type": "boolean", + "description": "Overwrite an existing key of the same minion ID." + } + } + } + } + } +} diff --git a/Salt/README.md b/Salt/README.md new file mode 100644 index 0000000..b40b978 --- /dev/null +++ b/Salt/README.md @@ -0,0 +1,110 @@ +# Salt + +Salt is an open-source infrastructure automation and remote execution engine. Its salt-api service exposes the master's execution, runner, and wheel functions over a REST interface (the `rest_cherrypy` netapi module), letting external systems run commands against minions, manage minion authentication keys, and track jobs without a local Salt client. + +This project provides a Studio Project of workflows covering the REST API operations most useful for automation, plus an OpenAPI spec for building your own automation via an Integration Model — see **Studio Projects** and **OpenAPIs** below. + +## Table of Contents + +- [Salt](#salt) + - [Table of Contents](#table-of-contents) + - [Contents](#contents) + - [Requirements](#requirements) + - [Integration Configuration](#integration-configuration) + - [Connection Properties](#connection-properties) + - [OpenAPIs](#openapis) + - [`salt-latest.json`](#salt-latestjson) + - [`salt-3008.1.json`](#salt-30081json) + - [Studio Projects](#studio-projects) + - [Salt Project](#salt-project) + - [Folder Structure](#folder-structure) + - [Dependencies](#dependencies) + +## Contents + +| Asset | Description | +|---|---| +| [OpenAPIs/](./OpenAPIs/) | Salt `rest_cherrypy` netapi OpenAPI specs — curated `-latest` plus the matching dated spec | +| [Studio Projects/](./Studio%20Projects/) | Itential Platform project containing all 9 workflows in 4 folders | + +## Requirements + +| Requirement | Version | +|---|---| +| Itential Platform | P6+ | +| Salt master with `salt-api` and the `rest_cherrypy` netapi module enabled | Any release exposing `/login`, `/`, `/minions`, `/jobs`, and `/keys` | +| `Salt:latest` Integration Model | Required to build automation against the OpenAPI spec | +| A Salt eauth account (PAM, LDAP, or another configured external auth module) | Used for the session-token login | + +> **Note:** This project does not require Itential Gateway. All API calls are made directly from Itential Platform to the Salt master. + +## Integration Configuration + +Import the OpenAPI spec from `OpenAPIs/` as an Integration Model in **Admin > Integrations**, then create an integration pointing at your Salt master. + +### Connection Properties + +```json +{ + "server": { + "protocol": "https", + "host": "", + "port": "8000" + }, + "authentication": { + "SaltToken": { + "username": "", + "password": "", + "eauth": "" + } + } +} +``` + +Itential Platform logs in against `/login` with these credentials, extracts the session token from the response, and replays it on the `X-Auth-Token` header of every subsequent request. + +## OpenAPIs + +| Spec | Version | Operations | Description | +|---|---|---|---| +| [`salt-latest.json`](./OpenAPIs/salt-latest.json) | latest (curated) | 9 | Actively-maintained spec — see breakdown below | +| [`salt-3008.1.json`](./OpenAPIs/salt-3008.1.json) | 3008.1 | 9 | Dated spec matching the documented `rest_cherrypy` REST surface | + +### `salt-latest.json` + +Actively-maintained spec (`x-vendor-api-version: 3008.1`). Reviewed against the repo's common-CRUD-for-automation policy: all 9 documented `rest_cherrypy` operations are already in scope, so the full spec is carried through as `-latest`. + +Resources included, by category: + +- **Execution**: Run a lowstate command against targeted minions (or a runner/wheel/ssh function) and wait for the result; start the same call asynchronously and get back a job ID +- **Minions**: List all minions and their grains, get a single minion's grains +- **Jobs**: List published jobs, get a job's metadata and per-minion results +- **Keys**: List minion authentication keys by status, get a single minion's key fingerprint, generate and auto-accept a new minion keypair + +### `salt-3008.1.json` + +Dated spec matching the documented `rest_cherrypy` REST surface as of Salt 3008.1. + +--- + +## Studio Projects + +### Salt Project + +Backed by the **`Salt:latest`** Integration Model (see [`salt-latest.json`](./OpenAPIs/salt-latest.json) above). The project contains **9 workflows** organized into **4 folders**, one atomic workflow per API operation. All workflows follow the naming convention ` ` (e.g. `List Minions`, `Get Job`). + +#### Folder Structure + +| Folder | Workflows | Scope | +|---|---|---| +| Execution | Run Command, Run Command Async | Lowstate command execution, synchronous and asynchronous | +| Minions | List Minions, Get Minion | Minion inventory and grain data | +| Jobs | List Jobs, Get Job | Published job tracking and results | +| Keys | List Keys, Get Key, Generate Key | Minion authentication key management | + +#### Dependencies + +| Dependency | Notes | +|---|---| +| `Salt:latest` Integration Model | Import from [`salt-latest.json`](./OpenAPIs/salt-latest.json) before importing the project | +| `Salt` integration instance | Create in **Admin > Integrations** with the connection properties above. Workflows are wired to an integration instance named `Salt` — update the `adapter_id` value in each workflow task if yours is named differently | diff --git a/Salt/Studio Projects/Salt.project.json b/Salt/Studio Projects/Salt.project.json new file mode 100644 index 0000000..7e8bc47 --- /dev/null +++ b/Salt/Studio Projects/Salt.project.json @@ -0,0 +1,1227 @@ +{ + "_id": "15dd3d9f3831404fa73b7eaf", + "name": "Salt", + "description": "Workflows covering Salt's rest_cherrypy netapi command execution, job tracking, minion inventory, and key management REST API operations, organized by category.", + "components": [ + { + "iid": 0, + "type": "workflow", + "reference": "2198d410-d9a2-4e1f-abba-5f60a23a3ea2", + "folder": "/Execution", + "document": { + "name": "Run Command", + "description": "Run Command", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "runCommand", + "canvasName": "runCommand", + "summary": "Run Command", + "description": "Publish one or more lowstate commands and wait for the result.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "bodyContentType": "application/json", + "requestBodyPayload": "$var.job.commands" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "commands": { + "type": "array", + "description": "Lowstate commands to run.", + "items": { + "type": "object", + "properties": { + "client": { + "type": "string", + "enum": [ + "local", + "local_async", + "runner", + "runner_async", + "wheel", + "wheel_async", + "ssh" + ], + "description": "Salt netapi client to dispatch through." + }, + "tgt": { + "type": "string", + "description": "Target expression (minion ID, glob, grain/compound match, etc.)." + }, + "tgt_type": { + "type": "string", + "enum": [ + "glob", + "pcre", + "list", + "grain", + "grain_pcre", + "pillar", + "pillar_pcre", + "compound", + "nodegroup", + "ipcidr" + ], + "description": "How to interpret tgt." + }, + "fun": { + "type": "string", + "description": "Execution/runner/wheel function to call, e.g. 'test.ping'." + }, + "arg": { + "type": "array", + "items": {}, + "description": "Positional arguments passed to fun." + }, + "kwarg": { + "type": "object", + "description": "Keyword arguments passed to fun." + }, + "timeout": { + "type": "integer", + "description": "Seconds to wait for minion replies." + } + } + } + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object" + }, + "description": "One result object per lowstate command submitted." + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "6cb43672-fca6-4b90-a384-9bc743339878", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 1, + "type": "workflow", + "reference": "73d1200f-d1d9-4d0b-860d-d2e6acb54e53", + "folder": "/Execution", + "document": { + "name": "Run Command Async", + "description": "Run Command Async", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "runCommandAsync", + "canvasName": "runCommandAsync", + "summary": "Run Command Async", + "description": "Start an execution-module function against targeted minions asynchronously and return a job ID immediately.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "bodyContentType": "application/json", + "requestBodyPayload": "$var.job.commands" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "commands": { + "type": "array", + "description": "Lowstate commands to run asynchronously.", + "items": { + "type": "object", + "properties": { + "client": { + "type": "string", + "enum": [ + "local", + "local_async", + "runner", + "runner_async", + "wheel", + "wheel_async", + "ssh" + ], + "description": "Salt netapi client to dispatch through." + }, + "tgt": { + "type": "string", + "description": "Target expression (minion ID, glob, grain/compound match, etc.)." + }, + "tgt_type": { + "type": "string", + "enum": [ + "glob", + "pcre", + "list", + "grain", + "grain_pcre", + "pillar", + "pillar_pcre", + "compound", + "nodegroup", + "ipcidr" + ], + "description": "How to interpret tgt." + }, + "fun": { + "type": "string", + "description": "Execution/runner/wheel function to call, e.g. 'test.ping'." + }, + "arg": { + "type": "array", + "items": {}, + "description": "Positional arguments passed to fun." + }, + "kwarg": { + "type": "object", + "description": "Keyword arguments passed to fun." + }, + "timeout": { + "type": "integer", + "description": "Seconds to wait for minion replies." + } + } + } + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "properties": { + "jid": { + "type": "string", + "description": "Job ID assigned to the async execution." + }, + "minions": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "_links": { + "type": "object", + "description": "HATEOAS links, including the /jobs/ URL for polling the result." + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "9e6548aa-0c60-408f-8578-dfe2c490b733", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 2, + "type": "workflow", + "reference": "7d86fd80-b85c-490c-8f03-774c37ed4b16", + "folder": "/Minions", + "document": { + "name": "List Minions", + "description": "List Minions", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "listMinions", + "canvasName": "listMinions", + "summary": "List Minions", + "description": "List all known minions and their full grain data.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "description": "Map of minion ID to its full grain set." + } + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "46b985a1-16e3-4375-b424-3c0e8c47560f", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 3, + "type": "workflow", + "reference": "5e9f6058-0b63-44d0-b0f8-835cab8bcbf5", + "folder": "/Minions", + "document": { + "name": "Get Minion", + "description": "Get Minion", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "getMinion", + "canvasName": "getMinion", + "summary": "Get Minion", + "description": "Retrieve grain data for a single minion.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "mid": "$var.job.mid" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "mid": { + "type": "string", + "description": "Minion ID." + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "49793dd9-a98d-4f78-aaeb-699797737457", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 4, + "type": "workflow", + "reference": "4fd95e21-df46-4474-a5c7-da5fed4c0eb8", + "folder": "/Jobs", + "document": { + "name": "List Jobs", + "description": "List Jobs", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "listJobs", + "canvasName": "listJobs", + "summary": "List Jobs", + "description": "List all jobs the master has published, from the job cache.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "array", + "items": { + "type": "object", + "description": "Map of job ID to job summary." + } + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "fe294eed-eaa9-4aa7-88c2-7cbb5ffb7bad", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 5, + "type": "workflow", + "reference": "ce1d2533-6230-422b-9d7f-da5929a63cbb", + "folder": "/Jobs", + "document": { + "name": "Get Job", + "description": "Get Job", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "getJob", + "canvasName": "getJob", + "summary": "Get Job", + "description": "Retrieve metadata and per-minion results for a job, by job ID.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "jid": "$var.job.jid" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "jid": { + "type": "string", + "description": "Job ID." + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "info": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Job metadata." + }, + "return": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Per-minion return values." + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "0bd552d7-ead0-4dbc-9400-8b4dd428b5d6", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 6, + "type": "workflow", + "reference": "aeef8f4e-1820-4eba-a3ef-5fcb145b764f", + "folder": "/Keys", + "document": { + "name": "List Keys", + "description": "List Keys", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "listKeys", + "canvasName": "listKeys", + "summary": "List Keys", + "description": "List all minion authentication keys known to the master, grouped by accepted, pending, rejected, and denied.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": {} + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "local": { + "type": "array", + "items": { + "type": "string" + } + }, + "minions": { + "type": "array", + "items": { + "type": "string" + } + }, + "minions_pre": { + "type": "array", + "items": { + "type": "string" + } + }, + "minions_rejected": { + "type": "array", + "items": { + "type": "string" + } + }, + "minions_denied": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "349ec18c-ff11-452a-8807-7e18820359bb", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 7, + "type": "workflow", + "reference": "693a3a74-5512-46e0-8737-ddc5c86512e3", + "folder": "/Keys", + "document": { + "name": "Get Key", + "description": "Get Key", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "getKey", + "canvasName": "getKey", + "summary": "Get Key", + "description": "Retrieve the fingerprint of a single minion's key.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "mid": "$var.job.mid" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "mid": { + "type": "string", + "description": "Minion ID." + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "return": { + "type": "object", + "properties": { + "minions": { + "type": "object", + "description": "Map of minion ID to its key fingerprint." + } + } + } + } + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "24d620f4-a896-4a75-a2a5-7e44be7b94d0", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + }, + { + "iid": 8, + "type": "workflow", + "reference": "940f7b9e-c46a-484d-9b6a-17a32f72c75f", + "folder": "/Keys", + "document": { + "name": "Generate Key", + "description": "Generate Key", + "type": "automation", + "canvasVersion": 3, + "font_size": 12, + "tasks": { + "workflow_start": { + "name": "workflow_start", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 0 + } + }, + "a1": { + "name": "generateKey", + "canvasName": "generateKey", + "summary": "Generate Key", + "description": "Generate a new minion keypair on the master, automatically accept it, and return it as a tarball.", + "location": "Adapter", + "locationType": "Salt:latest", + "app": "Salt:latest", + "type": "automatic", + "displayName": "Salt", + "variables": { + "incoming": { + "adapter_id": "Salt", + "bodyContentType": "application/x-www-form-urlencoded", + "requestBodyPayload": "$var.job.body" + }, + "outgoing": { + "response": null + }, + "error": "", + "decorators": [] + }, + "groups": [], + "actor": "Pronghorn", + "scheduled": false, + "nodeLocation": { + "x": 264, + "y": 150 + } + }, + "workflow_end": { + "name": "workflow_end", + "groups": [], + "nodeLocation": { + "x": 264, + "y": 300 + } + } + }, + "transitions": { + "workflow_start": { + "a1": { + "type": "standard", + "state": "success" + } + }, + "a1": { + "workflow_end": { + "type": "standard", + "state": "success" + } + }, + "workflow_end": {} + }, + "inputSchema": { + "type": "object", + "properties": { + "body": { + "type": "object", + "description": "Form fields for Generate Key.", + "properties": { + "mid": { + "type": "string", + "description": "Minion ID to generate and accept a keypair for." + }, + "keysize": { + "type": "integer", + "description": "RSA key size in bits." + }, + "force": { + "type": "boolean", + "description": "Overwrite an existing key of the same minion ID." + } + } + } + } + }, + "outputSchema": { + "type": "object", + "properties": {} + }, + "last_updated": "2026-09-23T12:00:00.000Z", + "last_updated_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "lastUpdatedVersion": "5.55.5", + "uuid": "17e34359-94b0-4453-a05e-8dc83b1c1aac", + "created": "2026-09-23T12:00:00.000Z", + "created_by": { + "provenance": "LDAP", + "username": "admin@itential", + "firstname": "admin@itential", + "inactive": false + }, + "createdVersion": "5.55.5", + "scenarios": [], + "tags": [], + "groups": [], + "migrationVersion": 8 + } + } + ], + "iid": 0, + "thumbnail": "", + "backgroundColor": "#ffffff", + "created": "2026-09-23T12:00:00.000Z", + "lastUpdated": "2026-09-23T12:00:00.000Z", + "createdBy": { + "_id": "6aa81494cced17e2080dcf15", + "provenance": "LDAP", + "username": "admin@itential" + }, + "lastUpdatedBy": { + "_id": "6aa81494cced17e2080dcf15", + "provenance": "LDAP", + "username": "admin@itential" + } +}