Using Vault with GitLab OIDC

Posted on Apr 17, 2020

I already had experience using the Github Auth Method for Vault, and it was super easy. As I’ve been playing around with GitLab more (and migrating much of my stuff there), I thought I’d wire up GitLab as an auth method. Should be straightforward and easy, right? Ha!

Part 1: Follow the GitLab Docs

No, really. Just follow the docs. This part is pretty straight forward. It walks you through setting everything up, and the demo works great.

Sweet! I’m off to the races. Going to close this story out in record time. Only one problem… the demo doesn’t actually set up authorization. Any GitLab.com user can log in to your vault and assume the demo role, so you have that going for you.

So, off I set on a quest for OIDC knowledge so that I could actually do something useful.

DISCLAIMER - I knew basically nothing about OIDC when I started off, so this may be boring and/or obvious for people that know more. I, more often than I like to admit, find myself needing somebody (or something) to help connect the dots. Too often in tech, we make people feel dumb. Don’t do that.

Oh, BTW, there’s an issue that has been closed to Make using GitLab auth with Vault easy. I guess it could have been worse…

Part 2: The Secret Sauce

So, I actually want to make a role that does something. My main (and seemingly simple) goal was to map users that had access to a repo or group to a policy. I found the Gitlab OIDC docs. And the Vault ones. Ok, I need to learn about bound_claims… Great!

Turn on OIDC Debug Logging

Just one problem. There’s no actual example of what claims get returned from an OIDC authentication. After pouring through docs for awhile, I figured out how to turn on debug logging for OIDC (NOTE: Don’t do this in production, there will be stuff in your logs that you don’t want in your logs).

  1. Edit your vault config file. Add log_level = "Debug" and restart vault. It should look something like this:
ui = true
log_level = "Debug"

listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
  1. Remember that useless role you created in Part 1? Now we are going to edit it to enable OIDC verbose logging. As a bonus, if anyone random is logging in to your vault, you can see their info ;).
vault write /auth/oidc/role/demo verbose_oidc_logging=true
  1. Log in to vault using the OIDC method. You will generate some logging that is helpful.
vault login -method=oidc role=demo
  1. Grab the magic sauce from your log. You will see a not-so-pretty-printed representation of this:
[DEBUG] auth.oidc.auth_oidc_a1764b20: OIDC provider response: 
claims="{
    
    "aud":"54aaeadfasd654561a5e40eb28c5397cds474173229c7bc946734d0",
    "auth_time":1586905466,"exp":1586961575,
    "groups":[
        "myawesomegroup",
        "myawesomegroup/myawesomesubgroup",
        "anothersuperawesomeproject/anditssubproject"
    ],
    "iat":159875455,
    "iss":"https://gitlab.com",
    "name":"Your Name",
    "nickname":"yourhandle",
    "picture":"https://secure.gravatar.com/avatar/6841e2c5ebed832e8bf3d013a0a659fe?s=80\u0026d=identicon",
    "profile":"https://gitlab.com/yourhandle",
    "sub":"6871632",
    "sub_legacy":"dasf56456651de3df8e27f3a6c2aedff6d879845dasf2744915bb61a"
}"

Great! We actually have some usable info to create a role.

Create a Useful Role

Easy enough, I thought. Now I just need to create a bound_claim based on the groups returned above. Back to the vault docs I went:

bound_claims (map: <optional>) - If set, a map of claims/values to match against. The expected value may be a single string or a list of strings. The interpretation of the bound claim values is configured with

Umm… and how might I represent this mythical map via the CLI? After a whole bunch of unsuccessful attempts, I found this Bug. Hah! I’m not going crazy. It actually doesn’t work via the CLI. Luckily (thanks everyone!) I found a working example. So, without further ado, here’s the SECRET SAUCE.

vault write auth/oidc/role/demo -<<EOF
{
  "allowed_redirect_uris": ["http://localhost:8250/oidc/callback", "https://your.vault.com/ui/vault/auth/oidc/oidc/callback"],
  "user_claim": "sub",
  "bound_audiences": "54aaeadfasd654561a5e40eb28c5397cds474173229c7bc946734d0",
  "role_type" : "oidc",
  "oidc_scopes" : "openid",
  "policies" : "demo",
  "ttl" : "1h",
  "bound_claims" : { "groups": ["myawesomegroup/myawesomesubgroup"] }
}
EOF

You now have a working role that will map any users from myawesomegroup/myawesomesubgroup to the demo policy. Thanks to everyone that left enough crumbs throughout the interwebs to help get this working. Happy vaulting!