Skip to content

Commit 28b4579

Browse files
Merge pull request #2540 from vamshi-stepsecurity/feat/pin-using-action-commit-map
2 parents 0eded23 + fe0a86d commit 28b4579

File tree

6 files changed

+127
-15
lines changed

6 files changed

+127
-15
lines changed

remediation/workflow/hardenrunner/addaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func AddAction(inputYaml, action string, pinActions, pinToImmutable bool, skipCo
5151
}
5252

5353
if updated && pinActions {
54-
out, _ = pin.PinAction(action, out, nil, pinToImmutable)
54+
out, _ = pin.PinAction(action, out, nil, pinToImmutable, nil)
5555
}
5656

5757
return out, updated, nil

remediation/workflow/pin/pinactions.go

Lines changed: 31 additions & 10 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, pinToImmutable bool) (string, bool, error) {
17+
func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool, actionCommitMap map[string]string) (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, pinToImmutable bool)
2929
for _, step := range job.Steps {
3030
if len(step.Uses) > 0 {
3131
localUpdated := false
32-
out, localUpdated = PinAction(step.Uses, out, exemptedActions, pinToImmutable)
32+
out, localUpdated = PinAction(step.Uses, out, exemptedActions, pinToImmutable, actionCommitMap)
3333
updated = updated || localUpdated
3434
}
3535
}
@@ -38,7 +38,7 @@ func PinActions(inputYaml string, exemptedActions []string, pinToImmutable bool)
3838
return out, updated, nil
3939
}
4040

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

