111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package inspect
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/api"
|
|
)
|
|
|
|
type workflow struct {
|
|
Repository string `json:"repository"`
|
|
}
|
|
|
|
type externalParameters struct {
|
|
Workflow workflow `json:"workflow"`
|
|
}
|
|
|
|
type githubInfo struct {
|
|
RepositoryID string `json:"repository_id"`
|
|
RepositoryOwnerId string `json:"repository_owner_id"`
|
|
}
|
|
|
|
type internalParameters struct {
|
|
GitHub githubInfo `json:"github"`
|
|
}
|
|
|
|
type buildDefinition struct {
|
|
ExternalParameters externalParameters `json:"externalParameters"`
|
|
InternalParameters internalParameters `json:"internalParameters"`
|
|
}
|
|
|
|
type metadata struct {
|
|
InvocationID string `json:"invocationId"`
|
|
}
|
|
|
|
type runDetails struct {
|
|
Metadata metadata `json:"metadata"`
|
|
}
|
|
|
|
// Predicate captures the predicate of a given attestation
|
|
type Predicate struct {
|
|
BuildDefinition buildDefinition `json:"buildDefinition"`
|
|
RunDetails runDetails `json:"runDetails"`
|
|
}
|
|
|
|
// AttestationDetail captures attestation source details
|
|
// that will be returned by the inspect command
|
|
type AttestationDetail struct {
|
|
OrgName string `json:"orgName"`
|
|
OrgID string `json:"orgId"`
|
|
RepositoryName string `json:"repositoryName"`
|
|
RepositoryID string `json:"repositoryId"`
|
|
WorkflowID string `json:"workflowId"`
|
|
}
|
|
|
|
func getOrgAndRepo(tenant, repoURL string) (string, string, error) {
|
|
var after string
|
|
var found bool
|
|
if tenant == "" {
|
|
after, found = strings.CutPrefix(repoURL, "https://github.com/")
|
|
if !found {
|
|
return "", "", fmt.Errorf("failed to get org and repo from %s", repoURL)
|
|
}
|
|
} else {
|
|
after, found = strings.CutPrefix(repoURL,
|
|
fmt.Sprintf("https://%s.ghe.com/", tenant))
|
|
if !found {
|
|
return "", "", fmt.Errorf("failed to get org and repo from %s", repoURL)
|
|
}
|
|
}
|
|
|
|
parts := strings.Split(after, "/")
|
|
return parts[0], parts[1], nil
|
|
}
|
|
|
|
func getAttestationDetail(tenant string, attr api.Attestation) (AttestationDetail, error) {
|
|
envelope, err := attr.Bundle.Envelope()
|
|
if err != nil {
|
|
return AttestationDetail{}, fmt.Errorf("failed to get envelope from bundle: %v", err)
|
|
}
|
|
|
|
statement, err := envelope.EnvelopeContent().Statement()
|
|
if err != nil {
|
|
return AttestationDetail{}, fmt.Errorf("failed to get statement from envelope: %v", err)
|
|
}
|
|
|
|
var predicate Predicate
|
|
predicateJson, err := json.Marshal(statement.Predicate)
|
|
if err != nil {
|
|
return AttestationDetail{}, fmt.Errorf("failed to marshal predicate: %v", err)
|
|
}
|
|
|
|
err = json.Unmarshal(predicateJson, &predicate)
|
|
if err != nil {
|
|
return AttestationDetail{}, fmt.Errorf("failed to unmarshal predicate: %v", err)
|
|
}
|
|
|
|
org, repo, err := getOrgAndRepo(tenant, predicate.BuildDefinition.ExternalParameters.Workflow.Repository)
|
|
if err != nil {
|
|
return AttestationDetail{}, fmt.Errorf("failed to parse attestation content: %v", err)
|
|
}
|
|
|
|
return AttestationDetail{
|
|
OrgName: org,
|
|
OrgID: predicate.BuildDefinition.InternalParameters.GitHub.RepositoryOwnerId,
|
|
RepositoryName: repo,
|
|
RepositoryID: predicate.BuildDefinition.InternalParameters.GitHub.RepositoryID,
|
|
WorkflowID: predicate.RunDetails.Metadata.InvocationID,
|
|
}, nil
|
|
}
|