Add a --actions-admin-user flag

Same as in here
33463970b8/internal/push/push.go (L106-L113)

Add a warning about the missing site_admin scope in the token
Add a way to ignore the actions admin impersonation.
This commit is contained in:
Denys Zhuravel
2022-09-09 09:32:08 +00:00
parent 51405dbbd5
commit 7ef65dedf2

View File

@@ -17,9 +17,14 @@ import (
"golang.org/x/oauth2"
)
const enterpriseAegisVersionHeaderValue = "GitHub AE"
const enterpriseAPIPath = "/api/v3"
const enterpriseVersionHeaderKey = "X-GitHub-Enterprise-Version"
const xOAuthScopesHeader = "X-OAuth-Scopes"
type PushOnlyFlags struct {
BaseURL, Token string
DisableGitAuth bool
BaseURL, Token, ActionsAdminUser string
DisableGitAuth bool
}
type PushFlags struct {
@@ -34,6 +39,7 @@ func (f *PushFlags) Init(cmd *cobra.Command) {
func (f *PushOnlyFlags) Init(cmd *cobra.Command) {
cmd.Flags().StringVar(&f.BaseURL, "destination-url", "", "URL of GHES instance")
cmd.Flags().StringVar(&f.ActionsAdminUser, "actions-admin-user", "actions-admin", "The name of the Actions admin user. Pass '-' to disable the impersonation")
cmd.Flags().StringVar(&f.Token, "destination-token", "", "Token to access API on GHES instance")
cmd.Flags().BoolVar(&f.DisableGitAuth, "disable-push-git-auth", false, "Disables git authentication whilst pushing")
}
@@ -53,7 +59,62 @@ func (f *PushOnlyFlags) Validate() Validations {
return validations
}
func GetImpersonationToken(ctx context.Context, flags *PushFlags) (string, error) {
fmt.Printf("Getting an impersonation token for `%s`..\n", flags.ActionsAdminUser)
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: flags.Token})
tc := oauth2.NewClient(ctx, ts)
ghClient, err := github.NewEnterpriseClient(flags.BaseURL, flags.BaseURL, tc)
if err != nil {
return "", errors.Wrap(err, "error creating enterprise client")
}
rootRequest, err := ghClient.NewRequest("GET", enterpriseAPIPath, nil)
if err != nil {
return "", errors.Wrap(err, "Error constructing request for GitHub Enterprise client.")
}
rootResponse, err := ghClient.Do(ctx, rootRequest, nil)
if err != nil {
return "", errors.Wrap(err, "Error checking connectivity for GitHub Enterprise client.")
}
scopesHeader := rootResponse.Header.Get(xOAuthScopesHeader)
fmt.Printf("These are the scopes we have for the current token `%s`..\n", scopesHeader)
isAE := rootResponse.Header.Get(enterpriseVersionHeaderKey) == enterpriseAegisVersionHeaderValue
minimumRepositoryScope := "public_repo"
if isAE {
// the default repository scope for non-ae instances is 'public_repo'
// while it is `repo` for ae.
minimumRepositoryScope = "repo"
fmt.Printf("Running against GitHub AE, changing the repository scope to '%s'..\n", minimumRepositoryScope)
} else {
if !strings.Contains(scopesHeader, "site_admin") {
fmt.Printf("The current token doesn't have the `site_admin` scope. The impersonation request for GHES requres the `site_admin` permission to be able to impersonate. For GitHub AE it's not required.")
}
}
impersonationToken, _, err := ghClient.Admin.CreateUserImpersonation(ctx, flags.ActionsAdminUser, &github.ImpersonateUserOptions{Scopes: []string{minimumRepositoryScope, "workflow"}})
if err != nil {
return "", errors.Wrap(err, "Failed to impersonate Actions admin user.")
}
fmt.Printf("Got the impersonation token for `%s`..\n", flags.ActionsAdminUser)
return impersonationToken.GetToken(), nil
}
func Push(ctx context.Context, flags *PushFlags) error {
if flags.ActionsAdminUser != "-" {
var token, err = GetImpersonationToken(ctx, flags)
if err != nil {
return errors.Wrap(err, "error obtaining the impersonation token")
}
// Override the initial token with the one that we got in the exchange
flags.Token = token
}
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: flags.Token})
tc := oauth2.NewClient(ctx, ts)
ghClient, err := github.NewEnterpriseClient(flags.BaseURL, flags.BaseURL, tc)