Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configuring users with TLS certificate authentication does not seem to exist in hvac #481

Open
buchs opened this issue Jun 26, 2019 · 9 comments
Assignees
Labels
tls-cert-auth Related to TLS Certificates Auth Method

Comments

@buchs
Copy link

buchs commented Jun 26, 2019

No description provided.

@buchs
Copy link
Author

buchs commented Jun 26, 2019

Ack! Blank description. I want to do the equivalent of:

vault write auth/cert/certs/
display_name= policies=web [email protected] ttl=3600

I don't see a way to do it currently in hvac. Please let me know because I might be able to create a pull request with it implemented.

@nick-george
Copy link

nick-george commented May 23, 2020

Hi @buchs, did you end up implementing this feature? I'm keen to use it.

I thought that the 'enable_auth_method()' might be a simple wrapper around the Vault (https://www.vaultproject.io/api-docs/system/auth) auth api endpoint, but alas, hvac wants a class implemented for each auth method.

@buchs
Copy link
Author

buchs commented May 23, 2020

I did not end up using this.

@nick-george
Copy link

OK, thanks Kevin.

@UlfbertWusel
Copy link

Hi, I would like to use this feature in my code aswell, any updates as far as implementation?

Ack! Blank description. I want to do the equivalent of:

vault write auth/cert/certs/
display_name= policies=web [email protected] ttl=3600

I don't see a way to do it currently in hvac. Please let me know because I might be able to create a pull request with it implemented.

@jeffwecan
Copy link
Member

I'll take a look at adding support for the TLS Certificates auth method over the next week or so.

@jeffwecan jeffwecan added the tls-cert-auth Related to TLS Certificates Auth Method label Aug 19, 2020
@jeffwecan jeffwecan added this to the 0.10.6 milestone Aug 19, 2020
@jeffwecan jeffwecan self-assigned this Aug 19, 2020
@sficyrus
Copy link

Thanks for looking into this.
I've been able to use hvac to get all other portions of my workflow set up (enabling the cert backend, authenticating via TLS, etc.). It would be quite helpful to have the ability to write a certificate into the "cert" auth backend via hvac as well. Right now, I seem to either have to conduct this step manually via the UI or (I guess) do it via CLI....which I'd rather be able to finish the job in hvac!

@jeffwecan jeffwecan removed this from the 0.10.6 milestone Apr 29, 2021
@Tylerlhess
Copy link
Contributor

Should be solved with #691

@sficyrus
Copy link

Hi @Tylerlhess, thanks for giving this a go.

For context, I'd like to be able to use your new implementation for mutual TLS authentication between the Vault instance and the hvac client. It seemed I had the auth part working up through hvac 0.10.11 using the auth_tls method. The storing of the certificates on the cert mount point, I had to do outside hvac.

Afterwards (>= hvac 0.10.12), something else has changed where the client certificate appears to be dropped. This looks like it isn't necessarily related to your work but something deeper.

To help give a bit more context, here's an adapted toy example:

#!/usr/bin/env python

import hvac
import json
import logging as logger
import sys
from pydantic import BaseSettings

logger.basicConfig(stream=sys.stdout, level=logger.DEBUG)


class VaultSettings(BaseSettings):
    VAULT_SERVER_NAME: str = "vault"
    VAULT_SERVER_URL: str = "https://kme1:8200"
    CLIENT_NAME: str = "watcher"
    CERT_DIRPATH: str = "/volumes/kme1/certificates/production/admin"
    CLIENT_DIRPATH: str = f"{CERT_DIRPATH}/{CLIENT_NAME}"
    CA_CHAIN_SUFFIX: str = ".ca-chain.cert.pem"
    KEY_SUFFIX: str = ".key.pem"
    CLIENT_CERT_FILEPATH: str = f"{CLIENT_DIRPATH}/{CLIENT_NAME}{CA_CHAIN_SUFFIX}"
    CLIENT_KEY_FILEPATH: str = f"{CLIENT_DIRPATH}/{CLIENT_NAME}{KEY_SUFFIX}"
    SERVER_CERT_FILEPATH: str = f"{CERT_DIRPATH}/{VAULT_SERVER_NAME}/{VAULT_SERVER_NAME}{CA_CHAIN_SUFFIX}"
    VAULT_CERT_AUTH_MOUNT_POINT: str = "cert"


settings = VaultSettings()


class VaultClientAuthCert:

    def __init__(self) -> None:
        """Authenticate to Vault server instance with TLS certificates
        """
        self.create_client()

    def create_client(self) -> None:
        """Create hvac vault client
        """
        logger.info("Attempt hvac create client")
        logger.debug(f"Vault Server URL: {settings.VAULT_SERVER_URL}")
        logger.debug(f"Client Certificate Filepath: {settings.CLIENT_CERT_FILEPATH}")
        logger.debug(f"Client Key Filepath: {settings.CLIENT_KEY_FILEPATH}")
        logger.debug(f"Server CA Chain Filepath: {settings.SERVER_CERT_FILEPATH}")

        self.vclient: hvac.Client = \
            hvac.Client(url=settings.VAULT_SERVER_URL,
                        cert=(settings.CLIENT_CERT_FILEPATH,
                              settings.CLIENT_KEY_FILEPATH),
                        verify=settings.SERVER_CERT_FILEPATH
                        )

    def vault_cert_client_auth(self,
                               role_name: str = settings.CLIENT_NAME
                               ) -> None:
        mount_point = settings.VAULT_CERT_AUTH_MOUNT_POINT
        logger.info("Attempt TLS client login")
        logger.debug(f"Cert Auth Mount Point: {mount_point}")

        auth_response = self.vclient.auth.\
            cert.login(name=role_name,
                       cacert=False,  # Should already be picked up from verify above?
                       cert_pem=settings.CLIENT_CERT_FILEPATH,
                       key_pem=settings.CLIENT_KEY_FILEPATH,
                       mount_point=mount_point,
                       use_token=True)

        logger.debug(f"Vault auth response: {json.dumps(auth_response, indent=2, sort_keys=True)}")

        if self.vclient.is_authenticated():
            logger.info(f"\"{settings.CLIENT_NAME}\" is now authenticated")
        else:
            logger.info(f"\"{settings.CLIENT_NAME}\" has failed to authenticate")

    # Old method of logging in. Works up through hvac 0.10.11
    # Afterwards:
    # Vault log info: http: TLS handshake error from ... tls: client didn't provide a certificate
    # requests.exceptions.SSLError: HTTPSConnectionPool(host='...', port=8200): Max retries
    #     exceeded with url: /v1/auth/cert/login (Caused by SSLError(SSLError(1, '[SSL:
    #     SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:2633)')))
    def vault_client_auth_tls(self) -> None:
        mount_point = settings.VAULT_CERT_AUTH_MOUNT_POINT
        logger.info("Attempt TLS client login")
        logger.debug(f"Cert Auth Mount Point: {mount_point}")

        auth_response = self.vclient.\
            auth_tls(mount_point=mount_point,
                     use_token=True
                     )

        logger.debug(f"Vault auth response: {json.dumps(auth_response, indent=2, sort_keys=True)}")

        if self.vclient.is_authenticated():
            logger.info(f"\"{settings.CLIENT_NAME}\" is now authenticated")
        else:
            logger.info(f"\"{settings.CLIENT_NAME}\" has failed to authenticate")


if __name__ == "__main__":
    # toggle between hvac versions to get old client to work
    logger.debug("Try new auth method")
    new_client = VaultClientAuthCert().vault_cert_client_auth()

    logger.debug("Try auth_tls method")
    old_client = VaultClientAuthCert().vault_client_auth_tls()

In hvac 0.10.10, this runs the old method okay and the new method isn't implemented yet. In 0.10.14, both auth methods seem to fail because of the same reason.

new_method:

hvac.exceptions.InvalidRequest: invalid certificate or no client certificate supplied, on post https://kme1:8200/v1/auth/cert/login

old method:

requests.exceptions.SSLError: HTTPSConnectionPool(host='kme1', port=8200): Max retries exceeded with url: /v1/auth/cert/login (Caused by SSLError(SSLError(1, '[SSL: SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:2633)')))

vault output:
http: TLS handshake error from ...: tls: client didn't provide a certificate

Hopefully someone can shed some light what I might be doing incorrectly or what might be happening.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tls-cert-auth Related to TLS Certificates Auth Method
Projects
None yet
Development

No branches or pull requests

6 participants