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

For review: Vault integration #2039

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

candlerb
Copy link
Contributor

@candlerb candlerb commented Mar 12, 2021

Overview

This is a connector for Hashicorp Vault, just for initial review and comments.

What this PR does / why we need it

This allows Vault roles to be used for Dex authentication. It supports both username/password and OIDC auth roles.

Vault has an interesting story around identity management - see the diagrams in this blog post.

Users are "entities" which can be linked to multiple authentication identities; groups can be assembled from entities, either using internal membership, or external mapping of OIDC claims to groups.

As an example: suppose you have two OIDC sources, let's say Google and Azure AD. Instead of pointing Dex directly at those two sources, you could configure Vault to use those sources (two separate Vault auth mounts), and enable the Dex Vault connector twice for those two auth mounts.

The end result is similar - the user gets to choose between two OIDC sources to login to Dex. However:

  • Dex sub claims are the Vault entity IDs
  • You can link the same user (entity) to a Google account and and Azure AD account. They can login with either, and they will appear as the same sub to Dex [^1]
  • You can create a group in Vault, which contains a mix of individual users from Google and Azure AD, and/or a mix of groups from Google and Azure AD. This is especially useful when using Google without a G-Suite domain.
  • You can manage group membership and entity metadata via the Vault web UI

Special notes for your reviewer

A problem I had is that Vault's OIDC challenge sets its own "state" which is different from Dex's "state".

Since Dex validates the state before calling HandleCallback(), I had to replace the Vault state with the Dex state, and stash the Vault state away somewhere to restore later.

For now, I have done this in a sync.Map. Ideally this state would be stored in the storage backend, because I couldn't find a way to stash data in the authrequest between LoginURL() and HandleCallback(). Maybe the connector API surface needs extending to handle this. (EDIT: raised separately as #2040 / #2041)

Another note: Vault has a rich way of setting metadata on entities. This is crying out for being returned as custom claims, but they're not available in Dex yet (#1182).

Currently, this connector has no Vault token of its own: all Vault API calls are done using the token generated from the user's login process, i.e. under the privileges of the authenticated user. However it might be necessary for the connector to have its own token, in particular if it wants to map group IDs to group names.

Does this PR introduce a user-facing change?

It's a new connector. I realise there's a moratorium on those pending external connectors (#1907) - but hopefully it would be easy enough to extract.


[^1] EDIT: this is not quite true, because the Dex "sub" claim is a combination of the sub and the connector id. So if you make two connector instances, say "vault-azure" and "vault-google", even if both return the same entity ID, the Dex subs will be 1234-abcd vault-azure and 1234-abcd vault-google (plus protobuf and base64 encoding)

connectors:
- type: vault
  id: userpass
  name: Vault (Userpass)
  config:
    vaultURL: https://vault.example.com:8200
    mountType: userpass
    claimMappings:
      email: email_address

- type: vault
  id: google
  name: Vault (Google)
  config:
    vaultURL: https://vault.example.com:8200
    mountType: oidc
    mountPath: google
    claimMappings:
      email: email_address
      preferred_username: ssh_username
      # mapping metadata to group membership
      "?ssh": ssh_username

Signed-off-by: Brian Candler <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants