[Guide] using Hashicorp Vault to manage PKI and issue certificates

Sufiyan Ghori
Aug 5, 2018 · 11 min read

Vault is an encrypted key-value store, which is designed to solve many challenges that are faced by organisations these days, be it a small startup or an enterprise, they all face some basic issues, one of which is “secret sprawl”, which means that 100s of credentials just ramble around, generated by dozens of different people. This is due to a lack of centralisation of credentials; organisations don’t have a single source where all these credentials originated from.

Another such challenge is “Limited Visibility”; organisations don’t know what certain credentials are being used for? Should it be revoked? Will it break something if revoked? You see, there is very limited visibility on how these credentials are being utilised.

In comes Hashicorp Vault, a centralised key-value store which provides restrictive access to credentials using policies and ACLs. It also acts as a pass-through-encryption, which essentially means that instead of just storing data within Vault, it can return encrypted data to a user, thus providing Encryption as a Service (EaaS) model. Some of Vault’s distinct features that separates it from any other tool in the market are,

  • Dynamic credentials generation using secret backends.
  • Authentication and auditing of each request and response.
  • Credentials having a lease associated with them.

But that’s not all, Vault allows you to manage an entire Public Key Infrastructure (PKI) to ensure secure communication among different services. This allows companies to easily setup their own certificate authority (CA), revoke or issue new certificates using simple API calls, thus dumping the painful process of constantly generating self-signed certificates.

In this guide, I am going to briefly explain how Vault works, how it can be configured, and finally how you can use it to create your own Root CA, issue certificates dynamically thus leveraging Vault’s auth method.

Things covered in this guide:

  • Installing and configuring Vault
  • How vault initialisation works
  • How vault secures itself
  • Creating a Root CA
  • Creating Intermediate CA
  • Issuing a certificate to a Web server

Downloading Vault

Vault pre-compiled binaries can be downloaded from https://www.vaultproject.io/downloads.html The vault binary inside the zip file is all that is necessary to run Vault. Once downloaded, unzip the file,

unzip vault_0.10.4_linux_amd64.zip -d /etc/vault/

Add vault into PATH,

$ echo 'export PATH=$PATH:/etc/vault/' >> ~/.profile$ . ~/.profile

Verify installation,

vault -h

Vault ships with a pre-configured dev mode which doesn’t require any further configuration, and allows room for experimentation. In this mode, Vault runs entirely in-memory and starts unsealed (more on it later) with a single unseal key (It is recommended not to run dev mode in production as it is highly insecure).

To fully utilise Vault’s capabilities, I’ll setup a real vault server which requires a configuration file unlike dev mode. Vault accepts HCL and JSON as its configuration, and must be provided with -config flag. Vault accepts various parameters among which storage and listener are required. storage configures the storage backend where Vault data should be stored, while the latter allows to configure host and a port where Vault listens for API requests. You can explore further optional parameters on Vault configuration page.

So, let’s create a config file with required parameters,

backend "file" {
path = "/home/suf/secrets"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = 1
}

Save above content in config.hcl file, and start vault server,

vault server -config config.hcl

While the server is running, open another terminal, and initialise vault for use:

export VAULT_ADDR='http://127.0.0.1:8200'vault operator init

As soon as the server is initialised, you will see some useful information on your screen, including Unseal Keys, Initial Root Token, etc, as shown below,

Copy this information in a separate file as we are going to use it soon. Now, let’s talk about why this information is extremely important, and why your Vault storage becomes useless if you lose it.

Let me give you a little bit of background. When you first run a Vault server, it starts in a “sealed” state, which essentially means that even though Vault is aware of the location of encrypted storage, and how to access it, it has no knowledge of how to decrypt the data at rest.
It’s kind of a chicken and egg situation, and the question is how Vault should access its own encrypted data? There must be a key that decrypts vault’s entire storage.
So where does Vault store this decryption key? The answer is, nowhere. In fact, vault uses Shamir’s Secret Sharing algorithm which is a form of secret sharing, where an actual key is split into N parts, T of which are required to re-create the original key. These N parts in vault are called “Unseal Keys”, and they are generated when the vault server is initialised.

