diff --git a/README.md b/README.md index ef43c73..5fbf2e5 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. |---------|-------------| | [HTTP Request With OAuth Client Credentials](http-oauth-client-credentials) | Perform HTTP requests to endpoints requiring OAuth 2.0 authentication using client credentials | | [HTTP Request via SAP Cloud Connector](http-cloud-connector) | Perform HTTP requests to internal endpoints via SAP Cloud Connector | +| [Execute a SAP Host Agent Operation via SAP Cloud Connector](sap-host-agent-via-cloud-connector) | Execute a SAP Host Agent Operation in an internal environment via SAP Cloud Connector | ### Scripting diff --git a/sap-host-agent-via-cloud-connector/README.md b/sap-host-agent-via-cloud-connector/README.md new file mode 100644 index 0000000..cfbcc52 --- /dev/null +++ b/sap-host-agent-via-cloud-connector/README.md @@ -0,0 +1,55 @@ +# Execution of a SAP Host Agent operation via Automation Pilot and SAP Cloud Connector + +Table of Contents + +* [Description](#description) +* [Requirements](#requirements) +* [How to use](#how-to-use) +* [Expected result](#expected-result) + +## Description + +This example demonstrates how SAP Automation Pilot can perform HTTP requests in order to execute SAP Host Agent Operations via the [SAP Cloud Connector](https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/cloud-connector). Any HTTP-based protocol is supported, including OData, REST, and SOAP. + +By leveraging the Cloud Connector, Automation Pilot can interact with systems that are not directly accessible from the public Internet, enabling secure automation scenarios across hybrid landscapes. + +## Requirements + +To use this example you'll need the following: + +* **SAP Automation Pilot Tenant**: Access to an SAP Automation Pilot tenant - [help](https://help.sap.com/docs/automation-pilot/automation-pilot/initial-setup). +* **SAP Cloud Connector**: Connected to the same SAP BTP account as your Automation Pilot tenant - [help](https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/cloud-connector). [Here](https://help.sap.com/docs/automation-pilot/automation-pilot/what-is-sap-automation-pilot) you can find in which regions SAP Automation Pilot is available. +* **Configured Cloud Connector Mapping**: The internal HTTP endpoint for SAP Host Agent must be exposed via the Cloud Connector and accessible using a virtual hostname and port. + +### Cloud Connector Setup Steps + +1. **Expose access to the SAP Host Agent through the Cloud Connector** + Assign a virtual host and port to SAP Host Agent in the Cloud Connector admin console. This virtual host will be used to send requests from BTP (e.g., Automation Pilot) to the agent. + Standard **Internal HTTPS port** - *1129* and **URL Path** - */saphostagent/services/SAPHostControl* + +2. **Verify Cloud Connector connection in BTP** + Once the Cloud Connector is successfully connected to your BTP subaccount and the system is exposed, you will see the Cloud Connector listed in your BTP subaccount cockpit. + +## How to use + +1. **Import the Example**: + * Copy the content of the provided file. + * Go to your SAP Automation Pilot tenant and navigate to `My Catalogs`. + * Click on `Import` in the upper right corner. + * Paste the catalog's content and import it. + +2. **Trigger the Command**: + * Use the `RunOperationViaScc` command. + * Provide the neccessary values for the input keys: + * server - the virtual hostname as configured in the Cloud Connector + * arguments - the arguments that will be passed to the SAP Host Agent operation, in the format *{"argumentName": "argumentValue"}* + * sensitiveArguments – sensitive arguments that will be passed to the SAP Host Agent operation, in the same format as arguments + * name - the name of the SAP Host Agent operation + * user - the user used for authenticating to the system. Most commonly *sapadm* + * password - the user's password + * locationId - the Location ID of the Cloud Connector (or leave empty if not specified) + * Start the automation. + +## Expected result + +After execution, the command will trigger the specified SAP Host Agent operation via the Cloud Connector and wait for it to finish. The result from the operation will be returned as output. diff --git a/sap-host-agent-via-cloud-connector/catalog.json b/sap-host-agent-via-cloud-connector/catalog.json new file mode 100644 index 0000000..a6d3c92 --- /dev/null +++ b/sap-host-agent-via-cloud-connector/catalog.json @@ -0,0 +1,643 @@ +{ + "id": "examples-<<>>", + "technicalName": "examples", + "name": "Automation Pilot Examples", + "description": "Source: https://github.com/SAP-samples/automation-pilot-examples", + "owner": "<<>>", + "inputs": [], + "commands": [ + { + "configuration": { + "values": [], + "output": { + "result": "$(.GetResult.output.body | fromXml)", + "isOperationSuccessful": "$(.GetResult.output.body | fromXml | .Envelope.Body.Fault.faultstring | length == 0)", + "exitCode": "$(.GetResult.output.body | fromXml | .Envelope.Body.Fault.detail.OperationException.mResponseMessages.item | filter(.mMessageKey == \"exitcode\") | .[-1].mMessageValue)", + "isOperationFinished": "$(.Poll.output.body)" + }, + "executors": [ + { + "execute": "http-sapcp:HttpRequest:1", + "input": { + "headers": "{\"Content-Type\":\"text/xml; charset=utf-8\"}", + "responseBodyTransformer": ". | fromXml | .Envelope.Body.IsOperationFinishedResponse.IsFinished", + "password": "$(.execution.input.password)", + "method": "POST", + "sccLocationId": "$(.execution.input.locationId)", + "body": "\n \n \n \n \n $(.execution.input.operationId)\n \n \n", + "user": "$(.execution.input.user)", + "url": "https://$(.execution.input.server):1129/saphostagent/services/SAPHostControl", + "timeout": "10", + "sccEnabled": "true" + }, + "alias": "Poll", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "http-sapcp:HttpRequest:1", + "input": { + "headers": "{\"Content-Type\":\"text/xml; charset=utf-8\"}", + "password": "$(.execution.input.password)", + "method": "POST", + "sccLocationId": "$(.execution.input.locationId)", + "body": "\n \n \n \n $(.execution.input.operationId)\n \n 0\n \n \n \n", + "successResponseCodes": "[\"2xx\",\"500\"]", + "user": "$(.execution.input.user)", + "url": "https://$(.execution.input.server):1129/saphostagent/services/SAPHostControl", + "timeout": "10", + "sccEnabled": "true" + }, + "alias": "GetResult", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.Poll.output.body | toBoolean)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "true" + ] + } + ] + } + ] + }, + "validate": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(if .GetResult.output.status == 500 then (.GetResult.output.body | fromXml | .Envelope.Body.Fault.faultstring == \"Command execution failed.\") else true end)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "true" + ] + } + ] + } + ] + }, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:PollOperationViaScc:1", + "name": "PollOperationViaScc", + "description": "Poll the execution of a custom SAP Host Agent operation", + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "server": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "password": { + "type": "string", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "locationId": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "operationId": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "user": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "result": { + "type": "object", + "sensitive": false, + "description": null + }, + "isOperationSuccessful": { + "type": "boolean", + "sensitive": false, + "description": null + }, + "exitCode": { + "type": "number", + "sensitive": false, + "description": "The exit code of a non-successful operation" + }, + "isOperationFinished": { + "type": "boolean", + "sensitive": false, + "description": null + } + }, + "tags": {}, + "issues": [] + }, + { + "configuration": { + "values": [], + "output": { + "result": "$(.PollOperation.output.result)" + }, + "executors": [ + { + "execute": "examples-<<>>:TriggerOperationViaScc:1", + "input": { + "server": "$(.execution.input.server)", + "clientCert": "$(.execution.input.clientCert)", + "sensitiveArguments": "$(.execution.input.sensitiveArguments)", + "password": "$(.execution.input.password)", + "locationId": "$(.execution.input.locationId)", + "name": "$(.execution.input.name)", + "arguments": "$(.execution.input.arguments)", + "user": "$(.execution.input.user)" + }, + "alias": "TriggerOperation", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "examples-<<>>:PollOperationViaScc:1", + "input": { + "server": "$(.execution.input.server)", + "clientCert": "$(.execution.input.clientCert)", + "password": "$(.execution.input.password)", + "locationId": "$(.execution.input.locationId)", + "operationId": "$(.TriggerOperation.output.operationId)", + "user": "$(.execution.input.user)" + }, + "alias": "PollOperation", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.PollOperation.output.isOperationSuccessful)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "true" + ] + } + ] + } + ] + }, + "autoRetry": null, + "repeat": { + "maxCount": 600, + "until": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.PollOperation.output.isOperationFinished)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "true" + ] + } + ] + } + ] + }, + "delay": "10s", + "failOnMaxCount": true + }, + "errorMessages": [ + { + "message": "SAP Host Agent Operation execution not successful - exitCode: $(.PollOperation.output.exitCode)$(\"\\n\")$(.PollOperation.output.result)", + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.PollOperation.output.isOperationSuccessful)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "false" + ] + } + ] + } + ] + } + } + ], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:RunOperationViaScc:1", + "name": "RunOperationViaScc", + "description": "Trigger an execution of a SAP Host Agent custom operation and wait for it to finish", + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "server": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "sensitiveArguments": { + "type": "object", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "password": { + "type": "string", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "locationId": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "name": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "arguments": { + "type": "object", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "user": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "result": { + "type": "string", + "sensitive": false, + "description": null + } + }, + "tags": {}, + "issues": [] + }, + { + "configuration": { + "values": [], + "output": { + "test": "$(.void.output.message)", + "rawResult": "$(.ExecuteRequest.output.body)", + "operationId": "$(.ExecuteRequest.output.body | fromXml | .Envelope.Body.ExecuteOperationResponse.result.mOperationID)" + }, + "executors": [ + { + "execute": "http-sapcp:HttpRequest:1", + "input": { + "headers": "{\"Content-Type\":\"text/xml; charset=utf-8\"}", + "password": "$(.execution.input.password)", + "method": "POST", + "sccLocationId": "$(.execution.input.locationId)", + "body": "\n \n \n \n \n $(.execution.input.name)\n \n \n $(.execution.input.arguments + .execution.input.sensitiveArguments | to_entries | map(\" \\(.key)\") | join(\"\\n\"))\n \n \n \n\n", + "user": "$(.execution.input.user)", + "url": "https://$(.execution.input.server):1129/saphostagent/services/SAPHostControl", + "timeout": "10", + "sccEnabled": "true" + }, + "alias": "ExecuteRequest", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:TriggerOperationViaScc:1", + "name": "TriggerOperationViaScc", + "description": "Trigger the execution of a custom SAP Host Agent operation", + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "server": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "sensitiveArguments": { + "type": "object", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "password": { + "type": "string", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "locationId": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "name": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "arguments": { + "type": "object", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": "Keys and values that will be used as arguments for the operation for the SHA request" + }, + "user": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "test": { + "type": "string", + "sensitive": false, + "description": null + }, + "rawResult": { + "type": "string", + "sensitive": false, + "description": null + }, + "operationId": { + "type": "string", + "sensitive": false, + "description": null + } + }, + "tags": {}, + "issues": [] + } + ] +}