arazzo: 1.0.1 info: title: Grafana Issue Automation Credentials summary: Create a service account, mint a token for it, and confirm the token is attached. description: >- Grafana replaced long-lived API keys with service accounts, and this is the flow every pipeline needs before it can call anything else here. It creates a service account with a least-privilege role, mints a token with an explicit lifetime, and reads the account back to confirm the token is attached and the account is enabled. The token secret is returned exactly once, at creation, so the minting step's output is the only chance to capture it — send it straight to a secret store, never to a log. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: grafanaApi url: ../openapi/grafana-openapi.yml type: openapi workflows: - workflowId: issue-service-account-token summary: Provision a Grafana service account and an API token for automation. description: >- Creates the service account, adds a named token with a bounded lifetime, and verifies the resulting account state. inputs: type: object required: - accountName - tokenName properties: accountName: type: string description: Name of the service account (e.g. "ci-dashboard-deployer"). role: type: string description: >- Org role for the service account; Viewer, Editor, or Admin. Prefer the least privilege the automation can do its job with. default: Viewer isDisabled: type: boolean description: >- Create the account disabled. Useful when the account is provisioned ahead of the change window that turns it on. default: false tokenName: type: string description: Name of the token, shown in the UI and in audit logs. secondsToLive: type: integer description: >- Token lifetime in seconds. Omit for a token that never expires, which you should rarely want. steps: - stepId: createServiceAccount description: >- Create the service account. It is an identity in the current organization with its own role, so it can be audited and revoked independently of any person. operationId: createServiceAccount requestBody: contentType: application/json payload: name: $inputs.accountName role: $inputs.role isDisabled: $inputs.isDisabled successCriteria: - condition: $statusCode == 201 outputs: serviceAccountId: $response.body#/id serviceAccountUid: $response.body#/uid login: $response.body#/login role: $response.body#/role - stepId: mintToken description: >- Mint a token against the service account. The "key" returned here is the bearer credential and Grafana will not show it again — capture it into a secret store on this step or the account is useless. operationId: createToken parameters: - name: serviceAccountId in: path value: $steps.createServiceAccount.outputs.serviceAccountId requestBody: contentType: application/json payload: name: $inputs.tokenName secondsToLive: $inputs.secondsToLive successCriteria: - condition: $statusCode == 200 outputs: tokenId: $response.body#/id tokenName: $response.body#/name tokenKey: $response.body#/key - stepId: verifyAccount description: >- Read the service account back to confirm it is enabled and the token is attached, so a broken credential is caught here rather than by the first pipeline that tries to use it. operationId: retrieveServiceAccount parameters: - name: serviceAccountId in: path value: $steps.createServiceAccount.outputs.serviceAccountId successCriteria: - condition: $statusCode == 200 outputs: accountName: $response.body#/name isDisabled: $response.body#/isDisabled tokens: $response.body#/tokens role: $response.body#/role outputs: serviceAccountId: $steps.createServiceAccount.outputs.serviceAccountId serviceAccountUid: $steps.createServiceAccount.outputs.serviceAccountUid tokenId: $steps.mintToken.outputs.tokenId tokenKey: $steps.mintToken.outputs.tokenKey