So, what happened when you initialized a Vault server?

When you first initialised the server using vault operator init command, Vault generated a master key, and immediately split it into 5 key parts, i.e. “Unseal Key 1…5”. That master key was never stored anywhere, and the only way to retrieve that key is to have a quorum of unseal keys re-generate it, as depicted below:

Vault uses Shamir Secret sharing algorithm to create Master key

This master key is used to decrypt the underlying encryption key.

This is an actual message that displays when vault server is first initialised,

Vault initialised with 5 key shares and a key threshold of 3. Please securely distribute the key shares printed above. When the Vault is re-sealed, restarted, or stopped, you must supply at least 3 of these keys to unseal it before it can start servicing requests.

Vault does not store the generated master key. Without at least 3 keys to reconstruct the master key, Vault will remain permanently sealed!

As you can see, 3 Unseal keys are required to unseal Vault before we can access it. If you try to access Vault before unsealing it, you will get Vault is sealed error. Let’s go ahead and unseal the vault using any 3 of 5 unseal keys,

vault operator unseal 5E+rusg+bMYNjLyI/QltN/WBB/uK8IhwjA9lKicLJPiP
vault operator unseal 06w4FpfzNbq4Vid060m4HRNZ4pW/7ijLOuY4aXTRBdCv
vault operator unseal jP2ugbUMy1l2l+kNZQX8yfLtqGS25FVIRnRu4DD+z3PZ
Unsealing Vault

Once unsealed successfully, Login to Vault using the root token you saved earlier. (You can learn more about Root Token here)

vault login

You should receive the following message,

Logging in to vault

Before going any further, we need to learn some basics about vault backends, since this is what we will be using to create a PKI.

Vault Backends

Vault has a concept of backends, you can think of them like plugins that have some specific features. For instance, in our config file, we have used Storage backend called file. Vault has other storage backends available as well, such as; in-mem, consul, mysql, postgresql etc.

Just like storage backends, Vault has “secret backends” which are responsible for managing secrets. Some secret backends simply act like encrypted key-value store, while others dynamically generate secrets when queried. PKI is one such backend, and can manage an entire CA. It is important to note that unlike storage backend, of which you can only have one, multiple PKI backends can be created, and can be isolated from each other using paths. This is necessary in our situation, since we would be creating two PKI backends, one for the Root CA, and the other for Intermediate CA.

We are now equipped to start creating our chain of trust!

Creating Root CA

Before creating a Root CA, we need to enable PKI backend, and mount it at a path,

vault secrets enable -path=rootca_store -description=”PKI backend for Root CA” -max-lease-ttl=87600h pkiSuccess! Enabled the pki secrets engine at: rootca_store/

verify by listing all secret engines,

vault secrets list

-path option mount PKI secret backend at a new path, rootca_store in this case. Each secret engine in vault defines its own path and properties. To the user, secrets engines behave similar to a virtual filesystem, supporting operations like read, write, and delete depending on the permission assigned to them using roles.

Now let’s create our CA Certificate and Key.

/pki/root/generate/:type endpoint is used for generating Root CA. :type in this endpoint specifies the type of the root to create. It can either be exported, in which case the root private key will be returned in the response; or internal, where the private key will not be returned and cannot be retrieved later.

vault write rootca_store/root/generate/internal \
common_name=”suf.com” \
ttl=87600h \
key_bits=4096

To learn about the other options I used, checkout Vault’s PKI docs.

Verify that the Certificate has been generated:

curl -s http://127.0.0.1:8200/v1/rootca_store/ca/pem

Great! You have just created a Root CA.

But wait! We haven’t configured certificate revocation, i.e. CRL or OSCP yet. This must be configured using config/urls endpoint.

Let’s go ahead and configure CRL then:

vault write rootca_store/config/urls issuing_certificates="http://127.0.0.1:8200/v1/rootca_store/ca" \
crl_distribution_points="http://127.0.0.1:8200/v1/rootca_store/crl"

