How to get Resource Availability Statuses with Azure Java SDK - azure

I want to find out the availability status of a resource in Azure.
There is a REST API available for Resource Health.
How is it possible to call this endpoint with the Azure Java SDK?

I found a solution using com.azure.resourcemanager:azure-resourcemanager:2.2.0.
Following code loads the availability status of an Azure Key Vault.
TokenCredential credentials = InteractiveBrowserCredentialBuilder().build();
AzureResourceManager resourceManager = AzureResourceManager
.configure()
.authenticate(credentials, AzureProfile(AzureEnvironment.AZURE))
.withDefaultSubscription();
String resourceGroup = "resource-group-name";
String keyVaultName = "key-vault-name";
GenericResource resource = resourceManager.genericResources().get(
resourceGroup,
"Microsoft.KeyVault",
"vaults/" + keyVaultName + "/providers/Microsoft.ResourceHealth",
"availabilityStatuses",
"/current",
"2020-05-01"
);
// Map containing the availabilityState
resource.properties();

Related

Create Databricks token for another user

After deploying Databricks workspace I would like to add an application user and generate a token for it. Is there a way to have something like:
resource "databricks_service_principal" "app" {
application_id = "01234567-89ab-cdef-0123-456789abcdef"
}
resource "databricks_token" "token" {
service_principal_id = databricks_service_principal.app.application_id
comment = "A token"
}
Currently databricks_token doesn't support service_principal_id field, it only creates token for current user.
It depends on the cloud:
On AWS there is support for so-called "on behalf of" (OBO) token - there is a dedicated resource for it: databricks_obo_token (doc).
On Azure, you can create a separate provider instance to authenticate to Databricks using Service Principal authentication (doc) and generate token using that provider instance (although, frankly speaking, it's better always use AAD auth for service principals on Azure). Something like this:
# this will use "normal" provider instance
resource "databricks_service_principal" "app" {
application_id = "01234567-89ab-cdef-0123-456789abcdef"
}
# Provider instance for Service Principal
provider "databricks" {
host = azurerm_databricks_workspace.this.workspace_url
azure_workspace_resource_id = azurerm_databricks_workspace.this.id
azure_client_id = var.client_id
azure_client_secret = var.client_secret
azure_tenant_id = var.tenant_id
alias = "spn"
}
resource "databricks_token" "token" {
provider = databricks.spn
comment = "A token"
depends_on = [databricks_service_principal.app]
}

terraform backend state file storage using keys instead of AD account

It appears that Terraform uses Keys for backend state files when persisting to an Azure storage account. I wish to use a single storage account with dedicated folders for different service principals but without cross-folder write access. I am trying to avoid accidental overwrites of the state files by different service principals. But since Terraform is using the keys to update the storage account, every service principal technically has rights to update every file. And the developer would have to take care not to accidentally reference the wrong state file to update. Any thoughts on how to protect against this?
You can use a SAS token generated for a Container to be used by that service principal only and no other service principals .
I tested with something like below:
data "terraform_remote_state" "foo" {
backend = "azurerm"
config = {
storage_account_name = "cloudshellansuman"
container_name = "test"
key = "prod.terraform.tfstate"
sas_token = "sp=racwdl&st=2021-09-28T05:49:01Z&se=2023-04-01T13:49:01Z&sv=2020-08-04&sr=c&sig=O87nHO01sPxxxxxxxxxxxxxsyQGQGLSYzlp6F8%3D"
}
}
provider "azurerm" {
features {}
use_msi = true
subscription_id = "948d4068-xxxxx-xxxxxx-xxxxxxxxxx"
tenant_id = "72f988bf-xxxx-xxxxx-xxxxxx-xxxxxxx"
}
resource "azurerm_resource_group" "test" {
name="xterraformtest12345"
location ="east us"
}
But If I change container name to another container then I can't write as it will error out saying the authentication failed as the SAS token is for Test container not Test1 container.
For more information on how to generate SAS token for containers and how to set backend azurerm for terraform , please refer the below links:
Generate shared access signature (SAS) token for containers and blobs with Azure portal. | Microsoft Docs
Use Azure storage for Terraform remote state
OR
You can set the containers authentication method to azure ad user account, after assigning storage blob data contributor/owner role to the service principal which will use that specific container .
Then you can use something like below:
data "terraform_remote_state" "foo" {
backend = "azurerm"
config = {
storage_account_name = "cloudshellansuman"
container_name = "test1"
key = "prod.terraform.tfstate"
subscription_id = "b83c1ed3-xxxx-xxxxxx-xxxxxxx"
tenant_id = "72f988bf-xxx-xxx-xxx-xxx-xxxxxx"
client_id = "f6a2f33d-xxxx-xxxx-xxx-xxxxx"
client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxxxx"
use_azuread_auth =true
}
}
provider "azurerm"{
subscription_id = "b83c1ed3-xxxx-xxxxxx-xxxxxxx"
tenant_id = "72f988bf-xxx-xxx-xxx-xxx-xxxxxx"
client_id = "f6a2f33d-xxxx-xxxx-xxx-xxxxx"
client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxxxx"
features {}
}
data "azurerm_resource_group" "test" {
name="resourcegroupname"
}
resource "azurerm_virtual_network" "example" {
name = "example-network"
resource_group_name = data.azurerm_resource_group.test.name
location = data.azurerm_resource_group.test.location
address_space = ["10.254.0.0/16"]
}
Output:
If service principal doesn't have Role assigned to it for the container , then it will give error like below:
Note: For the first scenario I have used managed system identity, but the same can be achieved for service principal as well.

Create Azure Service Principal for multiple subscriptions

I have been able to successfully create a Service Principal secret with the below terraform. However, I am a bit confused on what is the correct approach for trying to create a Service Principal for several subscriptions. I am bit of a novice and unfortunately running into a wall with this. What is the best/right way to implement service principal for multiple subscriptions?
data "azurerm_subscription" "example-subscription" {
subscription_id = "959e460c-209e-43d7-a6e9-e30c716e0691"
}
# Azure AD App
resource "azuread_application" "example-subscription" {
name = "example-subscription"
available_to_other_tenants = false
}
# Service Principal associated with the Azure AD App
resource "azuread_service_principal" "example-subscription" {
application_id = azuread_application.example-subscription.application_id
}
# Random string to be used for Service Principal password
resource "random_password" "password-subscription" {
length = 32
special = true
}
# Service Principal password
resource "azuread_service_principal_password" "example-subscription" {
service_principal_id = azuread_service_principal.example-subscription.id
value = random_password.password-subscription.result
end_date_relative = "17520h"
}
# Role assignment for service principal
resource "azurerm_role_assignment" "example-subscription" {
scope = data.azurerm_subscription.example-subscription.id
role_definition_name = "Contributor"
principal_id = azuread_service_principal.example-subscription.id
}
Example Subscriptions
data "azurerm_subscription" "example-subscription" {
subscription_id = "959e460c-209e-43d7-a6e9-e30c716e0691"
}
data "azurerm_subscription" "example-subscription2” {
subscription_id = "b344b74c-4600-470d-ad73-e918b0d0ccd3"
}
data "azurerm_subscription" "example-subscription3” {
subscription_id = "242d05b2-e06e-4713-8094-44955dab1ee8"
}
A service principal is the local representation, or application instance, of a global application object in a single Azure AD tenant or directory. A service principal is a concrete instance created from the application object and inherits certain properties from that application object.
https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals
If you have multiple Azure Subscription in one Azure AD tenant you may use your single Service Principal across all of your Azure Subscriptions.

