cyberark / conjur

CyberArk Conjur automatically secures secrets used by privileged users and machine identities
https://conjur.org
Other
780 stars 124 forks source link

Spike: There are clear instructions for programmatically retrieving the Conjur SSL certificate #2038

Closed izgeri closed 3 years ago

izgeri commented 3 years ago

At current, we recommend users retrieve the Conjur PEM-encoded x509 CA certificate chain using a complicated OpenSSL command:

openssl s_client -showcerts -servername [DAP_INSTANCE_DNS_NAME] -connect [DAP_INSTANCE_DNS_NAME]:443 < /dev/null 2> /dev/null

We would like to provide clear instructions for retrieving the Conjur PEM-encoded x509 CA certificate chain when:

However the certificate is retrieved, it will be added to the Kubernetes cluster in a ConfigMap during the cluster setup designed in #2039.

We should consider whether Conjur / DAP certificates are being signed by a known / trusted CA or if they are self-signed.

In devising a proposed solution, we should review the options with the security architect to ensure the proposed solution is secure.

The outcome of this spike will inform the rest of the work planned to complete #2026.

AC:

izgeri commented 3 years ago

We may want to learn from the recent lessons of the Python CLI project - you can see some details on their approach in https://github.com/cyberark/conjur-api-python3/issues/198

izgeri commented 3 years ago

I propose that clients should:

  1. by default verify server cert (to ensure it’s signed by a trusted CA and has a valid hostname) against CAs trusted by the system. Note: if you are using self-signed certificates, you can modify the applications CA certificate store to add the Conjur CA cert.
  2. if directory of certificates of trusted CAs is provided to the client, then verify server cert (to ensure it’s signed by a trusted CA and has a valid hostname) against the CA certificates in the provided directory. Note: if you are using self-signed certificates, you can provide the client with a directory containing the Conjur CA certificate store (in K8s this would be via ConfigMap).
  3. if CA certificate is provided to the client, then verify server cert (to ensure it’s signed by the provided trusted CA and has a valid hostname). Note: if you are using self-signed certificates, you can provide the client with the Conjur CA certificate (in K8s this would be via ConfigMap).
  4. if “skip-ssl-validation” (or similar) is provided to client, then client does not perform server certification verification. This is not recommended as it makes the client vulnerable to MitM attacks.

If this is the guidance we provide to end-users who use our clients, then we would need to provide instructions to retrieve the Conjur CA certificate in case self-signed certificates are being used. This is not trivial, but:

We could just make some assumptions. Since we know we don't have an intermediate CA, then we can safely assume that the last certificate in the output from openssl s_client -showcerts is going to be the root CA and just cut that bit out.

Here is an example flow some vendors use to explain to customers how to get the root CA cert:

  1. To create a CA certificate, execute the following command: openssl s_client -connect your.name.com:8443 –showcerts
  2. The command output appears on the screen. The second block of base-64 encoded text (between the “-----BEGIN CERTIFICATE-----” and the “-----END CERTIFICATE -----“) is the certificate of interest.
  3. Copy the certificate text into the 1.2.3.4_CA.pem file.
  4. Copy the 1.2.3.4_CA.pem file to XXX machine.

Note that this may not always work, see for example this SO thread.

doodlesbykumbi commented 3 years ago

Created a gist with example Golang implementation for fetching certificate, see https://gist.github.com/doodlesbykumbi/33130af98c94f28aabab60206206cc70.

doodlesbykumbi commented 3 years ago

Also noted from the python CLI issue that

The tricky part about fetching the cert is that it's possible that the server is (mis)configured to not advertise the whole chain, and so trying to use the fetched certificate for verification results in an error like SSL Error: unable to get local issuer certificate. I believe the way to circumvent this is to get the missing part of the chain to the root CA certificate (likely from a person or some other service) and use that for cert_file: "/path/to/cert". The cool thing is we can check for this after fetching the certificate by trying to verify the endpoint using the fetched certificate.

So we'll want to attempt verification after fetching the cert to ensure that it's enough.

doodlesbykumbi commented 3 years ago

Updated the gist to include detecting incomplete certs by attempting to verify the endpoint using the fetched certificate, see https://gist.github.com/doodlesbykumbi/33130af98c94f28aabab60206206cc70.