External process credential provider executes external processes and parses their JSON output to retrieve credentials, useful for integration with custom credential management systems and corporate authentication tools.
Executes external processes to retrieve AWS credentials.
/**
* Creates a credential provider function that executes external process and parses JSON output
* @param init - Process credential configuration parameters
* @returns Process credential provider function
*/
function fromProcess(init?: FromProcessInit): AwsCredentialIdentityProvider;
interface FromProcessInit {
/** Configuration profile name (defaults to AWS_PROFILE or 'default') */
profile?: string;
/** Path to shared credentials file (defaults to ~/.aws/credentials) */
filepath?: string;
/** Path to shared config file (defaults to ~/.aws/config) */
configFilepath?: string;
}Usage Examples:
import { S3Client } from "@aws-sdk/client-s3";
import { fromProcess } from "@aws-sdk/credential-providers";
// Use default profile process configuration
const client = new S3Client({
region: "us-east-1",
credentials: fromProcess()
});
// Use specific profile
const devClient = new S3Client({
region: "us-east-1",
credentials: fromProcess({
profile: "development"
})
});
// Custom configuration file paths
const customClient = new S3Client({
region: "us-east-1",
credentials: fromProcess({
filepath: "/custom/path/credentials",
configFilepath: "/custom/path/config"
})
});Configure credential processes in AWS configuration files:
~/.aws/credentials:
[default]
credential_process = /usr/local/bin/aws-credentials
[development]
credential_process = /usr/local/bin/aws-credentials --environment dev
[production]
credential_process = /usr/local/bin/aws-credentials --environment prod --mfa~/.aws/config:
[default]
credential_process = /usr/local/bin/aws-credentials
region = us-east-1
[profile development]
credential_process = /usr/local/bin/aws-credentials --environment dev
region = us-west-2External processes must output JSON to stdout in this exact format:
{
"Version": 1,
"AccessKeyId": "ASIAIOSFODNN7EXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5T...",
"Expiration": "2023-12-31T23:59:59Z"
}#!/bin/bash
# /usr/local/bin/aws-credentials
# Example: retrieve credentials from corporate vault
VAULT_RESPONSE=$(vault kv get -format=json secret/aws/credentials)
# Extract credentials from vault response
ACCESS_KEY=$(echo "$VAULT_RESPONSE" | jq -r '.data.data.access_key')
SECRET_KEY=$(echo "$VAULT_RESPONSE" | jq -r '.data.data.secret_key')
SESSION_TOKEN=$(echo "$VAULT_RESPONSE" | jq -r '.data.data.session_token')
EXPIRATION=$(echo "$VAULT_RESPONSE" | jq -r '.data.data.expiration')
# Output in required format
cat <<EOF
{
"Version": 1,
"AccessKeyId": "$ACCESS_KEY",
"SecretAccessKey": "$SECRET_KEY",
"SessionToken": "$SESSION_TOKEN",
"Expiration": "$EXPIRATION"
}
EOF#!/usr/bin/env python3
# /usr/local/bin/aws-credentials
import json
import sys
import boto3
import argparse
from datetime import datetime, timezone
def get_credentials(environment):
"""Retrieve credentials from custom source"""
# Example: corporate SSO or identity provider integration
if environment == "dev":
# Development credentials logic
return {
"AccessKeyId": "AKIA...",
"SecretAccessKey": "...",
"SessionToken": "...",
"Expiration": "2023-12-31T23:59:59Z"
}
elif environment == "prod":
# Production credentials logic
# Could integrate with HashiCorp Vault, Azure Key Vault, etc.
return fetch_from_vault(environment)
raise ValueError(f"Unknown environment: {environment}")
def fetch_from_vault(environment):
"""Example integration with external credential store"""
# Your custom credential retrieval logic here
pass
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--environment", default="default")
parser.add_argument("--mfa", action="store_true")
args = parser.parse_args()
try:
credentials = get_credentials(args.environment)
output = {
"Version": 1,
**credentials
}
print(json.dumps(output))
except Exception as e:
print(json.dumps({"Error": str(e)}), file=sys.stderr)
sys.exit(1)#!/usr/bin/env node
// /usr/local/bin/aws-credentials
const { execSync } = require('child_process');
async function getCredentials() {
try {
// Example: integrate with corporate identity system
const response = await fetch('https://internal-auth.company.com/aws-credentials', {
headers: {
'Authorization': `Bearer ${process.env.COMPANY_TOKEN}`
}
});
const data = await response.json();
return {
Version: 1,
AccessKeyId: data.accessKey,
SecretAccessKey: data.secretKey,
SessionToken: data.sessionToken,
Expiration: data.expiresAt
};
} catch (error) {
console.error(JSON.stringify({ Error: error.message }));
process.exit(1);
}
}
getCredentials().then(credentials => {
console.log(JSON.stringify(credentials));
});Handle different environments with parameters:
~/.aws/config:
[profile dev-vault]
credential_process = vault-aws-credentials --environment=development
[profile prod-vault]
credential_process = vault-aws-credentials --environment=production --require-mfa
[profile test-corp]
credential_process = corporate-sso-credentials --domain=test.company.comImplement MFA in credential processes:
#!/bin/bash
# MFA-enabled credential process
if [ "$1" = "--mfa" ]; then
echo "Enter MFA token: " >&2
read -s MFA_TOKEN
VAULT_TOKEN=$(vault auth -method=aws -token="$MFA_TOKEN")
fi
# Retrieve credentials using MFA-authenticated session
vault kv get -format=json secret/aws/prod-credentials | \
jq '{
Version: 1,
AccessKeyId: .data.data.access_key,
SecretAccessKey: .data.data.secret_key,
SessionToken: .data.data.session_token,
Expiration: .data.data.expiration
}'Handle process credential failures:
import { fromProcess } from "@aws-sdk/credential-providers";
try {
const credentials = await fromProcess({
profile: "vault-profile"
})();
} catch (error) {
if (error.message.includes('Process exited with non-zero status')) {
console.error('Credential process failed - check process configuration');
} else if (error.message.includes('Invalid JSON response')) {
console.error('Process output is not valid JSON');
} else if (error.message.includes('Profile not found')) {
console.error('Process profile does not exist in configuration');
} else {
console.error('Process credentials failed:', error.message);
}
}# Set secure permissions for credential processes
chmod 750 /usr/local/bin/aws-credentials
chown root:aws-users /usr/local/bin/aws-credentials# Avoid passing secrets as command line arguments
# Use environment variables or secure files instead
credential_process = aws-credentials # Good
credential_process = aws-credentials --secret=xyz123 # Bad - visible in process listimport logging
import json
# Log credential requests for auditing
logging.basicConfig(
filename='/var/log/aws-credentials.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def get_credentials(environment):
logging.info(f"Credential request for environment: {environment}")
# ... credential retrieval logic
logging.info("Credentials retrieved successfully")
return credentials#!/bin/bash
# Vault AWS secrets engine integration
vault write aws/sts/developer ttl=1h | \
jq '{
Version: 1,
AccessKeyId: .data.access_key,
SecretAccessKey: .data.secret_key,
SessionToken: .data.security_token,
Expiration: (.data.ttl | tostring + "s" | now + (tonumber | floor) | strftime("%Y-%m-%dT%H:%M:%SZ"))
}'#!/usr/bin/env python3
import boto3
import json
from datetime import datetime, timezone
def get_sso_credentials():
"""Custom SSO credential logic"""
sso_client = boto3.client('sso')
# Custom SSO logic here
response = sso_client.get_role_credentials(
roleName='MyRole',
accountId='123456789012',
accessToken=get_cached_sso_token()
)
credentials = response['roleCredentials']
return {
"Version": 1,
"AccessKeyId": credentials['accessKeyId'],
"SecretAccessKey": credentials['secretAccessKey'],
"SessionToken": credentials['sessionToken'],
"Expiration": datetime.fromtimestamp(
credentials['expiration'] / 1000, timezone.utc
).isoformat().replace('+00:00', 'Z')
}
print(json.dumps(get_sso_credentials()))Process credentials are executed on each request:
#!/bin/bash
# Add caching to reduce external calls
CACHE_FILE="/tmp/aws-credentials-cache-$(id -u)"
CACHE_DURATION=3300 # 55 minutes
if [ -f "$CACHE_FILE" ] && [ $(($(date +%s) - $(stat -c %Y "$CACHE_FILE"))) -lt $CACHE_DURATION ]; then
cat "$CACHE_FILE"
else
# Fetch new credentials
NEW_CREDS=$(vault kv get -format=json secret/aws/credentials | \
jq '{Version:1,AccessKeyId:.data.data.access_key,SecretAccessKey:.data.data.secret_key,SessionToken:.data.data.session_token,Expiration:.data.data.expiration}')
echo "$NEW_CREDS" | tee "$CACHE_FILE"
fi