Skip to content

Commit 2e3e2b9

Browse files
authored
feat(iluwaa): Add support for security_and_analysis (#2)
Reworked from mineiros-io#143 by @iluwaa
1 parent fd5eef1 commit 2e3e2b9

File tree

7 files changed

+156
-8
lines changed

7 files changed

+156
-8
lines changed

README.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ A [Terraform] module for creating a public or private repository on [Github].
1818
- [Resources](#resources)
1919
- [Inputs](#inputs)
2020
- [Outputs](#outputs)
21+
- [Security And Analysis Configuration](#security-and-analysis-configuration)
2122
- [External Documentation](#external-documentation)
2223
- [Terraform Github Provider Documentation](#terraform-github-provider-documentation)
2324
- [Module Versioning](#module-versioning)
@@ -87,13 +88,13 @@ See [variables.tf] and [examples/] for details and use-cases.
8788
| Name | Version |
8889
|------|---------|
8990
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3 |
90-
| <a name="requirement_github"></a> [github](#requirement\_github) | >= 6.2, < 7.0 |
91+
| <a name="requirement_github"></a> [github](#requirement\_github) | >= 6.2, < 6.9 |
9192

9293
### Providers
9394

9495
| Name | Version |
9596
|------|---------|
96-
| <a name="provider_github"></a> [github](#provider\_github) | >= 6.2, < 7.0 |
97+
| <a name="provider_github"></a> [github](#provider\_github) | >= 6.2, < 6.9 |
9798

9899
### Resources
99100

@@ -178,6 +179,7 @@ See [variables.tf] and [examples/] for details and use-cases.
178179
| <a name="input_push_team_ids"></a> [push\_team\_ids](#input\_push\_team\_ids) | (Optional) A list of teams (by id) to grant push (read-write) permission to. | `list(string)` | `[]` | no |
179180
| <a name="input_push_teams"></a> [push\_teams](#input\_push\_teams) | (Optional) A list of teams (by name/slug) to grant push (read-write) permission to. | `list(string)` | `[]` | no |
180181
| <a name="input_rulesets"></a> [rulesets](#input\_rulesets) | (Optional) A list of branch rulesets to apply to the repository. Default is [].<br/><br/>It is very likely removal of any section will require setting it to an empty list/map.<br/>This is due to limitations in the API whereby components are not destroyed upon removal. | <pre>list(<br/> object({<br/> enforcement = string<br/> name = string<br/> target = string<br/><br/> rules = list(<br/> object({<br/> creation = optional(bool)<br/> deletion = optional(bool)<br/> non_fast_forward = optional(bool)<br/> required_signatures = optional(bool)<br/> required_linear_history = optional(bool)<br/> update = optional(bool)<br/> update_allows_fetch_and_merge = optional(bool)<br/><br/> branch_name_pattern = optional(<br/> object({<br/> operator = string<br/> pattern = string<br/> name = optional(string)<br/> negate = optional(bool)<br/> })<br/> )<br/><br/> commit_author_email_pattern = optional(<br/> object({<br/> operator = string<br/> pattern = string<br/> name = optional(string)<br/> negate = optional(bool)<br/> })<br/> )<br/><br/> commit_message_pattern = optional(<br/> object({<br/> operator = string<br/> pattern = string<br/> name = optional(string)<br/> negate = optional(bool)<br/> })<br/> )<br/><br/> committer_email_pattern = optional(<br/> object({<br/> operator = string<br/> pattern = string<br/> name = optional(string)<br/> negate = optional(bool)<br/> })<br/> )<br/><br/> tag_name_pattern = optional(<br/> object({<br/> operator = string<br/> pattern = string<br/> name = optional(string)<br/> negate = optional(bool)<br/> })<br/> )<br/><br/> required_status_checks = optional(<br/> object({<br/> strict_required_status_checks_policy = optional(bool)<br/> do_not_enforce_on_create = optional(bool)<br/> required_check = list(<br/> object({<br/> context = string<br/> integration_id = optional(number)<br/> })<br/> )<br/> })<br/> )<br/><br/> pull_request = optional(<br/> object({<br/> dismiss_stale_reviews_on_push = optional(bool)<br/> require_code_owner_review = optional(bool)<br/> require_last_push_approval = optional(bool)<br/> required_approving_review_count = optional(number)<br/> required_review_thread_resolution = optional(bool)<br/> })<br/> )<br/><br/> required_workflows = optional(<br/> object({<br/> required_workflow = list(<br/> object({<br/> repository_id = number<br/> ref = string<br/> path = string<br/> })<br/> )<br/> })<br/> )<br/><br/> required_deployments = optional(<br/> object({<br/> required_deployment_environments = list(string)<br/> })<br/> )<br/><br/> required_code_scanning = optional(<br/> object({<br/> required_code_scanning_tool = list(<br/> object({<br/> tool = string<br/> alerts_threshold = string<br/> security_alerts_threshold = string<br/> })<br/> )<br/> })<br/> )<br/><br/> merge_queue = optional(<br/> object({<br/> check_response_timeout_minutes = optional(number)<br/> grouping_strategy = optional(string)<br/> max_entries_to_build = optional(number)<br/> max_entries_to_merge = optional(number)<br/> merge_method = optional(string)<br/> min_entries_to_merge = optional(number)<br/> min_entries_to_merge_wait_minutes = optional(number)<br/> })<br/> )<br/> })<br/> )<br/><br/> bypass_actors = optional(<br/> list(<br/> object({<br/> actor_id = optional(number)<br/> actor_type = string<br/> bypass_mode = optional(string)<br/> })<br/> )<br/> )<br/><br/> conditions = optional(<br/> object({<br/> ref_name = object({<br/> include = list(string)<br/> exclude = list(string)<br/> })<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
182+
| <a name="input_security_and_analysis"></a> [security\_and\_analysis](#input\_security\_and\_analysis) | (Optional) Security and analysis configuration for the repository.<br/><br/>- All fields except org\_advanced\_security are strings: "enabled" or "disabled".<br/>- org\_advanced\_security is a bool indicating whether the org has split licensing for Advanced Security. | <pre>object({<br/> org_advanced_security = optional(bool, false)<br/> advanced_security = optional(string, "disabled")<br/> code_security = optional(string, "disabled")<br/> secret_scanning = optional(string, "disabled")<br/> secret_scanning_push_protection = optional(string, "disabled")<br/> secret_scanning_ai_detection = optional(string, "disabled")<br/> secret_scanning_non_provider_patterns = optional(string, "disabled")<br/> })</pre> | `null` | no |
181183
| <a name="input_squash_merge_commit_message"></a> [squash\_merge\_commit\_message](#input\_squash\_merge\_commit\_message) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. | `string` | `"COMMIT_MESSAGES"` | no |
182184
| <a name="input_squash_merge_commit_title"></a> [squash\_merge\_commit\_title](#input\_squash\_merge\_commit\_title) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. | `string` | `"COMMIT_OR_PR_TITLE"` | no |
183185
| <a name="input_template"></a> [template](#input\_template) | (Optional) Template repository to use. (Default: {}) | <pre>object({<br/> owner = string<br/> repository = string<br/> })</pre> | `null` | no |
@@ -210,6 +212,41 @@ See [variables.tf] and [examples/] for details and use-cases.
210212
| <a name="output_webhooks"></a> [webhooks](#output\_webhooks) | All attributes and arguments as returned by the github\_repository\_webhook resource. |
211213
<!-- END_TF_DOCS -->
212214

215+
### Security And Analysis Configuration
216+
217+
- [**`security_and_analysis`**](#var-security_and_analysis): *(Optional `object(security_and_analysis)`)*<a name="var-security_and_analysis"></a>
218+
219+
(Optional) The repository's [security and analysis](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) configuration.
220+
See [Security and Analysis Configuration](#security-and-analysis-configuration) below for details.
221+
222+
Default is `null`.
223+
224+
The `security_and_analysis` object accepts the following attributes:
225+
226+
- [**`org_advanced_security`**](#attr-security_and_analysis-org_advanced_security: *(**Optional** `bool`)*<a name="attr-security_and_analysis-org_advanced_security"></a>
227+
228+
If your GitHub Organization has split licensing for Advanced Security you can have Security and Analysis on non-public repositories. Otherwise Security and Analysis operates on all public repositories. Currently there is no known way to automatically detect this.
229+
230+
Define `org_advanced_security` as true to give more visibility options.
231+
232+
- [**`advanced_security`**](#attr-security_and_analysis-advanced_security): *(**Optional** `string`)*<a name="attr-security_and_analysis-advanced_security"></a>
233+
234+
The advanced security configuration for the repository. See [Advanced Security Configuration](#advanced-security-configuration) below for details.
235+
236+
Default is `"disabled"`, except if `org_advanced_security` is not true when it is `"enabled"`.
237+
238+
- [**`secret_scanning`**](#attr-security_and_analysis-secret_scanning): *(**Optional** `string`)*<a name="attr-security_and_analysis-secret_scanning"></a>
239+
240+
The secret scanning configuration for the repository. See [Secret Scanning Configuration](#secret-scanning-configuration) below for details.
241+
242+
Default is `"disabled"`.
243+
244+
- [**`secret_scanning_push_protection`**](#attr-security_and_analysis-secret_scanning_push_protection): *(**Optional** `string`)*<a name="attr-security_and_analysis-secret_scanning_push_protection"></a>
245+
246+
The secret scanning push protection configuration for the repository. See [Secret Scanning Push Protection Configuration](#secret-scanning-push-protection-configuration) below for details.
247+
248+
Default is `"disabled"`.
249+
213250
## External Documentation
214251

215252
### Terraform Github Provider Documentation

locals.tf

Lines changed: 0 additions & 5 deletions
This file was deleted.

main.tf

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,63 @@ resource "github_repository" "repository" {
153153
}
154154
}
155155

156+
dynamic "security_and_analysis" {
157+
for_each = (
158+
var.visibility == "public" || local.security_and_analysis.org_advanced_security
159+
) ? [local.security_and_analysis] : []
160+
161+
content {
162+
dynamic "advanced_security" {
163+
for_each = var.visibility == "public" ? [] : [local.advanced_security_status]
164+
content {
165+
status = advanced_security.value
166+
}
167+
}
168+
169+
secret_scanning {
170+
status = local.security_and_analysis.secret_scanning
171+
}
172+
173+
secret_scanning_push_protection {
174+
status = local.security_and_analysis.secret_scanning_push_protection
175+
}
176+
177+
# code_security, secret_scanning_ai_detection, and secret_scanning_non_provider_patterns require integrations/github >= 6.9
178+
# code_security {
179+
# status = local.security_and_analysis.code_security
180+
# }
181+
# secret_scanning_ai_detection {
182+
# status = local.security_and_analysis.secret_scanning_ai_detection
183+
# }
184+
# secret_scanning_non_provider_patterns {
185+
# status = local.security_and_analysis.secret_scanning_non_provider_patterns
186+
# }
187+
}
188+
}
189+
156190
lifecycle {
157191
ignore_changes = [
158192
auto_init,
159193
license_template,
160194
gitignore_template,
161195
template,
162196
]
197+
precondition {
198+
condition = (
199+
(
200+
var.visibility == "public"
201+
|| local.security_and_analysis.org_advanced_security
202+
|| !local.saa_child_enabled
203+
)
204+
&&
205+
local.push_protection_valid
206+
)
207+
error_message = (
208+
local.push_protection_valid
209+
? "security_and_analysis cannot be used for private/internal repositories unless org_advanced_security is true."
210+
: "secret_scanning_push_protection requires secret_scanning to also be enabled."
211+
)
212+
}
163213
}
164214
}
165215

rulesets_resources.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
locals {
2+
rulesets_by_name = {
3+
for rs in var.rulesets : rs.name => rs
4+
}
5+
}
6+
17
resource "github_repository_ruleset" "ruleset" {
28
for_each = local.rulesets_by_name
39

securityanalysis_resources.tf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
locals {
2+
security_and_analysis = var.security_and_analysis != null ? var.security_and_analysis : {
3+
org_advanced_security = false
4+
advanced_security = "disabled"
5+
code_security = "disabled"
6+
secret_scanning = "disabled"
7+
secret_scanning_push_protection = "disabled"
8+
secret_scanning_ai_detection = "disabled"
9+
secret_scanning_non_provider_patterns = "disabled"
10+
}
11+
12+
saa_child_enabled = (
13+
local.security_and_analysis.code_security == "enabled" ||
14+
local.security_and_analysis.secret_scanning == "enabled" ||
15+
local.security_and_analysis.secret_scanning_push_protection == "enabled" ||
16+
local.security_and_analysis.secret_scanning_ai_detection == "enabled" ||
17+
local.security_and_analysis.secret_scanning_non_provider_patterns == "enabled"
18+
)
19+
20+
advanced_security_status = (
21+
local.saa_child_enabled || local.security_and_analysis.advanced_security == "enabled"
22+
) ? "enabled" : "disabled"
23+
24+
push_protection_valid = (
25+
local.security_and_analysis.secret_scanning_push_protection == "enabled"
26+
? local.security_and_analysis.secret_scanning == "enabled"
27+
: true
28+
)
29+
}

securityanalysis_variables.tf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
variable "security_and_analysis" {
2+
description = <<EOF
3+
(Optional) Security and analysis configuration for the repository.
4+
5+
- All fields except org_advanced_security are strings: "enabled" or "disabled".
6+
- org_advanced_security is a bool indicating whether the org has split licensing for Advanced Security.
7+
EOF
8+
type = object({
9+
org_advanced_security = optional(bool, false)
10+
advanced_security = optional(string, "disabled")
11+
code_security = optional(string, "disabled")
12+
secret_scanning = optional(string, "disabled")
13+
secret_scanning_push_protection = optional(string, "disabled")
14+
secret_scanning_ai_detection = optional(string, "disabled")
15+
secret_scanning_non_provider_patterns = optional(string, "disabled")
16+
})
17+
18+
default = null
19+
20+
validation {
21+
condition = (
22+
alltrue([
23+
for key, value in(
24+
var.security_and_analysis != null ? var.security_and_analysis : {}
25+
) :
26+
key != "org_advanced_security" ? contains(["enabled", "disabled"], value) : true
27+
])
28+
)
29+
error_message = "All security_and_analysis string fields must be 'enabled' or 'disabled'."
30+
}
31+
}

versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ terraform {
88
required_providers {
99
github = {
1010
source = "integrations/github"
11-
version = ">= 6.2, < 7.0"
11+
version = ">= 6.2, < 6.9"
1212
}
1313
}
1414
}

0 commit comments

Comments
 (0)