give access to service principal which is in another azure tenant - azure

we deploy resources in our Azure tenant through Jenkins which uses terraform to provision infra resources.
and we use service principal for authentication and infra provisioning which are in same tenant. in our infra deployment we also create VNET peering with the new Vnet which get deployed and our central VNET which has all the infra resources like monitoring and logging platform.
now we have a use case where by using the same Jenkins and terraform scripts we want to provision resources on different tenant. this can be done by using the service principal of remote tenant.
but now issue is service principal of TenantB do not have rights to create network resources in TenantA. to make this happen service principal of TenantB should have access on Vnet in TenantA.
i am looking for documentation or guidance how we can give access to service principal of TenantB in our TenantA?

Hoping that you have created a service principal a service principal
using multi-tenant authentication (if single-tenant please change the
authentication method to multi-tenant) , add a redirect uri
https://www.microsoft.com.
After you have created the service principal you can open the below url in a private browser for adding it on another tenant:
https://login.microsoftonline.com/<Tenant B ID>/oauth2/authorize?client_id=<Application (client in tenant A)
ID>&response_type=code&redirect_uri=https%3A%2F%2Fwww.microsoft.com%2F
It will ask for authorization on behalf of organization , you can
accept it.
After the above is done , then you can login to portal of that tenant
and go to enterprise application you will see that , provide role
assignment for that subscription (owner/contributor).
After this is done you can use something like the below terraform
script:
provider "azurerm" {
alias = "tenantA"
subscription_id = "b83c1ed3-xxxxx-xxxxxx-xxxxxx-xxxxxx" #subid for tenant A
tenant_id = "72f988bf-xxxxxx-xxxxx-xxxxxxx-xxxxxx"#tenantid of tenant A
client_id = "f6a2f33d-xxxx-xxxx-xxxxx-xxxxxxxx"#client id of service principal in tenant A
client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxx"#client secret of service principal in tenant A
auxiliary_tenant_ids = ["ab078f81-xxxxxx-xxxxxxxx-xxxxxx"]# tenant id of tenant B
features {}
}
provider "azurerm"{
alias = "tenantB"
subscription_id = "88073b30-xxx-xxxxx-xxxxx-xxxxxxx"#sub id of tenant B
tenant_id = "ab078f81-xxxxx-xxxxxxx-xxxxxxxxx" # tenant id of tenant B
client_id = "f6a2f33d-xxxx-xxxxxx-xxxxxx-xxxxxx" #client id of service principal in tenant A
client_secret = "y5L7Q~oiMOoGCxm7fK~xxxxxxxxxxxxxxxx" #client secret of service principal in tenant A
auxiliary_tenant_ids = ["72f988bf-xxxx-xxxxx-xxxxxxxxxx-xx"] # tenant id of tenant A
features {}
}
data "azurerm_resource_group" "tenantARG"{
provider = azurerm.tenantA
name = "reswourcegroup"
}
data "azurerm_resource_group" "tenantBRG"{
provider = azurerm.tenantB
name = "ansuman-resourcegroup"
}
data "azurerm_virtual_network" "GlobalVnet"{
provider = azurerm.tenantA
name = "ansuman-vnet"
resource_group_name= data.azurerm_resource_group.tenantARG.name
}
data "azurerm_virtual_network" "tenantBVnet"{
provider = azurerm.tenantB
name = "test-vnet"
resource_group_name= data.azurerm_resource_group.tenantBRG.name
}
resource "azurerm_virtual_network_peering" "example-1" {
provider= azurerm.tenantA
name = "peer1to2"
resource_group_name = data.azurerm_resource_group.tenantARG.name
virtual_network_name = data.azurerm_virtual_network.GlobalVnet.name
remote_virtual_network_id = data.azurerm_virtual_network.tenantBVnet.id
}
resource "azurerm_virtual_network_peering" "example-2" {
provider = azurerm.tenantB
name = "peer2to1"
resource_group_name = data.azurerm_resource_group.tenantBRG.name
virtual_network_name = data.azurerm_virtual_network.tenantBVnet.name
remote_virtual_network_id = data.azurerm_virtual_network.GlobalVnet.id
}
Output:
Note: In my test case , I have used 2 vnets present in different tenants. I created a service principal in tenant A and provided contributor permissions to it in tenant B using the above methods and then used terraform to perform the vnet peering.

Related

How to create a Client Secret using Terraform?

