Blog

Luis Majano

June 15, 2026

Spread the word


Share your thoughts

Every production application carries secrets: database passwords, API tokens, encryption keys. The question is never whether to manage them -- it's how badly the current approach is going to hurt you.

Hardcoded credentials in config files get committed to repos. Environment variables sprawl across deployment pipelines with no audit trail. Custom integration code for each cloud provider means three different patterns to maintain, test, and rotate. And when a key needs to rotate at 2am? Someone is waking up.

Today we're shipping three new BoxLang+ modules that solve this at the language level:

  • bx-aws-secrets -- AWS Secrets Manager
  • bx-azure-secrets -- Azure Key Vault
  • bx-google-secrets -- Google Secret Manager

One consistent API. Three major cloud providers. Zero custom plumbing in your application code. They are also fully documented:


One Pattern to Rule Them All

No matter which cloud provider you use, the interface is the same:

// AWS
dbPassword = getSystemSetting( "aws.DB_PASSWORD" )

// Azure
dbPassword = getSystemSetting( "azure.DB-PASSWORD" )

// Google
dbPassword = getSystemSetting( "google.DB_PASSWORD" )

That's it. BoxLang's getSystemSetting() BIF understands cloud provider namespaces. Your application code never knows where the secret lives -- and that's the point. Swap providers, rotate credentials, move between environments: your code doesn't change.

Need a fallback for local development?

apiKey = getSystemSetting( "aws.API_KEY", "local-dev-key" )

If the secret can't be resolved (no credentials, wrong environment, network issue), BoxLang falls back gracefully to your default. No exceptions to swallow, no conditional logic to write.


Installation

Via CommandBox

# AWS
box install bx-plus,bx-aws-secrets

# Azure
box install bx-plus,bx-azure-secrets

# Google
box install bx-plus,bx-google-secrets

Via BoxLang OS Binary

install-bx-module bx-plus bx-aws-secrets
install-bx-module bx-plus bx-azure-secrets
install-bx-module bx-plus bx-google-secrets

All three modules require an active BoxLang+ license. See plans at boxlang.io/plans.


How Configuration Resolution Works

Each module resolves its settings using a clean 3-tier hierarchy -- independently per setting, so you can mix sources freely:

PrioritySourceUse Case
1stthis.aws / this.azure / this.google in Application.bxPer-application isolation
2ndModule settings in boxlang.jsonGlobal server defaults
3rdCloud provider environment variablesCI/CD pipelines, containers

This means a multi-tenant server can run multiple applications, each with their own credentials and region, with no cross-contamination. Each application gets its own dedicated client instance, created on first use and cleaned up on application shutdown.

Per-Application Configuration (Application.bx)

class {
    this.name = "myApp"

    // AWS example
    this.aws = {
        region          : "us-east-2",
        accessKeyId     : "${Setting: AWS_ACCESS_KEY_ID not found}",
        secretAccessKey : "${Setting: AWS_SECRET_ACCESS_KEY not found}",
        cacheTTL        : 300
    }

    // Azure example
    this.azure = {
        vaultUrl     : "https://my-vault.vault.azure.net/",
        tenantId     : "${Setting: AZURE_TENANT_ID not found}",
        clientId     : "${Setting: AZURE_CLIENT_ID not found}",
        clientSecret : "${Setting: AZURE_CLIENT_SECRET not found}",
        cacheTTL     : 300
    }

    // Google example
    this.google = {
        projectId       : "my-gcp-project",
        credentialsPath : "${Setting: GOOGLE_APPLICATION_CREDENTIALS not found}",
        cacheTTL        : 300
    }
}

Global Server Configuration (boxlang.json)

{
  "modules": {
    "bxaws-secrets": {
      "settings": {
        "region": "us-east-2",
        "accessKeyId": "${Setting: AWS_ACCESS_KEY_ID not found}",
        "secretAccessKey": "${Setting: AWS_SECRET_ACCESS_KEY not found}",
        "cacheTTL": 300
      }
    },
    "bxazure-secrets": {
      "settings": {
        "vaultUrl": "https://my-vault.vault.azure.net/",
        "cacheTTL": 300
      }
    },
    "bxgoogle-secrets": {
      "settings": {
        "projectId": "my-gcp-project",
        "cacheTTL": 300
      }
    }
  }
}

Real-World Usage: Datasource Configuration

This is where it gets satisfying. No more credentials in your datasource config, no more environment variable juggling:

class {
    this.name = "myApp"

    this.datasources = {
        main : {
            className        : "org.postgresql.Driver",
            connectionString : "jdbc:postgresql: //db.prod.internal:5432/app",
            username         : getSystemSetting( "aws.DB_USER" ),
            password         : getSystemSetting( "aws.DB_PASSWORD" )
        }
    }
}

Rotate the secret in AWS Secrets Manager, and the next cache expiry cycle picks it up automatically. No redeployment, no config change, no 2am wake-up call.


Built-In Caching: Performance Without Compromise

Every secrets call is cached in-memory with a configurable TTL (default: 300 seconds). Cache keys are scoped to the provider identity (region:secretName for AWS, vaultUrl:secretName for Azure, projectId:secretName for Google) so there is no leakage between applications or providers.

The math is straightforward: a BoxLang application handling thousands of requests per minute would otherwise generate thousands of Secrets Manager API calls. With caching, that's one call per TTL window. Your cloud bill will notice.

Set cacheTTL to 0 if you need fresh values on every resolution -- useful in certain compliance scenarios.


Local Development Support

All three modules have first-class local development stories.

AWS with LocalStack:

{
  "modules": {
    "bxaws-secrets": {
      "settings": {
        "region": "us-east-1",
        "accessKeyId": "test",
        "secretAccessKey": "test",
        "endpointOverride": "http://localhost:4566"
      }
    }
  }
}
aws --endpoint-url=http://localhost:4566 secretsmanager create-secret \
  --name DB_PASSWORD \
  --secret-string "local-password"

Azure with Azure CLI:

az login
az keyvault secret set --vault-name my-vault --name DB-PASSWORD --value "local-password"

Google with gcloud:

gcloud auth application-default login
gcloud secrets create DB_PASSWORD --replication-policy="automatic"
gcloud secrets versions add DB_PASSWORD --data-file=- <<< "local-password"

In each case, the same application code that runs in production works locally with no changes. That's the contract.


Environment Variable Support

All three modules fall back to standard provider environment variables when no explicit configuration is set. This makes them drop-in compatible with existing container and CI/CD setups:

ModuleKey Variables
bx-aws-secretsAWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
bx-azure-secretsAZURE_KEY_VAULT_URL, AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
bx-google-secretsGOOGLE_CLOUD_PROJECT, GOOGLE_APPLICATION_CREDENTIALS

Azure and Google also support their respective managed identity and default credential chains (DefaultAzureCredential, Application Default Credentials), so workloads running inside Azure or GCP need no explicit credentials at all.


This Is a BoxLang+ Feature

These modules are available exclusively to BoxLang+ and BoxLang++ subscribers. If you're already a subscriber, install away. If you're not, this is a good moment to look at what's in the tier.

Explore BoxLang plans


Get Started

# Pick your provider and install
box install bx-plus,bx-aws-secrets
box install bx-plus,bx-azure-secrets
box install bx-plus,bx-google-secrets

Full documentation:

Questions? Drop into the Ortus Community -- we're there. 🚀


BoxLang+ modules are part of the Ortus Solutions commercial offering. A valid bx-plus license is required. See plans.

Add Your Comment

Recent Entries