HashiCorp Vault — Authentication Exercises

4 minute read

Practice authentication methods with these hands-on exercises.


Exercise 1 — Token Lifecycle

Task: Create and manage tokens with different properties.

  1. Create a service token with policy default, TTL 1h, max TTL 4h
  2. Look up the token’s properties
  3. Renew the token with a 2h increment
  4. Create a batch token with policy default and TTL 30m
  5. Try to renew the batch token — what happens?
  6. Create an orphan token and verify it has no parent
Show Answer
# 1. Create service token
vault token create -policy=default -ttl=1h -max-ttl=4h
# Save the token value

# 2. Look up
vault token lookup hvs.CAESI...
# Shows: ttl, max_ttl, policies, type=service

# 3. Renew
vault token renew -increment=2h hvs.CAESI...
# TTL extended (up to max_ttl)

# 4. Create batch token
vault token create -policy=default -ttl=30m -type=batch
# Token starts with "hvb."

# 5. Try to renew batch token
vault token renew hvb.AAAA...
# Error: batch tokens cannot be renewed

# 6. Create orphan token
vault token create -orphan -policy=default -ttl=1h
vault token lookup hvs.orphan...
# orphan: true, no parent reference

Exercise 2 — Userpass Setup

Task: Set up userpass authentication with multiple users and policies.

  1. Enable userpass auth
  2. Create a policy read-only that allows reading secret/data/*
  3. Create a policy read-write that allows full CRUD on secret/data/*
  4. Create user viewer with read-only policy
  5. Create user editor with read-write policy
  6. Login as viewer and try to write a secret — verify it fails
  7. Login as editor and write a secret — verify it succeeds
Show Answer
# Enable userpass
vault auth enable userpass

# Create read-only policy
vault policy write read-only - <<EOF
path "secret/data/*" {
  capabilities = ["read", "list"]
}
path "secret/metadata/*" {
  capabilities = ["list", "read"]
}
EOF

# Create read-write policy
vault policy write read-write - <<EOF
path "secret/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/metadata/*" {
  capabilities = ["list", "read", "delete"]
}
EOF

# Create users
vault write auth/userpass/users/viewer password="viewer-pass" policies="read-only"
vault write auth/userpass/users/editor password="editor-pass" policies="read-write"

# Login as viewer
vault login -method=userpass username=viewer password="viewer-pass"

# Try to write (should fail)
vault kv put secret/test key=value
# Error: permission denied

# Login as editor
vault login -method=userpass username=editor password="editor-pass"

# Write (should succeed)
vault kv put secret/test key=value
# Success!

Exercise 3 — AppRole for CI/CD

Task: Set up an AppRole for a CI/CD pipeline.

  1. Create a policy that allows reading secret/data/ci/*
  2. Enable AppRole auth
  3. Create a role named ci-runner with the policy, 1h TTL, single-use secret_id
  4. Get the role_id
  5. Generate a secret_id
  6. Authenticate using role_id + secret_id
  7. Use the resulting token to read a secret
  8. Try to use the same secret_id again — what happens?
Show Answer
# Create policy
vault policy write ci-read - <<EOF
path "secret/data/ci/*" {
  capabilities = ["read", "list"]
}
EOF

# Enable AppRole
vault auth enable approle

# Create role
vault write auth/approle/role/ci-runner \
    token_policies="ci-read" \
    token_ttl=1h \
    secret_id_ttl=5m \
    secret_id_num_uses=1

# Get role_id
ROLE_ID=$(vault read -field=role_id auth/approle/role/ci-runner/role-id)
echo "Role ID: $ROLE_ID"

# Generate secret_id
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/ci-runner/secret-id)
echo "Secret ID: $SECRET_ID"

# Login
TOKEN=$(vault write -field=token auth/approle/login \
    role_id="$ROLE_ID" \
    secret_id="$SECRET_ID")
echo "Token: $TOKEN"

# Write a secret first (as admin)
vault kv put secret/ci/config deploy_key="abc123"

# Use the AppRole token
VAULT_TOKEN=$TOKEN vault kv get secret/ci/config

# Try same secret_id again
vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"
# Error: invalid secret id (already used — num_uses=1)

Exercise 4 — Token Hierarchy

Task: Demonstrate parent-child token behavior.

  1. Create a parent token with TTL 2h
  2. Login with the parent token
  3. Create two child tokens
  4. Revoke the parent token
  5. Check if child tokens still work
Show Answer
# Create parent token
PARENT=$(vault token create -policy=default -ttl=2h -field=token)

# Login with parent
vault login $PARENT

# Create child tokens
CHILD1=$(vault token create -policy=default -ttl=1h -field=token)
CHILD2=$(vault token create -policy=default -ttl=1h -field=token)

# Verify children work
VAULT_TOKEN=$CHILD1 vault token lookup
VAULT_TOKEN=$CHILD2 vault token lookup

# Re-login as root/admin
vault login my-root-token

# Revoke parent
vault token revoke $PARENT

# Check children — they're revoked too!
VAULT_TOKEN=$CHILD1 vault token lookup
# Error: bad token
VAULT_TOKEN=$CHILD2 vault token lookup
# Error: bad token

# This is the parent-child hierarchy in action
# To avoid this, use -orphan flag

Exercise 5 — Auth Method Comparison

Question: For each scenario, which auth method would you use?

  1. A Jenkins pipeline that deploys to production
  2. An SRE team that uses Okta for SSO
  3. A Kubernetes microservice that needs database credentials
  4. A developer testing locally on their laptop
  5. An AWS Lambda function that needs to read secrets
  6. A legacy application that can only use static credentials
Show Answer

| Scenario | Auth Method | Reasoning | |———-|————-|———–| | Jenkins pipeline | AppRole | Machine auth with role_id baked in, secret_id generated per build | | SRE team with Okta | OIDC | Browser-based SSO, maps Okta groups to Vault policies | | K8s microservice | Kubernetes | Uses service account JWT, no secrets to distribute | | Developer testing | Userpass or Token | Simple, local development, short-lived tokens | | AWS Lambda | AWS (IAM) | Uses Lambda’s execution role, no credentials to manage | | Legacy app with static creds | Token with long TTL, or AppRole with periodic token | If the app truly can’t be modified, a periodic service token is the last resort. Better: refactor to use AppRole. |


What’s Next?

You’ve mastered Vault authentication. Next, we’ll control what authenticated users can access using policies.

Next Chapter: Policies & ACLs