Skip to main content

A command-line utility for declaratively provisioning PKI in Hashicorp Vault

Project description

pkictl

Python Version License Coverage Status CircleCI

pkictl is a CLI tool for declaratively configuring and provisioning PKI secrets in HashiCorp Vault. Root and Intermediate Certificate Authorities (CAs) along with their associated roles and policies can be defined and created from a YAML file. It simplifies automating the provisioning of an internal PKI using Vault and strives to achieve idempotency.

pkictl is inspired by kubectl.

How It Works

pkictl uses the Vault HTTP API to mount PKI secrets engines for Root and Intermediate CAs. Intermediate CAs can be signed by a Root CA or other Intermediate CAs. Roles and Policies can be defined in the YAML file for Intermediate CAs.

The Key/Value secrets engine is also used to store the private keys of Intermediate CAs that are configured for export (ie. spec.type: exported).

Installation

pkictl can be installed via pip:

$ pip install pkictl

Compatibility

pkictl has been tested against versions 0.10.X and 0.11.X of Vault.

Usage

$ pkictl --help

declaratively configure PKI secrets in Hashicorp Vault

optional arguments:
-h, --help     show this help message and exit
-d, --debug    enable debug output
-v, --version  show program's version number and exit

subcommands:

    init         Initializes the Hashicorp Vault server
    apply        Creates PKI secrets from a YAML file

Prerequisites

If you're unfamiliar with Vault's PKI secrets, read this guide: Build Your Own Certificate Authority (CA)

pkictl requires an unsealed Hashicorp Vault server and an authentication token with privileges to:

  • mount PKI and KV secrets engines
  • read and write PKI secrets
  • write KV secrets

Initializing the Vault server

Initialize a new Vault server and unseal it:

$ pkictl init -u https://localhost:8200

The Vault server will be initialized with 5 key shares and a key threshold of 3.

  • the root token is saved in .vault-token
  • the master keys shares are saved in vault.log

Initializing and unsealing the Vault server this way is only provided as a convenience for development/testing and is highly discouraged.

Declaratively provisioning PKI secrets

A YAML manifest file is used to define Root and Intermediate CAs, Key/Value engines, roles and policies.

Create a manifest file:

---
kind: RootCA
name: demo-root-ca
description: pkictl demo Root CA
spec:
  key_type: ec
  key_bits: 384
  ttl: 17532h
  exclude_cn_from_sans: true
  subject:
    common_name: Demo Root CA
    organization: pkictl
    ou: README Demo
    country: US
    locality: San Francisco
    province: California
---
kind: IntermediateCA
name: demo-intermediate-ca
description: pkictl demo Intermediate CA
issuer: demo-root-ca
kv_backend: demo-kv-engine
spec:
  type: exported
  key_type: rsa
  key_bits: 4096
  ttl: 8766h
  subject:
    common_name: Demo Intermediate CA
    organization: pkictl
    ou: README Demo
    country: US
    locality: San Francisco
    province: California
  roles:
  - name: server
    config:
      max_ttl: 8766h
      ttl: 8766h
      allow_subdomains: true
      allowed_domains:
        - demo.pkictl.com
      client_flag: false
      server_flag: true
  policies:
  - name: demo-intermediate-ca-pkey
    policy: |
      path "demo-kv-engine" {
        capabilities = ["list"]
      }
      path "demo-kv-engine/demo-intermediate-ca" {
        capabilities = ["read"]
      }
  - name: demo-intermediate-ca-server
    policy: |
      path "demo-intermediate-ca/issue/server" {
        capabilities = ["read", "update"]
      }
      path "demo-intermediate-ca/sign/server" {
        capabilities = ["read", "update"]
      }
---
kind: KV
name: demo-kv-engine
description: pkictl demo KV v1 engine
spec:
  options:
    version: 1

The above example will create:

  • a ECDSA-based Root CA with a TTL of 2 years
  • an RSA-based Intermediate CA with a TTL of 1 year signed by the Root CA
  • a Role named server permitting the Intermediate CA to generate or sign TLS server certificates for any subdomains on demo.pkictl.com
  • a Policy mapped to the server role
  • a Key/Value engine to store the exported private key of the Intermediate CA

