diff --git a/api/build/cancel.go b/api/build/cancel.go index 40e165287..178d66ed2 100644 --- a/api/build/cancel.go +++ b/api/build/cancel.go @@ -15,7 +15,6 @@ import ( "github.com/go-vela/server/api/types" "github.com/go-vela/server/cache" - "github.com/go-vela/server/compiler/types/yaml" "github.com/go-vela/server/constants" "github.com/go-vela/server/database" "github.com/go-vela/server/internal/token" @@ -161,7 +160,7 @@ func CancelBuild(c *gin.Context) { var scmToken string if b.GetRepo().GetInstallID() != 0 { - scmToken, _, err = scm.FromContext(c).GetNetrcPassword(ctx, database.FromContext(c), cache.FromContext(c), b, yaml.Git{}) + scmToken, _, err = scm.FromContext(c).GetNetrcPassword(ctx, database.FromContext(c), cache.FromContext(c), b, nil, nil) if err != nil { l.Errorf("unable to generate new installation token for build %s: %v", entry, err) diff --git a/api/webhook/post.go b/api/webhook/post.go index 15d74c6bb..8a2c1d2f7 100644 --- a/api/webhook/post.go +++ b/api/webhook/post.go @@ -483,7 +483,21 @@ func PostWebhook(c *gin.Context) { util.HandleError(c, code, err) - err = scm.FromContext(c).Status(ctx, b, p.Token) + // send status update with proper token + var scmToken string + + if repo.GetInstallID() != 0 { + scmToken, _, err = scm.FromContext(c).GetNetrcPassword(ctx, database.FromContext(c), cache.FromContext(c), b, nil, nil) + if err != nil { + l.Errorf("unable to generate installation token for failed compile status %s: %v", repo.GetFullName(), err) + + return + } + } else { + scmToken = repo.GetOwner().GetToken() + } + + err = scm.FromContext(c).Status(ctx, b, scmToken) if err != nil { l.Debugf("unable to set commit status for %s/%d: %v", repo.GetFullName(), b.GetNumber(), err) } diff --git a/compiler/native/compile.go b/compiler/native/compile.go index c4bc1c917..4608ccca4 100644 --- a/compiler/native/compile.go +++ b/compiler/native/compile.go @@ -50,7 +50,7 @@ func (c *Client) Compile(ctx context.Context, v any) (*pipeline.Build, *api.Pipe // netrc can be provided directly using WithNetrc for situations like local exec if c.netrc == nil && c.scm != nil { // get the netrc password from the scm - netrc, exp, err := c.scm.GetNetrcPassword(ctx, c.db, c.cache, c.build, p.Git) + netrc, exp, err := c.scm.GetNetrcPassword(ctx, c.db, c.cache, c.build, p.Git.Repositories, p.Git.Permissions) if err != nil { return nil, nil, err } diff --git a/scm/github/repo.go b/scm/github/repo.go index e0b415296..64f10e451 100644 --- a/scm/github/repo.go +++ b/scm/github/repo.go @@ -15,7 +15,6 @@ import ( api "github.com/go-vela/server/api/types" "github.com/go-vela/server/cache" - "github.com/go-vela/server/compiler/types/yaml" "github.com/go-vela/server/constants" "github.com/go-vela/server/database" ) @@ -488,7 +487,7 @@ func (c *Client) GetBranch(ctx context.Context, r *api.Repo, branch string) (str // GetNetrcPassword returns a clone token using the repo's github app installation if it exists. // If not, it defaults to the user OAuth token. -func (c *Client) GetNetrcPassword(ctx context.Context, db database.Interface, tknCache cache.Service, b *api.Build, g yaml.Git) (string, int64, error) { +func (c *Client) GetNetrcPassword(ctx context.Context, db database.Interface, tknCache cache.Service, b *api.Build, repos []string, perms map[string]string) (string, int64, error) { r := b.GetRepo() u := b.GetRepo().GetOwner() @@ -506,11 +505,6 @@ func (c *Client) GetNetrcPassword(ctx context.Context, db database.Interface, tk var err error - // repos that the token has access to - // providing no repos, nil, or empty slice will default the token permissions to the list - // of repos added to the installation - repos := g.Repositories - // enforce max number of repos allowed for token // // this prevents a large number of access checks for the repo owner @@ -541,8 +535,8 @@ func (c *Client) GetNetrcPassword(ctx context.Context, db database.Interface, tk permissions["deployments"] = constants.PermissionWrite } - if len(g.Permissions) > 0 { - permissions = g.Permissions + if len(perms) > 0 { + permissions = perms normalizePermissions(permissions) } @@ -550,7 +544,7 @@ func (c *Client) GetNetrcPassword(ctx context.Context, db database.Interface, tk // verify repo owner has `write` access to listed repositories before provisioning install token // // this prevents an app installed across the org from bypassing restrictions - for _, repo := range g.Repositories { + for _, repo := range repos { if repo == r.GetName() { continue } diff --git a/scm/github/repo_test.go b/scm/github/repo_test.go index e346c4422..0d5e6ca7c 100644 --- a/scm/github/repo_test.go +++ b/scm/github/repo_test.go @@ -17,7 +17,6 @@ import ( "github.com/google/go-github/v84/github" api "github.com/go-vela/server/api/types" - "github.com/go-vela/server/compiler/types/yaml" "github.com/go-vela/server/constants" ) @@ -1277,52 +1276,41 @@ func TestGithub_GetNetrcPassword(t *testing.T) { name string repo *api.Repo user *api.User - git yaml.Git + repos []string + perms map[string]string appsTransport bool wantToken string wantExp int64 wantErr bool }{ { - name: "installation token", - repo: installedRepo, - user: u, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - Permissions: map[string]string{"contents": "read"}, - }, - }, + name: "installation token", + repo: installedRepo, + user: u, + repos: []string{"Hello-World"}, + perms: map[string]string{"contents": "read"}, appsTransport: true, wantToken: "ghs_16C7e42F292c6912E7710c838347Ae178B4a", wantExp: 1468275250, wantErr: false, }, { - name: "no app configured returns user oauth token", - repo: installedRepo, - user: u, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - Permissions: map[string]string{"contents": "read"}, - }, - }, + name: "no app configured returns user oauth token", + repo: installedRepo, + user: u, + repos: []string{"Hello-World"}, + perms: map[string]string{"contents": "read"}, appsTransport: false, wantToken: "bar", wantExp: 0, wantErr: false, }, { - name: "repo not installed returns user oauth token", - repo: oauthRepo, - user: u, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - Permissions: map[string]string{"contents": "read"}, - }, - }, + name: "repo not installed returns user oauth token", + repo: oauthRepo, + user: u, + repos: []string{"Hello-World"}, + perms: map[string]string{"contents": "read"}, appsTransport: true, wantToken: "bar", wantExp: 0, @@ -1338,44 +1326,32 @@ func TestGithub_GetNetrcPassword(t *testing.T) { wantErr: false, }, { - name: "invalid permission resource", - repo: installedRepo, - user: u, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - Permissions: map[string]string{"invalid": "read"}, - }, - }, + name: "invalid permission resource", + repo: installedRepo, + user: u, + repos: []string{"Hello-World"}, + perms: map[string]string{"invalid": "read"}, appsTransport: true, wantToken: "bar", wantExp: 0, wantErr: false, }, { - name: "invalid permission level", - repo: installedRepo, - user: u, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - Permissions: map[string]string{"contents": "invalid"}, - }, - }, + name: "invalid permission level", + repo: installedRepo, + user: u, + repos: []string{"Hello-World"}, + perms: map[string]string{"contents": "invalid"}, appsTransport: true, wantToken: "bar", wantExp: 0, wantErr: false, }, { - name: "owner with inadequate permission to other repo", - repo: otherRepo, - user: badUser, - git: yaml.Git{ - Token: yaml.Token{ - Repositories: []string{"Hello-World"}, - }, - }, + name: "owner with inadequate permission to other repo", + repo: otherRepo, + user: badUser, + repos: []string{"Hello-World"}, appsTransport: true, wantToken: "bar", wantExp: 0, @@ -1395,7 +1371,7 @@ func TestGithub_GetNetrcPassword(t *testing.T) { testBuild := new(api.Build) testBuild.SetRepo(test.repo) - got, gotExp, err := client.GetNetrcPassword(t.Context(), nil, nil, testBuild, test.git) + got, gotExp, err := client.GetNetrcPassword(t.Context(), nil, nil, testBuild, test.repos, test.perms) if (err != nil) != test.wantErr { t.Errorf("GetNetrcPassword() error = %v, wantErr %v", err, test.wantErr) return diff --git a/scm/service.go b/scm/service.go index 1d5c0d4b0..d01427888 100644 --- a/scm/service.go +++ b/scm/service.go @@ -10,7 +10,6 @@ import ( "github.com/go-vela/server/api/types/settings" "github.com/go-vela/server/cache" "github.com/go-vela/server/cache/models" - "github.com/go-vela/server/compiler/types/yaml" "github.com/go-vela/server/database" "github.com/go-vela/server/internal" ) @@ -151,7 +150,7 @@ type Service interface { GetHTMLURL(context.Context, *api.User, string, string, string, string) (string, error) // GetNetrcPassword defines a function that returns the netrc // password injected into build steps. - GetNetrcPassword(context.Context, database.Interface, cache.Service, *api.Build, yaml.Git) (string, int64, error) + GetNetrcPassword(context.Context, database.Interface, cache.Service, *api.Build, []string, map[string]string) (string, int64, error) // SyncRepoWithInstallation defines a function that syncs // a repo with the installation, if it exists. SyncRepoWithInstallation(context.Context, *api.Repo) (*api.Repo, error)