Skip to content

Commit 52e1853

Browse files
authored
feat: Add github_actions_enterprise_permissions (#2155)
* Adding github_actions_enterprise_permissions (#1) * Adding enterprise permissions resource * Working version * Adding docs * Functioning tests * Adding check on integration tests * Switching to github_enterprise_actions_permissions
1 parent 4cebab8 commit 52e1853

5 files changed

+662
-0
lines changed

github/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func Provider() *schema.Provider {
125125
},
126126

127127
ResourcesMap: map[string]*schema.Resource{
128+
"github_enterprise_actions_permissions": resourceGithubActionsEnterprisePermissions(),
128129
"github_actions_environment_secret": resourceGithubActionsEnvironmentSecret(),
129130
"github_actions_environment_variable": resourceGithubActionsEnvironmentVariable(),
130131
"github_actions_organization_oidc_subject_claim_customization_template": resourceGithubActionsOrganizationOIDCSubjectClaimCustomizationTemplate(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"github.com/google/go-github/v57/github"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
10+
)
11+
12+
func resourceGithubActionsEnterprisePermissions() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceGithubActionsEnterprisePermissionsCreateOrUpdate,
15+
Read: resourceGithubActionsEnterprisePermissionsRead,
16+
Update: resourceGithubActionsEnterprisePermissionsCreateOrUpdate,
17+
Delete: resourceGithubActionsEnterprisePermissionsDelete,
18+
Importer: &schema.ResourceImporter{
19+
StateContext: schema.ImportStatePassthroughContext,
20+
},
21+
22+
Schema: map[string]*schema.Schema{
23+
"enterprise_id": {
24+
Type: schema.TypeString,
25+
Required: true,
26+
ForceNew: true,
27+
Description: "The ID of the enterprise.",
28+
},
29+
"allowed_actions": {
30+
Type: schema.TypeString,
31+
Optional: true,
32+
Description: "The permissions policy that controls the actions that are allowed to run. Can be one of: 'all', 'local_only', or 'selected'.",
33+
ValidateDiagFunc: toDiagFunc(validation.StringInSlice([]string{"all", "local_only", "selected"}, false), "allowed_actions"),
34+
},
35+
"enabled_organizations": {
36+
Type: schema.TypeString,
37+
Required: true,
38+
Description: "The policy that controls the organizations in the enterprise that are allowed to run GitHub Actions. Can be one of: 'all', 'none', or 'selected'.",
39+
ValidateDiagFunc: toDiagFunc(validation.StringInSlice([]string{"all", "none", "selected"}, false), "enabled_organizations"),
40+
},
41+
"allowed_actions_config": {
42+
Type: schema.TypeList,
43+
Optional: true,
44+
MaxItems: 1,
45+
Description: "Sets the actions that are allowed in an enterprise. Only available when 'allowed_actions' = 'selected'",
46+
Elem: &schema.Resource{
47+
Schema: map[string]*schema.Schema{
48+
"github_owned_allowed": {
49+
Type: schema.TypeBool,
50+
Required: true,
51+
Description: "Whether GitHub-owned actions are allowed in the enterprise.",
52+
},
53+
"patterns_allowed": {
54+
Type: schema.TypeSet,
55+
Optional: true,
56+
Description: "Specifies a list of string-matching patterns to allow specific action(s). Wildcards, tags, and SHAs are allowed. For example, 'monalisa/octocat@', 'monalisa/octocat@v2', 'monalisa/'.",
57+
Elem: &schema.Schema{Type: schema.TypeString},
58+
Set: schema.HashString,
59+
},
60+
"verified_allowed": {
61+
Type: schema.TypeBool,
62+
Optional: true,
63+
Description: "Whether actions in GitHub Marketplace from verified creators are allowed. Set to 'true' to allow all GitHub Marketplace actions by verified creators.",
64+
},
65+
},
66+
},
67+
},
68+
"enabled_organizations_config": {
69+
Type: schema.TypeList,
70+
Optional: true,
71+
MaxItems: 1,
72+
Description: "Sets the list of selected organizations that are enabled for GitHub Actions in an enterprise. Only available when 'enabled_organizations' = 'selected'.",
73+
Elem: &schema.Resource{
74+
Schema: map[string]*schema.Schema{
75+
"organization_ids": {
76+
Type: schema.TypeSet,
77+
Description: "List of organization IDs to enable for GitHub Actions.",
78+
Elem: &schema.Schema{Type: schema.TypeInt},
79+
Required: true,
80+
},
81+
},
82+
},
83+
},
84+
},
85+
}
86+
}
87+
88+
func resourceGithubActionsEnterpriseAllowedObject(d *schema.ResourceData) (*github.ActionsAllowed, error) {
89+
allowed := &github.ActionsAllowed{}
90+
91+
config := d.Get("allowed_actions_config").([]interface{})
92+
if len(config) > 0 {
93+
data := config[0].(map[string]interface{})
94+
switch x := data["github_owned_allowed"].(type) {
95+
case bool:
96+
allowed.GithubOwnedAllowed = &x
97+
}
98+
99+
switch x := data["verified_allowed"].(type) {
100+
case bool:
101+
allowed.VerifiedAllowed = &x
102+
}
103+
104+
patternsAllowed := []string{}
105+
106+
switch t := data["patterns_allowed"].(type) {
107+
case *schema.Set:
108+
for _, value := range t.List() {
109+
patternsAllowed = append(patternsAllowed, value.(string))
110+
}
111+
}
112+
113+
allowed.PatternsAllowed = patternsAllowed
114+
} else {
115+
return &github.ActionsAllowed{},
116+
errors.New("the allowed_actions_config {} block must be specified if allowed_actions == 'selected'")
117+
}
118+
119+
return allowed, nil
120+
}
121+
122+
func resourceGithubActionsEnabledOrganizationsObject(d *schema.ResourceData) ([]int64, error) {
123+
var enabled []int64
124+
125+
config := d.Get("enabled_organizations_config").([]interface{})
126+
if len(config) > 0 {
127+
data := config[0].(map[string]interface{})
128+
switch x := data["organization_ids"].(type) {
129+
case *schema.Set:
130+
for _, value := range x.List() {
131+
enabled = append(enabled, int64(value.(int)))
132+
}
133+
}
134+
} else {
135+
return nil, errors.New("the enabled_organizations_config {} block must be specified if enabled_organizations == 'selected'")
136+
}
137+
return enabled, nil
138+
}
139+
140+
func resourceGithubActionsEnterprisePermissionsCreateOrUpdate(d *schema.ResourceData, meta interface{}) error {
141+
client := meta.(*Owner).v3client
142+
143+
ctx := context.Background()
144+
if !d.IsNewResource() {
145+
ctx = context.WithValue(ctx, ctxId, d.Id())
146+
}
147+
148+
enterpriseId := d.Get("enterprise_id").(string)
149+
allowedActions := d.Get("allowed_actions").(string)
150+
enabledOrganizations := d.Get("enabled_organizations").(string)
151+
152+
_, _, err := client.Actions.EditActionsPermissionsInEnterprise(ctx,
153+
enterpriseId,
154+
github.ActionsPermissionsEnterprise{
155+
AllowedActions: &allowedActions,
156+
EnabledOrganizations: &enabledOrganizations,
157+
})
158+
if err != nil {
159+
return err
160+
}
161+
162+
if allowedActions == "selected" {
163+
actionsAllowedData, err := resourceGithubActionsEnterpriseAllowedObject(d)
164+
if err != nil {
165+
return err
166+
}
167+
_, _, err = client.Actions.EditActionsAllowedInEnterprise(ctx,
168+
enterpriseId,
169+
*actionsAllowedData)
170+
if err != nil {
171+
return err
172+
}
173+
}
174+
175+
if enabledOrganizations == "selected" {
176+
enabledOrgsData, err := resourceGithubActionsEnabledOrganizationsObject(d)
177+
if err != nil {
178+
return err
179+
}
180+
_, err = client.Actions.SetEnabledOrgsInEnterprise(ctx,
181+
enterpriseId,
182+
enabledOrgsData)
183+
if err != nil {
184+
return err
185+
}
186+
}
187+
188+
d.SetId(enterpriseId)
189+
return resourceGithubActionsEnterprisePermissionsRead(d, meta)
190+
}
191+
192+
func resourceGithubActionsEnterprisePermissionsRead(d *schema.ResourceData, meta interface{}) error {
193+
client := meta.(*Owner).v3client
194+
ctx := context.Background()
195+
196+
actionsPermissions, _, err := client.Actions.GetActionsPermissionsInEnterprise(ctx, d.Id())
197+
if err != nil {
198+
return err
199+
}
200+
201+
if actionsPermissions.GetAllowedActions() == "selected" {
202+
actionsAllowed, _, err := client.Actions.GetActionsAllowedInEnterprise(ctx, d.Id())
203+
if err != nil {
204+
return err
205+
}
206+
207+
// If actionsAllowed set to local/all by removing all actions config settings, the response will be empty
208+
if actionsAllowed != nil {
209+
if err = d.Set("allowed_actions_config", []interface{}{
210+
map[string]interface{}{
211+
"github_owned_allowed": actionsAllowed.GetGithubOwnedAllowed(),
212+
"patterns_allowed": actionsAllowed.PatternsAllowed,
213+
"verified_allowed": actionsAllowed.GetVerifiedAllowed(),
214+
},
215+
}); err != nil {
216+
return err
217+
}
218+
}
219+
} else {
220+
if err = d.Set("allowed_actions_config", []interface{}{}); err != nil {
221+
return err
222+
}
223+
}
224+
225+
if actionsPermissions.GetEnabledOrganizations() == "selected" {
226+
opts := github.ListOptions{PerPage: 10, Page: 1}
227+
var orgList []int64
228+
var allOrgs []*github.Organization
229+
230+
for {
231+
enabledOrgs, resp, err := client.Actions.ListEnabledOrgsInEnterprise(ctx, d.Id(), &opts)
232+
if err != nil {
233+
return err
234+
}
235+
allOrgs = append(allOrgs, enabledOrgs.Organizations...)
236+
237+
opts.Page = resp.NextPage
238+
239+
if resp.NextPage == 0 {
240+
break
241+
}
242+
}
243+
for index := range allOrgs {
244+
orgList = append(orgList, *allOrgs[index].ID)
245+
}
246+
if allOrgs != nil {
247+
if err = d.Set("enabled_organizations_config", []interface{}{
248+
map[string]interface{}{
249+
"organization_ids": orgList,
250+
},
251+
}); err != nil {
252+
return err
253+
}
254+
} else {
255+
if err = d.Set("enabled_organizations_config", []interface{}{}); err != nil {
256+
return err
257+
}
258+
}
259+
}
260+
261+
if err = d.Set("allowed_actions", actionsPermissions.GetAllowedActions()); err != nil {
262+
return err
263+
}
264+
if err = d.Set("enabled_organizations", actionsPermissions.GetEnabledOrganizations()); err != nil {
265+
return err
266+
}
267+
268+
return nil
269+
}
270+
271+
func resourceGithubActionsEnterprisePermissionsDelete(d *schema.ResourceData, meta interface{}) error {
272+
client := meta.(*Owner).v3client
273+
274+
ctx := context.WithValue(context.Background(), ctxId, d.Id())
275+
276+
// This will nullify any allowedActions elements
277+
_, _, err := client.Actions.EditActionsPermissionsInEnterprise(ctx,
278+
d.Get("enterprise_id").(string),
279+
github.ActionsPermissionsEnterprise{
280+
AllowedActions: github.String("all"),
281+
EnabledOrganizations: github.String("all"),
282+
})
283+
if err != nil {
284+
return err
285+
}
286+
287+
return nil
288+
}

0 commit comments

Comments
 (0)