I am trying to create a Client_secret for My service principal using the below code :
data "azuread_service_principal" "existing_SP" {
display_name = "TestAppRegistration"
}
resource "azuread_service_principal_password" "Client_Secret" {
service_principal_id = data.azuread_service_principal.existing_SP.object_id
}
Doing a terraform-apply it get successfully created but I don't see it in the Secrets and certificates section of the app registration:
But when I check the tfstate , it shows the value there created for the service principal but the object Id is same as the enterprise application present for the same app registration:
So, My question:
How can I create a client secret using terraform, is there something I am doing wrong ?
If I am doing correct then where is the secret generated can be found in portal?
How can I create a client secret using terraform, is there something I
am doing wrong ?
Yes , You are doing everything correctly.
But to clear the confusion here , as you may already know there are 2 types of azure ad application i.e. app registrations and enterprise application. In terraform or powershell or cli the App Registration is know as Azure AD application and the Enterprise Application for the same app registration is know as Service Principal. So , if you have created from Portal by going to app registration blade , then bydefault a service principal is created for it , but its not the same if you create a app registration from Powershell or Terraform.
And By default you will be not be able to see the secret or certificate created for service principal from portal but you will be defintely able to use it with the client-id for authentication purpose .
For example :
I tested this on my environment using your code and I took the value of password present in tfstate file and used it to do az login:
Note: Its safe to use terraform for creating a service principal password as it will be stored in the tfstate file so, you won't face difficulty in searching for it .
If I am doing correct then where is the secret generated can be found
in portal?
But if you are trying to look for the secret from portal , then I will suggest you to use azuread_application:
data "azuread_application" "example" {
display_name = "postman"
}
resource "azuread_application_password" "example" {
display_name = "terraformgenerated"
application_object_id = data.azuread_application.example.object_id
}

Assign role to user using Service principal

I have created some resources in Azure using Terraform and a Service principal:
A resource group
A virtual network
A virtual machine
Now, I need to create a virtual Gateway from this resource group and virtual network, but using a personal Azure account in the same Organization.
How can I add my user email as a Administrator to this resource group, from Terraform, using the Service Principal credentials?
You can use Terraform resource azurerm_role_assignment to add Owner permissions for your user to this resource group.
Example:
resource "azurerm_resource_group" "this" {
name = "example"
location = "West Europe"
}
resource "azurerm_role_assignment" "this" {
scope = azurerm_resource_group.this.id
role_definition_name = "Owner"
principal_id = "<Your user object id>"
}

How to register an application with the Microsoft identity platform via Terraform code

Register an application with the Microsoft identity platform can be found here
Each time when I redeploy the application, the registration will be deleted from the identity platform, and I don't want to do doing the registration again by click around in the portal.
Can I doing this via Terraform azure provider code?
You could use the terraform Azure Active Directory provider to manage it. You could refer to samples in this blog for more details.
For example, you may want to registry a basic application and associated it with a service principal then assign a contributor role to it.
# Configure the Microsoft Azure Active Directory Provider
provider "azuread" {}
provider "azurerm" {
features {}
}
data "azurerm_subscription" "primary" {
}
# Create an application
resource "azuread_application" "example" {
display_name = "example"
}
# Create a service principal
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
}
# Assign a Contributor role
resource "azurerm_role_assignment" "test" {
scope = data.azurerm_subscription.primary.id
role_definition_name = "Contributor"
principal_id = azuread_service_principal.example.object_id
}

NSG rule across subscription in azure via terraform

#provider azurem.mgmt is Subscription A.
#prodiver azurem.corpapps is Subscription B.
I am trying to create nsg rule in Subscription A with Provider azurerm.mgmt. Here the destination application security group is in Subscription B with Provider azurerm.corpapps in this subscription.
provider "azurerm" {
client_id = "${var.client_id}"
client_secret = "${var.client_secret}"
tenant_id = "${var.tenant_id}"
subscription_id = "${var.subscription}"
alias = "mgmt"
}
provider "azurerm" {
client_id = "${var.client_id}"
client_secret = "${var.client_secret}"
tenant_id = "${var.tenant_id}"
subscription_id = "${var.subscription_B}"
alias = "corpapps"
}
Then i use the provider to get my asg from Subscription B as shown:
Then i use that reference in my nsg rule
However, i get error - saying the ASG is not found:
But, in azure portal the resource is already there as shown:
I have tried to assign the SP which has owner role on both subscriptions or using Azure account with CLI but it's no luck. Also, as the comment points out, there is a limitation that NSG does not reference ASG in different location. After my validation, you can not add the ASG from another subscription even it's in the same region as the NSG or targets VNet.
Moreover, when you add this ASG as the target source or destination in the NSG rules, you will see
Select an application security group (ASG) as the security rule
source. ASGs enable fine-grained network security policies based on
workloads or applications instead of IP addresses or CIDR blocks.
Rules specifying an application security group are only applied to
network interfaces that are members of the application security group
on the same virtual network.

How Do I Query 2 Different Azure Directories When Using Terraform?

I am configuring my infrastructure in one Azure Directory with terraform and so I have set the Azure CLI to use that subscription:
az account set --subscription xxxxxxxx-0000-xxxx-YYYY-zzzzzzzzzzzz
Part of the setup is to add Active Directory Groups to APIM Management.
I create the groups and query AD for their ids using az cli in local-exec.
However, Active Directory is in a different subscription to where the infrastructure is being created so this step fails.
How can I switch directory/subscription for this one call?
I create the groups and query AD for their ids using az cli in local-exec.
You can query for groups with datasource azuread_group and/or manage resource azuread_group instead of az cli.
To use datasource/resource with multiple subscriptions you should authenticate multiple providers with aliases with different subscription_id like that:
provider "azuread" {
subscription_id = "xxxxxxxx-0000-xxxx-YYYY-zzzzzzzzzzzz"
}
provider "azuread" {
subscription_id = "another-subscription-id"
alias = "custom"
}
resource "azurerm_api_management" "test" {
...
}
resource "azuread_group" "mygroup" {
provider = azuread.custom
name = "my-group"
}

Resources