I got a problem I hope some kind soul in this chan...
# python
i
I got a problem I hope some kind soul in this channel will shed some light on. I am trying to create Github environment secrets and failing miserably at it. As always the documentation is almost non-existent and the Pulumi Artificial Idiot is useless. Going by these Github issues: https://github.com/pulumi/pulumi/discussions/9377 https://github.com/pulumi/pulumi-github/issues/248#issue-1393340785 I have to encrypt the plaintext values of the secrets using the Github repo public key before uploading them to the environment. The problem I am encountering is that no matter what I do I am getting the following error:
Copy code
error: 1 error occurred:
        * PUT <https://api.github.com/repositories/REPO_ID/environments/ENVIRONMENT_NAME/secrets/CLIENT_ID>: 422 Bad request - validation failed due to an improperly encrypted secret []
I have tried the procedure outlined here: https://docs.github.com/en/rest/guides/encrypting-secrets-for-the-rest-api?apiVersion=2022-11-28#example-encrypting-a-secret-using-python as well as the one in those two Github issues but I had no luck. When I try to get the repository key I am getting two different values, depending on what I use. If I try to get the public key through Pulumi, using the get_actions_public_key function I get one value. If I try to get using the Github CLI and the API I get another value. Halp pls.
m
Can you show the relevant part of your code? Can you create a secret by providing the plaintext value, or does that fail as well?
Pulumi uses the Terraform provider under the hood (via the Pulumi Terraform bridge) so you can also refer to the upstream docs as well: https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_environment_secret
i
here's the code:
Copy code
#Github repository public key
public_key=github.get_actions_public_key(
    repository="DevOps",
)

#repository
existing_repo=github.get_repository(
    full_name="organization/DevOps",
)
#repository environment
test_env=github.RepositoryEnvironment(
    "test-env",
    repository=existing_repo.name,
    environment="test",
    can_admins_bypass=True
)

# function to encrypt the secret's value
# this is based off pynacl
def encrypt_github_action_secret(public_encryption_key: str, secret_value: str) -> str:
    public_key = public.PublicKey(public_encryption_key.encode("utf-8"), encoding.Base64Encoder())
    sealed_box = public.SealedBox(public_key)
    encrypted = sealed_box.encrypt(secret_value.encode("utf-8"))
    return b64encode(encrypted).decode("utf-8")


encrypted_secret = encrypt_github_action_secret(public_encryption_key=public_key.key, secret_value="whatever")

# creating the actual environment secret
github.ActionsEnvironmentSecret(
    "test-client-id",
    environment=test_env.environment,
    repository="DevOps",
    secret_name="CLIENT_ID",
    encrypted_value=encrypted_secret,
)
And yes I can create a secret by providing a plaintext value
The secret is there, the environment is there, but when running the action none of those secrets have values
m
Have you tried to confirm that your encryption function generates the correct output?
For example, by creating your own public key and making a roundtrip? This could very well be an encoding issue.
i
No I have not
I have wasted way too much time on this already and I am not sure I want to waste any more
I was hoping that there was either some glaring error in the code or that someone has encountered this
at this point it might be faster to just use the pulumi command and do everything through Github CLI
instead of going deeper into this particular rabbit hole
f
yeah i'm inclined to believe this is an encoding issue, lookin now
e.g.
sealed_box.encrypt
returns a "composed ciphertext", containing both the public part of the keypair and the ciphertext proper, encoded with the encoder."
m
I think if you take the example at https://pynacl.readthedocs.io/en/latest/public/#nacl-public-box and plug in your encryption function in-between this should help figure out where things go wrong
☝️ 1
And then perhaps you could make a PR for the Pulumi docs with the proper encryption function
i
there's also the fact that I am getting different public keys depending on what I use using curl: curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer <token>" https://api.github.com/repositories/834197836/environments/sikrit/secrets/public-key { "key_id": "3380204578043523366", "key": "blahblah" } using the get_actions_public_key I get a completely different value
👀 1
m
Per the docs, you should use the organization's public key, no? https://www.pulumi.com/registry/packages/github/api-docs/getactionsorganizationpublickey/
i
based on the discussion in those two Github issues
m
Yes, I might also be wrong here.
i
I can try the org pulbic key
m
You're updating an environment secret, right?
i
I am creating it from scratch
m
i
and that's what I was using
I tried both values, the one obtained through curl and the one obtained through get_actions_public_key
in both cases I am getting the same error
422 Bad request - validation failed due to an improperly encrypted secret
m
☝️ 1
i
I'll get a better lock at that sealed box
in one form or another, this has been a problem since 2022
m
It looks like it's not possible to retrieve the environment public key via Pulumi or Terraform
f
yeah, hm
i
even if I plug the key I got using the curl it's still not working
m
The relevant API endpoint is not exposed it seems
even if I plug the key I got using the curl it's still not working
But can you do it fully via curl?
f
wonder what
gh
does
i
that's github CLI
gh api \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ /repos/OWNER/REPO/environments/ENVIRONMENT/secrets/public-key { "key_id": "3380204578043523366", "key": "blahblah" }
I got it, I used it, it did not work
f
i
I was able to PUT the environment secret slobodan@slobodan:~$ gh api \ --method PUT \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ /repos/OWNER/REPO/environments/ENVIRONMENT/secrets/SECRETNAME \ -f "encrypted_value=<the usual alphanumeric mess>" -f "key_id=1234567890" {}
it's time for a break
💯 1
and a stiff drink
thanks for your help
f
so it worked fine if you manually got the environment's public key, encrypted the secret with that, and manually PUT the encrypted secret?
one other thought here: even by using
plaintext_value
via pulumi the PUT request's secret value to github is encrypted in transit, so you could use a pulumi secret to keep the value encrypted at rest and it would be sent encrypted to github. verified via local proxy
in other words, I don't think the docs anywhere (gh, tf, pulumi) are clear enough 😆