pipeline: Missing validation when referencing unknown params with bracket notation

Expected Behavior

There are three ways to reference a parameter in task steps.

# dot notation
$(params.<name>)
# or bracket notation (wrapping <name> with either single or double quotes):
$(params['<name>'])
$(params["<name>"])

If task steps use an unknown <name> in any 3 reference forms (means the parameter name is not declared in params), the webhook should validate against it and report an error like the following when applying a taskrun.

Error from server (BadRequest): error when creating "validation-test.yaml": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: non-existent variable in "set -e\necho $(params.fooo) | tee $(results.echo-output.path)\n": spec.taskSpec.steps[0].script

Actual Behavior

  • Only validate against $(params.<name>) dot notation reference
  • Not validate against $(params['<name>']) $(params["<name>"]) bracket notation reference. If I use wrong parameter name, the taskrun still succeeds, but the unknown param reference has some bad behaviour i.e. when echo to result.

Steps to Reproduce the Problem

  1. Apply the following taskrun in which the step echo-params references an unknown parameter name fooo using the bracket notation.
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: validation-
spec:
  taskSpec:
    params:
      - name: foo
        type: string
        default: "bar"
    results:
      - name: echo-output
        description: "see echo output"
    steps:
      - name: echo-params
        image: bash
        script: |
          set -e
          echo $(params["fooo"]) | tee $(results.echo-output.path)
  1. Then, you can see nothing is complaint and taskrun is applied successfully. But the expectation is that the taskrun should not be run and an error should be reported.
  2. Get the taskrun yaml kubectl get tr <TASKRUN_NAME> -o yaml
  3. You can see the taskResults echo-output has unexpected content because the parameter fooo doesn’t exits. And this should not happen.
...
  taskResults:
  - name: echo-output
    value: |2+

...

Additional Info

Normal behaviour when using unknown name in dot notation $(params.<name>).

  1. Change the echo command in step1’s yaml to echo $(params.fooo) | tee $(results.echo-output.path)
  2. apply that yaml file
  3. you can see the admission webhook will complaint, which is the expected behaviour when using unknown parameter names.
Error from server (BadRequest): error when creating "validation-test.yaml": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: non-existent variable in "set -e\necho $(params.fooo) | tee $(results.echo-output.path)\n": spec.taskSpec.steps[0].script

Kubernetes version:

Output of kubectl version:

Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:41:01Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.6-gke.1503", GitCommit:"2c7bbda09a9b7ca78db230e099cf90fe901d3df8", GitTreeState:"clean", BuildDate:"2022-02-18T03:17:45Z", GoVersion:"go1.16.9b7", Compiler:"gc", Platform:"linux/amd64"}
WARNING: version difference between client (1.23) and server (1.21) exceeds the supported minor version skew of +/-1

Tekton Pipeline version:

Output of tkn version or kubectl get pods -n tekton-pipelines -l app=tekton-pipelines-controller -o=jsonpath='{.items[0].metadata.labels.version}'

Client version: 0.21.0
Pipeline version: devel

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (15 by maintainers)

Most upvoted comments

After implementing the above fixes, I now get errors from the webhook if the names are inconsistent even with the bracket notation when I run this task:

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: validation-
spec:
  taskSpec:
    params:
      - name: foo
        type: string
        default: "bar"
    results:
      - name: echo-output
        description: "see echo output"
    steps:
      - name: echo-params
        image: bash
        script: |
          set -e
          echo $(params["fooo"]) | tee $(results.echo-output.path)
chitrang-macbookpro:pipeline chitrang$ ko create -f examples/v1beta1/chitrang/missing_brac.yaml
Error from server (BadRequest): error when creating "STDIN": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: non-existent variable in "set -e\necho $(params.fooo) | tee $(results.echo-output.path)\n": spec.taskSpec.steps[0].script
Error: error executing 'kubectl create': exit status 1
2022/04/29 15:18:34 error during command execution:error executing 'kubectl create': exit status 1

chitrang-macbookpro:pipeline chitrang$ vim examples/v1beta1/chitrang/missing_brac.yaml
chitrang-macbookpro:pipeline chitrang$ ko create -f examples/v1beta1/chitrang/missing_brac.yaml
Error from server (BadRequest): error when creating "STDIN": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: non-existent variable in "set -e\necho $(params['fooo']) | tee $(results.echo-output.path)\n": spec.taskSpec.steps[0].script
Error: error executing 'kubectl create': exit status 1
2022/04/29 15:19:21 error during command execution:error executing 'kubectl create': exit status 1

chitrang-macbookpro:pipeline chitrang$ vim examples/v1beta1/chitrang/missing_brac.yaml
chitrang-macbookpro:pipeline chitrang$ ko create -f examples/v1beta1/chitrang/missing_brac.yaml
Error from server (BadRequest): error when creating "STDIN": admission webhook "validation.webhook.pipeline.tekton.dev" denied the request: validation failed: non-existent variable in "set -e\necho $(params[\"fooo\"]) | tee $(results.echo-output.path)\n": spec.taskSpec.steps[0].script
Error: error executing 'kubectl create': exit status 1
2022/04/29 15:24:04 error during command execution:error executing 'kubectl create': exit status 1

To allow bracket notation to extract the variable properly, I think the regex pattern needs to be updated to

const braceMatchingRegex = "(\\$(\\(%s(\\.(?P<var1>%s)|\\[\"(?P<var2>%s)\"\\]|\\['(?P<var3>%s)'\\])\\)))"

And line needs to be replaced by something like:

		for _, v := range []string{"var1", "var2", "var3"} {
			val := strings.SplitN(groups[v], ".", 2)[0]
			if strings.SplitN(groups[v], ".", 2)[0] != "" {
				vars[i] = val
				break
			}

		}

I’m happy to take a stab at this and add some unit tests if you are not working on it @chuangw6.

Proposed Solution

Modify the extractVariablesFromString function to enable it to extract variable names from bracket notation reference strings. Currently, it can only extract variable names from dot notation reference strings.

Example:

current functionality

  • It can on extract foo from string $(params.foo) and extract foo[*] from string $(params.foo[*]), but it cannot extract foo from string $(params["foo"]) or $(params['foo'])

expect functionality

  • Also be able to extract foo from string $(params["foo"]) or $(params['foo'])