Skip to content

Commit d133450

Browse files
authored
DTOSS-9226: Create Permissions for Foundry Function App (#183)
* DTOSS-9226: Create Permissions for Foundry Function App * Adding in an example to the module
1 parent 093557a commit d133450

File tree

8 files changed

+245
-0
lines changed

8 files changed

+245
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# service-bus
2+
3+
## Terraform documentation
4+
For the list of inputs, outputs, resources... check the [terraform module documentation](tfdocs.md).
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
regions = {
2+
uksouth = {
3+
is_primary_region = true
4+
address_space = "10.113.0.0/16"
5+
connect_peering = false
6+
subnets = {}
7+
}
8+
}
9+
10+
service_bus_subscriptions = {
11+
subscriber_config = {
12+
event-dev-ap = {
13+
subscription_name = "events-sub"
14+
topic_name = "events"
15+
namespace_name = "dtoss-nsp"
16+
subscriber_functionName = "foundryRelay"
17+
}
18+
}
19+
}
20+
21+
service_bus = {
22+
dtoss-nsp = {
23+
capacity = 1
24+
sku_tier = "Premium"
25+
max_payload_size = "100mb"
26+
topics = {
27+
events = {}
28+
}
29+
}
30+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module "service_bus_subscription" {
2+
for_each = local.service_bus_subscriptions_map
3+
4+
source = "../../../../../dtos-devops-templates/infrastructure/modules/service-bus-subscription"
5+
6+
subscription_name = each.value.service_bus_subscription_key
7+
max_delivery_count = 10
8+
topic_id = values(module.azure_service_bus["${each.value.namespace_name}-${each.value.region}"].topic_ids)[0]
9+
namespace_name = "${each.value.namespace_name}-${each.value.region}"
10+
service_bus_namespace_id = module.azure_service_bus["${each.value.namespace_name}-${each.value.region}"].namespace_id
11+
function_app_principal_id = module.functionapp["${each.value.subscriber_functionName}-${each.value.region}"].function_app_sami_id
12+
13+
}
14+
15+
locals {
16+
17+
service_bus_subscriptions_object_list = flatten([
18+
for region in keys(var.regions) : [
19+
for service_bus_subscription_key, service_bus_subscription_details in var.service_bus_subscriptions.subscriber_config : merge(
20+
{
21+
region = region # 1st iterator
22+
service_bus_subscription_key = service_bus_subscription_key # 2nd iterator
23+
},
24+
service_bus_subscription_details # the rest of the key/value pairs for a specific service_bus
25+
)
26+
]
27+
])
28+
29+
# ...then project the list of objects into a map with unique keys (combining the iterators), for consumption by a for_each meta argument
30+
service_bus_subscriptions_map = {
31+
for object in local.service_bus_subscriptions_object_list : "${object.service_bus_subscription_key}-${object.region}" => object
32+
}
33+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
variable "service_bus_subscriptions" {
2+
description = "Configuration for event grid subscriptions"
3+
type = object({
4+
subscriber_config = map(object({
5+
subscription_name = string
6+
namespace_name = optional(string)
7+
topic_name = string
8+
subscriber_functionName = string
9+
}))
10+
})
11+
}
12+
13+
variable "regions" {
14+
type = map(object({
15+
address_space = optional(string)
16+
is_primary_region = bool
17+
connect_peering = optional(bool, false)
18+
subnets = optional(map(object({
19+
cidr_newbits = string
20+
cidr_offset = string
21+
create_nsg = optional(bool, true) # defaults to true
22+
name = optional(string) # Optional name override
23+
delegation_name = optional(string)
24+
service_delegation_name = optional(string)
25+
service_delegation_actions = optional(list(string))
26+
})))
27+
}))
28+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "azurerm_servicebus_subscription" "this" {
2+
name = var.subscription_name
3+
topic_id = var.topic_id
4+
max_delivery_count = var.max_delivery_count
5+
lock_duration = "PT5M" # ISO 8601 duration
6+
7+
}
8+
9+
resource "azurerm_role_assignment" "sb_role" {
10+
scope = var.service_bus_namespace_id
11+
role_definition_name = "Azure Service Bus Data Receiver" # or "Azure Service Bus Data Owner" if you want full control
12+
principal_id = var.function_app_principal_id
13+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Module documentation
2+
3+
## Required Inputs
4+
5+
The following input variables are required:
6+
7+
### <a name="input_function_app_principal_id"></a> [function\_app\_principal\_id](#input\_function\_app\_principal\_id)
8+
9+
Description: The principal ID (object ID) of the Function App's managed identity.
10+
11+
Type: `string`
12+
13+
### <a name="input_namespace_name"></a> [namespace\_name](#input\_namespace\_name)
14+
15+
Description: The name of the Service Bus namespace.
16+
17+
Type: `string`
18+
19+
### <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name)
20+
21+
Description: The name of the resource group containing the Service Bus namespace.
22+
23+
Type: `string`
24+
25+
### <a name="input_service_bus_namespace_id"></a> [service\_bus\_namespace\_id](#input\_service\_bus\_namespace\_id)
26+
27+
Description: The ID of the Service Bus namespace resource for role assignment scope.
28+
29+
Type: `string`
30+
31+
### <a name="input_subscription_name"></a> [subscription\_name](#input\_subscription\_name)
32+
33+
Description: The name of the Service Bus subscription.
34+
35+
Type: `string`
36+
37+
### <a name="input_topic_name"></a> [topic\_name](#input\_topic\_name)
38+
39+
Description: The name of the Service Bus topic.
40+
41+
Type: `string`
42+
43+
## Optional Inputs
44+
45+
The following input variables are optional (have default values):
46+
47+
### <a name="input_max_delivery_count"></a> [max\_delivery\_count](#input\_max\_delivery\_count)
48+
49+
Description: The maximum delivery count of a message before it is dead-lettered.
50+
51+
Type: `number`
52+
53+
Default: `10`
54+
55+
### <a name="input_tags"></a> [tags](#input\_tags)
56+
57+
Description: A map of tags to assign to the subscription.
58+
59+
Type: `map(string)`
60+
61+
Default: `{}`
62+
63+
64+
## Resources
65+
66+
The following resources are used by this module:
67+
68+
- [azurerm_role_assignment.sb_role](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource)
69+
- [azurerm_servicebus_subscription.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/servicebus_subscription) (resource)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
variable "subscription_name" {
2+
description = "The name of the Service Bus subscription."
3+
type = string
4+
5+
validation {
6+
condition = length(var.subscription_name) > 0 && length(var.subscription_name) <= 50
7+
error_message = "subscription_name must be between 1 and 50 characters."
8+
}
9+
}
10+
11+
variable "topic_id" {
12+
description = "The name of the Service Bus topic."
13+
type = string
14+
15+
# validation {
16+
# condition = length(var.topic_name) > 0 && length(var.topic_name) <= 50
17+
# error_message = "topic_name must be between 1 and 50 characters."
18+
# }
19+
}
20+
21+
variable "namespace_name" {
22+
description = "The name of the Service Bus namespace."
23+
type = string
24+
25+
validation {
26+
condition = length(var.namespace_name) > 0 && length(var.namespace_name) <= 50
27+
error_message = "namespace_name must be between 1 and 50 characters."
28+
}
29+
}
30+
31+
variable "max_delivery_count" {
32+
description = "The maximum delivery count of a message before it is dead-lettered."
33+
type = number
34+
default = 10
35+
36+
validation {
37+
condition = var.max_delivery_count > 0 && var.max_delivery_count <= 100
38+
error_message = "max_delivery_count must be between 1 and 100."
39+
}
40+
}
41+
42+
variable "service_bus_namespace_id" {
43+
description = "The ID of the Service Bus namespace resource for role assignment scope."
44+
type = string
45+
46+
validation {
47+
condition = can(regex("^/subscriptions/.+/resourceGroups/.+/providers/Microsoft.ServiceBus/namespaces/.+$", var.service_bus_namespace_id))
48+
error_message = "service_bus_namespace_id must be a valid Azure Service Bus namespace resource ID."
49+
}
50+
}
51+
52+
variable "function_app_principal_id" {
53+
description = "The principal ID (object ID) of the Function App's managed identity."
54+
type = string
55+
56+
validation {
57+
condition = length(var.function_app_principal_id) == 36 || length(var.function_app_principal_id) == 32
58+
error_message = "function_app_principal_id should be a valid GUID string."
59+
}
60+
}

infrastructure/modules/service-bus/output.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ output "servicebus_connection_string" {
66
output "namespace_id" {
77
value = azurerm_servicebus_namespace.this.id
88
}
9+
10+
output "namespace_name" {
11+
value = azurerm_servicebus_namespace.this.name
12+
}
13+
14+
output "topic_ids" {
15+
value = { for k, topic in azurerm_servicebus_topic.this : k => topic.id }
16+
}

0 commit comments

Comments
 (0)