alexK
alexK

Reputation: 953

Hashicorp Vault tls cert authentication does not read certificate

I'm trying to setup certificate-based authentication in Vault. For tests I've just created a clean Vault setup. Vault configuration below:

listener "tcp" {
  address                  = "192.168.33.10:8200"
  tls_cert_file            = "/etc/vault/vault_cert.pem"
  tls_key_file             = "/etc/vault/vault_key.pem"
  tls_disable_client_certs = false
  tls_disable              = false
}

listener "tcp" {
  address                  = "127.0.0.1:8200"
  tls_disable              = true
}

storage "file" {
  path = "/etc/vault/data"
}

I've started and unsealed Vault and enabled cert authentication:

[vagrant@localhost ~]$ ./vault status
Key             Value
---             -----
Seal Type       shamir
Sealed          false
Total Shares    5
Threshold       3
Version         0.9.3
Cluster Name    vault-cluster-37dffb3b
Cluster ID      1ddd4712-99f6-3691-a066-d476fbc6d7c6
HA Enabled      false
[vagrant@localhost ~]$ ./vault auth list
Path      Type     Description
----      ----     -----------
cert/     cert     n/a
token/    token    token based credentials

Now I've generated ssl key/certificate pair which is not added yet to Vault, so I expect Vault to tell me that certificate is invalid (at least that's my understanding from reading sources here. Though the answer I'm getting says that the certificate was not supplied at all:

[vagrant@localhost ~]$ VAULT_ADDR='https://192.168.33.10:8200' ./vault login -method cert -tls-skip-verify -client-cert=./client_cert.pem -client-key=./client_key.pem
Error authenticating: Error making API request.

URL: PUT https://192.168.33.10:8200/v1/auth/cert/login
Code: 400. Errors:

* client certificate must be supplied

From what I was able to find in sources, this error message is only returned when there is no certificate supplied to Vault at all. Just to make sure that's not a problem in Vault cli client, I've tried to do the same with curl, but got the same result:

