Authentication

This document defines how authentication is provided during execution of a TaskRun or a PipelineRun (referred to as Runs in this document).

The build system supports two types of authentication, using Kubernetes’ first-class Secret types:

  • kubernetes.io/basic-auth
  • kubernetes.io/ssh-auth

Secrets of these types can be made available to the Run by attaching them to the ServiceAccount as which it runs.

Exposing credentials

In their native form, these secrets are unsuitable for consumption by Git and Docker. For Git, they need to be turned into (some form of) .gitconfig. For Docker, they need to be turned into a ~/.docker/config.json file. Also, while each of these supports has multiple credentials for multiple domains, those credentials typically need to be blended into a single canonical keyring.

To solve this, before any PipelineResources are retrieved, all pods execute a credential initialization process that accesses each of its secrets and aggregates them into their respective files in $HOME.

SSH authentication (Git)

  1. Define a Secret containing your SSH private key (in secret.yaml):
   apiVersion: v1
   kind: Secret
   metadata:
     name: ssh-key
     annotations:
       tekton.dev/git-0: github.com # Described below
   type: kubernetes.io/ssh-auth
   data:
     ssh-privatekey: <base64 encoded>
     # This is non-standard, but its use is encouraged to make this more secure.
     # If it is not provided then the git server's public key will be requested
     # when the repo is first fetched.
     known_hosts: <base64 encoded>

tekton.dev/git-0 in the example above specifies which web address these credentials belong to. See Guiding Credential Selection below for more information.

  1. Generate the value of ssh-privatekey by copying the value of (for example) cat ~/.ssh/id_rsa | base64.

  2. Copy the value of cat ~/.ssh/known_hosts | base64 to the known_hosts field.

  3. Next, direct a ServiceAccount to use this Secret (in serviceaccount.yaml):

   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: build-bot
   secrets:
     - name: ssh-key
  1. Then use that ServiceAccount in your TaskRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: TaskRun
   metadata:
     name: build-push-task-run-2
   spec:
     serviceAccountName: build-bot
     taskRef:
       name: build-push
  1. Or use that ServiceAccount in your PipelineRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: PipelineRun
   metadata:
     name: demo-pipeline
     namespace: default
   spec:
     serviceAccountName: build-bot
     pipelineRef:
       name: demo-pipeline
  1. Execute the Run:
   kubectl apply --filename secret.yaml serviceaccount.yaml run.yaml

When the Run executes, before steps execute, a ~/.ssh/config will be generated containing the key configured in the Secret. This key is then used to authenticate when retrieving any PipelineResources.

Using a custom port for SSH authentication

In order to interact with your git server over a custom SSH port you must specify the port as part of the Secret. Here’s an example:

apiVersion: v1
kind: Secret
metadata:
  name: ssh-key-custom-port
  annotations:
    tekton.dev/git-0: example.com:2222
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: <base64 encoded>
  known_hosts: <base64 encoded>

Any PipelineResource referencing a repo at example.com will now connect to it over port 2222.

Using SSH authentication in your own git Tasks

The SSH credentials described above can be used when invoking git commands directly in your own Task’s Steps. However, a Step will first need to symlink /tekton/home/.ssh to its user home directory (e.g. /root/.ssh when the Step’s container runs as root).

This is required because while Tekton does set the $HOME environment variable to /tekton/home by default, ssh ignores that environment variable and only considers the user’s home as that described in /etc/passwd.

Note: The additional symlink is not required if you are using the git-clone catalog Task or Git PipelineResource.

For an example of vanilla git commands using the SSH credentials described above, see the authenticating-git-commands example.

Basic authentication (Git)

  1. Define a Secret containing the username and password that the Run should use to authenticate to a Git repository (in secret.yaml):
   apiVersion: v1
   kind: Secret
   metadata:
     name: basic-user-pass
     annotations:
       tekton.dev/git-0: https://github.com # Described below
   type: kubernetes.io/basic-auth
   stringData:
     username: <username>
     password: <password>