Access azure container registry (ACR) by role assignment for azure app service in Terraform

I have a azure app service that is provisioned by Terraform. The app service fires up the docker image from Azure ACR there fore it need to access the ACR. I'm currently using the password and login name method in my Terraform configuration. How can I make the azure app service to access the ACR by service principle role assignment in Terraform?
resource "azurerm_app_service" "tf_app_service" {
name = var.application_name
location = azurerm_resource_group.tf_resource_group.location
resource_group_name = azurerm_resource_group.tf_resource_group.name
app_service_plan_id = azurerm_app_service_plan.tf_service_plan.id
site_config {
always_on = true
linux_fx_version = "DOCKER|${var.acr_name}.azurecr.io/${var.img_repo_name}:${var.tag}"
}
// How to use role assignment?
app_settings = {
DOCKER_REGISTRY_SERVER_URL = // need to avoid docker URL
WEBSITES_ENABLE_APP_SERVICE_STORAGE = "false"
DOCKER_REGISTRY_SERVER_USERNAME = // need to avoid user name
DOCKER_REGISTRY_SERVER_PASSWORD = // need to avoid PW
}
identity {
type = "SystemAssigned"
}
tags = {
environment = var.environment
DeployedBy = "terraform"
}
}
The steps to use a Service Principle to access ACR are lined out here.
So to do the same in Terraform, you need to first create a new service principle. Then assign a password to it. Afterwards you should be able to use those two to fill the app settings of your app service.

