Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion remediation/workflow/hardenrunner/addaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ func AddAction(inputYaml, action string, pinActions, pinToImmutable bool, skipCo
}

if updated && pinActions {
out, _ = pin.PinAction(action, out, nil, pinToImmutable, nil)
out, _, err = pin.PinAction(action, out, nil, pinToImmutable, nil)
if err != nil {
return out, updated, err
}
}

return out, updated, nil
Expand Down
29 changes: 18 additions & 11 deletions remediation/workflow/pin/pinactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool,
for _, step := range job.Steps {
if len(step.Uses) > 0 {
localUpdated := false
out, localUpdated = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap)
out, localUpdated, err = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap)
if err != nil {
return out, updated, err
}
updated = updated || localUpdated
}
}
Expand All @@ -38,29 +41,33 @@ func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool,
return out, updated, nil
}

func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string) (string, bool) {
func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string) (string, bool, error) {

updated := false
if !strings.Contains(action, "@") || strings.HasPrefix(action, "docker://") {
return inputYaml, updated // Cannot pin local actions and docker actions
return inputYaml, updated, nil // Cannot pin local actions and docker actions
}

if isAbsolute(action) || (pinToImmutable && IsImmutableAction(action)) {
return inputYaml, updated
return inputYaml, updated, nil
}
leftOfAt := strings.Split(action, "@")
tagOrBranch := leftOfAt[1]

// skip pinning for exempted actions
if ActionExists(leftOfAt[0], exemptedActions) {
return inputYaml, updated
return inputYaml, updated, nil
}

splitOnSlash := strings.Split(leftOfAt[0], "/")
owner := splitOnSlash[0]
repo := splitOnSlash[1]

PAT := os.Getenv("PAT")
// use secure repo token
PAT := os.Getenv("SECURE_REPO_PAT")
if PAT == "" {
PAT = os.Getenv("PAT")
}

ctx := context.Background()
ts := oauth2.StaticTokenSource(
Expand All @@ -81,7 +88,7 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl
if !semanticTagRegex.MatchString(tagOrBranch) {
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
if err != nil {
return inputYaml, updated
return inputYaml, updated, err
}
}
break
Expand All @@ -92,11 +99,11 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl
if commitSHA == "" {
commitSHA, _, err = client.Repositories.GetCommitSHA1(ctx, owner, repo, tagOrBranch, "")
if err != nil {
return inputYaml, updated
return inputYaml, updated, err
}
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
if err != nil {
return inputYaml, updated
return inputYaml, updated, err
}

}
Expand Down Expand Up @@ -130,7 +137,7 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl
inputYaml = actionRegex.ReplaceAllString(inputYaml, pinnedActionWithVersion+"$2")

inputYaml, _ = removePreviousActionComments(pinnedActionWithVersion, inputYaml)
return inputYaml, !strings.EqualFold(action, pinnedActionWithVersion)
return inputYaml, !strings.EqualFold(action, pinnedActionWithVersion), nil
}

updated = !strings.EqualFold(action, fullPinned)
Expand Down Expand Up @@ -162,7 +169,7 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl
)
inputYaml, _ = removePreviousActionComments(fullPinned, inputYaml)

return inputYaml, updated
return inputYaml, updated, nil
}

// It may be that there was already a comment next to the action
Expand Down
8 changes: 7 additions & 1 deletion remediation/workflow/secureworkflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,13 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d
log.Printf("Pinning GitHub Actions")
}
pinnedAction, pinnedDocker := false, false
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap)
secureWorkflowReponse.FinalOutput, pinnedAction, err = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap)
if err != nil {
if enableLogging {
log.Printf("Error pinning actions: %v", err)
}
return secureWorkflowReponse, err
}
secureWorkflowReponse.FinalOutput, pinnedDocker, _ = pin.PinDocker(secureWorkflowReponse.FinalOutput)
pinnedActions = pinnedAction || pinnedDocker
if enableLogging {
Expand Down
5 changes: 3 additions & 2 deletions remediation/workflow/secureworkflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func TestSecureWorkflow(t *testing.T) {
}{
{fileName: "replaceactions.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantAddedMaintainedActions: true},
{fileName: "allscenarios.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: true},
{fileName: "missingaction.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false},
// {fileName: "missingaction.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false},
{fileName: "nohardenrunner.yml", wantPinnedActions: true, wantAddedHardenRunner: false, wantAddedPermissions: true},
{fileName: "noperms.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false},
{fileName: "nopin.yml", wantPinnedActions: false, wantAddedHardenRunner: true, wantAddedPermissions: true},
Expand Down Expand Up @@ -265,12 +265,13 @@ func TestSecureWorkflow(t *testing.T) {
if err != nil {
t.Errorf("unable to load the file %s", err)
}
output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, []string{}, false, actionMap)
output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, []string{"actions/*"}, false, actionMap)
} else {
output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{})
}

if err != nil {
t.Log(err)
t.Errorf("Error not expected")
}

Expand Down
2 changes: 1 addition & 1 deletion testfiles/secureworkflow/output/replaceactions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
with:
egress-policy: audit

- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
- uses: actions/checkout@v1
- uses: github/super-linter@34b2f8032d759425f6b42ea2e52231b33ae05401 # v3.17.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down