Skip to content

Commit

Permalink
Merge pull request #584 from hashicorp/feature/app-role-assignments
Browse files Browse the repository at this point in the history
New resource: `azuread_app_role_assignment`
  • Loading branch information
manicminer authored Sep 22, 2021
2 parents 4d82e05 + ba06ff6 commit 3247ffb
Show file tree
Hide file tree
Showing 15 changed files with 891 additions and 13 deletions.
1 change: 1 addition & 0 deletions .teamcity/components/project.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const val providerName = "azuread"

var services = mapOf(
"applications" to "Applications",
"approleassignments" to "App Role Assignments",
"conditionalaccess" to "Conditional Access",
"directoryroles" to "Directory Roles",
"domains" to "Domains",
Expand Down
174 changes: 174 additions & 0 deletions docs/resources/app_role_assignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
subcategory: "App Role Assignments"
---

# Resource: azuread_app_role_assignment

Manages an app role assignment for a group, user or service principal. Can be used to grant admin consent for application permissions.

## API Permissions

The following API permissions are required in order to use this resource.

When authenticated with a service principal, this resource requires one of the following application roles: `AppRoleAssignment.ReadWrite.All` and `Application.Read.All`, or `AppRoleAssignment.ReadWrite.All` and `Directory.Read.All`, or `Application.ReadWrite.All`, or `Directory.ReadWrite.All`

When authenticated with a user principal, this resource requires one of the following directory roles: `Application Administrator` or `Global Administrator`

## Example Usage

*App role assignment for accessing Microsoft Graph*

```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"
}
}
}
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
}
resource "azuread_app_role_assignment" "example" {
app_role_id = azuread_service_principal.msgraph.app_role_ids["User.Read.All"]
principal_object_id = azuread_service_principal.example.object_id
resource_object_id = azuread_service_principal.msgraph.object_id
}
```

*App role assignment for internal application*

```terraform
resource "azuread_application" "internal" {
display_name = "internal"
app_role {
allowed_member_types = ["Application"]
description = "Apps can query the database"
display_name = "Query"
enabled = true
id = "00000000-0000-0000-0000-111111111111"
value = "Query.All"
}
}
resource "azuread_service_principal" "internal" {
application_id = azuread_application.internal.application_id
}
resource "azuread_application" "example" {
display_name = "example"
required_resource_access {
resource_app_id = azuread_application.internal.application_id
resource_access {
id = azuread_service_principal.internal.app_role_ids["Query.All"]
type = "Role"
}
}
}
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
}
resource "azuread_app_role_assignment" "example" {
app_role_id = azuread_service_principal.internal.app_role_ids["Query.All"]
principal_object_id = azuread_service_principal.example.object_id
resource_object_id = azuread_service_principal.internal.object_id
}
```

*Assign a user and group to an internal application*

```terraform
data "azuread_domains" "example" {
only_initial = true
}
resource "azuread_application" "internal" {
display_name = "internal"
app_role {
allowed_member_types = ["Application", "User"]
description = "Admins can perform all task actions"
display_name = "Admin"
enabled = true
id = "00000000-0000-0000-0000-222222222222"
value = "Admin.All"
}
}
resource "azuread_service_principal" "internal" {
application_id = azuread_application.internal.application_id
}
resource "azuread_group" "example" {
display_name = "example"
security_enabled = true
}
resource "azuread_app_role_assignment" "example" {
app_role_id = azuread_service_principal.internal.app_role_ids["Admin.All"]
principal_object_id = azuread_group.example.object_id
resource_object_id = azuread_service_principal.internal.object_id
}
resource "azuread_user" "example" {
display_name = "D. Duck"
password = "SecretP@sswd99!"
user_principal_name = "d.duck@${data.azuread_domains.example.domains.0.domain_name}"
}
resource "azuread_app_role_assignment" "example" {
app_role_id = azuread_service_principal.internal.app_role_ids["Admin.All"]
principal_object_id = azuread_user.example.object_id
resource_object_id = azuread_service_principal.internal.object_id
}
```

## Argument Reference

The following arguments are supported:

* `app_role_id` - (Required) The ID of the app role to be assigned. Changing this forces a new resource to be created.
* `principal_object_id` - (Required) The object ID of the user, group or service principal to be assigned this app role. Supported object types are Users, Groups or Service Principals. Changing this forces a new resource to be created.
* `resource_object_id` - (Required) The object ID of the service principal representing the resource. Changing this forces a new resource to be created.

## Attributes Reference

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

* `principal_display_name` - The display name of the principal to which the app role is assigned.
* `principal_type` - The object type of the principal to which the app role is assigned.
* `resource_display_name` - The display name of the application representing the resource.

## Import

App role assignments can be imported using the object ID of the service principal representing the resource and the ID of the app role assignment (note: _not_ the ID of the app role), e.g.

```shell
terraform import azuread_app_role_assignment.example 00000000-0000-0000-0000-000000000000/appRoleAssignment/aaBBcDDeFG6h5JKLMN2PQrrssTTUUvWWxxxxxyyyzzz
```

-> This ID format is unique to Terraform and is composed of the Resource Service Principal Object ID and the ID of the App Role Assignment in the format `{ResourcePrincipalID}/appRoleAssignment/{AppRoleAssignmentID}`.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 // indirect
github.com/klauspost/compress v1.12.2 // indirect
github.com/manicminer/hamilton v0.29.0
github.com/manicminer/hamilton v0.30.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 @@ -285,8 +285,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.29.0 h1:SmKNUMbuk7Crp9mJUWJTNRKnsFzdIxyIhlvvJ0HjCGk=
github.com/manicminer/hamilton v0.29.0/go.mod h1:QryxpD/4+cdKuXNi0UjLDvgxYdP0LLmYz7dYU7DAX4U=
github.com/manicminer/hamilton v0.30.0 h1:n7og9/Xh4d/JX0XG0uG1rv2vlkIkz8jwynCWoQszZvA=
github.com/manicminer/hamilton v0.30.0/go.mod h1:QryxpD/4+cdKuXNi0UjLDvgxYdP0LLmYz7dYU7DAX4U=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
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=
Expand Down
19 changes: 11 additions & 8 deletions internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/hashicorp/terraform-provider-azuread/internal/common"
applications "github.com/hashicorp/terraform-provider-azuread/internal/services/applications/client"
approleassignments "github.com/hashicorp/terraform-provider-azuread/internal/services/approleassignments/client"
conditionalaccess "github.com/hashicorp/terraform-provider-azuread/internal/services/conditionalaccess/client"
directoryroles "github.com/hashicorp/terraform-provider-azuread/internal/services/directoryroles/client"
domains "github.com/hashicorp/terraform-provider-azuread/internal/services/domains/client"
Expand All @@ -29,20 +30,22 @@ type Client struct {

StopContext context.Context

Applications *applications.Client
ConditionalAccess *conditionalaccess.Client
DirectoryRoles *directoryroles.Client
Domains *domains.Client
Groups *groups.Client
Invitations *invitations.Client
ServicePrincipals *serviceprincipals.Client
Users *users.Client
Applications *applications.Client
AppRoleAssignments *approleassignments.Client
ConditionalAccess *conditionalaccess.Client
DirectoryRoles *directoryroles.Client
Domains *domains.Client
Groups *groups.Client
Invitations *invitations.Client
ServicePrincipals *serviceprincipals.Client
Users *users.Client
}

func (client *Client) build(ctx context.Context, o *common.ClientOptions) error {
client.StopContext = ctx

client.Applications = applications.NewClient(o)
client.AppRoleAssignments = approleassignments.NewClient(o)
client.Domains = domains.NewClient(o)
client.ConditionalAccess = conditionalaccess.NewClient(o)
client.DirectoryRoles = directoryroles.NewClient(o)
Expand Down
2 changes: 2 additions & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"github.com/hashicorp/terraform-provider-azuread/internal/services/applications"
"github.com/hashicorp/terraform-provider-azuread/internal/services/approleassignments"
"github.com/hashicorp/terraform-provider-azuread/internal/services/conditionalaccess"
"github.com/hashicorp/terraform-provider-azuread/internal/services/directoryroles"
"github.com/hashicorp/terraform-provider-azuread/internal/services/domains"
Expand All @@ -14,6 +15,7 @@ import (
func SupportedServices() []ServiceRegistration {
return []ServiceRegistration{
applications.Registration{},
approleassignments.Registration{},
conditionalaccess.Registration{},
directoryroles.Registration{},
domains.Registration{},
Expand Down
Loading

0 comments on commit 3247ffb

Please sign in to comment.