Using this CLI tool, you can copy Vault Kubernetes Auth Config and Roles from one Kubernetes Auth Method mount path to another mount path, even across Vault instances! :D
Note: The tool is written in Golang and uses Vault Official Golang API. The official Vault API documentation is here - https://pkg.go.dev/github.com/hashicorp/vault/api
Note: The tool needs Vault credentials of a user/account that has access to both the source and destination Vault, to read the Kubernetes Auth Method Configuration and Roles from source Vault and to configure the Kubernetes Auth Method Configuration and Roles in the destination Vault
Note: We have tested this only with some versions of Vault (like v1.15.x). So beware to test this in a testing environment before using this in critical environments like production!
Note
Note: This does NOT copy the Token Reviewer JWT token as it's not supported to be read from Vault once written. I think this is a security feature that Vault has implemented to not be able to read the token reviewer JWT token once it has been configured, to avoid leakage/exposure of the token
Note: This tool does NOT currently enable auth methods at any path. It assumes that the Kubernetes Auth Method has already been enabled at the given destination path and just configures it and adds roles
Note: This method also does NOT create any Vault policies or copy Vault policies from source Vault to detination Vault. It assumes that the Vault policies referred to in the Kubernetes Auth Method Roles (Roles Configuration) in the source Vault already exist in the destination Vault. If the policies referred to in the Kubernetes Auth Method Roles exist in source Vault but not in destination Vault, but you copy the Kubernetes Auth Method Configuration and Roles Configuration from source Vault to destination Vault, the Kubernetes Auth Method in the destination Vault will not work as expected, that is - it will not work the same way as the source Vault, since the destination Vault will not have the Vault policies referred to in the Kubernetes Auth Method Roles which was just copied from source Vault to destination Vault
Future version ideas:
- Support for copying Vault Policies referred to in the Kubernetes Auth Method Roles (Roles Configuration) from source Vault to destination Vault
- Support for providing the Token Reviewer JWT Token as user input, say through environment variable, so that you can copy that to destination Vault and configure it as part of Kubernetes Auth Method Configuration, since it CANNOT be read from the source Vault through the Vault API
- Remove log verbosity for default settings. It's too verbose now, by default.
- Remove log which shows no information (
nil
) about the data copied to destination Vault, as Write API does NOT seem to be returning any data in the reponse, so, we can just ignore it
go build -v
$ ./vault-k8s-auth-cp
usage: vault-k8s-auth-cp <source-k8s-auth-mount-path> <destination-k8s-auth-mount-path>
Source Vault, it's a secured Vault with HTTPS API enabled and a big token for root. It has some auth methods enabled and configured.
I'm using the Vault Root Token here for full access
$ export VAULT_ADDR='https://127.0.0.1:8200'
$ export VAULT_TOKEN="some-big-token-here"
$ export VAULT_CACERT=$HOME/vault-ca.crt
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 1.15.6
Build Date 2024-02-28T17:07:34Z
Storage Type raft
Cluster Name vault-cluster-9f170feb
Cluster ID 151e903e-e1e7-541e-d089-ce8db2da0a34
HA Enabled true
HA Cluster https://karuppiah-vault-0:8201
HA Mode active
Active Since 2024-04-27T23:15:36.130464099Z
Raft Committed Index 78945
Raft Applied Index 78945
$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
kubernetes/ kubernetes auth_kubernetes_03e3ab8d kubernetes backend n/a
production/ kubernetes auth_kubernetes_0666b235 n/a n/a
token/ token auth_token_b827a290 token based credentials n/a
$ vault read auth/production/config
Key Value
--- -----
disable_iss_validation true
disable_local_ca_jwt true
issuer n/a
kubernetes_ca_cert -----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host https://some-kubernetes-cluster.com
pem_keys []
$ vault list auth/production/role
Keys
----
default
$ vault read auth/production/role/default
Key Value
--- -----
alias_name_source serviceaccount_uid
bound_service_account_names [default]
bound_service_account_namespaces [default]
policies [allow_secrets]
token_bound_cidrs []
token_explicit_max_ttl 0s
token_max_ttl 0s
token_no_default_policy false
token_num_uses 0
token_period 0s
token_policies [allow_secrets]
token_ttl 1h
token_type default
ttl 1h
$ vault policy list
allow_secrets
default
root
$ vault policy read allow_secrets
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
We can see that it has some auth methods enabled and configured. We can also see that it has some policies configured and a Kubernetes Auth Method Role configured for one of the Kubernetes Auth Methods. We are interested in the Kubernetes Auth Method enabled at production
mount path of the source Vault.
Destination Vault, it's a local dev Vault server, with no HTTPS, with token as root
. It was run using
$ vault server -dev -dev-root-token-id root -dev-listen-address 127.0.0.1:8300
We see that it has no auth enabled.
I'm using the Vault Root Token here for full access
$ export VAULT_ADDR='http://127.0.0.1:8300'
$ export VAULT_TOKEN="root"
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.15.4
Build Date 2023-12-04T17:45:28Z
Storage Type inmem
Cluster Name vault-cluster-4543cfc5
Cluster ID c521d162-70ba-bf83-c33d-c6283366d735
HA Enabled false
$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
token/ token auth_token_517e4e2e token based credentials n/a
Let's enable Kubernetes Auth over here at production-copy
mount path and see it's configuration
$ vault auth enable -path production-copy kubernetes
Success! Enabled kubernetes auth method at: production-copy/
$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
production-copy/ kubernetes auth_kubernetes_f09ee9e8 n/a n/a
token/ token auth_token_517e4e2e token based credentials n/a
$ vault read auth/production-copy/config
No value found at auth/production-copy/config
$ vault list auth/production-copy/role
No value found at auth/production-copy/role
As we can see it has no configurations or roles defined/configured, since we just enabled it. Now, let's just copy the Kubernetes Auth Method Configuration and Roles from source Vault to destination Vault. Again, note that we are interested in the Kubernetes Auth Method enabled at production
mount path of the source Vault.
I'm using the Vault Root Token here for both source Vault and destination Vault, for full access. But you don't need Vault Root Token. You just need any Vault Token / Credentials that has enough access to read Kubernetes Auth Method Configuration and Roles from source Vault and configure (write) Kubernetes Auth Method Configuration and Roles in destination Vault
$ export SOURCE_VAULT_ADDR='https://127.0.0.1:8200'
$ export SOURCE_VAULT_TOKEN="some-big-token-here"
$ export SOURCE_VAULT_CACERT=$HOME/vault-ca.crt
$ export DESTINATION_VAULT_ADDR='http://127.0.0.1:8300'
$ export DESTINATION_VAULT_TOKEN="root"
$ ./vault-k8s-auth-cp production production-copy
Source Kubernetes Auth Config: map[disable_iss_validation:true disable_local_ca_jwt:true issuer: kubernetes_ca_cert:-----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host:https://some-kubernetes-cluster.com pem_keys:[]]
Destination Kubernetes Auth Config: <nil>
Source Kubernetes Auth Roles: map[keys:[default]]
Source Kubernetes Auth Role: map[alias_name_source:serviceaccount_uid bound_service_account_names:[default] bound_service_account_namespaces:[default] policies:[allow_secrets] token_bound_cidrs:[] token_explicit_max_ttl:0 token_max_ttl:0 token_no_default_policy:false token_num_uses:0 token_period:0 token_policies:[allow_secrets] token_ttl:3600 token_type:default ttl:3600]
Destination Kubernetes Auth Role: <nil>
Now, let's look at the destination Vault and see if everything is copied and hence configured
$ export VAULT_ADDR='http://127.0.0.1:8300'
$ export VAULT_TOKEN="root"
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.15.4
Build Date 2023-12-04T17:45:28Z
Storage Type inmem
Cluster Name vault-cluster-4543cfc5
Cluster ID c521d162-70ba-bf83-c33d-c6283366d735
HA Enabled false
$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
production-copy/ kubernetes auth_kubernetes_f09ee9e8 n/a n/a
token/ token auth_token_517e4e2e token based credentials n/a
$ vault read auth/production-copy/config
Key Value
--- -----
disable_iss_validation true
disable_local_ca_jwt true
issuer n/a
kubernetes_ca_cert -----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host https://some-kubernetes-cluster.com
pem_keys []
$ vault list auth/production-copy/role
Keys
----
default
$ vault read auth/production-copy/role/default
Key Value
--- -----
alias_name_source serviceaccount_uid
bound_service_account_names [default]
bound_service_account_namespaces [default]
policies [allow_secrets]
token_bound_cidrs []
token_explicit_max_ttl 0s
token_max_ttl 0s
token_no_default_policy false
token_num_uses 0
token_period 0s
token_policies [allow_secrets]
token_ttl 1h
token_type default
ttl 1h
Everything looks good! :D
Note that, the destination Vault does not have any user defined Vault policies. And as mentioned before in the Notes, the policies referred to in the Kubernetes Auth Method Roles (Roles Configuration) in the source Vault are NOT copied to the destination Vault.
In this case, the allow_secrets
Vault policy referred to in the default
Kubernetes Auth Method Role is not present in the destination Vault
$ vault policy list
default
root
This alone, one needs to create themselves manually. In the future, one can use a separate tool for copying Vault Policies. I also plan to add the feature to this tool to copy just the Vault Policies referred to in the Kubernetes Auth Method Roles (Roles Configuration) from source Vault to destination Vault :) So that this manual step is NOT required :)
Note: For now, until I add the feature to this tool to copy just the Vault Policies referred to in the Kubernetes Auth Method Roles (Roles Configuration) from source Vault to destination Vault, you can use my small and simple tool vault-policy-cp
to copy Vault Policies from source Vault to destination Vault
Note: If the destination Vault does NOT have the Kubernetes Auth Method enabled at the given destination mount path, then the tool throws an error similar to this -
$ ./vault-k8s-auth-cp production production
Source Kubernetes Auth Config: map[disable_iss_validation:true disable_local_ca_jwt:true issuer: kubernetes_ca_cert:-----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host:https://some-kubernetes-cluster.com pem_keys:[]]
Error writing k8s auth config to destination vault: Error making API request.
URL: PUT http://127.0.0.1:8300/v1/auth/production/config
Code: 404. Errors:
* no handler for route "auth/production/config". route entry not found.
Note: If the Vault Token / Credentials used for the destination Vault is not valid / wrong / does not have enough access, then the tool throws an error similar to this regardless of if the Kubernetes Auth Method is enabled or not at the given destination mount path -
For example, for a destination mount path that is present with Kubernetes Auth Method enabled in it -
$ export SOURCE_VAULT_ADDR='https://127.0.0.1:8200'
$ export SOURCE_VAULT_TOKEN="some-big-token-here"
$ export SOURCE_VAULT_CACERT=$HOME/vault-ca.crt
$ export DESTINATION_VAULT_ADDR='http://127.0.0.1:8300'
$ export DESTINATION_VAULT_TOKEN="blah" # wrong Vault Token
$ ./vault-k8s-auth-cp production production
Source Kubernetes Auth Config: map[disable_iss_validation:true disable_local_ca_jwt:true issuer: kubernetes_ca_cert:-----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host:https://some-kubernetes-cluster.com pem_keys:[]]
Error writing k8s auth config to destination vault: Error making API request.
URL: PUT http://127.0.0.1:8300/v1/auth/production/config
Code: 403. Errors:
* permission denied
For a destination mount path that is NOT present at all in the destination Vault, for that also same error with bad Vault Token / Credentials -
$ export SOURCE_VAULT_ADDR='https://127.0.0.1:8200'
$ export SOURCE_VAULT_TOKEN="some-big-token-here"
$ export SOURCE_VAULT_CACERT=$HOME/vault-ca.crt
$ export DESTINATION_VAULT_ADDR='http://127.0.0.1:8300'
$ export DESTINATION_VAULT_TOKEN="blah" # wrong Vault Token
$ ./vault-k8s-auth-cp production production-copy
Source Kubernetes Auth Config: map[disable_iss_validation:true disable_local_ca_jwt:true issuer: kubernetes_ca_cert:-----BEGIN CERTIFICATE-----
something
-----END CERTIFICATE-----
kubernetes_host:https://some-kubernetes-cluster.com pem_keys:[]]
Error writing k8s auth config to destination vault: Error making API request.
URL: PUT http://127.0.0.1:8300/v1/auth/production-copy/config
Code: 403. Errors:
* permission denied