Balis 情報マガジン

credentialsymlenc

📅 October 29, 2026📖 Verified Publication
Credentials.yml.enc in Chef Infra: Complete Guide to Encrypted Data Bags & Key Management

Credentials.yml.enc in Chef Infra: The Definitive Guide to Encrypted Data Bags and Secure Configuration Management

Key Takeaways

  • credentials.yml.enc is a Chef Infra encrypted data bag item file that stores sensitive values such as passwords, API keys, and tokens using AES-256 encryption.
  • It is paired with a validation key (credentials.key) or a dedicated encryption key stored securely—never commit keys to version control.
  • Encrypted data bags outperform plain-text secrets in attributes files because they support server-side decryption at compile time and work with knife and Chef Infra Client seamlessly.
  • Common pitfalls include key rotation failures, missing encrypted format declaration, and attempting to decrypt without the correct key on the node.
  • For large-scale environments, consider supplementing encrypted data bags with external secret managers (HashiCorp Vault, AWS Secrets Manager) via custom resources or InSpec-driven delivery.

What Is credentials.yml.enc?

Definition and Role in the Chef Ecosystem

In Chef Infra, credentials.yml.enc is the physical representation of an encrypted data bag item. A data bag is a global JSON variable stored on the Chef server; when a bag item is marked as encrypted, Chef encrypts its fields with AES-256 before persisting them. The resulting .enc file contains the ciphertext and an initialization vector—but never the plaintext secret.

The companion file, typically named credentials.key, holds the symmetric encryption key. Chef Infra Client uses this key at convergence time to decrypt the bag item and make the secrets available to recipes as a Ruby hash. Without the key present on the node or the ability to fetch it from a secure location, any recipe that reads the bag will raise a Chef::Exceptions::EncryptedDataBagItemNotFound or decryption error.

File Structure Breakdown

A typical credentials.yml.enc (or more accurately, a JSON-encoded .enc blob) stores data in this shape:

{
  "id": "database",
  "encrypted_data": "BASE64_AES256_CIPHERTEXT",
  "iv": "BASE64_INITIALIZATION_VECTOR",
  "encrypted": true,
  "version": "1.2.0"
}

Note that although the filename may carry a .yml extension in some tooling wrappers, the Chef server stores and transmits encrypted data bags as JSON. The .enc suffix indicates that the payload has been processed through the encryption routine, not that the format is YAML.

How Encryption Works Under the Hood

AES-256-CBC with PKCS7 Padding

Chef Infra uses the openssl library in Ruby to perform AES-256-CBC encryption. The process is:

  1. A 256-bit symmetric key is derived from the contents of credentials.key.
  2. A random 128-bit initialization vector (IV) is generated per encryption operation.
  3. The plaintext JSON data bag item is padded with PKCS7 to align to the 16-byte AES block size.
  4. The cipher text, IV, and metadata are serialized into a single JSON blob and base64-encoded for transport.

Compile-Time vs. Converge-Time Decryption

One of the most powerful aspects of encrypted data bags is that decryption happens on the node during the converge phase, not on the Chef server. This means:

  • The Chef server never sees plaintext secrets during a normal run.
  • Keys must be distributed to nodes through a secure channel (Puppet-style key distribution, environment variables, or a secret management integration).
  • Lazy evaluation (lazy { node['credentials']['password'] }) is often required in attribute files to defer decryption until converge time.

Credentials.yml.enc vs. Alternative Secret Management Approaches

Understanding where encrypted data bags fit in the broader IaC and configuration management landscape helps teams make informed architectural decisions. The table below compares the most common approaches.

Comparison of Secret Storage Mechanisms in Infrastructure-as-Code Workflows
Approach Encryption Standard Key Rotation Support Server-Side Storage External Dependency Best For
credentials.yml.enc (Chef) AES-256-CBC Manual re-encryption required Chef Server None (built-in) Mid-size Chef environments; teams already invested in the Chef ecosystem
Chef Vault AES-256-GCM Built-in vault item migration Chef Server + local vault files chef-vault gem Environments requiring per-node or per-group secret scoping
HashiCorp Vault AES-256-GCM (transit), KMS-backed Native lease-based rotation Vault cluster (external) Vault Agent sidecar or API calls Multi-cloud, multi-tool platforms needing a centralized secrets plane
AWS Secrets Manager AES-256 (KMS-managed) Automatic or scheduled rotation AWS managed service AWS SDK / IAM roles AWS-native deployments with existing KMS infrastructure
Environment Variables None (OS-level protection only) Restart or reload required Node process space None Development environments; trivial test fixtures
Ansible Vault AES-256 Re-encrypt manually or via script Control node / Git (encrypted blobs) ansible-vault CLI Ansible-centric shops managing encrypted playbooks or inventories

Step-by-Step: Creating and Using credentials.yml.enc

Step 1 — Generate or Obtain the Encryption Key

# Generate a 256-bit random key and base64-encode it
openssl rand -base64 32 > credentials.key

# Secure the key file
chmod 600 credentials.key

Step 2 — Create the Encrypted Data Bag Item

knife data bag create database_bags database \
  --secret-file credentials.key \
  --format json

Alternatively, use the interactive mode:

knife data bag create database_bags database --secret-file credentials.key

Knife will prompt you for each field and write the encrypted JSON to the Chef server.

Step 3 — Reference the Bag in a Recipe

db_creds = data_bag_item('database_bags', 'database')

template '/etc/app/database.yml' do
  source 'database.yml.erb'
  variables(
    username: db_creds['username'],
    password: db_creds['password']
  )
  sensitive true
end

Step 4 — Distribute the Key to Nodes

Nodes must have access to the same credentials.key to decrypt bag