Skip to content

Vault agent template render with 'writeToFile' and 'pkiCert’ changes files on disk on every render cycle causing file watchers reloading services #32031

Description

@Viewer4835

Describe the bug
We use the Vault Agent and templates to render TLS-Certificates from Vault Server.

With the following template file:

{{- /* /opt/vault/templates/client_cert.ctmpl */ -}}
{{- with pkiCert "pki/issue/client-cert" "common_name=node1.example.com" "alt_names= node1.example.com, node1.node.consul,service1.service.consul,localhost" "ip_sans=127.0.0.1,192.168.1.1.1" "format=pem" "ttl=168h" -}}
{{- .Cert -}}
{{- if .Key -}}
{{- .Key  | writeToFile "/opt/app/pki/client_cert.key" "app" "app" "0440" -}}
{{- end -}}
{{- end -}}

The cert files are correctly rendered to disk with the correct permissions and owner/group. But when the vault agent checks the cert for renewal it touches the file which is rendered with the writeToFile template function. Causing the modified date to be updated.

Our application uses a FileWatcherService which is watching the certificate files on disk for changes and reloading the app when a change in that files is detected. With the current configuration, see below, this causes a reload every 10 minutes. I’ am not 100% sure but I think this issue was not present before in older vault releases.

We also tried the example template from consul-template docs, and set the template destination to a different file but the behavior is the same:

{{- /* /opt/vault/templates/client_cert.ctmpl */ -}}
{{- with pkiCert "pki/issue/client-cert" "common_name=node1.example.com" "alt_names= node1.example.com, node1.node.consul,service1.service.consul,localhost" "ip_sans=127.0.0.1,192.168.1.1.1" "format=pem" "ttl=168h" -}}
{{ .Cert }}{{ .CA }}{{ .Key }}
{{ .Key | writeToFile "/opt/app/pki/client_cert.key" "app" "app" "0440" }}
{{ .Cert | writeToFile "/opt/app/pki/client_cert.pem" "app" "app" "0440" }}
{{- end -}}
template {
  source      = "/opt/vault/templates/client_cert.ctmpl"
  destination = "/opt/app/pki/cache/client_cert.pem"
  perms = 0440
  user = "app"
  group = "app"
  left_delimiter  = "{{"
  right_delimiter = "}}"
  wait {
    min = "24h"
    max = "72h"
  }
}

To Reproduce
Steps to reproduce the behavior:

  1. Use Vault server and Agent in Version 1.21.4
  2. Configure vault agent to render template with pkiCert and writeToFile
  3. Watch the template destination for changes on disk e.g. watch -n2 'ls -la /opt/app/pki'
  4. On every secret_render_interval (5m by default) the modified timestamp of the files with writeToFile are being updated.

Expected behavior
The files written to disk by the consul-template writeToFile function should not be touched as long there is no need to update them, e. g. in our case the certificate is due to renewal and is being renewed.

Environment:

  • Vault Server Version (retrieve with vault status): 1.21.4
  • Vault CLI Version (retrieve with vault version): Vault v1.21.4 (ffe7023), built 2026-03-04T17:40:05Z
  • Server Operating System/Architecture: Red Hat Enterprise Linux 8 and 9 x86_64

Vault server configuration file(s):

pid_file  = "/var/run/vault-agent.pid"
vault {
  address = https:/vaul.exmple.com:8200
}

auto_auth {
  method {
    type          = "approle"
    config = {
      role_id_file_path = "/opt/vault/roleid"
      secret_id_file_path = "/opt/vault/secretid"
    }
  }
  sink {
    type = "file"
    config = {
      path = "/opt/vault/.token"
      mode = 0600
    }
  }
}

template_config {
  exit_on_retry_failure = true
  static_secret_render_interval = "10m"
}

template {
  source      = "/opt/vault/templates/client_cert.ctmpl"
  destination = "/opt/app/pki/client_cert.pem"
  perms = 0440
  user = "app"
  group = "app"
  left_delimiter  = "{{"
  right_delimiter = "}}"
  wait {
    min = "24h"
    max = "72h"
  }
}

Additional context

I created an auditd rule to see what is happening during rendering of templates:

type=PROCTITLE msg=audit(09.07.2026 12:12:41.480:2196) : proctitle=/usr/bin/vault agent -config=/etc/vault.d/vault.hcl
type=PATH msg=audit(09.07.2026 12:12:41.480:2196) : item=1 name=/opt/app/pki/client_cert.pem inode=5491205 dev=fd:06 mode=file,440 ouid=app ogid=app rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(09.07.2026 12:12:41.480:2196) : item=0 name=/opt/app/pki/ inode=5491216 dev=fd:06 mode=dir,750 ouid=app ogid=app rdev=00:00 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(09.07.2026 12:12:41.480:2196) : cwd=/
type=SYSCALL msg=audit(09.07.2026 12:12:41.480:2196) : arch=x86_64 syscall=openat success=yes exit=10 a0=AT_FDCWD a1=0xc001b7af00 a2=O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC a3=0x1b6 items=2 ppid=1 pid=1984 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=vault exe=/usr/bin/vault
----
type=PROCTITLE msg=audit(09.07.2026 12:12:41.480:2197) : proctitle=/usr/bin/vault agent -config=/etc/vault.d/vault.hcl
type=PATH msg=audit(09.07.2026 12:12:41.480:2197) : item=0 name=/opt/app/pki/client_cert.pem inode=5491205 dev=fd:06 mode=file,440 ouid=app ogid=app rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(09.07.2026 12:12:41.480:2197) : cwd=/
type=SYSCALL msg=audit(09.07.2026 12:12:41.480:2197) : arch=x86_64 syscall=fchownat success=yes exit=0 a0=AT_FDCWD a1=0xc001b7af40 a2=0x1777 a3=0x1777 items=1 ppid=1 pid=1984 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=vault exe=/usr/bin/vault
----
type=PROCTITLE msg=audit(09.07.2026 12:12:41.480:2198) : proctitle=/usr/bin/vault agent -config=/etc/vault.d/vault.hcl
type=PATH msg=audit(09.07.2026 12:12:41.480:2198) : item=0 name=/opt/app/pki/client_cert.pem inode=5491205 dev=fd:06 mode=file,440 ouid=app ogid=app rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(09.07.2026 12:12:41.480:2198) : cwd=/
type=SYSCALL msg=audit(09.07.2026 12:12:41.480:2198) : arch=x86_64 syscall=fchmodat success=yes exit=0 a0=AT_FDCWD a1=0xc001b7af80 a2=0440 a3=0x0 items=1 ppid=1 pid=1984 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=vault exe=/usr/bin/vault

Metadata

Metadata

Assignees

No one assigned

    Labels

    agentbugUsed to indicate a potential bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions