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
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (h Handler) Invoke(ctx context.Context, req []byte) ([]byte, error) {
inputYaml = httpRequest.Body
}

fixResponse, err := workflow.SecureWorkflow(httpRequest.QueryStringParameters, inputYaml, dynamoDbSvc)
fixResponse, err := workflow.SecureWorkflow(httpRequest.QueryStringParameters, nil, inputYaml, dynamoDbSvc)

if err != nil {
response = events.APIGatewayProxyResponse{
Expand Down
2 changes: 1 addition & 1 deletion remediation/workflow/hardenrunner/addaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func AddAction(inputYaml, action string, pinActions bool) (string, bool, error)
}

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

return out, updated, nil
Expand Down
29 changes: 26 additions & 3 deletions remediation/workflow/pin/pinactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

Expand All @@ -13,7 +14,7 @@ import (
"gopkg.in/yaml.v3"
)

func PinActions(inputYaml string) (string, bool, error) {
func PinActions(inputYaml string, exemptedActions []string) (string, bool, error) {
workflow := metadata.Workflow{}
updated := false
err := yaml.Unmarshal([]byte(inputYaml), &workflow)
Expand All @@ -28,7 +29,7 @@ func PinActions(inputYaml string) (string, bool, error) {
for _, step := range job.Steps {
if len(step.Uses) > 0 {
localUpdated := false
out, localUpdated = PinAction(step.Uses, out)
out, localUpdated = PinAction(step.Uses, out, exemptedActions)
updated = updated || localUpdated
}
}
Expand All @@ -37,7 +38,7 @@ func PinActions(inputYaml string) (string, bool, error) {
return out, updated, nil
}

func PinAction(action, inputYaml string) (string, bool) {
func PinAction(action, inputYaml string, exemptedActions []string) (string, bool) {

updated := false
if !strings.Contains(action, "@") || strings.HasPrefix(action, "docker://") {
Expand All @@ -50,6 +51,11 @@ func PinAction(action, inputYaml string) (string, bool) {
leftOfAt := strings.Split(action, "@")
tagOrBranch := leftOfAt[1]

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

splitOnSlash := strings.Split(leftOfAt[0], "/")
owner := splitOnSlash[0]
repo := splitOnSlash[1]
Expand Down Expand Up @@ -188,3 +194,20 @@ func getSemanticVersion(client *github.Client, owner, repo, tagOrBranch, commitS
}
return tagOrBranch, nil
}

// Function to check if an action matches any pattern in the list
func actionExists(actionName string, patterns []string) bool {
for _, pattern := range patterns {
// Use filepath.Match to match the pattern
matched, err := filepath.Match(pattern, actionName)
if err != nil {
// Handle invalid patterns
fmt.Printf("Error matching pattern: %v\n", err)
continue
}
if matched {
return true
}
}
return false
}
8 changes: 5 additions & 3 deletions remediation/workflow/pin/pinactions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,9 @@ func TestPinActions(t *testing.T) {
})

tests := []struct {
fileName string
wantUpdated bool
fileName string
wantUpdated bool
exemptedActions []string
}{
{fileName: "alreadypinned.yml", wantUpdated: false},
{fileName: "branch.yml", wantUpdated: true},
Expand All @@ -276,6 +277,7 @@ func TestPinActions(t *testing.T) {
{fileName: "actionwithcomment.yml", wantUpdated: true},
{fileName: "repeatedactionwithcomment.yml", wantUpdated: true},
{fileName: "immutableaction-1.yml", wantUpdated: true},
{fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*"}},
}
for _, tt := range tests {
input, err := ioutil.ReadFile(path.Join(inputDirectory, tt.fileName))
Expand All @@ -284,7 +286,7 @@ func TestPinActions(t *testing.T) {
log.Fatal(err)
}

output, gotUpdated, err := PinActions(string(input))
output, gotUpdated, err := PinActions(string(input), tt.exemptedActions)
if tt.wantUpdated != gotUpdated {
t.Errorf("test failed wantUpdated %v did not match gotUpdated %v", tt.wantUpdated, gotUpdated)
}
Expand Down
4 changes: 2 additions & 2 deletions remediation/workflow/secureworkflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const (
HardenRunnerActionName = "Harden Runner"
)

func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc dynamodbiface.DynamoDBAPI) (*permissions.SecureWorkflowReponse, error) {
func SecureWorkflow(queryStringParams map[string]string, exemptedActions []string, inputYaml string, svc dynamodbiface.DynamoDBAPI) (*permissions.SecureWorkflowReponse, error) {
pinActions, addHardenRunner, addPermissions, addProjectComment := true, true, true, true
pinnedActions, addedHardenRunner, addedPermissions := false, false, false
ignoreMissingKBs := false
Expand Down Expand Up @@ -68,7 +68,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d

if pinActions {
pinnedAction, pinnedDocker := false, false
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput)
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions)
secureWorkflowReponse.FinalOutput, pinnedDocker, _ = pin.PinDocker(secureWorkflowReponse.FinalOutput)
pinnedActions = pinnedAction || pinnedDocker
}
Expand Down
2 changes: 1 addition & 1 deletion remediation/workflow/secureworkflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func TestSecureWorkflow(t *testing.T) {
}
queryParams["addProjectComment"] = "false"

output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{})
output, err := SecureWorkflow(queryParams, nil, string(input), &mockDynamoDBClient{})

if err != nil {
t.Errorf("Error not expected")
Expand Down
44 changes: 44 additions & 0 deletions testfiles/pinactions/input/exemptaction.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: publish to nuget
on:
push:
branches:
- master # Default release branch
jobs:
publish:
name: build, pack & publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1

# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: 3.1.200

# Publish
- name: publish on version change
id: publish_nuget
uses: brandedoutcast/publish-nuget@v2
with:
PROJECT_FILE_PATH: Core/Core.csproj
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}
NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json
publish1:
name: build, pack & publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1

# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: 3.1.200

# Publish
- name: publish on version change
id: publish_nuget
uses: rohith/publish-nuget@v2
with:
PROJECT_FILE_PATH: Core/Core.csproj
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}
NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json
44 changes: 44 additions & 0 deletions testfiles/pinactions/output/exemptaction.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: publish to nuget
on:
push:
branches:
- master # Default release branch
jobs:
publish:
name: build, pack & publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1

# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: 3.1.200

# Publish
- name: publish on version change
id: publish_nuget
uses: brandedoutcast/publish-nuget@c12b8546b67672ee38ac87bea491ac94a587f7cc # v2.5.5
with:
PROJECT_FILE_PATH: Core/Core.csproj
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}
NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json
publish1:
name: build, pack & publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1

# - name: Setup dotnet
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: 3.1.200

# Publish
- name: publish on version change
id: publish_nuget
uses: rohith/publish-nuget@v2
with:
PROJECT_FILE_PATH: Core/Core.csproj
NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}
NUGET_SOURCE: https://nuget.pkg.github.com/OWNER/index.json