Skip to content

Commit

Permalink
Merge pull request #474 from hashicorp/f/application-improvements
Browse files Browse the repository at this point in the history
Application improvements
  • Loading branch information
manicminer authored Jul 21, 2021
2 parents 99b15ba + cdf4f18 commit 48f63a6
Show file tree
Hide file tree
Showing 46 changed files with 2,057 additions and 399 deletions.
28 changes: 28 additions & 0 deletions docs/data-sources/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,40 @@ output "azure_ad_object_id" {
The following attributes are exported:

* `api` - An `api` block as documented below.
* `app_role_ids` - A mapping of app role values to app role IDs, intended to be useful when referencing app roles in other resources in your configuration.
* `app_roles` - A collection of `app_role` blocks as documented below. For more information see [official documentation on Application Roles](https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles).
* `application_id` - The Application ID (also called Client ID).
* `device_only_auth_enabled` - Specifies whether this application supports device authentication without a user.
* `disabled_by_microsoft` - Whether Microsoft has disabled the registered application. If the application is disabled, this will be a string indicating the status/reason, e.g. `DisabledDueToViolationOfServicesAgreement`
* `display_name` - The display name for the application.
* `fallback_public_client_enabled` - The fallback application type as public client, such as an installed application running on a mobile device.
* `group_membership_claims` - The `groups` claim issued in a user or OAuth 2.0 access token that the app expects.
* `identifier_uris` - A list of user-defined URI(s) that uniquely identify a Web application within it's Azure AD tenant, or within a verified custom domain if the application is multi-tenant.
* `logo_url` - CDN URL to the application's logo.
* `marketing_url` - URL of the application's marketing page.
* `oauth2_permission_scope_ids` - A mapping of OAuth2.0 permission scope values to scope IDs, intended to be useful when referencing permission scopes in other resources in your configuration.
* `oauth2_post_response_required` - Specifies whether, as part of OAuth 2.0 token requests, Azure AD allows POST requests, as opposed to GET requests. When `false`, only GET requests are allowed.
* `object_id` - The application's object ID.
* `optional_claims` - An `optional_claims` block as documented below.
* `owners` - A list of object IDs of principals that are assigned ownership of the application.
* `privacy_statement_url` - URL of the application's privacy statement.
* `public_client` - A `public_client` block as documented below.
* `publisher_domain` - The verified publisher domain for the application.
* `required_resource_access` - A collection of `required_resource_access` blocks as documented below.
* `sign_in_audience` - The Microsoft account types that are supported for the current application. One of `AzureADMyOrg`, `AzureADMultipleOrgs`, `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount`.
* `single_page_application` - A `single_page_application` block as documented below.
* `support_url` - URL of the application's support page.
* `terms_of_service_url` - URL of the application's terms of service statement.
* `web` - A `web` block as documented below.

---

`api` block exports the following:

* `known_client_applications` - A set of application IDs (client IDs), used for bundling consent if you have a solution that contains two parts: a client app and a custom web API app.
* `mapped_claims_enabled` - Allows an application to use claims mapping without specifying a custom signing key.
* `oauth2_permission_scope` - One or more `oauth2_permission_scope` blocks as documented below, to describe delegated permissions exposed by the web API represented by this application.
* `requested_access_token_version` - The access token version expected by this resource. Possible values are `1` or `2`.

---

Expand Down Expand Up @@ -93,6 +109,12 @@ The following attributes are exported:

---

`public_client` block exports the following:

* `redirect_uris` - A list of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.

---

`required_resource_access` block exports the following:

* `resource_access` - A collection of `resource_access` blocks as documented below, describing OAuth2.0 permission scopes and app roles that the application requires from the specified resource.
Expand All @@ -107,6 +129,12 @@ The following attributes are exported:

---

`single_page_application` block exports the following:

* `redirect_uris` - A list of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.

---

`web` block exports the following:

* `homepage_url` - Home page or landing page of the application.
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/microsoft-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ The deprecated `oauth2_permissions` block has been replaced by the `oauth2_permi

-> In the new `oauth2_permission_scope` block, the `is_enabled` field has been renamed to `enabled` and the `id` field is now **required**. See the [New required UUID fields](#new-required-uuid-fields) section below for more information.

The deprecated field `public_client` has been replaced by the `fallback_public_client_enabled` field and has been removed.
The deprecated field `public_client` has been replaced by the `fallback_public_client_enabled` field. The new `public_client` block now contains settings for public client applications.

The deprecated field `reply_urls` has been replaced by the `redirect_uris` field in the `web` block and has been removed.

Expand Down Expand Up @@ -253,7 +253,7 @@ The `id` field in the deprecated `oauth2_permissions` block was previously Compu

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 zero values. It's also appropriate in some cases for a field to be Computed, particularly where it helps prevent disruption to services or users.
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.

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

Expand Down Expand Up @@ -362,7 +362,7 @@ resource "azuread_application" "example" {
admin_consent_description = "Allow the application to access example-app on behalf of the signed-in user."
admin_consent_display_name = "Access example-app"
id = random_uuid.example_app_user_impersonation_scope.result
is_enabled = true
enabled = true
type = "User"
user_consent_description = "Allow the application to access example-app on your behalf."
user_consent_display_name = "Access example-app"
Expand Down
50 changes: 47 additions & 3 deletions docs/resources/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ resource "azuread_application" "example" {
sign_in_audience = "AzureADMultipleOrgs"
api {
mapped_claims_enabled = true
requested_access_token_version = 2
known_client_applications = [
azuread_application.known1.application_id,
azuread_application.known2.application_id,
]
oauth2_permission_scope {
admin_consent_description = "Allow the application to access example on behalf of the signed-in user."
admin_consent_display_name = "Access example"
Expand Down Expand Up @@ -117,26 +125,40 @@ resource "azuread_application" "example" {

The following arguments are supported:

* `api` - (Optional) An `api` block as documented below, which configures API related settings for this Application.
* `api` - (Optional) An `api` block as documented below, which configures API related settings for this application.
* `app_role` - (Optional) A collection of `app_role` blocks as documented below. For more information see [official documentation on Application Roles](https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles).
* `device_only_auth_enabled` - (Optional) Specifies whether this application supports device authentication without a user. Defaults to `false`.
* `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.
* `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.
* `owners` - (Optional) A list of object IDs of principals that will be granted ownership of the application. It's recommended to specify the object ID of the authenticated principal running Terraform, to ensure sufficient permissions that the application can be subsequently updated.
* `prevent_duplicate_names` - (Optional) If `true`, will return an error if an existing application is found with the same name. Defaults to `false`.
* `privacy_statement_url` - (Optional) URL of the application's privacy statement.
* `public_client` - (Optional) A `public_client` block as documented below, which configures non-web app or non-web API application settings, for example mobile or other public clients such as an installed application running on a desktop device.
* `required_resource_access` - (Optional) A collection of `required_resource_access` blocks as documented below.
* `sign_in_audience` - (Optional) The Microsoft account types that are supported for the current application. Must be one of `AzureADMyOrg`, `AzureADMultipleOrgs`, `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount`. Defaults to `AzureADMyOrg`.
* `web` - (Optional) A `web` block as documented below, which configures web related settings for this Application.

~> **Changing `sign_in_audience` for existing applications** When updating an existing application to use a `sign_in_audience` value of `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount`, your configuration may no longer be valid. Refer to [official documentation](https://docs.microsoft.com/en-gb/azure/active-directory/develop/supported-accounts-validation) to understand the differences in supported configurations. Where possible, the provider will attempt to validate your configuration and try to avoid applying unsupported settings to your application.

* `single_page_application` - (Optional) A `single_page_application` block as documented below, which configures single-page application (SPA) related settings for this application.
* `support_url` - (Optional) URL of the application's support page.
* `terms_of_service_url` - (Optional) URL of the application's terms of service statement.
* `web` - (Optional) A `web` block as documented below, which configures web related settings for this application.

-> **Application Name Uniqueness** Application names are not unique within Azure Active Directory. Use the `prevent_duplicate_names` argument to check for existing applications if you want to avoid name collisions.

---

`api` block supports the following:

* `known_client_applications` - (Optional) A set of application IDs (client IDs), used for bundling consent if you have a solution that contains two parts: a client app and a custom web API app.
* `mapped_claims_enabled` - (Optional) Allows an application to use claims mapping without specifying a custom signing key. Defaults to `false`.
* `oauth2_permission_scope` - (Optional) One or more `oauth2_permission_scope` blocks as documented below, to describe delegated permissions exposed by the web API represented by this application.
* `requested_access_token_version` - (Optional) The access token version expected by this resource. Must be one of `1` or `2`, and must be `2` when `sign_in_audience` is either `AzureADandPersonalMicrosoftAccount` or `PersonalMicrosoftAccount` Defaults to `1`.

---

Expand Down Expand Up @@ -193,6 +215,12 @@ The following arguments are supported:

---

`public_client` block supports the following:

* `redirect_uris` - (Optional) A set of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.

---

`required_resource_access` block supports the following:

* `resource_access` - (Required) A collection of `resource_access` blocks as documented below, describing OAuth2.0 permission scopes and app roles that the application requires from the specified resource.
Expand All @@ -209,12 +237,18 @@ The following arguments are supported:

---

`single_page_application` block supports the following:

* `redirect_uris` - (Optional) A set of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.

---

`web` block supports the following:

* `homepage_url` - (Optional) Home page or landing page of the application.
* `implicit_grant` - (Optional) An `implicit_grant` block as documented above.
* `logout_url` - (Optional) The URL that will be used by Microsoft's authorization service to sign out a user using front-channel, back-channel or SAML logout protocols.
* `redirect_uris` - (Optional) A list of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.
* `redirect_uris` - (Optional) A set of URLs where user tokens are sent for sign-in, or the redirect URIs where OAuth 2.0 authorization codes and access tokens are sent.

---

Expand All @@ -227,8 +261,18 @@ The following arguments are supported:

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

* `app_role_ids` - A mapping of app role values to app role IDs, intended to be useful when referencing app roles in other resources in your configuration.
* `application_id` - The Application ID (also called Client ID).
* `disabled_by_microsoft` - Whether Microsoft has disabled the registered application. If the application is disabled, this will be a string indicating the status/reason, e.g. `DisabledDueToViolationOfServicesAgreement`
* `oauth2_permission_scope_ids` - A mapping of OAuth2.0 permission scope values to scope IDs, intended to be useful when referencing permission scopes in other resources in your configuration.
* `object_id` - The application's object ID.
* `publisher_domain` - The verified publisher domain for the application.

---

`info` block exports the following:

* `logo_url` - CDN URL to the application's logo.

## Import

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.17.0
github.com/manicminer/hamilton v0.20.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.17.0 h1:6QEvPW1GyCiJ0ZJmpnOv0XHgce4TQtAocPBkxHNyFp4=
github.com/manicminer/hamilton v0.17.0/go.mod h1:y0lB5Ey1UesBkFa9NAtybwWPoN4v1SbY1Chp3OqGtN4=
github.com/manicminer/hamilton v0.20.0 h1:3FmCr3vKtkBSTkhawtVKgyzQNeWZftVHQhgh/GASUI8=
github.com/manicminer/hamilton v0.20.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
24 changes: 24 additions & 0 deletions internal/helpers/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import (
"github.com/manicminer/hamilton/msgraph"
)

func ApplicationFlattenAppRoleIDs(in *[]msgraph.AppRole) map[string]string {
result := make(map[string]string)
if in != nil {
for _, role := range *in {
if role.Value != nil && *role.Value != "" && role.ID != nil {
result[*role.Value] = *role.ID
}
}
}
return result
}

func ApplicationFlattenAppRoles(in *[]msgraph.AppRole) (result []map[string]interface{}) {
if in == nil {
return
Expand Down Expand Up @@ -49,6 +61,18 @@ func ApplicationFlattenAppRoles(in *[]msgraph.AppRole) (result []map[string]inte
return //nolint:nakedret
}

func ApplicationFlattenOAuth2PermissionScopeIDs(in *[]msgraph.PermissionScope) map[string]string {
result := make(map[string]string)
if in != nil {
for _, scope := range *in {
if scope.Value != nil && *scope.Value != "" && scope.ID != nil {
result[*scope.Value] = *scope.ID
}
}
}
return result
}

func ApplicationFlattenOAuth2PermissionScopes(in *[]msgraph.PermissionScope) (result []map[string]interface{}) {
if in == nil {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log"
"net/http"
"strings"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down Expand Up @@ -151,7 +152,7 @@ func applicationCertificateResourceCreate(ctx context.Context, d *schema.Resourc
newCredentials := make([]msgraph.KeyCredential, 0)
if app.KeyCredentials != nil {
for _, cred := range *app.KeyCredentials {
if cred.KeyId != nil && *cred.KeyId == *credential.KeyId {
if cred.KeyId != nil && strings.EqualFold(*cred.KeyId, *credential.KeyId) {
return tf.ImportAsExistsDiag("azuread_application_certificate", id.String())
}
newCredentials = append(newCredentials, cred)
Expand Down Expand Up @@ -194,7 +195,7 @@ func applicationCertificateResourceRead(ctx context.Context, d *schema.ResourceD
var credential *msgraph.KeyCredential
if app.KeyCredentials != nil {
for _, cred := range *app.KeyCredentials {
if cred.KeyId != nil && *cred.KeyId == id.KeyId {
if cred.KeyId != nil && strings.EqualFold(*cred.KeyId, id.KeyId) {
credential = &cred
break
}
Expand Down Expand Up @@ -248,7 +249,7 @@ func applicationCertificateResourceDelete(ctx context.Context, d *schema.Resourc
newCredentials := make([]msgraph.KeyCredential, 0)
if app.KeyCredentials != nil {
for _, cred := range *app.KeyCredentials {
if cred.KeyId != nil && *cred.KeyId != id.KeyId {
if cred.KeyId != nil && !strings.EqualFold(*cred.KeyId, id.KeyId) {
newCredentials = append(newCredentials, cred)
}
}
Expand Down
Loading

0 comments on commit 48f63a6

Please sign in to comment.