terraform-provider-azuread
terraform-provider-azuread copied to clipboard
Terraform destroy on azuread_service_principal returns 403, but is destroyed
Currently I am using the Terraform's azurerm and azuread provider to create the same resources as az ad sp create-for-rbac
would do. For this I apply the following code:
provider "azurerm" {
features {}
}
data "azurerm_client_config" "current" {}
data "azurerm_resource_group" "rg" {
name = "my_rg"
}
resource "azuread_application" "app-registration" {
display_name = "my-app-registration"
owners = [data.azurerm_client_config.current.object_id]
}
resource "azuread_service_principal" "service-principal" {
application_id = azuread_application.app-registration.application_id
}
resource "azuread_application_password" "password" {
application_object_id = azuread_application.app-registration.object_id
end_date = "2022-01-01T00:00:00Z"
}
resource "azurerm_role_assignment" "role" {
principal_id = azuread_service_principal.service-principal.id
role_definition_name = "Contributor"
scope = data.azurerm_resource_group.rg.id
}
For now I authenticate via a User principal (i.e. az login) to an Azure subscription of which I am the Owner. In AAD I am a regular User (with no additional assigned roles such as Application Administrator or Global Administrator). Applying the above code with terraform apply
works and creates the app registration, service principal and service principal secret.
When I, however, use terraform destroy
on this code I get the following error
│ Error: Deleting service principal with object ID "XXX", got status 403
│
│ ServicePrincipalsClient.BaseClient.Delete(): unexpected status 403 with OData error: Authorization_RequestDenied: Insufficient privileges to complete the operation.
At that moment the following resources are left in my terraform state:
data.azurerm_client_config.current
azuread_application.app-registration
azuread_service_principal.service-principal
If I then again use terraform destroy
, the azuread_application.app-registration
is destroyed. Meaning that the service principal is deleted in Azure and not accessible anymore, but azuread_service_principal.service-principal
is still present in my terraform state.
Terraform (and AzureAD Provider) Version
Terraform v1.0.5 on linux_amd64
- provider registry.terraform.io/hashicorp/azuread v2.0.1
- provider registry.terraform.io/hashicorp/azurerm v2.74.0
Affected Resource(s)
-
azuread_application
-
azuread_service_principal
Terraform Configuration Files
See above
# Copy-paste your Terraform configurations here - for large Terraform configs,
# please use a service like Dropbox and share a link to the ZIP file. For
# security, you can also encrypt the files using our GPG public key: https://keybase.io/hashicorp
Debug Output
Panic Output
Expected Behavior
Either the azuread_application.app-registration
and azuread_service_principal.service-principal
should both be deletable from my Terraform state, or they should both be not deletable from my Terraform state.
Actual Behavior
azuread_application.app-registration
and azuread_service_principal.service-principal
are deleted from Azure, but azuread_service_principal.service-principal
is still present in my Terraform state.
Steps to Reproduce
-
terraform apply
-
terraform destroy
(throws error) -
terraform destroy
(on the remaining resources)
Important Factoids
References
- #0000
May be related to #535
I also hit this before reaching #535 - I think that it can be resolved by adding owners
to the service principal, just as on the application.
I think that the reason that the service principal is destroyed is that, although destroying it as a standalone object failed, it goes when the application goes.
Would be nice if there's anything that can be done to make the terraform behaviour better, but I'm not sure what.
This would usually be taken care of by the DAG if you reference the application_id
in the service principal resource, from the application resource - I'll play around with this and see what can be improved.
@dimbleby thanks for your solution, that indeed works! But I agree with @manicminer if the parent resource (in this case azuread_application.app-registration
) is owned by my object-id then I would expect that you can delete the child resource (azuread_service_principal.service-principal
) without specifying the owner.
@avinashpancham Given the authentication setup you describe, I suspect this is down to API/object permissions. There is a useful Azure docs page describing the default permissions for users when no additional directory roles are assigned - which states that a regular (non-guest) user can register applications and read service principals (noting that service principals are referred to as 'enterprise applications' versus 'registered applications' which are app registrations).
I agree with @dimbleby that specifying yourself in the owners
list for both the application and service principal may resolve the deletion issue for you. There is a bug in 2.0.0/2.0.1 with service principal owners so I'd suggest waiting for 2.1.0 to confirm that.
Failing that, the service principal resource has a new property use_existing
. When you set this to true
, the provider will first look for an existing service principal that might have been auto-created and will use that instead of creating a new one - and subsequently it will ignore any permissions errors when deleting/destroying that same service principal. It's not ideal behavior but does work around SPs for first-party applications and cases such as this where you don't have permission to delete but you can delete the linked app registration.
Just as a heads up this is still an issue in 2.2.1
Hi @avinashpancham, @dimbleby, @slyons
Thanks for reporting on this issue. I have not observed this error myself however it's likely in my testing I don't have the same configurations of principals and API/directory roles which would cause this to occur.
I would suggest checking that the following conditions are being met by your Azure and Terraform configurations:
- If your authenticated principal is a user principal, that it is a Member of the tenant directory. If it is a Guest, it must have the
Applications Administrator
directory role assigned in the tenant in which it is a guest. - If your authenticated principal is a service principal, that one of these are true:
- The linked application has the
Applications.ReadWrite.All
API role assigned and admin consent is granted to the service principal - The linked application has the
Applications.ReadWrite.OwnedBy
API role assigned with admin consent granted to the service principal, and in your Terraform configuration, that theowners
is specified for both the application and service principal that Terraform is trying to create, and thatowners
for both resources includes the authenticated (calling) principal, e.g. the value ofazuread_client_config.object_id
- The linked application has the
If you are confident these conditions are met, and you still receive the error, feel free to post HTTP traces for both the apply
and the destroy
operations to this issue, and I'll be happy to verify that Terraform is sending the correct request(s). Should Terraform be demonstrated to be doing the right thing, I'll pass the evidence to the service team for further investigation. Thanks!