The Clanker backend provides secure credential storage and retrieval, allowing you to sync cloud provider credentials across multiple machines without managing local credential files.
Overview
Instead of configuring AWS, GCP, Azure, Cloudflare, and Kubernetes credentials on every machine, store them once in the Clanker backend and retrieve them with an API key.
Benefits :
Single source of truth : Update credentials in one place
Multi-machine sync : Same credentials on laptop, server, CI/CD
Secure storage : Credentials encrypted at rest
No local credential files : Reduces credential sprawl
Easy rotation : Update once, applies everywhere
Configuration
Set backend credentials in your config file:
backend :
# API key for authentication (or set CLANKER_BACKEND_API_KEY)
api_key : "your-api-key-here"
# Environment: testing, staging, or production
env : "testing"
# Optional: Custom backend URL (overrides env)
# url: "https://custom-url.example.com"
Or use environment variables:
export CLANKER_BACKEND_API_KEY = "your-api-key"
export CLANKER_BACKEND_ENV = "testing" # optional
export CLANKER_BACKEND_URL = "https://..." # optional
Or pass as flags:
clanker ask "test" --api-key "your-key" --backend-env "testing"
See cmd/root.go:40 for backend flags.
Storing credentials
AWS credentials
Store credentials from an existing AWS profile:
clanker credentials store aws --profile dev
This reads from ~/.aws/credentials and uploads:
Access key ID
Secret access key
Region (from profile config)
Session token (if present)
Or provide credentials directly:
clanker credentials store aws \
--access-key-id "AKIA..." \
--secret-access-key "..." \
--region "us-east-1"
API endpoint : PUT /api/v1/secrets/aws
Request body :
{
"provider" : "aws" ,
"credentials" : {
"access_key_id" : "AKIA..." ,
"secret_access_key" : "..." ,
"region" : "us-east-1" ,
"session_token" : "..." // optional
}
}
See internal/backend/client.go:237.
GCP credentials
Store GCP service account credentials:
clanker credentials store gcp \
--project-id "my-project" \
--service-account-json "$( cat service-account.json)"
API endpoint : PUT /api/v1/secrets/gcp
Request body :
{
"provider" : "gcp" ,
"credentials" : {
"project_id" : "my-project" ,
"service_account_json" : "{ \" type \" : \" service_account \" ,...}"
}
}
See internal/backend/client.go:264.
Azure credentials
Store Azure service principal credentials:
clanker credentials store azure \
--subscription-id "..." \
--tenant-id "..." \
--client-id "..." \
--client-secret "..."
API endpoint : PUT /api/v1/secrets/azure
Request body :
{
"provider" : "azure" ,
"credentials" : {
"subscription_id" : "..." ,
"tenant_id" : "..." ,
"client_id" : "..." ,
"client_secret" : "..."
}
}
See internal/backend/client.go:346.
Cloudflare credentials
Store Cloudflare API token:
clanker credentials store cloudflare \
--api-token "..." \
--account-id "..." \
--zone-id "..." # optional
API endpoint : PUT /api/v1/secrets/cloudflare
Request body :
{
"provider" : "cloudflare" ,
"credentials" : {
"api_token" : "..." ,
"account_id" : "..." ,
"zone_id" : "..." // optional
}
}
See internal/backend/client.go:291.
Kubernetes credentials
Store kubeconfig content:
clanker credentials store kubernetes \
--kubeconfig "$( cat ~/.kube/config)" \
--context "production" # optional
API endpoint : PUT /api/v1/secrets/kubernetes
Request body :
{
"provider" : "kubernetes" ,
"credentials" : {
"kubeconfig_content" : "apiVersion: v1 \n kind: Config \n ..." ,
"context_name" : "production" // optional
}
}
See internal/backend/client.go:318.
Retrieving credentials
Clanker automatically retrieves credentials from the backend when you provide an API key.
Automatic retrieval
# Set API key once
export CLANKER_BACKEND_API_KEY = "your-key"
# Credentials loaded automatically
clanker ask "list ec2 instances" --aws
Debug output :
[backend] GET /api/v1/cli/credentials/aws
[backend] Using AWS credentials from backend
If backend credentials aren’t available, Clanker falls back to local credentials:
[backend] No AWS credentials available (not found), falling back to local
See cmd/ask.go:638.
Manual listing
List all stored credentials:
clanker credentials list --api-key "your-key"
Output :
Stored Credentials:
Provider: aws
Created: 2024-03-15 10:30:00
Updated: 2024-03-20 14:15:00
Masked: access_key_id=AKIA***, region=us-east-1
Provider: gcp
Created: 2024-03-16 09:00:00
Updated: 2024-03-16 09:00:00
Masked: project_id=my-project
Provider: cloudflare
Created: 2024-03-18 16:45:00
Updated: 2024-03-18 16:45:00
Masked: account_id=abc***
API endpoint : GET /api/v1/cli/credentials
Response :
{
"success" : true ,
"data" : [
{
"provider" : "aws" ,
"created_at" : "2024-03-15T10:30:00Z" ,
"updated_at" : "2024-03-20T14:15:00Z" ,
"masked" : {
"access_key_id" : "AKIA***" ,
"region" : "us-east-1"
}
}
]
}
See internal/backend/client.go:373.
Deleting credentials
Remove stored credentials:
clanker credentials delete aws --api-key "your-key"
API endpoint : DELETE /api/v1/secrets/aws
Response :
{
"success" : true ,
"message" : "Credentials deleted successfully"
}
See internal/backend/client.go:396.
Backend environments
Clanker supports multiple backend environments:
Environment URL Purpose testinghttps://lychaz5ra6.execute-api.us-east-1.amazonaws.com/testingDevelopment and testing staginghttps://2gjp7z6bxi.execute-api.us-east-1.amazonaws.com/stagingPre-production validation productionContact support Production use (contact for access)
Set the environment:
Or override with a custom URL:
backend :
url : "https://your-custom-backend.example.com"
See internal/backend/resolver.go for URL resolution.
API client implementation
Client structure
type Client struct {
apiKey string
baseURL string
httpClient * http . Client
debug bool
}
func NewClient ( apiKey string , debug bool ) * Client {
return & Client {
apiKey : apiKey ,
baseURL : ResolveBackendURL (),
httpClient : & http . Client {
Timeout : 30 * time . Second ,
},
debug : debug ,
}
}
See internal/backend/client.go:20.
Authentication
All requests include the API key in the X-API-Key header:
req . Header . Set ( "X-API-Key" , c . apiKey )
req . Header . Set ( "Content-Type" , "application/json" )
See internal/backend/client.go:70.
Error handling
The client handles common HTTP error codes:
Status Error 401 unauthorized: invalid API key404 not found: credential or resource does not exist400+ Parse error message from response body
Example :
if resp . StatusCode == http . StatusUnauthorized {
return nil , fmt . Errorf ( "unauthorized: invalid API key" )
}
if resp . StatusCode >= 400 {
var apiResp APIResponse
if err := json . Unmarshal ( respBody , & apiResp ); err == nil && apiResp . Error != "" {
return nil , fmt . Errorf ( "API error: %s " , apiResp . Error )
}
return nil , fmt . Errorf ( "API error: status %d " , resp . StatusCode )
}
See internal/backend/client.go:88.
Credential types
AWS credentials
type AWSCredentials struct {
AccessKeyID string `json:"access_key_id"`
SecretAccessKey string `json:"secret_access_key"`
Region string `json:"region,omitempty"`
SessionToken string `json:"session_token,omitempty"`
}
See internal/backend/types.go:5.
GCP credentials
type GCPCredentials struct {
ProjectID string `json:"project_id"`
ServiceAccountJSON string `json:"service_account_json,omitempty"`
}
See internal/backend/types.go:13.
Azure credentials
type AzureCredentials struct {
SubscriptionID string `json:"subscription_id"`
TenantID string `json:"tenant_id,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientSecret string `json:"client_secret,omitempty"`
}
See internal/backend/types.go:32.
Cloudflare credentials
type CloudflareCredentials struct {
APIToken string `json:"api_token"`
AccountID string `json:"account_id,omitempty"`
ZoneID string `json:"zone_id,omitempty"`
}
See internal/backend/types.go:19.
Kubernetes credentials
type KubernetesCredentials struct {
KubeconfigContent string `json:"kubeconfig_content"`
ContextName string `json:"context_name,omitempty"`
}
See internal/backend/types.go:26.
Fallback behavior
Clanker always tries backend credentials first, then falls back to local configuration:
Check for backend API key (flag, env var, or config)
If API key exists : Try to retrieve credentials from backend
If backend succeeds : Use backend credentials
If backend fails (not found, unauthorized, etc.): Fall back to local credentials
Example flow (AWS):
backendAPIKey := backend . ResolveAPIKey ( apiKeyFlag )
if backendAPIKey != "" {
backendClient := backend . NewClient ( backendAPIKey , debug )
backendCreds , backendErr := backendClient . GetAWSCredentials ( ctx )
if backendErr == nil {
// Use backend credentials
awsClient , err = aws . NewClientWithCredentials ( ctx , & aws . BackendAWSCredentials {
AccessKeyID : backendCreds . AccessKeyID ,
SecretAccessKey : backendCreds . SecretAccessKey ,
Region : backendCreds . Region ,
}, debug )
} else {
// Fall back to local profile
awsClient , err = aws . NewClientWithProfileAndDebug ( ctx , targetProfile , debug )
}
}
See cmd/ask.go:638.
Security considerations
Never commit your API key or credentials to version control. Use environment variables or local config files (ensure ~/.clanker.yaml is in .gitignore).
API key protection
# Store API key in environment variable
echo 'export CLANKER_BACKEND_API_KEY="your-key"' >> ~/.zshrc
source ~/.zshrc
# Or use a password manager
clanker ask "test" --api-key "$( security find-generic-password -s clanker-api-key -w )"
Credential rotation
When rotating cloud provider credentials:
Generate new credentials in your cloud provider console
Update backend storage:
clanker credentials store aws --profile new-profile
Verify retrieval:
clanker credentials list --debug
Delete old credentials from cloud provider
Audit trail
The backend tracks creation and update timestamps:
Provider: aws
Created: 2024-03-15 10:30:00
Updated: 2024-03-20 14:15:00 ← Last rotation
Troubleshooting
Invalid API key
Error :
failed to get AWS credentials: unauthorized: invalid API key
Solution :
Check your API key:
echo $CLANKER_BACKEND_API_KEY
Or verify in config:
grep api_key ~/.clanker.yaml
Credentials not found
Error :
failed to get AWS credentials: not found: credential or resource does not exist
Solution :
Store credentials first:
clanker credentials store aws --profile dev
Verify storage:
Backend timeout
Error :
request failed: context deadline exceeded
Solution :
Check network connectivity and backend URL:
curl -I https://lychaz5ra6.execute-api.us-east-1.amazonaws.com/testing/api/v1/cli/credentials
The default timeout is 30 seconds (see internal/backend/client.go:34).
Wrong backend environment
Error :
Solution :
Verify backend environment:
clanker credentials list --backend-env "testing" --debug
Expected debug output:
[backend] GET /api/v1/cli/credentials
Configuration Config file and backend setup
Debugging Debug credential retrieval
Credentials command CLI reference for credential management
Security Best practices for credential management