Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: always use the default GITHUB_TOKEN for signing #898

Merged
merged 9 commits into from Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .golangci.yml
Expand Up @@ -56,7 +56,6 @@ linters:
- misspell
- nakedret
- nestif
- noctx
- nolintlint
- paralleltest
- predeclared
Expand Down
1 change: 1 addition & 0 deletions github/github.go
Expand Up @@ -91,6 +91,7 @@ func (c *Client) ParseFromURL(baseRepoURL, repoName string) (RepoInfo, error) {
}

log.Printf("getting repo info from URL: %s", repoURL.String())
//nolint:noctx
req, err := http.NewRequestWithContext(
c.ctx,
http.MethodGet,
Expand Down
11 changes: 8 additions & 3 deletions main.go
Expand Up @@ -41,15 +41,20 @@ func main() {
}

// Sign json results.
if err = signing.SignScorecardResult("results.json"); err != nil {
// Always use the default GitHub token, never a PAT.
accessToken := os.Getenv(options.EnvInputInternalRepoToken)
s, err := signing.New(accessToken)
if err != nil {
log.Fatalf("error SigningNew: %v", err)
}
if err = s.SignScorecardResult("results.json"); err != nil {
log.Fatalf("error signing scorecard json results: %v", err)
}

// Processes json results.
repoName := os.Getenv(options.EnvGithubRepository)
repoRef := os.Getenv(options.EnvGithubRef)
accessToken := os.Getenv(options.EnvInputRepoToken)
if err := signing.ProcessSignature(jsonPayload, repoName, repoRef, accessToken); err != nil {
if err := s.ProcessSignature(jsonPayload, repoName, repoRef); err != nil {
log.Fatalf("error processing signature: %v", err)
}
}
Expand Down
46 changes: 39 additions & 7 deletions signing/signing.go
Expand Up @@ -20,11 +20,13 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
"time"

sigOpts "github.com/sigstore/cosign/cmd/cosign/cli/options"
Expand All @@ -34,15 +36,45 @@ import (
"github.com/ossf/scorecard-action/options"
)

// SignScorecardResult signs the results file and uploads the attestation to the Rekor transparency log.
func SignScorecardResult(scorecardResultsFile string) error {
var (
errorEmptyToken = errors.New("error token empty")
errorInvalidToken = errors.New("invalid token")
)

// Signing is a signing structure.
type Signing struct {
token string
}

// New creates a new Signing instance.
func New(token string) (*Signing, error) {
// Set the default GITHUB_TOKEN, because it's not available by default
// in a GitHub Action. We need it for OIDC.
if token == "" {
return nil, fmt.Errorf("%w", errorEmptyToken)
}

// Check for a workflow secret.
if !strings.HasPrefix(token, "ghs_") {
return nil, fmt.Errorf("%w: not a default GITHUB_TOKEN", errorInvalidToken)
}
if err := os.Setenv("GITHUB_TOKEN", token); err != nil {
return nil, fmt.Errorf("error setting GITHUB_TOKEN env var: %w", err)
}

if err := os.Setenv("COSIGN_EXPERIMENTAL", "true"); err != nil {
return fmt.Errorf("error setting COSIGN_EXPERIMENTAL env var: %w", err)
return nil, fmt.Errorf("error setting COSIGN_EXPERIMENTAL env var: %w", err)
}

return &Signing{
token: token,
}, nil
}

// SignScorecardResult signs the results file and uploads the attestation to the Rekor transparency log.
func (s *Signing) SignScorecardResult(scorecardResultsFile string) error {
// Prepare settings for SignBlobCmd.
rootOpts := &sigOpts.RootOptions{Timeout: sigOpts.DefaultTimeout} // Just the timeout.

keyOpts := sigOpts.KeyOpts{
FulcioURL: sigOpts.DefaultFulcioURL, // Signing certificate provider.
RekorURL: sigOpts.DefaultRekorURL, // Transparency log.
Expand Down Expand Up @@ -87,7 +119,7 @@ func GetJSONScorecardResults() ([]byte, error) {
}

// ProcessSignature calls scorecard-api to process & upload signed scorecard results.
func ProcessSignature(jsonPayload []byte, repoName, repoRef, accessToken string) error {
func (s *Signing) ProcessSignature(jsonPayload []byte, repoName, repoRef string) error {
// Prepare HTTP request body for scorecard-webapp-api call.
// TODO: Use the `ScorecardResult` struct from `scorecard-webapp`.
resultsPayload := struct {
Expand All @@ -97,7 +129,7 @@ func ProcessSignature(jsonPayload []byte, repoName, repoRef, accessToken string)
}{
Result: string(jsonPayload),
Branch: repoRef,
AccessToken: accessToken,
AccessToken: s.token,
}

payloadBytes, err := json.Marshal(resultsPayload)
Expand All @@ -113,7 +145,7 @@ func ProcessSignature(jsonPayload []byte, repoName, repoRef, accessToken string)
if err != nil {
return fmt.Errorf("parsing Scorecard API endpoint: %w", err)
}
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(payloadBytes)) //nolint
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(payloadBytes))
if err != nil {
return fmt.Errorf("creating HTTP request: %w", err)
}
Expand Down
7 changes: 6 additions & 1 deletion signing/signing_test.go
Expand Up @@ -17,6 +17,7 @@
package signing

import (
"fmt"
"os"
"testing"

Expand Down Expand Up @@ -88,7 +89,11 @@ func Test_ProcessSignature(t *testing.T) {
t.Errorf("Error reading testdata:, %v", err)
}

if err := ProcessSignature(jsonPayload, repoName, repoRef, accessToken); err != nil {
s, err := New(accessToken)
if err != nil {
panic(fmt.Sprintf("error SigningNew: %v", err))
}
if err := s.ProcessSignature(jsonPayload, repoName, repoRef); err != nil {
t.Errorf("ProcessSignature() error:, %v", err)
return
}
Expand Down