Skip to main content
TNB provides a flexible credential management system for external services that supports multiple storage backends including HashiCorp Vault, YAML files, and system properties.

Overview

Each System-X service has an associated Account class that contains connection information. For external services (like AWS, Salesforce, Twitter), credentials should not be hardcoded. TNB’s AccountFactory automatically loads credentials from configured sources.
Self-hosted services (Kafka, MongoDB, PostgreSQL) use hardcoded credentials by default since they’re deployed by TNB. External services require credential configuration.

Credential loading methods

TNB supports three methods for loading credentials, with the following priority:
1

HashiCorp Vault

Load credentials from a Vault server (most secure for production)
2

YAML file

Load credentials from a local YAML file (convenient for development)
3

System property

Load credentials from a YAML string in system properties (useful for CI/CD)

Using YAML credentials file

The simplest method for local development is using a YAML credentials file.

File format

Create a YAML file with the following structure:
services:
    aws:
        credentials:
            access_key: AKIAIOSFODNN7EXAMPLE
            secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
            region: us-east-1
            account_id: "123456789012"
    jira:
        credentials:
            username: [email protected]
            password: mypassword
    salesforce:
        credentials:
            client_id: 3MVG9lKcPoNINVB...
            client_secret: 1234567890123456789
            username: [email protected]
            password: mypassword
            login_url: https://login.salesforce.com
    slack:
        credentials:
            token: xoxb-1234-5678-abcd
            webhook_url: https://hooks.slack.com/services/T00/B00/XXXX
The credentials ID (like aws, jira) must match the ID returned by the account’s credentialsId() method.

Configuring the credentials file

Specify the path to your credentials file:
test.credentials.file=~/tnb-credentials.yaml

Field naming conventions

YAML field names must match the Java account class field names exactly:
services:
    aws:
        credentials:
            access_key: AKIAIOSFODNN7EXAMPLE
            secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
            region: us-east-1

Using HashiCorp Vault

For production environments, use HashiCorp Vault to securely store credentials.

Vault structure

Store credentials in Vault with the same YAML structure:
{
  "access_key": "AKIAIOSFODNN7EXAMPLE",
  "secret_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "region": "us-east-1",
  "account_id": "123456789012"
}

Configuration

Configure Vault access with these properties:
test.credentials.use.vault=true
test.credentials.vault.address=https://vault.company.com
test.credentials.vault.token=s.XXXXXXXXXXXXXXXXXXXX
test.credentials.vault.path.pattern=/secret/services/%s/credentials
The %s in the path pattern is replaced with the credentials ID (e.g., aws, jira).
Never hardcode Vault tokens in properties files. Use environment variables:
mvn test -Dtest.credentials.vault.token=${VAULT_TOKEN}

Vault path patterns

The path pattern determines where credentials are stored in Vault:
PatternExample resolution for aws
/secret/services/%s/credentials/secret/services/aws/credentials
/kv/data/%s/kv/data/aws
/team/shared/%s/creds/team/shared/aws/creds

Using system property credentials

For CI/CD pipelines, pass credentials as a YAML string in system properties:
mvn test -Dtest.credentials="
services:
  aws:
    credentials:
      access_key: ${AWS_ACCESS_KEY}
      secret_key: ${AWS_SECRET_KEY}
      region: us-east-1
"
This method uses the same YAML format as the credentials file, but passed as a string.

Overriding account IDs

Each account has a default credentials ID. Override it using a system property:
# Override AWSAccount to use different credentials
tnb.awsaccount.id=aws-production

# Override SlackAccount
tnb.slackaccount.id=slack-team-a
The property format is: tnb.<AccountClassName>.id
services:
    aws-production:  # Custom ID
        credentials:
            access_key: PROD_KEY
            secret_key: PROD_SECRET
            region: us-east-1
    aws-staging:  # Another custom ID
        credentials:
            access_key: STAGING_KEY
            secret_key: STAGING_SECRET
            region: us-west-2

Composite accounts

Composite accounts allow credential inheritance from parent account classes.

How it works

When creating an account, TNB checks all parent classes for the WithId interface and merges credentials:
public class ParentAccount implements Account, WithId {
    private String parentKey;

    @Override
    public String credentialsId() {
        return "parent";
    }
}
When creating ChildAccount, TNB:
  1. Loads credentials from parent ID
  2. Merges credentials from child ID
  3. Result: both parentKey and childKey are populated

Partial credentials

At least one credentials ID must exist. You can provide all values under one ID:
services:
    child:
        credentials:
            parentKey: parentValue  # Parent class field
            childKey: childValue    # Child class field
This is useful when you don’t want to split credentials across multiple entries.

Loading credentials in code

Use AccountFactory to load credentials automatically:
import software.tnb.common.account.AccountFactory;

// Automatically loads credentials based on account's credentialsId()
AWSAccount account = AccountFactory.create(AWSAccount.class);

// Access credentials
String accessKey = account.getAccessKey();
String secretKey = account.getSecretKey();
If the account doesn’t implement WithId, AccountFactory.create() returns an instance with default values and no credential loading.

TNB CLI credential management

The TNB CLI tool has special credential handling:
1

Credential request

When deploying a service that needs credentials, the CLI prompts you to enter them interactively if not found.
2

Local storage

Entered credentials are saved to ~/.tnb/credentials/<id>.properties for future use.
3

Configuration file

Set up credentials in ~/.tnb/init.groovy:
System.setProperty('test.credentials.file', '~/credentials.yaml')
See the CLI tool documentation for more details.

Security best practices

Never commit credentials

Add credentials files to .gitignore. Use template files to document required structure.

Use Vault for production

Always use HashiCorp Vault or similar secret management for production and shared environments.

Rotate credentials

Regularly rotate credentials, especially after team member changes or potential exposure.

Minimal permissions

Use service accounts with minimal required permissions instead of personal credentials.

Separate environments

Use different credentials for development, staging, and production environments.

Environment variables

In CI/CD, inject credentials via environment variables, never hardcode in pipeline definitions.

Troubleshooting

Ensure the credentials ID matches between your account’s credentialsId() method and your YAML file or Vault path.Check that the credentials file path is correct and the file exists:
ls -la ~/credentials.yaml
Verify that YAML field names exactly match the Java account class field names (including underscores).Use the same case and naming convention:
# Correct
access_key: value

# Wrong - won't match access_key field
accessKey: value
Verify your Vault token is valid:
vault token lookup
Check the Vault path exists and you have read permissions:
vault kv get /secret/services/aws/credentials
Remember that at least one credentials ID (parent or child) must exist in your credentials source.Check that parent classes implementing WithId have credentials defined if using inheritance.

Example configurations

credentials.yaml
services:
    aws:
        credentials:
            access_key: AKIAIOSFODNN7EXAMPLE
            secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
            region: us-east-1
            account_id: "123456789012"
    salesforce:
        credentials:
            client_id: 3MVG9lKcPoNINVB...
            client_secret: 1234567890123456789
            username: [email protected]
            password: devpassword123
            login_url: https://test.salesforce.com
test.properties
test.credentials.file=~/tnb-credentials.yaml

Build docs developers (and LLMs) love