How can I use Terraform to create a service principal and use that principal in a provider?

I have read the write-ups online but they dont seem to cover this topic completely and was hoping someone who has done it may have some direction for me.
We are setting up a complicated Terraform template to satisfy our IaC requirements relating to our SaaS offering. In doing so we want the template to use the user's credentials at launch to create a new service principal in Azure AD (This part I have no problem doing). Then in the next portion of the template we are using that service principal as the provider. Problem is that it throws errors in the plan/apply because the service principal doesnt exist (aka the id is non existent due to the service provider section not running yet).
So is there a way that I can do this? Create a service principal and then us it in a provider alias that uses that service principal without splitting this into multiple templates?
In the end I want this template to create the service provider using the local user's permissions or MSI, give it RBAC to a subscription, then use that service provider to create assets in that subscription.
main.ts (root)
provider "azurerm" {
alias = "ActiveDirectory"
subscription_id = "${var.subscriptionNucleus}"
}
provider "azurerm" {
alias = "Infrastructure"
subscription_id = "${var.subscriptionInfrastructure}"
}
module "activedirectory" {
providers = { azurerm = "azurerm.ActiveDirectory"
}
source = "./modules/activedirectory"
subscription_id_infrastructure = "${var.subscriptionInfrastructure}"
}
module "infrastructure" {
providers = { azurerm = "azurerm.Infrastructure"}
source = "./modules/infrastructure"
location = "${var.location}"
application_id =
"${module.activedirectory.service_principal_application_id}"
subscription_id = "${var.subscriptionInfrastructure}"
prefix = "${var.prefix}"
}
main.ts (./modules/infrastructure)
data "azurerm_azuread_service_principal" "serviceprincipal" {
application_id = "${var.application_id}"
}
provider "azurerm" {
alias = "InfrastructureSP"
subscription_id = "${var.subscription_id}"
client_id = "${var.application_id}"
client_secret = "secret"
tenant_id =
"${data.azurerm_client_config.clientconfig.tenant_id}"
}
For Azure Service Principal, there are two ways to use the service principal.
First: If you already have a service principal and want to use it in the Terraform. You can make use of the Terraform Data and the test like this:
data "azurerm_azuread_service_principal" "sp" {
application_id = "21f3e1de-54e2-4951-9743-c280ad7bd74a"
}
output "test" {
value = "${data.azurerm_azuread_service_principal.sp.id}"
}
The screenshot of the result is here:
Second: You don't have the service principal and you can just create a service principal in the Terraform like this:
resource "azurerm_azuread_service_principal" "test" {
application_id = "${azurerm_azuread_application.test.application_id}"
}
resource "azurerm_azuread_service_principal_password" "test" {
service_principal_id = "${azurerm_azuread_service_principal.test.id}"
value = "your pasword"
end_date = "2020-01-01T01:02:03Z"
}
Then, no matter which way you choose, there is an important step you should do for most resources. The step is that you need to create the role to give the permission and then assign it to the resource which needs. You can do that like this:
resource "azurerm_role_assignment" "test" {
scope = "yourScope" # the resource id
role_definition_name = "the Role In need" # such as "Contributor"
principal_id = "your service principal id"
}
Hope this will help you.
There is currently no working "depends_on" that works with modules that is not a hack (null_reference). This means that if you are breaking your template into modules(separating concerns) your order of operation is required to be correct to complete this successfully as one module will not know that the data source of service provider has to wait on the previous module to complete. I have had to break this into 2 separate templates where the first creates the service principal and the second has the modular separation that can then use a data source of azurerm_azuread_service_principal.
Once Hashicorp can implement the module depends_on, this will become easier.

Resources