Use-case example: Using JWT Authentication to integrate Conjur and GitLab

This topic demonstrates a use-case scenario of how to integrate GitLab with Conjur using JWT authentication to Conjur.

 

For more information about this authentication, see JWT Authentication.

Assumptions

For this use case scenario:

  • We'll use Conjur CLI v8.x to load policy and to populate variables.

  • We'll use the following GitLab token:

Configure the authentication

In this section we plan and configure the JWT authentication.

Step 1: Plan the configuration

Before we begin, we need to decide which claim or claims in the GitLab token to use to create a 1:1 relationship between the applications and Conjur.

Let's say we want all entities in the namespace1 namespace path in GitLab to be able to authenticate to Conjur. We will use the namespace_path claim to create this 1:1 relationship when we define the JWT Authenticator. For added security, we will also add the full path of the application identity (host) in Conjur, conjur/authn-jwt/gitlab/apps.

To learn more, see Configure JWT authentication.

In addition, we have to define at least one annotation when we define the application identity. The more annotations we use, the more we narrow down the entities that can authenticate using this JWT Authenticator.

We can use any string-type claim from the token as an annotation. This claim must not contain spaces or special characters that are not allowed by Conjur. Let's use the project_id, project_path, and ref claims for the annotations.

 

You can define the JWT Authenticator to enforce selected claims, making respective host annotations mandatory for passing authentication.

Moreover, when you define the JWT Authenticator, you can map vague claim names to more user-friendly aliases. In the JWT above, ref actually refers to the branch. You can map ref to branch, and branch would be reflected in the host annotation rather than ref.

For more information about enforcing claims and mapping claim names to more user-friendly aliases, see Configure JWT authentication.

Step 2: Configure the authentication

Now let's configure and enable the JWT authentication in Conjur.

  1. We start by configuring a JWT Authenticator. We create a policy where we configure:

    • the JSON Web Key Set (JWKS) URI (jwks-uri) provided by GitLab

    • the token-app-property,identity-path, and issuer variables for creating a 1:1 relationship between the application and Conjur

    To do this, let's copy the template policy and adjust it to our needs:

    • We name the JWT Authenticator authn-jwt/gitlab. This helps us identify this as a JWT Authenticator for GitLab entities.

    • We uncomment the jwks-uri variable

    • We uncomment the token-app-property, identity path, and issuer variables

     
    - !policy
        id: conjur/authn-jwt/gitlab
        body:
        - !webservice
      
      
        #Mandatory variable: The JWT provider URI
        #Uncomment either 'public-keys' OR 'jwks-uri'
     
        #- !variable
        #    id: public-keys
      
        - !variable
            id: jwks-uri
     
        #Optional variables
        #Uncomment one or all of the following optional variables.
        #Note: If you uncomment 'token-app-property' you must also uncomment 'identity-path',
        #and vice versa;
     
        - !variable
            id: token-app-property
      
        - !variable
            id: identity-path
     
        - !variable
            id: issuer
    
        #- !variable
        #    id: enforced-claims
    
        #- !variable
        #    id: claim-aliases
    
        #- !variable
        #    id: audience  
    
      
        #Group of applications that can authenticate using this JWT Authenticator
        - !group apps
     
        - !permit
            role: !group apps
            privilege: [ read, authenticate ]
            resource: !webservice
     
        - !webservice
            id: status
     
        #Group of users who can check the status of the JWT Authenticator
        - !group
            id: operators
     
        - !permit
            role: !group operators
            privilege: [ read ]
            resource: !webservice status

    Let's save the policy as authn-jwt-gitlab.yaml and load it into root:

     
    conjur policy load -f /path/to/file/authn-jwt-gitlab.yaml -b root
  2. Next, let's populate the variables in Conjur with information related to the JWT using the Conjur CLI.

    1. We populate the jwks-uri variable with the JWT provider URL:

       
      conjur variable set -i conjur/authn-jwt/gitlab/jwks-uri -v https://gitlab.com/-/jwks/
    2. We populate the token-app-property variable with the namespace_path claim, as discussed in Plan the configuration above.

       
      conjur variable set -i conjur/authn-jwt/gitlab/token-app-property -v namespace_path
    3. We populate the identity-path variable with the application path (without the host/ prefix):

       
      conjur variable set -i conjur/authn-jwt/gitlab/identity-path -v gitlab-apps
    4. Lastly, we populate the issuer variable with the GitLab URL:

       
      conjur variable set -i conjur/authn-jwt/gitlab/issuer -v gitlab.com
  3. Lastly, we need to enable our JWT Authenticator, authn-jwt/gitlab, on all of our Followers.

    To do this, in the Conjur configuration file (conjur.yml), let's add the JWT Authenticator under authenticator::

     
    authenticators: 
      - authn-jwt/gitlab

    and apply the changes:

     
    $ evoke configuration apply

Step 3: Create an application identity (app ID) in Conjur

Now let's create an application identity (app ID) in Conjur.

We name the app ID for the value of the token-app-property (the namespace_path claim) that we configured in the JWT Authenticator. So we call the app ID namespace1.

We also add the annotation that we discussed earlier (see Plan the configuration).

The following app ID represents entities in namespace 1 that authenticate to Conjur if their GitLab token matches the project_id, ref, and project_path claims defined in the annotations:

 
- !policy
  id: gitlab-apps
  body:
    - !group
 
    - &hosts
      - !host
        id: namespace1
        annotations:
            authn-jwt/gitlab/project_id: 26768846
            authn-jwt/gitlab/ref: master
            authn-jwt/gitlab/project_path: namespace1/jwt-example
          
           
    - !grant
      role: !group
      members: *hosts

Let's call this policy authn-jwt-hosts.yaml and load it into root::

conjur policy load -f /path/to/file/authn-jwt-hosts.yaml -b root

We need to grant the app ID (host) permissions to the JWT Authenticator:

 

You must be a Conjur admin to perform this task.

 
- !grant
  role: !group authn-jwt/gitlab/apps
  member: !group gitlab-apps

Let's call this policy authn-jwt-grant.yaml and load it into root:

conjur policy load -f /path/to/file/authn-jwt-grant.yaml -b root

Send an authentication request

To send an authentication request to Conjur, we use the JWT Authenticator REST API:

 
POST https://<Conjur-server-hostname>/authn-jwt/<service-id>/<account>/[<host-id>]/authenticate

In curl, the authentication request will look like this:

 
curl -k --request POST 'https://follower1.example.com/authn-jwt/gitlab/myorg/authenticate' --header 'Content-Type: application/x-www-form-urlencoded' --header "Accept-Encoding: base64" --data-urlencode 'jwt=eyJ0e......jjjkl'

We do not need to include the <host-id> because we defined a token-app-property variable in our JWT Authenticator endpoint.