Observe that I have also configured issuing_certificates url, which specifies the value for the Issuing Certificate field. Both issuing_certificates and crl_distribution_points can be an array or a comma-separated string list.

Creating an Intermediate CA

Following steps must be followed in order to generate an intermediate CA:

  • Mount PKI to a new path
  • Generate intermediate certificate signing request (CSR)
  • Sign Intermediate CSR using Root CA and generate Certificate
  • Import Root signed certificate into Intermediate CA
  • Verify signing was successful
  • Configure certificate revocation

Let’s get started!

  • Mount PKI to a new path
vault secrets enable -path=interca -description="PKI backend for Intermediate CA" \
-max-lease-ttl=87600h pki
Success! Enabled the pki secrets engine at: interca/
  • Generate intermediate CSR

Generate certificate signing request, and save it into a file, let’s name it signing_request.csr,

vault write interca/intermediate/generate/internal ttl=26280h key_bits=4096 | grep -zo — "-*BEGIN.*END.*-*$" > signing_request.csr

We need to take that signing request from the intermediate authority and sign it using root CA generated earlier.

  • Sign Intermediate CSR using Root CA and generate a certificate
vault write rootca_store/root/sign-intermediate \
csr=@signing_request.csr \
ttl=8760h \ format=pem_bundle

Save both certificate and issuing_ca in a single file, let’s say mycertreq.crt,

 -----BEGIN CERTIFICATE-----
