diff --git a/internal/cmd/setup.go b/internal/cmd/setup.go index 876f4b91..21a80bf4 100644 --- a/internal/cmd/setup.go +++ b/internal/cmd/setup.go @@ -448,6 +448,14 @@ a fork of the repository you want to protect. fmt.Printf("\n â„šī¸ Controls already enabled on %s\n\n", opts.GetRepository().Path) return nil } + + if errors.Is(err, models.ErrRepositoryAccessDenied) { + fmt.Printf("\n 🔐 %s sourcetool does not have access to %s\n\n", colorHiRed("Error:"), opts.GetRepository().Path) + fmt.Println() + fmt.Printf("Please run %s again and grant the app access\n", w("sourcetool auth login")) + fmt.Println("to the repository or organization.") + return nil + } return fmt.Errorf("configuring controls: %w", err) } diff --git a/pkg/ghcontrol/checklevel.go b/pkg/ghcontrol/checklevel.go index 4d37bfc4..c718f0d7 100644 --- a/pkg/ghcontrol/checklevel.go +++ b/pkg/ghcontrol/checklevel.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "log" + "net/http" "slices" "time" @@ -249,7 +250,7 @@ func (ghc *GitHubConnection) EnableBranchRules(ctx context.Context) error { } // Create the SLSA ruleset - if _, _, err := ghc.Client().Repositories.CreateRuleset(ctx, ghc.Owner(), ghc.Repo(), github.RepositoryRuleset{ + if _, resp, err := ghc.Client().Repositories.CreateRuleset(ctx, ghc.Owner(), ghc.Repo(), github.RepositoryRuleset{ Name: "SLSA Branch Controls", Target: github.Ptr(github.RulesetTargetBranch), Enforcement: EnforcementActive, @@ -265,6 +266,9 @@ func (ghc *GitHubConnection) EnableBranchRules(ctx context.Context) error { NonFastForward: &github.EmptyRuleParameters{}, }, }); err != nil { + if resp.StatusCode == http.StatusNotFound { + return models.ErrRepositoryAccessDenied + } return fmt.Errorf("creating branch protection ruleset: %w", err) } @@ -290,7 +294,7 @@ func (ghc *GitHubConnection) EnableTagRules(ctx context.Context) error { } // Create the SLSA ruleset - if _, _, err := ghc.Client().Repositories.CreateRuleset(ctx, ghc.Owner(), ghc.Repo(), github.RepositoryRuleset{ + if _, resp, err := ghc.Client().Repositories.CreateRuleset(ctx, ghc.Owner(), ghc.Repo(), github.RepositoryRuleset{ Name: "SLSA Tag Controls", Target: github.Ptr(github.RulesetTargetTag), Enforcement: EnforcementActive, @@ -309,6 +313,9 @@ func (ghc *GitHubConnection) EnableTagRules(ctx context.Context) error { }, }, }); err != nil { + if resp.StatusCode == http.StatusNotFound { + return models.ErrRepositoryAccessDenied + } return fmt.Errorf("creating tag protection ruleset: %w", err) } diff --git a/pkg/sourcetool/models/models.go b/pkg/sourcetool/models/models.go index b37da3c4..bc11404e 100644 --- a/pkg/sourcetool/models/models.go +++ b/pkg/sourcetool/models/models.go @@ -18,7 +18,10 @@ import ( "github.com/slsa-framework/source-tool/pkg/slsa" ) -var ErrProtectionAlreadyInPlace = errors.New("controls already in place in the repository") +var ( + ErrProtectionAlreadyInPlace = errors.New("controls already in place in the repository") + ErrRepositoryAccessDenied = errors.New("access to repository denied") +) // AttestationStorageReader abstracts an attestation storage system where // sourcetool can read VSAs and provenance attestations.