Skip to content

Vault Certificate Resolver

The Vault certificate resolver allows Traefik Enterprise to use a Vault server with the PKI secret engine enabled as a certificate resolver. This is a brief overview of how to configure Vault PKI. For a more in-depth tutorial, consult the user guide

In order to use the Vault certificate resolver, Traefik Enterprise needs access to a Vault server with the PKI secret engine enabled and set up. You can find more information on how to do so here. Note that the role used by the Vault certificate resolver needs to be configured with at least one of ttl or max_ttl explicitly set.

Once the Vault server is ready, a Vault certificate resolver can be added in Traefik Enterprise's static configuration:

certificatesResolvers:
  resolverName:
    vault:
      url: "http://127.0.0.1:8200"
      auth:
        token: "s.CUDDqqjiIFXF60KVSeJOxeb5"
      namespace: "ns"
      enginePath: "pki"
      role: "vault-role"
[certificatesResolvers.resolverName.vault]
  url = "http://127.0.0.1:8200"
  namespace = "ns"
  enginePath = "pki"
  role = "vault-role"
  [certificatesResolvers.resolverName.vault.auth]
    token = "s.CUDDqqjiIFXF60KVSeJOxeb5"

Next, define a router that references this certificate resolver:

labels:
  - "traefik.http.routers.routerName.rules=Host(`example.com`)"
  - "traefik.http.routers.routerName.tls.certResolver=resolverName"
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: example
spec:
  routes:
    - match: Host(`example.com`)
      kind: Rule
  tls:
    certResolver: resolverName
- "traefik.http.routers.routerName.rules=Host(`example.com`)"
- "traefik.http.routers.routerName.tls.certResolver=resolverName"
"labels": {
    "traefik.http.routers.routerName.rules": "Host(`example.com`)",
    "traefik.http.routers.routerName.tls.certResolver": "resolverName"
}
labels:
  - "traefik.http.routers.routerName.rules=Host(`example.com`)"
  - "traefik.http.routers.routerName.tls.certResolver=resolverName"
http:
  routers:
    routerName:
      rules: "Host(`example.com`)"
      tls:
        certResolver: "resolverName"
[http.routers]
  [http.routers.routerName]
    rules = "Host(`example.com`)"
    [http.routers.routerName.tls]
      certResolver = "resolverName"

Certificates are generated accordingly to the role configuration. This means their maximum time-to-live (TTL) is equal to either the ttl or the max_ttl of the role, whichever has the lowest value.

Once a certificate reaches ⅔ of its lifetime, the Vault certificate resolver tries to renew it. If this operation fails, the old certificate will continue to be served until it expires or another renewal attempt succeeds.

Changing the role's TTL

The Vault certificate resolver regularly verifies if the role configuration has been modified. If the lowest value between ttl and max_ttl is changed, a renewal process starts for all certificates issued by the certificate resolver. This is done so certificates handled by the resolver always reflect the role configuration.

Certificate Resolver Configuration

url

Required, Default=""

Defines the URL of the Vault server, including the scheme and port.

certificatesResolvers:
  resolverName:
    vault:
      url: "http://127.0.0.1:8200"
[certificatesResolvers.resolverName.vault]
  url = "http://127.0.0.1:8200"

tls.caBundle

Optional, Default=""

An optional caBundle containing a PEM-encoded certificate bundle or a path to a file containing the certificate bundle used to establish a TLS connection with the Vault server.

Using a File

Note that TraefikEE does not watch for file changes. If caBundle is set to a file path, its content will be read once when the certificate resolver is initialized but if the file is modified the resolver will need to be restarted to take the latest changes into effect.

providers:
  plugin:
    vault:
      tls:
        caBundle: |-
          -----BEGIN CERTIFICATE-----
          MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
          BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
          Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
          aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
          DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
          EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
          RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
          apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
          Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
          ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
          98TwDIK/39WEB/V607As+KoYazQG8drorw==
          -----END CERTIFICATE-----
providers:
  plugin:
    vault:
      tls:
        caBundle: /etc/tls/ca-bundle.pem
[providers.plugin.vault.tls]
  caBundle = """
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
"""
[providers.plugin.vault.tls]
        caBundle = "/etc/tls/ca-bundle.pem"

tls.cert

Optional, Default=""

An optional cert containing a PEM-encoded certificate or a path to a file containing the certificate used to establish a mTLS connection with the Vault server.

Using a File

Note that TraefikEE does not watch for file changes. If cert is set to a file path, its content will be read once when the certificate resolver is initialized but if the file is modified the resolver will need to be restarted to take the latest changes into effect.

providers:
  plugin:
    vault:
      tls:
        cert: |-
          -----BEGIN CERTIFICATE-----
          MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
          BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
          Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
          aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
          DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
          EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
          RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
          apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
          Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
          ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
          98TwDIK/39WEB/V607As+KoYazQG8drorw==
          -----END CERTIFICATE-----
providers:
  plugin:
    vault:
      tls:
        cert: /etc/tls/cert.pem
[providers.plugin.vault.tls]
  cert = """
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
"""
[providers.plugin.vault.tls]
        cert = "/etc/tls/cert.pem"

tls.key

Optional, Default=""

An optional key containing a PEM-encoded key or a path to a file containing the key used to establish a mTLS connection with the Vault server.

Using a File

