Storing a GCP service account as secret and inject to Kubernetes ("\n" being removed from private key)

Hi everyone,

I’m currently injecting a vault secret in a Kubernetes deployment which consists of a gcp service account.
The secret is correctly mounted in the pod but the content is not what I was expecting.

The service account to be valid needs to contain “\n” in the private key but the secret when deployed Vault removes the “\n”.

Format of a valid key (https://cloud.google.com/iam/docs/creating-managing-service-account-keys.):

{
  "type": "service_account",
  ...
  "private_key": "-----BEGIN PRIVATE KEY-----**\n**private-key**\n**-----END PRIVATE KEY-----**\n**",
  ...
}

I created a vault secret with the sa provided in json format.

vault kv put internal/gcp-creds/config @/tmp/sa.json

vault kv get -field=private_key internal/gcp-creds/config

-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLHTjoBmalopF**\n**ZTSMecA3W9xvFebWStAqzBtWtj

K8s deployment annotation:

...
vault.hashicorp.com/agent-inject-template-sa.json: |
  {{- with secret "internal/gcp.creds/config" -}}
  { 
    ...
    "private_key_id": "{{ .Data.data.private_key_id }}",
    ...
  }
  {{- end -}}

This is how it looks like when you “cat /vault/secrets/sa.json”

{
  "type": "service_account",
  ...

“private_key”: "-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEsdssfddsfdsfdsfAQCzLHTjoBmalopF
ZTSMecfsdfdsfdsfdsffiuEULNnqm23nq4uBKrhDgYOLxs6QDPOeEkYkR
1nE68zrdAgMBAAECggEAAPT10tliCZ9Qsss2BkNvuo9fAEWJYqdzYV73KI

-----END PRIVATE KEY-----
",

As you can see the “\n” were removed and replaced with a real line break.

Does anyone have an ideia how I can sort this one out? I’m using Vault v1.6.2.

Thanks

Hi, Any update on this issue? Were you able to solve this?

The problem in the original poster’s example, is that they are trying to use an injector template to manually format a JSON document. This of course fails when you have characters, like newlines, which ought to be escaped within a JSON value.

The correct approach would be to use a dedicated JSON formatting function:

{{- with secret "..." -}}
{{- .Data.data | toUnescapedJSON -}}
{{- end -}}