Boundary vault integration - dynamic credential username_templating

Hi,

Regarding to boundary integrate with vault, when boundary credential store configure to use vault token to read the dynamic credentials from db connection in vault, it will pass “token” as user name to vault which configured a username_templating pattern to generate dynamic credential having username as “token_token_xxxxx”. Is there a way to pass user account who actually currently boundary authenticating through oidc method rather that “token” (somehow still be able to read credentials via token, but dynamic credential username-templating taking boundary oidc user account?)

Just trying to figure out how we can track dynamic credentials accessing DB if all user connect to backend db through
“boundary connect --target-id xxxx” as boundary controller will return same pattern of vault dynamic credentials without real user account name, then how to track/audit db activities for those users (even before they being removed after credential expired)?

Can anyone please help with this? Thanks…

Hi @amosc, we’ve added support for templating Vault credential library path information based on user metadata, including account name, to our next release (0.11.1). This should allow you to access targets with user-specific credentials, such as the database example you cited above. You can read more about this feature in our changelog here. Does this satisfy your requirement?

  • Vault Parameter Templating: In vault credential libraries, the paths and any POST bodies can contain templated parameters using Go template syntax (similar to Consul-Template). The following template parameters are supported (note that account values are tied to the account associated with the token making the call):
    • {{ .User.Id }}: the user’s ID
    • {{ .User.Name }}: the user’s name (from the user resource)
    • {{ .User.FullName }}: the user’s name (from the account corresponding to the primary auth method in the user’s scope; this may not be populated or maybe different than the account name in the template)
    • {{ .User.Email }}: the user’s email address (same caveat as FullName)
    • {{ .Account.Id }}: the account’s ID
    • {{ .Account.Name }}: the account’s name (from the account resource)
    • {{ .Account.LoginName }}: the account’s login name (if used by that type of account)
    • {{ .Account.Subject }}: the account’s subject (if used by that type of account)
    • {{ .Account.Email }}: the account’s email (if used by that type of account)Additionally, there is currently a single function that strips the rest of a string after a specified substring; this is useful for pulling an user/account name from an email address. In the following example it uses the account email can be any other parameter:
    • {{ truncateFrom .Account.Email "@" }}: this would turn foo@example.com into foo

0.11.1 will be released imminently but if you need this change earlier you can pilot it from main with the instructions here.

Thanks @PPacent
This will definitely provide more capabilities for us to customise vault credential username templating. That will work for user talk to vault credential libraries via vault cli / vault api through vault oidc auth or vault user auth. But I think my problem is different since we are using Boundary + Vault.

User OIDC auth through Boundary either CLI or desktop client with related permission to access boundary targets ( which configured the connection to target systems such as RDS db on AWS and related dynamic db credentials from vault credential libraries). So the boundary configuration which use a “vault token” boundary_credential_store_vault to talk to Vault server and get back dynamic credential for boundary cli to connect to target DB via boundary worker proxy. The problem is the user talk to vault is always as “token” when vault parameter templating take in rather than “boundary oidc authenticated user account” being passed through somehow.

for example,
I auth log in boundary with “amos.c”, but boundary will still get back dynamic credential with “token” as the user name for vault parameter templating but not “amos.c” which I would like to be part of the result dynamic credential return from vault credential library.

Thanks,
Amos

@PPacent sorry, after read further and have a chat with my colleague, what you mentioned above seems what we are after. Will test it out when it released.

Thanks,
Amos

hi @PPacent,

I have upgrade our boundary to v0.11.1.
What should I pass to http_request_body in order to pass * {{ .Account.Name }}: the account’s name (from the account resource) to vault credential library?

resource "boundary_credential_library_vault" "bar" {
  name                = "bar"
  description         = "My second Vault credential library!"
  credential_store_id = boundary_credential_store_vault.foo.id
  path                = "my/secret/bar" # change to Vault backend path
  http_method         = "POST"
  http_request_body   = <<EOT
{
  AccountName: {{ .Account.Name}} ,  ## ????
 }
EOT
}

based on boundary terraform doc

and then refer that parameter in vault username_templating below?

resource "vault_database_secret_backend_connection" "bc_mysql" {
    for_each = var.bc_mysql
    backend       = vault_mount.database.path
    name          = each.key
    allowed_roles = each.value["allowedRoles"]
    mysql {
        username = each.value["dbUserName"]
        password = each.value["dbPassword"]
        connection_url = each.value["connectionUri"]
        # username_template="{{printf \"%s_%s\" (.DisplayName | replace \"oidc-\" \"\" | replace \"@xxxxxxx.com.au\" \"\") (random 32) | truncate 32 }}"
        username_template="{{printf \"%s_%s\" (.AccountName) (random 32) | truncate 32 }}"
    }
}

I have tested and tried above, but seems not right.

from " (note that account values are tied to the account associated with the token making the call)" → not sure whether I understand properly, this account is the user who oidc authenticate to boundary and make a call with specific vault token to get dynamic credential from vault credential library?

Not sure how exactly the token associated account name pass to the vault username_templating to get back dynamic credential contain the .Account.Name string. Would you please help to give me an example as I cannot find from documentation.

Thanks,
Amos

Hi there,

The account name substitution happens entirely in Boundary; the Vault configuration and any Vault templating is distinct. Your http_request_body looks fine (other than not being valid JSON with the comma there, but I assume that was just for the example). What is the issue you’re having?

Have you verified via a read on the account that the account name associated with the OIDC user is what you expect?

Hi @jeff

yeah, I expect that the account name associated with the boundary OIDC user being passed to Vault username_templating and being substituted during the time boundary get dynamic db credential from Vault database connection.

hi @jeff

When terraform apply for configuration of resource "vault_database_secret_backend_connection" "bc_mysql" . It pops up follow error since .AccountName not being aware of by Vault at all as it doesn’t exist in dbplugin.UsernameMetadata at all.

* error creating database object: invalid username template: unable to apply template: template: template:1:18: executing "template" at <.AccountName>: can't evaluate field AccountName in type dbplugin.UsernameMetadata

so
http_method = "POST" http_request_body = <<EOT { AccountName: {{ .Account.Name}} ## ???? } EOT

“AccountName” field in above example is not correct. It should be a PLACE_HOLD field/fields for vault username_templating function being able to take in value and substitute when boundary_credential_library_vault requesting db dynamic credential via http POST.

There seems no such PLACE_HOLD fields from the Vault username_templating doc.

Hi @amosc ,

What you posted above is TF for Vault, but Boundary doesn’t pass through templated values into Vault, it performs the template substitution first, and then makes the call to Vault with the templated string.

hi @jeff

From what I understand the POST above actually is TF for boundary, that’s post request from boundary_credential_library_vault resource to Vault, isn’t it?

Yeah, at the moment, I didn’t see the feature shows Value has been passed to Vault and can be substituted by username templating.

That’s what I tried to explain above, it might require a PLACEHOLDER with default null value (won’t be substituted during the Vault configuration until if there is PLACEHOLDER field override request from API/CLI call. e.g. vault api call related vault path such as “my/secret/bar” from boundary credential library which pass value into vault and redo the template substitution with override value and response back to boundary with expected templated username.)

resource "boundary_credential_library_vault" "bar" {
  name                = "bar"
  description         = "My second Vault credential library!"
  credential_store_id = boundary_credential_store_vault.foo.id
  path                = "my/secret/bar" # change to Vault backend path
  http_method         = "POST"
  http_request_body   = <<EOT
{
  AccountName: {{ .Account.Name}} ,  ## ????
 }
EOT
}

Thanks,
Amos

Hi @jeff

Would above be a new vault feature to be considered as it is really useful for auditing target systems access by using vault dynamic credentials through boundary connect after boundary connection session expired and vault dynamic credentials expired?

thanks
Amos

1 Like

Hi @amosc,
I am having the exact same issue. No way to correlate the boundary session with the username created by vault. I thought about reading the vault audit logs to get the username but both the username and the password are hashed. Did you figured any way to solve this? I thought this was the hole point of implementing boundary for DB connections.

The best I manage to do so far is getting the audit log from vault to see the request for the username and password but the values are hmac-sha256 encoded. So, not really a solution. Maybe there is another way i am missing on how to accomplish this trace. Maybe @jeff or @PPacent know of a way to accomplish this?

hi @ebarriosjr,

No, I cannot work around with this ATM as the feature doesn’t exist in current release. I am still waiting for @jeff or @PPacent or someone else to consider adding some new futures on vault side to be able to taking extra args for creating dynamic credentials with custom username template.

IMO, from vault audit logs even it doesn’t encrypted, it will just show ‘vault token’ user used by boundary credential library api call to vault db connections in order to read the dynamic db credential. vault connections will always use a separated related db user to talk to back end db instances and provision dynamic db credentials.

If you didn’t use boundary to connect to backend db target, instead using Vault CLI, then you could custom the username_template to including your user account info into dynamic credential from vault db connection tf config.

Cheers,
Amos

I’ve got to be honest, I don’t think I’m really following the issue here. As far as I can tell you want Vault to implement more templating options so that they are available in Boundary? If that’s the case you need to be reaching out on the Vault forum.

Thanks @jeff

Basically yes. It requires vault to implement more templating options in order to passing boundary oidc account name to vault templating from boundary when boundary_credential_library_vault calling vault api to get db dynamic credential.

The issue is boundary_credential_library_vault use a vault token for the api call and templating option using pattern option [auth-method]-[user]_[random characters] (e.g. in above case dynamic credential boundary connect will have token-token_ue1LD0vkDWLaAWJn9jdx to connect to backend target DB. As an administrator I cannot audit who is that user in real world actually access the db). So would like to pass boundary oidc user/account name to vault which can override the [user] option of vault username_templating pattern before dynamic credential generated and returned back to boundary connect response as “username”: “token-amos.c_ue1LD0vkDWLaAWJn9jdx”.

Hope this explain the issue.

I didn’t aware of they are 2 different forum for Vault and Boundary. I thought it’s the same hashicorp forum with different tag to topic for different product. I will post another to Vault forum.

Thanks,
Amos

hi @jeff

Would you mind to send me specific URL for Vault forum I need to post the question in order to avoid from posting on wrong place again?

Thanks,
Amos

Hi @amosc, did you create a ticket on the vault side of the forum? Or are you still waiting on the response from @jeff ? I think the right place would be here: Vault - HashiCorp Discuss

Thanks @ebarriosjr
I have just created a new ticket on Vault discussion here.