Skip to content

Commit

Permalink
feat(aad-groups): for demo org team structure
Browse files Browse the repository at this point in the history
Merge branch 'feat/aad-groups' into main

* feat/aad-groups:
  chore: remove unused module main.tf
  style: tf formatter
  rbac: assign roles to aad groups
  azure-ad: add contribtor and own groups per team
  • Loading branch information
julie-ng committed Oct 14, 2020
2 parents 2fe3df5 + 0e7c220 commit 314f52c
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 84 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# Terraform - state and plan files
.terraform/
*.tfplan
*.tfstate
*.tfstate.*

# Debugging
debug.azcli
Expand Down
91 changes: 73 additions & 18 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,93 @@
# unique names. Use a suffix to avoid automation errors.

resource "random_string" "suffix" {
length = 5
length = 4
special = false
upper = false
}

# List of Workspaces
# ------------------
# This map defines our workspaces. The keys can be referenced in outputs,
# e.g. module.workspace["gov_shared"]. Suffixes are appended later.
locals {
suffix = random_string.suffix.result
}

variable "workspaces" {

# Azure AD Groups
# ---------------
# Workspaces generally have 2 groups of actors, general
# team members who are granted "Contributor" permissions
# and admins who are granted "Owner" permissions.

variable "teams" {
type = map(string)
default = {
fruits_dev = "fruits-dev"
fruits_prod = "fruits-prod"
veggies_dev = "veggies-dev"
veggies_prod = "veggies-prod"
gov_shared = "gov-shared"
fruits = "fruits"
fruits_admins = "fruits-admins"
veggies_admins = "veggies-admins"
veggies = "veggies"
infra = "infra"
infra_admins = "infra"
}
}

# Module: Create Workspaces
# -------------------------
# Finally create workspaces, which in this demo are resource groups.
# Using `*` automatically output _all_ module outputs.
resource "azuread_group" "groups" {
for_each = var.teams
name = "demo-${each.value}-${local.suffix}"
prevent_duplicate_names = true
}


# Workspaces
# ----------
# This map defines our workspaces. The keys can be referenced in outputs,
# e.g. module.workspace["gov_shared"]. Suffixes are appended later.

variable "environments" {
type = map(map(string))

default = {
fru_dev = {
env = "dev"
team = "fruits"
}

fru_prod = {
env = "prod"
team = "fruits"
}

veg_dev = {
env = "dev"
team = "veggies"
}

veg_prod = {
env = "prod"
team = "veggies"
}

shared = {
env = "shared"
team = "infra"
}
}
}

module "workspace" {
for_each = var.workspaces
source = "./modules/workspace"
name = "${each.value}-${random_string.suffix.result}"
for_each = var.environments
source = "./modules/workspace"
name = "${each.value.team}-${each.value.env}-${local.suffix}"
team_group_id = azuread_group.groups["${each.value.team}"].id
admin_group_id = azuread_group.groups["${each.value.team}_admins"].id
}


# Outputs
# -------

output "workspaces" {
value = module.workspace[*]
}

output "aad_groups" {
value = azuread_group.groups[*]
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,49 +117,3 @@ resource "azurerm_key_vault_secret" "kv_reader_sp_secret" {
azurerm_key_vault_access_policy.me
]
}


# SERVICE_PRINCIPALS
# ------------------

# SP - Workspace (scoped to resource group)

resource "azuread_application" "workspace_sp" {
name = "${local.name}-rg-sp"

depends_on = [
azurerm_resource_group.workspace
]
}

resource "azuread_application_password" "workspace_sp_secret" {
application_object_id = azuread_application.workspace_sp.object_id
value = random_password.workspace_sp.result
end_date_relative = "4380h" # 6 months
}

resource "azuread_service_principal" "workspace_sp" {
application_id = azuread_application.workspace_sp.application_id
}

resource "azurerm_role_assignment" "workspace_sp" {
scope = azurerm_resource_group.workspace.id
role_definition_name = "Contributor"
principal_id = azuread_service_principal.workspace_sp.id
}

# SP - Key Vault Reader (just for Azure Pipeline)

resource "azuread_application" "kv_reader_sp" {
name = "${local.name}-kv-reader-sp"
}

resource "azuread_application_password" "kv_reader_sp_secret" {
application_object_id = azuread_application.kv_reader_sp.object_id
value = random_password.kv_reader_sp.result
end_date_relative = "4380h" # 6 months
}

resource "azuread_service_principal" "kv_reader_sp" {
application_id = azuread_application.kv_reader_sp.application_id
}
27 changes: 27 additions & 0 deletions modules/workspace/_rbac.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Owners
# ------

resource "azurerm_role_assignment" "team_admins" {
role_definition_name = "Owner"
principal_id = var.admin_group_id
scope = azurerm_resource_group.workspace.id
}

# Contributors
# ------------

# Service Principal

resource "azurerm_role_assignment" "workspace_sp" {
role_definition_name = "Contributor"
principal_id = azuread_service_principal.workspace_sp.id
scope = azurerm_resource_group.workspace.id
}

# AAD Group

resource "azurerm_role_assignment" "team_members" {
role_definition_name = "Contributor"
principal_id = var.team_group_id
scope = azurerm_resource_group.workspace.id
}
57 changes: 57 additions & 0 deletions modules/workspace/_service-principals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SERVICE_PRINCIPALS
# ------------------

# SP - Workspace (scoped to resource group)

resource "azuread_application" "workspace_sp" {
name = "${local.name}-rg-sp"

depends_on = [
azurerm_resource_group.workspace
]
}

resource "azuread_application_password" "workspace_sp_secret" {
application_object_id = azuread_application.workspace_sp.object_id
value = random_password.workspace_sp.result
end_date_relative = "4380h" # 6 months
}

resource "azuread_service_principal" "workspace_sp" {
application_id = azuread_application.workspace_sp.application_id
}


# SP - Key Vault Reader (just for Azure Pipeline)

resource "azuread_application" "kv_reader_sp" {
name = "${local.name}-kv-reader-sp"
}

resource "azuread_application_password" "kv_reader_sp_secret" {
application_object_id = azuread_application.kv_reader_sp.object_id
value = random_password.kv_reader_sp.result
end_date_relative = "4380h" # 6 months
}

resource "azuread_service_principal" "kv_reader_sp" {
application_id = azuread_application.kv_reader_sp.application_id
}

# Random Passwords

resource "random_password" "workspace_sp" {
length = 30
special = true
min_numeric = 5
min_special = 2
override_special = "-_%@?"
}

resource "random_password" "kv_reader_sp" {
length = 30
special = true
min_numeric = 5
min_special = 2
override_special = "-_%@?"
}
15 changes: 0 additions & 15 deletions modules/workspace/random.tf

This file was deleted.

24 changes: 21 additions & 3 deletions modules/workspace/variables.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
data "azurerm_client_config" "current" {}

variable "name" {
type = string
description = "Base name of your workspace that will be used in resource names. Please use lowercase with dashes"
description = "Base name of your workspace that will be used in resource names. Please use lowercase with dashes."


validation {
condition = length(var.name) < 20
error_message = "Name must be less than 20 characters."
}
}

variable "location" {
Expand All @@ -11,6 +15,16 @@ variable "location" {
default = "westeurope"
}

variable "team_group_id" {
description = "AAD Group ID to receive 'Contributor' permissions"
type = string
}

variable "admin_group_id" {
description = "AAD Group ID to receive 'Owner' permissions"
type = string
}

variable "client_tenant_id" {
description = "AAD Tenant ID for Azure Resource Manager (ARM) client. Defaults to current session."
type = string
Expand All @@ -34,6 +48,10 @@ variable "tags" {
}
}

# Variables - Normalized

data "azurerm_client_config" "current" {}

locals {
name = lower(var.name)
name_squished = replace(local.name, "-", "")
Expand Down
15 changes: 13 additions & 2 deletions provider.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Provision Azure Resources (ARM)
provider "azurerm" {
version = "=2.26.0"
features {
Expand All @@ -7,7 +8,17 @@ provider "azurerm" {
}
}

# # Provision AAD Groups
provider "azuread" {
version = "=1.0.0"
}

# Store Terraform Stage in Azure Storage Account (see azure.conf.sample)
terraform {
backend "azurerm" {
}
# backend "azurerm" {
# }
}

# So we can give current user access to resources too
# b/c we are provisioning from local computer. Will need to change when using CI
data "azurerm_client_config" "current" {}

0 comments on commit 314f52c

Please sign in to comment.