Create PKI secrets from the YAML manifest file:

$ pkictl apply -u https://localhost:8200 -f manifest.yaml

[*] pkictl - the Vault server has been initialized and is not sealed
[*] pkictl - Enabled KV backend: demo-kv-engine
[*] pkictl - Enabled PKI backend: demo-root-ca
[*] pkictl - Generated Root CA: demo-root-ca
[*] pkictl - Enabled PKI backend: demo-intermediate-ca
[*] pkictl - Created intermediate CA: demo-intermediate-ca
[*] pkictl - Signed intermediate CA 'demo-intermediate-ca' with issuing CA: demo-root-ca
[*] pkictl - Set signed certificate for intermediate CA: demo-intermediate-ca
[*] pkictl - Configured URLs for CA: demo-intermediate-ca
[*] pkictl - Set CRL configuration for CA: demo-intermediate-ca
[*] pkictl - Stored private key for 'demo-intermediate-ca' in KV backend: demo-kv-engine
[*] pkictl - Configured role 'server' for intermediate CA: demo-intermediate-ca
[*] pkictl - Configured policy 'demo-intermediate-ca-server' for intermediate CA: demo-intermediate-ca
[*] pkictl - Configured policy 'demo-intermediate-ca-pkey' for intermediate CA: demo-intermediate-ca

Obtain a Vault token:

$ vault token create -policy=demo-intermediate-ca-server -ttl=1h

Use this token to obtain a TLS server certificate and private key for web.demo.pkictl.com from the Intermediate CA:

$ vault write demo-intermediate-ca/issue/server common_name=web.demo.pkictl.com ttl=2160h

Alternatively, you can generate a certificate signing request (CSR) and private key locally and have the CSR signed by the Intermediate CA:

$ openssl req -batch -nodes -sha256 -new -newkey rsa:2048 \
  -keyout web.demo.pkictl.com.key -out web.demo.pkictl.com.csr -subj '/CN=web.demo.pkictl.com/'

$ vault write demo-intermediate-ca/sign/server csr=@web.demo.pkictl.com.csr ttl=2160h

Vault will return the signed TLS server certificate along with the full chain (the certificates for the Root and Intermediate CA).

Since spec.type: exported, the private key of this CA has been saved in the KV engine demo-kv-engine. A separate Vault token is required to retrieve it:

$ vault token create -policy=demo-intermediate-ca-pkey -ttl=1m
$ vault kv get -version=1 demo-kv-engine/demo-intermediate-ca

Documentation

For documentation and additional examples, see the docs directory.

Testing

nose2 is used for testing. Tests are located in pkictl/tests.

To run the unit tests:

$ make test

End to end tests requires Vault running locally. To build and run the Vault container:

$ make build-vault-container
$ make run-vault-container

Run the end-to-end tests:

$ make e2e-test

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pkictl-0.1.2.tar.gz (11.0 kB view details)

Uploaded Source

Built Distribution

pkictl-0.1.2-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file pkictl-0.1.2.tar.gz.

File metadata

  • Download URL: pkictl-0.1.2.tar.gz
  • Upload date:
  • Size: 11.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.5.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6

File hashes

Hashes for pkictl-0.1.2.tar.gz
Algorithm Hash digest
SHA256 1c7b5e7c462c159e3ac38f64f41467b283a77d7dc7c01f41d35f1cc6ff02a64f
MD5 99bd42fb43b6ab031e915e83aaa78b06
BLAKE2b-256 c959296d36449ca32ec6ce6dbea29224b99354e40bd3bd8efa9158adb4e6a027

See more details on using hashes here.

File details

Details for the file pkictl-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pkictl-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.5.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6

File hashes

Hashes for pkictl-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5a63d8ded4b9d2220dd20c63eec62bc3b0669e6bd6a512bf79c38c7d1eb55cf7
MD5 4f1ab70fc9cfd49ea202168105fa5842
BLAKE2b-256 ace702d6bc45302f2a34991084d82007240b977c501a0ebb072dec1489f5162a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page