[vagrant@localhost ~]$ curl -iv -k -X POST --cert ./client_cert.pem --key ./client_key.pem https://192.168.33.10:8200/v1/auth/cert/login
* About to connect() to 192.168.33.10 port 8200 (#0)
*   Trying 192.168.33.10...
* Connected to 192.168.33.10 (192.168.33.10) port 8200 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: CN=Vault,[email protected],O=Exmaple,L=Berlin,ST=BERLIN,C=DE
*   start date: Feb 14 15:59:37 2018 GMT
*   expire date: Feb 12 15:59:37 2028 GMT
*   common name: Vault
*   issuer: CN=Vault,[email protected],O=Exmaple,L=Berlin,ST=BERLIN,C=DE
> POST /v1/auth/cert/login HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.33.10:8200
> Accept: */*
>
< HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
< Cache-Control: no-store
Cache-Control: no-store
< Content-Type: application/json
Content-Type: application/json
< Date: Wed, 14 Feb 2018 16:20:57 GMT
Date: Wed, 14 Feb 2018 16:20:57 GMT
< Content-Length: 51
Content-Length: 51

<
{"errors":["client certificate must be supplied"]}
* Connection #0 to host 192.168.33.10 left intact

Vault server running in trace mode doesn't provide any logs during this interaction. Though, if I will use a key from the different certificate trying to deliberately break TLS, I see an error message in Vault indicating that.

Any idea what could be wrong with this setup?

Upvotes: 3

Views: 23742

Answers (3)

Raman Sharma
Raman Sharma

Reputation: 2150

Although I am answering late. But I was able to configure spring cloud config server to use Vault as backend with CERT authentication via certificates.

Here is my tutorial : https://medium.com/@java.developer.raman/enable-spring-config-server-to-use-cert-authentication-with-vault-as-back-end-ff84e1ef2de7?sk=45a26d7f1277437d91a5cff3d5997287

And GitHub repository: https://github.com/java-developer-raman/config-server-vault-backend

Upvotes: 0

jAC
jAC

Reputation: 5324

After digging through commits regarding the TLS client verification for Vault, I finally have a working Vault instance.

For setting up client certificate verification for any request to the Vault TCP listener, you have to configure two values:

  • tls_client_ca_file = "/my/intermediate/ca/intermediate.cert.pem
  • tls_require_and_verify_client_cert = true

When these two settings are configured, all requests to the backend without a valid client certificate are blocked, all valid client requests are then forwarded to the Vault instance.

In my understanding this simply is a "filter" for unauthorised access.

So let's begin with the TLS cert authentication setup:

First of all, we have to set up the Vault CLI to provide a Client Certificate for each request it executes:

export VAULT_CLIENT_CERT="/my/cert/path/vault-client.cert.pem"
export VAULT_CLIENT_KEY="/my/cert/path/vault-client.key.pem"

export VAULT_ADDR="https://my.vault.app.com:8200"

With this command, we can get through the TCP listener's "filter".

And finally execute the command that enables the Client Certificate authentication

vault auth enable cert

For granting access to specific clients, the certificate has to be linked to a policy which itself describes access to a specific Secrets Engine:

Let's create a simple KV secrets engine for myorganization/dev:

vault secrets enable -path=myorganization/dev kv

Then we have to create a policy file (HCL syntax) for the Secrets Engine:

path "myorganization/dev/myapp" {
     capabilities = ["read"]
}

After creating the policy file, we can upload it to the vault's policy store:

vault policy write myapp-read-access myapp-read-access.hcl

And finally we have to assign an app or client certificate* to this policy by uploading the .cert.pem file to the certificate store and mapping it to this policy:

vault write auth/cert/certs/myapp display_name="My Vault Test App" policies=myapp-read-access certificate=myapp.cert.pem ttl=3600

* This can be the same as in the export directives or some other cert (same CA of course)

After this is configured, you can then use the CLI client:

vault login -method=cert

Alternatively, you can specify another certificate for the login by using:

vault login -method=cert -client-cert=myapp.cert.pem -client-key=myapp.key.pem

In my case I used a Java client, with the following Maven POM for dependencies:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-vault-dependencies</artifactId>
    <version>2.0.2.BUILD-SNAPSHOT</version>
    <scope>import</scope>
    <type>pom</type>
</dependency>

And the following Vault client configuration (bootstrap.yml):

spring.application.name: myapp
spring.cloud.vault:
  host: my.vault.app.com
  port: 8200
  scheme: https
  generic.backend: myorganization/dev
  authentication: CERT
  ssl:
    key-store: classpath:myapp.jks
    key-store-password: <MYKEYSTOREPW>
    cert-auth-path: cert

Et voilà:

2018-09-19 14:02:18.114 INFO 51832 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='vault', propertySources=[LeaseAwareVaultPropertySource {name='myorganization/dev/myapp'}, LeaseAwareVaultPropertySource {name='myorganization/dev/application'}]}

Or in case a invalid certificate is provided:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://my.vault.app.com:8200/v1/auth/cert/login": Received fatal alert: bad_certificate; nested exception is javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

Upvotes: 6

JJP
JJP

Reputation: 11

I had same exact issue today .. spent half day trying to figure out what's wrong ... turned out that in vault config "tls_disable_client_certs = false" in listener section, actually disables cert authentication ..

so hope anyone else might stumble upon this issue get some clue ... remove that line and cert auth should work.

here is document link , not sure how I interpreted this as enabling this means browser and other clients will ignore self-sign cert, which is not the case..

https://www.vaultproject.io/docs/configuration/listener/tcp.html#tls_disable_client_certs

tls_disable_client_certs (string: "false") – Turns off client authentication for this listener. The default behavior (when this is false) is for Vault to request client certificates when available.

Upvotes: 1

Related Questions