Usage

API Key

The API key is a cryptographically strong random sequence of numbers hashed into a 128-character string. It is encrypted and stored internally using AES 256 encryption. Any language with a Representational State Transfer (REST) compliant interface can access the API with the API key and RunAs in the authorization header.

Some environments may still use an old-style API key, which is a formatted Globally Unique Identifier (GUID). Rotating the API Key produces the new-style API key described above.

Session State

Session state is maintained between API calls. The method is dependent on the scripting language. Initiate a session using API POST Auth/SignAppIn and always call POST Auth/Signout when you are done.

Base Endpoint

The following base endpoint is used throughout this document. For on-premises instances, the-server is a placeholder and should be replaced with the server name in your environment.

<base> = https://the-server/BeyondTrust/api/public/v3

For cloud instances, the-cloud-instance-url is a placeholder and should be replaced with the cloud instance URL in your environment.

<base> = https://the-cloud-instance-url/BeyondTrust/api/public/v3

SSL is required to use the Password Safe Public API.

Authorization Header

Use the web request authorization header to communicate the API application key, the RunAs username, and the user password:

  • key: The API key configured in BeyondInsight for your application.
  • runas: The username of a BeyondInsight user that has been granted permission to use the API key.
  • pwd: The RunAs user password surrounded by square brackets (optional; required only if the User Password is required on the application API registration).
Authorization=PS-Auth key=c479a66f…c9484d; runas=doe-main\johndoe; pwd=[un1qu3];

The API keys in the examples have been shortened for brevity. A domain user is being used. When using a domain user, depending on the programming or scripting tool used, you may need to escape the backslash (\) character between the domain name and username.

Two-Factor Authentication

Depending on how the two-factor server is configured, a programmatic two-factor challenge is sometimes required.

No Challenge

If the two-factor server is configured to authenticate through a push or mobile two-factor challenge, a challenge response is often not required. The first call to POST Auth/SignAppIn logs the user in, as long as the authentication request to the two-factor server does not time out.

Challenge

When a two-factor challenge is configured, two calls to POST Auth/SignAppIn are required and session state must be maintained between these two calls to validate the two-factor challenge.

The initial call to POST Auth/SignAppIn results in a 401 Unauthorized response which contains a header WWW-Authenticate-2FA containing the prompt from the authentication service. The prompt can be used to prompt the user for the challenge answer.

If the WWW-Authenticate-2FA header is not present, a two-factor authentication challenge has not been configured for the user.

When the challenge answer has been received from the user, POST Auth/SignAppIn is called again with the challenge answer in the authorization header, similar to the other authorization parameters:

  • challenge: The answer to the two-factor challenge.
Authorization=PS-Auth key=c479a66f…c9484d; runas=doe-main\johndoe; pwd=[un1qu3]; challenge=543687;

The challenge answer is only required on the second call to POST Auth/SignAppIn and not on subsequent requests.

OAuth Public API Authentication

The OAuth sign-in method uses the OAuth client credential flow. The client credentials grant type is used by clients to obtain an access token outside of the context of a user.

Only users with user type Application, who are associated to an API Access Policy API registration in BeyondInsight, can use this authentication method.

Impersonation for the OAuth client credential flow is different than API key. Instead of providing the RunAs user as part of the Authorization header you provide the RunAs user using a new RunAs header. You can only impersonate users who are in the same group as the application user.

Setting up an OAuth authentication method requires the following steps:
  • Create an API Registration using the API Access Policy type
  • Create an application user
  • Assign your access policy to the user
  • Record their client ID and secret for later use
  • Assign user to a group with necessary permissions

For more information, please see OAuth 2.0 Client Credentials Grant.

Use Certificates with APIs

When Client certificate required is enabled on API authentication, the following items are required to authenticate via API:

  • Client certificate must be present on the calling machine/instance.
  • Client certificate must be trusted by the appliance/Instance.
  • Client certificate must be included in script when calling Password Safe API.

For cloud certificate authentication, the client certificate must be signed by a well-known CA for cloud instance to trust it and allow authentication.

The client cert can be downloaded from the Password Safe appliance/Instance in the Configuration > System > Downloads menu.

For examples of utilizing a client cert in your API script, refer to the default scripts in the resource kit for your relevant version.

Request Body

For Password Safe API Endpoints, some request bodies have multiple versions available. The request body versions allow for different sets of data to be sent to a API endpoint dependent on what needs to be accomplished by the request. Each request body version is outlined on its relevant endpoint and these body versions are only relevant to their listed URI.

When using a request body, if no version is specified in the URI, the default listed version is used (typically v3.0). To use a specific version, the version must be included in the URI.

https://server/BeyondTrust/api/public/v3.1/endpoint

Common Response Codes

Below are response codes common to all APIs. Custom responses are detailed in the individual endpoints.

  • 200 – Request successful.
  • 204 – Request successful. No content in body.
  • 400 – Bad Request – Validation failure, missing request body, or string values exceed the maximum length. Reason in response body.
  • 401 – Unauthorized – User is not authenticated. Typical reasons include:
    • An invalid product license was detected.
    • The request headers were not set properly.
    • The server could not verify the validity of the request (due to one or more API factors).
    • The user session has expired.
    • The API key has been rotated but has not been updated in the calling script or application.

When you encounter a 401 error due to factor validation failure, a User Audit entry is created in BeyondInsight and an email is sent to the administrator detailing the reason. Look here first for the reason why authorization failed.

  • 403: – Access forbidden. User does not have the appropriate role or permission.

A 403 can also occur when SSL trust cannot be established.

  • 404 – Object not found where expected. Reason in response body.
  • 500 – Unexpected server error occurred. Please contact the developers.

Examples

C#

Create and reuse a persistent connection using the System.Net.Http.HttpClient class.

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization",
"PS-Auth key= c479a66f…c9484d; runas=doe-main\\johndoe;");

string json = Newtonsoft.Json.JsonConvert.SerializeObject(null);
System.Net.Http.StringContent content = new StringContent(json);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

HttpResponseMessage signInResponse = client.PostAsync("<base>/Auth/SignAppin", content).Result;

Subsequent calls:

HttpResponseMessage getResponse = client.GetAsync("<base>/ManagedAccounts").Result;

User Password Factor Enabled (header example only)

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization",
"PS-Auth key= c479a66f…c9484d; runas=doe-main\\johndoe; pwd=[un1qu3];");
Powershell

Powershell internally creates a session variable to use for each subsequent call; Invoke-RestMethod CmdLet options -SessionVariable and -WebSession respectively. In the below example, the variable is named "session" and has script-level scope.

$headers = @{ Authorization="PS-Auth key=c479a66f…c9484d; runas=doe-main\\johndoe;"; };
$uri = "<base>/Auth/SignAppin";
$signinResult = Invoke-RestMethod -Uri $uri -Method POST -Headers $headers -SessionVariable script:session;

Subsequent calls:

$uri = "<base>/ManagedAccounts";
$accounts = Invoke-RestMethod -Uri $uri -Method GET -WebSession $script:session -Headers $headers;
Java

Create and reuse a persistent connection using the java.net.HttpURLConnection class.

URL baseURL = new URL("HTTPS", "the-server", 443, "/BeyondTrust/api/public/v3/");
URL url = new URL(baseURL, "Auth/SignAppIn");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestProperty("Authorization","PS-Auth key=c479a66f…c9484d; runas=doe-main\\johndoe;");
Ruby

Using the rest-client gem, carry over the ASP.NET_SessionId header.

samp_key = 'PS-Auth key= c479a66f…c9484d; runas=doe-main\\johndoe;'
result = RestClient::Request.execute(method: :post, url: '<base>/Auth/SignAppin', :headers => {‘Authorization’ => samp_key} )
session_id = result.cookies["ASP.NET_SessionId"]

Subsequent calls:

result = RestClient::Request.execute(method: :get, url: '<base>/ManagedAccounts', :headers=>{‘Authorization’ => samp_key, :cookies => {'ASP.NET_SessionId' => session_id}} )
Python

Create and reuse a persistent connection using the requests module.

header = {'Authorization': 'PS-Auth key=c479a66f…c9484d; runas=doe-main\\johndoe;'}
session = requests.Session()
session.headers.update(header)
response = session.post('<base>/Auth/SignAppin')

Subsequent calls:

accounts = session.get('<base>/ManagedAccounts')
Bash

Using curl, option –c stores authentication information for subsequent requests and –b uses it in subsequent API calls.

curl -i -c apiToken -X POST https:<base>/Auth/SignAppin -H "Content-Type: application/json" -H "Authorization: PS-Auth key=c479a66f…c9484d; runas=doe-main\\johndoe;" -d ""

Subsequent calls:

curl -i -b apiToken -X GET https:<base>/ManagedAccounts

Workflow

There are some loose dependencies between the APIs. A typical sequence is to list accounts or find an account, request a password, retrieve that password (once approved), and then release the password.

Create and Manage an Asset, Create User Group, Assign Roles

Case: Create and manage an asset, create a managed account, create a managed account quick rule, create/provision an LDAP/AD/BeyondInsight user group, grant Read access to new Smart Rule with requester role and access policy.

  • POST <base>/Auth/SignAppin
  • POST <base>/Workgroups/{ID}/Assets
  • POST <base>/Assets/{assetId}/ManagedSystems
  • POST <base>/ManagedSystems/{managedSystemId}/ManagedAccounts
  • POST <base>/QuickRules
  • POST <base>/UserGroups
  • POST <base>/UserGroups/{userGroupId}/SmartRules/{smartRuleId}/Roles
  • POST <base>/Auth/Signout

Retrieve a Password

Case: request, retrieve, and check in a password for a managed account:

  • POST <base>/Auth/SignAppin
  • GET <base>/ManagedAccounts OR GET <base>/ManagedAccounts?systemName={systemName}&accountName={accountName}
  • POST <base>/Requests
  • GET <base>/Credentials/{requestId}
  • PUT <base>/Requests/{requestId}/Checkin
  • POST <base>/Auth/Signout

Create a Session

Case: request a session, create a session, and check in the request for a managed account:

  • POST <base>/Auth/SignAppin
  • GET <base>/ManagedAccounts OR GET <base>/ManagedAccounts?systemName={systemName}&accountName={accountName}
  • POST <base>/Requests (AccessType="RDP" or AccessType="SSH" or AccessType="App")
  • POST <base>/Requests/{requestId}/Sessions (SessionType == Request.AccessType above)
  • PUT <base>/Requests/{requestId}/Checkin
  • POST <base>/Auth/Signout

Retrieve a Password as an ISA

Case: create an ISA password request:

  • POST <base>/Auth/SignAppin
  • GET <base>/ManagedAccounts OR GET <base>/ManagedAccounts?systemName={systemName}&accountName={accountName}
  • POST <base>/ISARequests
  • POST <base>/Auth/Signout

Create a Session as an ISA

Case: create an ISA session:

  • POST <base>/Auth/SignAppin
  • GET <base>/ManagedAccounts OR GET <base>/ManagedAccounts?systemName={systemName}&accountName={accountName}
  • POST <base>/ISASessions
  • POST <base>/Auth/Signout