Vault X.509 證書管理

DEC 06 2018 CHRISTIE KOEHLER

In this blog post, we’ll look at practical public key certificate management in Vault, which uses a dynamic secrets approach.

HashiCorp Vault provides secrets management and protection of sensitive data. It provides a central place to secure, store, and control access to tokens, passwords, certificates, and encryption keys. There are challenges of centralized secrets management, particularly related to applications. Applications don’t keep secrets and secrets are often shared among different applications.

Vault presents an answer to these problems in the form of dynamic secrets. A dynamic secret is generated on demand and is unique to a client. This is opposed to a static secret, which is defined ahead of time and is often shared by different clients. Vault associates each dynamic secret with a lease and automatically destroys the credentials when the lease expires. Static secrets, by contrast, often have much longer lifecycles.

Dynamic secrets allows us to manage intentions (e.g. web server needs database access) instead of a managing credentials (e.g. authentication data provided to web servers requiring database access). This allows us to achieve the same end goal while solving major challenges, including leaky applications, non-repudiation, automatic rotation, and practical revocation. See Why We Need Dynamic Secrets for more details.

Vault applies a dynamic secret approach to public key certificates as well, acting as a signing intermediary to generate short lived certificates. This allows certificates to be generated on-demand, as needed, and rotated automatically.

In this post we’ll look at the most common operator activities involved in certificate management using Vault. We’ll cover:

  • Enabling and Configuring PKI engine(s).
  • Creating roles and generating certificates.
  • Revoking certificates and updating Certificate Revocation Lists (CRLs).
  • Integrating with applications.

Enabling and configuring the PKI engine(s)

Vault supports many secrets engines. To use a secrets engine, you enable it at a given path or mount point. After installing and configuring Vault, you’ll need to enable and configure the PKI secrets engine.

$ vault secrets enable pki
Success! Enabled the pki secrets engine at: pki/

The default is for engines to be enabled at a path named for their type (e.g. pki for the PKI engine, as seen above). With few exceptions, secrets engines can be enabled at multiple paths by enabling each with a unique name. Enabled secrets engines cannot see each other’s data, even if they are of the same type.

To specify a mount point, use the -path argument when enabling the engine.

For example, to create a second PKI secrets engine to act as your intermediate signing authority, you would do the following, after creating the first engine pki above:

$ vault secrets enable -path=pki-inter pki
Success! Enabled the pki secrets engine at: pki-inter/

To issue commands to this instance of the secrets engine, you’ll need to use the pki-inter prefix rather than pki. For example: vault write pki-inter/config/ca instead of vault write pki/config/ca.

Adjust Global TTL

Often it also makes sense to adjust the global maximum time-to-live (TTL) of tokens and leases for this secrets engine. The default is 30 days which might be too short. Individual roles can restrict this value to be shorter on a per-certificate basis.

Here’s how to adjust the TTL to one year:

$ vault secrets tune -max-lease-ttl=8760h pki
Success! Tuned the secrets engine at: pki/

You’ll need to do this for each PKI engine you’ve enabled.

Configure Root and/or Intermediate CAs

Each PKI secrets engine must be configured with a CA certificate and associated private key.

There are three methods for accomplishing this:

  • generate a self-signed root CA
  • generate an intermediate CA (with a Certificate Signing Request, CSR, for signing)
  • set a PEM-encoded certificate and private key bundle directly into the backend

You’ll also need to configure a root CA. You can have Vault generate a self-signed root CA or provide the details for your root CA. There are separate end points for each.

To generate a self-signed root CA, use the pki/root/generate endpoint:

$ vault write pki/root/generate/internal \
    common_name=my-website.com \
    ttl=8760h

To generate an intermediate CA, use the /pki/intermediate/generate/ endpoint:

$ vault write pki/intermediate/generate/internal common_name=example.com data=@pem_bundle.json

To set a PEM-encoded certificate and private key bundle, use the pki/config/ca endpoint:

$ vault write pki/config/ca pem_bundle=@pem_bundle.json

Only one CA certificate is allowed per secrets engine. If you want to issue certificates from multiple CAs, mount the PKI secrets engine at multiple mount points with separate CA certificates in each.

A common and recommended pattern is to have one mount act as your root CA and to use this CA only to sign intermediate CA CSRs from other PKI secrets engines. See Build Your Own Certificate Authority (CA) on HashiCorp Learn or our webinar Streamline Certificate Management for further details.

Configure URL values for issue certificate endpoints

For each PKI engine that you enable you’ll need to configure the url values for issuing certificate endpoints and CRL distribution points that will be encoded into issued certificates:

$ vault write pki/config/urls \
    issuing_certificates="http://127.0.0.1:8200/v1/pki/ca" \
    crl_distribution_points="http://127.0.0.1:8200/v1/pki/crl"
Success! Data written to: pki/config/urls

Creating roles and generating certificates

Generating certificates requires you to supply a role. The role definition sets the conditions under which a certificate can be generated.

Use the /pki/roles/:name endpoint to create and update roles:

$ vault write pki/roles/example-dot-com \
    allowed_domains=example.com \
    allow_subdomains=true max_ttl=72h
Success! Data written to: pki/roles/example-dot-com

The roles endpoint accepts a number of parameters and nearly any issuing policy can be accommodated. If a client requests a certificate that is not allowed by the role, the request is denied.

Once a role has been created, you can use it to generate certificates with the pki/issue endpoint:

$ vault write pki/issue/example-dot-com \
    common_name=my.example.com
Key                 Value
---                 -----
certificate         -----BEGIN CERTIFICATE-----

