Skip to content

Commit c83839f

Browse files
jtgrohnkfcampbell
andauthored
Bugfix: Make security_and_analysis settings optional (#1489)
* make advanced security property optional, defaulting to disabled for public repositories - default to - not setting advanced_security - as it is enabled by default and uneditable - disabling - secret scanning and - secret scanning push protection. * add example repository security and analysis * make security_and_analysis secret_scanning and secret_scanning_and_push_protection properties optional Co-authored-by: Keegan Campbell <me@kfcampbell.com>
1 parent d27da35 commit c83839f

File tree

8 files changed

+237
-115
lines changed

8 files changed

+237
-115
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Repository Visibility Example
2+
3+
This demos setting `security_and_analysis` for a repository. See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-security-and-analysis-settings-for-your-repository for details on what these settings do.
4+
5+
This example will create a repositories in the specified `owner` organization. See https://www.terraform.io/docs/providers/github/index.html for details on configuring [`providers.tf`](./providers.tf) accordingly.
6+
7+
Alternatively, you may use variables passed via command line:
8+
9+
```console
10+
export GITHUB_OWNER=
11+
export GITHUB_TOKEN=
12+
```
13+
14+
```console
15+
terraform apply \
16+
-var "owner=${GITHUB_OWNER}" \
17+
-var "github_token=${GITHUB_TOKEN}"
18+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
resource "github_repository" "terraformed" {
2+
name = "terraformed"
3+
description = "A repository created by terraform"
4+
visibility = "public"
5+
6+
security_and_analysis {
7+
# Cannot set advanced_security for public repositories as it is always on by default.
8+
# advanced_security {
9+
# status = "enabled"
10+
# }
11+
secret_scanning {
12+
status = "enabled"
13+
}
14+
secret_scanning_push_protection {
15+
status = "enabled"
16+
}
17+
}
18+
}
19+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "repository" {
2+
description = "Example repository JSON blob"
3+
value = github_repository.terraformed
4+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
provider "github" {
2+
owner = var.owner
3+
token = var.github_token
4+
}
5+
6+
terraform {
7+
required_providers {
8+
github = {
9+
source = "integrations/github"
10+
}
11+
}
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
variable "owner" {
2+
description = "GitHub owner used to configure the provider"
3+
type = string
4+
}
5+
6+
variable "github_token" {
7+
description = "GitHub access token used to configure the provider"
8+
type = string
9+
}

github/resource_github_repository.go

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ func resourceGithubRepository() *schema.Resource {
6060
"security_and_analysis": {
6161
Type: schema.TypeList,
6262
Optional: true,
63+
Computed: true,
6364
MaxItems: 1,
6465
Description: "Security and analysis settings for the repository. To use this parameter you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository.",
6566
Elem: &schema.Resource{
6667
Schema: map[string]*schema.Schema{
6768
"advanced_security": {
6869
Type: schema.TypeList,
69-
Required: true,
70+
Optional: true,
7071
MaxItems: 1,
7172
Elem: &schema.Resource{
7273
Schema: map[string]*schema.Schema{
@@ -80,7 +81,7 @@ func resourceGithubRepository() *schema.Resource {
8081
},
8182
"secret_scanning": {
8283
Type: schema.TypeList,
83-
Required: true,
84+
Optional: true,
8485
MaxItems: 1,
8586
Elem: &schema.Resource{
8687
Schema: map[string]*schema.Schema{
@@ -94,7 +95,7 @@ func resourceGithubRepository() *schema.Resource {
9495
},
9596
"secret_scanning_push_protection": {
9697
Type: schema.TypeList,
97-
Required: true,
98+
Optional: true,
9899
MaxItems: 1,
99100
Elem: &schema.Resource{
100101
Schema: map[string]*schema.Schema{
@@ -352,6 +353,54 @@ func calculateVisibility(d *schema.ResourceData) string {
352353
return "public"
353354
}
354355

356+
func tryGetSecurityAndAnalysisSettingStatus(securityAndAnalysis map[string]interface{}, setting string) (bool, string) {
357+
value, ok := securityAndAnalysis[setting]
358+
if !ok {
359+
return false, ""
360+
}
361+
362+
asList := value.([]interface{})
363+
if len(asList) == 0 || asList[0] == nil {
364+
return false, ""
365+
}
366+
367+
return true, asList[0].(map[string]interface{})["status"].(string)
368+
}
369+
370+
func calculateSecurityAndAnalysis(d *schema.ResourceData) *github.SecurityAndAnalysis {
371+
value, ok := d.GetOk("security_and_analysis")
372+
if !ok {
373+
return nil
374+
}
375+
376+
asList := value.([]interface{})
377+
if len(asList) == 0 || asList[0] == nil {
378+
return nil
379+
}
380+
381+
lookup := asList[0].(map[string]interface{})
382+
383+
var securityAndAnalysis github.SecurityAndAnalysis
384+
385+
if ok, status := tryGetSecurityAndAnalysisSettingStatus(lookup, "advanced_security"); ok {
386+
securityAndAnalysis.AdvancedSecurity = &github.AdvancedSecurity{
387+
Status: github.String(status),
388+
}
389+
}
390+
if ok, status := tryGetSecurityAndAnalysisSettingStatus(lookup, "secret_scanning"); ok {
391+
securityAndAnalysis.SecretScanning = &github.SecretScanning{
392+
Status: github.String(status),
393+
}
394+
}
395+
if ok, status := tryGetSecurityAndAnalysisSettingStatus(lookup, "secret_scanning_push_protection"); ok {
396+
securityAndAnalysis.SecretScanningPushProtection = &github.SecretScanningPushProtection{
397+
Status: github.String(status),
398+
}
399+
}
400+
401+
return &securityAndAnalysis
402+
}
403+
355404
func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
356405
return &github.Repository{
357406
Name: github.String(d.Get("name").(string)),
@@ -379,6 +428,7 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
379428
Archived: github.Bool(d.Get("archived").(bool)),
380429
Topics: expandStringList(d.Get("topics").(*schema.Set).List()),
381430
AllowUpdateBranch: github.Bool(d.Get("allow_update_branch").(bool)),
431+
SecurityAndAnalysis: calculateSecurityAndAnalysis(d),
382432
}
383433
}
384434

@@ -477,14 +527,6 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta interface{}) er
477527
}
478528
}
479529

480-
securityAndAnalysis := expandSecurityAndAnalysis(d.Get("security_and_analysis").([]interface{}))
481-
if securityAndAnalysis != nil {
482-
_, _, err := client.Repositories.Edit(ctx, owner, repoName, securityAndAnalysis)
483-
if err != nil {
484-
return err
485-
}
486-
}
487-
488530
return resourceGithubRepositoryUpdate(d, meta)
489531
}
490532

@@ -634,29 +676,6 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta interface{}) er
634676
}
635677
}
636678

637-
if d.HasChange("security_and_analysis") && !d.IsNewResource() {
638-
opts := expandSecurityAndAnalysis(d.Get("security_and_analysis").([]interface{}))
639-
if opts != nil {
640-
_, _, err := client.Repositories.Edit(ctx, owner, repoName, opts)
641-
if err != nil {
642-
return err
643-
}
644-
} else { // disable security and analysis
645-
_, _, err := client.Repositories.Edit(ctx, owner, repoName, &github.Repository{
646-
SecurityAndAnalysis: &github.SecurityAndAnalysis{
647-
AdvancedSecurity: &github.AdvancedSecurity{
648-
Status: github.String("disabled")},
649-
SecretScanning: &github.SecretScanning{
650-
Status: github.String("disabled")},
651-
SecretScanningPushProtection: &github.SecretScanningPushProtection{
652-
Status: github.String("disabled")}},
653-
})
654-
if err != nil {
655-
return err
656-
}
657-
}
658-
}
659-
660679
if d.HasChange("topics") {
661680
topics := repoReq.Topics
662681
_, _, err = client.Repositories.ReplaceAllTopics(ctx, owner, *repo.Name, topics)
@@ -815,45 +834,22 @@ func flattenSecurityAndAnalysis(securityAndAnalysis *github.SecurityAndAnalysis)
815834
return []interface{}{}
816835
}
817836

818-
advancedSecurityMap := make(map[string]interface{})
819-
advancedSecurityMap["status"] = securityAndAnalysis.GetAdvancedSecurity().GetStatus()
820-
821-
secretScanningMap := make(map[string]interface{})
822-
secretScanningMap["status"] = securityAndAnalysis.GetSecretScanning().GetStatus()
823-
824-
secretScanningPushProtectionMap := make(map[string]interface{})
825-
secretScanningPushProtectionMap["status"] = securityAndAnalysis.GetSecretScanningPushProtection().GetStatus()
826-
827837
securityAndAnalysisMap := make(map[string]interface{})
828-
securityAndAnalysisMap["advanced_security"] = []interface{}{advancedSecurityMap}
829-
securityAndAnalysisMap["secret_scanning"] = []interface{}{secretScanningMap}
830-
securityAndAnalysisMap["secret_scanning_push_protection"] = []interface{}{secretScanningPushProtectionMap}
831-
832-
return []interface{}{securityAndAnalysisMap}
833-
}
834-
835-
func expandSecurityAndAnalysis(input []interface{}) *github.Repository {
836-
if len(input) == 0 || input[0] == nil {
837-
return nil
838-
}
839-
840-
securityAndAnalysis := input[0].(map[string]interface{})
841-
update := &github.SecurityAndAnalysis{}
842838

843-
advancedSecurity := securityAndAnalysis["advanced_security"].([]interface{})[0].(map[string]interface{})
844-
update.AdvancedSecurity = &github.AdvancedSecurity{
845-
Status: github.String(advancedSecurity["status"].(string)),
839+
advancedSecurity := securityAndAnalysis.GetAdvancedSecurity()
840+
if advancedSecurity != nil {
841+
securityAndAnalysisMap["advanced_security"] = []interface{}{map[string]interface{}{
842+
"status": advancedSecurity.GetStatus(),
843+
}}
846844
}
847845

848-
secretScanning := securityAndAnalysis["secret_scanning"].([]interface{})[0].(map[string]interface{})
849-
update.SecretScanning = &github.SecretScanning{
850-
Status: github.String(secretScanning["status"].(string)),
851-
}
846+
securityAndAnalysisMap["secret_scanning"] = []interface{}{map[string]interface{}{
847+
"status": securityAndAnalysis.GetSecretScanning().GetStatus(),
848+
}}
852849

853-
secretScanningPushProtection := securityAndAnalysis["secret_scanning_push_protection"].([]interface{})[0].(map[string]interface{})
854-
update.SecretScanningPushProtection = &github.SecretScanningPushProtection{
855-
Status: github.String(secretScanningPushProtection["status"].(string)),
856-
}
850+
securityAndAnalysisMap["secret_scanning_push_protection"] = []interface{}{map[string]interface{}{
851+
"status": securityAndAnalysis.GetSecretScanningPushProtection().GetStatus(),
852+
}}
857853

858-
return &github.Repository{SecurityAndAnalysis: update}
854+
return []interface{}{securityAndAnalysisMap}
859855
}

0 commit comments

Comments
 (0)