Skip to content

Commit

Permalink
Improvements to Service Principals and some other bug fixes
Browse files Browse the repository at this point in the history
**Service Principals**

- Support the `account_enabled` field
- Support the `alternative_names` field
- Support the `description` field
- Support the `login_url` field
- Support the `notes` field
- Support the `notification_email_addresses` field
- Support the `preferred_single_sign_on_mode` field
- Support the `use_existing` field
- Export the `application_tenant_id` attribute
- Export the `display_name` attribute
- Export the `homepage_url` attribute
- Export the `logout_url` attribute
- Export the `redirect_uris` attribute
- Export the `saml_metadata_url` attribute
- Export the `service_principal_names` attribute
- Export the `sign_in_audience` attribute
- Export the `type` attribute

**Applications**

- New data source: `azuread_application_published_app_ids`

**Bug fixes**

- `azuread_application` - `identifier_uris` is now a TypeSet (was TypeList) **Breaking Change**
- `azuread_application` - fix a bug parsing the `implicit_grant` block
  • Loading branch information
manicminer committed Jul 21, 2021
1 parent 3e5eed1 commit 64a98a4
Show file tree
Hide file tree
Showing 23 changed files with 668 additions and 77 deletions.
62 changes: 62 additions & 0 deletions docs/data-sources/application_published_app_ids.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
subcategory: "Applications"
---

# Data Source: azuread_application_published_app_ids

Use this data source to discover application IDs for APIs published by Microsoft.