4343
updated := false
4444
if !strings.Contains(action, "@") || strings.HasPrefix(action, "docker://") {
@@ -69,15 +69,36 @@ func PinAction(action, inputYaml string, exemptedActions []string, pinToImmutabl
6969
tc := oauth2.NewClient(ctx, ts)
7070

7171
client := github.NewClient(tc)
72-
73-
commitSHA, _, err := client.Repositories.GetCommitSHA1(ctx, owner, repo, tagOrBranch, "")
74-
if err != nil {
75-
return inputYaml, updated
72+
var commitSHA string
73+
var err error
74+
75+
if actionCommitMap != nil {
76+
// Check case-insensitively by iterating through the map
77+
for mapAction, actionWithCommit := range actionCommitMap {
78+
if strings.EqualFold(action, mapAction) && actionWithCommit != "" {
79+
commitSHA = strings.Split(actionWithCommit, "@")[1]
80+
81+
if !semanticTagRegex.MatchString(tagOrBranch) {
82+
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
83+
if err != nil {
84+
return inputYaml, updated
85+
}
86+
}
87+
break
88+
}
89+
}
7690
}
7791

78-
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
79-
if err != nil {
80-
return inputYaml, updated
92+
if commitSHA == "" {
93+
commitSHA, _, err = client.Repositories.GetCommitSHA1(ctx, owner, repo, tagOrBranch, "")
94+
if err != nil {
95+
return inputYaml, updated
96+
}
97+
tagOrBranch, err = getSemanticVersion(client, owner, repo, tagOrBranch, commitSHA)
98+
if err != nil {
99+
return inputYaml, updated
100+
}
101+
81102
}
82103

83104
// pinnedAction := fmt.Sprintf("%s@%s # %s", leftOfAt[0], commitSHA, tagOrBranch)

remediation/workflow/pin/pinactions_test.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ func TestPinActions(t *testing.T) {
239239
}
240240
})
241241

242+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/peter-evans-test/close-issue/commits/v1",
243+
httpmock.NewStringResponder(200, `a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe`))
244+
245+
httpmock.RegisterResponder("GET", "https://api.github.com/repos/peter-evans-test/close-issue/git/matching-refs/tags/v1.",
246+
httpmock.NewStringResponder(200,
247+
`[
248+
{
249+
"ref": "refs/tags/v1.0.4",
250+
"object": {
251+
"sha": "a700eac5bf2a1c7a8cb6da0c13f93ed96fd53vam",
252+
"type": "commit"
253+
}
254+
}
255+
]`))
256+
242257
// Mock manifest endpoints for specific versions and commit hashes
243258
manifestResponders := []string{
244259
// the following list will contain the list of actions with versions
@@ -296,15 +311,29 @@ func TestPinActions(t *testing.T) {
296311
{fileName: "exemptaction.yml", wantUpdated: true, exemptedActions: []string{"actions/checkout", "rohith/*"}, pinToImmutable: true},
297312
{fileName: "donotpintoimmutable.yml", wantUpdated: true, pinToImmutable: false},
298313
{fileName: "invertedcommas.yml", wantUpdated: true, pinToImmutable: false},
314+
{fileName: "pinusingmap.yml", wantUpdated: true, pinToImmutable: true},
299315
}
300316
for _, tt := range tests {
317+
318+
var output string
319+
var gotUpdated bool
320+
var err error
321+
var actionCommitMap map[string]string
322+
301323
input, err := ioutil.ReadFile(path.Join(inputDirectory, tt.fileName))
302324

303325
if err != nil {
304326
log.Fatal(err)
305327
}
306328

307-
output, gotUpdated, err := PinActions(string(input), tt.exemptedActions, tt.pinToImmutable)
329+
if tt.fileName == "pinusingmap.yml" {
330+
actionCommitMap = map[string]string{
331+
"peter-evans-test/close-issue@v1": "peter-evans-test/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53vam",
332+
"peter-check/[email protected]": "peter-check/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53tom",
333+
}
334+
}
335+
336+
output, gotUpdated, err = PinActions(string(input), tt.exemptedActions, tt.pinToImmutable, actionCommitMap)
308337
if tt.wantUpdated != gotUpdated {
309338
t.Errorf("test failed wantUpdated %v did not match gotUpdated %v", tt.wantUpdated, gotUpdated)
310339
}

remediation/workflow/secureworkflow.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d
2424
enableLogging := false
2525
addEmptyTopLevelPermissions := false
2626
skipHardenRunnerForContainers := false
27-
exemptedActions, pinToImmutable, maintainedActionsMap := []string{}, false, map[string]string{}
27+
exemptedActions, pinToImmutable, maintainedActionsMap, actionCommitMap := []string{}, false, map[string]string{}, map[string]string{}
2828

2929
if len(params) > 0 {
3030
if v, ok := params[0].([]string); ok {
@@ -41,6 +41,11 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d
4141
maintainedActionsMap = v
4242
}
4343
}
44+
if len(params) > 3 {
45+
if v, ok := params[3].(map[string]string); ok {
46+
actionCommitMap = v
47+
}
48+
}
4449

4550
if queryStringParams["pinActions"] == "false" {
4651
pinActions = false
@@ -143,7 +148,7 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d
143148
log.Printf("Pinning GitHub Actions")
144149
}
145150
pinnedAction, pinnedDocker := false, false
146-
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable)
151+
secureWorkflowReponse.FinalOutput, pinnedAction, _ = pin.PinActions(secureWorkflowReponse.FinalOutput, exemptedActions, pinToImmutable, actionCommitMap)
147152
secureWorkflowReponse.FinalOutput, pinnedDocker, _ = pin.PinDocker(secureWorkflowReponse.FinalOutput)
148153
pinnedActions = pinnedAction || pinnedDocker
149154
if enableLogging {
@@ -176,10 +181,11 @@ func SecureWorkflow(queryStringParams map[string]string, inputYaml string, svc d
176181
secureWorkflowReponse.AddedMaintainedActions = replacedMaintainedActions
177182

178183
if enableLogging {
179-
log.Printf("SecureWorkflow complete - PinnedActions: %v, AddedHardenRunner: %v, AddedPermissions: %v, HasErrors: %v",
184+
log.Printf("SecureWorkflow complete - PinnedActions: %v, AddedHardenRunner: %v, AddedPermissions: %v, AddedMaintainedActions: %v, HasErrors: %v",
180185
secureWorkflowReponse.PinnedActions,
181186
secureWorkflowReponse.AddedHardenRunner,
182187
secureWorkflowReponse.AddedPermissions,
188+
secureWorkflowReponse.AddedMaintainedActions,
183189
secureWorkflowReponse.HasErrors)
184190
}
185191

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: "close issue"
2+
3+
on:
4+
push:
5+
6+
7+
jobs:
8+
closeissue:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Close Issue
13+
uses: peter-evans-test/close-issue@v1
14+
with:
15+
issue-number: 1
16+
comment: Auto-closing issue
17+
18+
- name: Close Issue
19+
uses: peter-evans/close-issue@v1
20+
with:
21+
issue-number: 1
22+
comment: Auto-closing issue
23+
24+
- name: Close Issue
25+
uses: peter-check/[email protected]
26+
with:
27+
issue-number: 1
28+
comment: Auto-closing issue
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: "close issue"
2+
3+
on:
4+
push:
5+
6+
7+
jobs:
8+
closeissue:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Close Issue
13+
uses: peter-evans-test/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53vam # v1.0.4
14+
with:
15+
issue-number: 1
16+
comment: Auto-closing issue
17+
18+
- name: Close Issue
19+
uses: peter-evans/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53dbe # v1.0.3
20+
with:
21+
issue-number: 1
22+
comment: Auto-closing issue
23+
24+
- name: Close Issue
25+
uses: peter-check/close-issue@a700eac5bf2a1c7a8cb6da0c13f93ed96fd53tom # v1.2.3
26+
with:
27+
issue-number: 1
28+
comment: Auto-closing issue

0 commit comments

Comments
 (0)