A certificate can be renewed at any time by providing issue with the same common name as an existing certificate. The original certificate will continue to be valid through its original time-to-live unless explicitly revoked.

Revoking certificates and rotating CRLs

If a certificate must be revoked, you can easily perform the revocation action which will cause the CRL (Certificate Revocation List) to be regenerated. When the CRL is regenerated, any expired certificates are removed from the CRL.

$ vault write pki/revoke serial_number=<serial_number>

Operators can also trigger rotation of the CRLs directly with the pki/crl/rotate endpoint. Because this end point doesn’t ingest any data, you’ll need to use the vault read command instead of write:

$ vault read pki/crl/rotate
Key        Value
---        -----
success    true

As with all Vault commands, you can also interact with the API directly, as such:

$ curl \
    --header "X-Vault-Token: ..." \
    http://127.0.0.1:8200/v1/pki/crl/rotate

There’s also the Vault UI, available in version 0.10+, as well as Vault Enterprise.

Using the tidy endpoint, operators can optimize the storage backend and CRL by periodically removing certificates that have expired and are past a certain buffer period beyond their expiration time.

$ vault write pki/tidy tidy_cert_store=true tidy_revoked_certs=true

Integrating with applications

Already you can see how generating PKI certificates with Vault saves operators time. A single call to the Vault API replaces the tedious process of generating a private key, generating a CSR, submitting to a CA, and then waiting for a verification and signing process to complete.

To automate the process further, use a template rendering tool such as Consul Template.

Consul Template is a daemon that queries a Consul or Vault cluster and updates any number of specified templates on the file system. Rendering templates requires both a template file and a template configuration. Template files are written in the Go Template format and the configuration files are in HCL. (See Consul Template’s README.md for further documentation.)

When generating PKI certificates with Vault, the certificate, private key, and any intermediate certs are all returned as part of the same API call. Most applications require that this data be placed in separate files on the system.

Here are the templates we can use to retrieve the necessary certificate files and save them locally:

{{- /* /tmp/cert.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.certificate }}{{ end }}

{{- /* /tmp/ca.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.issuing_ca }}{{ end }}

{{- /* /tmp/key.tpl */ -}}
{{ with secret "pki/issue/example-dot-com" "common_name=my.example.com" }}
{{ .Data.private_key }}{{ end }}

The with secret directive queries Vault at the supplied API endpoint (“pki/issue/example-dot-com”) with the given parameters (“common_name=my.example.com”). This is equivalent to the Vault command we showed earlier for generating certificates: vault write pki/issue/example-dot-com.

Consul Template writes the data returned by Vault into .Data.certificate, .Data.issuing_ca, and .Data.private_key, which directly correspond to the data returned by the Vault API:

{
...
  "data": {
    "certificate": "-----BEGIN CERTIFICATE-----",
    "issuing_ca": "-----BEGIN CERTIFICATE-----",
    "private_key": "-----BEGIN RSA PRIVATE KEY-----",
    ...
    },
}

In this example, there are three different input templates. But, when run under the same Consul Template process, they are compressed into a single API call, sharing the resulting data.

Here is an example the corresponding Consul Template configuration:

template {
  source      = "/tmp/cert.tpl"
  destination = "/opt/my-app/ssl/my-app.crt"
}

template {
  source      = "/tmp/ca.tpl"
  destination = "/opt/my-app/ssl/ca.crt"
}

template {
  source      = "/tmp/key.tpl"
  destination = "/opt/my-app/ssl/my-app.key"
}

Use multiple template blocks to define multiple templates. The source directive indicates which source file on disk to use as the input template. The destination directive indicates the path on disk where the source template will render.

Note: Please always consider the security implications of having the contents of a secret in plain-text on disk. If an attacker is able to get access to the file, they will have access to plain-text secrets.

Consul Template will fetch a new secret at half the lease duration of the original secret. For example, the role we created above has a max_ttl=72h. Because we did not specify a ttl when we created our certificate with vault write pki/issue/example-dot-com, it will have a lease of 72 hours. This means Consul Template will renew the secret, which in the case of certificates means generating a new one, every 36 hours. However, because Vault does not support blocking queries, Consul Template will not immediately reload in the event a secret is changed as it does with Consul's key-value store.

For more examples of using Consul template, see the examples directory in the project.

Next Steps

To learn more, see:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涡尘,一起剝皮案震驚了整個濱河市荷科,隨后出現(xiàn)的幾起案子户辫,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡而克,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門怔毛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來员萍,“玉大人,你說我怎么就攤上這事拣度∷橐铮” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵蜡娶,是天一觀的道長混卵。 經(jīng)常有香客問我,道長窖张,這世上最難降的妖魔是什么幕随? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮宿接,結(jié)果婚禮上赘淮,老公的妹妹穿的比我還像新娘。我一直安慰自己睦霎,他們只是感情好梢卸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著副女,像睡著了一般蛤高。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碑幅,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天戴陡,我揣著相機(jī)與錄音,去河邊找鬼沟涨。 笑死恤批,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裹赴。 我是一名探鬼主播喜庞,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼棋返!你這毒婦竟也來了延都?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤睛竣,失蹤者是張志新(化名)和其女友劉穎窄潭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫉你,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年月帝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幽污。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡嚷辅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出距误,到底是詐尸還是另有隱情簸搞,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布准潭,位于F島的核電站趁俊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刑然。R本人自食惡果不足惜寺擂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泼掠。 院中可真熱鬧怔软,春花似錦、人聲如沸择镇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腻豌。三九已至家坎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吝梅,已是汗流浹背虱疏。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留憔涉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓析苫,卻偏偏與公主長得像兜叨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子衩侥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容