hashicorp / terraform-provider-azuread

Terraform provider for Azure Active Directory
https://registry.terraform.io/providers/hashicorp/azuread/latest/docs
Mozilla Public License 2.0
418 stars 285 forks source link

Support for AzureAD Enterprise Applications & Proxy Resources #7

Open rayterrill opened 6 years ago

rayterrill commented 6 years ago

Community Note

Description

Create resources to support Enterprise Applications and specifically AzureAD application proxy resources (https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/application-proxy).

We're using this heavily with AzureAD and would love a declarative way to manage them vs creating them with the GUI or the relatively new PowerShell cmdlets.

New or Affected Resource(s)

References

tombuildsstuff commented 6 years ago

hey @rayterrill

Thanks for opening this issue :)

Taking a quick look into this - I can't see an API available for this functionality here: https://docs.microsoft.com/en-us/rest/api/resources/ - do you know if it happens to go by another name?

Thanks!

rayterrill commented 6 years ago

@tombuildsstuff Unfortunately I don't. That's what I was afraid of - given that they just added the PowerShell mechanism to do that work I had a feeling there might not be a public API yet. :(

ranieuwe commented 6 years ago

Which step are you seeking to manage? The registration of the application or the connectors or both?

ranieuwe commented 6 years ago

Taking a quick look into this - I can't see an API available for this functionality here: https://docs.microsoft.com/en-us/rest/api/resources/ - do you know if it happens to go by another name?

It is not part of AzureRM but part of Graph. According to the Changelog for Graph this was already pushed in September 2016, but I can't really find any clear documentation on it. In the Azure REST API specification you can see some of it pop up as Graph RBAC, which is implemented by the Go SDK.

rayterrill commented 6 years ago

@ranieuwe The registration of "Enterprise Applications" in general would be really useful for us. As far as the App Proxy piece, basically everything in the "On-premises application" section (internal URL, external URL, Preauthentication, connector group, etc). https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/application-proxy-publish-azure-portal. Things like being able to add users/groups to the apps, SSO settings, etc would also be beautiful.

tombuildsstuff commented 5 years ago

๐Ÿ‘‹๐Ÿป

We've just posted a proposal regarding splitting the Azure Active Directory resources out into their own Provider in #2322, which would allow us to ship support for additional AzureAD resources. If you're subscribed to this thread we'd be interested to hear any feedback you may have on the proposal in that thread :)

Thanks!

katbyte commented 5 years ago

Hi @rayterrill,

As in 2.0 we are deprecating all Azure AD resources and data sources in the Azure RM provider in favour of this new provider I have moved the issue here.

midacts commented 5 years ago

Is the Azure AD Graph API what is blocking enterprise applications?

StefanSchoof commented 4 years ago

I was able to create Enterprise Application with

resource "azuread_service_principal" "this" {
  application_id                = azuread_application.this.application_id
  tags = [
    "AppServiceIntegratedApp",
    "WindowsAzureActiveDirectoryIntegratedApp",
  ]
}

The tags matter. I had no time to try of both tags are required.

See also https://stackoverflow.com/questions/54071385/difference-between-enterprise-application-and-app-registration-in-azure

borancar commented 4 years ago

Just "WindowsAzureActiveDirectoryIntegratedApp". I found that out by manually having created a resource and then importing it in Terraform.

JasonDonnelly commented 4 years ago

Forget mining for bitcoins, its golden nuggets like this that deliver real value, thx to the community for sharing.

dgteixeira commented 2 years ago

@borancar hey, how are you? With that code, could I create, through terraform, a specific Enterprise Application? For example, this one: GitHub Enterprise Cloud Organization.

I haven't found any way of creating this and specifying its details (SAML SSO and Provisioning mappings, for example) through terraform.

Best regards, Diogo Teixeira

borancar commented 2 years ago

@borancar hey, how are you? With that code, could I create, through terraform, a specific Enterprise Application? For example, this one: GitHub Enterprise Cloud Organization.

Give it a shot - I haven't worked with Azure in a while, so wouldn't know... putting that tag was all that was needed to make the principal into an Enterprise Application.

manicminer commented 1 year ago

Potential docs reference: https://learn.microsoft.com/en-us/graph/application-proxy-configure-api?tabs=http

timja commented 1 year ago

Notes from my attempt:

Yes https://learn.microsoft.com/en-us/graph/application-proxy-configure-api?tabs=http is the correct doc.

First issue:

Error with app roles, I commented out the code disabling them to get past it. (Looks related to https://github.com/hashicorp/terraform-provider-azuread/issues/950)

    //if err := applicationDisableAppRoles(ctx, client, &properties, expandApplicationAppRoles(d.Get("app_role").(*schema.Set).List())); err != nil {
    //  return tf.ErrorDiagPathF(err, "app_role", "Could not disable App Roles for application with object ID %q", d.Id())
    //}

Second issue: Invalid property name being sent, I checked the SDK and the name didn't match the expected value, fixed with https://github.com/manicminer/hamilton/pull/244

Third issue: Properties couldn't be updated on the application created with the recommended template 8adf8e6e-67b2-4cf2-a259-e3dc5476c621 (I didn't investigate this much other than commenting out the code)

{"error":{"code":"BadRequest","message":"The request is currently not supported on the targeted entity set","innerError":{"date":"2023-06-07T15:00:10","request-id":"80b887fd-c2b6-47d5-83bb-cfae8e2b604f","client-request-id":"80b887fd-c2b6-47d5-83bb-cfae8e2b604f"}}}

I commented out the relevant code:

    //if _, err := client.Update(ctx, properties); err != nil {
    //  return tf.ErrorDiagF(err, "Could not update global application with object ID: %q", d.Id())
    //}

To work around the properties update I created a specific PATCH just for these attributes and I still got the error:

{"error":{"code":"BadRequest","message":"The request is currently not supported on the targeted entity set","innerError":{"date":"2023-06-07T15:00:10","request-id":"80b887fd-c2b6-47d5-83bb-cfae8e2b604f","client-request-id":"80b887fd-c2b6-47d5-83bb-cfae8e2b604f"}}}

I added TF_LOG and compared the body that was being sent to one that worked in the graph explorer and I saw that the id for the application is sent in the body by terraform. When I send the request with id in the graph explorer it fails, when I remove the id it works:

broken:

{
  "id": "32860704-96e8-4493-a5fc-9c4d917a24ec",
  "onPremisesPublishing": {
    "externalAuthenticationType": "aadPreAuthentication",
    "externalUrl": "https://contosoiwaapp-contoso.msappproxy.net",
    "internalUrl": "https://contosoiwaapp.com",
    "isHttpOnlyCookieEnabled": true,
    "isOnPremPublishingEnabled": true,
    "isPersistentCookieEnabled": false,
    "isSecureCookieEnabled": false,
    "isTranslateHostHeaderEnabled": true,
    "isTranslateLinksInBodyEnabled": false
  }
}

broken response:

{
    "error": {
        "code": "BadRequest",
        "message": "The request is currently not supported on the targeted entity set",
        "innerError": {
            "date": "2023-06-07T15:49:19",
            "request-id": "7ddc08bd-ea56-44eb-96c0-df53f22398a7",
            "client-request-id": "08ca0054-e0f7-ee3b-d011-95075684da43"
        }
    }
}

working is above without id

Code reference: https://github.com/manicminer/hamilton/blob/9893247866cc3aa95ff00b2dec2f70215e5f3d9b/msgraph/applications.go#L154-L158

Is there anyway to work around this @manicminer? I'm a bit surprised the id is added to the body for no reason, is it required in some cases or just a mistake by virtue of the object having an ID in it and then accidentally serialised, or should the API just be ignoring this value and not complaining?

My changes: https://github.com/hashicorp/terraform-provider-azuread/compare/main...timja:terraform-provider-azuread:app-proxy?expand=1

charliegibb commented 1 year ago

Hi @timja, just adding a +1 to this. Awesome work glad this has got some traction, it'll be a great resource to have in TF

timja commented 1 year ago

I've written a blog and a CLI tool using the Graph API to work around this in the meantime:

https://blog.timja.dev/how-to-automate-azure-ad-application-proxy-part-2/

https://github.com/hmcts/azure-app-proxy-manager

It should be do-able to adapt terraform but it will need changes to the SDK used and I would like @manicminer 's input on that

ctejeda commented 1 year ago

I know the graph API requires you to utilize a Microsoft template for Azure ad App proxy type apps. There is a requirement to instantiate non-gallery apps. see link below. https://learn.microsoft.com/en-us/graph/api/applicationtemplate-instantiate?view=graph-rest-1.0&tabs=http

I had to go this route when calling Graph API via power automate to create Azure AD Applications which utilized Application Proxy.

image image image

there's a static template id for non-gallery azure apps that we may be able to specify via terraform Example:

`resource "azuread_application" "example_app" { display_name = "example azure application app" template_id = "8adf8e6e-67b2-4cf2-a259-e3dc5476c621" }

resource "azuread_service_principal" "example_app" { application_id = azuread_application.template2.application_id use_existing = true feature_tags { enterprise = true gallery = false } }`

hope this helps shed some light on this request.

ctejeda commented 1 year ago

{ "id": "32860704-96e8-4493-a5fc-9c4d917a24ec", "onPremisesPublishing": { "externalAuthenticationType": "aadPreAuthentication", "externalUrl": "https://contosoiwaapp-contoso.msappproxy.net", "internalUrl": "https://contosoiwaapp.com", "isHttpOnlyCookieEnabled": true, "isOnPremPublishingEnabled": true, "isPersistentCookieEnabled": false, "isSecureCookieEnabled": false, "isTranslateHostHeaderEnabled": true, "isTranslateLinksInBodyEnabled": false } }

May you provide an example of a resource creation with the app proxy settings ?

timja commented 1 year ago

May you provide an example of a resource creation with the app proxy settings ?

What do you mean? it's not possible with terraform currently.

You need to use the Graph API, or you can take a look at the app I wrote for it: https://blog.timja.dev/how-to-automate-azure-ad-application-proxy-part-2/

ctejeda commented 1 year ago

I came up with a workaround that works for my use case. you can read more about it here: https://ctejeda.com/documentation/creating-azure-apps-that-utilize-azure-application-proxy-via-terrafrom/

Thanks @timja for shedding some light on this.

using the below worked for me as a work around.

`terraform { required_providers { azuread = { source = "hashicorp/azuread" version = "~> 2.7.0" } } }

provider "azuread" {

client_id = "var.client_id" client_secret = "var.sec" tenant_id = "var.tenant_id" }

data "azuread_application_template" "example" { template_id = "8adf8e6e-67b2-4cf2-a259-e3dc5476c621" }

resource "azuread_application" "example" { display_name = "example" template_id = data.azuread_application_template.example.template_id feature_tags { custom_single_sign_on = true } }

resource "azuread_service_principal" "example" { application_id = azuread_application.example.application_id use_existing = true preferred_single_sign_on_mode = "saml" login_url = "https://test-verifieddoamin.net/" feature_tags { enterprise = true gallery = false custom_single_sign_on = true }

provisioner "local-exec" { command = <<EOF curl --location --request PATCH 'https://graph.microsoft.com/beta/applications/${azuread_application.example.object_id}' --header 'Content-Type: application/json' --header 'Authorization: Bearervar.token' --data '{ "onPremisesPublishing": { "externalAuthenticationType": "aadPreAuthentication", "internalUrl": "https://internalurl.com/", "externalUrl": "https://externalurl.verifieddomain.com/", "isHttpOnlyCookieEnabled": true, "isOnPremPublishingEnabled": true, "isPersistentCookieEnabled": true, "isSecureCookieEnabled": true, "isStateSessionEnabled": true, "isTranslateHostHeaderEnabled": true, "isTranslateLinksInBodyEnabled": true } }' EOF }

}

`

ctejeda commented 1 year ago

Just posted my official workaround here for anyone still looking for a work around.

https://github.com/ctejeda/azuread_appproxy

daviewales commented 5 months ago

Just "WindowsAzureActiveDirectoryIntegratedApp". I found that out by manually having created a resource and then importing it in Terraform.

Not sure when this was added, but you can now specify this using the higher level feature_tags block:

resource "azuread_application" "example" {
  display_name = "example"
}

resource "azuread_service_principal" "example" {
  client_id = azuread_application.example.client_id

  feature_tags {
    enterprise = true
  }
}

The docs linked state that specifying enterprise = true is the same as assigning the WindowsAzureActiveDirectoryIntegratedApp tag.