Table of Contents

Vault

Vault is a service to securely store secrets such as passwords or certificates.

Installation

  1. Download and unzip the vault binary from their website:
    $ wget https://releases.hashicorp.com/vault/1.1.0/vault_1.1.0_linux_amd64.zip
    $ unzip vault_1.1.0_linux_amd64.zip
  2. make vault executable and copy it to /usr/local/bin
    $ chmod +x vault
    $ sudo cp vault /usr/local/bin/
  3. For security reasons vault data should not be swapped to disk. In order to prevent this vault needs to be able to execute the mlock systemcall. Enable it like this:
    $ sudo setcap cap_ipc_lock=+ep /usr/local/bin/vault
  4. Create a new user for vault:
    $ sudo useradd --system --home /etc/vault.d --shell /bin/false vault
  5. Create a systemd service file (/etc/systemd/system/vault.service) for vault with the following content:
    [Unit]
    Description="HashiCorp Vault - A tool for managing secrets"
    Documentation=https://www.vaultproject.io/docs/
    Requires=network-online.target
    After=network-online.target
    ConditionFileNotEmpty=/etc/vault.d/vault.hcl
    
    [Service]
    User=vault
    Group=vault
    ProtectSystem=full
    ProtectHome=read-only
    PrivateTmp=yes
    PrivateDevices=yes
    SecureBits=keep-caps
    AmbientCapabilities=CAP_IPC_LOCK
    Capabilities=CAP_IPC_LOCK+ep
    CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK
    NoNewPrivileges=yes
    ExecStart=/usr/local/bin/vault server -config=/etc/vault.d/vault.hcl
    ExecReload=/bin/kill --signal HUP $MAINPID
    KillMode=process
    KillSignal=SIGINT
    Restart=on-failure
    RestartSec=5
    TimeoutStopSec=30
    StartLimitIntervalSec=60
    StartLimitBurst=3
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
  6. create the directories /etc/vault.d and /opt/vault and hand ownership over to vault.
    $ sudo mkdir /etc/vault.d
    $ sudo mkdir /opt/vault
    $ sudo chown vault:vault /etc/vault.d
    $ sudo chown vault:vault /etc/vault
  7. create the file /etc/vault.d/vault.hcl with the following content:
    listener "tcp" {
            address         = "<server ip>:8200"
            tls_cert_file   = "path/to/fullchain.pem"
            tls_key_file    = "path/to/privkey.key"
    }
    
    storage "file" {
            path = "/opt/vault"
    }
    
    ui = true
  8. Make sure to hand ownership over to vault
    $ sudo chown vault:vault /etc/vault.d/vault.hcl
  9. Vault can now be started up.
    $ sudo systemctl enable vault
    $ sudo systemctl start vault
  10. Vaults web-ui should now be accessible at https://<server ip>:8200

Unsealing Vault

When you first visit the Web UI you will be prompted to generate unseal keys. You can Specify how many keys should be generated and how many are necesarry to unseal vault. A root token will also be generated.

After generating the keys provide as many as necessary to unseal vault and log in using the root token to start configuring vault.

Configuring Vault

LDAP Login

  1. Enable ldap authentication under access→Auth Methods→enable new method
  2. Confugre LDAP login
    URL: ldaps://ldap.in.tum.de:636
    LDAP Options -
        Discover DN: yes
        User Attribute: uid
    Customize User Search:
        User DN: ou=Personen,ou=IN,o=TUM,c=DE
    Customize Group Membership Search:
        Group Filter: (&(objectClass=posixGroup)(memberUid={{.Username}}))
        Group Attribute: cn
        Group DN: ou=Gruppen,ou=IN,o=TUM,c=DE
  3. another way is to use the commandline by clicking on the symbol in the top right and execute the following code (you may need to type it all in one line):
    write auth/ldap/config \
    	groupdn=ou=Gruppen,ou=IN,o=TUM,c=DE \
    	url=ldaps://ldap.in.tum.de:636 \
    	discoverdn=true \
    	userdn=ou=Personen,ou=IN,o=TUM,c=DE \
    	userattr=uid \
    	groupattr=cn \
    	groupfilter=(&(objectClass=posixGroup)(memberUid={{.Username}}))
  4. Create a new external group under Access → Groups → create group (Name: admin, Type: external)
  5. In the newly created group click on the Aliases tab → Add Alias and use the ldap group name (il11admin) as name and ldap/(ldap) as auth backend
  6. You can now create a new Policy under Policies → create ACL policy (Name: admin) and associate it with your group

    admin - policy

    # Allow tokens to look up their own properties
    path "auth/token/lookup-self" {
        capabilities = ["read"]
    }
    
    # Allow tokens to renew themselves
    path "auth/token/renew-self" {
        capabilities = ["update"]
    }
    
    # Allow tokens to revoke themselves
    path "auth/token/revoke-self" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up its own capabilities on a path
    path "sys/capabilities-self" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up its own entity by id or name
    path "identity/entity/id/{{identity.entity.id}}" {
      capabilities = ["read"]
    }
    path "identity/entity/name/{{identity.entity.name}}" {
      capabilities = ["read"]
    }
    
    
    # Allow a token to look up its resultant ACL from all policies. This is useful
    # for UIs. It is an internal path because the format may change at any time
    # based on how the internal ACL features and capabilities change.
    path "sys/internal/ui/resultant-acl" {
        capabilities = ["read"]
    }
    
    # Allow a token to renew a lease via lease_id in the request body; old path for
    # old clients, new path for newer
    path "sys/renew" {
        capabilities = ["update"]
    }
    path "sys/leases/renew" {
        capabilities = ["update"]
    }
    
    # Allow looking up lease properties. This requires knowing the lease ID ahead
    # of time and does not divulge any sensitive information.
    path "sys/leases/lookup" {
        capabilities = ["update"]
    }
    
    # Allow a token to manage its own cubbyhole
    path "cubbyhole/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    path "kv/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    path "transit/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    path "files/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
    }
    path "sys/seal" {
            capabilities = ["create", "read", "update", "delete", "list", "sudo"]
    }
    # Allow a token to wrap arbitrary values in a response-wrapping token
    path "sys/wrapping/wrap" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up the creation time and TTL of a given
    # response-wrapping token
    path "sys/wrapping/lookup" {
        capabilities = ["update"]
    }
    
    # Allow a token to unwrap a response-wrapping token. This is a convenience to
    # avoid client token swapping since this is also part of the response wrapping
    # policy.
    path "sys/wrapping/unwrap" {
        capabilities = ["update"]
    }
    
    # Allow general purpose tools
    path "sys/tools/hash" {
        capabilities = ["update"]
    }
    path "sys/tools/hash/*" {
        capabilities = ["update"]
    }
    path "sys/tools/random" {
        capabilities = ["update"]
    }
    path "sys/tools/random/*" {
        capabilities = ["update"]
    }
    
    # Allow checking the status of a Control Group request if the user has the
    # accessor
    path "sys/control-group/request" {
        capabilities = ["update"]
    }
  7. Associate the policy with the group by clicking on the group Access → Groups → <group> → Edit group. Select Policies and choose the new policy.