This data source uses an [unofficial source of application IDs](https://github.com/manicminer/hamilton/blob/main/environments/published.go), as there is currently no available official indexed source for applications or APIs published by Microsoft.

The app IDs returned by this data source are sourced from the Azure Global (Public) Cloud, however some of them are known to work in government and national clouds.

## Example Usage

*Listing well-known application IDs*

```terraform
data "azuread_application_published_app_ids" "well_known" {}
output "published_app_ids" {
value = data.azuread_application_published_app_ids.well_known.result
}
```

*Granting access to an application*

```terraform
data "azuread_application_published_app_ids" "well_known" {}
resource "azuread_service_principal" "msgraph" {
application_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
use_existing = true
}
resource "azuread_application" "example" {
display_name = "example"
required_resource_access {
resource_app_id = data.azuread_application_published_app_ids.well_known.result.MicrosoftGraph
resource_access {
id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
type = "Role"
}
resource_access {
id = azuread_service_principal.msgraph.oauth2_permission_scope_ids["User.ReadWrite"]
type = "Scope"
}
}
}
```

## Argument Reference

This data source does not have any arguments.

## Attributes Reference

The following attributes are exported:

* `result` - A map of application names to application IDs.
15 changes: 15 additions & 0 deletions docs/data-sources/service_principal.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,26 @@ The following arguments are supported:

The following attributes are exported:

* `account_enabled` - - Whether or not the service principal account is enabled.
* `alternative_names` - A list of alternative names, used to retrieve service principals by subscription, identify resource group and full resource ids for managed identities.
* `app_role_ids` - A mapping of app role values to app role IDs, as published by the associated application, intended to be useful when referencing app roles in other resources in your configuration.
* `app_roles` - A list of app roles published by the associated application, as documented below. For more information [official documentation](https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles).
* `application_tenant_id` - The tenant ID where the associated application is registered.
* `description` - A description of the service principal provided for internal end-users.
* `homepage_url` - Home page or landing page of the associated application.
* `login_url` - The URL where the service provider redirects the user to Azure AD to authenticate. Azure AD uses the URL to launch the application from Microsoft 365 or the Azure AD My Apps.
* `logout_url` - The URL that will be used by Microsoft's authorization service to logout an user using OpenId Connect front-channel, back-channel or SAML logout protocols, taken from the associated application.
* `notes` - A free text field to capture information about the service principal, typically used for operational purposes.
* `notification_email_addresses` - A list of email addresses where Azure AD sends a notification when the active certificate is near the expiration date. This is only for the certificates used to sign the SAML token issued for Azure AD Gallery applications.
* `object_id` - The object ID for the service principal.
* `oauth2_permission_scope_ids` - A mapping of OAuth2.0 permission scope values to scope IDs, as exposed by the associated application, intended to be useful when referencing permission scopes in other resources in your configuration.
* `oauth2_permission_scopes` - A collection of OAuth 2.0 delegated permissions exposed by the associated application. Each permission is covered by an `oauth2_permission_scopes` block as documented below.
* `redirect_uris` - A list of URLs where user tokens are sent for sign-in with the associated application, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent for the associated application.
* `saml_metadata_url` - The URL where the service exposes SAML metadata for federation.
* `service_principal_names` - A list of identifier URI(s), copied over from the associated application.
* `sign_in_audience` - The Microsoft account types that are supported for the associated application. Possible values include `AzureADMyOrg`, `AzureADMultipleOrgs`, `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount`.
* `tags` - A list of tags applied to the service principal.
* `type` - Identifies whether the service principal represents an application or a managed identity. Possible values include `Application` or `ManagedIdentity`.

---

Expand Down
8 changes: 5 additions & 3 deletions docs/guides/microsoft-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ The `mail_enabled` and `security_enabled` fields are no longer read-only, and at

## Removal of deprecated fields

The following attributes/properties have been deprecated in the AzureAD provider, and has been removed in version 2.0.
The following attributes/properties were deprecated in the AzureAD provider, and have now been removed in version 2.0.

~> **Compatibility Note** You will need to update your Terraform configuration in the latest v1.x release to use the new fields, prior to upgrading to 2.0.

Expand Down Expand Up @@ -249,12 +249,14 @@ The `id` field in the `app_role` block was previously currently Computed (read-o

The `id` field in the deprecated `oauth2_permissions` block was previously Computed (read-only) but its replacement field `id` in the `oauth2_permission_scope` block is Required.

## Computed fields
## Computed fields and other breaking changes

In previous version of the provider, many fields were introduced as Optional + Computed fields. This meant that omitting such fields would cause Terraform to ignore them and not attempt to manage them. However, this approach has many side effects including the inability to unset or clear these fields, and sometimes being forced to accept an undesired default value.

To resolve these issues, many of these fields are no longer Computed in version 2.0 of the provider. This means that Terraform will manage these fields and if you do not specify their values in your configuration, they will be unset or set to their default or zero values. In some cases it's appropriate for a field to be Computed, particularly where it helps prevent disruption to services or users.

Additionally, some fields have been updated in ways that may break existing configurations, for example changing their type.

Accordingly, in version 2.0 of the provider the following fields have changed.

### Resource: `azuread_application`
Expand All @@ -265,7 +267,7 @@ The `value` field in the `app_role` block is no longer Computed, omitting this f

The `fallback_public_client_enabled` field is no longer Computed, omitting this field will cause Terraform to default this value to `false`.

The `identifier_uris` field is no longer Computed, omitting this field will cause Terraform to remove any identifier URIs configured for an application.
The `identifier_uris` field was previously a List type field and is now a Set type field. This is due to API ordering and means you can no longer reference this field and index it sequentially without first converting it to a list. Additional, this field is no longer Computed, so omitting this field will cause Terraform to remove any identifier URIs configured for an application.

The `oauth2_permission_scope` block is no longer Computed, omitting this block will cause Terraform to remove any OAuth2 permission scopes published by an application.

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ The following arguments are supported:
* `display_name` - (Required) The display name for the application.
* `fallback_public_client_enabled` - (Optional) Specifies whether the application is a public client. Appropriate for apps using token grant flows that don't use a redirect URI. Defaults to `false`.
* `group_membership_claims` - (Optional) Configures the `groups` claim issued in a user or OAuth 2.0 access token that the app expects. Possible values are `None`, `SecurityGroup`, `DirectoryRole`, `ApplicationGroup` or `All`.
* `identifier_uris` - (Optional) The user-defined URI(s) that uniquely identify an application within its Azure AD tenant, or within a verified custom domain if the application is multi-tenant.
* `identifier_uris` - (Optional) A set of user-defined URI(s) that uniquely identify an application within its Azure AD tenant, or within a verified custom domain if the application is multi-tenant.
* `marketing_url` - (Optional) URL of the application's marketing page.
* `oauth2_post_response_required` - (Optional) Specifies whether, as part of OAuth 2.0 token requests, Azure AD allows POST requests, as opposed to GET requests. Defaults to `false`, which specifies that only GET requests are allowed.
* `optional_claims` - (Optional) An `optional_claims` block as documented below.
Expand Down
18 changes: 18 additions & 0 deletions docs/resources/service_principal.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,38 @@ resource "azuread_service_principal" "example" {

The following arguments are supported:

* `account_enabled` - (Optional) Whether or not the service principal account is enabled. Defaults to `true`.
* `alternative_names` - (Optional) A set of alternative names, used to retrieve service principals by subscription, identify resource group and full resource ids for managed identities.
* `app_role_assignment_required` - (Optional) Whether this service principal requires an app role assignment to a user or group before Azure AD will issue a user or access token to the application. Defaults to `false`.
* `application_id` - (Required) The application ID (client ID) of the application for which to create a service principal.
* `description` - (Optional) A description of the service principal provided for internal end-users.
* `login_url` - (Optional) The URL where the service provider redirects the user to Azure AD to authenticate. Azure AD uses the URL to launch the application from Microsoft 365 or the Azure AD My Apps. When blank, Azure AD performs IdP-initiated sign-on for applications configured with SAML-based single sign-on.
* `notes` - (Optional) A free text field to capture information about the service principal, typically used for operational purposes.
* `notification_email_addresses` - (Optional) A set of email addresses where Azure AD sends a notification when the active certificate is near the expiration date. This is only for the certificates used to sign the SAML token issued for Azure AD Gallery applications.
* `preferred_single_sign_on_mode` - (Optional) The single sign-on mode configured for this application. Azure AD uses the preferred single sign-on mode to launch the application from Microsoft 365 or the Azure AD My Apps. Supported values are `oidc`, `password`, `saml` or `notSupported`. Omit this property or specify a blank string to unset.
* `tags` - (Optional) A set of tags to apply to the service principal.
* `use_existing` - (Optional) When true, any existing service principal linked to the same application will be automatically imported. When false, an import error will be raised for any pre-existing service principal.

-> **Caveats of `use_existing`** Enabling this behaviour is useful for managing existing service principals that may already be installed in your tenant for Microsoft-published APIs, as it allows you to make changes where permitted, and then also reference them in your Terraform configuration. However, the behaviour of delete operations is also affected - when `use_existing` is `true`, Terraform will still attempt to delete the service principal on destroy, although it will not raise an error if the deletion fails (as it often the case for first-party Microsoft applications).

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `app_role_ids` - A mapping of app role values to app role IDs, as published by the associated application, intended to be useful when referencing app roles in other resources in your configuration.
* `app_roles` - A list of app roles published by the associated application, as documented below. For more information [official documentation](https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles).
* `application_tenant_id` - The tenant ID where the associated application is registered.
* `display_name` - The display name of the application associated with this service principal.
* `homepage_url` - Home page or landing page of the associated application.
* `logout_url` - The URL that will be used by Microsoft's authorization service to logout an user using OpenId Connect front-channel, back-channel or SAML logout protocols, taken from the associated application.
* `oauth2_permission_scope_ids` - A mapping of OAuth2.0 permission scope values to scope IDs, as exposed by the associated application, intended to be useful when referencing permission scopes in other resources in your configuration.
* `oauth2_permission_scopes` - A list of OAuth 2.0 delegated permission scopes exposed by the associated application, as documented below.
* `object_id` - The object ID of the service principal.
* `redirect_uris` - A list of URLs where user tokens are sent for sign-in with the associated application, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent for the associated application.
* `saml_metadata_url` - The URL where the service exposes SAML metadata for federation.
* `service_principal_names` - A list of identifier URI(s), copied over from the associated application.
* `sign_in_audience` - The Microsoft account types that are supported for the associated application. Possible values include `AzureADMyOrg`, `AzureADMultipleOrgs`, `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount`.
* `type` - Identifies whether the service principal represents an application or a managed identity. Possible values include `Application` or `ManagedIdentity`.

---

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 // indirect
github.com/klauspost/compress v1.12.2 // indirect
github.com/manicminer/hamilton v0.21.0
github.com/manicminer/hamilton v0.22.0
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/manicminer/hamilton v0.21.0 h1:TsvOK9GkUQVVostAuWA6b67kI7TW7TdGVDDFCe2baac=
github.com/manicminer/hamilton v0.21.0/go.mod h1:y0lB5Ey1UesBkFa9NAtybwWPoN4v1SbY1Chp3OqGtN4=
github.com/manicminer/hamilton v0.22.0 h1:qsoUquW//kQoxZtq8zTnHCVO7jzp9+iYoDsBfkQ3G50=
github.com/manicminer/hamilton v0.22.0/go.mod h1:y0lB5Ey1UesBkFa9NAtybwWPoN4v1SbY1Chp3OqGtN4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
Expand Down
9 changes: 9 additions & 0 deletions internal/acceptance/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ func (td TestData) ResourceTest(t *testing.T, testResource types.TestResource, s
td.runAcceptanceTest(t, testCase)
}

func (td TestData) ResourceTestIgnoreDangling(t *testing.T, _ types.TestResource, steps []resource.TestStep) {
testCase := resource.TestCase{
PreCheck: func() { PreCheck(t) },
Steps: steps,
}

td.runAcceptanceTest(t, testCase)
}

func (td TestData) runAcceptanceTest(t *testing.T, testCase resource.TestCase) {
testCase.ProviderFactories = map[string]func() (*schema.Provider, error){
"azuread": func() (*schema.Provider, error) {
Expand Down
2 changes: 1 addition & 1 deletion internal/clients/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (b *ClientBuilder) Build(ctx context.Context) (*Client, error) {
}
client.TenantID = cli.TenantID
if clientId, ok := environments.PublishedApis["MicrosoftAzureCli"]; ok && clientId != "" {
client.ClientID = string(clientId)
client.ClientID = clientId
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package applications

import (
"context"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/manicminer/hamilton/environments"

"github.com/hashicorp/terraform-provider-azuread/internal/tf"
)

func applicationPublishedAppIdsDataSource() *schema.Resource {
return &schema.Resource{
ReadContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics {
tf.Set(d, "result", environments.PublishedApis)
d.SetId("appIds")
return nil
},

Timeouts: &schema.ResourceTimeout{
Read: schema.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*schema.Schema{
"result": {
Description: "A mapping of application names and application IDs",
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package applications_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-azuread/internal/acceptance"
"github.com/hashicorp/terraform-provider-azuread/internal/acceptance/check"
)

type ApplicationPublishedAppIdsDataSource struct{}

func TestAccApplicationPublishedAppIdsDataSource_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azuread_application_published_app_ids", "test")
r := ApplicationPublishedAppIdsDataSource{}

data.DataSourceTest(t, []resource.TestStep{
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("result.%").Exists(),
),
},
})
}

func (ApplicationPublishedAppIdsDataSource) basic(data acceptance.TestData) string {
return `provider azuread {}
data "azuread_application_published_app_ids" "test" {}`
}
Loading

0 comments on commit 64a98a4

Please sign in to comment.