Skip to content

Commit

Permalink
Add support for Azure Org Onboarding using service-principal (#8)
Browse files Browse the repository at this point in the history
* Add support for Azure Org Onboarding using service-principal

Change summary:
----------------
- Supporting single vs org resources creation (using is_organizational)
- Role assignments for Root Mgmt Group at Tenant level
- Added README.md for the service-principal module
- Updated sysdig provider version

Pending:
---------
Add support for conditional creation of azuread sp resource

* Parameterize mgmt group with default and handle SP creation

* Fix resource naming and indexing

* Add org test and cleanup single subscription test

* Prevent unintended SP deletes
  • Loading branch information
ravinadhruve10 authored Nov 22, 2023
1 parent 8d60bed commit cad1e6c
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 13 deletions.
73 changes: 73 additions & 0 deletions modules/services/service-principal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Azure Service Prinicpal Module

This module will deploy a Service Principal in Azure for a single subscription, or for an Azure Tenant.

The following resources will be created:
- A Service Principal in your tenant, associated with the application ID of the service client in the Sysdig tenant.
- Role assignments with associated role permissions to grant Sysdig read only permissions to secure your Azure subscription, or Azure Tenant.

If instrumenting an Azure Tenant, the role assignments will be created at the Root Management Group level by default for the Tenant.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >= 3.76.0 |
| <a name="requirement_azuread"></a> [azuread](#requirement\_azuread) | >= 2.43.0 |
| <a name="requirement_sysdig"></a> [sysdig](#requirement\_sysdig) | >= 1.18.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >= 3.76.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [azuread_service_principal.sysdig_sp](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal) | resource |
| [azurerm_role_assignment.sysdig_reader](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.sysdig_k8s_reader](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.sysdig_vm_user](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.sysdig_reader_for_tenant](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.sysdig_k8s_reader_for_tenant](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.sysdig_vm_user_for_tenant](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_subscription.primary](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subscription) | data source |
| [azurerm_management_group.sysdig_management_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/management_group) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_subscription_id"></a> [subscription\_id](#input\_subscription\_id) | The identifier of the Azure Subscription in which to create a trust relationship | `string` | n/a | yes |
| <a name="input_sysdig_client_id"></a> [sysdig\_client\_id](#input\_sysdig\_client\_id) | The application ID of the service client in the Sysdig tenant. Service principal will be created for this application client ID | `string` | n/a | yes |
| <a name="input_is_organizational"></a> [is\_organizational](#input\_is\_organizational) | true/false whether secure-for-cloud should be deployed in an organizational setup (all subscriptions of tenant) or not (only on default azure provider subscription) | `bool` | `false` | no |
| <a name="input_management_group"></a> [management\_group](#input\_management\_group) | Display name of the Azure Management Group. secure-for-cloud will be deployed to all subscriptions under this management group | `string` | `"Tenant Root Group"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_service_principal_display_name"></a> [service\_principal\_display\_name](#output\_service\_principal\_display\_name) | Display name of the Service Principal created |
| <a name="output_service_principal_client_id"></a> [service\_principal\_client\_id](#output\_service\_principal\_client\_id) | Client ID of the Service Principal created |
| <a name="output_service_principal_id"></a> [service\_principal\_id](#output\_service\_principal\_id) | Service Principal ID on the customer tenant |
| <a name="output_service_principal_app_display_name"></a> [service\_principal\_app\_display\_name](#output\_service\_principal\_app\_display\_name) | Display name of the Application created |
| <a name="output_service_principal_app_owner_organization_id"></a> [service\_principal\_app\_owner\_organization\_id](#output\_service\_principal\_app\_owner\_organization\_id) | Organization ID of the Application created |
| <a name="output_subscription_tenant_id"></a> [subscription\_tenant\_id](#output\_subscription\_tenant\_id) | Tenant ID of the Subscription |
| <a name="output_subscription_alias"></a> [subscription\_alias](#output\_subscription\_alias) | Display name of the subscription |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## Authors

Module is maintained by [Sysdig](https://sysdig.com).

## License

Apache 2 Licensed. See LICENSE for full details.
20 changes: 19 additions & 1 deletion modules/services/service-principal/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,29 @@ data "azurerm_subscription" "primary" {

#---------------------------------------------------------------------------------------------
# Create service principal in customer tenant
#
# If there is an existing service principal in the tenant, this will automatically import
# and use it, ensuring we have just one service principal linked to the Sysdig application
# in the customer tenant.
# Note: Please refer to the caveats of use_existing attribute for this resource.
#
# Note: Once created, this cannot be deleted via Terraform. It can be manually deleted from Azure.
# This is to safeguard against unintended deletes if the service principal is in use.
#---------------------------------------------------------------------------------------------
resource "azuread_service_principal" "sysdig_sp" {
client_id = var.sysdig_client_id
client_id = var.sysdig_client_id
use_existing = true
lifecycle {
prevent_destroy = true
}
}

#---------------------------------------------------------------------------------------------
# Assign "Reader" role to Sysdig SP for primary subscription
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_reader" {
count = var.is_organizational ? 0 : 1

scope = data.azurerm_subscription.primary.id
role_definition_name = "Reader"
principal_id = azuread_service_principal.sysdig_sp.object_id
Expand All @@ -26,6 +40,8 @@ resource "azurerm_role_assignment" "sysdig_reader" {
# Assign "Azure Kubernetes Service Cluster User Role" role to Sysdig SP for primary subscription
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_k8s_reader" {
count = var.is_organizational ? 0 : 1

scope = data.azurerm_subscription.primary.id
role_definition_name = "Azure Kubernetes Service Cluster User Role"
principal_id = azuread_service_principal.sysdig_sp.object_id
Expand All @@ -35,6 +51,8 @@ resource "azurerm_role_assignment" "sysdig_k8s_reader" {
# Assign "Virtual Machine User Login" role to Sysdig SP for primary subscription
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_vm_user" {
count = var.is_organizational ? 0 : 1

scope = data.azurerm_subscription.primary.id
role_definition_name = "Virtual Machine User Login"
principal_id = azuread_service_principal.sysdig_sp.object_id
Expand Down
40 changes: 40 additions & 0 deletions modules/services/service-principal/organizational.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#---------------------------------------------------------------------------------------------
# Fetch the management group for customer tenant and onboard subscriptions under it
#---------------------------------------------------------------------------------------------
data "azurerm_management_group" "sysdig_management_group" {
count = var.is_organizational ? 1 : 0
display_name = var.management_group
}

#---------------------------------------------------------------------------------------------
# Assign "Reader" role to Sysdig SP for customer tenant
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_reader_for_tenant" {
count = var.is_organizational ? 1 : 0

scope = data.azurerm_management_group.sysdig_management_group[0].id
role_definition_name = "Reader"
principal_id = azuread_service_principal.sysdig_sp.object_id
}

#---------------------------------------------------------------------------------------------
# Assign "Azure Kubernetes Service Cluster User Role" role to Sysdig SP for customer tenant
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_k8s_reader_for_tenant" {
count = var.is_organizational ? 1 : 0

scope = data.azurerm_management_group.sysdig_management_group[0].id
role_definition_name = "Azure Kubernetes Service Cluster User Role"
principal_id = azuread_service_principal.sysdig_sp.object_id
}

#---------------------------------------------------------------------------------------------
# Assign "Virtual Machine User Login" role to Sysdig SP for customer tenant
#---------------------------------------------------------------------------------------------
resource "azurerm_role_assignment" "sysdig_vm_user_for_tenant" {
count = var.is_organizational ? 1 : 0

scope = data.azurerm_management_group.sysdig_management_group[0].id
role_definition_name = "Virtual Machine User Login"
principal_id = azuread_service_principal.sysdig_sp.object_id
}
15 changes: 14 additions & 1 deletion modules/services/service-principal/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ variable "subscription_id" {
variable "sysdig_client_id" {
type = string
description = "Service client ID in the Sysdig tenant"
}
}

variable "is_organizational" {
description = "(Optional) Set this field to 'true' to deploy secure-for-cloud to an Azure Tenant."
type = bool
default = false
}

# By default, this will be the root management group whose default display name is "Tenant root group"
variable "management_group" {
description = "(Optional) Display name of the Azure Management Group. secure-for-cloud will be deployed to all the subscriptions under this management group."
type = string
default = "Tenant Root Group"
}
2 changes: 1 addition & 1 deletion modules/services/service-principal/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ terraform {
}
sysdig = {
source = "sysdiglabs/sysdig"
version = ">= 1.15.0"
version = ">= 1.18.0"
}
}
}
77 changes: 77 additions & 0 deletions test/organization/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
provider "azurerm" {
features {}
}
terraform {
required_providers {
sysdig = {
source = "local/sysdiglabs/sysdig"
version = "~> 1.0.0"
}
}
}

provider "sysdig" {
sysdig_secure_url = "https://secure-staging.sysdig.com"
sysdig_secure_api_token = "<client_secret>"
}

module "organization-posture" {
source = "../modules/services/service-principal"
subscription_id = "test-azure-provider"
sysdig_client_id = "<sysdig_application_client_id>"
is_organizational = true
}

resource "sysdig_secure_cloud_auth_account" "azure_subscription_test" {
enabled = true
provider_id = "test-azure-provider"
provider_type = "PROVIDER_AZURE"
provider_tenant_id = module.organization-posture.subscription_tenant_id
provider_alias = module.organization-posture.subscription_alias

feature {

secure_config_posture {
enabled = true
components = ["COMPONENT_SERVICE_PRINCIPAL/secure-posture"]
}
}
component {
type = "COMPONENT_SERVICE_PRINCIPAL"
instance = "secure-posture"
service_principal_metadata = jsonencode({
azure = {
active_directory_service_principal = {
account_enabled = true
display_name = module.organization-posture.service_principal_display_name
id = module.organization-posture.service_principal_id
app_display_name = module.organization-posture.service_principal_app_display_name
app_id = module.organization-posture.service_principal_client_id
app_owner_organization_id = module.organization-posture.service_principal_app_owner_organization_id
}
}
})
}
component {
type = "COMPONENT_SERVICE_PRINCIPAL"
instance = "secure-onboarding"
service_principal_metadata = jsonencode({
azure = {
active_directory_service_principal = {
account_enabled = true
display_name = module.organization-posture.service_principal_display_name
id = module.organization-posture.service_principal_id
app_display_name = module.organization-posture.service_principal_app_display_name
app_id = module.organization-posture.service_principal_client_id
app_owner_organization_id = module.organization-posture.service_principal_app_owner_organization_id
}
}
})
}
depends_on = [module.organization-posture]
}

resource "sysdig_secure_organization" "azure_organization_test" {
management_account_id = sysdig_secure_cloud_auth_account.azure_subscription_test.id
depends_on = [module.organization-posture]
}
21 changes: 11 additions & 10 deletions test/main.tf → test/single_subscription/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ provider "sysdig" {
sysdig_secure_api_token = "<client_secret>"
}

module "project-posture" {
module "subscription-posture" {
source = "../modules/services/service-principal"
subscription_id = "db4d1aaa-4d7f-47d8-b0fe-445d0d70ffce"
sysdig_client_id = "a39a3795-c3d7-4c8b-9c1a-24ea5011be8a"
subscription_id = "test-azure-provider"
sysdig_client_id = "<sysdig_application_client_id>"
}


resource "sysdig_secure_cloud_auth_account" "azure_subscription_test" {
enabled = true
provider_id = "test-azure-provider"
provider_type = "PROVIDER_AZURE"
provider_tenant_id = module.project-posture.subscription_tenant_id
provider_alias = module.project-posture.subscription_alias
provider_tenant_id = module.subscription-posture.subscription_tenant_id
provider_alias = module.subscription-posture.subscription_alias

feature {

Expand All @@ -43,13 +43,14 @@ resource "sysdig_secure_cloud_auth_account" "azure_subscription_test" {
azure = {
active_directory_service_principal = {
account_enabled = true
display_name = module.project-posture.service_principal_display_name
id = module.project-posture.service_principal_id
app_display_name = module.project-posture.service_principal_app_display_name
app_id = module.project-posture.service_principal_client_id
app_owner_organization_id = module.project-posture.service_principal_app_owner_organization_id
display_name = module.subscription-posture.service_principal_display_name
id = module.subscription-posture.service_principal_id
app_display_name = module.subscription-posture.service_principal_app_display_name
app_id = module.subscription-posture.service_principal_client_id
app_owner_organization_id = module.subscription-posture.service_principal_app_owner_organization_id
}
}
})
}
depends_on = [module.subscription-posture]
}

0 comments on commit cad1e6c

Please sign in to comment.