Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

output token cannot be used across jobs #66

Closed
unicornware opened this issue Oct 22, 2023 · 13 comments
Closed

output token cannot be used across jobs #66

unicornware opened this issue Oct 22, 2023 · 13 comments

Comments

@unicornware
Copy link

unicornware commented Oct 22, 2023

Current behavior

Output tokens cannot be used across jobs. This causes jobs that depend on said token to fail.

  1. Unless the skip-token-revoke input is set to a truthy value, the token is revoked in the post step of the action, which means it cannot be passed to another job.

Using skip-token-revoke does not allow a token to be used across jobs, which is what this wording seems to imply.

Possible solutions

  • opt-in to token masking + allow revoking token via action input (i.e action: 'revoke')
  • fix (clarify) documentation

Additional context

Action summary screenshot

Screen Shot 2023-10-22 at 4 31 32 AM

@smockle
Copy link
Contributor

smockle commented Oct 23, 2023

Hi, thanks for reporting this!

This is a “necessity and sufficiency” issue: Setting skip-token-revoke to a truthy value is necessary for cross-job token usage, but that alone is not sufficient for cross-job token usage. I’m open to updating the docs to make that more clear—is there specific phrasing you’d suggest?

I don’t think masking should be optional. Instead, we should document how to use tokens across jobs. There are a few workable techniques, such as ‘storing the token as a repository secret’ or ‘encrypting the token and outputting the (unmasked) encrypted value’. In your case, implementing one of these techniques would required you to add another step to your preflight job.

@gr2m
Copy link
Contributor

gr2m commented Oct 23, 2023

I think it would be great to document a working example of "use token across jobs" usecase in the README. And yes we should make clear that tokens cannot be passed as job output in clear text. I think the GitHub Actions documentation mentions it somewhere and suggests to use a secrets service, but I couldn't find it right now

@MarkIannucci
Copy link

We're running into the same frustration. Our use case is to pass the token from one job to a reusable workflow which consumes it downstream. Our reusable workflow is a wrapper around terraform, so refactoring it to get the token for itself reduces the genericity of the workflow which is currently configured to take in a generic secret. We're currently working around this using a classic PAT which GH suggests shouldn't be neceessary.

Here's the documentation that @gr2m is likely thinking about. It recommends sending the secret to hashicorp's vault and then fetching from it, which is not a light-weight approach for a secret which by definition is only valid for ten minutes.

As a customer of GitHub Enterprise, I'd like to see GH relax the ::add-mask:: functionality so that we can decide for ourselves if we want to be able to use the output in future workflow steps.

In the meantime, reading #55, it seems like @smockle may have a workable solution. Can you share how you're using the token you skip revoking?

@gr2m
Copy link
Contributor

gr2m commented Oct 24, 2023

I think even when the token is not masked by our action, and not revoked in the post job, GitHub will still not permit you to set an output to token that it recognizes as such, I ran into this before. There is some kind of automated masking in place for tokens.

@MarkIannucci
Copy link

MarkIannucci commented Oct 24, 2023

I realized I didn't say thank you to everyone who has contributed to this action. We're beginning to eliminate our PATs in our org, and this is trusted and helpful, which is exactly what we need.

Another use case we have is building container images. We have a reusable workflow for that, it needs to check out multiple internal repos to build the stuff and it can't because we can't pass the token from the job that fetches it to a build argument in the job that builds the stuff.

Elaborating on the ask to relax the ::add-mask:: and GITHUB_TOKEN sniffing and dropping functionality, I completely understand why the runner would do that in public repositories. Where I'm a bit confused is why GH wouldn't give the engineers working in internal repos the ability to make the decision on how to manage secret things in their workflows.

While I'm sure GH would prefer that there not be any tokens getting accidentally written to logs or exfiltrated, I suspect GH would be happier to have an app's 10 minute token get leaked than an individual or machine account's long lived PAT get leaked.

@gr2m
Copy link
Contributor

gr2m commented Oct 25, 2023

can you try writing the token to an environment variable and see if that environment variable is accessible in other jobs?

@MarkIannucci
Copy link

I assume by environment variable you're talking about using GITHUB_ENV? I tested that out in this repo using clear text data so it'd be easier to follow and I wasn't able to update an environment variable's value in one job and have it persist to the second :( Stepping through my test bench, I initially set environment variables for the workflow as a whole:

env:
  foo: bar

Then update it:

      - run: |
          echo "foo before we change it using the env command: $foo"
          echo "foo=baz" >> "$GITHUB_ENV"
          echo "foo after we change it using the env command -- note it is still what it was: $foo"
          echo "foo if we reference it in the env object: ${{env.foo}}"

Then echo it in a second step to validate that it was updated:

      - run: |
          echo "foo if we reference it in a second step: $foo"
          echo "foo if we reference it using the env object in a second step: ${{env.foo}}"

And finally I echo it in a second job to see if I can pass the value down the line:

  second-job:
    runs-on: ubuntu-latest
    needs: [first-job]
    steps:
      - run: |
          echo "foo in job two after it was updated by job one: $foo"

And unfortunately, I find that in the second job, $foo's value is bar

@gr2m
Copy link
Contributor

gr2m commented Nov 1, 2023

Thank you for testing this.

I reached out to the actions team, and unfortunately there is not a simple and safe solution to this problem. Feedback I got is

Not easily no, you'd need to store it in an artifact. You'd want to delete the artifact and ensure you're revoking token before the run ends.

The only way I can think is to re-run the create-github-app-token for each follow up job.

What exactly is your use case?

@unicornware
Copy link
Author

unicornware commented Nov 4, 2023

@smockle

thanks for the feedback! my computer was down for a little bit, so i'm still getting caught up 😅

This is a “necessity and sufficiency” issue: Setting skip-token-revoke to a truthy value is necessary for cross-job token usage, but that alone is not sufficient for cross-job token usage. I’m open to updating the docs to make that more clear—is there specific phrasing you’d suggest?

the bit before the phrasing question (adjusted for context, if necessary) would be perfect haha

I don’t think masking should be optional. Instead, we should document how to use tokens across jobs. There are a few workable techniques, such as ‘storing the token as a repository secret’ or ‘encrypting the token and outputting the (unmasked) encrypted value’. In your case, implementing one of these techniques would required you to add another step to your preflight job.

would it be possible to incorporate one of those suggestions into this action?

@gr2m
Copy link
Contributor

gr2m commented Nov 5, 2023

would it be possible to incorporate one of those suggestions into this action?

I would rather not. This is not working for a reason. I would rather document a workaround and explain why it is necessary. I think in many cases I would recommend to use the action in each job, instead of passing the token via jobs outputs.

@unicornware
Copy link
Author

i'm not a fan of copying one of those techniques from repo to repo, and there are a few cases where i'd rather not use the action in each job, so i'll most likely implement an action that suits more of my needs. this issue can be closed. thanks though!

@acuD1
Copy link

acuD1 commented Jun 11, 2024

Hi everyone,

I ran into this exact situation where I need to set up a token that can write to the registry. Before migrating to an organization, I used my own PAT, but now it's a bit more tricky, so we need a GitHub App.

After reading these topics, I would like to confirm that for now the only viable solution is to call this action before each job that needs a token ?

Thank you.

@gr2m
Copy link
Contributor

gr2m commented Jun 11, 2024

the only viable solution is to call this action before each job that needs a token

Yes, that is correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants