Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEVEX-179] Add a TF module to make mono-repository setup easier #148

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
af0b770
alpha
Oct 17, 2024
1b256d7
add examples
Oct 17, 2024
463b0c9
add managed identities
Krusty93 Oct 25, 2024
b53639a
tweaks
Krusty93 Oct 28, 2024
1c224e2
add roles
Krusty93 Nov 4, 2024
5616c35
improvements
Krusty93 Nov 4, 2024
4a51a2c
fmt
Krusty93 Nov 4, 2024
8052cb1
add default
Krusty93 Nov 5, 2024
ce9eee9
remove data about azuread
Krusty93 Nov 5, 2024
728cd0e
fix syntax
Krusty93 Nov 5, 2024
bac6ad8
tentative to add github repo
Krusty93 Nov 5, 2024
e427c8b
remove imports
Krusty93 Nov 5, 2024
68e01ac
renaming
Krusty93 Nov 5, 2024
4f64867
add github provider
Krusty93 Nov 6, 2024
7676f4f
add security block to github repo
Krusty93 Nov 6, 2024
80a3f2e
add github envs
Krusty93 Nov 6, 2024
854f81e
module renaming
Krusty93 Nov 6, 2024
3aa092a
add gh runner and fixes
Krusty93 Nov 6, 2024
61a49ce
rename var
Krusty93 Nov 6, 2024
be66fd2
changes to kv ref
Krusty93 Nov 6, 2024
352a41b
other improvements
Krusty93 Nov 6, 2024
042480e
bug fixing
Krusty93 Nov 6, 2024
f57da78
reduce cae name
Krusty93 Nov 6, 2024
e78c254
solve warning
Krusty93 Nov 6, 2024
c1014cb
resource renaming
Krusty93 Nov 6, 2024
477b3bb
add variables for roles on vnet and apim
Nov 7, 2024
d0bff61
fix property
Nov 7, 2024
c4ad319
changes after PR
Krusty93 Nov 13, 2024
eace19f
add roles to dns zone rg
Krusty93 Nov 19, 2024
c48949d
comment out admins on gh branch protection
Krusty93 Nov 19, 2024
37fa86b
fix opex roles
Krusty93 Nov 25, 2024
8e5126b
remove comment
Dec 23, 2024
cd9a33d
fix parse
Dec 23, 2024
454f327
restore sub id
Dec 23, 2024
f92e530
disable signed commits
Dec 23, 2024
10dff20
add support for deployment policies
Dec 23, 2024
7fcaea9
update default
Dec 23, 2024
fb9a8e0
fix property
Dec 23, 2024
b12acee
add unit tests
Jan 7, 2025
8fb26cd
add more roles to ids
Jan 14, 2025
6c1d5d3
test w azure ad
Jan 14, 2025
73cdc18
remove w ad group
Jan 15, 2025
2ad26c7
role refactoring
Jan 15, 2025
2d261c0
fix roles
Jan 15, 2025
9adf5a4
restore role
Jan 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# azure_monorepo_single_env_starter_pack
129 changes: 129 additions & 0 deletions infra/modules/azure_monorepo_single_env_starter_pack/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# subscription roles defined in `eng-azure-authorization` repo

# Resource Group
resource "azurerm_role_assignment" "admins_group_rg" {
scope = azurerm_resource_group.main.id
role_definition_name = "Owner"
principal_id = var.entraid_groups.admins_object_id
description = "Allow ${var.repository.name} AD Admin group the complete ownership at monorepository resource group scope"
}

# Storage Account - Terraform state file
resource "azurerm_role_assignment" "admins_group_st_tf" {
scope = local.tf_storage_account.id
role_definition_name = "Storage Blob Data Contributor"
principal_id = var.entraid_groups.admins_object_id
description = "Allow ${var.repository.name} AD Admin group to apply changes to the Terraform state file Storage Account scope"
}

# Key Vault
resource "azurerm_role_assignment" "admins_group_rg_kv_data" {
scope = azurerm_resource_group.main.id
role_definition_name = "Key Vault Data Access Administrator"
principal_id = var.entraid_groups.admins_object_id
description = "Allow ${var.repository.name} AD Admin group to changes to apply changes to KeyVault's data at monorepository resource group scope"
}

