Configuration Automation - Ping CLI

Making API Requests

Ping CLI can make API requests to supported products, similar to using curl, using the pingcli request command.

Benefits of using Ping CLI

Using Ping CLI to make direct API requests against a Ping Identity deployment offers a number of benefits.

Ping CLI manages the API authentication

With commands similar to curl, it is typically up to the developer to provide credentials in the required format or a valid OAuth bearer token with the request. With Ping CLI, the API authentication is managed by the CLI tool and injected to the API request without the developer needing to add it manually. This capability allows the developer to focus on the structure and content of the request and ultimately focus on managing the Ping Identity deployment.

For example, the PingOne API requires a valid OAuth 2.0 bearer token that is typically short lived and can expire. When using Ping CLI, the developer needs to configure the PingOne worker application details in the Ping CLI configuration and issue the API request without needing to add any authentication to the request syntax. The Ping CLI tool manages getting a valid access token and (if necessary) the refresh of an existing access token and adds the token to the request on behalf of the developer.

Ping CLI manages the base URL

With commands similar to curl, it’s typically up to the developer to provide the full URL in the request. This requirement typically means the developer has to create variables for the hostname/port to be able to use the same script for development, test or production. Ping CLI injects the base URL value according to the developer’s CLI configuration, meaning the same requests can be used between multiple environments without the need for custom variables.

Ping CLI performs automatic retries of transient errors

APIs of any hosted or deployed service may respond with transient errors, for example rate limiting, server congestion or network issues. There are cases when the developer needs to handle these errors and invoke custom logic. However errors that are considered transient should be retried automatically.

Ping CLI automatically retries transient errors silently to the developer, so if they are encountered on the rare occasion, the developer doesn’t need to retry an API request manually or (if embedded in a script) need to code specific retry logic.

For example, if PingOne returned back a 429 HTTP response code (as a result of rate limiting), Ping CLI handles the Retry-After header and (if needed) invokes an exponential backoff retry method according to documented best practice on the PingOne API documentation. This repeated request process happens silently to the developer and allows for resilency in scripting environment management.

Making a request

When making a request to the API, the format is pingcli request [flags] API_URI.

The API_URI is required and must be the API URI path omitting the base API path of the service. For example, with PingOne a full URL might be documented in the API documentation as:

{{apiPath}}/environments/{{envID}}/applications

Since Ping CLI injects the apiPath value, the API_URI value to provide to the Ping CLI is environments/{{envID}}/applications. For example:

pingcli request [flags] environments/$ENVIRONMENT_ID/applications

The --service (or -s for short) parameter is required to instruct the Ping CLI tool as to which service API style to invoke.

When invoking a service through the --service parameter, the service must be configured in the specified configuration profile. For example, the pingone service must have a valid PingOne worker application configured. See Connecting Ping Identity Services for more information.

The --http-method (or -m short code) is optional and defaults to GET. If issuing a POST, PUT, PATCH or DELETE API request, the --http-method parameter must be specified.

Example GET request

The following example command will read all applications for the PingOne environment ID, PINGONE_ENVIRONMENT_ID.

As a prerequisite, the Ping CLI tool should be configured to connect to the PingOne tenant using a worker application. Learn more in Connecting Ping Identity Services.

As the request is a GET request, there is no request payload.

The API example aligns with the request documented on the PingOne API Documentation:

Request command:

pingcli request \
  -s pingone \
  environments/$PINGONE_ENVIRONMENT_ID/applications
Expand example response
response: {
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications"
        }
    },
    "_embedded": {
        "applications": [
            {
                "_links": {
                    "environment": {
                        "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
                    },
                    "self": {
                        "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/fb955fe0-9b00-4bd3-a64e-6054dc95eae3"
                    }
                },
                "environment": {
                    "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
                },
                "id": "fb955fe0-9b00-4bd3-a64e-6054dc95eae3",
                "name": "PingOne Admin Console",
                "description": "The admin console application which is used to manage this environment's configuration and identity data.",
                "enabled": true,
                "type": "PING_ONE_ADMIN_CONSOLE",
                "accessControl": {
                    "role": {
                        "type": "ADMIN_USERS_ONLY"
                    }
                },
                "icon": {
                    "id": "a3d073bc-3108-49ad-b96c-404bea59a1d0",
                    "href": "https://assets.pingone.com/ux/ui-library/4.18.0/images/logo-pingidentity.png"
                },
                "protocol": "OPENID_CONNECT",
                "createdAt": "2021-02-25T23:51:49.790Z",
                "updatedAt": "2021-02-25T23:51:49.790Z",
                "pkceEnforcement": "OPTIONAL",
                "tokenEndpointAuthMethod": "NONE"
            },
            {
                "_links": {
                    "grants": {
                        "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/b158e2b1-a936-4022-ad46-9c1dc61446cd/grants"
                    },
                    "environment": {
                        "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
                    },
                    "self": {
                        "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/b158e2b1-a936-4022-ad46-9c1dc61446cd"
                    }
                },
                "environment": {
                    "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
                },
                "id": "b158e2b1-a936-4022-ad46-9c1dc61446cd",
                "name": "PingOne Self-Service - MyAccount",
                "description": "The self-service application where users can manage profile details, passwords, MFA devices, etc.",
                "enabled": true,
                "type": "PING_ONE_SELF_SERVICE",
                "icon": {
                    "id": "a3d073bc-3108-49ad-b96c-404bea59a1d0",
                    "href": "https://assets.pingone.com/ux/ui-library/4.18.0/images/logo-pingidentity.png"
                },
                "protocol": "OPENID_CONNECT",
                "createdAt": "2021-02-25T23:51:49.777Z",
                "updatedAt": "2021-02-25T23:51:49.777Z",
                "pkceEnforcement": "OPTIONAL",
                "tokenEndpointAuthMethod": "NONE"
            }
        ]
    },
    "size": 2
}
status: 200
SUCCESS: Custom request successful

