Skip to content

Instantly share code, notes, and snippets.

@fluffy-cakes
Created February 26, 2021 17:34
Show Gist options
  • Save fluffy-cakes/956386d4170679c270f7eb0c56bfe7a4 to your computer and use it in GitHub Desktop.
Save fluffy-cakes/956386d4170679c270f7eb0c56bfe7a4 to your computer and use it in GitHub Desktop.
How to call the Azure API directly via PowerShell from within Terraform
resource "null_resource" "deploy_workspace_settings" {
provisioner "local-exec" {
command = <<EOT
Import-Module ${path.module}/tf_azure_api_call.psm1
New-WorkspaceSetting `
-ClientId "${var.ARM_CLIENT_ID}" `
-ClientSecret "${var.ARM_CLIENT_SECRET}" `
-SubscriptionId "${var.ARM_SUBSCRIPTION_ID}" `
-TenantId "${var.ARM_TENANT_ID}" `
-WorkspaceId "${var.workspace_id}" `
-WorkspaceScope "${var.scope_id}"
EOT
interpreter = ["pwsh", "-Command"]
}
}
resource "null_resource" "destroy_workspace_settings" {
triggers = {
"ClientId" = var.ARM_CLIENT_ID
"ClientSecret" = var.ARM_CLIENT_SECRET
"SubscriptionId" = var.ARM_SUBSCRIPTION_ID
"TenantId" = var.ARM_TENANT_ID
}
provisioner "local-exec" {
when = destroy
command = <<EOT
Import-Module ${path.module}/tf_azure_api_call.psm1
Remove-WorkspaceSetting `
-ClientId "${self.triggers.ClientId}" `
-ClientSecret "${self.triggers.ClientSecret}" `
-SubscriptionId "${self.triggers.SubscriptionId}" `
-TenantId "${self.triggers.TenantId}"
EOT
interpreter = ["pwsh", "-Command"]
}
}
<#
.Synopsis
An example set of Terraform functions that allows you to deploy resources to Azure via API calls.
This was created to bypass deployments via Azure ARM templates and Terraform which routinely timed
out and failed, an issue that had been raised, still many months later with no fix in sight.
~ example ref: https://github.com/terraform-providers/terraform-provider-azurerm/issues/5475
.Parameter ClientId
Service principal client ID authorised for the deployment scope
.Parameter ClientSecret
Service principal client secret
.Parameter SubscriptionId
The ID of the subscription to deploy to
.Parameter TenantId
The ID of the tenant to deploy to
.Parameter WorkspaceId
The Log Analytics workspace ID used in this example to enable the workspace settings in Security Center
.Parameter WorkspaceScope
The subscription scope to which this workspace setting applies to
.Example
resource "null_resource" "deploy_workspace_settings" {
provisioner "local-exec" {
command = <<EOT
Import-Module ${path.module}/workspace_settings.psm1
New-WorkspaceSetting `
-ClientId "${var.ARM_CLIENT_ID}" `
-ClientSecret "${var.ARM_CLIENT_SECRET}" `
-SubscriptionId "${var.ARM_SUBSCRIPTION_ID}" `
-TenantId "${var.ARM_TENANT_ID}" `
-WorkspaceId "${var.workspace_id}" `
-WorkspaceScope "${var.scope_id}"
EOT
interpreter = ["pwsh", "-Command"]
}
}
resource "null_resource" "destroy_workspace_settings" {
triggers = {
"ClientId" = var.ARM_CLIENT_ID
"ClientSecret" = var.ARM_CLIENT_SECRET
"SubscriptionId" = var.ARM_SUBSCRIPTION_ID
"TenantId" = var.ARM_TENANT_ID
}
provisioner "local-exec" {
when = destroy
command = <<EOT
Import-Module ${path.module}/workspace_settings.psm1
Remove-WorkspaceSetting `
-ClientId "${self.triggers.ClientId}" `
-ClientSecret "${self.triggers.ClientSecret}" `
-SubscriptionId "${self.triggers.SubscriptionId}" `
-TenantId "${self.triggers.TenantId}"
EOT
interpreter = ["pwsh", "-Command"]
}
}
#>
function Get-Authenticated {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string] $ClientId,
[ValidateNotNullOrEmpty()]
[string] $ClientSecret,
[ValidateNotNullOrEmpty()]
[string] $TenantId
)
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/x-www-form-urlencoded")
# Client secrets can contain special characters, so we encode it to be used without errors
$encode = [System.Web.HTTPUtility]::UrlEncode("$ClientSecret")
$body = "client_id=$ClientId&client_secret=$encode&grant_type=client_credentials&scope=https%3A%2F%2Fmanagement.azure.com%2F.default"
$url = "https://login.microsoftonline.com/" + $TenantId + "/oauth2/v2.0/token"
$authentication = Invoke-RestMethod $url -Method 'GET' -Headers $headers -Body $body
return $authentication.access_token
}
function New-WorkspaceSetting {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string] $ClientId,
[ValidateNotNullOrEmpty()]
[string] $ClientSecret,
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[ValidateNotNullOrEmpty()]
[string] $TenantId,
[ValidateNotNullOrEmpty()]
[string] $WorkspaceId,
[ValidateNotNullOrEmpty()]
[string] $WorkspaceScope
)
$workspaceName = "default"
$token = Get-Authenticated -ClientId "$ClientId" -ClientSecret "$ClientSecret" -TenantId "$TenantId"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer $token")
$headers.Add("Content-Type", "application/json")
$body = "{`n
`"properties`": {`n
`"workspaceId`": `"$WorkspaceId`",`n
`"scope`": `"$WorkspaceScope`"`n
}`n
}"
$url = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/providers/Microsoft.Security/workspaceSettings/" + $workspaceName + "?api-version=2017-08-01-preview"
$response = Invoke-RestMethod $url -Method 'PUT' -Headers $headers -Body $body
$response
}
function Remove-WorkspaceSetting {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string] $ClientId,
[ValidateNotNullOrEmpty()]
[string] $ClientSecret,
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[ValidateNotNullOrEmpty()]
[string] $TenantId
)
$workspaceName = "default"
$token = Get-Authenticated -ClientId "$ClientId" -ClientSecret "$ClientSecret" -TenantId "$TenantId"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer $token")
$url = "https://management.azure.com/subscriptions/" + $SubscriptionId + "/providers/Microsoft.Security/workspaceSettings/" + $workspaceName + "?api-version=2017-08-01-preview"
$response = Invoke-RestMethod $url -Method 'DELETE' -Headers $headers -Body $body
$response
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment