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

Use terraform to maintain the organizational structure #14

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c5285e1
terraform org mgmt
cunla Jul 12, 2024
f175617
terraform org mgmt
cunla Jul 12, 2024
e59e51d
terraform org mgmt
cunla Jul 12, 2024
19ce7dc
terraform org mgmt
cunla Jul 13, 2024
de7a932
terraform org mgmt
cunla Jul 13, 2024
5d0ede6
terraform org mgmt
cunla Jul 13, 2024
56d0267
terraform org mgmt
cunla Jul 13, 2024
6edf954
terraform org mgmt
cunla Jul 15, 2024
1165e81
terraform org mgmt
cunla Jul 16, 2024
6b638e7
remove webhooks
cunla Jul 20, 2024
2023d5f
added permissions to readme
cunla Jul 20, 2024
6616b25
readme changes
cunla Jul 20, 2024
46ff1b4
readme changes
cunla Jul 20, 2024
9ffc5e6
readme changes
cunla Jul 20, 2024
b423afc
gha
cunla Jul 20, 2024
0c37c09
gha
cunla Jul 20, 2024
0bb5e56
gha
cunla Jul 20, 2024
bad31e0
gha
cunla Jul 20, 2024
61dc4a4
gha
cunla Jul 20, 2024
9ac827d
gha
cunla Jul 20, 2024
9cff7bb
gha
cunla Jul 20, 2024
298065b
gha
cunla Jul 20, 2024
0874fda
gha
cunla Jul 20, 2024
96000ca
gha
cunla Jul 20, 2024
6bb454d
gha
cunla Jul 20, 2024
a9e312b
gha
cunla Jul 20, 2024
6661316
Use member as dynamic variable to avoid confusion with the members list.
tim-schilling Jul 24, 2024
e042e5b
Adjust repository defaults.
tim-schilling Jul 24, 2024
3332bf9
Comment the main terraform file with descriptions of what each sectio…
tim-schilling Jul 24, 2024
8b997ce
Pin the terraform github action third-party actions to SHA hashes.
tim-schilling Jul 24, 2024
1d0af1e
Use domain specific naming for variables.
tim-schilling Jul 24, 2024
bd3f0ad
Re-add review request delegation.
tim-schilling Jul 24, 2024
94358af
Attempt to split the org teams from the repo teams.
tim-schilling Jul 24, 2024
16354a6
Revise the playbooks for the new names for the variables.
tim-schilling Jul 24, 2024
7e5837f
Fix missed team_parents reference.
tim-schilling Jul 24, 2024
99c0cfc
Update terraform specific docs with new variable names.
tim-schilling Jul 24, 2024
274b098
The teams are maps, not lists.
tim-schilling Jul 24, 2024
b057101
Revert change, use dynamic members.
tim-schilling Jul 24, 2024
e46b855
Remove maintainers collections where they are unnecessary.
tim-schilling Jul 24, 2024
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
9 changes: 9 additions & 0 deletions terraform/backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Backend Configuration
# https://www.terraform.io/language/settings/backends/configuration

terraform {
backend "local" {
path = "tfstate.json"
}

}
55 changes: 55 additions & 0 deletions terraform/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Local Values
# https://www.terraform.io/language/values/locals

