Skip to content

Commit a1871e2

Browse files
add pinToImmutable configuration
1 parent c988535 commit a1871e2

File tree

9 files changed

+66
-25
lines changed

9 files changed

+66
-25
lines changed

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (h Handler) Invoke(ctx context.Context, req []byte) ([]byte, error) {
128128
inputYaml = httpRequest.Body
129129
}
130130

131-
fixResponse, err := workflow.SecureWorkflow(httpRequest.QueryStringParameters, nil, inputYaml, dynamoDbSvc)
131+
fixResponse, err := workflow.SecureWorkflow(httpRequest.QueryStringParameters, nil, false, inputYaml, dynamoDbSvc)
132132

133133
if err != nil {
134134
response = events.APIGatewayProxyResponse{

remediation/workflow/hardenrunner/addaction.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const (
1515
HardenRunnerActionName = "Harden Runner"
1616
)
1717

18-
func AddAction(inputYaml, action string, pinActions bool) (string, bool, error) {
18+
func AddAction(inputYaml, action string, pinActions, pinToImmutable bool) (string, bool, error) {
1919
workflow := metadata.Workflow{}
2020
updated := false
2121
err := yaml.Unmarshal([]byte(inputYaml), &workflow)
@@ -47,7 +47,7 @@ func AddAction(inputYaml, action string, pinActions bool) (string, bool, error)
4747
}
4848

4949
if updated && pinActions {
50-
out, _ = pin.PinAction(action, out, nil)
50+
out, _ = pin.PinAction(action, out, nil, pinToImmutable)
5151
}
5252

5353
return out, updated, nil

remediation/workflow/hardenrunner/addaction_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestAddAction(t *testing.T) {
3232
if err != nil {
3333
t.Fatalf("error reading test file")
3434
}
35-
got, gotUpdated, err := AddAction(string(input), tt.args.action, false)
35+
got, gotUpdated, err := AddAction(string(input), tt.args.action, false, false)
3636

3737
if gotUpdated != tt.wantUpdated {
3838
t.Errorf("AddAction() updated = %v, wantUpdated %v", gotUpdated, tt.wantUpdated)

remediation/workflow/pin/pinactions.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"gopkg.in/yaml.v3"
1515
)
1616

17-
func PinActions(inputYaml string, exemptedActions []string) (string, bool, error) {
17+
func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool) (string, bool, error) {
1818
workflow := metadata.Workflow{}
1919
updated := false
2020
err := yaml.Unmarshal([]byte(inputYaml), &workflow)
@@ -29,7 +29,7 @@ func PinActions(inputYaml string, exemptedActions []string) (string, bool, error
2929
for _, step := range job.Steps {
3030
if len(step.Uses) > 0 {
3131
localUpdated := false
32-
out, localUpdated = PinAction(step.Uses, out, exemptedActions)
32+
out, localUpdated = PinAction(step.Uses, out, exemptedActions, pinToImmutable)
3333
updated = updated || localUpdated
3434
}
3535
}
@@ -38,14 +38,14 @@ func PinActions(inputYaml string, exemptedActions []string) (string, bool, error
3838
return out, updated, nil
3939
}
4040

41-
func PinAction(action, inputYaml string, exemptedActions []string) (string, bool) {
41+
func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutable bool) (string, bool) {
4242

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

48-
if isAbsolute(action) || IsImmutableAction(action) {
48+
if isAbsolute(action) || (pinToImmutable && IsImmutableAction(action)) {
4949
return inputYaml, updated
5050
}
5151
leftOfAt := strings.Split(action, "@")
@@ -84,7 +84,7 @@ func PinAction(action, inputYaml string, exemptedActions []string) (string, bool
8484

8585
// if the action with version is immutable, then pin the action with version instead of sha
8686
pinnedActionWithVersion := fmt.Sprintf("%s@%s", leftOfAt[0], tagOrBranch)
87-
if semanticTagRegex.MatchString(tagOrBranch) && IsImmutableAction(pinnedActionWithVersion) {
87+
if pinToImmutable && semanticTagRegex.MatchString(tagOrBranch) && IsImmutableAction(pinnedActionWithVersion) {
8888
pinnedAction = pinnedActionWithVersion
8989
}
9090

remediation/workflow/pin/pinactions_test.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,21 @@ func TestPinActions(t *testing.T) {
188188
}
189189
]`))
190190

191+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/github/codeql-action/commits/v3.28.2",
192+
httpmock.NewStringResponder(200, `d68b2d4edb4189fd2a5366ac14e72027bd4b37dd`))
193+
194+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/github/codeql-action/git/matching-refs/tags/v3.28.2.",
195+
httpmock.NewStringResponder(200,
196+
`[
197+
{
198+
"ref": "refs/tags/v3.28.2",
199+
"object": {
200+
"sha": "d68b2d4edb4189fd2a5366ac14e72027bd4b37dd",
201+
"type": "commit"
202+
}
203+
}
204+
]`))
205+
191206
// mock ping response
192207
httpmock.RegisterResponder("GET", "https://ghcr.io/v2/",
193208
httpmock.NewStringResponder(200, ``))
@@ -266,18 +281,20 @@ func TestPinActions(t *testing.T) {
266281
fileName string
267282
wantUpdated bool
268283
exemptedActions []string
284+
pinToImmutable bool
269285
}{
270-
{fileName: "alreadypinned.yml", wantUpdated: false},
271-
{fileName: "branch.yml", wantUpdated: true},
272-
{fileName: "localaction.yml", wantUpdated: true},
273-
{fileName: "multiplejobs.yml", wantUpdated: true},
274-
{fileName: "basic.yml", wantUpdated: true},
275-
{fileName: "dockeraction.yml", wantUpdated: true},
276-
{fileName: "multipleactions.yml", wantUpdated: true},
277-
{fileName: "actionwithcomment.yml", wantUpdated: true},
278-
{fileName: "repeatedactionwithcomment.yml", wantUpdated: true},
279-
{fileName: "immutableaction-1.yml", wantUpdated: true},
280-
{fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*"}},
286+
{fileName: "alreadypinned.yml", wantUpdated: false, pinToImmutable: true},
287+
{fileName: "branch.yml", wantUpdated: true, pinToImmutable: true},
288+
{fileName: "localaction.yml", wantUpdated: true, pinToImmutable: true},
289+
{fileName: "multiplejobs.yml", wantUpdated: true, pinToImmutable: true},
290+
{fileName: "basic.yml", wantUpdated: true, pinToImmutable: true},
291+
{fileName: "dockeraction.yml", wantUpdated: true, pinToImmutable: true},
292+
{fileName: "multipleactions.yml", wantUpdated: true, pinToImmutable: true},
293+
{fileName: "actionwithcomment.yml", wantUpdated: true, pinToImmutable: true},
294+
{fileName: "repeatedactionwithcomment.yml", wantUpdated: true, pinToImmutable: true},
295+
{fileName: "immutableaction-1.yml", wantUpdated: true, pinToImmutable: true},
296+
{fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*"}, pinToImmutable: true},
297+
{fileName: "donotpintoimmutable.yml", wantUpdated: true, pinToImmutable: false},
281298
}
282299
for _, tt := range tests {
283300
input, err := ioutil.ReadFile(path.Join(inputDirectory, tt.fileName))
@@ -286,7 +303,7 @@ func TestPinActions(t *testing.T) {
286303
log.Fatal(err)
287304
}
288305

289-
output, gotUpdated, err := PinActions(string(input), tt.exemptedActions)
306+
output, gotUpdated, err := PinActions(string(input), tt.exemptedActions, tt.pinToImmutable)
290307
if tt.wantUpdated != gotUpdated {
291308
t.Errorf("test failed wantUpdated %v did not match gotUpdated %v", tt.wantUpdated, gotUpdated)
292309
}

remediation/workflow/secureworkflow.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const (
1313
HardenRunnerActionName = "Harden Runner"
1414
)
1515

16-
func SecureWorkflow(queryStringParams map[string]string, exemptedActions []string, inputYaml string, svc dynamodbiface.DynamoDBAPI) (*permissions.SecureWorkflowReponse, error) {
16+
func SecureWorkflow(queryStringParams map[string]string, exemptedActions []string, pinToImmutable bool, inputYaml string, svc dynamodbiface.DynamoDBAPI) (*permissions.SecureWorkflowReponse, error) {
1717
pinActions, addHardenRunner, addPermissions, addProjectComment := true, true, true, true
1818
pinnedActions, addedHardenRunner, addedPermissions := false, false, false
1919
ignoreMissingKBs := false
@@ -68,13 +68,13 @@ func SecureWorkflow(queryStringParams map[string]string, exemptedActions []strin
6868

6969
if pinActions {
7070
pinnedAction, pinnedDocker := false, false
71-
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions)
71+
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable)
7272
secureWorkflowReponse.FinalOutput, pinnedDocker, _ = pin.PinDocker(secureWorkflowReponse.FinalOutput)
7373
pinnedActions = pinnedAction || pinnedDocker
7474
}
7575

7676
if addHardenRunner {
77-
secureWorkflowReponse.FinalOutput, addedHardenRunner, _ = hardenrunner.AddAction(secureWorkflowReponse.FinalOutput, HardenRunnerActionPathWithTag, pinActions)
77+
secureWorkflowReponse.FinalOutput, addedHardenRunner, _ = hardenrunner.AddAction(secureWorkflowReponse.FinalOutput, HardenRunnerActionPathWithTag, pinActions, pinToImmutable)
7878
}
7979

8080
// Setting appropriate flags

remediation/workflow/secureworkflow_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func TestSecureWorkflow(t *testing.T) {
148148
}
149149
queryParams["addProjectComment"] = "false"
150150

151-
output, err := SecureWorkflow(queryParams, nil, string(input), &mockDynamoDBClient{})
151+
output, err := SecureWorkflow(queryParams, nil, false, string(input), &mockDynamoDBClient{})
152152

153153
if err != nil {
154154
t.Errorf("Error not expected")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Integration Test Github
2+
on: [push]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v1
8+
- uses: github/codeql-action/[email protected]
9+
- uses: borales/[email protected]
10+
with:
11+
auth-token: ${{ secrets.GITHUB_TOKEN }}
12+
registry-url: npm.pkg.github.com
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Integration Test Github
2+
on: [push]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0
8+
- uses: github/codeql-action/analyze@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3.28.2
9+
- uses: borales/actions-yarn@4965e1a0f0ae9c422a9a5748ebd1fb5e097d22b9 # v2.3.0
10+
with:
11+
auth-token: ${{ secrets.GITHUB_TOKEN }}
12+
registry-url: npm.pkg.github.com

0 commit comments

Comments
 (0)