From 8424056b037312c9fe963af8df791cfed261cc52 Mon Sep 17 00:00:00 2001 From: Charlie McNeill Date: Wed, 10 Apr 2024 14:01:19 +0100 Subject: [PATCH] [vergo:minor-release] Use Bearer auth if presented with the GITHUB_TOKEN env variable (#17) --- CHANGELOG.md | 4 +++ GNUmakefile | 2 +- README.md | 14 ++++++++++ git/git.go | 65 +++++++++++++++++++++++++++++----------------- release/release.go | 2 +- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf3944..3620a01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [0.28.0] - 09-04-2024 +Prefers to use the GITHUB_TOKEN Bearer authentication over SSH if the environment variable is present. +This is useful when pushing tags using GitHub actions. + ## [0.27.0] - 08-02-2023 Fixed bug introduced in version `0.21.0` where `vergo bump` and `vergo check` would fail if the current commit is not the latest on a versioned branch e.g. `master` or `main`. diff --git a/GNUmakefile b/GNUmakefile index d4669fc..8485a57 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -3,7 +3,7 @@ export GORELEASER_VERSION := 0.179.0 -LINTER_VERSION := 1.46.2 +LINTER_VERSION := 1.53.3 PATH := $(shell pwd)/bin:$(PATH) SHELL := bash diff --git a/README.md b/README.md index 249314a..3d26227 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,20 @@ You can address the error `ssh: handshake failed: knownhosts: key is unknown ` w - Calling `ssh-keyscan -H github.com >> ~/.ssh/known_hosts` prior to pushing your vergo tag to introduce github to your known hosts. - Calling `vergo` with the `--disable-strict-host-check` flag. This should only be used on CI where known hosts are not cached. +## Using GITHUB_TOKEN inside GitHub Actions + +Vergo will first try to use Token Bearer Authentication using the GITHUB_TOKEN environment variable when running inside a GitHub Action/Workflow. It will fallback to ssh based authentication if the GITHUB_TOKEN is not present. + +Inside github actions please ensure that the GITHUB_TOKEN environment variable is set with the `${{ secrets.GITHUB_TOKEN }}` in order to push to the current repository. + +Please see [token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow) for further details. + +The GITHUB_TOKEN will require the following permissions to be able to push: +```yaml + permissions: + contents: write +``` + ## Running Locally - SSH Key Failures You can address the error `FATA[0000] failed to get signers, make sure to add private key identities to the authentication agent error=""` when pushing tags with vergo by: - Calling `ssh-add ~/.ssh/` to add your github ssh key to the ssh agent diff --git a/git/git.go b/git/git.go index fbccd30..8c3b853 100644 --- a/git/git.go +++ b/git/git.go @@ -9,6 +9,9 @@ import ( "sort" "strings" + "github.com/go-git/go-git/v5/plumbing/transport" + "github.com/go-git/go-git/v5/plumbing/transport/http" + "github.com/Masterminds/semver/v3" gogit "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" @@ -118,33 +121,30 @@ type PushTagFunc func( func PushTag(r *gogit.Repository, version, prefix, remote string, dryRun bool, disableStrictHostChecking bool) error { tag := prefix + version - socket, found := os.LookupEnv("SSH_AUTH_SOCK") - if !found { - return ErrUndefinedSSHAuthSock - } - - conn, err := net.Dial("unix", socket) - if err != nil { - log.WithError(err).Fatalln("Failed to open SSH_AUTH_SOCK") - } + var auth transport.AuthMethod - agentClient := agent.NewClient(conn) - defer func() { - _ = conn.Close() - }() + if githubToken, ok := os.LookupEnv("GITHUB_TOKEN"); ok { + log.Debug("Using Github Bearer Token Auth") + auth = &http.TokenAuth{ + Token: githubToken, + } + } else if socket, ok := os.LookupEnv("SSH_AUTH_SOCK"); ok { + log.Debug("Using SSH Agent Authentication") + conn, err := net.Dial("unix", socket) + if err != nil { + log.WithError(err).Fatalln("Failed to open SSH_AUTH_SOCK") + } - signers, err := agentClient.Signers() - if err != nil || len(signers) == 0 { - log.WithError(err).Fatalln("failed to get signers, make sure to add private key identities to the authentication agent") - } + agentClient := agent.NewClient(conn) + defer func() { + _ = conn.Close() + }() - auth := &ssh.PublicKeys{ - User: "git", - Signer: signers[0], - } + sshAuth := generateSshAuth(agentClient, disableStrictHostChecking) - if disableStrictHostChecking { - auth.HostKeyCallback = cryptossh.InsecureIgnoreHostKey() + auth = sshAuth + } else { + return ErrUndefinedSSHAuthSock } log.Debugf("Pushing tag: %v", tag) @@ -159,7 +159,7 @@ func PushTag(r *gogit.Repository, version, prefix, remote string, dryRun bool, d if dryRun { log.Infof("Dry run: push tag %v", tag) } else { - err = r.Push(po) + err := r.Push(po) if err != nil { if errors.Is(err, gogit.NoErrAlreadyUpToDate) { @@ -173,6 +173,23 @@ func PushTag(r *gogit.Repository, version, prefix, remote string, dryRun bool, d return nil } +func generateSshAuth(agentClient agent.ExtendedAgent, disableStrictHostChecking bool) *ssh.PublicKeys { + signers, err := agentClient.Signers() + if err != nil || len(signers) == 0 { + log.WithError(err).Fatalln("failed to get signers, make sure to add private key identities to the authentication agent") + } + + sshAuth := &ssh.PublicKeys{ + User: "git", + Signer: signers[0], + } + + if disableStrictHostChecking { + sshAuth.HostKeyCallback = cryptossh.InsecureIgnoreHostKey() + } + return sshAuth +} + func ListRefs(repo *gogit.Repository, prefix string, direction SortDirection, maxListSize int) ([]SemverRef, error) { versions, err := refsWithPrefix(repo, prefix) if err != nil { diff --git a/release/release.go b/release/release.go index d0c2991..84048ce 100644 --- a/release/release.go +++ b/release/release.go @@ -90,7 +90,7 @@ func ValidateHEAD(repo *gogit.Repository, remoteName string, versionedBranches [ validRef := false for _, mainBranchName := range versionedBranches { remote, err := repo.Remote(remoteName) - if err != nil && err != gogit.ErrRemoteNotFound { + if err != nil && !errors.Is(err, gogit.ErrRemoteNotFound) { return err } var branchRef plumbing.ReferenceName