Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

username template / dynamic username for role #35

Closed
TJM opened this issue Feb 21, 2023 · 10 comments
Closed

username template / dynamic username for role #35

TJM opened this issue Feb 21, 2023 · 10 comments
Assignees
Labels
enhancement New feature or request

Comments

@TJM
Copy link
Contributor

TJM commented Feb 21, 2023

Enhancement to allow creating a templated/dynamic username instead of a "static" account. Maybe default to something like a prefix-unixtimestamp or whatever (automation-1677017997)?

Backstory

We have had a problem where "someone" (something) was using an expired token, and because all the different namespaces were using the same role, and thus the same "username" that username was being "blocked" by artifactory. So, even if they had the correct token, they were getting a backoff. If each retrieved token had a dynamically created user account, they couldn't affect eachother.

This may also be relevant to #27

@alexhung alexhung self-assigned this Feb 21, 2023
@alexhung alexhung added the enhancement New feature or request label Feb 21, 2023
@TJM
Copy link
Contributor Author

TJM commented Feb 24, 2023

Username Templating: https://developer.hashicorp.com/vault/docs/concepts/username-templating

@alexhung
Copy link
Member

@TJM Can you provide an example of how you envision this is used? Reason I ask is that username isn't an arbitrary thing. It must correspond to a valid user in Artifactory. May be I am missing something (since I'm still relatively green on Vault)?

@TJM
Copy link
Contributor Author

TJM commented Feb 24, 2023

Actually I have that above.. (rolename-UNIXTIMESTAMP). The username does not need to correspond to a valid user in artifactory, they are created dynamically. The group name might need to exist? I need to determine what the "specs" for username are (max length of a dynamic user account, allowed character set, etc).

@alexhung
Copy link
Member

Perhaps I'm conflating Vault username with Artifactory token's username. Sounds like they are not the same thing.

@TJM
Copy link
Contributor Author

TJM commented Feb 24, 2023

https://www.jfrog.com/confluence/display/JFROG/JFrog+Platform+REST+API#JFrogPlatformRESTAPI-CreateToken

  • If the scope includes applied-permissions/user then the token's username must be a valid existing user that is enabled (and not locked or disabled).

We would be using applied-permissions/group:GROUPNAME, but #27 would be using the applied-permissions/USERNAME (cool)

  • Only an admin can set the username for a name that is not the same as the authenticated principal
  • Only an admin can create the token with a group's scope.

This is fine. I think we could get by with documentation for this, rather than "verifying" the admin token's scope.

Also:

The username is then used to set the subject of the token: <service-id>/users/<username>
Limited to 255 characters.

@alexhung
Copy link
Member

alexhung commented Feb 24, 2023

I'm very familiar with that API and its intricacies 😄

If the scope includes applied-permissions/user then the token's username must be a valid existing user that is enabled (and not locked or disabled).

This is what I'm referring to as the username must correspond to an existing user in Artifactory.

Can you please provide an end-to-end example (vault cli, vault info, artifactory user data?) to illustrate what you are proposing? These contradictory requirements are not clear to me at all.

For example, I attempted to create a token for an user foobar who doesn't exist in my local Artifactory and this is the error message I received:

{
    "error": "invalid_request",
    "error_description": "requested username does not exists or not enabled. username [foobar] user status [DOES NOT EXISTS]"
}

@TJM
Copy link
Contributor Author

TJM commented Feb 27, 2023

@TJM
Copy link
Contributor Author

TJM commented Feb 27, 2023

Sorry, my last comment was just some docs that were apparently saved in my browser instead of being submitted?

to respond to your last comment...

I am suggesting that we create a group scoped token, such as:

scope=applied-permissions/group:readers ... then you can set username=whatever-you-want-up-to-256-chars, and it should create a token with a dynamic (?) (not created in the user database) for it.

Example:

[tmcneely@local artifactory-secrets-plugin]$ curl -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:8082/access/api/v1/tokens -d "scope=applied-permissions/groups:readers" -d "username=whatever-you-want-up-to-256-chars"
{
  "token_id" : "0fe0cff5-8e12-43b4-b3c6-4a88d3584707",
  "access_token" : "eyJ2ZXIiOiIyIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYiLCJraWQiOiJZZjFINmx6SEdhWlcya2NPZGZxdUpCYTY1N2JfamVZcDRraE10NHFEQVBjIn0.eyJleHQiOiJ7XCJyZXZvY2FibGVcIjpcInRydWVcIn0iLCJzdWIiOiJqZmFjQDAxZ3QwOTl4OWptZGRyMGFhYWgwYjkwMGhtXC91c2Vyc1wvd2hhdGV2ZXIteW91LXdhbnQtdXAtdG8tMjU2LWNoYXJzIiwic2NwIjoiYXBwbGllZC1wZXJtaXNzaW9uc1wvZ3JvdXBzOnJlYWRlcnMiLCJhdWQiOiIqQCoiLCJpc3MiOiJqZmFjQDAxZ3QwOTl4OWptZGRyMGFhYWgwYjkwMGhtIiwiaWF0IjoxNjc3NTMwNDIyLCJqdGkiOiIwZmUwY2ZmNS04ZTEyLTQzYjQtYjNjNi00YTg4ZDM1ODQ3MDcifQ.MhSgut0w6emAgPILIh7R6q5FEUnQj4hcnpJw5oOXbjdprHW7W07OXtawTZWA5d0KwmtIOu8v1zt3ByCStmrFSNuZDJY-oy2V0-6cyGXCadn0N6q65FXliRw7Cz79rq-V0S0f5h5CmVtMiyiyv_4t1RlmPNvjVOJlKfnHzBJIa2kqts-8C0lblF5yb4UHSxaKm6GRSKv2kdcugnLxfGamBUGblZM2RYlGTRo2c8-HVMWhBaqyVmruEq2tIdUa6wJl9r0GaQYtnVyqCm6hBcPmhWKcjCnFd5D7Oq4Uj5NIJXI3t_RcFoN1iaooglYZjsZC2OcPrKphT-3GSy-1lp7-vw",
  "scope" : "applied-permissions/groups:readers",
  "token_type" : "Bearer"
}
[tmcneely@local artifactory-secrets-plugin]$ jwt decode eyJ2ZXIiOiIyIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYiLCJraWQiOiJZZjFINmx6SEdhWlcya2NPZGZxdUpCYTY1N2JfamVZcDRraE10NHFEQVBjIn0.eyJleHQiOiJ7XCJyZXZvY2FibGVcIjpcInRydWVcIn0iLCJzdWIiOiJqZmFjQDAxZ3QwOTl4OWptZGRyMGFhYWgwYjkwMGhtXC91c2Vyc1wvd2hhdGV2ZXIteW91LXdhbnQtdXAtdG8tMjU2LWNoYXJzIiwic2NwIjoiYXBwbGllZC1wZXJtaXNzaW9uc1wvZ3JvdXBzOnJlYWRlcnMiLCJhdWQiOiIqQCoiLCJpc3MiOiJqZmFjQDAxZ3QwOTl4OWptZGRyMGFhYWgwYjkwMGhtIiwiaWF0IjoxNjc3NTMwNDIyLCJqdGkiOiIwZmUwY2ZmNS04ZTEyLTQzYjQtYjNjNi00YTg4ZDM1ODQ3MDcifQ.MhSgut0w6emAgPILIh7R6q5FEUnQj4hcnpJw5oOXbjdprHW7W07OXtawTZWA5d0KwmtIOu8v1zt3ByCStmrFSNuZDJY-oy2V0-6cyGXCadn0N6q65FXliRw7Cz79rq-V0S0f5h5CmVtMiyiyv_4t1RlmPNvjVOJlKfnHzBJIa2kqts-8C0lblF5yb4UHSxaKm6GRSKv2kdcugnLxfGamBUGblZM2RYlGTRo2c8-HVMWhBaqyVmruEq2tIdUa6wJl9r0GaQYtnVyqCm6hBcPmhWKcjCnFd5D7Oq4Uj5NIJXI3t_RcFoN1iaooglYZjsZC2OcPrKphT-3GSy-1lp7-vw

Token header
------------
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "Yf1H6lzHGaZW2kcOdfquJBa657b_jeYp4khMt4qDAPc"
}

Token claims
------------
{
  "aud": "*@*",
  "ext": "{\"revocable\":\"true\"}",
  "iat": 1677530422,
  "iss": "jfac@01gt099x9jmddr0aaah0b900hm",
  "jti": "0fe0cff5-8e12-43b4-b3c6-4a88d3584707",
  "scp": "applied-permissions/groups:readers",
  "sub": "jfac@01gt099x9jmddr0aaah0b900hm/users/whatever-you-want-up-to-256-chars"

@davidcorrigan714
Copy link
Contributor

davidcorrigan714 commented Feb 28, 2023

Trying to understand the root problem here as I think we're going to be doing something similar. Essentially having CI/CD processes assume "roles" in JFrog (ie group) after logging into Vault with the CI/CD pipeline's OIDC tokens (yay secret-free authentication!). In our proof-of-concept I'm constructing the roles through terraform with something like this:

locals {
  jfrog_group_roles = [
    "rnd-pipelines-pre",
    "rnd-pipelines-prod",
    "it-pipelines-pre",
    "it-pipelines-prod",
  ]
}

resource "vault_generic_endpoint" "artifactory_group_roles" {
  depends_on = [
    module.plugins.secret_mounts
  ]

  for_each             = { for group in local.jfrog_group_roles : group => group }
  path                 = "artifactory/roles/${each.key}"
  ignore_absent_fields = true

  data_json = jsonencode({
    username = each.key
    scope    = "applied-permissions/groups:${each.key}"
    # 43200 seconds = 12 hours. Vault will accept '12h' but show a diff
    # because it uses seconds when returning the current state
    default_ttl = 43200
    max_ttl     = 43200
  })
}

In this case the "username" of the token is just the role name, would this end up hitting rate limits as described in the ticket if too many pipelines assumed the same role simultaneously?

@TJM
Copy link
Contributor Author

TJM commented Mar 20, 2023

Closed by #47

@TJM TJM closed this as completed Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants