Service Accounts Management

Traditional service accounts enable organizations to take advantage of automation, but they come with a host of security concerns: lack of visibility, long-standing credentials, usability, and the threat of compromise.

BastionZero offers a solution to these drawbacks when using service accounts by providing command logs; session recordings; credential rotation; robust policy enforcement, including instant revocation; and a trustless architecture that utilizes two roots-of-trust.

What are BastionZero service accounts and what can they do?

A BastionZero service account is a Google, Azure, or generic service account that integrates with BastionZero by sharing its JSON Web Key Set (JWKS) URL. The headless authentication closely follows the OpenID Connect (OIDC) protocol. The JWKS contains the public key from a public/private key pair that you must generate. You use the private key to sign the service account’s identity and access tokens, and then BastionZero uses the public key within the JWKS URL to validate the service account.

BastionZero service accounts can perform many of the actions a named identity provider (IdP) user or administrator can perform (e.g., shelling into a target, uploading/downloading files from a Linux box, creating policy, and connecting to a Kubernetes cluster).

There are a few exceptions. Service accounts cannot:

  1. Add new service accounts

  2. Enable or disable a service account

  3. Configure targets to recognize themselves or other service accounts

  4. Rotate a service account’s multi-factor authentication (MFA) credentials, including its own

  5. Change the role (user/admin) of other service accounts or users

  6. Enable or disable MFA for users

  7. Remove users from a BastionZero organization

  8. Delete an IdP groups integration from a BastionZero organization

All the above actions must be done from an administrator account tied to a named IdP user.

All service accounts are added as users by default. If you would like a service account to be able to perform actions beyond a “user” role, you must modify its role after creation to be an administrator.

How to set up your BastionZero service account

IMPORTANT: You must be a BastionZero administrator to set up a service account

Requirements: Service accounts require a minimum of zli v. 6.14.0 and bzero v. 7.3.0

Generic Service Account

  1. Create a private/public key pair by using, for example, openSSL: openssl genrsa -out private.key 2048; openssl pkey -pubout -in private.key > public.pem

  2. Convert the public key to JSON Web Key (JWK) format.

  3. Create a new URL that serves your JWK. This URL must adhere to the following format: https://<url>/<service-account-username>@<service-account-domain>, and it MUST be accessible from the public Internet.

    • For example, a Google service account’s URL would look like:

  4. Create and securely store a JSON file that will serve as your provider file. This must contain the following information:

    • client_id: a unique identifier chosen by you that BastionZero will use to identify your service account

    • private_key_id: key id (kid) used when you converted your public key to JWK format

    • private_key: private key created in step 1. Note that because the output from openSSL includes intentional newlines, you will need to convert those to \n in your JSON provider file

    • client_email: service account email address (although this does not need to be a functioning email address, it must still validate against the following regex: ^[a-zA-Z0-9_-]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]+$)

    • jwksURL: URL created in step 3

    • jwksURLPattern: structure of your JWKS URL (prefix and suffix). For example, if your JWKS URL were https://bastionzero-service-accounts/, the pattern would be https://bastionzero-service-accounts/*, where https://bastionzero-service-accounts/ is your prefix and is your suffix.

    • Once you have finished the above steps, your provider file should look something like this:

      "private_key_id": "example-private-key-id", 
      "private_key": "-----BEGIN PRIVATE KEY-----\neach\nkey\nline\n-----END PRIVATE KEY-----\n", 
      "client_email": "", 
      "client_id": "alice-client-id", 
      "jwksUrl": "https://bastionzero-service-accounts/", 
      "jwksURLPattern": "https://bastionzero-service-accounts/*" 

  5. Log in to the ZLI: zli login.

  6. Create your BastionZero service account: zli service-account create <provider-file.json>. The result of this command will be a bzeroCreds.json file that you must securely store because it will be required to access your BastionZero service account.

  7. Your BastionZero service account is now added to your BastionZero organization! Next steps may include adding the service account to new or existing policies, modifying the service account’s role to be an administrator, and configuring your existing targets to recognize your service account.

  8. Finally, once you’ve set up policy and configured any existing targets to recognize your service account (or registered a new target), log in and try connecting to a target as your service account: zli service-account login --providerCreds /path/to/provider-file.json --bzeroCreds /path/to/bzeroCreds.json, followed by a zli connect command.

Configure your service account on existing targets

When adding a service account, you may need to take two actions on behalf of existing targets:

  1. Upgrade your bzero agent to a version (7.3.0+) that supports BastionZero service accounts.

  2. Once the agent is at the minimum supported feature version, configure existing target(s) to recognize the service account as a valid user using:

    • zli service-account configure -a <service-account-username>@<service-account-domain> -t <target-name(s), delimited with spaces> to enable the service account on a subset of existing targets, or

    • zli service-account configure -a <service-account-username>@<service-account-domain> --all to enable the service account on all existing targets This command will add the JWKS URL format to the targets so any future service accounts that use the same JWKS pattern (prefix and suffix) will already be configured and will require no additional action on your end. For example, if your service account email,, has a JWKS URL that looks like https://bastionzero-service-accounts/, future accounts that also use https://bastionzero-service-accounts/* will not require further configuration.

