Need another pair of eyes to troubleshot Vault provider error

I have below terraform code:

resource "vault_identity_oidc_key" "human" {
  name      = "human"
  algorithm = "RS256"
}

resource "vault_identity_oidc_role" "human" {
  name = "human"
  key  = vault_identity_oidc_key.human.name
}

resource "vault_identity_entity" "yulei" {
  name     = "yulei"
  policies = ["superuser", "human-identity-token-policies"]
  metadata = {
    role = "Sales"
    team = "SalesEngineer"
  }
}

resource "vault_policy" "human-identity-token-policies" {
  name   = "human-identity-token-policies"
  policy = <<EOF
 path "identity/oidc/token/human" {
   capabilities = ["create", "read", "update", "delete", "list", "sudo"]
 }
 EOF
}

resource "vault_identity_entity_alias" "yulei-github" {
  name           = "ausmartway"
  mount_accessor = vault_github_auth_backend.hashicorp.accessor
  canonical_id   = vault_identity_entity.yulei.id
}

resource "vault_identity_entity_alias" "yulei-pki" {
  name           = "yulei"
  mount_accessor = vault_auth_backend.cert.accessor
  canonical_id   = vault_identity_entity.yulei.id
}

#create a signing key for the human identity
resource "vault_identity_oidc_key" "human_identity" {
  name      = "human_identity"
  algorithm = "RS256"
}

#create human role so that it can be used to generate tokens. the token format is defined in the role 
#example of the token format is azp = "spiffe://TRUSTDOMAIN/ENVIROMENT/BUSINESS_UNIT/ENTITY_NAME"

resource "vault_identity_oidc_role" "human_identity" {
  name      = "human_identity"
  client_id = "spiffe://vault"
  key       = vault_identity_oidc_key.human_identity.name
  template  = jsonencode({ "azp" : "spiffe://vault/{{identity.entity.metadata.role}}/{{identity.entity.metadata.team}}/{{identity.entity.name}}" })
}

#allow the human identity to use the role/key to generate identity tokens
resource "vault_identity_oidc_key_allowed_client_id" "hunam_identity" {
  key_name          = vault_identity_oidc_key.human_identity.name
  allowed_client_id = vault_identity_oidc_role.human_identity.client_id
}

terraform plan works but when applying I get below error:

Error: error writing IdentityOidcRole identity/oidc/role/human_identity: Error making API request. URL: PUT https://nginx/v1/identity/oidc/role/human_identity Code: 400. Errors: * error parsing template JSON: invalid character '"' after object key:value pair

with vault_identity_oidc_role.human_identity

on human_identities.tf line 50, in resource "vault_identity_oidc_role" "human_identity":

resource "vault_identity_oidc_role" "human_identity" {

I have spend the whole day troubleshotting this, any help is appreciated.

I am using vault provider 3.25.0 and terraform 1.6.3

Hi @ausmartway,

This error is coming from the Vault API itself rather than from Terraform, and so I’ve moved this question over to the Vault category in the hope that it’ll find folks who are more familiar with Vault.

However, from reading the Vault documentation on this template format it seems like Vault is expecting you to use template substitutions in place of entire JSON values, rather than as part of JSON strings.

Specifically, I think Vault wants you to send it something like this:

{
  "azp": {{identity.entity.metadata.role}}
}

Notice the lack of quotes around the interpolation sequence. I think this interpolation is being replaced by a JSON-encoded string which therefore has its own quotes, and therefore your current template is generating something invalid:

{
  "azp": "spiffe://vault/"something"/"something"/"something""
}

These extra quotes are causing the JSON string to end early as far as Vault’s parser is concerned, and so it therefore misinterprets the next " as the “invalid character” the error message talks about.

Since Vault wants its template syntax instead of plain JSON, I don’t think you can use jsonencode here: that function is only for generating standard JSON, not for generating Vault’s template syntax. Instead I think you will need to write the template out directly, such as using Terraform’s “heredoc template” syntax:

  template = <<-EOT
    {
      "azp": {{something}}
    }
  EOT

The part I’m not sure about is how you would adapt your template that tries to use multiple substitutions as part of a larger JSON string. Since Vault thinks it’s inserting entire JSON values, that seems incompatible with concatenating multiple values together into a single string. Hopefully now that this topic is in the Vault category someone with more Vault knowledge can offer a more concrete suggestion.

1 Like

Thank you, @apparentlymart. Agree with your thinking.

anyway , I have tried different syntax like:

  template = <<-EOT
    {
      "azp": {{something}}
    }
  EOT

and stringfied json:

template = "{\"azp\": \"spiffe://vault/{{something}}\"}"

they all have the same error. I will wait for more response from vault side.