tekton.dev/git-0 in the example above specifies which web address these credentials belong to. See Guiding Credential Selection below for more information.

  1. Next, direct a ServiceAccount to use this Secret (in serviceaccount.yaml):
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: build-bot
   secrets:
     - name: basic-user-pass
  1. Then use that ServiceAccount in your TaskRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: TaskRun
   metadata:
     name: build-push-task-run-2
   spec:
     serviceAccountName: build-bot
     taskRef:
       name: build-push
  1. Or use that ServiceAccount in your PipelineRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: PipelineRun
   metadata:
     name: demo-pipeline
     namespace: default
   spec:
     serviceAccountName: build-bot
     pipelineRef:
       name: demo-pipeline
  1. Execute the Run:
   kubectl apply --filename secret.yaml serviceaccount.yaml run.yaml

When this Run executes, before steps execute, a ~/.gitconfig will be generated containing the credentials configured in the Secret, and these credentials are then used to authenticate when retrieving any PipelineResources.

Basic authentication (Docker)

  1. Define a Secret containing the username and password that the build should use to authenticate to a Docker registry (in secret.yaml):
   apiVersion: v1
   kind: Secret
   metadata:
     name: basic-user-pass
     annotations:
       tekton.dev/docker-0: https://gcr.io # Described below
   type: kubernetes.io/basic-auth
   stringData:
     username: <username>
     password: <password>

tekton.dev/docker-0 in the example above specifies which web address these credentials belong to. See Guiding Credential Selection below for more information.

  1. Next, direct a ServiceAccount to use this Secret (in serviceaccount.yaml):
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: build-bot
   secrets:
     - name: basic-user-pass
  1. Then use that ServiceAccount in your TaskRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: TaskRun
   metadata:
     name: build-push-task-run-2
   spec:
     serviceAccountName: build-bot
     taskRef:
       name: build-push
  1. Or use that ServiceAccount in your PipelineRun (in run.yaml):
   apiVersion: tekton.dev/v1beta1
   kind: PipelineRun
   metadata:
     name: demo-pipeline
     namespace: default
   spec:
     serviceAccountName: build-bot
     pipelineRef:
       name: demo-pipeline
  1. Execute the Run:
   kubectl apply --filename secret.yaml serviceaccount.yaml run.yaml

When the Run executes, before steps execute, a ~/.docker/config.json will be generated containing the credentials configured in the Secret, and these credentials are then used to authenticate when retrieving any PipelineResources.

Kubernetes’s Docker registry’s secret

Kubernetes defines two types of secrets for Docker registries : the old format kubernetes.io/dockercfg and the new kubernetes.io/dockerconfigjson. Tekton supports those secrets in addition to the one described above.

  1. Define a Secret from a Docker client configuration file, as documented in Pull an Image from a Private Registry
   kubectl create secret generic regcred \
    --from-file=.dockerconfigjson=<path/to/.docker/config.json> \
    --type=kubernetes.io/dockerconfigjson
  1. Instruct a ServiceAccount to use this Secret:
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: build-bot
   secrets:
     - name: regcred
  1. Use that ServiceAccount in your TaskRun:
   apiVersion: tetkon.dev/v1beta1
   kind: TaskRun
   metadata:
     name: build-with-basic-auth
   spec:
     serviceAccountName: build-bot
     steps:
     ...
  1. Execute the build:
   kubectl apply --filename secret.yaml --filename serviceaccount.yaml --filename taskrun.yaml

When this TaskRun executes, before the steps are getting executed, a ~/.docker/config.json will be generated containing the credentials configured in the Secret, and these credentials are then used to authenticate with the Docker registry.

If both kubernetes.io/* and tekton flavored basic authentication secret are provided, tekton will merge the credentials from those two ; tekton flavored credentials taking precedence over kubernetes.io/dockerconfigjson (or kubernetes.io/dockercfg) ones.

Guiding credential selection

A Run might require many different types of authentication. For instance, a Run might require access to multiple private Git repositories, and access to many private Docker repositories. You can use annotations to guide which secret to use to authenticate to different resources, for example:

apiVersion: v1
kind: Secret
metadata:
  annotations:
    tekton.dev/git-0: https://github.com
    tekton.dev/git-1: https://gitlab.com
    tekton.dev/docker-0: https://gcr.io
type: kubernetes.io/basic-auth
stringData:
  username: <cleartext non-encoded>
  password: <cleartext non-encoded>

This describes a “Basic Auth” (username and password) secret that should be used to access Git repos at github.com and gitlab.com, as well as Docker repositories at gcr.io.

Similarly, for SSH:

apiVersion: v1
kind: Secret
metadata:
  annotations:
    tekton.dev/git-0: github.com
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: <base64 encoded>
  # This is non-standard, but its use is encouraged to make this more secure.
  # Omitting this results in the server's public key being blindly accepted.
  known_hosts: <base64 encoded>

This describes an SSH key secret that should be used to access Git repos at github.com only.

Credential annotation keys must begin with tekton.dev/docker- or tekton.dev/git-, and the value describes the URL of the host with which to use the credential.

Using credentials as non-root user

For a number of reasons you may need to use the credentials described in this doc in non-root contexts:

  • Your platform may randomize the user and/or groups that your containers run as.
  • The Steps of Tasks that you use may define a non-root securityContext.
  • Tasks themselves may specify non-root securityContexts applied to all Steps.

Running as a non-root user has several effects that need to be accounted for when using the credentials mounted with the process described above:

  1. Certain credential types (SSH/git) require that the user have a valid home directory defined in /etc/passwd. Just having a random UID but no home directory will result in SSH erroring out.
  2. Credentials may need to be moved or symlinked from the $HOME directory that Tekton defines (/tekton/home) to the correct home directory for your user. This is true for SSH, which ignores the $HOME environment variable completely.

For an example of using SSH credentials in a non-root securityContext, see the authenticating-git-commands example.

Implementation details

Docker basic-auth

Given URLs, usernames, and passwords of the form: https://url{n}.com, user{n}, and pass{n}, generate the following for Docker:

=== ~/.docker/config.json ===
{
  "auths": {
    "https://url1.com": {
      "auth": "$(echo -n user1:pass1 | base64)",
      "email": "not@val.id",
    },
    "https://url2.com": {
      "auth": "$(echo -n user2:pass2 | base64)",
      "email": "not@val.id",
    },
    ...
  }
}

Docker doesn’t support kubernetes.io/ssh-auth, so annotations on these types are ignored.

Git basic-auth

Given URLs, usernames, and passwords of the form: https://url{n}.com, user{n}, and pass{n}, generate the following for Git:

=== ~/.gitconfig ===
[credential]
    helper = store
[credential "https://url1.com"]
    username = "user1"
[credential "https://url2.com"]
    username = "user2"
...
=== ~/.git-credentials ===
https://user1:pass1@url1.com
https://user2:pass2@url2.com
...

Git ssh-auth

Given hostnames, private keys, and known_hosts of the form: url{n}.com, key{n}, and known_hosts{n}, generate the following for Git:

=== ~/.ssh/id_key1 ===
{contents of key1}
=== ~/.ssh/id_key2 ===
{contents of key2}
...
=== ~/.ssh/config ===
Host url1.com
    HostName url1.com
    IdentityFile ~/.ssh/id_key1
Host url2.com
    HostName url2.com
    IdentityFile ~/.ssh/id_key2
...
=== ~/.ssh/known_hosts ===
{contents of known_hosts1}
{contents of known_hosts2}
...

Note: When known_hosts is not provided, Tekton will configure SSH to accept any public key that is returned on its first request to the server. This is implemented by setting git’s core.sshCommand to ssh -o StrictHostKeyChecking=accept-new.

Least privilege

The secrets as outlined here will be stored into $HOME (by convention the volume: /tekton/home), and will be available to Source and all Steps.

For sensitive credentials that should not be made available to some steps, do not use the mechanisms outlined here. Instead, the user should declare an explicit Volume from the Secret and manually VolumeMount it into the Step.


Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License.


Last modified January 1, 0001