pki

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2022 License: MIT Imports: 7 Imported by: 0

README

vault-pki-client

A tiny wrapper around the HashiCorp Vault PKI secrets engine. This client allows you to enable the PKI secrets engine, generate the certs, have the root sign the intermediate and re-import the signed certificate. This client follows the steps outlined in the official HashiCorp tutorial here with the exception of the creation of the PKI role and the issue of the leaf certificates, which will be implemented in the future.

Usage

To test the behavior of the client, you can run the docker compose file contained with this repo, which will spin up two Vault containers running on ports 8200 and 8201:

docker-compose up -d

Now you can generate the root and the intermediate CA and perform the signing procedure as follows:

package main

import (
	"fmt"

	"github.com/ansorren/vault-pki-client"
)

func main() {
	// instantiate the client for the root CA vault cluster
	rootClient, err := pki.NewClient(
		pki.WithAddress("http://localhost:8200"),
		pki.WithToken("admin"),
	)
	if err != nil {
		panic(err)
	}

	// instantiate the client for the intermediate CA vault cluster
	intermediateClient, err := pki.NewClient(
		pki.WithAddress("http://localhost:8201"),
		pki.WithToken("admin"),
	)
	if err != nil {
		panic(err)
	}

	// Enable the root CA PKI secrets engine
	err = rootClient.EnablePKIEngine("pki")
	if err != nil {
		panic(err)
	}

	// Enable the intermediate CA PKI secrets engine
	err = intermediateClient.EnablePKIEngine("pki")
	if err != nil {
		panic(err)
	}


	// Generate the root CA certificate
	rootCaCert, err := rootClient.GenerateRootCA("pki", "root.localhost")
	if err != nil {
		panic(err)
	}
	fmt.Println("common name of the root CA certificate:", rootCaCert.Subject.CommonName)

	// Generate the intermediate CA certificate
	csr, err := intermediateClient.GenerateIntermediateCA("pki", "intermediate.localhost")
	if err != nil {
		panic(err)
	}

	// Ask the root CA to sign the intermediate
	signedCertificate, err := rootClient.SignIntermediateCA("pki", csr)
	if err != nil {
		panic(err)
	}

	// Import the certificate signed by the root CA back into the intermediate
	// PKI secrets engine
	err = intermediateClient.SetSignedCertificate("pki", signedCertificate)
	if err != nil {
		panic(err)
	}
}

Now query the unauthenticated Vault endpoint listed here with the following command, and you should see that the intermediate certificate (intermediate.localhost) has been signed by root.localhost (the Issuer field):