MIIFhzCCA2+gAwIBAgIUH83a+PyxwgzsZERZHzRR1kwwSc4wDQYJKoZIhvcNAQEL
BQAwEjEQMA4GA1UEAxMHc3VmLmNvbTAeFw0xODA4MDUwMjEyMTJaFw0xOTA4MDUw
MjEyNDJaMAAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNgvwCJIY/
+DxWl34sFz7QaI17ckBcAqv0dQbjH1yFXQ7H9Rt/jx1sUIZ8ErAJZzbSOUCPZWQ8
sMtnvhshptPIlqg7JmCcz6kWQaY1cO9qGaVlFUJunfIbY0l8EJX6LSjN82OskyXk
1PLWWTYS32GqJqCTYXe4ZhUJ3TYSkrJKd8MBGu4IPVaZOxlbsR63S+Gv9e+oIWiS
Y5/Vh07BihHHUJrWjov0ab4e4uhFduQrMsbr8k4q83XeNII4Uq1MzQvf3EK3l6fc
JqQ86NEqi36DBUgIJLb/SmyCoYBY37EQgsmEcOiaDJiaoOT/tfO6IYnhB9B9zEQU
8lOnFD8ULlGdfu/YaxRixKKIYFTzeAU/4YDGRxO5drYIK0uCqC83aZYFZnX9U4cN
5/sxGTIq/5ZkQA11bYCGnFr5OzraRA7kkOxIYOWDuW/cxEhm2O5pRRoZY2Dzi55U
4Y9JS0/Rq+TXveHCLm6gtYsKK8g1dGiMGiiFnOZn6XhAh5TFLTEjFdbi8a5jBzG+
QDi/ApWA+3wHgPhTw2i5ynVOOkq0/Kr+425wd4WAwycKb3m8xPtrZCzO3U4xysHe
W+fV7a363+0aT4ftyRUEZache6Xd7/YTZxoVbr6/aZ+ac+sbU8QeN4S6n7LaUTmB
8DkruOhWu0B+CI4PfevWScwSk4XGu0IKvwIDAQABo4HmMIHjMA4GA1UdDwEB/wQE
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRCLHE6vM3saxmePN8Uc4uu
SdcwRTAfBgNVHSMEGDAWgBQIviOHuu6uxaPbmCpy1riVAmnOkDBEBggrBgEFBQcB
AQQ4MDYwNAYIKwYBBQUHMAKGKGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9yb290
Y2Ffc3RvcmUvY2EwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovLzEyNy4wLjAuMTo4
MjAwL3YxL3Jvb3RjYV9zdG9yZS9jcmwwDQYJKoZIhvcNAQELBQADggIBAFxSk+ZD
09mEtlOR75t5ZOuwsNXnlPAhAiSSioqDtIXYR3/8QhE8PDyiP3ZM6LaCp24QSh8B
MlPPQ4DkVul1ofAGDU7vfk5tCaj8AAPPFp8Dikffw5HFuhDeEa4EYqRWr1uhz+ox
6V177k27FKrL4dAvOu7Hi0cTXC3vahTF25tV8v3GHz1XGlalCUL9IVa7L22a0evN
Cfx9ewRz7fAwEN1mygwC+SBfY/0TlrTb8tlPuMaTZAafS8x4mJuvO9a41sK2i/1K
mn0N8n5sGjh9JJBMEJ4b9jDfwJLB7a91Hv4kGMO7/qyEwl4rQJdMWrBVYkrncSXu
LW1LMeCfzZRecMHZMdwuWwdQzBrIXky96vu1T5iiaBUJPBTcC7aHSfwn0gGQyYaI
kc3Us5RgToZES+SksrcUWBhHVsndme4CGHXiiKHox/HKZE3ctcc+AJq++kUwMb0P
Xp/WyVINjLTjX80YL5Qjf4ROqcCOzQmnF2Yqx+9ujTEEkJ9/ZK56bIUWtq2aVLtz
EKDaBNYD8ss9fizqDWtGKFscObdu7xuNj8VViAqerDhgx/YqOykE8OWhRgxQpNSl
qroZr4Vi2cBPFIB4FdjA6rmFKNE5EEsdF/6df9Lt6+bGhmR9ZlxEmbWMHO+XeFfB
4olsunIOoaF0qAV+BtnzvK4CJVrLo3y7kqE8
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFKTCCAxGgAwIBAgIUdRRhQEOr37CPPjR9PKMMRzZOcLcwDQYJKoZIhvcNAQEL
BQAwEjEQMA4GA1UEAxMHc3VmLmNvbTAeFw0xODA4MDUwMDQ2MThaFw0yODA4MDIw
MDQ2NDdaMBIxEDAOBgNVBAMTB3N1Zi5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQDeqKJ256dW9USAzsKWRxfoLk3oM0/JBosAD4Ab4bt40MiRCSav
i5rqBA0JIDC85N1dQBA73iU0a43D0hGWXY3B9IdzlHR3mPLTBtEtp/bL6Yn6D1dj
cbBSMNjfbyjOCa942IQP4CrDyXkC8XnjRkDmrNLxVXSDOAHnbAePHZaF9U2TMZ3w
olOwkffxFQ/KxEqluVXSKTipZM1FNMN4tjYigoDHHutc2MCP9h9yG8G/PdAKMh+a
quRECkYPbhKJkRaPYeuEec2yc+RWNRE0irfadnRVhjcCDp/TEHDrZlVbgLHjF5g3
gI421qtAHOtPIdDIqFaODJ1rIWHGrVIH9ohEp00T7FTHgqpssuAvIeBcdAfpbcIs
r3VTDOKD/3V9fwzkjLfEqnV/kxyHumDCSD5pAqyVn0nGgPv8a4ayOkh8RUvq9igY
rzkJWck4WXfalTOnDV8BTX7H8GLvZ7CnzPp+jR9miNMhSeq4WCMMIkaGX/yV2U1Q
gMV/UuP5dLHB/PeksAyJGDGjMqTLKlaHe2aRvEjlqvTWpoTglwOYTSC/BmRZbDAX
WKtvjmVVXedOiLQ37q+AGklpJa6GlcGBeqViQKFnEHuUr3aiT26YGGgPGwE4/LXq
HWUonCkrsWAkKdjErxMLs4KxQXSPRJDo17b/Hs3ybtrY8Z9Ddt3Gng+aEQIDAQAB
o3cwdTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
CL4jh7rursWj25gqcta4lQJpzpAwHwYDVR0jBBgwFoAUCL4jh7rursWj25gqcta4
lQJpzpAwEgYDVR0RBAswCYIHc3VmLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEA1YpO
nToJOgNt2UYNRL/p9rxPO7a3eWnqYnH065kt+ygAJUaagVULUWOMGjkO4lAhFbMg
TKn1kzoLWvYAqv5urK8YmIx3G9EitLdX2D7pUU4XvNI0aJwrbVR4fa1zMaFedQJ7
r7ml8gpddArYRbpH3I4PexiYLBUxi2e2sBxpCgBdRI4YQ38jF8W6nso5x+1YLLax
GRj6/NykYYG6ON6t65TMLOQnBqEAEkWxbczmq2LMd8D7ufYBMJg1hChM8KpcD6Sq
5uoD5PaGkeYsdX6Gdd8RtWVDG0bi5hUqvCkxpvXakbOmo4DMc+ww/mc0LL5mlecd
9HX1cs9ZBjJEQ5ADul6GGOpeqxsWdE543OnNsy6HjnXYJhHPbu342c+jlXccCpnA
KfmpZdFU58KYzaHAKudV9PWlyloUk0X3gIqSqHX7bX7/8E3MtTivJKxl9zIaI/YP
EgYHLwZQ10ODi2tlSs1zJ6KYYFyrtVSqdysnTAg2WtH3uFtWOf181VMs3BpgdyUk
6EPbdyluZ27nzA2/OFVECAUwfjVPIx98Y6g1CYa3cTjOMJcmoiNDL6ciptfDDsVt
iePV5Ybos0fUD7/IyUHGSNnvyXDiCrFfTCFdveqiU6vkKj6oPQI2WPIKrZPsymnC
DbUog0VYDpC/M10Dix9s51lfdKyvar7uDuJ6ONw=
-----END CERTIFICATE-----
  • Import Root signed certificate into the Intermediate CA

