hashicorp-vault

HashiCorp Transit Engine, what permission are required to read the public key?


I have a docker-compose that setup HashiCorp Vault and Vault Agent services.

Then I have a script that setup a Transit engine and a key. The script creates the policy to the transit key and add it to the role of the token. Using the token as credential I need to get the transit key.

I get the error 403 "1 error occurred:\n\t* permission denied\n\n".
With a wrong token I have 403 "permission denied", also using the token I'm able to login in the UI. That proves the token is working as credentials.
Using the rootToken I get the 200 success result.
So, problem seems related to permissions/policies.

In the Docker compose I use this to set the Agent: command: [ 'vault', 'agent', '-config=/volumes/vault-agent-localhost/config.txt']

config.txt:

pid_file = "/volumes/vault-agent/pidfile"

vault {
  address = "http://vault:8200"
}

auto_auth {
  method {
    type = "approle"
    config = {
      role_id_file_path                   = "/volumes/vault-agent/role-id"
      secret_id_file_path                 = "/volumes/vault-agent/secret-id"
      remove_secret_id_file_after_reading = false
    }
  }

  sink {
    type = "file"
    config = {
      path = "/volumes/vault-agent/token"
    }
  }
}

the seatup.sh script:

export VAULT_ADDR='http://127.0.0.1:8210'
export VAULT_TOKEN='rootToken'


# setup AppRole
vault auth enable approle


# update is required to call "sign" !!
policy='path "transit-local/*" { capabilities = ["read", "update"] } '

# create policy ("-" mean it read from std-in)
echo $policy | vault policy write myapp -

vault write auth/approle/role/my-role \
    role_id="my-role" \
    token_policies="myapp" \
    token_ttl=120m \
    token_max_ttl=120m \
    secret_id_num_uses=0

# this solved the error: error getting path or data from method: error="no known secret ID"
vault write -f -field=secret_id auth/approle/role/my-role/secret-id > volumes/vault-agent/secret-id


# Create the transit engine (if not exists)
vault write sys/mounts/transit-local type=transit path=transit-local

# create a new Ed25519 key 
key_name="my-key-ed25519"
vault write -f transit-local/keys/$key_name type=ed25519

If I login the UI with rootToken I can see the transit-local path, and the key inside it.
If I login the UI with generated token I cannot see the transit-local path.

In the UI Policies section, I can see "myapp" and if I open it I can see the policies:

path "transit-local/*" { capabilities = ["read", "update"] } 

What is missing here ? why that token is not getting the permission?

** [Update] **

I'm using the Read endpoint (https://developer.hashicorp.com/vault/api-docs/secret/transit#read-key) that is NOT returning the secret key.
For Ed25519 key type it returns something like this (extract):

        "keys": {
            "1": {
                "creation_time": "2023-06-03T09:00:33.940999141Z",
                "name": "ed25519",
                "public_key": "kAD**************************cw="
            }
        },
        "latest_version": 1,

Using the latest version I can get the right public key (Base64 format).

There is no other endpoints that allow to get the public key (at least, I haven't found).

[Update 2]

Output of vault token lookup:

---                  -----
accessor             9aTi***DwU
creation_time        1717405261
creation_ttl         768h
display_name         approle
entity_id            9a19ad41-da28-22f5-7161-018c6b4b8af7
expire_time          2024-07-05T09:01:01.486433609Z
explicit_max_ttl     0s
id                   hvs.CAES***reEw
issue_time           2024-06-03T09:01:01.480247932Z
last_renewal         2024-06-03T09:01:01.486433709Z
last_renewal_time    1717405261
meta                 map[role_name:my-role]
num_uses             0
orphan               true
path                 auth/approle/login
policies             [default]
renewable            true
ttl                  761h50m56s
type                 service

Token is the one stored in /volume/.../token. :OK.
"num_uses: 0" does not seems correct.
"policies: [default]" does not seems correct neither.

** [Update-3] **

I'm not sure the vault command is always using the right address (I've no errors running the script, and the other Vault at 8200 is down to avoid false result) because it seems like for some commands (like calling "vault read" from the console) I have to pass the -address parameter, otherwise the error says the key was not found at 127.0.0.1:8200... while it should use 8210, as specified with export VAULT_ADDR.
Maybe is just a problem in the last test I did in the console.

Another detail: I'm using GitBash in Windows. I have this alias set: alias vault="/c/Data/Tools/Hashicorp\ Vault/vault.exe" so I just use "vault" command in GitBash shell.

** [Update 4] **
The 2 services are setup with Docker Compose.
Since another application has already a Vault exposed on default 8200, here I had to expose the Vault on 8210.

networks:
  my-network:
    name: my-network

services:
  vault:
    container_name: my-vault
    hostname: vault
    image: hashicorp/vault:latest
    restart: unless-stopped
    command: ["vault", "server", "-dev", "-dev-listen-address=0.0.0.0:8200"]
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: rootToken
      VAULT_ADDR: http://127.0.0.1:8200
    volumes:
      - ./volumes/vault/file:/vault/file
      - ./volumes/vault/logs:/vault/logs
    cap_add:
      - IPC_LOCK
    ports:
      # 8200 is used by another Vault
      - "8210:8200"  # Map container port 8200 (UI) to host port 8210
    networks:
      - my-network

  vaultagent:
    depends_on: [vault]      
    container_name: my-vaultagent
    image: hashicorp/vault:latest
    restart: always
    command: [ 'vault', 'agent', '-config=/volumes/vault-agent-localhost/config.txt']
    volumes:
      - ./volumes/vault-agent-localhost:/volumes/vault-agent-localhost
    cap_add:
      - IPC_LOCK
    networks:
      - my-network

Solution

  • The comments thread below your question shows that the myapp policy is not applied to the AppRole's token.

    The agent uses address = "http://vault:8200", but your configuration script uses export VAULT_ADDR='http://127.0.0.1:8210'.

    Assuming the vault hostname resolves to the Vault that is running on localhost, change the port in config.txt from 8200 to 8210 (or make whatever changes are required to reach the instance where the policy is).