Search code examples
oauthsnowflake-cloud-data-platformhashicorp-vault

How can I manipulate the username attribute included in a Vault Identity Token?


I am trying to set up the following in Hashicorp Vault:

GitHub Actions authenticates to Vault using JWT auth method. Vault creates an Identity Token containing the repo name. Actions can then use this token to authenticate to a Snowflake database, where I've set up Vault as an External OAuth server. The repo name will be used as the username in snowflake.

Here's the role with my token template:

resource "vault_identity_oidc_role" "github_actions" {
  namespace = vault_namespace.namespace.path
  name = "github_actions"
  client_id = "https://mine.eu-north-1.aws.snowflakecomputing.com"
  key  = vault_identity_oidc_key.key.name
  template = <<EOF
{
  "scp": "session:role:${var.snowflake_role}",
  "username": {{identity.entity.aliases.${vault_jwt_auth_backend.github_actions.accessor}.name}}
}
EOF
}

Everything seems like it should work fine. I get a token, it's valid, and Snowflake accepts it. But it tells me the username is "wrong". Testing manually, I found that usernames containing special characters just aren't accepted by snowflake. And using the repository field from GitHub gives me a username like "repo-owner/repo-name" which contains slashes and dashes and whatnot.

I'm thinking that if I can just manipulate this value in the token (replace slashes with "SLASH" or something), I'll end up with a username that Snowflake will accept. Is this possible, and if so, how?


Solution

  • You can tackle this on the JWT auth method.

    The GitHub OIDC documentation shows a sample token that includes the field repository_id, which is simply a number with no problematic characters, so my first thought would be to switch to leveraging that field when creating your aliases.

    If that repository_id field is NOT globally unique, I would create a different JWT Auth Method per GitHub organization that you're supporting. That way, you don't need to have the organization referenced in the alias name to create a unique alias, and the GitHub organization is defined by the location of the auth method mount. (vault auth enable -path="github.com/org-name" jwt might be a reasonable path in this pattern.)

    If that repository_id field IS globally unique, then you only need to switch to that field in the JWT role definition user_claim parameter and you're done.

    Yes, this will make things less user-friendly and more arcane - in order to resolve the repository ID, you'll have to do a GitHub API call, which will make audit log review include additional steps - but I don't see any other point at which you have control over the strings in the auth flow.