gocd / gocd-vault-secret-plugin

GoCD secrets plugin for HashiCorp's Vault
https://gocd.org
14 stars 7 forks source link

Support OpenID Connect #102

Open Anroc opened 2 years ago

Anroc commented 2 years ago

What is this change about?

OpenID Connect (OIDC) is an authentication schema build on top of OAuth 2.0. It allows services to authenticate an external entity using an Identity Token. This makes the process of authenticating and accessing cloud resources password and tokenless. Github Actions already supports OIDC tokens to authenticate to external services such as Google Cloud Project using Workload Identity Federation.

Since Vault can be configured to provide OIDC Identity Tokens it also gives GoCD the power using this plugin to issue such identity tokens to GoCD pipelines. This change adds the functionally to

To enable this mode the user can choose between the secret engine mode of secret, which defaults to the normal behaviour of this plugin to use Vault as a Key-Value Secret Storage, and oidc which causes this plugin to act as a OIDC Identity Token provider for pipelines.

What changed?

OIDC Identity Token Provider

The main changes relate to the functionality to communicate to GoCD's API to fetch pipeline metadata information and the respective communication to Vault to create a pipeline entity, retrieve a token for this entity and fetch an Identity Token.

The whole flow is defined in this sequence diagram while only the blue highlighted area is the flow that is implemented in this pull-request.

pipeline-identity-public-2022-05-17T13-19-25 190Z

After Vault is configured probably (as also outlined in the updated README.md), this plugin executes upon request the following steps:

  1. Retrieve pipeline configuration for the requesting pipeline with name foo. Extract pipeline name and pipeline group. The information which pipeline should be requested is contained in the ID_TOKEN secret reference. E.g. for a pipeline foo: {{SECRET:[vault-oidc][foo]}}. 2 a). Resolve the git material definition in this configuration to extract repository, organisation, branch 2 b) If no git material is defined check for git plugin definitions. Request the SCM configuration and resolve the git url to retrieve repository, organisation and branch information. 2 c) If no git or plugin material is defined, check if this pipeline is defined as a pipeline dependency. If yes, resolve the depended pipeline configuration and repeat step 2 recursively.
  2. Using the extracted metadata information (pipeline name, pipeline group, git repository name, git repository organisation and executing branch), create an entity in Vault attaching the same metadata information
  3. Create an entity alias to connect the entity with the Auth token endpoint in Vault (for that the auth token mount information and the entity ID must be fetched by the plugin)
  4. Create a Vault token for this newly created entity
  5. Impersonating the pipeline entity foo, request an OIDC Identity Token from Vault
  6. Return this identity token to the calling pipeline

Switching to OkHTTP as API client to Vault

Besides the new mode of operation of this plugin, I also started switching this plugin to OkHTTP to use the API of Vault. As mentioned in https://github.com/gocd/gocd-vault-secret-plugin/issues/94 Better Cloud Vault is deprecated and should not be used anymore.

Limitations and Todos

Here a list of items that are supported only in limited fashion and should be considered before merging this PR:

Security Concerns

Here a list of security concerns which must be respected by the developer who wants to include this change.

Privilege escalation though entity alias creation

Vault allows quite heavily policy restrictions which should be used to restrict what policies can be attached to entities by this plugin. However, it is possible for this plugin to create an entity alias for a different entity (e.g. an admin) and then create a token for this entity alias essentially assuming this entity. This risk is also outlined in the Vault documentation:

If a user can modify an alias they can login with, they can bind it to an entity with higher privileges.

https://www.vaultproject.io/api/secret/identity/entity-alias

I found this risk acceptable, since I also didn't see a way around this problem. I guess we would need to wait until Vault allows us to restrict for which entity an entity alias can be created. In the meantime, it is recommended to restrict access to the plugin Vault credentials as good as possible.

No separation of duties between pipelines

As already mentioned OIDC tokens are generated depending on the requested pipeline name in the secret reference. E.g. to create an Identity Token for pipeline foo the secret reference is: ID_TOKEN={{SECRET:[vault-oidc][foo]}}.

Using this plugin in its raw form can be quit tricky as it allows any GoCD user to configure a pipeline and set a completely different pipeline name into the secret reference. As this plugin doesn't know who requested the creation of an OIDC Identity Token, it needs to rely on the correctness of the requested pipeline name.

I would recommend here to extend the functionality of this plugin to accept a new configuration parameter which contains a list of pipeline names. This pipeline names are then bound using the rules for secret manager plugins in GoCD to a user group. However, this is currently not supported in this Pull-Request.

arvindsv commented 2 years ago

Hello! This looks great. It's obvious a lot of thought has gone into this.

However, none of the maintainers at this time is using this plugin. The challenge with accepting a big change such as this is that people who don't have intimate knowledge of this (I'll speak for myself) end up being responsible for it going forward. In this particular case, I wonder if it's not a bad idea for you to fork this plugin, and for this repository to be archived. Then, we can point others to your repository as the canonical source. What do you think?

We've had this challenge before and have had to move plugins outside of the "gocd" org, to "gocd-contrib" or elsewhere to show that the plugin isn't being maintained directly by the people maintaining GoCD. However, it's still too close for comfort. :) That's why the suggestion of a fork in your organisation.

Hope that makes sense.