locals {

admins = {
for user in var.admins : user => "admin"
}

branch_protections = {
for repository_key, repository in var.repositories : repository_key => repository if repository.enable_branch_protection
}

child_team_repositories = {

for repository in flatten([
for team_child_key, team_child in var.team_children : [
for repository in team_child.repositories : {
team_child = team_child_key
repository = repository
permission = team_child.permission
}
]
]) : "${repository.team_child}-${repository.repository}" => repository }

datadog_webhooks = {
for repository_key, repository in var.repositories : repository_key => repository if repository.enable_datadog_webhook
}

discord_webhooks = {
for repository_key, repository in var.repositories : repository_key => repository if repository.enable_discord_webhook
}
cunla marked this conversation as resolved.
Show resolved Hide resolved

members = {
for user in var.members : user => "member"
}

parent_team_repositories = {

for repository in flatten([
for team_parent_key, team_parent in var.team_parents : [
for repository in team_parent.repositories : {
team_parent = team_parent_key
repository = repository
permission = team_parent.permission
}
]
]) : "${repository.team_parent}-${repository.repository}" => repository }

review_request_delegations = {
for team_parent_key, team_parent in var.team_parents : team_parent_key => team_parent if team_parent.review_request_delegation
}

users = merge(local.admins, local.members)
}
290 changes: 290 additions & 0 deletions terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
# Required Providers
# https://www.terraform.io/docs/language/providers/requirements.html#requiring-providers

terraform {
required_providers {
github = {
source = "integrations/github"
}

# Random Provider
# https://registry.terraform.io/providers/hashicorp/random/latest/docs

random = {
source = "hashicorp/random"
}

# Time Provider
# https://registry.terraform.io/providers/hashicorp/time/latest/docs

time = {
source = "hashicorp/time"
}
}
}

# Github Provider
# https://registry.terraform.io/providers/integrations/github/latest/docs

provider "github" {
owner = "django-commons"
token = var.github_token
}

# Github Actions Secret Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_secret

resource "github_actions_organization_secret" "this" {

# Ensure GitHub Actions secrets are encrypted
# checkov:skip=CKV_GIT_4: We are passing the secret from the random_password resource which is sensitive by default
# and not checking in any plain text values. State is always secured.

for_each = var.organization_secrets

plaintext_value = random_password.this[each.key].result
secret_name = each.key
visibility = each.value.visibility
}

# Github Branch Protection Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection
#
# resource "github_branch_protection" "this" {
#
# # GitHub pull requests should require at least 2 approvals
# # checkov:skip=CKV_GIT_5: 1 approval is reasonable for a small team
# for_each = local.branch_protections
#
# enforce_admins = false
# pattern = "main"
# repository_id = github_repository.this[each.key].name
# require_conversation_resolution = true
# required_linear_history = true
# require_signed_commits = true
#
# required_pull_request_reviews {
# dismiss_stale_reviews = true
# require_code_owner_reviews = true
# required_approving_review_count = 1
# }
#
# required_status_checks {
# contexts = each.value.required_status_checks_contexts
# strict = true
# }
#
# restrict_pushes {
# push_allowances = each.value.push_allowances
# }
# }

# GitHub Membership Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/membership

resource "github_membership" "this" {
for_each = local.users

role = each.value
username = each.key
}

# Github Organization Security Manager Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_security_manager

resource "github_organization_security_manager" "this" {
team_slug = github_team.parents["security-team"].slug
}

# Github Repository Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository

resource "github_repository" "this" {

# Ensure GitHub repository is Private
# checkov:skip=CKV_GIT_1: Public is ok for us since we are an open source project

for_each = var.repositories

allow_auto_merge = each.value.allow_auto_merge
allow_merge_commit = each.value.allow_merge_commit
allow_rebase_merge = each.value.allow_rebase_merge
allow_squash_merge = each.value.allow_squash_merge
allow_update_branch = each.value.allow_update_branch
archive_on_destroy = true
delete_branch_on_merge = true
description = each.value.description
has_downloads = each.value.has_downloads
has_discussions = each.value.has_discussions
has_issues = true
has_projects = true
has_wiki = false
cunla marked this conversation as resolved.
Show resolved Hide resolved
is_template = each.value.is_template
name = each.key
squash_merge_commit_message = "BLANK"
squash_merge_commit_title = "PR_TITLE"
topics = each.value.topics
visibility = each.value.visibility
vulnerability_alerts = false

dynamic "template" {
for_each = each.value.template != null ? [each.value.template] : []

content {
owner = "django-commons"
repository = template.value
}
}
}

# GitHub Repository File Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_file
#
# resource "github_repository_file" "security_policy" {
# for_each = var.repositories
#
# branch = "main"
# content = templatefile("${path.module}/markdown/SECURITY.md.tpl", { repository = each.key })
# file = "SECURITY.md"
# repository = each.key
# commit_message = "Update SECURITY.md"
# commit_author = "Open Source Infrastructure as Code Service Account"
# commit_email = "github-sa@osinfra.io"
# overwrite_on_create = true
#
# depends_on = [
# github_branch_protection.this
# ]
# }


# Github Team Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team

# If you need to import a team, you can do so with the following command:
# terraform import github_team.this\[\"google-cloud-platform\"\] <team_id>

# To get the team ids, you can run the following curl command with a token that has the read:org scope against your own organization.
# curl -H "Authorization: token $GITHUB_READ_ORG_TOKEN" https://api.github.com/orgs/osinfra-io/teams

resource "github_team" "parents" {
for_each = var.team_parents

name = each.key
description = each.value.description
privacy = each.value.privacy
}

resource "github_team" "children" {
for_each = var.team_children

description = each.value.description
name = each.key
parent_team_id = github_team.parents[each.value.parent_team_key].id
privacy = github_team.parents[each.value.parent_team_key].privacy
}

# GitHub Team Membership Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_members

resource "github_team_members" "parents" {
for_each = var.team_parents

team_id = github_team.parents[each.key].id

dynamic "members" {
for_each = each.value.members

content {
username = members.value
role = "member"
}
}

dynamic "members" {
for_each = each.value.maintainers

content {
username = members.value
tim-schilling marked this conversation as resolved.
Show resolved Hide resolved
role = "maintainer"
}
}
}

resource "github_team_members" "children" {
for_each = var.team_children

team_id = github_team.children[each.key].id

dynamic "members" {
for_each = each.value.members

content {
username = members.value
role = "member"
}
}

dynamic "members" {
for_each = each.value.maintainers

content {
username = members.value
role = "maintainer"
}
}
}

# Github Team Repository Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_repository

resource "github_team_repository" "children" {
for_each = local.child_team_repositories

team_id = github_team.children[each.value.team_child].id
repository = each.value.repository
permission = each.value.permission
}

resource "github_team_repository" "parents" {
for_each = local.parent_team_repositories

team_id = github_team.parents[each.value.team_parent].id
repository = each.value.repository
permission = each.value.permission
}

# GitHub Team Settings Resource
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_settings

resource "github_team_settings" "this" {
for_each = local.review_request_delegations

review_request_delegation {
algorithm = "LOAD_BALANCE"
member_count = 2
notify = false
}

team_id = github_team.parents[each.key].id
}

# Random Password Resource
# https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password

resource "random_password" "this" {
tim-schilling marked this conversation as resolved.
Show resolved Hide resolved
for_each = var.organization_secrets
length = 32
special = false

keepers = {
rotation_time = time_rotating.this.rotation_rfc3339
}
}

# Time Rotating Resource
# https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/rotating

resource "time_rotating" "this" {
tim-schilling marked this conversation as resolved.
Show resolved Hide resolved
rotation_days = 5
}
10 changes: 10 additions & 0 deletions terraform/markdown/SECURITY.md.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# <img align="left" width="45" height="45" src="https://github.com/osinfra-io/terraform-google-cloud-sql/assets/1610100/ef899efa-b2ce-4c31-83cf-debefadd481d"> Security Policy

Open Source Infrastructure (as Code) exposes identifying information that would not be exposed in a traditional
private organization to share knowledge and best practices. This is a net positive for
the community, but it does come with some risks.

## Reporting a Vulnerability

Privately discuss, fix, and publish information about security vulnerabilities in this repository by drafting a new
[security advisory](https://github.com/osinfra-io/${repository}/security/advisories/new).
Loading