This configuration step is not required for any targets registered after your service accounts are created. All new targets will be provided the existing service accounts' jwksUrlPatterns during registration. Note that if you add another service account using a new jwksUrlPattern after target registration, you will have to configure the service account using the zli service-account configure command, as shown above.

Google Cloud Service Account

The Google Cloud Platform (GCP) provides a convenient way of creating the public/private key pair and the JWKS URL, both of which are needed for setting up your BastionZero service account.

  1. Add a new JSON key. GCP will prompt you to save the private key locally to your machine. This will be your provider file, and we strongly suggest saving it in a vault or other secure location.

  2. Follow the remaining instructions in the generic service account setup, starting at step 5.

Azure Service Account

Azure provides a way to create and host the JWKS URL needed to use BastionZero service accounts.

  1. Use this guide provided by Azure to create the .well-known OIDC configuration document. When generating the discovery document in step 2, ensure the jwks_uri satisfies the required pattern for BastionZero service accounts (see generic service account step 3 for full details).

    • For example, your jwks_uri may be: https://${AZURE_STORAGE_ACCOUNT}${AZURE_STORAGE_CONTAINER}/openid/v1/jwks/ Note that does not need to be a functioning email address.

  2. Generate your JWKS using the next section in the Azure guide. Verify that you replace the --name value in step 3 with the suffix created in step 1 above (i.e., --name openid/v1/jwks/

  3. You’ve now created both the private/public key pair and the JWKS URL that serves the public key. Follow the remaining instructions in the generic service account setup starting at step 4. A few things to note:

    • Your client_email will be the address you used above in step 1 (i.e.,

    • You will find your key ID in the jwks.json file you created in step 2

    • When adding your private key to your BastionZero provider file, make sure that new lines in your key are represented with a valid JSON format (\n).

Working with service accounts

BastionZero service accounts are primarily managed from the Zero-Trust Command Line Interface (ZLI). Full details on new and expanded ZLI commands are below.

From the ZLI

ActionZLI commandRole requiredNotes

Add a new service account

zli service-account create </path/to/provider_creds.json> [--bz-creds=/path/to/write/bzcreds.json]

Non-service-account admin

  • IdP user emails and service account emails must always be unique and cannot overlap.

  • You can specify where to save the bzcreds.json file if desired using --bz-creds.

  • Save the bzcreds.json file in a secure location. It is required for your service account to log in.

Configure the service account on existing target(s)

zli service-account configure --target <target-names, delimited with spaces> --service-account <service-account-email>

Non-service-account admin

If you would like to enable the service account on all existing targets, use the --all flag instead of specifying --target.

List all service accounts

zli service-account list [-d]


Use the -d flag to receive additional details about your service account(s).

Modify a service account's role (user/admin)

zli service-account set-role <admin/user> <service-account-email>

Non-service-account admin

By default, all service accounts are added as users.

Add a service account to an existing policy

zli policy add-subject <policyName> <service-account-email>


This command can be used to add both service accounts and IdP users to an existing policy.

Create a new policy with a service account as a subject

zli policy create-{cluster |tconnect|recording|proxy} --serviceAccounts <service account>


For all 4 policy create commands, there is a new flag --serviceAccounts, which allows you to add a service account as a subject for the new policy.

Remove a service account from an existing policy

zli policy delete-subject <policyName> <service-account-email>


This command can be used to remove both service accounts and IdP users from an existing policy.

Rotate a service account's TOTP MFA credential

zli service-account rotate-mfa <service-account-email>

Non-service-account admin

This command will create a new bzcreds.json file. Store this in a vault or other secure place.

Enable/disable a service account

zli service-account <enable|disable> <service-account-email>

Non-service-account admin

Once you disable a service account, it will be deleted from all relevant policies. If you re-enable it at a later date, you must re-add the service account to all necessary policies.

Log in with a service account

zli service-account login --creds=/path/to/providercreds.json --bz-creds=/path/to/write/bzcreds.json


We strongly recommend that the provider_creds.json file and the bzcreds.json file are stored in a vault or other secured place.

From the web app

Although managing your service accounts is done from the ZLI, several changes are present in the web app, as illustrated below.


You will notice a new field called “Service Accounts” in the Kubernetes, proxy, session recording, and target connect policies. This field allows you to add a service account as a policy subject and grants it access to specific targets and actions.

Audit logs

Service accounts generate audit logs in the same way as BastionZero users tied to an IdP account. Below is an example of the thanos-sa-test@thanos-sa-test service account performing the "exit" command “ as the ssm-user on the than-bzero-agent. Service account activity is captured in command logs, Kubernetes command logs, connections, connections events, and subject events (renamed from user events).

Users & service accounts menu

What used to be called “User Management” underneath the “Administration” section has been renamed to “Users & Service Accounts.” You can both disable/enable a service account from this menu and close all its active connections.

Last updated

Copyright © 2024