From 1af3f73782040df47c38413b1cbbe3214ab6c358 Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Wed, 29 Oct 2025 15:17:26 +0530 Subject: [PATCH 1/9] use secure repo token --- .../workflow/hardenrunner/addaction.go | 2 +- remediation/workflow/pin/pinactions.go | 23 +++++++++++-------- remediation/workflow/secureworkflow.go | 8 ++++++- remediation/workflow/secureworkflow_test.go | 5 ++-- testfiles/secureworkflow/output/oneJob.yml | 2 +- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/remediation/workflow/hardenrunner/addaction.go b/remediation/workflow/hardenrunner/addaction.go index c47d2e35..57adf1c9 100644 --- a/remediation/workflow/hardenrunner/addaction.go +++ b/remediation/workflow/hardenrunner/addaction.go @@ -51,7 +51,7 @@ func AddAction(inputYaml, action string, pinActions, pinToImmutable bool, skipCo } if updated && pinActions { - out, _ = pin.PinAction(action, out, nil, pinToImmutable, nil) + out, _, _ = pin.PinAction(action, out, nil, pinToImmutable, nil) } return out, updated, nil diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index 8d16b211..8bbc9033 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -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 } } @@ -38,22 +41,22 @@ 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], "/") @@ -81,7 +84,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 @@ -92,11 +95,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 } } @@ -130,7 +133,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) @@ -162,7 +165,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 diff --git a/remediation/workflow/secureworkflow.go b/remediation/workflow/secureworkflow.go index 71025561..dc0ed859 100644 --- a/remediation/workflow/secureworkflow.go +++ b/remediation/workflow/secureworkflow.go @@ -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 { diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index da0d8454..c026cf80 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -217,7 +217,7 @@ func TestSecureWorkflow(t *testing.T) { }{ {fileName: "oneJob.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}, @@ -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") } diff --git a/testfiles/secureworkflow/output/oneJob.yml b/testfiles/secureworkflow/output/oneJob.yml index e8d874fd..ada285de 100644 --- a/testfiles/secureworkflow/output/oneJob.yml +++ b/testfiles/secureworkflow/output/oneJob.yml @@ -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 }} From 42f920ddba175e7be3a6bc45f5ccc362ed223155 Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Wed, 29 Oct 2025 15:19:54 +0530 Subject: [PATCH 2/9] use secure repo token --- remediation/workflow/pin/pinactions.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index 8bbc9033..7f0dcff9 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -63,7 +63,11 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl 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( From b912dfc0150d3b80a78e6ad769cfda3b98d8f3ea Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Wed, 29 Oct 2025 18:47:08 +0530 Subject: [PATCH 3/9] use secure repo token --- remediation/workflow/hardenrunner/addaction.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/remediation/workflow/hardenrunner/addaction.go b/remediation/workflow/hardenrunner/addaction.go index 57adf1c9..bb0eb7e6 100644 --- a/remediation/workflow/hardenrunner/addaction.go +++ b/remediation/workflow/hardenrunner/addaction.go @@ -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 From c62caaf9ef1eef72b108a77772f589715f71a64d Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Thu, 30 Oct 2025 22:00:13 +0530 Subject: [PATCH 4/9] log to validate pat --- remediation/workflow/pin/pinactions.go | 2 ++ remediation/workflow/secureworkflow_test.go | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index 7f0dcff9..ebba8a30 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -3,6 +3,7 @@ package pin import ( "context" "fmt" + "log" "os" "path/filepath" "regexp" @@ -67,6 +68,7 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl PAT := os.Getenv("SECURE_REPO_PAT") if PAT == "" { PAT = os.Getenv("PAT") + log.Println("SECURE_REPO_PAT is not set, using PAT") } ctx := context.Background() diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index c026cf80..fdc5b6e3 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -217,7 +217,6 @@ func TestSecureWorkflow(t *testing.T) { }{ {fileName: "oneJob.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: "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}, From b1c1f0b890e0bdf099c51178f2525d2872e6b450 Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Fri, 31 Oct 2025 12:41:20 +0530 Subject: [PATCH 5/9] handle missing action error --- remediation/workflow/secureworkflow_test.go | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index fdc5b6e3..122f67dd 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -214,15 +214,17 @@ func TestSecureWorkflow(t *testing.T) { wantAddedHardenRunner bool wantAddedPermissions bool wantAddedMaintainedActions bool + wantError bool }{ - {fileName: "oneJob.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantAddedMaintainedActions: true}, - {fileName: "allscenarios.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: true}, - {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}, - {fileName: "allperms.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: true}, - {fileName: "multiplejobperms.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: true}, - {fileName: "error.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: false}, + {fileName: "replaceactions.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantAddedMaintainedActions: true, wantError: false}, + {fileName: "allscenarios.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: true, wantError: false}, + {fileName: "nohardenrunner.yml", wantPinnedActions: true, wantAddedHardenRunner: false, wantAddedPermissions: true, wantError: false}, + {fileName: "noperms.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantError: false}, + {fileName: "nopin.yml", wantPinnedActions: false, wantAddedHardenRunner: true, wantAddedPermissions: true, wantError: false}, + {fileName: "allperms.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: true, wantError: false}, + {fileName: "multiplejobperms.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: true, wantError: false}, + {fileName: "error.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: false, wantError: false}, + {fileName: "missingaction.yml", wantPinnedActions: false, wantAddedHardenRunner: false, wantAddedPermissions: false, wantError: true}, } for _, test := range tests { var err error @@ -269,6 +271,14 @@ func TestSecureWorkflow(t *testing.T) { output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) } + if test.wantError { + if err == nil { + t.Errorf("test failed %s expected an error but got none", test.fileName) + } + // Skip further validation if we expected an error + continue + } + if err != nil { t.Log(err) t.Errorf("Error not expected") From 478cdc09b756470e4d9c02a88c7abbe6cadd4d0f Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Fri, 31 Oct 2025 21:30:05 +0530 Subject: [PATCH 6/9] rename testcase file --- remediation/workflow/secureworkflow_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index 122f67dd..80b9945a 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -216,7 +216,7 @@ func TestSecureWorkflow(t *testing.T) { wantAddedMaintainedActions bool wantError bool }{ - {fileName: "replaceactions.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantAddedMaintainedActions: true, wantError: false}, + {fileName: "oneJob.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantAddedMaintainedActions: true, wantError: false}, {fileName: "allscenarios.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: true, wantError: false}, {fileName: "nohardenrunner.yml", wantPinnedActions: true, wantAddedHardenRunner: false, wantAddedPermissions: true, wantError: false}, {fileName: "noperms.yml", wantPinnedActions: true, wantAddedHardenRunner: true, wantAddedPermissions: false, wantError: false}, From b9c9f5318e6b5abe6e2f3157cdca1b55dee4d864 Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Sun, 2 Nov 2025 23:32:19 +0530 Subject: [PATCH 7/9] add log --- remediation/workflow/pin/pinactions.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index ebba8a30..624eb84b 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -69,6 +69,8 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl if PAT == "" { PAT = os.Getenv("PAT") log.Println("SECURE_REPO_PAT is not set, using PAT") + } else { + log.Println("SECURE_REPO_PAT is set") } ctx := context.Background() From 4989623cd205153ee369ac87b602a160e5bfcebb Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Mon, 3 Nov 2025 14:51:33 +0530 Subject: [PATCH 8/9] support for passing logger --- main.go | 2 +- .../workflow/hardenrunner/addaction.go | 2 +- remediation/workflow/pin/pinactions.go | 25 ++++++++++++++----- remediation/workflow/pin/pinactions_test.go | 2 +- remediation/workflow/secureworkflow.go | 4 +-- remediation/workflow/secureworkflow_test.go | 8 +++--- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/main.go b/main.go index 8e4a8131..7af31373 100644 --- a/main.go +++ b/main.go @@ -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, inputYaml, dynamoDbSvc, nil) if err != nil { response = events.APIGatewayProxyResponse{ diff --git a/remediation/workflow/hardenrunner/addaction.go b/remediation/workflow/hardenrunner/addaction.go index bb0eb7e6..4730d80c 100644 --- a/remediation/workflow/hardenrunner/addaction.go +++ b/remediation/workflow/hardenrunner/addaction.go @@ -51,7 +51,7 @@ func AddAction(inputYaml, action string, pinActions, pinToImmutable bool, skipCo } if updated && pinActions { - out, _, err = pin.PinAction(action, out, nil, pinToImmutable, nil) + out, _, err = pin.PinAction(action, out, nil, pinToImmutable, nil, nil) if err != nil { return out, updated, err } diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index 624eb84b..299f8c45 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -3,19 +3,24 @@ package pin import ( "context" "fmt" - "log" "os" "path/filepath" "regexp" "strings" "github.com/google/go-github/v40/github" + "github.com/sirupsen/logrus" metadata "github.com/step-security/secure-repo/remediation/workflow/metadata" "golang.org/x/oauth2" "gopkg.in/yaml.v3" ) -func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string) (string, bool, error) { +type StepSecurityAppLogger struct { + RequestID string `json:"request_id,omitempty"` + *logrus.Logger +} + +func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string, logger *StepSecurityAppLogger) (string, bool, error) { workflow := metadata.Workflow{} updated := false err := yaml.Unmarshal([]byte(inputYaml), &workflow) @@ -30,7 +35,7 @@ func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, for _, step := range job.Steps { if len(step.Uses) > 0 { localUpdated := false - out, localUpdated, err = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap) + out, localUpdated, err = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap, logger) if err != nil { return out, updated, err } @@ -42,7 +47,7 @@ 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, error) { +func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string, logger *StepSecurityAppLogger) (string, bool, error) { updated := false if !strings.Contains(action, "@") || strings.HasPrefix(action, "docker://") { @@ -68,9 +73,17 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl PAT := os.Getenv("SECURE_REPO_PAT") if PAT == "" { PAT = os.Getenv("PAT") - log.Println("SECURE_REPO_PAT is not set, using PAT") + if logger != nil { + logger.Logf(logrus.InfoLevel, "SECURE_REPO_PAT is not set, using PAT") + } else { + logrus.Info("SECURE_REPO_PAT is not set, using PAT") + } } else { - log.Println("SECURE_REPO_PAT is set") + if logger != nil { + logger.Logf(logrus.InfoLevel, "SECURE_REPO_PAT is set") + } else { + logrus.Info("SECURE_REPO_PAT is set") + } } ctx := context.Background() diff --git a/remediation/workflow/pin/pinactions_test.go b/remediation/workflow/pin/pinactions_test.go index c600cda4..67c21034 100644 --- a/remediation/workflow/pin/pinactions_test.go +++ b/remediation/workflow/pin/pinactions_test.go @@ -333,7 +333,7 @@ func TestPinActions(t *testing.T) { } } - output, gotUpdated, err = PinActions(string(input), tt.exemptedActions, tt.pinToImmutable, actionCommitMap) + output, gotUpdated, err = PinActions(string(input), tt.exemptedActions, tt.pinToImmutable, actionCommitMap, nil) if tt.wantUpdated != gotUpdated { t.Errorf("test failed wantUpdated %v did not match gotUpdated %v", tt.wantUpdated, gotUpdated) } diff --git a/remediation/workflow/secureworkflow.go b/remediation/workflow/secureworkflow.go index dc0ed859..ade79a0a 100644 --- a/remediation/workflow/secureworkflow.go +++ b/remediation/workflow/secureworkflow.go @@ -17,7 +17,7 @@ const ( HardenRunnerActionName = "Harden Runner" ) -func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc dynamodbiface.DynamoDBAPI, params ...interface{}) (*permissions.SecureWorkflowReponse, error) { +func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc dynamodbiface.DynamoDBAPI, logger *pin.StepSecurityAppLogger, params ...interface{}) (*permissions.SecureWorkflowReponse, error) { pinActions, addHardenRunner, addPermissions, addProjectComment, replaceMaintainedActions := true, true, true, true, false pinnedActions, addedHardenRunner, addedPermissions, replacedMaintainedActions := false, false, false, false ignoreMissingKBs := false @@ -148,7 +148,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d log.Printf("Pinning GitHub Actions") } pinnedAction, pinnedDocker := false, false - secureWorkflowReponse.FinalOutput, pinnedAction, err = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap) + secureWorkflowReponse.FinalOutput, pinnedAction, err = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap, logger) if err != nil { if enableLogging { log.Printf("Error pinning actions: %v", err) diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index 80b9945a..f50cc332 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -266,9 +266,9 @@ 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{"actions/*"}, false, actionMap) + output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil, []string{"actions/*"}, false, actionMap) } else { - output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) + output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) } if test.wantError { @@ -369,7 +369,7 @@ func TestSecureWorkflowContainerJob(t *testing.T) { queryParams["skipHardenRunnerForContainers"] = "true" queryParams["addProjectComment"] = "false" - output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) + output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) if err != nil { t.Errorf("Error not expected") @@ -474,7 +474,7 @@ func TestSecureWorkflowEmptyPermissions(t *testing.T) { queryParams["addEmptyTopLevelPermissions"] = "true" queryParams["addProjectComment"] = "false" - output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) + output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) if err != nil { t.Errorf("Error not expected") From 1922e6e165b72850e709b5652cac8af3e563eda0 Mon Sep 17 00:00:00 2001 From: Balijepalli Vamshi Krishna Date: Mon, 3 Nov 2025 16:21:51 +0530 Subject: [PATCH 9/9] update secure workflow response --- main.go | 2 +- .../workflow/hardenrunner/addaction.go | 2 +- .../workflow/permissions/permissions.go | 1 + remediation/workflow/pin/pinactions.go | 31 +++++++------------ remediation/workflow/pin/pinactions_test.go | 2 +- remediation/workflow/secureworkflow.go | 10 +++--- remediation/workflow/secureworkflow_test.go | 8 ++--- 7 files changed, 25 insertions(+), 31 deletions(-) diff --git a/main.go b/main.go index 7af31373..8e4a8131 100644 --- a/main.go +++ b/main.go @@ -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, nil) + fixResponse, err := workflow.SecureWorkflow(httpRequest.QueryStringParameters, inputYaml, dynamoDbSvc) if err != nil { response = events.APIGatewayProxyResponse{ diff --git a/remediation/workflow/hardenrunner/addaction.go b/remediation/workflow/hardenrunner/addaction.go index 4730d80c..bb0eb7e6 100644 --- a/remediation/workflow/hardenrunner/addaction.go +++ b/remediation/workflow/hardenrunner/addaction.go @@ -51,7 +51,7 @@ func AddAction(inputYaml, action string, pinActions, pinToImmutable bool, skipCo } if updated && pinActions { - out, _, err = pin.PinAction(action, out, nil, pinToImmutable, nil, nil) + out, _, err = pin.PinAction(action, out, nil, pinToImmutable, nil) if err != nil { return out, updated, err } diff --git a/remediation/workflow/permissions/permissions.go b/remediation/workflow/permissions/permissions.go index 018eea47..2cbee465 100644 --- a/remediation/workflow/permissions/permissions.go +++ b/remediation/workflow/permissions/permissions.go @@ -25,6 +25,7 @@ type SecureWorkflowReponse struct { WorkflowFetchError bool JobErrors []JobError MissingActions []string + UsingSecureRepoPAT bool } type JobError struct { diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index 299f8c45..a7285493 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -3,24 +3,19 @@ package pin import ( "context" "fmt" + "log" "os" "path/filepath" "regexp" "strings" "github.com/google/go-github/v40/github" - "github.com/sirupsen/logrus" metadata "github.com/step-security/secure-repo/remediation/workflow/metadata" "golang.org/x/oauth2" "gopkg.in/yaml.v3" ) -type StepSecurityAppLogger struct { - RequestID string `json:"request_id,omitempty"` - *logrus.Logger -} - -func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string, logger *StepSecurityAppLogger) (string, bool, error) { +func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string) (string, bool, error) { workflow := metadata.Workflow{} updated := false err := yaml.Unmarshal([]byte(inputYaml), &workflow) @@ -35,7 +30,7 @@ func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, for _, step := range job.Steps { if len(step.Uses) > 0 { localUpdated := false - out, localUpdated, err = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap, logger) + out, localUpdated, err = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap) if err != nil { return out, updated, err } @@ -47,9 +42,9 @@ 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, logger *StepSecurityAppLogger) (string, bool, error) { - +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, nil // Cannot pin local actions and docker actions } @@ -73,17 +68,9 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl PAT := os.Getenv("SECURE_REPO_PAT") if PAT == "" { PAT = os.Getenv("PAT") - if logger != nil { - logger.Logf(logrus.InfoLevel, "SECURE_REPO_PAT is not set, using PAT") - } else { - logrus.Info("SECURE_REPO_PAT is not set, using PAT") - } + log.Println("SECURE_REPO_PAT is not set, using PAT") } else { - if logger != nil { - logger.Logf(logrus.InfoLevel, "SECURE_REPO_PAT is set") - } else { - logrus.Info("SECURE_REPO_PAT is set") - } + log.Println("SECURE_REPO_PAT is set") } ctx := context.Background() @@ -287,3 +274,7 @@ func ActionExists(actionName string, patterns []string) bool { } return false } + +func UsingSecureRepoPAT() bool { + return os.Getenv("SECURE_REPO_PAT") != "" +} diff --git a/remediation/workflow/pin/pinactions_test.go b/remediation/workflow/pin/pinactions_test.go index 67c21034..c600cda4 100644 --- a/remediation/workflow/pin/pinactions_test.go +++ b/remediation/workflow/pin/pinactions_test.go @@ -333,7 +333,7 @@ func TestPinActions(t *testing.T) { } } - output, gotUpdated, err = PinActions(string(input), tt.exemptedActions, tt.pinToImmutable, actionCommitMap, nil) + output, gotUpdated, err = PinActions(string(input), tt.exemptedActions, tt.pinToImmutable, actionCommitMap) if tt.wantUpdated != gotUpdated { t.Errorf("test failed wantUpdated %v did not match gotUpdated %v", tt.wantUpdated, gotUpdated) } diff --git a/remediation/workflow/secureworkflow.go b/remediation/workflow/secureworkflow.go index ade79a0a..2d2779e3 100644 --- a/remediation/workflow/secureworkflow.go +++ b/remediation/workflow/secureworkflow.go @@ -17,7 +17,7 @@ const ( HardenRunnerActionName = "Harden Runner" ) -func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc dynamodbiface.DynamoDBAPI, logger *pin.StepSecurityAppLogger, params ...interface{}) (*permissions.SecureWorkflowReponse, error) { +func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc dynamodbiface.DynamoDBAPI, params ...interface{}) (*permissions.SecureWorkflowReponse, error) { pinActions, addHardenRunner, addPermissions, addProjectComment, replaceMaintainedActions := true, true, true, true, false pinnedActions, addedHardenRunner, addedPermissions, replacedMaintainedActions := false, false, false, false ignoreMissingKBs := false @@ -148,7 +148,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d log.Printf("Pinning GitHub Actions") } pinnedAction, pinnedDocker := false, false - secureWorkflowReponse.FinalOutput, pinnedAction, err = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap, logger) + secureWorkflowReponse.FinalOutput, pinnedAction, err = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap) if err != nil { if enableLogging { log.Printf("Error pinning actions: %v", err) @@ -185,14 +185,16 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d secureWorkflowReponse.AddedHardenRunner = addedHardenRunner secureWorkflowReponse.AddedPermissions = addedPermissions secureWorkflowReponse.AddedMaintainedActions = replacedMaintainedActions + secureWorkflowReponse.UsingSecureRepoPAT = pin.UsingSecureRepoPAT() if enableLogging { - log.Printf("SecureWorkflow complete - PinnedActions: %v, AddedHardenRunner: %v, AddedPermissions: %v, AddedMaintainedActions: %v, HasErrors: %v", + log.Printf("SecureWorkflow complete - PinnedActions: %v, AddedHardenRunner: %v, AddedPermissions: %v, AddedMaintainedActions: %v, HasErrors: %v, UsingSecureRepoPAT: %v", secureWorkflowReponse.PinnedActions, secureWorkflowReponse.AddedHardenRunner, secureWorkflowReponse.AddedPermissions, secureWorkflowReponse.AddedMaintainedActions, - secureWorkflowReponse.HasErrors) + secureWorkflowReponse.HasErrors, + secureWorkflowReponse.UsingSecureRepoPAT) } return secureWorkflowReponse, nil diff --git a/remediation/workflow/secureworkflow_test.go b/remediation/workflow/secureworkflow_test.go index f50cc332..80b9945a 100644 --- a/remediation/workflow/secureworkflow_test.go +++ b/remediation/workflow/secureworkflow_test.go @@ -266,9 +266,9 @@ func TestSecureWorkflow(t *testing.T) { if err != nil { t.Errorf("unable to load the file %s", err) } - output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil, []string{"actions/*"}, false, actionMap) + output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, []string{"actions/*"}, false, actionMap) } else { - output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) + output, err = SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) } if test.wantError { @@ -369,7 +369,7 @@ func TestSecureWorkflowContainerJob(t *testing.T) { queryParams["skipHardenRunnerForContainers"] = "true" queryParams["addProjectComment"] = "false" - output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) + output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) if err != nil { t.Errorf("Error not expected") @@ -474,7 +474,7 @@ func TestSecureWorkflowEmptyPermissions(t *testing.T) { queryParams["addEmptyTopLevelPermissions"] = "true" queryParams["addProjectComment"] = "false" - output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}, nil) + output, err := SecureWorkflow(queryParams, string(input), &mockDynamoDBClient{}) if err != nil { t.Errorf("Error not expected")