Skip to content

Commit e940f43

Browse files
Merge pull request #23 from step-security/feat/pdpr-action-commit-map
Feat: Add action commit map attribute in pdpr for pinning actions.
2 parents 1b4fc4b + 8f7eb3d commit e940f43

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

docs/resources/policy_driven_pr.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ resource "stepsecurity_policy_driven_pr" "repo_level_config" {
7676
}
7777
]
7878
add_workflows = "https://github.com/[owner]/[repo]"
79+
action_commit_map = {
80+
"codecov/codecov-action@v5" : "cf3f51a67d2820f7a7cefa0831889fbbef41ca57",
81+
"codecov/codecov-action@v4" : "5ecb98a3c6b747ed38dc09f787459979aebb39be",
82+
"google-github-actions/auth@v2" : "ba79af03959ebeac9769e648f473a284504d9193",
83+
"google-github-actions/auth@v3" : "7c6bc770dae815cd3e89ee6cdf493a5fab2cc093"
84+
}
7985
}
8086
}
8187
@@ -132,6 +138,7 @@ import {
132138

133139
Optional:
134140

141+
- `action_commit_map` (Map of String) Map of actions to their corresponding commit SHAs to bypass pinning
135142
- `actions_to_exempt_while_pinning` (List of String) List of actions to exempt while pinning actions to SHA. When exempted, the action will not be pinned to SHA.
136143
- `actions_to_replace_with_step_security_actions` (List of String) List of actions to replace with Step Security actions. When provided, the actions will be replaced with Step Security actions.
137144
- `add_workflows` (String) Additional workflows to add as part of policy-driven PR.

examples/resources/stepsecurity_policy_driven_pr/resource.tf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ resource "stepsecurity_policy_driven_pr" "repo_level_config" {
6262
}
6363
]
6464
add_workflows = "https://github.com/[owner]/[repo]"
65+
action_commit_map = {
66+
"codecov/codecov-action@v5" : "cf3f51a67d2820f7a7cefa0831889fbbef41ca57",
67+
"codecov/codecov-action@v4" : "5ecb98a3c6b747ed38dc09f787459979aebb39be",
68+
"google-github-actions/auth@v2" : "ba79af03959ebeac9769e648f473a284504d9193",
69+
"google-github-actions/auth@v3" : "7c6bc770dae815cd3e89ee6cdf493a5fab2cc093"
70+
}
6571
}
6672
}
6773

@@ -93,4 +99,4 @@ resource "stepsecurity_policy_driven_pr" "org_level_with_exclusions" {
9399
import {
94100
to = stepsecurity_policy_driven_pr.org_level_all
95101
id = "test-organization"
96-
}
102+
}

internal/provider/resource_policy_driven_pr.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ func (r *policyDrivenPRResource) Schema(_ context.Context, _ resource.SchemaRequ
182182
Optional: true,
183183
Description: "Additional workflows to add as part of policy-driven PR.",
184184
},
185+
"action_commit_map": schema.MapAttribute{
186+
ElementType: types.StringType,
187+
Optional: true,
188+
Description: "Map of actions to their corresponding commit SHAs to bypass pinning",
189+
},
185190
},
186191
},
187192
"selected_repos": schema.ListAttribute{
@@ -310,6 +315,17 @@ func (r *policyDrivenPRResource) ImportState(ctx context.Context, req resource.I
310315
addWorkflowsValue = types.StringNull()
311316
}
312317

318+
var actionCommitMapValue types.Map
319+
if len(policy.AutoRemdiationOptions.ActionCommitMap) > 0 {
320+
mapElements := make(map[string]attr.Value)
321+
for key, value := range policy.AutoRemdiationOptions.ActionCommitMap {
322+
mapElements[key] = types.StringValue(value)
323+
}
324+
actionCommitMapValue, _ = types.MapValue(types.StringType, mapElements)
325+
} else {
326+
actionCommitMapValue = types.MapNull(types.StringType)
327+
}
328+
313329
optionsObj, _ := types.ObjectValue(
314330
map[string]attr.Type{
315331
"create_pr": types.BoolType,
@@ -330,7 +346,8 @@ func (r *policyDrivenPRResource) ImportState(ctx context.Context, req resource.I
330346
},
331347
},
332348
},
333-
"add_workflows": types.StringType,
349+
"add_workflows": types.StringType,
350+
"action_commit_map": types.MapType{ElemType: types.StringType},
334351
},
335352
map[string]attr.Value{
336353
"create_pr": types.BoolValue(policy.AutoRemdiationOptions.CreatePR),
@@ -345,6 +362,7 @@ func (r *policyDrivenPRResource) ImportState(ctx context.Context, req resource.I
345362
"update_precommit_file": updatePrecommitFileList,
346363
"package_ecosystem": packageEcosystemList,
347364
"add_workflows": addWorkflowsValue,
365+
"action_commit_map": actionCommitMapValue,
348366
},
349367
)
350368
state.AutoRemdiationOptions = optionsObj
@@ -375,6 +393,7 @@ type autoRemdiationOptionsModel struct {
375393
UpdatePrecommitFile types.List `tfsdk:"update_precommit_file"`
376394
PackageEcosystem types.List `tfsdk:"package_ecosystem"`
377395
AddWorkflows types.String `tfsdk:"add_workflows"`
396+
ActionCommitMap types.Map `tfsdk:"action_commit_map"`
378397
}
379398

