Skip to content

Add an integration test or example on how to use the addOrUpdateRepoSecret function. #1607

Description

@raboley

I wanted to use this library to push secrets from my env to my github repo easily, and eventually got it figured out. But It would be very helpful to have an example of how to do that since it requires sodiumlib which is extremely difficult to parse if you are trying to figure out the bare minimum needed to encrypt a secret for posting to github.

essentially what I had to do to update the repo's secret was

Authenticate with github

func GithubAuth() (context.Context, *github.Client, error) {
	token := os.Getenv("API_GITHUB_TOKEN")
	if token == "" {
		return nil, nil, errors.New(`no API_GITHUB_TOKNE was found in the environment variables.
This is needed to authenticate with github. Please generate a github token that has access to do what you are trying to do
and export it as an environment variable.

ex:
	export API_GITHUB_TOKEN="<token contents string>"
`)
	}
	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)
	return ctx, client, nil
}

Get the base64 encoded public key of the repo to encrypt a secret using sodiumlib

publicKey, _, err := client.Actions.GetRepoPublicKey(ctx, owner, repo)

encrypt the secret string with the public key

func encryptSecretWithPublicKey(publicKey *github.PublicKey, secretName string, secretValue string) (*github.EncryptedSecret, error) {
	decodedPublicKey, err := base64.StdEncoding.DecodeString(publicKey.GetKey())
	if err != nil {
		return nil, errors.New(fmt.Sprintf("base64.StdEncoding.DecodeString was unable to decode public key: %v", err))
	}

	secretBytes := []byte(secretValue)
	encryptedBytes, exit := sodium.CryptoBoxSeal(secretBytes, decodedPublicKey)
	if exit != 0 {
		return nil, errors.New("sodium.CryptoBoxSeal exited with non zero exit code")
	}

	encryptedString := base64.StdEncoding.EncodeToString(encryptedBytes)
	keyID := publicKey.GetKeyID()
	encryptedSecret := &github.EncryptedSecret{
		Name:           secretName,
		KeyID:          keyID,
		EncryptedValue: encryptedString,
	}
	return encryptedSecret, nil
}

bring it all together with AddRepoSecret function

func AddRepoSecret(owner string, repo string, secretName string, secretValue string) (string, error) {
	ctx, client, err := GithubAuth()
	if err != nil {
		return "", err
	}
	publicKey, _, err := client.Actions.GetRepoPublicKey(ctx, owner, repo)
	if err != nil {
		return "", err
	}

	encryptedSecret, err := encryptSecretWithPublicKey(publicKey, secretName, secretValue)
	if err != nil {
		return "", err
	}

	_, err = client.Actions.CreateOrUpdateRepoSecret(ctx, owner, repo, encryptedSecret)
	if err != nil {
		return "", errors.New(fmt.Sprintf("Actions.CreateOrUpdateRepoSecret returned error: %v", err))
	}

	return secretName, nil
}

Hopefully this helps someone, if there is a direction I should take I can work to contribute this back in some form or another.

Activity

  1. gmlewis commented on Aug 17, 2020

    @gmlewis
    Collaborator

    Thank you, @raboley !

    Please check out our "example" directory: https://github.com/google/go-github/tree/master/example
    and consider adding a new directory with a simple example showing what you did.
    You should be able to see how the other examples were put together and do something similar.

    Also, please make sure to read through our CONTRIBUTING.md file to get started on putting together a PR.

  2. vamsee47 commented on Aug 17, 2020

    @vamsee47

    good

  3. myungkwon commented on Aug 17, 2020

    @myungkwon

    x

  4. raboley commented on Sep 3, 2020

    @raboley
    ContributorAuthor

    @gmlewis Thank you for the notes! Sorry for the delay, I have create PR #1626 to add an example of this the best I could. I signed the contributing agreement, and tried to follow any direction and other examples as I could! Due to mine requiring 3rd party libraries and more complexity than I would have liked the example isn't quite as simple as others, but hopefully it makes it clear enough. Open to any feedback!

  5. raboley commented on Sep 12, 2020

    @raboley
    ContributorAuthor

    closed by #1626

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions