Skip to content

Commit 505ddb7

Browse files
author
radomarina
committed
feat: 1.4.0
1 parent db00e3e commit 505ddb7

File tree

13 files changed

+569
-0
lines changed

13 files changed

+569
-0
lines changed

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ Choose one of the following installation options based on your needs:
5555
### Option 1: Discovered Subscriptions
5656

5757
Use this option if you want Firefly to automatically discover and monitor all accessible Azure subscriptions.
58+
We use delegated AD service principal to discover and monitor all accessible Azure subscriptions.
59+
Go to Option 3 if you want to use non delegated AD service principal.
5860

5961
You can exclude subscriptions by adding a tag on them.
6062

@@ -142,6 +144,49 @@ module "firefly_azure_subscription_2" {
142144
}
143145
```
144146

147+
### Option 3: Non delegated AD service principal
148+
149+
```hcl
150+
provider "azuread" {
151+
client_id = var.client_id
152+
client_secret = var.client_secret
153+
tenant_id = var.tenant_id
154+
}
155+
156+
provider "azurerm" {
157+
features {}
158+
alias = "deployment_subscription"
159+
tenant_id = var.tenant_id
160+
subscription_id = var.subscription_id
161+
resource_provider_registrations = "none"
162+
}
163+
164+
module "firefly_azure" {
165+
source = "github.com/gofireflyio/terraform-firefly-azure-onboarding?ref=v1.3.0/modules/single_integration"
166+
providers = {
167+
azurerm.deployment_subscription = azurerm.deployment_subscription
168+
}
169+
170+
client_id = var.client_id
171+
client_secret = var.client_secret
172+
directory_domain = "your-organization.com"
173+
tenant_id = var.tenant_id
174+
subscription_id = var.subscription_id
175+
176+
firefly_access_key = var.firefly_access_key
177+
firefly_secret_key = var.firefly_secret_key
178+
179+
location = var.location
180+
prefix = var.prefix
181+
tags = var.tags
182+
// existing_app_id = "00000000-0000-0000-0000-000000000000"
183+
// existing_service_principal_id = "00000000-0000-0000-0000-000000000000"
184+
185+
186+
create_resource_provider_registration = false
187+
}
188+
```
189+
145190
## Required Resources
146191

147192
The Terraform module will create the following Azure resources:

modules/single_integration/data.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
data "azuread_client_config" "current" {}
2+
3+
data "azuread_application_published_app_ids" "well_known" {}
4+
5+
resource "azuread_service_principal" "msgraph" {
6+
client_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
7+
use_existing = true
8+
}
9+
10+
data "azuread_service_principal" "existing" {
11+
count = var.existing_service_principal_id != "" ? 1 : 0
12+
application_id = var.existing_service_principal_id
13+
}
14+
15+
resource "azurerm_resource_provider_registration" "current" {
16+
count = var.create_resource_provider_registration ? 1 : 0
17+
name = "microsoft.insights"
18+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
resource "azurerm_resource_group" "current" {
2+
count = var.existing_resource_group_name == "" ? 1 : 0
3+
provider = azurerm.deployment_subscription
4+
location = var.location
5+
name = "${module.naming.resource_group.name}-${var.prefix}firefly${var.suffix}"
6+
tags = local.tags
7+
}
8+
9+
resource "azurerm_storage_account" "current" {
10+
count = var.existing_storage_account_id == "" ? 1 : 0
11+
provider = azurerm.deployment_subscription
12+
account_replication_type = "LRS"
13+
cross_tenant_replication_enabled = false
14+
account_tier = "Standard"
15+
location = var.location
16+
name = "${module.naming.storage_account.name}${var.prefix != "" ? regex("\\w+", var.prefix) : ""}firefly${var.suffix != "" ? regex("\\w+", var.suffix) : ""}"
17+
resource_group_name = local.resource_group_name
18+
tags = local.tags
19+
dynamic "network_rules" {
20+
for_each = var.enforce_storage_network_rules ? [1] : []
21+
content {
22+
default_action = "Deny"
23+
ip_rules = var.firefly_eips
24+
}
25+
}
26+
}
27+
28+
resource "azurerm_eventgrid_system_topic" "current" {
29+
count = var.existing_eventgrid_topic_name == "" ? 1 : 0
30+
provider = azurerm.deployment_subscription
31+
name = "${module.naming.eventgrid_topic.name}-${var.prefix}firefly${var.suffix}"
32+
location = var.location
33+
resource_group_name = local.resource_group_name
34+
source_arm_resource_id = local.storage_account_id
35+
topic_type = "microsoft.storage.storageaccounts"
36+
tags = local.tags
37+
}
38+
39+
resource "azurerm_eventgrid_system_topic_event_subscription" "current" {
40+
count = var.existing_eventgrid_topic_name == "" ? 1 : 0
41+
provider = azurerm.deployment_subscription
42+
name = "${module.naming.eventgrid_event_subscription.name}-${var.prefix}firefly${var.suffix}"
43+
resource_group_name = local.resource_group_name
44+
system_topic = local.eventgrid_system_topic_name
45+
included_event_types = ["Microsoft.Storage.BlobCreated"]
46+
47+
webhook_endpoint {
48+
url = var.firefly_webhook_url
49+
max_events_per_batch = 1
50+
preferred_batch_size_in_kilobytes = 64
51+
}
52+
retry_policy {
53+
event_time_to_live = 1440
54+
max_delivery_attempts = 30
55+
}
56+
}
57+
58+
resource "azurerm_role_definition" "FireflyStorageAccountBlobReader" {
59+
provider = azurerm.deployment_subscription
60+
61+
name = "${module.naming.role_definition.name}-${var.prefix}FireflyStorageAccountBlobReader-${var.subscription_id}${var.suffix}"
62+
scope = "/subscriptions/${var.subscription_id}"
63+
description = "Firefly's requested permissions"
64+
65+
permissions {
66+
data_actions = [
67+
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"
68+
]
69+
}
70+
assignable_scopes = [
71+
"/subscriptions/${var.subscription_id}"
72+
]
73+
}
74+
75+
resource "azurerm_role_assignment" "FireflyStorageAccountBlobReader" {
76+
provider = azurerm.deployment_subscription
77+
78+
principal_id = local.service_principle_object_id
79+
role_definition_name = azurerm_role_definition.FireflyStorageAccountBlobReader.name
80+
scope = "/subscriptions/${var.subscription_id}"
81+
condition_version = "2.0"
82+
condition = <<-EOT
83+
(
84+
(
85+
!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'} AND NOT
86+
SubOperationMatches{'Blob.List'})
87+
)
88+
OR
89+
(
90+
@Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs:path] StringLike '*state'
91+
)
92+
OR
93+
(
94+
@Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs:path] StringLike '*.tfstateenv:*'
95+
)
96+
)
97+
EOT
98+
}
99+
100+
resource "azurerm_monitor_diagnostic_setting" "current" {
101+
provider = azurerm.deployment_subscription
102+
name = "${module.naming.monitor_diagnostic_setting.name}-${var.prefix}firefly${var.subscription_id}${var.suffix}"
103+
target_resource_id = "/subscriptions/${var.subscription_id}"
104+
storage_account_id = local.storage_account_id
105+
enabled_log {
106+
category = "Administrative"
107+
}
108+
depends_on = [local.storage_account_id]
109+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
data "http" "firefly_login" {
2+
count = var.firefly_secret_key != "" ? 1 : 0
3+
url = "${var.firefly_endpoint}/account/access_keys/login"
4+
method = "POST"
5+
request_headers = {
6+
Content-Type = "application/json"
7+
}
8+
request_body = jsonencode({ "accessKey" = var.firefly_access_key, "secretKey" = var.firefly_secret_key })
9+
}
10+
11+
locals {
12+
response_obj = try(jsondecode(data.http.firefly_login[0].response_body), {})
13+
token = lookup(local.response_obj, "access_token", "error")
14+
}
15+
16+
module "firefly_integrate" {
17+
count = var.trigger_integrations ? 1 : 0
18+
firefly_endpoint = var.firefly_endpoint
19+
source = "./modules/firefly_azure_integration"
20+
firefly_token = local.token
21+
subscription_id = var.subscription_id
22+
subscription_name = var.subscription_name
23+
tenant_id = var.tenant_id
24+
application_id = local.service_principle_client_id
25+
client_secret = azuread_service_principal_password.current.value
26+
directory_domain = var.directory_domain
27+
auto_discover_enabled = false
28+
is_prod = var.is_prod
29+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
locals {
2+
resource_group_name = var.existing_resource_group_name != "" ? var.existing_resource_group_name : azurerm_resource_group.current[0].name
3+
storage_account_id = var.existing_storage_account_id != "" ? var.existing_storage_account_id : azurerm_storage_account.current[0].id
4+
app_id = var.existing_app_id != "" ? var.existing_app_id : azuread_application_registration.current[0].id
5+
service_principle_client_id = var.existing_service_principal_id != "" ? var.existing_service_principal_id : azuread_service_principal.current[0].client_id
6+
service_principle_object_id = var.existing_service_principal_id != "" ? data.azuread_service_principal.existing[0].object_id : azuread_service_principal.current[0].object_id
7+
eventgrid_system_topic_name = azurerm_eventgrid_system_topic.current[0].name
8+
tags = merge(var.tags, {
9+
"firefly" = "true"
10+
})
11+
}
12+
13+
module "naming" {
14+
source = "Azure/naming/azurerm"
15+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
locals {
2+
version = "0.1.0"
3+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
data "http" "firefly_azure_integration_request" {
2+
url = "${var.firefly_endpoint}/integrations/azure/"
3+
method = "POST"
4+
request_headers = {
5+
Content-Type = "application/json"
6+
Authorization = "Bearer ${var.firefly_token}"
7+
}
8+
retry {
9+
attempts = 3
10+
max_delay_ms = 5000
11+
min_delay_ms = 5000
12+
}
13+
request_body = jsonencode(
14+
{
15+
"name" = var.subscription_name,
16+
"subscriptionId" = var.subscription_id,
17+
"tenantId" = var.tenant_id,
18+
"applicationId" = var.application_id,
19+
"clientSecret" = var.client_secret,
20+
"directoryDomain" = var.directory_domain,
21+
"isProd" = var.is_prod,
22+
"isEventDriven" = var.eventdriven_enabled,
23+
"isIacAutoDiscoveryDisabled" = var.iac_auto_discovery_disabled
24+
"isAutoDiscover" = var.auto_discover_enabled
25+
}
26+
)
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
terraform {
2+
required_providers {
3+
http = {
4+
source = "hashicorp/http"
5+
version = "3.4.2"
6+
}
7+
}
8+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
variable "subscription_name" {
2+
type = string
3+
description = "subscription_name"
4+
}
5+
6+
variable "firefly_token" {
7+
type = string
8+
description = "Token returned as result of login request, if provided firefly_access_key and firefly_secret_key are ignored"
9+
}
10+
11+
variable "subscription_id" {
12+
type = string
13+
description = "subscription id"
14+
}
15+
16+
17+
variable "firefly_endpoint" {
18+
type = string
19+
description = "The Firefly endpoint to register account management"
20+
default = "https://prodapi.gofirefly.io/api"
21+
}
22+
23+
variable "is_prod" {
24+
type = bool
25+
default = false
26+
description = "Is Production?"
27+
}
28+
29+
variable "tenant_id" {
30+
type = string
31+
}
32+
33+
variable "application_id" {
34+
type = string
35+
}
36+
37+
variable "client_secret" {
38+
type = string
39+
}
40+
41+
variable "directory_domain" {
42+
type = string
43+
}
44+
45+
variable "eventdriven_enabled" {
46+
type = bool
47+
default = true
48+
}
49+
50+
variable "auto_discover_enabled" {
51+
type = bool
52+
default = true
53+
}
54+
55+
variable "iac_auto_discovery_disabled" {
56+
type = bool
57+
default = false
58+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
output "firefly_service_principal_id" {
2+
value = local.service_principle_client_id
3+
}
4+
5+
output "firefly_service_principal_password" {
6+
value = azuread_service_principal_password.current.value
7+
sensitive = true
8+
}
9+
10+
11+
output "firefly_tenant_id" {
12+
value = var.tenant_id
13+
}
14+
15+
output "firefly_subscription_id" {
16+
value = var.subscription_id
17+
}
18+
19+
output "firefly_resource_group_name" {
20+
value = local.resource_group_name
21+
}
22+
23+
output "firefly_storage_account_id" {
24+
value = local.storage_account_id
25+
}
26+
27+
output "firefly_eventgrid_system_topic_name" {
28+
value = local.eventgrid_system_topic_name
29+
}
30+
31+
output "firefly_eips" {
32+
value = var.firefly_eips
33+
}

0 commit comments

Comments
 (0)