380399
type packageEcosystemModel struct {
@@ -618,6 +637,14 @@ func (r *policyDrivenPRResource) Create(ctx context.Context, req resource.Create
618637
}
619638
}
620639

640+
var actionCommitMap map[string]string
641+
if !options.ActionCommitMap.IsNull() {
642+
actionCommitMap = make(map[string]string)
643+
for key, value := range options.ActionCommitMap.Elements() {
644+
actionCommitMap[key] = value.(types.String).ValueString()
645+
}
646+
}
647+
621648
// Automatically compute config levels based on selected_repos
622649
// If selected_repos = ["*"], use org-level config
623650
// Otherwise, use repo-level config
@@ -641,6 +668,7 @@ func (r *policyDrivenPRResource) Create(ctx context.Context, req resource.Create
641668
UpdatePrecommitFile: updatePrecommitFile,
642669
PackageEcosystem: packageEcosystem,
643670
AddWorkflows: options.AddWorkflows.ValueString(),
671+
ActionCommitMap: actionCommitMap,
644672
},
645673
SelectedRepos: selectedRepos,
646674
UseRepoLevelConfig: useRepoLevel,
@@ -875,6 +903,16 @@ func (r *policyDrivenPRResource) Read(ctx context.Context, req resource.ReadRequ
875903
tflog.Info(ctx, "Preserving actions_to_replace_with_step_security_actions from state")
876904
}
877905

906+
if !currentStateOptions.ActionCommitMap.IsNull() {
907+
stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap = make(map[string]string)
908+
for key, value := range currentStateOptions.ActionCommitMap.Elements() {
909+
stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap[key] = value.(types.String).ValueString()
910+
}
911+
tflog.Info(ctx, "Preserving action_commit_map from state")
912+
} else if len(stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap) == 0 {
913+
stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap = map[string]string{}
914+
}
915+
878916
// Update state with API response, preserving selected_repos and excluded_repos from state
879917
r.updatePolicyDrivenPRState(ctx, *stepSecurityPolicy, &state, stateSelectedRepos, stateExcludedRepos)
880918

@@ -1016,6 +1054,16 @@ func (r *policyDrivenPRResource) Update(ctx context.Context, req resource.Update
10161054
}
10171055
}
10181056

1057+
var actionCommitMapPlan map[string]string
1058+
if !planOptions.ActionCommitMap.IsNull() {
1059+
actionCommitMapPlan = make(map[string]string)
1060+
for key, value := range planOptions.ActionCommitMap.Elements() {
1061+
actionCommitMapPlan[key] = value.(types.String).ValueString()
1062+
}
1063+
} else if len(planOptions.ActionCommitMap.Elements()) == 0 {
1064+
actionCommitMapPlan = map[string]string{}
1065+
}
1066+
10191067
// Automatically compute config levels based on planRepos
10201068
// If planRepos = ["*"], use org-level config
10211069
// Otherwise, use repo-level config
@@ -1038,6 +1086,7 @@ func (r *policyDrivenPRResource) Update(ctx context.Context, req resource.Update
10381086
UpdatePrecommitFile: updatePrecommitFilePlan,
10391087
PackageEcosystem: packageEcosystemPlan,
10401088
AddWorkflows: planOptions.AddWorkflows.ValueString(),
1089+
ActionCommitMap: actionCommitMapPlan,
10411090
},
10421091
SelectedRepos: planRepos,
10431092
UseRepoLevelConfig: useRepoLevel,
@@ -1225,6 +1274,17 @@ func (r *policyDrivenPRResource) updatePolicyDrivenPRState(ctx context.Context,
12251274
addWorkflowsValue = types.StringNull()
12261275
}
12271276

1277+
var actionCommitMapValue types.Map
1278+
if len(stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap) > 0 {
1279+
mapElements := make(map[string]attr.Value)
1280+
for key, value := range stepSecurityPolicy.AutoRemdiationOptions.ActionCommitMap {
1281+
mapElements[key] = types.StringValue(value)
1282+
}
1283+
actionCommitMapValue, _ = types.MapValue(types.StringType, mapElements)
1284+
} else {
1285+
actionCommitMapValue = types.MapNull(types.StringType)
1286+
}
1287+
12281288
optionsObj, _ := types.ObjectValue(
12291289
map[string]attr.Type{
12301290
"create_pr": types.BoolType,
@@ -1245,7 +1305,8 @@ func (r *policyDrivenPRResource) updatePolicyDrivenPRState(ctx context.Context,
12451305
},
12461306
},
12471307
},
1248-
"add_workflows": types.StringType,
1308+
"add_workflows": types.StringType,
1309+
"action_commit_map": types.MapType{ElemType: types.StringType},
12491310
},
12501311
map[string]attr.Value{
12511312
"create_pr": types.BoolValue(stepSecurityPolicy.AutoRemdiationOptions.CreatePR),
@@ -1260,6 +1321,7 @@ func (r *policyDrivenPRResource) updatePolicyDrivenPRState(ctx context.Context,
12601321
"update_precommit_file": updatePrecommitFileList,
12611322
"package_ecosystem": packageEcosystemList,
12621323
"add_workflows": addWorkflowsValue,
1324+
"action_commit_map": actionCommitMapValue,
12631325
},
12641326
)
12651327
state.AutoRemdiationOptions = optionsObj

internal/stepsecurity-api/gh-policy-driven-prs.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type AutoRemdiationOptions struct {
3030
UpdatePrecommitFile []string `json:"update_precommit_file,omitempty"`
3131
PackageEcosystem []DependabotConfig `json:"package_ecosystem,omitempty"`
3232
AddWorkflows string `json:"add_workflows,omitempty"`
33+
ActionCommitMap map[string]string `json:"action_commit_map"`
3334
}
3435

3536
// API request/response structures matching agent-api
@@ -56,6 +57,7 @@ type controlSettings struct {
5657
PackageEcosystem []DependabotConfig `json:"package_ecosystem,omitempty"`
5758
AddWorkflows string `json:"add_workflows,omitempty"`
5859
ApplyIssuePRConfigForAllRepos *bool `json:"apply_issue_pr_config_for_all_repos,omitempty"`
60+
ActionCommitMap map[string]string `json:"action_commit_map"`
5961
}
6062

6163
type DependabotConfig struct {
@@ -169,6 +171,7 @@ func (c *APIClient) CreatePolicyDrivenPRPolicy(ctx context.Context, createReques
169171
UpdatePrecommitFile: updatePrecommitFileMap,
170172
PackageEcosystem: createRequest.AutoRemdiationOptions.PackageEcosystem,
171173
AddWorkflows: createRequest.AutoRemdiationOptions.AddWorkflows,
174+
ActionCommitMap: createRequest.AutoRemdiationOptions.ActionCommitMap,
172175
ApplyIssuePRConfigForAllRepos: &applyToAllRepos,
173176
}
174177

0 commit comments

Comments
 (0)