Now that we have a Root CA signed certificate, we need to import it into our Intermediate CA backend.

vault write interca/intermediate/set-signed \
certificate=@mycertreq.crt
Success! Data written to: interca/intermediate/set-signed
  • Verify signing was successful
curl -s http://127.0.0.1:8200/v1/interca/ca/pem | openssl x509 -text
  • Configure certificate revocation

The last thing we need to do is to set the CA & CRL’s URL just like we did for the Root CA.

vault write interca/config/urls issuing_certificates="http://127.0.0.1:8200/v1/interca/ca" \ crl_distribution_points="http://127.0.0.1:8200/v1/interca/crl"

Our intermediate CA is now configured and ready to issue certificates.

  • Requesting a Certificate for a Web Server

Now that our CA’s are configured, we’d want to issue certificates. Doing so requires two steps:

  • We need to configure a role. A role is a logical name that maps to a policy used to generate those credentials. Our role will define constraints around certificates we generate, such as: key type, strength, types of certificates allowed, etc.
  • We need to request a certificate using the role we created.

roles/:name endpoint allows us to create or update the role definition. Let’s use it to create a role name test_server .

vault write interca/roles/test_server \
key_bits=2048 \
max_ttl=4380h \
allow_any_name=true

Head to Vault’s role documentation to know what other options are available.

Now, we can use this role to issue a certificate,

vault write interca/issue/test_server \
common_name=”your_server_hostname” \
ttl=720h \
format=pem

It will generate a new certificate, and output issuing_ca, and a private key that needs to be used by the relying party (our test_server).

Congratulations, you have just issued your first certificate!

What’s next?

We need to deploy this certificate on a web server, and test it using a local browser.

I will be deploying it on nginx server I created for this guide.

Here is what we are going to do:

  • Save certificate and issuing_ca from the generated certificate in a single file.
  • Save private_key in a separate file
  • Move certificate and private_key to nginx server in /etc/nginx/cert/
  • Configure nginx to use this certificate.

private key generated by certificate saved in /etc/nginx/cert/key :

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxOQ+LLtHQI3/8FJDQOjb1K5fEFER8rJjBEGgFeHYYrXN9kKh
ZfiRVybYgLUXqedn3NJkTANiwlyrRIjW5Dk1qwgA34SlXXEpRubk86Dxpj1s5Mv5
qUA9G1P2PgvBmP02/pBX1blfSLCwUaqx9HHhvimDiNVWWImN5Z7PWNqvqy5ojNmG
akLjTCAVqenpLEWOd7KdCY5u127i6ehMsazzjiYH1YYV0gnlP555Ay/iWXF7nJXJ
If42oO8z0olum2nj+YXE604HDr43sKVyhB1r27fqMvD5GiMHt3RZIWmmstwaOO/m
8aZk2E/LX69x27SE21Szkh6JbYHgbId48LvlOQIDAQABAoIBAQCvvpOI1fm5s4Za
evMxAykF5EdShyqgGX6sk+9S2O6O3XzkbYEnRgJlanUiHYLr03Qv9VQ1TWhf2Nu/
Ju25dR9kdJZi7UG18IZJlVuT43sPShDjAPbujjp9JCrOIyxBZPQrsafVS8uzVJNt
shF6AhTf6qpP/y09hjq0VVb7FuhqwERSyUaKJGLxeKbsQEUnBt8I4ZvGeVXZkgFn
sHZ+F8LVQ7LSwRUdr+jMYSOGni3rhx2YWqGFBqcAlG3mx232BlOWwRXSAb6YzYS3
JlhLjkXxxeBIjFlBtYDbkmp+o3kajEmR41CZwY1uBxyGzca204yyj3L+JHgJlNfv
GCTwrB8hAoGBAMdzS2DIMI/EL/GLQtCJ5PnLvzZeyMFFUsnd7NRRR7YeRCyx/jYO
Q16lav3g583WRgWUTNgoBjAgjAN41adgWMlUI1uHj4kWh/Z6ZPOvou37DpddwHAp
PPRXBvHOsHlnKz7OsL6nhKp5pUJDIor3cIbpaHdqmePgJ3R2WRkbvdy1AoGBAPy3
OTCnq0mxouzli+5oJ+0Lzf2Blky2Wq6nTbmNsmx1mqDYeGQ/O50fAIiR6VLrJOjJ
sf0VIrp480ut0OutoouFfxCMMOa5n20Vv98/TKqIRXd+r75iFPgAyuxP0VN3Bt3k
JZJmQK4ggQU2cpFlLdd1xxC6AFOaVoUvumMMoHz1AoGACMuSxV/OlGhoXNRxS9To
3gMYGYOwgqVV80TwDqTO7r8C7p2iwit62Q+eWjeywSbzy4cwpE+PhkvJINYRReI/
yBEHxh+COt9de4cGMKDMJIZvrEkcFVYcNAIqcjtVGOVtyMVAkge9F+9pVDS1rz8e
HTTpwGpZAu19j+swHqVUiAkCgYBSeEyOhzkLrI+ZtXNL0uusnNyVLRPqZtwDARAJ
TKd8Y4iZkur+8++1X6eh6dP1vkzmNuQBzkLuDYiAGvIB50ETPPZxZP6UXOEdDSr3
ZMXVJPFehJY/j+x93mxaX9XU4hP4l3p3Yy0aZfsUw2bx8c3a8VGMMNbocYZoomG1
7yn0fQKBgQC9BFfo0UdODFyRjALG0OlSThikXAGtXPxfBXI20wZRcOTouXwRy2sm
M4HZVmoIkeuLKewXgbO5MFR5jhlVCz2CZAcY1tPMyjHi0jWnPW/8IVTQfifp7n/s
bsH08+Nh4zmp4VsdXyuyB8Col/FkFc2B5fNRkSP9mExEvaoibOx7ig==
-----END RSA PRIVATE KEY-----

certificate followed by issuing_ca certificate saved in/etc/nginx/cert/ssl_cert :

-----BEGIN CERTIFICATE-----
MIIEbDCCAlSgAwIBAgIUZdZvZtcKcIBMaESNdZnBbDLFA3AwDQYJKoZIhvcNAQEL
BQAwADAeFw0xODA4MDUwMzMyNTBaFw0xODA5MDQwMzMzMjBaMBExDzANBgNVBAMT
BnVidW50dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTkPiy7R0CN
//BSQ0Do29SuXxBREfKyYwRBoBXh2GK1zfZCoWX4kVcm2IC1F6nnZ9zSZEwDYsJc
q0SI1uQ5NasIAN+EpV1xKUbm5POg8aY9bOTL+alAPRtT9j4LwZj9Nv6QV9W5X0iw
sFGqsfRx4b4pg4jVVliJjeWez1jar6suaIzZhmpC40wgFanp6SxFjneynQmObtdu
4unoTLGs844mB9WGFdIJ5T+eeQMv4llxe5yVySH+NqDvM9KJbptp4/mFxOtOBw6+
N7ClcoQda9u36jLw+RojB7d0WSFpprLcGjjv5vGmZNhPy1+vcdu0hNtUs5IeiW2B
4GyHePC75TkCAwEAAaOBzDCByTAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYI
KwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQiuugAzw+S17dbCofdj3WVcZvC
PzAfBgNVHSMEGDAWgBQ2t80LsdTqSoYnYlrRBqk8B0cfEDA/BggrBgEFBQcBAQQz
MDEwLwYIKwYBBQUHMAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9pbnRlcmNh
L2NhMBcGA1UdEQQQMA6CBnVidW50dYcEwKgvhTANBgkqhkiG9w0BAQsFAAOCAgEA
xmI2xYGuOpe+YKr/rKGDvIGURDUGAY0kvxLleE4arSKPOWG11jFlv7+MLl1c14+T
R7CV3+NFsScJoZf6nppecz6O+VSRzbsGqHY2b4LlMmGFrLQJO+VhpqAgG0DGIE60
blkL+IhMOpZLoO9ATjvAMYCKm2rXMgrPHO0PCZwSys9Cti/r0xR7l2fPVYRCcyrp
eHG0UjncbEmZ9ymzz6mi9sC1ICCcgra+UsV9K9ez3C/MKmQN2UkwZd814zS9Gi0Q
JrlxPN+QO1NdToowyT7JpEod615OkaRv8p5LnGsvdNghnmnCpmI3qh0XvexT+yUX
LkHBXX9jWvNL528VXgL59en9EN4lE82/TkwfdTvMEb2YmqqsmklrRTNlJM1UJLYX
a+oO6FoUDGDo3bl7YNh7r0W5huXeHurmP4ZSsn8H2LSYCiVglyUgUjyv8GYPJDLR
b5CiN8LCMJJH7TZ2frX7SKAr/TsqIEK5eFqYG/0rwjihWcBYckvW0ectINeLZC8z
SeDGFG7CeB5LLeLY6V9cPycgMq0uwOANsitCZCEDc3LM9lWg8I73PFvwTxuET+F/
Q1wrGSyAZ6ly8oB8e8pMlxoyjVU7DGU+jiM4xkD2ane5laRKbOtHmlF9rxqUD1lw
wmUdBMdXOMVvd+kNMlv6qv9MH/yHN7RRgjtFQ71Meis=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFhzCCA2+gAwIBAgIUTC8C3fVWCveITXkHOQS+mUcjlcEwDQYJKoZIhvcNAQEL
BQAwEjEQMA4GA1UEAxMHc3VmLmNvbTAeFw0xODA4MDUwMjI3MjdaFw0xOTA4MDUw
MjI3NTdaMAAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDtDiRPdl4T
BFTrK0OS6C4wbr/zMhcPwg1XZEwr57GvaAeDxNK2EB2lgX41d6J+xbdBT/R+Yjg9
FzQX5R97l3Or2J7oV4j6zSYF87hs4gs7aWXkNur9qMuYWU6GEQEOTwv1aF4Uc5NW
wK1W6NbElcFGujRZ0Fv3JnV6G+F/SONE8s8y1jJZCHnsoaQKHHq8xcFnwLOnUVvS
FbHwZoQYdYZHqg4jqovc/Z9sa+lVvLzwpsTDuYe1FBcF9ZLPrTP6QtLwr/9HseF/
kgnqViXGIpRf78tda+F8HGuMGh0I37Z7CU66JX8s3/OcfmUUX6DqHb3oXaLpdPJO
EOhmcds2fhg/Bjhinj0K6f4uomihkfRr1DdOzc8xZ0EEfyuJ66KXZi4XyYvwU1Gm
oua8HTV7fL64zBTawaqEWbqBNPSRiPpJsciSkN8YfVhrYb6LIhWpDmXlW9iD8uyf
wDDMmqUwzQKyHUjsRsSfLfbHWcgKTia/umea9YyJw0IBk8cIL6/QS+FWer5i3689
FJNn9Nw/OeRPxf5gz0eVRRY+URAbPQexgcjvVryHvzpZZGKJbrTGeqdtpel64tZu
aEj6gBorAJ6ooeiHZqgwQ1nXhlcVQv827lUYiY7zUXNq+DB812VtzHlytpo+sIez
+93oPCJmZaG8S3kn02a0dGE8TO8l2Ll0GQIDAQABo4HmMIHjMA4GA1UdDwEB/wQE
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2t80LsdTqSoYnYlrRBqk8
B0cfEDAfBgNVHSMEGDAWgBQIviOHuu6uxaPbmCpy1riVAmnOkDBEBggrBgEFBQcB
AQQ4MDYwNAYIKwYBBQUHMAKGKGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9yb290
Y2Ffc3RvcmUvY2EwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovLzEyNy4wLjAuMTo4
MjAwL3YxL3Jvb3RjYV9zdG9yZS9jcmwwDQYJKoZIhvcNAQELBQADggIBAFnUFAi6
lqkJHPJWXof259nZ/unXjqB39ZApEZY6uy7lrhIo3M/HbWAygZjElNAdk+Ula/79
rWTRSoQu2yl91KnQmIB6ZuaPtgAMpMbm3acAtmrnD7ibZKxSSA3WXb1cQi0b9eFf
wR6uUfZuB7cGgtvT+9p44LpxLHHHzYy1c2AMifArJtR0HmhUZbZy30uHf+kxcSsk
NFsVp3xJLjtL6giZv5hv5TubGo+i4BYFoQ/fOLmI2zo4dFJwHtSRwyxomYl92egH
ZgmRyKjtqNqlmbFfSl3K++M3oAmbTIys9Rel1sSqStUPxmlY0xJi02iN/ClyIdSa
b+Q3ccBQrE9COAhEeV+zgUq4okvE7AOkP8SsJ9a3VhLijjNeb/Migm6Z+Wl6pPbP
uYPOMLfTOTo9NBdFTT9yR9HRSHwdtWhpEX0kuZ5B4eDk586WXkIZWzEw1cEeRAzb
kM9lSuHKo016bwRUNGlVFlDTi+zGUbxfIKD9/tqI8Vw5OkUQI8FTXqLbe5C4XMT3
JTSo3XKneXxuF6fpXe+eUTkU02hwhIJOM1w33riZmf5QoCwTcttDaY3W/5aN8pIs
+r5lPwtKjz5mQWVJT4xDuRs5bfUNjRq+MREVUdORwdtRfEUfb8uMIEuMRX8Wr2kB
Xn8kPbKGYxJhp2A5WVy5/E6DW5DFG6by6syT
-----END CERTIFICATE-----

This is what my nginx.conf looks like,

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 443 ssl default_server;
server_name test_server;
ssl on;
ssl_session_timeout 5m;
ssl_certificate /etc/nginx/cert/ssl_cert;
ssl_certificate_key /etc/nginx/cert/key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Web-server is now using a certificate issued by our own root CA!

Testing

Your Root CA certificate must be available in your local browser to perform authentication.

From vault server, visit and save Root certificate in a file, let’s say root.crt,

curl -s http://127.0.0.1:8200/v1/rootca_store/ca/pem

Then in your local browser (I am using Google Chrome), go to Settings -> click on Advanced at the very bottom of the page, then select Manage certificates ,

Next, click on Import and select the root certificate file you saved earlier, click Next and Finish. You should get the following message:

Now visit your web-server, and you should see that your connection is secure.

Your server is using a certificate issued by your very own Root CA.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade