readOnly Workspace in Tekton Task

Priti Desai
Tekton Pipelines
Published in
4 min readJul 28, 2023

Tekton Task provides an option to specify a list of volumes that the task can utilize for creating/storing files during the execution of that task. The files created this way are also persisted after a task is completed such that the dependent tasks can consume them.

Let’s take a look at a very simple pipeline with two tasks. A task creating a file in the workspace and a dependent task which is accidentally tempering the data written by the parent task.

Create Tekton resources including a PVC, two tasks (write-secret and temper-secret), a pipeline, and a pipelineRun.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-01
spec:
resources:
requests:
storage: 100Mi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
---

apiVersion: tekton.dev/v1
kind: Task
metadata:
name: write-secret
spec:
workspaces:
- name: ws
steps:
- image: bash:latest
script: |
#!/usr/bin/env bash
echo "I am writing a secret message here, shh!" > $(workspaces.ws.path)/secret.txt
---

apiVersion: tekton.dev/v1
kind: Task
metadata:
name: temper-secret
spec:
workspaces:
- name: ws
steps:
- image: bash:latest
script: |
#!/usr/bin/env bash
echo "I am accidentally tempering the secret :)" > $(workspaces.ws.path)/secret.txt
---


apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: create-secured-secret
spec:
workspaces:
- name: ws
tasks:
- name: write-secret-task
workspaces:
- name: ws
taskRef:
name: write-secret
- name: temper-secret-task
workspaces:
- name: ws
taskRef:
name: temper-secret
runAfter:
- write-secret-task
---

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: pipelinerun-create-secured-secret-
spec:
workspaces:
- name: ws
persistentVolumeClaim:
claimName: pvc-01
pipelineRef:
name: create-secured-secret
---

Now, examine the pvc and the volume. On a single node kubernetes cluster with a local storage, the volume source has the path which is mounted and available to a task as a workspace. As expected, the file secret.txt created in the first task was modified by its dependent task.

k get pvc pvc-01                                      
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-01 Bound pvc-ff798b77-c5e1-4680-8d2c-3c6e695b6a6f 100Mi RWO standard 10m

k describe pv pvc-ff798b77-c5e1-4680-8d2c-3c6e695b6a6f
Name: pvc-ff798b77-c5e1-4680-8d2c-3c6e695b6a6f
...
Source:
Path: /var/local-path-provisioner/pvc-ff798b77-c5e1-4680-8d2c-3c6e695b6a6f_default_pvc-01

cat /var/local-path-provisioner/pvc-ff798b77-c5e1-4680-8d2c-3c6e695b6a6f_default_pvc-01/secret.txt
I am accidentally tempering the secret :)

This is very weak and vulnerable, isn’t it?

Tekton provides an inherent cloud native engine for declaring CI/CD style pipelines. Running on Kubernetes and extending custom resources makes it a natural fit for cloud native CI/CD. Kubernetes supports many types of volumes. Tekton workspaces inherits most of these types. A very common CI/CD use case is to produce some kind of data or reports and persist it before a run is complete. With a recent adoption of the Software Supply Chain Security, creating SBOMs as part of every build has become essential. So if a task in a pipeline is creating SBOM and it’s dependent task is responsible to upload it to a remote storage, we require some kind restriction or validation that the SBOM is not accidentally updated before locking it in a remote storage.

Tekton pipelines provides one easy solution of mounting the shared volume in a readOnly mode to avoid such accidents from happening.

apiVersion: tekton.dev/v1
kind: Task
metadata:
name: temper-secret
spec:
workspaces:
- name: ws
readOnly: true
steps:
- image: bash:latest
script: |
#!/usr/bin/env bash
echo "I am accidentally tempering the secret :)" > $(workspaces.ws.path)/secret.txt
ro VolumeMount

Now, examine the data created one more time and the file secret.txt is intact with the original content:

cat /var/local-path-provisioner/pvc-17245d7f-f3a9-4166-939c-74e2e22981b2_default_pvc-01/secret.txt
I am writing a secret message here, shh!

Notice the volume pvc-01 is created in readWrite mode but the mount is ro as we requested.

k describe pods pipelinerun-create-secured-secret-kwf6k-temper-secret-task-pod 
Name: pipelinerun-create-secured-secret-kwf6k-temper-secret-task-pod
...
Containers:
step-unnamed-0:
Image: bash:latest
Mounts:
...
/workspace/ws from ws-b28b8 (ro)
Volumes:
ws-b28b8:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc-01
ReadOnly: false

Tekton pipeline results in a failure if a task attempts to write to a readOnly workspace.

The caveat with this solution is readOnly option is only available in the task definition. There is no option available to the pipeline author to enforce such restriction on a task from the pipeline. In general, the pipeline authors cannot rely on the task authors for such enforcements.

Also, ro volume mounts might not be a sufficient solution in many Kubernetes clusters. As long as the volume is readWrite, it does not restrict write access by anyone with enough privileges in the cluster.

Tekton pipelines has more work to do to make such features available out of the box. Until then, please share how you are solving this problem in your deployment or let us know how you would like Tekton pipelines to solve it for you!

--

--

Priti Desai
Tekton Pipelines

Developer Lead @IBM. Tekton maintainer. Co-founder of License Scanner @Cyclonedx