resource "azurerm_role_assignment" "admins_group_rg_kv_admin" {
scope = azurerm_resource_group.main.id
role_definition_name = "Key Vault Administrator"
principal_id = var.entraid_groups.admins_object_id
description = "Allow ${var.repository.name} AD Admin group to changes to apply changes to KeyVault at monorepository resource group scope"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Resource Group
resource "azurerm_role_assignment" "devs_group_rg" {
scope = azurerm_resource_group.main.id
role_definition_name = "Contributor"
principal_id = var.entraid_groups.devs_object_id
description = "Allow ${var.repository.name} AD Dev group to apply changes at monorepository resource group scope"
}

# Storage Account - Terraform state file
resource "azurerm_role_assignment" "devs_group_tf_st" {
scope = local.tf_storage_account.id
role_definition_name = "Storage Blob Data Contributor"
principal_id = var.entraid_groups.devs_object_id
description = "Allow ${var.repository.name} AD Dev group to apply changes to the Terraform state file Storage Account scope"
}

# Key Vault
resource "azurerm_role_assignment" "devs_group_tf_rg_kv_secr" {
scope = azurerm_resource_group.main.id
role_definition_name = "Key Vault Secrets Officer"
principal_id = var.entraid_groups.devs_object_id
description = "Allow ${var.repository.name} AD Dev group to changes to KeyVault's secrets at monorepository resource group scope"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Resource Group
resource "azurerm_role_assignment" "externals_group_rg" {
count = var.entraid_groups.externals_object_id == null ? 0 : 1

scope = azurerm_resource_group.main.id
role_definition_name = "Reader"
principal_id = var.entraid_groups.externals_object_id
description = "Allow ${var.repository.name} AD external group to read resources at resource group scope"
}

# Storage Account - Terraform state file
resource "azurerm_role_assignment" "externals_group_tf_rg" {
count = var.entraid_groups.externals_object_id == null ? 0 : 1

scope = local.tf_storage_account.id
role_definition_name = "Storage Blob Data Reader"
principal_id = var.entraid_groups.externals_object_id
description = "Allow ${var.repository.name} AD external group to read blobs at the Terraform state file Storage Account scope"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

resource "azurerm_container_app_job" "github_runner" {
container_app_environment_id = var.github_private_runner.container_app_environment_id
name = local.container_apps.job_name
location = var.github_private_runner.container_app_environment_location
resource_group_name = azurerm_resource_group.main.name

identity {
type = "SystemAssigned"
}

replica_timeout_in_seconds = 1800
replica_retry_limit = 1

event_trigger_config {
parallelism = 1
replica_completion_count = 1

scale {
max_executions = var.github_private_runner.max_instances
min_executions = var.github_private_runner.min_instances
polling_interval_in_seconds = var.github_private_runner.polling_interval_in_seconds

rules {
name = "github-runner-rule"
custom_rule_type = "github-runner"
metadata = merge({
owner = var.repository.owner
runnerScope = "repo"
repos = var.repository.name
targetWorkflowQueueLength = "1"
github-runner = "https://api.github.com"
}, length(var.github_private_runner.labels) > 0 ? { labels = join(",", var.github_private_runner.labels) } : {})

authentication {
secret_name = local.container_apps.secret_name
trigger_parameter = "personalAccessToken"
}
}
}
}

secret {
key_vault_secret_id = "${data.azurerm_key_vault.runner.vault_uri}secrets/${var.github_private_runner.key_vault.secret_name}" # no versioning

identity = "System"
name = local.container_apps.secret_name
}

template {
container {
cpu = var.github_private_runner.cpu
image = "ghcr.io/pagopa/github-self-hosted-runner-azure:latest"
memory = var.github_private_runner.memory
name = "github-runner"

dynamic "env" {
for_each = var.github_private_runner.labels
content {
name = "LABELS"
value = join(",", var.github_private_runner.labels)
}
}

env {
name = "REPO_URL"
value = "https://github.com/${var.repository.owner}/${var.repository.name}"
}

env {
name = "REGISTRATION_TOKEN_API_URL"
value = "https://api.github.com/repos/${var.repository.owner}/${var.repository.name}/actions/runners/registration-token"
}

env {
name = "GITHUB_PAT"
secret_name = local.container_apps.secret_name
}
}
}

Krusty93 marked this conversation as resolved.
Show resolved Hide resolved
tags = var.tags
gunzip marked this conversation as resolved.
Show resolved Hide resolved
}

resource "azurerm_key_vault_access_policy" "keyvault_containerapp" {
key_vault_id = data.azurerm_key_vault.runner.id
tenant_id = azurerm_container_app_job.github_runner.identity[0].tenant_id
object_id = azurerm_container_app_job.github_runner.identity[0].principal_id

secret_permissions = [
"Get",
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
data "github_organization_teams" "all" {
root_teams_only = true
summary_only = true
}

data "azurerm_key_vault" "runner" {
name = var.github_private_runner.key_vault.name
resource_group_name = var.github_private_runner.key_vault.resource_group_name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
resource "github_branch_default" "main" {
repository = github_repository.this.name
branch = var.repository.default_branch_name
}

resource "github_branch_protection" "main" {
repository_id = github_repository.this.name
pattern = var.repository.default_branch_name

gunzip marked this conversation as resolved.
Show resolved Hide resolved
required_status_checks {
strict = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any value in having the branch up to date before merging as CI pipelines run over the merge commit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you elaborate a little bit more?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we're talking about monorepository (aka a single, potentially large repository), there is an high possibility that PR's branch is not up to date with main as other people are working on the same code base. I don't see this as an issue because the delta does not affect the validity of CI checks nor "manual" review as changes are on different paths. On the other hand, if changes are on the same files it is likely to have conflicts and PR cannot be merged

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's see what @pagopa/engineering-team-devex thinks about this

contexts = []
}

require_conversation_resolution = true
enforce_admins = true
require_signed_commits = false
allows_force_pushes = false
allows_deletions = false

required_pull_request_reviews {
dismiss_stale_reviews = false
require_code_owner_reviews = true
required_approving_review_count = 1
restrict_dismissals = true
}

gunzip marked this conversation as resolved.
Show resolved Hide resolved
lifecycle {
prevent_destroy = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
resource "github_repository_environment" "infra_prod_cd" {
environment = "infra-prod-cd"
repository = github_repository.this.name

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}
gunzip marked this conversation as resolved.
Show resolved Hide resolved

reviewers {
teams = matchkeys(
data.github_organization_teams.all.teams[*].id,
data.github_organization_teams.all.teams[*].slug,
local.infra_cd.reviewers_teams
)
}
gunzip marked this conversation as resolved.
Show resolved Hide resolved
}

resource "github_repository_environment" "app_prod_cd" {
environment = "app-prod-cd"
repository = github_repository.this.name

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}

reviewers {
teams = matchkeys(
data.github_organization_teams.all.teams[*].id,
data.github_organization_teams.all.teams[*].slug,
local.app_cd.reviewers_teams
)
}
}

resource "github_repository_environment" "opex_prod_cd" {
environment = "opex-prod-cd"
repository = github_repository.this.name

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}

reviewers {
teams = matchkeys(
data.github_organization_teams.all.teams[*].id,
data.github_organization_teams.all.teams[*].slug,
local.app_cd.reviewers_teams
)
}
}

resource "github_repository_environment_deployment_policy" "infra_prod_cd_branch" {
for_each = var.repository.infra_cd_policy_branches

repository = github_repository.this.name
environment = github_repository_environment.infra_prod_cd.environment
branch_pattern = each.value
}

resource "github_repository_environment_deployment_policy" "app_prod_cd_branch" {
for_each = var.repository.app_cd_policy_branches

repository = github_repository.this.name
environment = github_repository_environment.app_prod_cd.environment
branch_pattern = each.value
}

resource "github_repository_environment_deployment_policy" "opex_prod_cd_branch" {
for_each = var.repository.opex_cd_policy_branches

repository = github_repository.this.name
environment = github_repository_environment.opex_prod_cd.environment
branch_pattern = each.value
}

resource "github_repository_environment_deployment_policy" "infra_prod_cd_tag" {
for_each = var.repository.infra_cd_policy_tags

repository = github_repository.this.name
environment = github_repository_environment.infra_prod_cd.environment
tag_pattern = each.value
}

resource "github_repository_environment_deployment_policy" "app_prod_cd_tag" {
for_each = var.repository.app_cd_policy_tags

repository = github_repository.this.name
environment = github_repository_environment.app_prod_cd.environment
tag_pattern = each.value
}

resource "github_repository_environment_deployment_policy" "opex_prod_cd_tag" {
for_each = var.repository.opex_cd_policy_tags

repository = github_repository.this.name
environment = github_repository_environment.opex_prod_cd.environment
tag_pattern = each.value
}

resource "github_actions_environment_secret" "infra_prod_cd" {
for_each = local.infra_cd.secrets

repository = github_repository.this.name
environment = github_repository_environment.infra_prod_cd.environment
secret_name = each.key
plaintext_value = each.value
}

resource "github_actions_environment_secret" "app_prod_cd" {
for_each = local.app_cd.secrets

repository = github_repository.this.name
environment = github_repository_environment.app_prod_cd.environment
secret_name = each.key
plaintext_value = each.value
}

resource "github_actions_environment_secret" "opex_prod_cd" {
for_each = local.opex_cd.secrets

repository = github_repository.this.name
environment = github_repository_environment.opex_prod_cd.environment
secret_name = each.key
plaintext_value = each.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
resource "github_repository_environment" "infra_prod_ci" {
environment = "infra-prod-ci"
repository = github_repository.this.name

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}
}

resource "github_repository_environment" "opex_prod_ci" {
environment = "opex-prod-ci"
repository = github_repository.this.name

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}
}

resource "github_actions_environment_secret" "infra_prod_ci" {
for_each = local.infra_ci.secrets

repository = github_repository.this.name
environment = github_repository_environment.infra_prod_ci.environment
secret_name = each.key
plaintext_value = each.value
}

resource "github_actions_environment_secret" "opex_prod_ci" {
for_each = local.opex_ci.secrets

repository = github_repository.this.name
environment = github_repository_environment.opex_prod_ci.environment
secret_name = each.key
plaintext_value = each.value
}

Loading
Loading