pbchekin / vault-sync

Synchronize secrets between HashiCorp Vault instances
Apache License 2.0
27 stars 1 forks source link

Error: Unable to get local issuer certificate #14

Open r003k opened 2 months ago

r003k commented 2 months ago

Hi,

I've configured the vault-sync.yaml file as follows (just leaving the fields with an actual value set) :


id: vault-sync
full_sync_interval: 3600 # 1h

# Source Vault configuration to sync secrets from.
src:
  # Vault URL
  url: http://source.vault:8200/

  # Vault Token auth method
  token: xxx.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

# Destination Vault configuration to sync secrets to.
dst:
  # Vault URL
  url: https://target.vault:8200/

  # Vault Token auth method
  token:xxx.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

I then try to run the install with : docker run -it -v $PWD:/vault-sync pbchekin/vault-sync:0.8.0 vault-sync --config /vault-sync/vault-sync.yaml

Giving the output :

15:42:14 [INFO] Configuration from /vault-sync/vault-sync.yaml:
{
  "id": "vault-sync",
  "full_sync_interval": 3600,
  "bind": null,
  "src": {
    "url": "http://source.vault:8200/",
    "token": "***",
    "token_ttl": null,
    "token_max_ttl": null,
    "prefix": "",
    "backend": "secret"
  },
  "dst": {
    "url": "https://target.vault:8200/",
    "token": "***",
    "token_ttl": null,
    "token_max_ttl": null,
    "prefix": "",
    "backend": "secret"
  }
}
15:42:14 [INFO] Connecting to http://source.vault:8200/
15:42:14 [INFO] Audit device vault-sync exists: false
15:42:14 [INFO] Connecting to https://target.vault:8200/
15:42:14 [INFO] Token: TokenInfo { renewable: false, ttl: None, max_ttl: None }
15:42:14 [INFO] Plan: TokenInfo { renewable: false, ttl: None, max_ttl: None }
15:42:14 [ERROR] Failed to connect to https://target.vault:8200/: reqwest error: error sending request for url (https://target.vault:8200/v1/auth/token/lookup-self): error trying to connect: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1916: (unable to get local issuer certificate)
Error: Reqwest(reqwest::Error { kind: Request, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("target.vault")), port: Some(8200), path: "/v1/auth/token/lookup-self", query: None, fragment: None }, source: hyper::Error(Connect, Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 337047686, library: "SSL routines", function: "tls_process_server_certificate", reason: "certificate verify failed", file: "../ssl/statem/statem_clnt.c", line: 1916 }]))) }, X509VerifyResult { code: 20, error: "unable to get local issuer certificate" })) })

The connection to the source Vault which is using HTTP doesn't have any issue (it would seem). However, the connection to the target Vault which is restricted to HTTPS only fails because the "local issuer certificate" cannot be accessed.

How could I provide the "local issuer certificate" when installing ?

P.S: I've tested connecting directly on the target Vault UI with the token I provided in vault-sync.yaml and was able to login.

Thank you.

pbchekin commented 2 months ago

Hey, thank you for reporting this. Do you need an option to provide a certificate, or, as a workaround` a kind of "insecure" mode (see for example https://curl.se/docs/manpage.html#-k) to skip verifying a sever certificate?

r003k commented 2 months ago

Hey, both options are actually interesting. The "insecure" mode for testing purposes comes in very handy, however for more "productive" environments the use of a proper secured connection still is a requirement for many.

r003k commented 2 months ago

Making sure that the .pem certificate file was also in my current directory which is mounted on the docker image and then passing the SSL_CERT_FILE environment variable to point to the .pem file on the docker image proved to be a workaround :

docker run -it -v $PWD:/vault-sync -e SSL_CERT_FILE='/vault-sync/.certs/company-ca-bundle.pem' pbchekin/vault-sync:0.8.0 vault-sync --config /vault-sync/vault-sync.yaml

output

09:51:52 [INFO] Configuration from /vault-sync/vault-sync.yaml:
{
  "id": "vault-sync",
  "full_sync_interval": 3600,
  "bind": null,
  "src": {
    "url": "http://source.vault:8200/",
    "token": "***",
    "token_ttl": null,
    "token_max_ttl": null,
    "prefix": "",
    "backend": "secret"
  },
  "dst": {
    "url": "https://target.vault:8200/",
    "token": "***",
    "token_ttl": null,
    "token_max_ttl": null,
    "prefix": "",
    "backend": "secret"
  }
}
09:51:52 [INFO] Connecting to http://source.vault:8200/
09:51:52 [INFO] Audit device vault-sync exists: false
09:51:52 [INFO] Connecting to https://target.vault:8200/
09:51:52 [INFO] Token: TokenInfo { renewable: false, ttl: None, max_ttl: None }
09:51:52 [INFO] Plan: TokenInfo { renewable: false, ttl: None, max_ttl: None }
09:51:52 [INFO] Dry run: false
09:51:52 [INFO] Token: TokenInfo { renewable: true, ttl: Some(2690330s), max_ttl: None }
09:51:52 [INFO] Plan: TokenInfo { renewable: true, ttl: Some(2690330s), max_ttl: None }
09:51:52 [INFO] FullSync worker started
09:51:52 [INFO] FullSync started
09:51:52 [INFO] Sync worker started
09:51:52 [WARN] Failed to list secrets in : Error in vault response: Vault request failed: Response { url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("source.vault")), port: Some(8200), path: "/v1/secret/metadata/", query: None, fragment: None }, status: 404, headers: {"cache-control": "no-store", "content-type": "application/json", "strict-transport-security": "max-age=31536000; includeSubDomains", "date": "Thu, 27 Jun 2024 09:51:52 GMT", "content-length": "14"} }, error message: `{"errors":[]}
Could not read vault response.`
09:51:52 [INFO] FullSync finished in 30ms
09:51:52 [INFO] Secrets created/updated: 0, deleted: 0

I still have another error retrieving the secrets from the source Vault but this is another issue that I have to check.

lololastico74 commented 2 months ago

I have the same issue with an Openshift/ArgoCD deployment using the HELM implementation, I tried to create a secret with CA Cert of my company to implement it as a volume into the deployment. I tried to do the modification directly in the deployment but could not afford it. I do not want to skip teh verification but want to add my CA, any quick fix related ?

lololastico74 commented 2 months ago

Here is the logs:

07:08:48 [INFO] Connecting to https://vault.src/
07:08:48 [ERROR] Failed to connect to https://vault.src/: reqwest error: error sending request for url (https://vault.src/v1/auth/token/lookup-self): error trying to connect: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1916: (unable to get local issuer certificate)
Error: Reqwest(reqwest::Error { kind: Request, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("vault.src")), port: None, path: "/v1/auth/token/lookup-self", query: None, fragment: None }, source: hyper::Error(Connect, Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 337047686, library: "SSL routines", function: "tls_process_server_certificate", reason: "certificate verify failed", file: "../ssl/statem/statem_clnt.c", line: 1916 }]))) }, X509VerifyResult { code: 20, error: "unable to get local issuer certificate" })) })

here is my values:

vault-sync:
  vaultSync:
    src:
      url: https://vault.src/
      backend: engine
      token: xxx.xxxxxxxxxxxxxxxxxxxxxx
    dst:
      url: https://vault.dst/
      backend: engine
      token: xxx.xxxxxxxxxxxxxxxxxxxxxx
pbchekin commented 1 month ago

@lololastico74 it should be possible with the latest version (0.1.3) of the Helm chart:

First, you need to make sure you have a Kubernetes secret with the certificate, for example:

kubectl --namespace=vault-sync create secret generic certs --from-file=ca-bundle.pem=/path/to/certificate.pem

Then you need to provide the following additional chart values:

volumes:
  - name: certs
    secret:
      secretName: certs

volumeMounts:
  - mountPath: /certs
    name: certs
    readOnly: true

environmentVars:
  - name: SSL_CERT_FILE
    value: /certs/ca-bundle.pem

Let me know if that works for you.