Service Accounts Management
Last updated
Last updated
Moving forward, we are natively rebuilding BastionZero’s technology as Cloudflare’s service.
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.
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:
Add new service accounts
Enable or disable a service account
Configure targets to recognize themselves or other service accounts
Rotate a service account’s multi-factor authentication (MFA) credentials, including its own
Change the role (user/admin) of other service accounts or users
Enable or disable MFA for users
Remove users from a BastionZero organization
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.
IMPORTANT: You must be a BastionZero administrator to set up a service account
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
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
.
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/alice@bastionzero.com
, the pattern would be https://bastionzero-service-accounts/*bastionzero.com
, where https://bastionzero-service-accounts/
is your prefix and bastionzero.com
is your suffix.
Once you have finished the above steps, your provider file should look something like this:
Log in to the ZLI: zli login
.
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.
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.
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.
When adding a service account, you may need to take two actions on behalf of existing targets:
Upgrade your bzero
agent to a version (7.3.0+
) that supports BastionZero service accounts.
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 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.
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.
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.
Azure provides a way to create and host the JWKS URL needed to use BastionZero service accounts.
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
does not need to be a functioning email address.
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
).
BastionZero service accounts are primarily managed from the Zero-Trust Command Line Interface (ZLI). Full details on new and expanded ZLI commands are below.
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]
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.
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.
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).
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.
Convert the public key to .
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.
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.
Click on your newly created service account and select “Keys” in the top menu.
Follow the remaining instructions in the , starting at step 5.
Use this 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 step 3 for full details).
Generate your JWKS using the 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
).
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 starting at step 4. A few things to note: