, ,

Beyond the Cone of Shame: Taming the Password Beast with 1Password (Yes, Even for Netflix!)

Drowning in passwords for home (Netflix!) and work? Avoid the ‘Cone of Shame’ with a password manager. I explain why 1Password is essential digital hygiene, how its family features bring peace of mind, and how the same tool streamlines my secure DevSecOps setup using the CLI.

Remember that sinking feeling, the digital equivalent of wearing the ‘Cone of Shame’, when a security oversight bites you? We talked about securing application delivery pipelines back then, but let’s be honest, the foundational cracks often start much closer to home – with our sprawling, chaotic mess of personal passwords.

In today’s hyper-connected world, juggling credentials for banking, streaming, shopping, work tools, cloud accounts, and yes, even that online forum you signed up for in 2008, is a recipe for disaster or at least a migraine. Weak passwords? Reused passwords? Passwords scribbled on sticky notes that double as cat toys? We’ve all been tempted, but it’s time we acknowledged a fundamental truth: Password managers are no longer a nice-to-have; they’re essential digital hygiene, especially at home.

Why especially at home? Because that’s where the lines blur. It’s where your personal banking lives alongside your Netflix account, and where securing your digital life protects your family’s too.

Enter the Password Manager: My Weapon of Choice – 1Password

After trying various solutions, I landed on 1Password, and it’s become indispensable. Why?

  1. The Family Plan: This is brilliant. Sharing access to Netflix, Disney+, Amazon Prime – the important stuff! – without compromising security is a game-changer. No more texting passwords (please, never do that).
  2. Sharing Securely: It goes beyond streaming. As an “old person” (their words, possibly mine too), I can securely share critical details like pension access with my partner. It’s peace of mind, stored securely.
  3. MFA Everywhere: This is non-negotiable. We have Multi-Factor Authentication enabled on everyone’s devices. 1Password integrates smoothly, often storing the OTP (One-Time Password) secrets, making MFA less painful.
  4. Cross-Platform & Integration: This is where it bridges the gap between personal sanity and professional efficiency. Its seamless integration with macOS, Linux, and Windows is crucial for someone like me working in the IT/Cloud sector.

From Family Vaults to CI/CD Pipelines: A DevSecOps Perspective

My digital life, both personal and professional, revolves around secure access. I use 1Password vaults to meticulously segment credentials:

  • Family Vault: Shared logins (streaming, utilities, etc.).
  • Personal Vault: My individual accounts (banking, email, personal projects).
  • Work Vault(s): Client-specific credentials, work tool logins, API keys, cloud account IDs, secrets, sometimes even environment variables needed for specific projects.

Here’s a simplified look at how 1Password sits at the centre of my workflow:

As someone deep in the DevSecOps space, automation via the command line is my bread and butter. My shell of choice these days is the default macOS .zsh. Gone are the days of meticulously crafting bespoke shell environments; they’re now ephemeral, adaptable tools. I need to meet clients where they are, so keeping my local setup relatively standard is key.

Naturally, tools like Git (with SSH keys for GitHub) and HashiCorp’s Terraform (now under IBM’s wing) for Infrastructure as Code are staples. The real magic, however, happens with the 1Password CLI (op).

By installing the op CLI and configuring it in my .zshrc profile, I achieve near-instantaneous, secure bootstrapping for my development tasks. Here’s how:

  1. SSH Key Management: The op CLI integrates with the SSH agent. My private keys live securely in 1Password. When I open a terminal, my .zshrc configures the SSH agent to talk to 1Password. A quick fingerprint authentication, and my SSH keys are loaded securely into the agent, ready for Git operations, without the private key file ever sitting exposed on disk.
  2. Cloud Authentication (AWS Example): Forget scattering AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in config files or environment variables directly. While op can inject static keys (as shown commented out in the example below), a more robust approach for AWS is often using aws sso login (which op can sometimes help automate or work alongside) or dedicated op integrations for dynamic credential fetching. My profile ensures the necessary setup happens on shell startup.
  3. Secret Injection: Need API tokens for Terraform providers, database passwords, or other secrets? op fetches them directly from the relevant vault item and injects them as environment variables.

With the latest Macs, it’s literally a fingerprint tap when the terminal first asks, and my environment is securely configured and ready to build.

My .zshrc Example: Streamlined and Secure(d)

Here’s a cleaned-up and commented version of the relevant parts of my .zshrc, demonstrating how op bootstraps my environment (PII masked):

#!/bin/zsh

# === 1Password Secret Injection ===
# Ensure op CLI is available and configured before running these

# --- Terraform AWS Variables ---
# Fetch AWS Account ID from 1Password item and export as Terraform variable
eval $(op item get "<1P_ITEM_UUID_AWS_DETAILS>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="aws account id") | "export TF_VAR_aws_account_id=\(.value)"')

# Fetch AWS Key Name (for EC2 instances) from 1Password item and export as Terraform variable
eval $(op item get "<1P_ITEM_UUID_SSH_KEY>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="AWS Key Name") | "export TF_VAR_key_name=\(.value)"')

# --- Terraform Proxmox Variables (Example - replace if not used) ---
# Fetch Proxmox API Token ID from 1Password item and export
eval $(op item get "<1P_ITEM_UUID_PROXMOX_API>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="tokenid") | "export PM_API_TOKEN_ID=\(.value)"')
# Fetch Proxmox API Token Secret from 1Password item and export
eval $(op item get "<1P_ITEM_UUID_PROXMOX_API>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="secret") | "export PM_API_TOKEN_SECRET=\(.value)"')

# --- Terraform SSH Key Injection ---
# Fetch SSH Public Key content from 1Password item and export as Terraform variable
export TF_VAR_ssh_public_key="$(op item get "<1P_ITEM_UUID_SSH_KEY>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="public key") | .value')"
# Fetch SSH Private Key content from 1Password item and export as Terraform variable
# Use with caution: exposing private key content directly to env vars can be risky.
# Prefer using the SSH Agent integration where possible.
# export TF_VAR_ssh_private_key="$(op item get "<1P_ITEM_UUID_SSH_KEY>" --vault "<VAULT_NAME>" --format json | jq -r '.fields[] | select(.label=="private key") | .value')"

# === Shell & Tool Configuration ===

# --- Terraform ---
# Enable Terraform detailed logging to a file
export TF_LOG="INFO"
export TF_LOG_PATH="terraform.log"
# Set default Terraform variable for AWS Region
export TF_VAR_aws_region="eu-west-1"
# Set default Terraform variable for Domain Name (replace with your actual domain or fetch from 1P)
export TF_VAR_domain_name="<YOUR_DOMAIN.COM>"
# Set default Terraform variable for Admin IP (replace or fetch from 1P)
# Consider using a dynamic DNS name or fetching dynamically if your IP changes
export TF_VAR_admin_ip="<YOUR_ADMIN_IP>"

# --- AWS ---
# Set default AWS region for AWS CLI/SDKs
export AWS_REGION="eu-west-1"
export AWS_DEFAULT_REGION="eu-west-1"
# Define default AWS profile to use (ensure this profile is configured in ~/.aws/config)
export AWS_PROFILE="<YOUR_AWS_PROFILE_NAME>" # e.g., betty

# --- 1Password SSH Agent Integration ---
# Point SSH to the 1Password agent socket
export SSH_AUTH_SOCK=~/Library/Group\ Containers/HAPPYS2C.com.1password/t/agent.sock

# --- Terraform Auto-completion (Optional - Requires bashcompinit) ---
# Load bash completion support
autoload -U +X bashcompinit && bashcompinit
# Register Terraform completion function (ensure terraform path is correct)
# complete -o nospace -C /path/to/terraform terraform # Adjust path if necessary

# --- AWS SSO Login ---
# Attempt AWS SSO login non-interactively on shell start.
# This helps refresh temporary credentials if using AWS SSO profiles.
# May require interaction if session is expired. Output is suppressed.
aws sso login --profile ${AWS_PROFILE} > /dev/null 2>&1 || echo "AWS SSO Login for profile ${AWS_PROFILE} might require interaction."

# --- Dynamic AWS Info for Terraform Tags ---
# Fetch current AWS identity information after potential SSO login
# Use default profile or the one set in AWS_PROFILE
TF_AWS_UserId_raw=$(aws sts get-caller-identity --query UserId --output text --profile ${AWS_PROFILE})
TF_AWS_Account_raw=$(aws sts get-caller-identity --query Account --output text --profile ${AWS_PROFILE})
TF_AWS_Arn_raw=$(aws sts get-caller-identity --query Arn --output text --profile ${AWS_PROFILE})

# Check if AWS commands were successful before processing
if [ $? -eq 0 ]; then
    # Extract relevant parts securely
    export TF_AWS_UserId=$(echo "$TF_AWS_UserId_raw" | sed 's|.*:||') # Get part after last ':' if applicable, or full ID
    export TF_AWS_Account="$TF_AWS_Account_raw"
    export TF_AWS_Email=$(echo "$TF_AWS_Arn_raw" | sed 's|.*\/||') # Get assumed role user or base user

    # Export default tags as a JSON string for Terraform, using fetched AWS info
    export TF_VAR_default_tags_static=$(cat <<EOF
{
  "owner": "${TF_AWS_UserId}",
  "account": "${TF_AWS_Account}",
  "email": "${TF_AWS_Email}",
  "purpose": "demo environment"
}
EOF
)
else
    echo "Warning: Failed to retrieve AWS caller identity. Default tags might be incomplete."
fi


# === Custom Aliases ===
# Shorten common commands

# AWS
alias salt="aws sso login --profile ${AWS_PROFILE}" # Re-login easily

# Zsh
alias sz="source ~/.zshrc" # Reload shell config

# Terraform
alias tf="terraform"

# Kubectl (if used)
alias kc="kubectl"

# =====================

echo "Shell environment bootstrapped using 1Password secrets and AWS profile: ${AWS_PROFILE}"

Disclaimer: Directly exporting sensitive material like private keys into environment variables (TF_VAR_ssh_private_key) should be done with extreme caution. Using the SSH agent integration (SSH_AUTH_SOCK) is generally the more secure practice for handling SSH keys.

Solving the “Secret Zero” Problem

This entire setup effectively tackles the “Secret Zero” problem – how do you securely provide the initial secret (in this case, my 1Password master password/fingerprint) that unlocks all other secrets needed to bootstrap an environment or pipeline? 1Password, authenticated via biometrics or a strong master password, becomes that secure entry point.

But What About Production?

While 1Password is fantastic for personal use, development environments, and small teams, large-scale production environments often demand more advanced capabilities. This is where enterprise-grade solutions like HashiCorp Vault shine. Vault offers features like dynamic secret generation (creating database passwords or cloud credentials that exist only for a short time), advanced auditing, fine-grained access control policies, and secrets caching, which are crucial for robust, secure, and compliant production deployments.

Think of 1Password as the secure foundation for your personal and development life, and Vault as the hardened fortress for your production infrastructure.

The Final Frontier: Family Adoption

So, I’ve streamlined my workflow and secured my digital keys to the kingdom, both at home and work. The system works beautifully… for me. Now, the real challenge begins: convincing the rest of the family to fully embrace the password manager lifestyle. Wish me luck – I might need it more than trying to debug Terraform state drift!

Leave a comment