Skip to main content
Securing Jenkins on GKE with IAP
24 Sep 2020

Securing Jenkins on GKE with IAP

Jenkins is a self-contained, open source automation tool written in Java and has plugins mostly built for continuous integration purposes. You can automate all types of tasks related to building, testing, and deploying software with Jenkins. DevOps is all about speeding up the software development and release process. And Jenkins is widely popular in the DevOps space because of the same reason. Organizations can speed up the software development process through automation with the help of Jenkins. Google Kubernetes Engine (GKE) is a managed environment for deploying, managing, and scaling your containerized applications in the Google infrastructure. It is used to create and operate the Kubernetes clusters in a simplified way. Through GKE, your Kubernetes deployment will get top-quality support GCP (Google Cloud Platform), IAM (Identity and Access Management) identities, built-in HA configuration, along with secured clusters. It will also get native access to GCP's networking features.
Security is an essential aspect of any IT assembly, and securing Jenkins is no exception. In this blog, I will talk about how to secure Jenkins deployed on GKE using IAP. IAP stands for Identity Aware Proxy, and it is a GCP Kubernetes offering that secures your web applications. So, let's see what the prerequisites are:

  • Jenkins deployed on GKE.
  • Domain, e.g., test.xyz
  • An inbuilt Ingress controller of GKE, so you don't have to deploy an external Ingress controller (like Nginx).

I am assuming that you should have already deployed Jenkins on GKE and created a NodePort/ClusterIP service to expose your deployment. As GKE has an inbuilt Ingress controller, create a global reserved IP address which will be utilized by the HTTPS load balancer using the following command:

gcloud compute addresses create <strong>jenkins-gke-ip</strong> –global 

Now, create an Ingress using the YAML code given below:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.allow-http: "false" # Allow only https connections
kubernetes.io/ingress.global-static-ip-name: jenkins-gke-ip # Put the global reserved address name created in 3rd step
networking.gke.io/managed-certificates: ssl-cert # Put ssl certificate name created in 4th step
name: gke-ingress # name you want
namespace: gke # Namespace
spec:
rules:
- host: test.domain.xyz # Domain you used for ssl ceritficate
http:
paths:
- backend:
serviceName: gke-svc # This would be a NodePort/ClusterIP service you created for jenkins
servicePort: 8080 # This is a service Port you defined in service yaml spec

This Ingress will create an HTTPS load balancer. Put this load balancer's IP in the DNS record of type A. Recordset will look like test.domain.xyz == Ip of the load balancer. It will take some time for the Google-managed certificate to be active. Once that is done, you can access Jenkins URL, i.e., test.domain.xyz with HTTPS connection.

Enabling IAP

To enable the IAP, you need first to configure the OAuth consent screen. If you still haven't configured the OAuth consent screen, you can do so with an email address and product name. Firstly, visit the OAuth consent screen. Then, under the support email section, just select the email address you want to display as a public contact. Ensure that the email address you mention should be yours or of a Google group that you own. Just need to enter the application name that you want to be displayed and add the optional details according to your choice. After this, click on the Save button.

Now, let's see how to create the OAuth credentials. For this, you need to visit the Credentials page. Select the OAuth client ID from the Create credentials drop-down list and then select web application from the application type. Next, add a name for your OAuth client ID and click create. Once you click on creating your OAuth client ID and client secret gets generated and displayed on the OAuth client window. Now, click on Ok and select the client created by you. After this, copy the client ID to the clipboard, and now it is time to add the universal redirect URL to the authorized redirect URLs field.

Click on the download JSON located at the top of the page. You can use the credentials in the later stage. Now let's set up the IAP access. For this, first, visit the Identity-Aware Proxy page. Now, select a project that you want to secure with IAP and then select the checkbox located next to the resource where you want to add the members. On the right side, there is a panel. Click add member. Once the add members dialog appears, just enter the email addresses of groups or individuals who should have the IAP-secured Web App User for the project. The members should belong to either of the following accounts:

  • Google Account: user@gmail.com
  • Google Group: admins@googlegroups.com
  • Service account: server@example.gserviceaccount.com
  • G Suite domain: example.com

Make sure you add a Google Account that you have access to. Select Cloud IAP>IAP, then secured Web App User from Roles' drop-down list and then click Save.

Now, let's configure the BackendConfig for IAP. First, create a Kubernetes Secret. After this, add an IAP block to your BackendConfig; the BackendConfig will use a Kubernetes Secret to wrap your OAuth client that you have created earlier. Kubernetes Secrets are managed like other Kubernetes objects by using the kubectl command-line interface (CLI). To create a secret, run the following command where client_id_key and client_secret_key are the keys from the JSON file that you downloaded when you created OAuth credentials:

kubectl create secret generic my-secret --from-literal=client_id=client_id_key \

   --from-literal=client_secret=client_secret_key 

Specify the enabled and secretName values to configure the BackendConfig for IAP. While specifying these values, make sure that you have the permission to compute.backendServices.update. Now, add the IAP block to BackendConfig. In this block, my-secret is the Kubernetes Secret name that you created earlier:

apiVersion: cloud.google.com/v1

kind: BackendConfig

metadata:

  name: config-default

  namespace: my-namespace

spec:

  iap:

    enabled: true

    oauthclientCredentials:

      secretName: my-secret 

To trigger the IAP, you just have to associate the service ports with your BackendConfig. One method to make this association is by making all the service ports default to your BackendConfig, and this can be done by adding the annotation given below to your service resource:

metadata:

  annotations:

    beta.cloud.google.com/backend-config: '{"default": "config-default"}' 

To test the configuration, run kubectl get event. If you get this message "no BackendConfig for service port exists", then it means that you have correctly associated a service port with your BackendConfig. Still, the BackendConfig resource was not found. This error can occur in the event of one of the following scenarios:

  • Haven't created the BackendConfig resource
  • Created it in the wrong namespace
  • Misspelled the reference in the Service annotation.

If the secretName that you referred to doesn't exist or isn't structured correctly, then one of the following error messages will be displayed:

  • BackendConfig default/config-default is not valid: error retrieving secret "foo": secrets "foo" not found. Ensure that you have created the Kubernetes Secret correctly, as mentioned in the previous section, to solve this error.
  • BackendConfig default/config-default is not valid: secret "foo" missing client_secret data. Ensure that you have created the OAuth credentials properly to solve this error. This also ensures that you referred to the correct client_id and client_secret keys in the JSON that you downloaded earlier.

When the enabled flag is set to true and the secretName is correctly set, then the IAP gets configured for your selected resource. After the IAP gets configured, Jenkins deployed on GKE using IAP is secured. That is all. I hope this was helpful. Try this process and share your experience in the comments section below. Stay safe and happy coding.

Subscribe to our feed

select webform