While working on my osquery-file-carve-server project I determined my application needed authentication. However, I didn’t want to pigeon hole my application to a single platform/service for authentication. After some research, I decided to implement support for Vault into my application because it provides the ability for users to authenticate using various methods. However, during my research, I had a hard time understanding how the various Vault components connected to create this functionality.
This blog post will provide an understanding of the Vault components used to implement this functionality. In addition, it will demonstrate the relationship between the various Vault components: authentication backends, entities, groups, and policies. The final result of combining these Vault components is a system that can authenticate a single user using different authentication services.
DISCLAIMER
This blog post is a proof of concept (POC) for a homelab and does NOT implement best practices for an enterprise environment. Please review the Hashicorp Vault documentation for best practices.
DISCLAIMER
Goals
- Setup Vault to use Auth0 and Github as auth backends
- Use Auth0 OR Github to generate a Vault token
- Understand the relationship between auth backends, policies, groups, and entities
Background
Vault components?
- Policies – Defines what an entity can do – create, read, modify, delete
- Auth backend – A service that can authenticate users
- Entities – An entity ties different user accounts from different auth backends to a single entity. For example, my Auth0 username is “bbornholm” but my Github username is “CptOfEvilMinions”. In either case, the account is still ME, just a different platform and/or username. Entities tie of all these different auth services and usernames together as a single object.
- Groups – A group makes all this magic come together. Not only is a group a collection of entities ( users and auth backends) but an assignment of policies that defines what each entity can perform.
Diagram of relationships
The diagram above shows the relationships between policies, groups, entities, and authentication backends. At first, none of this made sense until I was able to map these relationships. In this blog post, I have three user accounts on three separate authentication backends which are Auth0, Github, and LDAP. All of these accounts are ME but I have three different usernames on three different platforms. An entity provides a layer of abstraction that says this entity can be associated with the following user account on its respective platform.
By default, the default policy on Vault provides common permissions – if a policy does not contain a rule to allow an action, the default action is to DENY. In order to allow a user to perform an action such as reading a secret, a policy must be created explicitly allowing that action. Next, a group is created which is a collection of entities and policies. The group provides a union of policies and entities, allowing the entities within the group to perform predefined actions within the policies on the Vault platform.
In this blog post scenario, we are going to create an entity with a friendly name of “bbornholm”. The entity “bbornholm” can utilize the following user accounts: the “thunderwagon” account from Auth0, the “CptOfEvilMinions” account from Github, or the “bbornholm2194” account via LDAP to login. Next, we will create a policy named “test-read-only” that contains a set of rules to allow READ
ing and LIST
ing all secrets from the following path secrets/hello
.
By default since the policy does not explicitly allow DELETE
, UPDATE
, or, CREATE
; therefore, these actions are blocked by default. Lastly, the entity “bbornholm” and our policy “test-read-only” will be applied to a group named “test-group”. This step connects policies and entities together to allow entities to perform the actions set by the policies.
Setup/Configure Vault
Step 0: Spin up Vault with Docker
This blog post assumes you have Vault setup, if you do not, take a look at my blog post: Install/Setup Vault for PKI + NGINX + Docker – Becoming your own CA.
git clone https://github.com/CptOfEvilMinions/BlogProjects
cd BlogProjects/vault-entities-groups-auths
Step 1: Create some SUPER DUPER secrets
export VAULT_ADDR=https://<Vault hostname>:<port>
vault login
- Login as root
vault secrets enable -path=secrets kv
- Enable KV secrets engine
vault kv put secrets/hello target=world
- Create a secret
vault kv get secrets/hello
- Query secret
Step 2: Create policies
vault policy write <POLICY_NAME> <POLICY_FILE>
- Create a read-only policy
-
vault policy write <POLICY_NAME> <POLICY_FILE>
- Create an admin policy
vault policy list
- Lists policies
vault policy read <POLICY_NAME>
Step 2: Setup Github for auth backend
vault auth enable github
vault write auth/github/config organization=<ORG_NAME>
- Enable Github auth for the specified Github org
Step 3: Setup FreeIPA(LDAP) for auth backend
vault auth enable ldap
vault write auth/ldap/config \
url="ldap[s]://ldap.example.com" \
userdn="cn=users,cn=accounts,dc=example,dc=com" \
userattr="uid" \
insecure_tls=<true/false> \
starttls=<true/false> \
groupdn="cn=groups,cn=accounts,dc=example,dc=com" \
groupattr="cn" \
binddn="uid=<BIND_USERNAME>,cn=sysaccounts,cn=etc,dc=example,dc=com" \
bindpass="<BIND_PASSWORD>"
Step 3: Create/Setup Auth0 for auth backend
Create Application
- Create an Auth0 account if you don’t already have one
- Login in to your Auth0 account as an admin
- Select “Applications” on the left
- Enter a name for the app
- Select “Native” for type
- Select “Create”
- Select the “Settings” tab
- Enter the following URLs below into the “Allowed Callback URLs” section
https://<vault_server_address>:8200/ui/vault/auth/oidc/oidc/callback
- URLs must be separated by a comma
https://<vault_server_address>:8250/oidc/callback
- Copy the domain value
- Copy the client ID value
- Select “Save changes”
Create a user (optional)
- Select “Users & Roles” on the right
- Select “Create user +”
- Enter e-mail for the user
- Enter password
- Select “Username-Password-Authentication” for Connection
- Select “Create”
Enable Auth0 on Vault
export AUTH0_DOMAIN="<Auth0 domain>"
export AUTH0_CLIENT_ID="<AUTH0_CLIENT_ID>"
export AUTH0_CLIENT_SECRET="<AUTH0_CLIENT_SECRET>"
vault auth enable oidc
vault write auth/oidc/config oidc_discovery_url="https://<AUTH0_DOMAIN>/" oidc_client_id="<AUTH0_CLIENT_ID>" oidc_client_secret="<AUTH0_CLIENT_SECRET>" default_role="reader"
- The
oidc_discovery_url
value needs a trailing “/”
- The
vault write auth/oidc/role/reader bound_audiences="<AUTH0_CLIENT_ID>" allowed_redirect_uris="http://<VAULT_HOSTNAME>:<VAULT_PORT>/ui/vault/auth/oidc/oidc/callback"
user_claim="sub" policies="reader"
Step 5: Create an entity
vault auth list
- Get accessor IDs for each auth backend
- Copy Accessor IDs for each auth backend
vault write identity/entity name="<entity username>" policies="<POICY_NAME>" metadata=organization="<ORG_NAME>" metadata=team="<TEAM_NAME>"
- Create an entity with metadata contain org name and team name
vault write identity/entity-alias name="<LDAP USERNAME>" canonical_id="<ENTITY_ID>" mount_accessor="<LDAP access ID>"
- Add the LDAP user account to the entity as an alias
vault write identity/entity-alias name="<GITHUB_USERNAME>" canonical_id=<ENTITY_ID> mount_accessor=<GITHUB_ACCESSOR_ID>
- Add the Github user account to the entity as an alias
vault write identity/entity-alias name="<AUTH0_USERNAME>" canonical_id=<ENTITY_ID> mount_accessor=<AUTH0_ACCESSOR_ID>
- Add the Auth0 user account to the entity as an alias
vault read identity/entity/id/<entity_id>
- The output should include the entity aliases, metadata (organization, and team), and base policy
Step 6: Create an internal group
It is common for organizations to enable auth methods such as LDAP, Auht0, and perhaps GitHub to handle the Vault user authentication, and individual user’s group memberships are defined within those identity providers. In order to manage the group-level authorization, you can create an external group to link Vault with the external identity provider (auth provider) and attach appropriate policies to the group.
vault write identity/group name="test-group" policies="test-read-only" member_entity_ids=<entity_id> metadata=team="Engineering" metadata=region="North America"
Test access
Use LDAP to access secret
vault login -method=ldap username=<LDAP username>
vault kv get kv/hello
Use Auth0 to access secret
vault login -method=oidc role="reader"
- A browser should open and direct you to the Auth0 login portal
vault kv get kv/hello
Use Github to access secret
Generate Github app token
- Login into Github as an org admin
- In the upper-right corner of any page, click your profile photo, then click Settings
- In the left sidebar, click Developer settings
- In the left sidebar, click Personal access tokens
- Select “Generate new token”
- Enter “<app name>”
- Check “read:org” permission
- Select “Generate token”
- Copy token
Login with token
vault login -method=github
- Enter GitHub Personal Access Token
vault kv get kv/hello
Lessons learned
I am currently reading a book called “Cracking the Coding Interview” and it is a great book. One interesting part of the book is their matrix to describe projects you worked on and the matrix contains the following sections which are: challenges, mistakes/failures, enjoyed, leadership, conflicts, and what would you do differently. I am going to try and use this model at the end of my blog posts to summarize and reflect on the things I learn. I don’t blog to post things that I know, I blog to learn new things and to share the knowledge of my security research.
New skills/knowledge
- Improved my understanding of Hashicorp Vault
- Learned how to create Vault policies
- Learned how to use Vault to support multiple authentication backends for a single entity
- Used the following new service Auth0
Challenges
- Finding documentation to setup auth backends with Vault in a secure manner
What You’d Do Differently
- This blog post was a proof-of-concept (PoC) for using Vault with various auth backends. However, I wish I had time to research OIDC to implement the authentication backend in a more secure manner.
References
- Vault – Secrets Engines
- Essential Patterns of Vault — Part 1
- Vault Policies
- GitHub Auth Method
- OIDC Auth Method
- Identity: Entities and Groups
- HashiCorp Vault and FreeIPA
- JSON on the command line with jq
- Vault – Read Entity by Name
- Versioned Key/Value Secrets Engine
- Okta Authentication in Vault using OpenID Connect (OIDC)
- Vault – LDAP
- Vault Policies