项目作者: bincyber

项目描述 :
Declaratively provision PKI with HashiCorp Vault
高级语言: Python
项目地址: git://github.com/bincyber/pkictl.git
创建时间: 2018-10-27T23:44:27Z
项目社区:https://github.com/bincyber/pkictl

开源协议:Mozilla Public License 2.0

下载


pkictl

License
Python
Version
Docker
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:

  1. $ pip install pkictl

Compatibility

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

Usage

  1. $ pkictl --help
  2. declaratively configure PKI secrets in Hashicorp Vault
  3. optional arguments:
  4. -h, --help show this help message and exit
  5. -d, --debug enable debug output
  6. -v, --version show program's version number and exit
  7. subcommands:
  8. init Initializes the Hashicorp Vault server
  9. 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:

  1. $ 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:

  1. ---
  2. kind: RootCA
  3. metadata:
  4. name: demo-root-ca
  5. description: pkictl demo Root CA
  6. spec:
  7. key_type: ec
  8. key_bits: 384
  9. ttl: 17532h
  10. exclude_cn_from_sans: true
  11. subject:
  12. common_name: Demo Root CA
  13. organization: pkictl
  14. ou: README Demo
  15. country: US
  16. locality: San Francisco
  17. province: California
  18. ---
  19. kind: IntermediateCA
  20. metadata:
  21. name: demo-intermediate-ca
  22. description: pkictl demo Intermediate CA
  23. issuer: demo-root-ca
  24. kv_engine: demo-kv-engine
  25. spec:
  26. type: exported
  27. key_type: rsa
  28. key_bits: 4096
  29. ttl: 8766h
  30. subject:
  31. common_name: Demo Intermediate CA
  32. organization: pkictl
  33. ou: README Demo
  34. country: US
  35. locality: San Francisco
  36. province: California
  37. roles:
  38. - name: server
  39. config:
  40. max_ttl: 8766h
  41. ttl: 8766h
  42. allow_subdomains: true
  43. allowed_domains:
  44. - demo.pkictl.com
  45. client_flag: false
  46. server_flag: true
  47. - name: client
  48. config:
  49. max_ttl: 336h
  50. ttl: 336h
  51. allow_any_name: true
  52. client_flag: true
  53. server_flag: false
  54. policies:
  55. - name: demo-intermediate-ca-pkey
  56. policy: |
  57. path "demo-kv-engine" {
  58. capabilities = ["list"]
  59. }
  60. path "demo-kv-engine/demo-intermediate-ca" {
  61. capabilities = ["read"]
  62. }
  63. - name: demo-intermediate-ca-server
  64. policy: |
  65. path "demo-intermediate-ca/issue/server" {
  66. capabilities = ["read", "update"]
  67. }
  68. path "demo-intermediate-ca/sign/server" {
  69. capabilities = ["read", "update"]
  70. }
  71. - name: demo-intermediate-ca-client
  72. policy: |
  73. path "demo-intermediate-ca/issue/client" {
  74. capabilities = ["read", "update"]
  75. }
  76. path "demo-intermediate-ca/sign/client" {
  77. capabilities = ["read", "update"]
  78. }
  79. ---
  80. kind: KV
  81. metadata:
  82. name: demo-kv-engine
  83. description: pkictl demo KV v1 engine
  84. spec:
  85. options:
  86. version: 1

The above example will create:

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

Create PKI secrets from the YAML manifest file:

  1. $ pkictl apply -u https://localhost:8200 -f manifest.yaml
  2. [*] pkictl - the Vault server has been initialized and is not sealed
  3. [*] pkictl - Mounted KV secrets engine: demo-kv-engine
  4. [*] pkictl - Mounted PKI secrets engine: demo-root-ca
  5. [*] pkictl - Generated Root CA: demo-root-ca
  6. [*] pkictl - Mounted PKI secrets engine: demo-intermediate-ca
  7. [*] pkictl - Created intermediate CA: demo-intermediate-ca
  8. [*] pkictl - Signed intermediate CA 'demo-intermediate-ca' with issuing CA: demo-root-ca
  9. [*] pkictl - Set signed certificate for intermediate CA: demo-intermediate-ca
  10. [*] pkictl - Configured URLs for CA: demo-intermediate-ca
  11. [*] pkictl - Set CRL configuration for CA: demo-intermediate-ca
  12. [*] pkictl - Stored private key for 'demo-intermediate-ca' in KV engine: demo-kv-engine
  13. [*] pkictl - Configured role 'server' for intermediate CA: demo-intermediate-ca
  14. [*] pkictl - Configured role 'client' for intermediate CA: demo-intermediate-ca
  15. [*] pkictl - Configured policy 'demo-intermediate-ca-pkey' for intermediate CA: demo-intermediate-ca
  16. [*] pkictl - Configured policy 'demo-intermediate-ca-server' for intermediate CA: demo-intermediate-ca
  17. [*] pkictl - Configured policy 'demo-intermediate-ca-client' for intermediate CA: demo-intermediate-ca

Obtain a Vault token attached to the demo-intermediate-ca-server Policy:

  1. $ VAULT_TOKEN=$(vault token create -policy=demo-intermediate-ca-client -ttl=1h -format json | jq -r .auth.client_token)

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

  1. $ 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:

  1. $ openssl req -batch -nodes -sha256 -new -newkey rsa:2048 \
  2. -keyout web.demo.pkictl.com.key -out web.demo.pkictl.com.csr -subj '/CN=web.demo.pkictl.com/'
  3. $ 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).

Obtain a Vault token attached to the demo-intermediate-ca-client Policy:

  1. $ VAULT_TOKEN=$(vault token create -policy=demo-intermediate-ca-client -ttl=1h -format json | jq -r .auth.client_token)

Use this token to obtain a TLS client certificate and private key from the Intermediate CA:

  1. $ vault write demo-intermediate-ca/issue/client common_name="example@demo.pkictl.com" ttl=24h

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

  1. $ VAULT_TOKEN=$(vault token create -policy=demo-intermediate-ca-pkey -ttl=1m -format json | jq -r .auth.client_token)
  2. $ 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:

  1. $ make test

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

  1. $ make build-vault-container
  2. $ make run-vault-container

Run the end-to-end tests:

  1. $ make e2e-test