Secret Engine

  1. Create a new secret engine to store passwords and secrets Secrets → Enable new engine → Generic: KV (Path: kv, Version: 2)
  2. Secrets stored in the KV (key-value store) under the path kv/services/ can be accessed by the awx approle

AWX Access - Approle Auth

  1. Enable a new auth method to enable Approle authentication Access → Auth Methods → Enable new method → Approle (Path: approle)
  2. Create a new policy to read and write values in the kv/services path ''Policies → Create ACL policy

    approle - policy

    # Allow tokens to look up their own properties
    path "auth/token/lookup-self" {
        capabilities = ["read"]
    }
    
    # Allow tokens to renew themselves
    path "auth/token/renew-self" {
        capabilities = ["update"]
    }
    
    # Allow tokens to revoke themselves
    path "auth/token/revoke-self" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up its own capabilities on a path
    path "sys/capabilities-self" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up its own entity by id or name
    path "identity/entity/id/{{identity.entity.id}}" {
      capabilities = ["read"]
    }
    path "identity/entity/name/{{identity.entity.name}}" {
      capabilities = ["read"]
    }
    
    
    # Allow a token to look up its resultant ACL from all policies. This is useful
    # for UIs. It is an internal path because the format may change at any time
    # based on how the internal ACL features and capabilities change.
    path "sys/internal/ui/resultant-acl" {
        capabilities = ["read"]
    }
    
    # Allow a token to renew a lease via lease_id in the request body; old path for
    # old clients, new path for newer
    path "sys/renew" {
        capabilities = ["update"]
    }
    path "sys/leases/renew" {
        capabilities = ["update"]
    }
    
    # Allow looking up lease properties. This requires knowing the lease ID ahead
    # of time and does not divulge any sensitive information.
    path "sys/leases/lookup" {
        capabilities = ["update"]
    }
    
    # Allow a token to manage its own cubbyhole
    path "cubbyhole/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    # Allow ansible token to access service secrets
    path "kv/data/services/*" {
      	capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    # Allow ansible token to access files
    path "files/*" {
      	capabilities = ["create", "read", "update", "delete", "list"]
    }
    
    # Allow a token to wrap arbitrary values in a response-wrapping token
    path "sys/wrapping/wrap" {
        capabilities = ["update"]
    }
    
    # Allow a token to look up the creation time and TTL of a given
    # response-wrapping token
    path "sys/wrapping/lookup" {
        capabilities = ["update"]
    }
    
    # Allow a token to unwrap a response-wrapping token. This is a convenience to
    # avoid client token swapping since this is also part of the response wrapping
    # policy.
    path "sys/wrapping/unwrap" {
        capabilities = ["update"]
    }
    
    # Allow general purpose tools
    path "sys/tools/hash" {
        capabilities = ["update"]
    }
    path "sys/tools/hash/*" {
        capabilities = ["update"]
    }
    path "sys/tools/random" {
        capabilities = ["update"]
    }
    path "sys/tools/random/*" {
        capabilities = ["update"]
    }
    
    # Allow checking the status of a Control Group request if the user has the
    # accessor
    path "sys/control-group/request" {
        capabilities = ["update"]
    }
  3. Create a new role with the attached policy, Click on the CLI icon at the top and execute this command
     vault write auth/approle/role/awx token_policies="approle"
  4. Get the RoleID and SecretID, be very carefull with these values!! with these two values all secrets and files from kv/services can be read and changed! You can add token_ttl=1h token_max_ttl=4h to make the credentials only valid for a certain time
    # retrieve roleID
    vault read auth/approle/role/awx/role-id
    # create a new secretID
    vault write -force auth/approle/role/awx/secret-id
  5. Store both IDs encrypted in AWX

Vault CLI

Revoking Tokens

Set the VAULT_TOKEN environment variable to the token you wish to revoke and execute

vault token revoke -self