Credential Management
A comprehensive guide to managing credentials securely in Qarion ETL.
Overview
Qarion ETL provides a credential store system that allows you to:
- Define credentials once and reuse them across different configurations
- Store credentials securely in databases, local keystores, or cloud key management services
- Reference credentials in configuration files without exposing sensitive data
- Support multiple backends (database, local keystore, AWS SSM Parameter Store)
- Automatic Fernet encryption - All credentials are encrypted using Fernet with a project-specific key
Fernet Encryption
Qarion ETL uses Fernet encryption (symmetric authenticated cryptography) to encrypt all stored credentials. A Fernet key is automatically generated when you initialize a new project and stored in your qarion-etl.toml configuration file.
Key Points:
- Fernet key is generated automatically on project initialization
- Each project has its own unique Fernet key
- All credential stores use this key for encryption
- The key is stored in
qarion-etl.toml- never commit this file to version control
Quick Start
1. Initialize Project (Fernet Key Generation)
When you create a new project, a Fernet encryption key is automatically generated:
qarion-etl new-project my_project
This creates qarion-etl.toml with a generated Fernet key:
fernet_key = "gAAAAABh..." # Automatically generated
Important: Never commit the fernet_key to version control. Add qarion-etl.toml to .gitignore or use environment variables for the key.
2. Configure Credential Store
Add credential store configuration to your qarion-etl.toml:
[credential_store]
type = "local_keystore"
[credential_store.config]
keystore_path = "~/.qarion_etl/credentials.keystore"
The Fernet key from your project configuration is automatically used for encryption.
3. Define Credentials
Define credential metadata in your configuration:
[[credentials]]
id = "my_aws_creds"
name = "AWS Production Credentials"
credential_type = "aws"
description = "AWS credentials for production S3 access"
4. Store Credentials
Store the actual credential data using the Python API:
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
store.store_credential(
credential_id="my_aws_creds",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "...",
"region_name": "us-east-1"
}
)
5. Use Credentials
Reference credentials in your configuration:
[properties.input_ingestion]
path = "s3://my-bucket/data/"
credentials = "${credential:my_aws_creds}"
Credential Store Types
Local Keystore (Recommended for Development)
Stores credentials in a local encrypted file.
Configuration:
[credential_store]
type = "local_keystore"
[credential_store.config]
keystore_path = "~/.qarion_etl/credentials.keystore" # Optional
Features:
- Simple setup, no external dependencies
- File permissions automatically set to 600 (owner read/write only)
- Default location:
~/.qarion_etl/credentials.keystore - Good for development and single-user environments
- Fernet encryption: Credentials are encrypted using the project's Fernet key
Example:
[credential_store]
type = "local_keystore"
Database Store (Recommended for Teams)
Stores credentials in a database table with optional encryption.
Configuration:
[credential_store]
type = "database"
[credential_store.config]
engine = { name = "sqlite", config = { path = "metadata.db" } }
table_name = "xt_credentials" # Optional
Features:
- Centralized credential storage
- Works with any database engine (SQLite, PostgreSQL, etc.)
- Fernet encryption: Credentials are encrypted using the project's Fernet key
- Good for team environments and production
Example:
[credential_store]
type = "database"
[credential_store.config]
engine = { name = "postgres", config = { host = "db.example.com", database = "mydb" } }
table_name = "credentials"
AWS SSM Parameter Store (Recommended for Production)
Uses AWS Systems Manager Parameter Store for secure credential storage with automatic encryption.
Configuration:
[credential_store]
type = "aws_ssm"
[credential_store.config]
parameter_prefix = "/qarion_etl/credentials/" # Optional, default: /qarion_etl/credentials/
region_name = "us-east-1"
kms_key_id = "alias/my-credentials-key" # Optional, uses default SSM key if not provided
Features:
- Automatic encryption using SecureString parameters
- Integrated with AWS IAM for access control
- Supports IAM roles and temporary credentials
- Highly secure for production environments
- No additional storage needed (SSM handles persistence)
- Optional KMS key for custom encryption
Example:
[credential_store]
type = "aws_ssm"
[credential_store.config]
parameter_prefix = "/myapp/credentials/"
region_name = "us-east-1"
kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
IAM Permissions Required:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:PutParameter",
"ssm:DeleteParameter",
"ssm:DescribeParameters",
"ssm:ListTagsForResource",
"ssm:AddTagsToResource"
],
"Resource": "arn:aws:ssm:*:*:parameter/qarion_etl/credentials/*"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:Encrypt"
],
"Resource": "arn:aws:kms:*:*:key/*"
}
]
}
Credential Definitions
Define credential metadata in your qarion-etl.toml:
[[credentials]]
id = "my_aws_creds"
name = "AWS Production Credentials"
credential_type = "aws"
description = "AWS credentials for production S3 access"
[credentials.metadata]
environment = "production"
region = "us-east-1"
Credential Types:
aws: AWS credentials (access key, secret key, region)database: Database credentials (host, user, password, database)api_key: API key credentialsoauth: OAuth credentialsbasic_auth: Basic authentication credentialscustom: Custom credential type
Using Credentials
CLI Commands
Qarion ETL provides CLI commands for managing credentials:
Store a Credential
# From JSON file
qarion-etl credentials store --credential-id aws_prod \
--name "AWS Production" \
--type aws \
--file credentials.json
# Interactive mode
qarion-etl credentials store --credential-id api_key --interactive
# From JSON string
qarion-etl credentials store --credential-id db_prod \
--json '{"host":"db.example.com","user":"admin","password":"secret"}'
List Credentials
# List all credentials
qarion-etl credentials list
# List as JSON
qarion-etl credentials list --format json
Get a Credential
# Verify credential exists
qarion-etl credentials get --credential-id aws_prod
# Show credential value
qarion-etl credentials get --credential-id aws_prod --show-value
# Show as environment variables
qarion-etl credentials get --credential-id aws_prod --show-value --format env
Delete a Credential
qarion-etl credentials delete --credential-id old_cred
Show Credential Metadata
qarion-etl credentials show --credential-id aws_prod
For complete CLI reference, see CLI Reference.
Using Credentials
Credential Reference Syntax
Reference credentials in configuration using:
${credential:credential_id}
In Flow Configuration
[properties.input_ingestion]
path = "s3://my-bucket/data/"
pattern = "*.csv"
credentials = "${credential:my_aws_creds}"
In Storage Backend Configuration
[storage]
type = "s3"
bucket = "my-bucket"
credentials = "${credential:my_aws_creds}"
In Engine Configuration
[engine]
name = "postgres"
[engine.config]
host = "db.example.com"
database = "mydb"
user = "myuser"
password = "${credential:db_password}"
In Dictionary Values
For credentials that return dictionaries, you can reference specific fields:
[engine.config]
host = "${credential:db_creds}.host"
database = "${credential:db_creds}.database"
user = "${credential:db_creds}.user"
password = "${credential:db_creds}.password"
Storing Credentials
Using Python API
from qarion_etl.credentials import get_credential_store, CredentialDefinition, CredentialType
# Get credential store
store = get_credential_store()
# Store AWS credentials
store.store_credential(
credential_id="my_aws_creds",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "...",
"region_name": "us-east-1"
},
credential_definition=CredentialDefinition(
id="my_aws_creds",
name="AWS Production Credentials",
credential_type=CredentialType.AWS,
description="AWS credentials for production"
)
)
# Store database credentials
store.store_credential(
credential_id="db_prod",
credential_data={
"host": "db.example.com",
"database": "mydb",
"user": "myuser",
"password": "secretpassword"
}
)
Retrieving Credentials
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
# Get credential
aws_creds = store.get_credential("my_aws_creds")
print(aws_creds)
# {
# "aws_access_key_id": "AKIA...",
# "aws_secret_access_key": "...",
# "region_name": "us-east-1"
# }
# List all credentials
credential_ids = store.list_credentials()
print(credential_ids)
# ["my_aws_creds", "db_prod"]
# Check if credential exists
exists = store.credential_exists("my_aws_creds")
print(exists)
# True
Deleting Credentials
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
store.delete_credential("my_aws_creds")
Complete Examples
Example 1: Local Keystore with AWS Credentials
Configuration (qarion-etl.toml):
[credential_store]
type = "local_keystore"
[[credentials]]
id = "aws_prod"
name = "AWS Production"
credential_type = "aws"
Store credentials:
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
store.store_credential(
credential_id="aws_prod",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "...",
"region_name": "us-east-1"
}
)
Use in flow:
[properties.input_ingestion]
path = "s3://my-bucket/data/"
credentials = "${credential:aws_prod}"
Example 2: Database Store with Multiple Credentials
Configuration:
[credential_store]
type = "database"
[credential_store.config]
engine = { name = "sqlite", config = { path = "metadata.db" } }
[[credentials]]
id = "aws_prod"
name = "AWS Production"
credential_type = "aws"
[[credentials]]
id = "db_prod"
name = "Database Production"
credential_type = "database"
Store credentials:
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
# Store AWS credentials
store.store_credential(
credential_id="aws_prod",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "..."
}
)
# Store database credentials
store.store_credential(
credential_id="db_prod",
credential_data={
"host": "db.example.com",
"database": "mydb",
"user": "myuser",
"password": "secretpassword"
}
)
Use in configurations:
[engine]
name = "postgres"
[engine.config]
host = "${credential:db_prod}.host"
database = "${credential:db_prod}.database"
user = "${credential:db_prod}.user"
password = "${credential:db_prod}.password"
Example 3: AWS SSM Parameter Store
Configuration:
[credential_store]
type = "aws_ssm"
[credential_store.config]
parameter_prefix = "/qarion_etl/credentials/"
region_name = "us-east-1"
kms_key_id = "alias/my-credentials-key" # Optional
Store credentials:
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
store.store_credential(
credential_id="aws_prod",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "..."
}
)
Migration from Inline Credentials
Before (Inline Credentials)
[properties.input_ingestion]
path = "s3://my-bucket/data/"
credentials = {
aws_access_key_id = "AKIA..."
aws_secret_access_key = "..."
region_name = "us-east-1"
}
After (Credential Store)
1. Configure credential store:
[credential_store]
type = "local_keystore"
2. Store credential:
from qarion_etl.credentials import get_credential_store
store = get_credential_store()
store.store_credential(
credential_id="aws_prod",
credential_data={
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "...",
"region_name": "us-east-1"
}
)
3. Update configuration:
[properties.input_ingestion]
path = "s3://my-bucket/data/"
credentials = "${credential:aws_prod}"
Fernet Key Management
Automatic Generation
A Fernet key is automatically generated when you:
- Run
qarion-etl new-projectto create a new project - Run
qarion-etl initto initialize a project
The key is stored in your qarion-etl.toml file:
fernet_key = "gAAAAABh..." # Automatically generated
Key Security
Critical Security Notes:
- Never commit
qarion-etl.tomlto version control if it contains a Fernet key - Backup your Fernet key - losing it means you cannot decrypt stored credentials
- Use different keys for different environments (dev, staging, production)
- Rotate keys periodically - generate a new key and re-encrypt credentials
Manual Key Generation
If you need to generate a new Fernet key:
from qarion_etl.credentials.encryption import generate_fernet_key
new_key = generate_fernet_key()
print(new_key)
# gAAAAABh...
Then update your qarion-etl.toml:
fernet_key = "gAAAAABh..." # Your new key
Warning: Changing the Fernet key will make existing encrypted credentials unreadable. You'll need to re-store all credentials with the new key.
Security Best Practices
-
Never commit credentials to version control
- Use credential stores for all sensitive data
- Never commit
qarion-etl.tomlwith Fernet key - add to.gitignore:# Qarion ETL configuration with sensitive Fernet key
qarion-etl.toml - Use environment variables as fallback only
- Add credential store files to
.gitignore:# Credential store files
~/.qarion_etl/credentials.keystore
*.keystore
-
Choose the right credential store
- Development: Local keystore
- Teams: Database store
- Production: AWS SSM Parameter Store or database with encryption
-
Rotate credentials regularly
- Update credentials in the credential store
- Old references will automatically use new credentials
- No need to update configuration files
-
Limit access to credential stores
- Use IAM roles for AWS SSM Parameter Store
- Restrict file permissions for local keystore (automatically set to 600)
- Use database access controls for database store
-
Use credential definitions
- Document what each credential is for
- Use descriptive names and descriptions
- Include metadata for tracking and auditing
-
Environment separation
- Use different credential stores for dev/staging/prod
- Use different credential IDs for different environments
- Never share credentials between environments
Troubleshooting
Credential Not Found
Error: Credential 'my_creds' not found in credential store
Solution:
- Verify credential store is configured in
qarion-etl.toml - Check that credential was stored:
store.credential_exists("my_creds") - List all credentials:
store.list_credentials()
Credential Store Not Configured
Error: Credential references are not resolved
Solution:
- Add
[credential_store]section toqarion-etl.toml - Ensure credential store type is supported
- Verify credential store configuration is valid
Permission Errors (Local Keystore)
Error: Permission denied when accessing keystore
Solution:
- Check file permissions:
ls -l ~/.qarion_etl/credentials.keystore - Ensure you own the file:
chown user:user ~/.qarion_etl/credentials.keystore - Set correct permissions:
chmod 600 ~/.qarion_etl/credentials.keystore
Related Documentation
- Configuration Guide - General configuration
- Engines and Storage - Storage configuration
- Credential Store Architecture - Complete technical documentation