Example POST request (using data from a file)

The following example command creates an application for the PingOne environment ID, PINGONE_ENVIRONMENT_ID.

As a prerequisite, the Ping CLI tool should be configured to connect to the PingOne tenant using a worker application. Learn more in Connecting Ping Identity Services.

As the request is a POST request, an API request payload is required. The API request data comes from a JSON file at ./my-application.json on the filesystem that the request is being run.

The API example aligns with the request documented on the PingOne API Documentation:

Request command:

pingcli request \
  -m POST \
  -s pingone \
  --data ./my-application.json \
  environments/$PINGONE_ENVIRONMENT_ID/applications
Expand my-application.json contents
{
    "enabled": true,
    "name": "OIDC-Web-App",
    "description": "Test Description - OIDC App (Web)",
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "homePageUrl": "https://example.com/homePage",
    "loginPageUrl": "https://example.com/loginPage",
    "icon": {
        "id": "{{iconID}}",
        "href": "https://upload.image/image.jpg"
    },
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "postLogoutRedirectUris": [
        "https://example.com/logout"
    ],
    "redirectUris": [
        "https://example.com"
    ],
    "responseTypes": [
        "CODE"
    ],
    "signing": {
        "keyRotationPolicy": {
            "id": "{{krpID}}"
        }
    },
    "tokenEndpointAuthMethod": "CLIENT_SECRET_BASIC",
    "pkceEnforcement": "REQUIRED",
    "refreshTokenDuration": 86400,
    "refreshTokenRollingDuration": 86400
}
Expand example response
response: {
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/403b2bb3-a151-42b2-99d5-5eae2b151215"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
        },
        "attributes": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/403b2bb3-a151-42b2-99d5-5eae2b151215/attributes"
        },
        "secret": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/403b2bb3-a151-42b2-99d5-5eae2b151215/secret"
        },
        "grants": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/403b2bb3-a151-42b2-99d5-5eae2b151215/grants"
        }
    },
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    },
    "id": "403b2bb3-a151-42b2-99d5-5eae2b151215",
    "name": "OIDC-Web-App",
    "enabled": true,
    "type": "WEB_APP",
    "loginPageUrl": "https://example.com/loginPage",
    "homePageUrl": "https://example.com/homePage",
    "icon": {
        "id": "1d39eadb-ee72-41a1-a460-f5a5fd2b0a27",
        "href": "https://upload.image/image.jpg"
    },
    "protocol": "OPENID_CONNECT",
    "createdAt": "2021-09-23T13:54:34.487Z",
    "updatedAt": "2021-09-23T13:54:34.487Z",
    "assignActorRoles": false,
    "responseTypes": [
        "CODE"
    ],
    "grantTypes": [
        "AUTHORIZATION_CODE"
    ],
    "signing": {
        "keyRotationPolicy": {
            "id": "1ea8a9b4-45cf-4f17-8304-ca3agy8d6bed"
        }
    },
    "refreshTokenDuration": 86400,
    "tokenEndpointAuthMethod": "CLIENT_SECRET_BASIC",
    "pkceEnforcement": "REQUIRED",
    "refreshTokenRollingDuration": 86400,
    "redirectUris": [
        "https://example.com"
    ]
}
status: 201
SUCCESS: Custom request successful

Example PUT request (using data from a file)

The following example command updates an application for the PingOne environment ID, PINGONE_ENVIRONMENT_ID, where the application has the ID PINGONE_MY_APPLICATION_ID.

As a prerequisite, the Ping CLI tool should be configured to connect to the PingOne tenant using a worker application. Learn more in Connecting Ping Identity Services.

As the request is a PUT request, an API request payload is required. The API request data comes from a JSON file at ./my-application.json on the filesystem that the request is being run.

The API example aligns with the request documented on the PingOne API Documentation:

Request command:

pingcli request \
  -m PUT \
  -s pingone \
  --data ./my-application.json \
  environments/$PINGONE_ENVIRONMENT_ID/applications/$PINGONE_MY_APPLICATION_ID
Expand my-application.json contents
{
    "name": "AppName",
    "description": "This is my UPDATED app description",
    "protocol": "OPENID_CONNECT",
    "type": "WEB_APP"
}
Expand example response
response: {
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
        },
        "secret": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea/secret"
        },
        "grants": {
            "href": "https://api.pingone.com/v1/environments/abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6/applications/d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea/grants"
        }
    },
    "environment": {
        "id": "abfba8f6-49eb-49f5-a5d9-80ad5c98f9f6"
    },
    "id": "d64c5a69-51ed-4c73-b8bc-8a3fafa6d0ea",
    "name": "AppName",
    "description": "this is my UPDATED app description",
    "enabled": false,
    "type": "WEB_APP",
    "protocol": "OPENID_CONNECT",
    "createdAt": "2019-06-13T19:12:40.321Z",
    "updatedAt": "2019-06-20T18:42:29.265Z"
}
status: 200
SUCCESS: Custom request successful

More information