Skip to content

Commit

Permalink
TES-359: Role assignments overhaul
Browse files Browse the repository at this point in the history
The overhaul focuses on simplifying the module dependencies
and responsibilities.

- Vault and backup modules no longer depend on an identity
- Added a new module rules dedicated for role assignments
  to anything required by the VMSS such as the key vault and
  backup storage account
- Moved custom roles to the new roles module
- Removed the storage account custom role in favor of directly
  providing the storage container in the user data script
- Removed useless empty BLOB creation in the storage account
- Optimized configurations role assignments for least privilege
- Updated some comments/descriptions
  • Loading branch information
mihailradkov committed Nov 29, 2023
1 parent 185d1f4 commit 4ba06d0
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
format: sarif
output: trivy.sarif

- name: Upload SARIF file
- name: Upload Trivy SARIF results
uses: github/codeql-action/upload-sarif@v2
timeout-minutes: 1
with:
Expand Down
56 changes: 33 additions & 23 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,35 @@ module "vault" {
tags = local.tags
}

# Creates a storage account for storing GraphDB backups
module "backup" {
source = "./modules/backup"

resource_name_prefix = var.resource_name_prefix
location = var.location
resource_group_name = azurerm_resource_group.graphdb.name

nacl_subnet_ids = [azurerm_subnet.graphdb-vmss.id]
nacl_ip_rules = var.management_cidr_blocks

storage_account_tier = var.storage_account_tier
storage_account_replication_type = var.storage_account_replication_type

tags = local.tags
}

# Creates and assigns required roles to the identity and services
module "roles" {
source = "./modules/roles"

resource_name_prefix = var.resource_name_prefix
resource_group_id = azurerm_resource_group.graphdb.id

identity_principal_id = module.identity.identity_principal_id
key_vault_id = module.vault.key_vault_id
backups_storage_container_id = module.backup.storage_account_id
}

