woodpecker-ci / woodpecker

Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.
https://woodpecker-ci.org
Apache License 2.0
4.1k stars 354 forks source link

Use variables for secrets #2375

Open lonix1 opened 1 year ago

lonix1 commented 1 year ago

Clear and concise description of the problem

According to the docs, a secret is supplied to the step as an uppercase environment variable.

For example, here are two global secrets named docker_username and docker_password:

steps:
  docker:
    image: docker
    commands:
      - echo $DOCKER_USERNAME
      - echo $DOCKER_PASSWORD
    secrets: [ docker_username, docker_password ]

That works, but isn't convenient - one will probably use those secrets multiple times in the same pipeline.

Suggested solution

So it's better and more maintainable to use variables, for example:

variables:
  - &SECRET bearer_token

steps:

  restore:
    image: some_sdk
    commands:
      - restore packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET

  push:
    image: some_sdk
    commands:
      - push packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET

  deploy:
    image: some_sdk
    commands:
      - deploy packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET

  other:
    # etc.

Notice how the SECRET variable is used, but one must nonetheless use the uppercase of the actual secret name BEARER_TOKEN. So in this case using a variable adds no value.

Please consider allowing this common use case? Then we could write this pipeline which is more sensible:

variables:
  - &SECRET bearer_token

steps:

  restore:
    image: some_sdk
    commands:
      - restore packages --api-token "$SECRET"      # <---- SECRET instead of BEARER_TOKEN
    secrets: *SECRET

  push:
    image: some_sdk
    commands:
      - push packages --api-token "$SECRET"         # <---- SECRET instead of BEARER_TOKEN
    secrets: *SECRET

  deploy:
    image: some_sdk
    commands:
      - deploy packages --api-token "$SECRET"       # <---- SECRET instead of BEARER_TOKEN
    secrets: *SECRET

  other:
    # etc.

Alternative

No response

Additional context

No response

Validations

qwerty287 commented 12 months ago

I don't think we'll add this because it adds to much complexity without having a really enhanced ux. However, if I remember correctly, secret resolving is case-insenstive, so you can set your SECRET variable to the uppercase value.

lonix1 commented 12 months ago

Thanks.

adds to much complexity

I believe you.

without having a really enhanced ux

I suppose it's different for different people / use cases, but ok!

set your SECRET variable to the uppercase value

Do you mean like this:

variables:
- - &SECRET bearer_token
+ - &SECRET BEARER_TOKEN

I'm unsure how that improves the issue?

qwerty287 commented 12 months ago

Do you mean like this:

Yes, that's what I mean.

I'm unsure how that improves the issue?

Wasn't this your issue? You wanted to use the same yaml var for both secret resolving and accessing. Or did I understand you wrong?

lonix1 commented 12 months ago

But then the result is this:

variables:
  - &SECRET BEARER_TOKEN                                # <----- uppercase

steps:

  restore:
    image: some_sdk
    commands:
      - restore packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET                                    # <--- useless

  push:
    image: some_sdk
    commands:
      - push packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET                                    # <--- useless

  deploy:
    image: some_sdk
    commands:
      - deploy packages --api-token "$BEARER_TOKEN"
    secrets: *SECRET                                    # <--- useless

  other:
    # etc.

If I'm understanding correctly, it's as before - one still needs to use "$BEARER_TOKEN" in the steps, so the secret does not serve any purpose.

qwerty287 commented 12 months ago

Ah now I see, you want to use yaml vars in the commands?

lonix1 commented 12 months ago

Yes - the idea is when a secret is used many times in a pipeline (a good example is a token) then it's more maintainable to use a variable instead.

But I understand your point above that this is very complex.

anbraten commented 12 months ago

Secrets are not available to the pre-processor. When using a var with a single $ the pre-processor tries to resolve it when compiling the config. In your case you could try to expose it to your terminal with - secrets: ... and use it in the commands with - deploy packages --api-token "$${BEARER_TOKEN}" (to mention I am not really happy with the pre-processor syntax being "normal" bash syntax, but a change would be huge breaking change)