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

Proposal: Google Cloud IAM Auth Backend #2813

Closed
emilymye opened this issue Jun 6, 2017 · 14 comments
Closed

Proposal: Google Cloud IAM Auth Backend #2813

emilymye opened this issue Jun 6, 2017 · 14 comments

Comments

@emilymye
Copy link
Contributor

emilymye commented Jun 6, 2017

We want to simplify deployment of Vault on Google Cloud Platform. Part of this work is implementing an auth backend for authenticating GCP entities, in particular IAM service accounts.

I've split my proposal into two pieces of work to be done:

  1. A simple IAM backend that constrains roles by service account IDs/emails. Vault verifies a signed JWT with the service account's information, confirms it belongs to the role's specified set of service accounts, and returns an auth token if successful.
  2. Adding different types of role constraints to authorize a service account based on its IAM permissions/roles.

Feedback is definitely welcome, especially for the second part. Do these role constraints make sense? Would they be useful?

Background

Overview of GCP IAM.

This backend will handle authentication of IAM service accounts, accounts which belong to an application or VM rather than an individual user. Clients will be able to use existing IAM service accounts and credentials to authenticate with Vault, rather than having to create new credentials per service account to use with another auth backend.

The only other type of IAM entity that can be used to establish identity are Google account users, which should probably fall under a separate auth backend using OAuth or Google Identity to authenticate individual users.

Part 1: Simple GCP IAM Backend

We initially will constrain roles by a list of service account emails/ids. The client will authenticate using a signed JWT, created by the client and signed using IAM API method signJwt for the authenticating service account.

The JWT body will contain information about the service account, at minimum:

{
    'id': 1234567890,
    'email': 'service_account@project-12345.iam.gserviceaccount.com', 
    ...
}

Google signs the JWT using one of the service account's system-owned private keys. The returned signed JWT contains the ID of the signing key as a kid field. These private keys are never exposed by Google and are rotated automatically.

On login, the client provides the signed JWT and the name of the role for Vault to verify:

Using this workflow, the auth backend will need initial configuration of some root credentials with the following IAM permissions:

  • iam.serviceAccountKeys.get
  • iam.serviceAccount.get

Once Vault has confirmed the client is the service account, Vault then simply checks the authorized group of service accounts to determine if the client account should be allowed to login under the given role.

Part 2: Constraining By IAM Permissions

It makes sense to provide the ability to constrain a service account to a Vault role by IAM permissions. Service accounts can be added to the authorized set of roles on the fly by adding or removing permissions, rather than updating or recreating a role to add/remove a service account.

However, querying the permissions of a service account and defining the Vault roles can get clumsy. This section discusses two types of constraints, IAM roles and IAM permissions, and their various issues. tl;dr: It's very hard to determine what service account has what role for an arbitrary resource.

Background

As a brief review of IAM roles/policies:

  • An IAM role is defined by a set of permissions on specific GCP resources.
  • An IAM policy is a list of bindings of a role to IAM users, service accounts, groups, etc. A policy is bound per resource and inherits from project or organization-level policies.

These are separate from the Vault role and policies, where policies determine allowed actions in Vault and roles are defined by a set of policies.

Currently, to query the IAM policies or permissions on an account, there are two types API methods, defined per resource/service:

  • getIamPolicy(): Returns the policy set on a resource. This does not take into consideration inherited policies for parent resources.
  • testIamPermissions(): Takes a set of permissions and outputs which permissions from that set the requesting service account has. Vault would need to assume the role of the service account being tested.

These two methods support two different type of constraints.

Proposal:

We would define Vault role constraints by the following arguments:

  • resource: Path of resource to query policy and roles from

and one of:

  • role: Name of role defined explicitly on that resource's policy. Vault would call getIamPolicy() on the given resource and search the returned Policy for a given role/service account binding.
  • permissions: Comma-seperated list of required permissions. Vault assumes the authenticating service account's role to call testIamPermissions() on the given resource, passing this set of permissions in and comparing the output set of allowed permissions for equality.

Concerns:

There are three main issues with these constraints. We discuss each further, as well as smaller concerns for each type of constraint:

1. IAM Methods defined per resource, per service

To query the IAM policy or permissions that a given service account has on a specific resource, Vault would thus need to parse from the resource which service to call (i.e. Cloud Resource Manager for a project, Compute Engine for GCE VM instances, etc) and support calling each service as necessary. The backend root credentials would also require additional permissions for each supported resource. The IAM methods on different resources/services are still being added as well, so supporting arbitrary resources would require more maintainance.

We can possible limit this to specific resources at first, depending on how people would want to use role constraints.

Each type of constraint we can support using these two IAM methods has its own issues.

2. getIamPolicy() doesn't support inheritance of roles/permissions.

For the IAM role constraint, we would use 'getIamPolicy()'. However, this requires that the role-user binding be defined explicitly on the given resource. For example, if we wanted to see if a service account has create permissions for some Compute Engine VM instance, if the service account had create access defined at the project level, this check would return false.

3. testIamPermissions() requires assuming the role of the authenticating service account.

For the permissions constraint, testIamPermissions() tests the permissions of the authorized caller. For Vault to do this call on behalf of the service account currently requires the credentials of that service account, which some users may rightfully be uncomfortable with.

Additional Concerns

For the IAM role constraint, the IAM Policy format is awkward to query for a given role/user binding; we would search a list for a role and then search another list of users. The API methods don't provide much help in terms of filtering.

For the permissions constraint, we would essentially redefine the permissions of some IAM role as part of the Vault role. Editing becomes difficult compared to the role constraint. However, the permissions check has the benefit of automatically checking for inherited permissions and doesn't require searching a list of unrelated policy bindings.

@jefferai
Copy link
Member

jefferai commented Jun 6, 2017

@emilymye Any chance you can put this in a Google Doc, so that it's easier to comment? With a GitHub issue you can't pop comments inline.

@emilymye
Copy link
Contributor Author

emilymye commented Jun 6, 2017

Here's a link: https://docs.google.com/document/d/1UiRM2QCJscv4Drluk5bhB4cQMwQYBrebjNDXygWbuk8/edit?usp=sharing

While I have your attention, could I also get added to the slack team so I can view the contributers' channel?

@jefferai
Copy link
Member

jefferai commented Jun 6, 2017

Sure! Incoming.

@pires
Copy link

pires commented Jun 28, 2017

Actually, there's another way to do it in Github: pull-request containing a markdown document. One great example of this working is the Kubernetes feature proposal process, e.g. kubernetes/community#611

@kamalmarhubi
Copy link

See also Rust RFC process: https://github.com/rust-lang/rfcs

@emilymye
Copy link
Contributor Author

Will update the issue when more things are ready, but just FYI I am still working on this with Vault team. We decided to create this as a standalone plugin.

@pires
Copy link

pires commented Jul 17, 2017

@emilymye any chance external contributions are accepted, even if just testing/doc?

@emilymye
Copy link
Contributor Author

@pires It'll be normal OSS, it's just not quite ready to review yet :) Mostly I wanted to bump so people know we're actively working on it.

@jefferai
Copy link
Member

@emilymye let me know when you want the repo public; it's up to you/Google!

@bmcustodio
Copy link
Contributor

@emilymye @jefferai are there any plans for making this public in the next couple of weeks? I'm eager to try it out and contribute with some testing! 😀

@emilymye
Copy link
Contributor Author

emilymye commented Aug 8, 2017

@brunomcustodio we are still going through a review but our goal is to have this out and public by next week. Thanks for being patient!

@pires
Copy link

pires commented Aug 8, 2017

Terrific! Thanks @emilymye

@emilymye
Copy link
Contributor Author

emilymye commented Aug 16, 2017

Closing this issue - the backend is now live and can be mounted using "vault auth-enable 'gcp'" from Vault v0.8.1 onward!

Repo: https://github.com/hashicorp/vault-plugin-auth-gcp
Docs: https://www.vaultproject.io/docs/auth/gcp.html

If you have questions, concerns, issues, please let us know via the vault-users group or by filing an issue on that repo. Thanks all!

@bmcustodio
Copy link
Contributor

Thank you @emilymye. Amazing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants