Access Providers
This page details all access providers supported by Voidkey for minting temporary credentials.
Overview
Section titled “Overview”Access providers integrate with cloud services to mint temporary, scoped credentials. Each provider implements the common AccessProvider interface while handling provider-specific authentication and credential formats.
Provider Status
Section titled “Provider Status”| Provider | Status | Description |
|---|---|---|
| AWS STS | ✅ Production Ready | Full support for AWS credential minting |
| MinIO | ✅ Production Ready | S3-compatible storage with STS |
| Google Cloud | 🚧 Coming Soon | Currently under development |
| Azure | 🚧 Coming Soon | Currently under development |
AWS STS
Section titled “AWS STS”AWS Security Token Service provides temporary credentials for AWS resources.
Configuration
Section titled “Configuration”accessProviders: - name: "aws-prod" type: "aws-sts" region: "us-east-1"
# Optional configurations endpoint: "https://sts.amazonaws.com" externalId: "${AWS_EXTERNAL_ID}" maxDuration: 3600
# Session tags tags: Environment: "production" ManagedBy: "voidkey"Key Configuration
Section titled “Key Configuration”clientIdentities: - subject: "repo:myorg/myapp:ref:refs/heads/main" idp: "github-actions" keys: AWS_PROD_DEPLOY: provider: "aws-prod" roleArn: "arn:aws:iam::123456789012:role/DeploymentRole" duration: 3600 sessionName: "github-${GITHUB_RUN_ID}" externalId: "custom-external-id" # Override provider default
# Custom session tags tags: Repository: "${repository}" Branch: "${ref}"
# Output mapping outputs: AWS_ACCESS_KEY_ID: "AccessKeyId" AWS_SECRET_ACCESS_KEY: "SecretAccessKey" AWS_SESSION_TOKEN: "SessionToken" AWS_REGION: "us-east-1" AWS_DEFAULT_REGION: "us-east-1"IAM Role Trust Policy
Section titled “IAM Role Trust Policy”Configure your AWS IAM role to trust the Voidkey broker:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::ACCOUNT:oidc-provider/auth.voidkey.example.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "auth.voidkey.example.com:aud": "voidkey-broker", "auth.voidkey.example.com:sub": "broker-service" }, "StringLike": { "auth.voidkey.example.com:token_use": "access" } } } ]}Advanced Features
Section titled “Advanced Features”Cross-Account Access:
AWS_CROSS_ACCOUNT: provider: "aws-prod" roleArn: "arn:aws:iam::987654321098:role/CrossAccountRole" externalId: "shared-external-id" duration: 1800Regional Endpoints:
accessProviders: - name: "aws-govcloud" type: "aws-sts" region: "us-gov-west-1" endpoint: "https://sts.us-gov-west-1.amazonaws.com"Session Policies:
AWS_LIMITED_ACCESS: provider: "aws-prod" roleArn: "arn:aws:iam::123456789012:role/LimitedRole" duration: 3600 policy: | { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"], "Resource": ["arn:aws:s3:::specific-bucket/*"] }] }Credential Output
Section titled “Credential Output”{ "AWS_DEPLOY": { "AWS_ACCESS_KEY_ID": "ASIATESTACCESSKEY", "AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY", "AWS_SESSION_TOKEN": "FwoGZXIvYXdzEBYaD...", "AWS_REGION": "us-east-1", "AWS_DEFAULT_REGION": "us-east-1" }}Google Cloud Platform (Coming Soon)
Section titled “Google Cloud Platform (Coming Soon)”🚧 Work in Progress: Google Cloud support is currently under development. The configuration and examples below show the planned implementation for the upcoming release.
Google Cloud uses service account impersonation for temporary credentials.
Configuration
Section titled “Configuration”accessProviders: - name: "gcp-prod" type: "gcp" projectId: "my-project-123"
# Optional configurations endpoint: "https://iamcredentials.googleapis.com" location: "global"
# Impersonation chain delegates: - "intermediate-sa@project.iam.gserviceaccount.com"Key Configuration
Section titled “Key Configuration”clientIdentities: - subject: "repo:myorg/myapp:ref:refs/heads/main" idp: "github-actions" keys: GCP_DEPLOY: provider: "gcp-prod" serviceAccount: "deploy-sa@my-project.iam.gserviceaccount.com" duration: 3600
# OAuth 2.0 scopes scopes: - "https://www.googleapis.com/auth/cloud-platform" - "https://www.googleapis.com/auth/compute" - "https://www.googleapis.com/auth/storage.read_write"
# Impersonation chain delegates: - "intermediate-sa@project.iam.gserviceaccount.com"
# Output mapping outputs: GOOGLE_OAUTH_ACCESS_TOKEN: "accessToken" GOOGLE_TOKEN_EXPIRY: "expiry" GOOGLE_PROJECT_ID: "my-project-123" GOOGLE_APPLICATION_CREDENTIALS: "credentialsFile" # JSON file pathWorkload Identity Setup
Section titled “Workload Identity Setup”# Create workload identity poolgcloud iam workload-identity-pools create voidkey-pool \ --location="global" \ --description="Voidkey workload identity pool"
# Create OIDC providergcloud iam workload-identity-pools providers create-oidc voidkey-provider \ --workload-identity-pool="voidkey-pool" \ --location="global" \ --issuer-uri="https://auth.voidkey.example.com" \ --attribute-mapping="google.subject=assertion.sub,google.groups=assertion.groups"
# Grant impersonation permissionsgcloud iam service-accounts add-iam-policy-binding \ deploy-sa@my-project.iam.gserviceaccount.com \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/PROJECT-NUMBER/locations/global/workloadIdentityPools/voidkey-pool/attribute.subject/broker-service"Credential Output
Section titled “Credential Output”{ "GCP_DEPLOY": { "GOOGLE_OAUTH_ACCESS_TOKEN": "ya29.A0ARrdaM-abc123...", "GOOGLE_TOKEN_EXPIRY": "2024-01-15T11:00:00Z", "GOOGLE_PROJECT_ID": "my-project-123" }}Azure Active Directory (Coming Soon)
Section titled “Azure Active Directory (Coming Soon)”🚧 Work in Progress: Azure support is currently under development. The configuration and examples below show the planned implementation for the upcoming release.
Azure AD provides managed identity and service principal authentication.
Configuration
Section titled “Configuration”accessProviders: - name: "azure-prod" type: "azure" tenantId: "12345678-1234-1234-1234-123456789012"
# Optional configurations endpoint: "https://login.microsoftonline.com" environment: "AzurePublicCloud" # AzureUSGovernment, AzureChina, AzureGermanKey Configuration
Section titled “Key Configuration”clientIdentities: - subject: "repo:myorg/myapp:ref:refs/heads/main" idp: "github-actions" keys: AZURE_DEPLOY: provider: "azure-prod" clientId: "12345678-1234-1234-1234-123456789012" duration: 3600
# OAuth 2.0 scopes scopes: - "https://management.azure.com/.default" - "https://storage.azure.com/.default"
# Output mapping outputs: AZURE_ACCESS_TOKEN: "accessToken" AZURE_TOKEN_EXPIRY: "expiry" AZURE_TENANT_ID: "12345678-1234-1234-1234-123456789012" AZURE_CLIENT_ID: "12345678-1234-1234-1234-123456789012"Federated Identity Setup
Section titled “Federated Identity Setup”# Create federated identity credentialaz ad app federated-credential create \ --id "app-object-id" \ --parameters '{ "name": "voidkey-github", "issuer": "https://auth.voidkey.example.com", "subject": "broker-service", "audiences": ["voidkey-broker"], "description": "Voidkey broker federated identity" }'
# Assign roles to the applicationaz role assignment create \ --assignee "app-object-id" \ --role "Contributor" \ --scope "/subscriptions/subscription-id/resourceGroups/my-rg"Credential Output
Section titled “Credential Output”{ "AZURE_DEPLOY": { "AZURE_ACCESS_TOKEN": "eyJ0eXAiOiJKV1QiLCJhbGc...", "AZURE_TOKEN_EXPIRY": "2024-01-15T11:00:00Z", "AZURE_TENANT_ID": "12345678-1234-1234-1234-123456789012", "AZURE_CLIENT_ID": "12345678-1234-1234-1234-123456789012" }}MinIO provides S3-compatible object storage with STS support.
Configuration
Section titled “Configuration”accessProviders: - name: "minio-prod" type: "minio" endpoint: "https://minio.example.com" region: "us-east-1"
# Optional configurations pathStyle: true # Use path-style requests insecure: false # Skip TLS verification (dev only) maxDuration: 7200 # 2 hours maximumKey Configuration
Section titled “Key Configuration”clientIdentities: - subject: "repo:myorg/myapp:ref:refs/heads/main" idp: "github-actions" keys: MINIO_STORAGE: provider: "minio-prod" duration: 3600
# IAM policy for scoped access policy: | { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::app-uploads/*", "arn:aws:s3:::app-backups/*" ] }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": [ "arn:aws:s3:::app-uploads", "arn:aws:s3:::app-backups" ] } ] }
# Output mapping outputs: MINIO_ACCESS_KEY: "AccessKeyId" MINIO_SECRET_KEY: "SecretAccessKey" MINIO_SESSION_TOKEN: "SessionToken" MINIO_ENDPOINT: "https://minio.example.com" S3_ENDPOINT: "https://minio.example.com"MinIO Server Setup
Section titled “MinIO Server Setup”Configure MinIO server with OIDC integration:
# Environment variablesexport MINIO_IDENTITY_OPENID_CONFIG_URL="https://auth.voidkey.example.com/.well-known/openid-configuration"export MINIO_IDENTITY_OPENID_CLIENT_ID="voidkey-broker"export MINIO_IDENTITY_OPENID_CLIENT_SECRET="broker-secret"export MINIO_IDENTITY_OPENID_SCOPES="openid,profile,email"export MINIO_IDENTITY_OPENID_CLAIM_NAME="policy"export MINIO_IDENTITY_OPENID_CLAIM_PREFIX="minio"
# Start MinIOminio server /data --console-address ":9001"Credential Output
Section titled “Credential Output”{ "MINIO_STORAGE": { "MINIO_ACCESS_KEY": "ASIATESTACCESSKEY", "MINIO_SECRET_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY", "MINIO_SESSION_TOKEN": "eyJhbGciOiJIUzI1NiIs...", "MINIO_ENDPOINT": "https://minio.example.com", "S3_ENDPOINT": "https://minio.example.com" }}Custom Access Providers
Section titled “Custom Access Providers”Implement custom providers for unsupported services.
Interface Implementation
Section titled “Interface Implementation”import { AccessProvider, Credentials, ProviderConfig } from '@voidkey/broker-core';
export class CustomAccessProvider implements AccessProvider { name: string; type: string;
constructor(private config: CustomProviderConfig) { this.name = config.name; this.type = 'custom-service'; }
async authenticate(brokerToken: string): Promise<void> { // Authenticate the broker with the custom service // Store authentication context for subsequent requests
const response = await fetch(`${this.config.endpoint}/auth`, { method: 'POST', headers: { 'Authorization': `Bearer ${brokerToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: this.config.clientId, client_secret: this.config.clientSecret }) });
if (!response.ok) { throw new Error(`Authentication failed: ${response.statusText}`); }
const authData = await response.json(); this.authToken = authData.access_token; }
async mintCredentials( keyConfig: any, subject: string ): Promise<Credentials> { // Mint temporary credentials for the subject
const response = await fetch(`${this.config.endpoint}/credentials`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.authToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ subject: subject, duration: keyConfig.duration, permissions: keyConfig.permissions, scopes: keyConfig.scopes }) });
if (!response.ok) { throw new Error(`Credential minting failed: ${response.statusText}`); }
const credData = await response.json();
// Return standardized credential format return { AccessKeyId: credData.access_key, SecretAccessKey: credData.secret_key, SessionToken: credData.session_token, Expiration: new Date(credData.expires_at),
// Custom fields CustomField1: credData.custom_value, CustomField2: credData.another_value }; }
private authToken?: string;}Provider Configuration
Section titled “Provider Configuration”interface CustomProviderConfig { name: string; endpoint: string; clientId: string; clientSecret: string; timeout?: number; retries?: number;}Registration
Section titled “Registration”// Register custom providerimport { CustomAccessProvider } from './custom-access.provider';
const customProvider = new CustomAccessProvider({ name: 'custom-service', endpoint: 'https://api.custom-service.com', clientId: 'voidkey-client', clientSecret: process.env.CUSTOM_SERVICE_SECRET});
// Register with provider registryproviderRegistry.registerAccessProvider('custom-service', customProvider);Configuration Usage
Section titled “Configuration Usage”accessProviders: - name: "custom-prod" type: "custom-service" endpoint: "https://api.custom-service.com" clientId: "voidkey-client" clientSecret: "${CUSTOM_SERVICE_SECRET}"
clientIdentities: - subject: "repo:myorg/myapp:ref:refs/heads/main" idp: "github-actions" keys: CUSTOM_ACCESS: provider: "custom-prod" duration: 3600 permissions: - "read:data" - "write:logs" scopes: - "api:access" outputs: CUSTOM_ACCESS_KEY: "AccessKeyId" CUSTOM_SECRET_KEY: "SecretAccessKey" CUSTOM_SESSION_TOKEN: "SessionToken" CUSTOM_ENDPOINT: "https://api.custom-service.com"Provider Best Practices
Section titled “Provider Best Practices”Security
Section titled “Security”- Least Privilege:
# Scope credentials to minimum required permissionspolicy: | { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::specific-bucket/specific-path/*"] }] }- Short Duration:
# Use shortest practical durationduration: 900 # 15 minutes for automated tasksduration: 1800 # 30 minutes for interactive useduration: 3600 # 1 hour maximum for most cases- Audit Trails:
# Include identifying information in session names/tagssessionName: "voidkey-${subject}-${timestamp}"tags: RequestedBy: "${subject}" Purpose: "deployment" Repository: "${repository}"Performance
Section titled “Performance”- Connection Pooling:
// Reuse HTTP connectionsconst agent = new https.Agent({ keepAlive: true, maxSockets: 10});- Caching:
// Cache provider authentication tokensconst authCache = new Map<string, AuthToken>();
async authenticate(brokerToken: string): Promise<void> { const cached = authCache.get(this.name); if (cached && cached.expiresAt > Date.now()) { this.authToken = cached.token; return; }
// Perform authentication... authCache.set(this.name, { token: newToken, expiresAt: Date.now() + 3600000 // 1 hour });}- Parallel Requests:
// Mint multiple credentials in parallelasync mintMultipleCredentials(keyConfigs: KeyConfig[]): Promise<Credentials[]> { const promises = keyConfigs.map(config => this.mintCredentials(config)); return Promise.all(promises);}Error Handling
Section titled “Error Handling”- Retries:
async mintCredentials(keyConfig: any, subject: string): Promise<Credentials> { const maxRetries = 3; let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await this.doMintCredentials(keyConfig, subject); } catch (error) { lastError = error;
if (this.isRetryableError(error) && attempt < maxRetries) { const delay = Math.pow(2, attempt) * 1000; // Exponential backoff await new Promise(resolve => setTimeout(resolve, delay)); continue; }
throw error; } }
throw lastError;}- Provider-Specific Errors:
class ProviderError extends Error { constructor( message: string, public provider: string, public errorCode?: string, public retryable: boolean = false ) { super(message); this.name = 'ProviderError'; }}
// Usageif (response.status === 429) { throw new ProviderError( 'Rate limit exceeded', this.name, 'RATE_LIMIT_EXCEEDED', true // retryable );}Monitoring
Section titled “Monitoring”- Metrics:
// Track provider performanceconst providerMetrics = { requestCount: 0, successCount: 0, errorCount: 0, averageLatency: 0};
async mintCredentials(keyConfig: any, subject: string): Promise<Credentials> { const startTime = Date.now(); providerMetrics.requestCount++;
try { const result = await this.doMintCredentials(keyConfig, subject); providerMetrics.successCount++; return result; } catch (error) { providerMetrics.errorCount++; throw error; } finally { const latency = Date.now() - startTime; providerMetrics.averageLatency = (providerMetrics.averageLatency + latency) / 2; }}- Health Checks:
async healthCheck(): Promise<boolean> { try { const response = await fetch(`${this.config.endpoint}/health`, { timeout: 5000 }); return response.ok; } catch (error) { return false; }}Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”Authentication failures:
- Verify broker has valid credentials for provider
- Check IdP token is valid and not expired
- Ensure correct audience configuration
Permission denied:
- Verify IAM roles/policies are correctly configured
- Check trust relationships and conditions
- Ensure sufficient permissions for assumed role
Network connectivity:
- Test provider endpoint accessibility
- Check firewall rules and security groups
- Verify TLS certificates are valid
Token format errors:
- Ensure provider returns credentials in expected format
- Check output mapping configuration
- Verify credential field names match expectations
Debug Commands
Section titled “Debug Commands”# Test AWS STS accessaws sts get-caller-identity
# Test GCP service account impersonationgcloud auth print-access-token --impersonate-service-account=sa@project.iam.gserviceaccount.com
# Test Azure authenticationaz account get-access-token
# Test MinIO connectivitymc admin info myminioNext Steps
Section titled “Next Steps”- Identity Providers - Configure identity providers
- Custom Providers - Build custom providers
- Configuration Examples - Real-world configurations
- Security Model - Security considerations