# Managed GraphDB configurations in the Key Vault
module "configuration" {
source = "./modules/configuration"
Expand Down Expand Up @@ -189,7 +218,7 @@ module "tls" {
tags = local.tags

# Wait for role assignments
depends_on = [module.identity, module.vault]
depends_on = [module.vault]
}

# Creates a public application gateway for forwarding internet traffic to the GraphDB proxies
Expand Down Expand Up @@ -257,13 +286,11 @@ module "vm" {
resource_name_prefix = var.resource_name_prefix
location = var.location
resource_group_name = azurerm_resource_group.graphdb.name
resource_group_id = azurerm_resource_group.graphdb.id
zones = var.zones

graphdb_subnet_id = azurerm_subnet.graphdb-vmss.id

identity_id = module.identity.identity_id
identity_principal_id = module.identity.identity_principal_id
application_gateway_backend_address_pool_ids = [module.application_gateway.gateway_backend_address_pool_id]

# Configurations for the user data script
Expand All @@ -281,28 +308,11 @@ module "vm" {

custom_user_data = var.custom_graphdb_vm_user_data

backup_schedule = var.backup_schedule
backup_storage_container_url = module.backup.storage_container_id
backup_schedule = var.backup_schedule

tags = local.tags

# Wait for configurations to be created in the key vault and roles to be assigned
depends_on = [module.configuration]
}

# Creates a storage account for storing GraphDB backups
module "backup" {
source = "./modules/backup"

resource_name_prefix = var.resource_name_prefix
location = var.location
resource_group_name = azurerm_resource_group.graphdb.name

nacl_subnet_ids = [azurerm_subnet.graphdb-vmss.id]
nacl_ip_rules = var.management_cidr_blocks

identity_principal_id = module.identity.identity_principal_id
storage_account_tier = var.storage_account_tier
storage_account_replication_type = var.storage_account_replication_type

tags = local.tags
depends_on = [module.configuration, module.roles]
}
14 changes: 0 additions & 14 deletions modules/backup/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ resource "azurerm_storage_container" "graphdb-backup" {
container_access_type = "private"
}

# Create an Azure Storage blob
resource "azurerm_storage_blob" "graphdb-backup" {
name = "${var.resource_name_prefix}-backup"
type = "Block"
storage_account_name = azurerm_storage_account.graphdb-backup.name
storage_container_name = azurerm_storage_container.graphdb-backup.name
}

resource "azurerm_role_assignment" "graphdb-backup" {
principal_id = var.identity_principal_id
role_definition_name = "Storage Blob Data Contributor"
scope = azurerm_storage_account.graphdb-backup.id
}

resource "azurerm_storage_management_policy" "graphdb-backup-retention" {
storage_account_id = azurerm_storage_account.graphdb-backup.id

Expand Down
12 changes: 11 additions & 1 deletion modules/backup/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
output "storage_account_id" {
description = "Storage account identifier for storing GraphDB backups"
value = azurerm_storage_account.graphdb-backup.id
}

output "storage_account_name" {
description = "Storage account name for storing GraphDB backups"
value = azurerm_storage_account.graphdb-backup.name
}

output "container_name" {
output "storage_container_id" {
description = "Identifier of the storage container for GraphDB backups"
value = azurerm_storage_container.graphdb-backup.id
}

output "storage_container_name" {
description = "Name of the storage container for GraphDB backups"
value = azurerm_storage_container.graphdb-backup.name
}
7 changes: 0 additions & 7 deletions modules/backup/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ variable "nacl_ip_rules" {
default = []
}

# Identity

variable "identity_principal_id" {
description = "Principal identifier of a user assigned identity for assigning permissions"
type = string
}

# Storage specifics

variable "storage_account_tier" {
Expand Down
33 changes: 24 additions & 9 deletions modules/configuration/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,34 @@ resource "azurerm_key_vault_secret" "graphdb-java-options" {
tags = var.tags
}

# TODO: Cannot assign the secret resource as scope for some reason... it doesn't show in the console and it does not work in the VMs
# TODO: Not the right place for this to be here if we cannot give more granular access
resource "azurerm_role_assignment" "graphdb-license-secret-reader" {
principal_id = var.identity_principal_id
scope = azurerm_key_vault_secret.graphdb-license.resource_versionless_id
role_definition_name = "Key Vault Secrets User"
}

# Give rights to the provided identity to be able to read it from the vault
resource "azurerm_role_assignment" "graphdb-license-reader" {
resource "azurerm_role_assignment" "graphdb-cluster-token-secret-reader" {
principal_id = var.identity_principal_id
scope = var.key_vault_id
role_definition_name = "Key Vault Reader"
scope = azurerm_key_vault_secret.graphdb-cluster-token.resource_versionless_id
role_definition_name = "Key Vault Secrets User"
}

# Give rights to the provided identity to actually get the secret value
resource "azurerm_role_assignment" "graphdb-license-secret-reader" {
resource "azurerm_role_assignment" "graphdb-java-options-secret-reader" {
count = var.graphdb_java_options != null ? 1 : 0
principal_id = var.identity_principal_id
scope = azurerm_key_vault_secret.graphdb-java-options[0].resource_versionless_id
role_definition_name = "Key Vault Secrets User"
}

resource "azurerm_role_assignment" "graphdb-password-secret-reader" {
principal_id = var.identity_principal_id
scope = azurerm_key_vault_secret.graphdb-password.resource_versionless_id
role_definition_name = "Key Vault Secrets User"
}

resource "azurerm_role_assignment" "graphdb-properties-secret-reader" {
count = var.graphdb_properties_path != null ? 1 : 0
principal_id = var.identity_principal_id
scope = var.key_vault_id
scope = azurerm_key_vault_secret.graphdb-properties[0].resource_versionless_id
role_definition_name = "Key Vault Secrets User"
}
2 changes: 2 additions & 0 deletions modules/identity/variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# General configurations

variable "resource_name_prefix" {
description = "Resource name prefix used for tagging and naming Azure resources"
type = string
Expand Down
1 change: 1 addition & 0 deletions modules/roles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# GraphDB Roles Module
45 changes: 45 additions & 0 deletions modules/roles/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Assign the identity to have read access to the key vault
resource "azurerm_role_assignment" "graphdb-vmss-key-vault-reader" {
principal_id = var.identity_principal_id
scope = var.key_vault_id
role_definition_name = "Key Vault Reader"
}

# Assign the identity to be able to upload GraphDB backups in the storage BLOB
resource "azurerm_role_assignment" "graphdb-backup" {
principal_id = var.identity_principal_id
scope = var.backups_storage_container_id
role_definition_name = "Storage Blob Data Contributor"
}

resource "azurerm_role_definition" "managed_disk_manager" {
name = "${var.resource_name_prefix}-ManagedDiskManager"
scope = var.resource_group_id
description = "This is a custom role created via Terraform required for creating data disks for GraphDB"

permissions {
actions = [
"Microsoft.Compute/disks/read",
"Microsoft.Compute/disks/write",
"Microsoft.Compute/virtualMachineScaleSets/read",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/applicationGateways/backendAddressPools/join/action",
"Microsoft.Network/networkSecurityGroups/join/action"
]
not_actions = []
}

assignable_scopes = [
var.resource_group_id
]
}

resource "azurerm_role_assignment" "rg-contributor-role" {
principal_id = var.identity_principal_id
scope = var.resource_group_id
role_definition_name = azurerm_role_definition.managed_disk_manager.name

depends_on = [azurerm_role_definition.managed_disk_manager]
}
Empty file added modules/roles/output.tf
Empty file.
32 changes: 32 additions & 0 deletions modules/roles/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Common configurations

variable "resource_name_prefix" {
description = "Resource name prefix used for tagging and naming Azure resources"
type = string
}

variable "resource_group_id" {
description = "Identifier of the resource group where GraphDB will be deployed."
type = string
}

# Identity

variable "identity_principal_id" {
description = "Principal identifier of a user assigned identity for assigning permissions"
type = string
}

# Key Vault

variable "key_vault_id" {
description = "Identifier of a Key Vault for storing GraphDB configurations"
type = string
}

# Backups storage

variable "backups_storage_container_id" {
description = "Identifier of the storage container for GraphDB backups"
type = string
}
5 changes: 2 additions & 3 deletions modules/tls/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ resource "azurerm_user_assigned_identity" "graphdb-tls-certificate" {
tags = var.tags
}

# TODO: probably have to add Key Vault Reader as well

resource "azurerm_role_assignment" "graphdb-tls-certificate-reader" {
# Azure AG requires this role to the be assigned to the Key Vault directly
resource "azurerm_role_assignment" "graphdb-tls-key-vault-secrets-reader" {
principal_id = azurerm_user_assigned_identity.graphdb-tls-certificate.principal_id
scope = var.key_vault_id
role_definition_name = "Key Vault Secrets User"
Expand Down
60 changes: 1 addition & 59 deletions modules/vm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ locals {
disk_iops_read_write : var.disk_iops_read_write
disk_mbps_read_write : var.disk_mbps_read_write
disk_size_gb : var.disk_size_gb
backup_storage_container_url : var.backup_storage_container_url,
backup_schedule : var.backup_schedule
})
}
Expand Down Expand Up @@ -63,8 +64,6 @@ resource "azurerm_linux_virtual_machine_scale_set" "graphdb" {
}

tags = var.tags

depends_on = [azurerm_role_assignment.rg-contributor-role, azurerm_role_assignment.rg-reader-role]
}

resource "azurerm_monitor_autoscale_setting" "graphdb-autoscale-settings" {
Expand All @@ -86,60 +85,3 @@ resource "azurerm_monitor_autoscale_setting" "graphdb-autoscale-settings" {

tags = var.tags
}

resource "azurerm_role_definition" "managed_disk_manager" {
name = "${var.resource_name_prefix}-ManagedDiskManager"
scope = var.resource_group_id
description = "This is a custom role created via Terraform required for creating data disks for GraphDB"

permissions {
actions = [
"Microsoft.Compute/disks/read",
"Microsoft.Compute/disks/write",
"Microsoft.Compute/virtualMachineScaleSets/read",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/applicationGateways/backendAddressPools/join/action",
"Microsoft.Network/networkSecurityGroups/join/action"
]
not_actions = []
}

assignable_scopes = [
var.resource_group_id
]
}

resource "azurerm_role_assignment" "rg-contributor-role" {
principal_id = var.identity_principal_id
scope = var.resource_group_id
role_definition_name = "${var.resource_name_prefix}-ManagedDiskManager"
depends_on = [azurerm_role_definition.managed_disk_manager]
}

resource "azurerm_role_definition" "backup_role" {
name = "${var.resource_name_prefix}-ReadOnlyVMSSStorageRole"
scope = var.resource_group_id
description = "This is a custom role created via Terraform required for creating backups in GraphDB"

permissions {
actions = [
"Microsoft.Compute/virtualMachineScaleSets/read",
"Microsoft.Storage/storageAccounts/read"
]
not_actions = []
}

assignable_scopes = [
var.resource_group_id
]
}

resource "azurerm_role_assignment" "rg-reader-role" {
principal_id = var.identity_principal_id
scope = var.resource_group_id
role_definition_name = "${var.resource_name_prefix}-ReadOnlyVMSSStorageRole"
depends_on = [azurerm_role_definition.backup_role]
}

4 changes: 1 addition & 3 deletions modules/vm/templates/entrypoint.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,7 @@ fi
BACKUP_NAME="\$(date +'%Y-%m-%d_%H-%M-%S').tar"
TEMP_BACKUP_DIR="/var/opt/graphdb/"
STORAGE_ACCOUNT="\$(az storage account list --resource-group "\$RESOURCE_GROUP" --query "[].name" --output tsv)"
CONTAINER_NAME="\$(az storage container list --account-name "\$STORAGE_ACCOUNT" --query "[].name" --output tsv --auth-mode login)"
BLOB_URL="\$(az storage blob url --account-name "\$STORAGE_ACCOUNT" --container-name "\$CONTAINER_NAME" --name "\$BACKUP_NAME" --auth-mode login --output tsv)"
BLOB_URL="${backup_storage_container_url}/\$${BACKUP_NAME}"
function trigger_backup {
curl -X POST --output "\$${TEMP_BACKUP_DIR}\$${BACKUP_NAME}" -H 'Content-Type: application/json' 'http://localhost:7200/rest/recovery/backup'
Expand Down
Loading

0 comments on commit 4ba06d0

Please sign in to comment.