# Service Accounts Management

{% hint style="danger" %}

### <mark style="color:red;">**The BastionZero product is maintained for existing BastionZero customers only.**</mark>&#x20;

Moving forward, we are natively rebuilding BastionZero’s technology as Cloudflare’s [Access for Infrastructure](https://developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/) service.
{% endhint %}

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 <mark style="color:purple;">cannot</mark>:

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.&#x20;

## How to set up your BastionZero service account

{% hint style="warning" %}
**IMPORTANT**: You **must** be a BastionZero administrator to set up a service account
{% endhint %}

{% hint style="info" %}
**Requirements**: Service accounts require a minimum of `zli v. 6.14.0` and `bzero v. 7.3.0`
{% endhint %}

### 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](https://russelldavies.github.io/jwk-creator/).

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: `https://www.googleapis.com/service_accounts/v1/jwk/example-sa@sa-domain.iam.gserviceaccount.com`.

4. Create and securely store a JSON file that will serve as your *<mark style="color:purple;">**provider file**</mark>*. 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 (<mark style="color:purple;">prefix</mark> and <mark style="color:orange;">suffix</mark>). For example, if your JWKS URL were `https://bastionzero-service-accounts/alice@bastionzero.com`, the pattern would be `https://bastionzero-service-accounts/*bastionzero.com`, where <mark style="color:purple;">`https://bastionzero-service-accounts/`</mark> is your prefix and <mark style="color:orange;">`bastionzero.com`</mark> is your suffix.
   * Once you have finished the above steps, your *<mark style="color:purple;">**provider file**</mark>* should look something like this:&#x20;

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

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 *<mark style="color:purple;">**existing targets**</mark>*:

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, `alice@bastionzero.com`, has a JWKS URL that looks like `https://bastionzero-service-accounts/alice@bastionzero.com`, future accounts that also use `https://bastionzero-service-accounts/*@bastionzero.com` will not require further configuration.

This configuration step is <mark style="color:purple;">**not required**</mark> 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. Using your GCP account and an existing or new project, navigate to the Identity and Access Management (IAM) & Admin menu and select the “Service Accounts” tab.\
   ![](https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2F6dOcMElJvXJjZjbqp0XM%2Fgcp-service%20accounts%20menu.png?alt=media\&token=dec64a85-1b4a-4133-9eeb-6893d8cf3536)
2. Create a new service account. Choose the service account ID carefully because this, combined with the project name, will be the BastionZero service account’s email and unique identifier. Note that the service account ID must be unique within your BastionZero organization and cannot overlap with an existing user.\
   ![](https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2FILUWkT7XYCGYvs3Znpjc%2Fgcp%20create%20service%20account.png?alt=media\&token=f834f719-26e2-45d9-84fc-35cb6d3447c8)
3. Click on your newly created service account and select “Keys” in the top menu.\
   ![](https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2Fea7rBsH03YK1JbYLWHLb%2Fgcp%20key%20in%20sa.png?alt=media\&token=35d0ef18-b164-4169-a5a3-3607752c8fab)
4. Add a new JSON key. GCP will prompt you to save the private key locally to your machine. This will be your *<mark style="color:purple;">provider file</mark>*, and we *<mark style="color:purple;">**strongly**</mark>* suggest saving it in a vault or other secure location.
5. Follow the remaining instructions in the [generic service account setup](#generic-service-account), starting at **step 5**.

### **Azure Service Account**

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

1. Use this [guide](https://azure.github.io/azure-workload-identity/docs/installation/self-managed-clusters/oidc-issuer/discovery-document.html) 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](#generic-service-account) **step 3** for full details).&#x20;
   * For example, your `jwks_uri` may be: `https://${AZURE_STORAGE_ACCOUNT}.blob.core.windows.net/${AZURE_STORAGE_CONTAINER}/openid/v1/jwks/az-example-sa@bastionzero.com`. Note that `az-example-sa@bastionzero.com` <mark style="color:purple;">**does not need**</mark> to be a functioning email address.
2. Generate your JWKS using the [next section](https://azure.github.io/azure-workload-identity/docs/installation/self-managed-clusters/oidc-issuer/jwks.html) 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/azure-example-sa@bastionzero.com`).
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](#generic-service-account) starting at **step 4**. A few things to note:
   * Your `client_email` will be the address you used above in **step 1** (i.e., `az-example-sa@bastionzero.com`)
   * 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**

| Action                                                  | ZLI command                                                                                                              | Role required             | Notes                                                                                                                                                                                                                                                                                                       |
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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 | <ul><li>IdP user emails and service account emails must always be unique and cannot overlap.</li><li>You can specify where to save the bzcreds.json file if desired using --bz-creds.</li><li>Save the bzcreds.json file in a secure location. It is required for your service account to log in.</li></ul> |
| 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]                                                                                           | User                      | 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>                                                            | Admin                     | 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>                            | Admin                     | 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>                                                         | Admin                     | 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                     | User                      | 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.

#### **Policy**

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.

<figure><img src="https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2FkB4l4pU0DVz0w0Wbyvkh%2Fpolicy.png?alt=media&#x26;token=0eed898b-4a60-409b-9ed3-fecb6528fba6" alt=""><figcaption></figcaption></figure>

#### **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).

<figure><img src="https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2FS02ONC1ygMqXKOqRzioK%2Faudit%20log%20sa.png?alt=media&#x26;token=ba43375e-d4ab-4a74-820a-4eb43deddc23" alt=""><figcaption></figcaption></figure>

#### **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.

<figure><img src="https://2296692744-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB1x0ofz14evTHlwIRKaW%2Fuploads%2FJLfkpjGce2jAfFRe0IZ5%2Fmanage%20user%20and%20service%20account.png?alt=media&#x26;token=16c88554-60d3-4548-a539-ecb48811de89" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bastionzero.com/docs/admin-guide/authentication/service-accounts-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
