I’m trying to create list of Azure AD Groups along with Role using Terraform
I have followed approach in such a way it would first create the required AD groups and then later it will assign the Role
# Required Provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}
required_version = ">= 1.1.0"
}
# Configure the Microsoft Azure Provider
provider "azurerm" {
features {}
....
....
}
data "azuread_client_config" "current" {}
# Variables
variable "ad_groups" {
description = "Azure AD groups to be added"
type = list(object({
display_name = string,
description = string,
scope = string,
role = string
}))
default = [
{
display_name = "Group1"
description = "some description",
scope = "/providers/Microsoft.Management/managementGroups/xxxxx",
role = "Owner"
},
{
display_name = "Group2"
description = "some description",
scope = "/providers/Microsoft.Management/managementGroups/xxxxx",
role = "Contributor"
}
]
}
# Create AD Groups and add the Current User
resource "azuread_group" "this"{
count = length(var.ad_groups)
display_name = var.ad_groups[count.index].display_name
description = var.ad_groups[count.index].description
security_enabled = true
# prevent_duplicate_names = true
owners = [data.azuread_client_config.current.object_id]
}
# Assign Permission to the AD Group
resource "azurerm_role_assignment" "sp-tenant-global-admin-user-access-role-assignment" {
count = length(var.ad_groups)
scope = var.ad_groups[count.index].scope
role_definition_name = var.ad_groups[count.index].role
principal_id = azuread_group.this[count.index].object_id
depends_on = [
azuread_group.this
]
}
does it look good and would it work? I don't have access to run the above code to validate.
I tried to reproduce the same in my environment.
variable "ad_groups" {
description = "Azure AD groups to be added"
type = list(object({
display_name = string,
description = string,
scope = string,
role = string
}))
default = [
{
display_name = "Group2"
description = "some description",
scope = "/providers/Microsoft.Management/managementGroups/xxxxx",
role = "Reader"
}
]
}
# Create AD Groups and add the Current User
resource "azuread_group" "this"{
count = length(var.ad_groups)
display_name = var.ad_groups[count.index].display_name
description = var.ad_groups[count.index].description
security_enabled = true
owners = [data.azuread_client_config.current.object_id]
}
# Assign Permission to the AD Group
resource "azurerm_role_assignment" "sp-tenant-global-admin-user-access-role-assignment" {
count = length(var.ad_groups)
scope = var.ad_groups[count.index].scope
role_definition_name = var.ad_groups[count.index].role
principal_id = azuread_group.this[count.index].object_id
depends_on = [
azuread_group.this
]
}
I have received error like:
As I donot have role over the scope of the subscription, as the
/providers/Microsoft.Management/managementGroups/xxxx need
privilege to assign role over the subscription scope.
But as you are using azurerm provider to create a role to group via
terraform , I tried the following code with a resource group scope
as I checked it is enough for my groups
Code:
Variables.tf
variable "ad_groups" {
description = "Azure AD groups to be added"
type = list(object({
display_name = string,
description = string,
scope = string,
role = string
}))
default = [
{
display_name = "Group2"
description = "some description",
scope = "/subscriptions/xxxxx/resourcegroups/myrg" #resource group scope
role = "Reader"
}
]
}
Main.tf:
resource "azuread_user" "example" {
display_name = "kavyaJDoe"
password = "notSecure123"
user_principal_name = "xxx.onmicrosoft.com"
}
resource "azuread_group" "example" {
display_name = "kavyaMyGroup"
owners = [data.azuread_client_config.current.object_id]
security_enabled = true
members = [
azuread_user.example.object_id,
# more users
]
}
resource "azuread_group" "this"{
count = length(var.ad_groups)
display_name = var.ad_groups[count.index].display_name
description = var.ad_groups[count.index].description
security_enabled = true
# prevent_duplicate_names = true
owners = [data.azuread_client_config.current.object_id]
}
resource "azurerm_role_assignment" "sp-tenant-global-admin-user-access-role-assignment" {
count = length(var.ad_groups)
scope ="/subscriptions/xxx/resourcegroups/myrg"
role_definition_name = var.ad_groups[count.index].role
principal_id = azuread_group.this[count.index].object_id
depends_on = [
azuread_group.this
]
}
Optional :if role is required to be assigned in order to provide roles to others:
resource "azurerm_role_definition" "role_assignment_write_delete" {
name = "RBAC Owner"
scope = data.azurerm_client_config.current.subscription_id
description = "Management of role assignments"
permissions {
actions = [
"Microsoft.Authorization/roleAssignments/write",
"Microsoft.Authorization/roleAssignments/delete",
]
not_actions = []
}
assignable_scopes = [
data.azurerm_client_config.current.subscription_id //or management group
]
}
I could create the role assignment successfully:
Can see the role created for the group2 that got initiated through variables:
Reference:
Understand scope for Azure RBAC | Microsoft Learn
Related
I'm Creating the App Registration, App Registration Secrets, API Permissions, and Role Assignment via Terraform. I'm Able to allocate the MicroSoft Graph API Permissions and able to Grant Permissions. For Log Analytic API Permission Grant, I'm Getting Error on the Terraform code.
data "azuread_client_config" "current" {}
data "azuread_application_published_app_ids" "well_known" {}
resource "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
use_existing = true
owners = [data.azuread_client_config.current.object_id]
}
data "azuread_application_published_app_ids" "log" {}
resource "azuread_service_principal" "LogAnalyticsApi" {
application_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI
use_existing = true
owners = [data.azuread_client_config.current.object_id]
}
# Retrieve domain information
data "azuread_domains" "domain" {
only_initial = true
}
# Create an application
resource "azuread_application" "appreg" {
display_name = "Demo_App_Registration_Portal"
owners = [data.azuread_client_config.current.object_id]
sign_in_audience = "AzureADMultipleOrgs"
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["Directory.Read.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["Domain.Read.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["Domain.ReadWrite.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["User.Read"]
type = "Scope"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["Domain.ReadWrite.All"]
type = "Scope"
}
#####
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["UserAuthenticationMethod.Read.All"]
type = "Role"
}
#####
}
#Log Analytic API Data Read Access
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI
resource_access {
id = azuread_service_principal.LogAnalyticsAPI.app_role_ids["Data.Read"]
type = "Role"
}
}
}
#Creating Client Password for the Application
resource "azuread_application_password" "appregpassword" {
display_name = "Demo_App_Registration_Portal_Password"
application_object_id = azuread_application.appreg.object_id
depends_on = [
azuread_application.appreg
]
}
output "azuread_application_password" {
value = azuread_application_password.appregpassword.id
}
# Create a service principal
resource "azuread_service_principal" "appregsp" {
application_id = azuread_application.appreg.application_id
app_role_assignment_required = true
owners = [data.azuread_client_config.current.object_id]
}
resource "azuread_app_role_assignment" "example" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
resource "azuread_app_role_assignment" "Directory" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["Directory.Read.All"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
resource "azuread_app_role_assignment" "Domain-Read" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["Domain.Read.All"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
resource "azuread_app_role_assignment" "Domain-Read-Write" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["Domain.ReadWrite.All"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
####
resource "azuread_app_role_assignment" "UserAuthenticationMethod-Read-All" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["UserAuthenticationMethod.Read.All"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
####
resource "azuread_service_principal_delegated_permission_grant" "example" {
service_principal_object_id = azuread_service_principal.appregsp.object_id
resource_service_principal_object_id = azuread_service_principal.msgraph.object_id
claim_values = ["User.Read", "Domain.ReadWrite.All"]
}
##Log Analytics API Role Assignment
resource "azuread_app_role_assignment" "LogAnalytics-Read" {
app_role_id = azuread_service_principal.LogAnalyticsAPI.app_role_ids["Data.Read"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.LogAnalyticsAPI.object_id
}
#Role Assigning to the App
data "azurerm_subscription" "primary" {
}
data "azurerm_client_config" "appregclient" {
}
resource "azurerm_role_assignment" "example" {
scope = data.azurerm_subscription.primary.id
role_definition_name = "Reader"
principal_id = azuread_service_principal.appregsp.object_id
depends_on = [
azuread_application.appreg
]
}
I'm Creating the App Registration, App Registration Secrets, API Permissions, and Role Assignment via Terraform. I'm Able to allocate the MicroSoft Graph API Permissions and able to Grant Permissions. For Log Analytic API Permission Grant, I'm Getting Error on the Terraform code. I have upload how I want Log Analytic API Permission in the Image.
But I'm getting the Error Message as below:
I tried to reproduce the same in my environment:
As we see azuread_service_principal block has been named LogAnalyticsApi and not LogAnalyticsAPI
resource "azuread_service_principal" "LogAnalyticsApi" {
application_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI
use_existing = true
owners = [data.azuread_client_config.current.object_id]
}
When changed it LogAnalyticsApi when referred in remaining blocks
For example:
resource "azuread_app_role_assignment" "LogAnalytics-Read" {
app_role_id = azuread_service_principal.LogAnalyticsApi.app_role_ids["Data.Read"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.LogAnalyticsApi.object_id
}
Then the error is resolved.
But occurred to map element LogAnalyticsAPI to log result .
Please change it to MicrosoftGraph or AppIds present in this available ApplicationIds in place of “ application_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI “
resource "azuread_service_principal" "LogAnalyticsApi" {
application_id = data.azuread_application_published_app_ids.log.result.MicrosoftGraph
use_existing = false
owners = [data.azuread_client_config.current.object_id]
}
And also correct the same while giving Data.Read access to it in required_resource_access block
ex:
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.log.result.MicrosoftGraph
resource_access {
id = azuread_service_principal.LogAnalyticsApi.app_role_ids["Data.Read"]
type = "Role"
}
}
Reference: https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/application_published_app_ids
There is a Mapping issue, which I have identified and fixed the issue. Regarding the Log Analytic Grant permission,
My Log Analytic Resource Block:
data "azuread_application_published_app_ids" "log" {}
resource "azuread_service_principal" "LogAnalyticsApi" {
application_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI
use_existing = true
owners = [data.azuread_client_config.current.object_id]
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.log.result.LogAnalyticsAPI
resource_access {
id = azuread_service_principal.LogAnalyticsAPI.app_role_ids["Data.Read"]
type = "Role"
}
}
resource "azuread_app_role_assignment" "LogAnalytics-Read" {
app_role_id = azuread_service_principal.LogAnalyticsAPI.app_role_ids["Data.Read"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.LogAnalyticsAPI.object_id
}
I have modified the code as Below and Log Analytic Api Permission I'm able to Grant the Log Analytic API Permission. You can check by calling the below resource blocks in your code.
data "azuread_application_published_app_ids" "log" {}
resource "azuread_service_principal" "LogAnalyticsApi" {
application_id = "ca7f3f0b-7d91-482c-8e09-c5d840d0eac5" #Data.Read
use_existing = true
owners = [data.azuread_client_config.current.object_id]
}
required_resource_access {
resource_app_id = "ca7f3f0b-7d91-482c-8e09-c5d840d0eac5"
resource_access {
id = azuread_service_principal.LogAnalyticsApi.app_role_ids["Data.Read"]
type = "Role"
}
}
resource "azuread_app_role_assignment" "LogAnalytics-Read" {
app_role_id = azuread_service_principal.LogAnalyticsApi.app_role_ids["Data.Read"]
principal_object_id = azuread_service_principal.appregsp.object_id
resource_object_id = azuread_service_principal.LogAnalyticsApi.object_id
}
I am trying to do app registration using Terraform Azure AD 2.0 provider and i get the below error while apply.
The Object ID is that for Microsoft Graph.
All the well known IDs are provided below :
https://github.com/manicminer/hamilton/blob/main/environments/published.go
https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/application_published_app_ids
│
Error: Updating service principal with object ID: "a2f717fe-bc5d-42e5-b0b4-801562508280"
│
│ with azuread_service_principal.msgraph,
│ on resources.application.tf line 220, in resource "azuread_service_principal" "msgraph":
│ 220: resource "azuread_service_principal" "msgraph" {
│
│ ServicePrincipalsClient.BaseClient.Patch(): unexpected status 403 with
│ OData error: Authorization_RequestDenied: Insufficient privileges to
│ complete the operation.
Below is my code :
data "azuread_application_published_app_ids" "well_known" {}
data "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
}
resource "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
use_existing = true
}
resource "azuread_application" "app-api" {
display_name = format("app-%s-api-%s", var.project.name, var.project.environment.name)
owners = [data.azuread_client_config.default.object_id]
api {
oauth2_permission_scope {
admin_consent_description = "Allows the app to read and write data"
admin_consent_display_name = local.oauth2_permissions.read-and-write.admin_consent_display_name
enabled = true
id = random_uuid.opsys-gw.result
type = "User"
value = "read-and-write"
}
}
app_role {
allowed_member_types = ["User", "Application"]
description = "Application administrators have the ability to administer the application."
display_name = local.app_roles.application-administrator.display_name
enabled = true
id = data.azuread_client_config.default.object_id
value = "application-administrator"
}
web {
logout_url = format("https://%s.azurewebsites.net/.auth/logout", module.name_app_service_api.location.app_service.name_unique)
redirect_uris = [format("https://%s.azurewebsites.net/.auth/login/aad/callback", module.name_app_service_api.location.app_service.name_unique)]
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph # Microsoft Graph
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
resource_access {
id = random_uuid.opsys-gw.result # User.Read.All
type = "Scope"
}
}
}
Azure AD API Service Principal Resource
resource "azuread_service_principal" "api-sp" {
application_id = azuread_application.app-api.application_id
app_role_assignment_required = false
owners = [data.azuread_client_config.default.object_id]
}
Azure AD API App Service Principal Secret
resource "azuread_application_password" "api-app-sp-secret" {
application_object_id = azuread_application.app-api.object_id
}
My Terraform Service Principal Application already has been assigned the required permissions in Azure AD as shown in the attachment
When i tried with your above code as a normal user was getting the same error(as i didn't know i should require a priviledge of Application Administator Or Global AdminStrator Role in my tenant.
Once I got the above one of roles and adminsitator permission so then able to run the code.
Also you need to Remove this statement from your code.
data "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
}
Terraform Code:
# Configure the Azure Active Directory Provider
provider "azuread" {
}
data "azuread_client_config" "current" {}
data "azuread_application_published_app_ids" "well_known" {}
resource "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
use_existing = true
}
resource "azuread_application" "app-api" {
display_name = "example3724"
owners = [data.azuread_client_config.current.object_id]
api {
oauth2_permission_scope {
admin_consent_description = "Allow the application to access example on behalf of the signed-in user."
admin_consent_display_name = "Access example"
enabled = true
id = "96183846-204b-4b43-82e1-5d2222eb4b9b"
type = "User"
user_consent_description = "Allow the application to access example on your behalf."
user_consent_display_name = "Access example"
value = "user_impersonation"
}
}
app_role {
allowed_member_types = ["User", "Application"]
description = "Admins can manage roles and perform all task actions"
display_name = "Admin"
enabled = true
id = data.azuread_client_config.current.object_id
value = "application-administrator"
}
web {
homepage_url = "https://app.example.net"
logout_url = "https://app.example.net/logout"
redirect_uris = ["https://app.example.net/account"]
implicit_grant {
access_token_issuance_enabled = true
id_token_issuance_enabled = true
}
}
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph # Microsoft Graph
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["User.ReadWrite"]# User.Read.All
type = "Scope"
}
}
}
OutPut--
I need some assistance to undertand the various forms of logging in to Databricks. I am using Terraform to provision Azure Databricks
I would like to know the difference in the two codes below
When i use option 1, i get the error as shown
Option 1:
required_providers {
azuread = "~> 1.0"
azurerm = "~> 2.0"
azuredevops = { source = "registry.terraform.io/microsoft/azuredevops", version = "~> 0.0" }
databricks = { source = "registry.terraform.io/databrickslabs/databricks", version = "~> 0.0" }
}
}
provider "random" {}
provider "azuread" {
tenant_id = var.project.arm.tenant.id
client_id = var.project.arm.client.id
client_secret = var.secret.arm.client.secret
}
provider "databricks" {
host = azurerm_databricks_workspace.db-workspace.workspace_url
azure_use_msi = true
}
resource "azurerm_databricks_workspace" "db-workspace" {
name = module.names-db-workspace.environment.databricks_workspace.name_unique
resource_group_name = module.resourcegroup.resource_group.name
location = module.resourcegroup.resource_group.location
sku = "premium"
public_network_access_enabled = true
custom_parameters {
no_public_ip = true
virtual_network_id = module.virtualnetwork["centralus"].virtual_network.self.id
public_subnet_name = module.virtualnetwork["centralus"].virtual_network.subnets["db-sub-1-public"].name
private_subnet_name = module.virtualnetwork["centralus"].virtual_network.subnets["db-sub-2-private"].name
public_subnet_network_security_group_association_id = module.virtualnetwork["centralus"].virtual_network.nsgs.associations.subnets["databricks-public-nsg-db-sub-1-public"].id
private_subnet_network_security_group_association_id = module.virtualnetwork["centralus"].virtual_network.nsgs.associations.subnets["databricks-private-nsg-db-sub-2-private"].id
}
tags = local.tags
}
Databricks Cluster Creation
resource "databricks_cluster" "dbcselfservice" {
cluster_name = format("adb-cluster-%s-%s", var.project.name, var.project.environment.name)
spark_version = var.spark_version
node_type_id = var.node_type_id
autotermination_minutes = 20
autoscale {
min_workers = 1
max_workers = 7
}
azure_attributes {
availability = "SPOT_AZURE"
first_on_demand = 1
spot_bid_max_price = 100
}
depends_on = [
azurerm_databricks_workspace.db-workspace
]
}
Databricks Workspace RBAC Permission
resource "databricks_group" "db-group" {
display_name = format("adb-users-%s", var.project.name)
allow_cluster_create = true
allow_instance_pool_create = true
depends_on = [
resource.azurerm_databricks_workspace.db-workspace
]
}
resource "databricks_user" "dbuser" {
count = length(local.display_name)
display_name = local.display_name[count.index]
user_name = local.user_name[count.index]
workspace_access = true
depends_on = [
resource.azurerm_databricks_workspace.db-workspace
]
}
Adding Members to Databricks Admin Group
resource "databricks_group_member" "i-am-admin" {
for_each = toset(local.email_address)
group_id = data.databricks_group.admins.id
member_id = databricks_user.dbuser[index(local.email_address, each.key)].id
depends_on = [
resource.azurerm_databricks_workspace.db-workspace
]
}
data "databricks_group" "admins" {
display_name = "admins"
depends_on = [
# resource.databricks_cluster.dbcselfservice,
resource.azurerm_databricks_workspace.db-workspace
]
}
The error that i get while TF apply is below :
Error: User not authorized
with databricks_user.dbuser[1],
on resources.adb.tf line 80, in resource "databricks_user" "dbuser":
80: resource "databricks_user" "dbuser"{
Error: User not authorized
with databricks_user.dbuser[0],
on resources.adb.tf line 80, in resource "databricks_user" "dbuser":
80: resource "databricks_user" "dbuser"{
Error: cannot refresh AAD token: adal:Refresh request failed. Status Code = '500'. Response body: {"error":"server_error", "error_description":"Internal server error"} Endpoint http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.core.windows.net%2F
with databricks_group.db-group,
on resources.adb.tf line 80, in resource "databricks_group" "db-group":
71: resource "databricks_group" "db-group"{
Is the error coming because of this block below ?
provider "databricks" {
host = azurerm_databricks_workspace.db-workspace.workspace_url
azure_use_msi = true
}
I just need to login automatically when i click on the URL from the portal. So what shall i use for that? And why do we need to provide two times databricks providers, once under required_providers and again in provider "databricks"?
I have seen if i don't provide the second provider i get the error :
"authentication is not configured for provider"
As mentioned in the comments , If you are using Azure CLI authentication i.e. az login using your username and password , then you can use the below code :
terraform {
required_providers {
databricks = {
source = "databrickslabs/databricks"
version = "0.3.11"
}
}
}
provider "azurerm" {
features {}
}
provider "databricks" {
host = azurerm_databricks_workspace.example.workspace_url
}
resource "azurerm_databricks_workspace" "example" {
name = "DBW-ansuman"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
sku = "premium"
managed_resource_group_name = "ansuman-DBW-managed-without-lb"
public_network_access_enabled = true
custom_parameters {
no_public_ip = true
public_subnet_name = azurerm_subnet.public.name
private_subnet_name = azurerm_subnet.private.name
virtual_network_id = azurerm_virtual_network.example.id
public_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.public.id
private_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.private.id
}
tags = {
Environment = "Production"
Pricing = "Standard"
}
}
data "databricks_node_type" "smallest" {
local_disk = true
depends_on = [
azurerm_databricks_workspace.example
]
}
data "databricks_spark_version" "latest_lts" {
long_term_support = true
depends_on = [
azurerm_databricks_workspace.example
]
}
resource "databricks_cluster" "dbcselfservice" {
cluster_name = "Shared Autoscaling"
spark_version = data.databricks_spark_version.latest_lts.id
node_type_id = data.databricks_node_type.smallest.id
autotermination_minutes = 20
autoscale {
min_workers = 1
max_workers = 7
}
azure_attributes {
availability = "SPOT_AZURE"
first_on_demand = 1
spot_bid_max_price = 100
}
depends_on = [
azurerm_databricks_workspace.example
]
}
resource "databricks_group" "db-group" {
display_name = "adb-users-admin"
allow_cluster_create = true
allow_instance_pool_create = true
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
resource "databricks_user" "dbuser" {
display_name = "Rahul Sharma"
user_name = "example#contoso.com"
workspace_access = true
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
resource "databricks_group_member" "i-am-admin" {
group_id = databricks_group.db-group.id
member_id = databricks_user.dbuser.id
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
Output:
If you are using Service Principal as authentication , then you can use something like below:
terraform {
required_providers {
databricks = {
source = "databrickslabs/databricks"
version = "0.3.11"
}
}
}
provider "azurerm" {
subscription_id = "948d4068-xxxx-xxxx-xxxx-e00a844e059b"
tenant_id = "72f988bf-xxxx-xxxx-xxxx-2d7cd011db47"
client_id = "f6a2f33d-xxxx-xxxx-xxxx-d713a1bb37c0"
client_secret = "inl7Q~Gvdxxxx-xxxx-xxxxyaGPF3uSoL"
features {}
}
provider "databricks" {
host = azurerm_databricks_workspace.example.workspace_url
azure_client_id = "f6a2f33d-xxxx-xxxx-xxxx-d713a1bb37c0"
azure_client_secret = "inl7Q~xxxx-xxxx-xxxxg6ntiyaGPF3uSoL"
azure_tenant_id = "72f988bf-xxxx-xxxx-xxxx-2d7cd011db47"
}
resource "azurerm_databricks_workspace" "example" {
name = "DBW-ansuman"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
sku = "premium"
managed_resource_group_name = "ansuman-DBW-managed-without-lb"
public_network_access_enabled = true
custom_parameters {
no_public_ip = true
public_subnet_name = azurerm_subnet.public.name
private_subnet_name = azurerm_subnet.private.name
virtual_network_id = azurerm_virtual_network.example.id
public_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.public.id
private_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.private.id
}
tags = {
Environment = "Production"
Pricing = "Standard"
}
}
data "databricks_node_type" "smallest" {
local_disk = true
depends_on = [
azurerm_databricks_workspace.example
]
}
data "databricks_spark_version" "latest_lts" {
long_term_support = true
depends_on = [
azurerm_databricks_workspace.example
]
}
resource "databricks_cluster" "dbcselfservice" {
cluster_name = "Shared Autoscaling"
spark_version = data.databricks_spark_version.latest_lts.id
node_type_id = data.databricks_node_type.smallest.id
autotermination_minutes = 20
autoscale {
min_workers = 1
max_workers = 7
}
azure_attributes {
availability = "SPOT_AZURE"
first_on_demand = 1
spot_bid_max_price = 100
}
depends_on = [
azurerm_databricks_workspace.example
]
}
resource "databricks_group" "db-group" {
display_name = "adb-users-admin"
allow_cluster_create = true
allow_instance_pool_create = true
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
resource "databricks_user" "dbuser" {
display_name = "Rahul Sharma"
user_name = "example#contoso.com"
workspace_access = true
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
resource "databricks_group_member" "i-am-admin" {
group_id = databricks_group.db-group.id
member_id = databricks_user.dbuser.id
depends_on = [
resource.azurerm_databricks_workspace.example
]
}
And why do we need to provide
two times databricks providers, once under required_providers and
again in provider "databricks"?
The required_providers is used to download and initialize the required providers from the source i.e. Terraform Registry . But the Provider Block is used for further configuration of that downloaded provider like describing client_id, features block etc. which can be used for authentication or other configuration.
The azure_use_msi option is primarily intended for use from CI/CD pipelines that are executed on machines with managed identity assigned to them. All possible authentication options are described in the documenation, but simplest way is to use authentication via Azure CLI, so you just need to leave host parameter in the provider block. If you don't have Azure CLI on that machine, you can use combination of host + personal access token instead.
if you're running that code from the machine with assigned managed identity, then you need to make sure that this identity is either added into workspace, or it has Contributor access to it - see Azure Databricks documentation for more details.
I would like to give access to two users to use Azure Databricks using the below block :
resource "databricks_user" "dbuser" {
display_name = local.name.display_name
user_name = local.name.user_name
workspace_access = true
}
I have locals defined as below :
locals {
name = {
display_name = ["Vincent Casinha",
"Susan Young"
]
user_name = ["vincent.casinha#contoso.com",
"susan.young#contoso.com"]
}
}
While trying to run terraform plan i get the error attached. How do i use the local values properly in the databricks_user block for the argumens display_name & user_name?
locals {
display_name = ["Vincent Casinha", "Susan Young"]
user_name = ["vincent.casinha#contoso.com","susan.young#contoso.com"]
}
#assuming length of display_name and user_name are same
resource "databricks_user" "dbuser" {
count = length(local.display_name)
display_name = local.display_name[count.index]
user_name = local.user_name[count.index]
workspace_access = true
}
#or you can do like below
locals {
name = [
{
display_name = "Vincent Casinha"
user_name = "vincent.casinha#contoso.com"
},
{
display_name = "Susan Young"
user_name = "susan.young#contoso.com"
}
]
}
resource "databricks_user" "dbuser" {
for_each = local.name
display_name = each.value.display_name
user_name = each.value.user_name
workspace_access = true
}
I am trying to create a custom RBAC role definition and assignment to assign to an app registration.
All resources and the definition create ok but when it goes to execute the azurerm_role_assignment resource I get:
Service returned an error. Status=400 Code="InvalidRoleDefinitionId" Message="The role definition ID 'xxxx-xxxx-xxxx-xxxx-xxxx' is not valid
I'm probably going a bit code blind as I can't see what's wrong, any ideas?
resource "random_password" "aad-app-myrbac" {
length = 24
special = true
override_special = "##$%+=_-*&[]{}?!"
}
resource "random_password" "aad-sp-myrbac" {
length = 24
special = true
override_special = "##$%+=_-*&[]{}?!"
}
resource "azuread_application" "myrbac" {
name = "my-app-registration"
homepage = "https://localhost"
identifier_uris = [""]
reply_urls = [""]
available_to_other_tenants = false
oauth2_allow_implicit_flow = false
}
resource "azuread_application_password" "myrbac" {
application_object_id = azuread_application.myrbac.id
description = "myrbac client secret"
value = random_password.aad-app-myrbac.result
end_date_relative = "87600h"
lifecycle {
ignore_changes = [end_date_relative]
}
}
resource "azuread_service_principal" "myrbac" {
application_id = azuread_application.myrbac.application_id
}
resource "azuread_service_principal_password" "myrbac" {
service_principal_id = azuread_service_principal.myrbac.id
value = random_password.aad-sp-myrbac.result
end_date_relative = "87600h"
lifecycle {
ignore_changes = [end_date_relative]
}
}
resource "azurerm_role_definition" "myrbac" {
name = "my role definition"
scope = data.azurerm_subscription.current.id
description = "my role definition"
permissions {
actions = [
"Microsoft.Authorization/permissions/read",
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachineScaleSets/read",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/*/read",
"Microsoft.Network/networkInterfaces/read",
"Microsoft.Network/publicIPAddresses/read",
"Microsoft.Network/virtualNetworks/read"
]
not_actions = []
}
assignable_scopes = [data.azurerm_subscription.current.id]
}
resource "azurerm_role_assignment" "myrbac" {
scope = data.azurerm_subscription.current.id
role_definition_id = azurerm_role_definition.myrbac.id
principal_id = azuread_service_principal.myrbac.object_id
skip_service_principal_aad_check = true
}
note code has been sanitised and the total role defs cut down for brevity.
You can use the parameter role_definition_name instead of role_definition_id and add the depends_on like this:
resource "azurerm_role_assignment" "myrbac" {
scope = data.azurerm_subscription.current.id
role_definition_name = azurerm_role_definition.myrbac.name
principal_id = azuread_service_principal.myrbac.object_id
skip_service_principal_aad_check = true
depends_on = [azurerm_role_definition.myrbac]
}
It will work for you.