--- title: "Establish the account foundation" description: "Identify the account and organization and create the setup service identity and credentials." source_url: https://dev.digicert.com/solutions/private-trust-stack/phase-1-account-foundation.html --- # Establish the account foundation Identify the account and organization and create the setup service identity and credentials. ## Phase metadata - Phase: 1 - Workstream: Shared foundation — Step 1 of 2 - Product: Account Manager - Goal: Create a service user with limited roles, capture its API token, and create its client authentication certificate. - Estimated time: 25 minutes - Inputs: bootstrap_api_token, account_name, organization_name, approved_role_names, client_auth_certificate_expiration In this phase, you identify the target account and organization and find the required role names in your tenant. You then create the setup service user and both authentication factors required later by DigiCert® Software Trust Manager. ## Phase prerequisites Make sure you have: - A bootstrap user with an API token for the target tenant, the **Manage users** permission in DigiCert® Account Manager, and access to the target account, organization, and assignable roles. Make the token available as `BOOTSTRAP_API_TOKEN` for cURL or `bootstrap_api_token` for Python. - The exact target account and organization names. - Approved roles for the other products that contain the exact permissions listed in [Before you begin](https://dev.digicert.com/md/solutions/private-trust-stack.md#before-you-begin). - A secure destination for the service-user API token, client certificate, and private key. - An approved UTC expiration timestamp for the client authentication credential. ## Endpoints used | Method | Path | Purpose | |--------|------|---------| | GET | `/account/api/v1/account` | List accessible accounts. | | GET | `/account/api/v1/role` | List assignable roles by product. | | GET | `/account/api/v1/organization` | List organizations in the target account. | | POST | `/account/api/v1/user` | Create the service user and return its API token once. | | POST | `/account/api/v1/client-auth-certificate` | Sign a certificate signing request (CSR) and create a client authentication certificate for the authenticated service user. | | GET | `/account/api/v1/user/me` on the `clientauth.` host | Verify the new certificate authenticates as the service user. | ## Step 1.1: Select the target account `GET /account/api/v1/account` returns an array. Select the intended active account explicitly. Do not assume the response contains only one account. **cURL** ```bash ACCOUNT_NAME="Example account" ACCOUNT_ID="$( curl --fail-with-body --silent --show-error \ "https://demo.one.digicert.com/account/api/v1/account" \ -H "x-api-key: ${BOOTSTRAP_API_TOKEN}" | jq -er --arg name "${ACCOUNT_NAME}" ' [.[] | select(.name == $name and .active == true)] | if length == 1 then .[0].id else error("expected one active target account") end' )" export ACCOUNT_ID printf '%s\n' "${ACCOUNT_ID}" > account-id.txt printf 'Selected account: %s (%s)\n' "${ACCOUNT_NAME}" "${ACCOUNT_ID}" ``` **Python** ```python import requests base_url = "https://demo.one.digicert.com" response = requests.get( f"{base_url}/account/api/v1/account", headers={"x-api-key": bootstrap_api_token}, timeout=30, ) response.raise_for_status() accounts = response.json() matches = [item for item in accounts if item["name"] == "TARGET_ACCOUNT_NAME" and item["active"]] if len(matches) != 1: raise RuntimeError(f"Expected one active target account. Found {len(matches)}") account_id = matches[0]["id"] print(f"Selected account: {matches[0]['name']} ({account_id})") ``` The cURL example exports `ACCOUNT_ID`. The Python example assigns `account_id`. ## Step 1.2: Find the required role names Role names are tenant-dependent. Retrieve the roles and select the minimum set that grants the DigiCert® Private CA, DigiCert® Device Trust Manager, and Software Trust Manager operations listed in [Before you begin](https://dev.digicert.com/md/solutions/private-trust-stack.md#before-you-begin). ```bash curl --fail-with-body --silent --show-error \ "https://demo.one.digicert.com/account/api/v1/role?account_id=${ACCOUNT_ID}" \ -H "x-api-key: ${BOOTSTRAP_API_TOKEN}" | jq '{ca_manager, device_trust_manager, secure_software_manager}' ``` Record the exact `name` values. Do not copy example role names from the API reference or another account. ## Step 1.3: Select an organization Software Trust Manager private trust certificate profiles associate issued certificates with an organization. Select the intended active organization by exact name. ```bash ORGANIZATION_NAME="Example organization" ORGANIZATION_ID="$( curl --fail-with-body --silent --show-error \ "https://demo.one.digicert.com/account/api/v1/organization?account_id=${ACCOUNT_ID}" \ -H "x-api-key: ${BOOTSTRAP_API_TOKEN}" | jq -er --arg name "${ORGANIZATION_NAME}" ' [.[] | select(.name == $name and .active == true)] | if length == 1 then .[0].id else error("expected one active target organization") end' )" export ORGANIZATION_ID printf '%s\n' "${ORGANIZATION_ID}" > organization-id.txt printf 'Selected organization: %s (%s)\n' "${ORGANIZATION_NAME}" "${ORGANIZATION_ID}" ``` The example fails unless the approved name identifies exactly one active organization. It exports `ORGANIZATION_ID` as the shell equivalent of `organization_id`. ## Step 1.4: Create the setup service user Set `ROLE_NAMES_JSON` to an array of exact role `name` values from [Find the required role names](#step-12-find-the-required-role-names). The API returns `api_token.token` only once. Write the response to a protected file, and do not print the token in logs. ```bash umask 077 ROLE_NAMES_JSON='[ "", "", "" ]' jq -n \ --arg account_id "${ACCOUNT_ID}" \ --argjson roles "${ROLE_NAMES_JSON}" \ '{ user_type: "service", friendly_name: "Private trust stack setup", email: "pki-automation-owner@example.com", description: "Setup identity for the private trust solution", accounts: [$account_id], roles: $roles }' | curl --fail-with-body --silent --show-error \ -X POST "https://demo.one.digicert.com/account/api/v1/user" \ -H "x-api-key: ${BOOTSTRAP_API_TOKEN}" \ -H "Content-Type: application/json" \ --data-binary @- \ -o service-user-response.json jq -r '.api_token.token' service-user-response.json > service-api-token.txt jq -r '.id' service-user-response.json > service-user-id.txt jq -r '.api_token.id' service-user-response.json > api-token-id.txt chmod 600 service-api-token.txt service-user-id.txt api-token-id.txt service-user-response.json SERVICE_USER_ID="$(", "enabled": true } } ``` Save the user `id` as `service_user_id`, `api_token.id` as `api_token_id`, and the returned token as `service_api_token`. You need both IDs to remove the credentials later and associate them with audit events. ## Step 1.5: Create the service user's client certificate The client authentication certificate must belong to the same service user whose API token you use with Software Trust Manager. Generate the private key locally, submit only the CSR, and authenticate the request with the service-user API token returned when you [create the setup service user](#step-14-create-the-setup-service-user). Send the token in the `x-api-key` header. The API associates the new certificate with the authenticated service user and never receives the private key. Set `CLIENT_AUTH_CERTIFICATE_EXPIRATION` to an approved UTC timestamp no more than 397 days in the future. The Account Manager API requires the `expiration_date` property. ```bash umask 077 CLIENT_AUTH_CERTIFICATE_NAME="Private trust stack client authentication" CLIENT_AUTH_CERTIFICATE_EXPIRATION="2027-01-31T23:59:59Z" openssl req -new -newkey rsa:2048 -nodes \ -keyout client.key \ -out client.csr \ -subj "/CN=Private trust stack setup" chmod 600 client.key client.csr jq -n \ --rawfile csr client.csr \ --arg name "${CLIENT_AUTH_CERTIFICATE_NAME}" \ --arg expiration_date "${CLIENT_AUTH_CERTIFICATE_EXPIRATION}" ' { csr: $csr, name: $name, expiration_date: $expiration_date }' | curl --fail-with-body --silent --show-error \ -X POST "https://demo.one.digicert.com/account/api/v1/client-auth-certificate" \ -H "x-api-key: ${SERVICE_API_TOKEN}" \ -H "Content-Type: application/json" \ --data-binary @- \ -o client-auth-certificate-response.json jq -er '.x509_cert' client-auth-certificate-response.json > client.crt jq -er '.ca_cert' client-auth-certificate-response.json > client-auth-ca.pem jq -er '.id' client-auth-certificate-response.json > client-auth-certificate-id.txt CLIENT_AUTH_CERTIFICATE_ID="$( /dev/null ``` ## Phase 1 checkpoint - [ ] `account_id` identifies the intended active account. - [ ] `organization_id` identifies the approved active organization. - [ ] The service user has only the required tenant role names. - [ ] `service_api_token` is stored in a secret manager or protected local file and does not appear in logs. - [ ] `client.crt` and `client.key` belong to the service user and match cryptographically. - [ ] The response `end_date` matches the certificate's `notAfter` value and complies with the approved validity policy. Next, [prepare the private trust domain](https://dev.digicert.com/md/solutions/private-trust-stack/phase-2-private-trust-anchor.md). ## Outputs and handoff | Output | Produced in | Used by | | --- | --- | --- | | `account_id` | Select the target account: response `id` | [Prepare the private trust domain](https://dev.digicert.com/md/solutions/private-trust-stack/phase-2-private-trust-anchor.md), [Configure device certificate infrastructure](https://dev.digicert.com/md/solutions/private-trust-stack/phase-3-device-infrastructure.md), [Enroll and verify a device](https://dev.digicert.com/md/solutions/private-trust-stack/phase-4-device-enrollment.md), [Configure and test private code signing](https://dev.digicert.com/md/solutions/private-trust-stack/phase-5-code-signing.md) | | `organization_id` | Select an organization: response `id` | [Configure and test private code signing](https://dev.digicert.com/md/solutions/private-trust-stack/phase-5-code-signing.md) | | `service_user_id` | Create the setup service user: response `id` | Operations, audit, or cleanup | | `api_token_id` | Create the setup service user: response `api_token.id` | Operations, audit, or cleanup | | `service_api_token` | Create the setup service user: response `api_token.token` | [Prepare the private trust domain](https://dev.digicert.com/md/solutions/private-trust-stack/phase-2-private-trust-anchor.md), [Configure device certificate infrastructure](https://dev.digicert.com/md/solutions/private-trust-stack/phase-3-device-infrastructure.md), [Enroll and verify a device](https://dev.digicert.com/md/solutions/private-trust-stack/phase-4-device-enrollment.md), [Configure and test private code signing](https://dev.digicert.com/md/solutions/private-trust-stack/phase-5-code-signing.md) | | `client_auth_certificate_id` | Create the service user's client certificate: response `id` | Operations, audit, or cleanup | | `client.crt` | Create the service user's client certificate | [Configure and test private code signing](https://dev.digicert.com/md/solutions/private-trust-stack/phase-5-code-signing.md) | | `client.key` | Create the service user's client certificate | [Configure and test private code signing](https://dev.digicert.com/md/solutions/private-trust-stack/phase-5-code-signing.md) |