Note that TraefikEE does not watch for file changes. If key is set to a file path, its content will be read once when the certificate resolver is initialized but if the file is modified the resolver will need to be restarted to take the latest changes into effect.

providers:
  plugin:
    vault:
      tls:
        key: |-
            -----BEGIN EC PRIVATE KEY-----
            MHcCAQEEIC8CsJ/B115S+JtR1/l3ZQwKA3XdXt9zLqusF1VXc/KloAoGCCqGSM49
            AwEHoUQDQgAEpwUmRIZHFt8CdDHYm1ikScCScd2q6QVYXxJu+G3fQZ78ScGtN7fu
            KXMnQqVjXVRAr8qUY8yipVKuMCepnPXScQ==
            -----END EC PRIVATE KEY-----
providers:
  plugin:
    vault:
      tls:
        cert: /etc/tls/key.pem
[providers.plugin.vault.tls]
  key = """
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIC8CsJ/B115S+JtR1/l3ZQwKA3XdXt9zLqusF1VXc/KloAoGCCqGSM49
AwEHoUQDQgAEpwUmRIZHFt8CdDHYm1ikScCScd2q6QVYXxJu+G3fQZ78ScGtN7fu
KXMnQqVjXVRAr8qUY8yipVKuMCepnPXScQ==
-----END EC PRIVATE KEY-----
"""
[providers.plugin.vault.tls]
        key = "/etc/tls/key.pem"

tls.insecureSkipVerify

Optional, Default=false

Disables TLS certificate verification when communicating with Vault. Useful for testing purposes but strongly discouraged for production.

providers:
  plugin:
    vault:
      tls:
        insecureSkipVerify: true
[providers.plugin.vault.tls]
  insecureSkipVerify = true

token (deprecated)

Deprecated, Default=""

Defines the token to authenticate with Vault.

Deprecated

This option is deprecated, please use auth.token instead.

certificatesResolvers:
  resolverName:
    vault:
      token: "s.CUDDqqjiIFXF60KVSeJOxeb5"
[certificatesResolvers.resolverName.vault]
  token = "s.CUDDqqjiIFXF60KVSeJOxeb5"

namespace

Default=""

Defines the namespace of the Vault PKI secret engine.

certificatesResolvers:
  resolverName:
    vault:
      namespace: "ns"
[certificatesResolvers.resolverName.vault]
  namespace = "ns"

enginePath

Optional, Default="pki"

Defines the path under which the PKI secret engine is enabled.

certificatesResolvers:
  resolverName:
    vault:
      enginePath: "pki"
[certificatesResolvers.resolverName.vault]
  enginePath = "pki"

role

Required, Default=""

The role used to issue certificates.

Role configuration

The role used by the Vault certificate resolver needs to be configured with at least one of ttl or max_ttl explicitly set. These are used to know the maximum time-to-live (TTL) of certificates.

certificatesResolvers:
  resolverName:
    vault:
      role: "vault-role"
[certificatesResolvers.resolverName.vault]
  role = "vault-role"

auth.token

Optional(one of auth.token, auth.appRole or auth.kubernetes must be set), Default=""

Defines the token to authenticate with Vault.

providers:
  plugin:
    vault:
      auth:
        token: "s.CUDDqqjiIFXF60KVSeJOxeb5"
[providers.plugin.vault.auth]
  token = "s.CUDDqqjiIFXF60KVSeJOxeb5"

auth.appRole

Optional(one of auth.token, auth.appRole or auth.kubernetes must be set), Default=None

Enables the AppRole authentication method. See auth.appRole.* options to see what needs to be provided.

auth.appRole.roleID

Required, Default=""

Defines the ID of the role to use when authenticating to Vault with AppRole.

providers:
  plugin:
    vault:
      auth:
        appRole:
          roleID: "4cf1dc0d-f431-f76d-42fd-ed1264f0b893"
[providers.plugin.vault.auth.appRole]
  roleID = "4cf1dc0d-f431-f76d-42fd-ed1264f0b893"

auth.appRole.secretID

Required, Default=""

Defines the ID of the secret to use when authenticating to Vault with AppRole.

providers:
  plugin:
    vault:
      auth:
        appRole:
          secretID: "63cffb45-b404-18c4-cdbb-af723aaef1e7"
[providers.plugin.vault.auth.appRole]
  secretID = "63cffb45-b404-18c4-cdbb-af723aaef1e7"

auth.appRole.path

Optional, Default="approle"

Defines the path under which the AppRole authentication method is enabled in Vault.

providers:
  plugin:
    vault:
      auth:
        appRole:
          path: "customAppRolePath"
[providers.plugin.vault.auth.appRole]
  path = "customAppRolePath"

auth.kubernetes

Optional(one of auth.token, auth.appRole or auth.kubernetes must be set), Default=None

Enables the Kubernetes authentication method. See auth.kubernetes.* options to see what needs to be provided.

auth.kubernetes.path

Optional, Default="kubernetes"

Defines the path under which the Kubernetes authentication method is enabled in Vault.

providers:
  plugin:
    vault:
      auth:
        kubernetes:
          path: "customKubernetesPath"
[providers.plugin.vault.auth.kubernetes]
  path = "customKubernetesPath"

auth.kubernetes.role

Required, Default=""

Defines the Vault role to use. See creating a role for more information.

providers:
  plugin:
    vault:
      auth:
        kubernetes:
          role: "myRole"
[providers.plugin.vault.auth.kubernetes]
  role = "myRole"