curl http://localhost:8201/v1/pki/ca/pem | openssl x509 -noout -text


Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            02:fd:22:b8:7a:d4:33:6e:6a:35:43:35:f7:0b:75:79:ea:5a:31:75
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=root.localhost
        Validity
            Not Before: Jan 28 17:01:38 2022 GMT
            Not After : Jan 26 17:02:08 2032 GMT
        Subject: CN=intermediate.localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ca:d6:8b:41:98:89:3e:86:d0:7d:1e:eb:91:2f:
                    28:c5:0b:30:96:b8:9f:20:d0:b2:99:33:48:51:22:
                    34:12:22:85:2f:ca:46:9f:16:75:12:52:48:b6:99:
                    2e:8a:c3:aa:f7:d6:56:8a:21:ee:96:cd:41:3b:94:
                    79:2e:99:ef:e1:06:bf:c1:29:15:5c:87:37:8e:ec:
                    b5:5f:c3:d1:fb:55:49:97:6f:a1:4a:12:0d:d6:f7:
                    dd:1f:78:2a:90:bf:69:9b:c7:27:b9:0a:3b:82:8b:
                    3c:08:92:0b:44:90:a8:d4:62:12:09:38:3a:1f:31:
                    2c:38:f3:48:0f:2a:74:0a:e0:dd:dd:52:c2:52:2c:
                    29:a9:54:3e:04:ea:23:ae:01:3a:ff:bd:19:b1:33:
                    02:ed:ce:36:6f:6b:ee:e3:c4:8f:40:c2:40:33:ca:
                    37:22:d3:42:60:ad:24:ce:10:82:07:97:c9:6c:5d:
                    48:f4:c7:f9:b7:02:6e:40:9f:ca:0f:bc:57:6a:65:
                    a3:e0:38:76:32:9f:25:cd:85:c7:16:3a:93:55:8b:
                    b3:d7:8f:ca:8f:ad:35:b1:6e:b1:77:45:05:11:19:
                    fc:88:b2:a8:28:af:e6:f9:0f:0c:c3:03:d6:07:fd:
                    98:30:46:2f:a6:6b:21:df:70:f3:ad:8f:37:72:dc:
                    f8:c7
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                81:7B:1A:87:CC:4E:DB:BF:BC:2C:5C:06:19:2C:18:A6:46:EA:D6:D8
            X509v3 Authority Key Identifier: 
                keyid:D2:A9:99:42:58:A4:DE:75:40:8E:99:46:29:39:05:C9:38:77:98:22

            X509v3 Subject Alternative Name: 
                DNS:intermediate.localhost
    Signature Algorithm: sha256WithRSAEncryption
         96:f3:29:0e:a0:24:c0:e2:ae:f0:1d:b1:8c:7c:8c:b0:05:1b:
         72:fa:2c:6b:e1:88:bc:20:87:da:66:7a:0a:cc:7c:cf:6e:88:
         85:f9:1f:91:94:d0:3b:01:3e:60:15:82:c9:c3:8c:64:c2:26:
         d2:4a:30:b1:b7:b5:e0:b7:79:9e:62:d2:ce:93:f0:c2:bc:e9:
         49:7a:a1:67:4c:ff:fb:2d:78:46:73:78:4f:3b:4c:f5:03:df:
         3b:9a:f0:7b:fb:9a:04:d8:9a:cf:9c:2c:c3:7c:26:cd:b5:0e:
         1d:3e:1c:cc:6c:76:65:cb:19:22:15:27:a8:7c:58:4d:32:60:
         84:24:cc:b5:64:5d:b9:97:12:61:04:e4:d8:af:e6:9d:9e:94:
         b9:9e:d7:c6:d7:eb:72:ae:85:5a:3e:9a:80:b7:13:52:2d:94:
         b9:b6:55:77:e9:a0:71:2d:10:f1:f1:f5:da:86:be:62:57:19:
         d3:84:50:38:04:3a:c0:ef:3d:d9:4f:41:47:fe:e1:3b:06:e5:
         94:62:ec:61:16:a6:8c:ca:a0:f7:1c:a4:e8:45:da:ff:ca:39:
         23:ee:ed:03:15:b3:40:82:8d:e7:95:7e:63:32:1f:38:32:7d:
         a6:e5:bd:0c:39:e6:d3:44:b4:9d:b4:17:92:f5:75:dd:fa:64:
         7a:2b:2e:2c

Documentation

Index

Constants

View Source
const (
	CsrPemBlockType         = "CERTIFICATE REQUEST"
	CertificatePemBlockType = "CERTIFICATE"
	PrivateKeyPemBlockType  = "PRIVATE KEY"
)
View Source
const (
	DefaultLeaseTTL    = "24h"
	DefaultMaxLeaseTTL = "87600h"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	Address string
	Token   string
	Client  *api.Client
}

Client is the vault client that knows how to talk to the

func NewClient

func NewClient(options ...Option) (*Client, error)

NewClient instantiates a new PKI client.

func (*Client) CreatePKIRole

func (c *Client) CreatePKIRole(path string, opts CreatePKIRoleOptions) error

CreatePKIRole creates a PKI role with the given options at the given path.

func (*Client) EnablePKIEngine

func (c *Client) EnablePKIEngine(path string) error

EnablePKIEngine enables the PKI engine at the given path.

func (*Client) GenerateIntermediateCA

func (c *Client) GenerateIntermediateCA(path string, commonName string) (*x509.CertificateRequest, error)

GenerateIntermediateCA generates an intermediate CA in the PKI secrets engine at the given path and then returns it.

func (*Client) GenerateRootCA

func (c *Client) GenerateRootCA(path string, commonName string) (*x509.Certificate, error)

GenerateRootCA generates a root CA in the PKI secrets engine at the given path and then returns it.

func (*Client) SetSignedCertificate

func (c *Client) SetSignedCertificate(path string, cert interface{}) error

SetSignedCertificate sets the signed certificate into the intermediate PKI secrets engine at the given path.

func (*Client) SignIntermediateCA

func (c *Client) SignIntermediateCA(path string, csr *x509.CertificateRequest) (interface{}, error)

SignIntermediateCA signs the CSR and imports it into the given root PKI secrets engine.

type CreatePKIRoleOptions

type CreatePKIRoleOptions struct {
	RoleName         string
	AllowedDomains   []string
	AllowSubdomains  bool
	AllowBareDomains bool
	AllowGlobDomains bool
	MaxTTL           string
}

CreatePKIRoleOptions is the data structure that holds the configuration required to create a PKI Role.

type Option

type Option func(client *Client) error

func WithAddress

func WithAddress(vaultAddr string) Option

WithAddress sets the given address on the client.

func WithConfig

func WithConfig(config *api.Config) Option

WithConfig instantiates a vault client with the given config.

func WithToken

func WithToken(vaultToken string) Option

WithToken sets the given token on the client.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL