GCP Authenticator
This topic describes how to configure a Google Cloud Platform (GCP) Authenticator.
Overview
The GCP Authenticator is a secure method for applications running on the Google Cloud Platform to authenticate to Conjur using a unique identity token signed by Google.
A Conjur identity can be established at varying granularity, allowing for a collection of resources to be identified to Conjur as one, or for individual workloads to be uniquely identified.
Supported Google Cloud services
- Google Compute Engine
- Google Cloud Function
Supported authentication strategies
Based on Google Identity Platform authentication, the GCP Authenticator uses an identity token based on a service account provided by Google.
How it works
This section describes how an application running on GCP authenticates to Conjur to retrieve secrets.
-
An application requests an identity token from the Google metadata server.
-
The metadata server responds with a Google-signed JWT (JSON Web Token) that contains metadata about the Google Cloud service, including claims about the service's Google identity.
-
The application sends an authentication request to Conjur, as well as the JWT, using the GCP Authenticator REST API.
-
Conjur attempts to authenticate and authorize the request. If successful, Conjur sends a short-lived access token back to the application.
-
The application can retrieve secrets stored in Conjur.
Obtain the Google identity token
The Google Cloud service obtains an identity token from Google's metadata server. Access to the metadata service is provided by Google Cloud Platform for any application that is deployed on one of the Google Cloud services. The token is used to verify the identity of the Google Cloud service.
For Google Compute Engine, Google strongly recommends creating a user-managed service account to create a Compute Engine instance, rather than using the default service account. For details, see the Google Cloud documentation. |
Request the Google identity token
This section describes how to request an identity token for supported Google Cloud services.
To request an identity token for a GCE instance, run the following command:
|
For example:
curl -G -H "Metadata-Flavor: Google" \ --data-urlencode "audience=conjur/myorg/host/gcp-app/test-app" --data-urlencode "format=full" \ "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity" |
Parameter |
Description |
---|---|
audience |
The unique URI agreed upon by both the token sender and receiver, used for validation of the token. In this case, audience is the Conjur host id. Syntax:
|
format |
Specifies whether or not the project and instance details are included in the payload. Conjur expects an identity token in Value: |
GCE token payload
The GCE token payload contains the aud
(audience) claim that was specified in the request. Because the token is requested with format=full
, the payload also includes claims about the GCE instance and its project. A full
token is mandatory when authenticating with the GCP Authenticator. For information about identity token payloads, see the Google Cloud documentation.
For example:
|
The following is an example of python code to be deployed as a Google Cloud function in order to obtain a Google identity token:
|
Requirements
The Google identity token should be generated for the Conjur host id as an audience
claim.
Parameter |
Description |
---|---|
audience |
The Conjur host id. Syntax:
|
GCF token payload
The payload contains the aud
(audience) claim that was specified in the request.
For example:
|
Configure the GCP Authenticator
To communicate with and retrieve secrets from Conjur, the application running on the Google Cloud service needs to authenticate to Conjur and receive a Conjur access token.
This section describes how to configure the GCP Authenticator
-
Before you begin
Before you begin, collect the following details about the Google Cloud service:
What you need
Description
For GCE only.
The name of the GCE instance to which this token belongs.
Project ID
For GCE only.
The ID for the project where you created the GCE instance.
Service account ID
The subject of the token. This is the unique ID for the service account that you associated with the Google Cloud service.
The service account's name is a unique ID. This appears in the service account's email address that is provisioned during creation.
Example:
sa-name@project-id.iam.gserviceaccount.com
.For more information about service accounts, see the Google Cloud documentation.
-
Define GCP Authenticator policy
In this step you define the GCP Authenticator in policy, and detail a group of Conjur hosts (applications) that have permission to use the GCP Authenticator to authenticate to Conjur.
The GCP Authenticator name must be
conjur/authn-gcp
. Only one GCP Authenticator can be defined in Conjur.-
Copy the following policy:
- !policy id: conjur/authn-gcp body: - !webservice - !group id: apps annotations: description: Group of hosts that can authenticate using the authn-gcp authenticator - !permit role: !group apps privilege: [ read, authenticate ] resource: !webservice
-
Save the policy as authn-gcp.yml, and load it into root:
conjur policy load -b root -f authn-gcp.yml
-
-
Define the GCP resource as a Conjur host in policy
In this step, you give a Conjur identity to an application running inside the Google Cloud service. The Conjur identity is represented as a host in Conjur. In the host role, you define the resource authentication details. These details are defined as host annotations.
Use the following guidelines when defining the host annotations:
-
The annotation prefix must be the authenticator ID. For the GCP Authenticator, the annotation prefix is
authn-gcp/
. -
Use at least one of the following annotations:
-
authn-gcp/instance-name
(GCE only) -
authn-gcp/project-id
(GCE only) -
authn-gcp/service-account-id
-
authn-gcp/service-account-email
-
-
The correlation between the annotations is an
AND
correlation. -
The annotations are validated against the claims in the Google identity token as follows:
Google Cloud service
Host annotation
JWT claim
Description
GCE only
instance-name
google/compute_engine/instance_name
The name of the GCE instance to which this token belongs.
GCE only
project-id
google/compute_engine/project_id
The ID for the GCP project where you created the GCE instance.
GCE; GCF
service-account-email
email
The Google Cloud service account's name is a unique identifier; it appears in the service account's email address that is provisioned during creation
Example:
sa-name@project-id.iam.gserviceaccount.com
GCE; GCF
service-account-id
sub
The subject of the token. That is, the unique ID for the Google Cloud service account that you associated with the Google Cloud service.
To define the Google Cloud service as a host in Conjur:
-
Copy the following policy, and substitute the parameters with the values you collected at the beginning of this procedure:
- !policy id: <policy-id> body: - !group - &hosts - !host id: <host-id> annotations: authn-gcp/instance-name: <instance-name> authn-gcp/project-id: <project-id> authn-gcp/service-account-id: <service-account-id> authn-gcp/service-account-email: <service-account-email> - !grant role: !group members: *hosts
If you are loading the policy into
root
, make sure to EXCLUDE the slash (/) preceding the path in:role: !group [/]conjur/authn-gcp/apps
.The path is already rooted, so the slash would be redundant.
For example:
- !policy id: gcp-apps body: - !group - &hosts - !host id: test-app annotations: authn-gcp/service-account-id: 177777777777777778 authn-gcp/service-account-email: 177777777777777778-compute@developer.gserviceaccount.com - !grant role: !group members: *hosts - !grant role: !group /conjur/authn-gcp/apps member: !group gcp-apps
-
Save the policy as authn-gcp-hosts.yml, and load the policy file into any policy level:
conjur policy load -b <policy-path> -f authn-gcp-hosts.yml
For example:
$
conjur policy load -b my/policy/path -f authn-gcp-hosts.yml
-
-
Define secrets and access for Google services
-
Define Conjur secrets and a group that has permissions on the secrets.
In the following example, all members of the
consumers
group are granted permissions on thetest-variable
secret.- !policy id: secrets body: - !group consumers - !variable test-variable - !permit role: !group consumers privilege: [ read, execute ] resource: !variable test-variable - !grant role: !group secrets/consumers member: !group gcp-apps
-
Save the policy as authn-gcp-secrets.yml.
-
Load the policy file into root:
conjur policy load -b root -f authn-gcp-secrets.yml
-
Populate the secret with a value. For example:
$ conjur variable set -i secrets/test-variable -v mySecret
-
-
Enable the GCP Authenticator
This step describes how to enable the GCP Authenticator in Conjur.
Set the CONJUR_AUTHENTICATORS variable as an environment variable, for example:
CONJUR_AUTHENTICATORS=authn-gcp
For more information about enabling authenticators in Conjur, see Configure authenticators. -
Check the authenticator status
Check that the GCP Authenticator is configured correctly. For details, see Authenticator Status Webservice.
GCP Authenticator REST API
Once the GCP Authenticator is configured, you can send an authentication request from the Google Cloud service to Conjur using the GCP Authenticator REST API.
For more information, see the GCP Authenticator API.
Troubleshooting the GCP Authenticator
This section lists issues that may arise and recommended solutions:
Check the authenticator status using the Authenticator Status API. For details, see Authenticator Status Webservice.
Issue: The following error appears in the logs:
Authentication Error: #<Errors::Authentication::Security::RoleNotFound: CONJ00007E 'myapps/test-app' not found> |
Possible solutions:
-
Using the Conjur CLI, validate that the host is defined in Conjur:
conjur list --kind host --search
For example:
conjur list --kind host --search myapps/test-app
-
Validate that you issued the token on the Google Cloud service with
'audience=conjur/account-name/host/host-id'
Request:
curl -G -H "Metadata-Flavor: Google" \ --data-urlencode "audience=conjur/<account-name>/host/<host-id>" \ --data-urlencode "format=full" \ "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity"
Example request:
curl -G -H "Metadata-Flavor: Google" \ --data-urlencode "audience=conjur/myorg/host/gcp-apps/test-app" \ --data-urlencode "format=full" \ "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity"
where:
-
gcp-apps
is the ID of the policy in which the host is defined -
format
must always have valuefull
-
Issue: The following error appears in the logs:
Authentication Error: #<Errors::Authentication::Jwt::TokenDecodeFailed: CONJ00035E Failed to decode token (3rdPartyError ='#<JWT::VerificationError: Signature verification raised>')> |
Possible cause: If you got this error but the signature is valid (for example, it's from https://jwt.io/), the token may contain EOL characters. This can happen when copying the token between different shells or tools.
Possible solutions:
- Use a different shell to obtain the token
- Delete all EOL characters from the original token