Skip to content

Commit

Permalink
azuread_service_principal - support for AppRoleAssignmentRequired (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmeenhuis authored and katbyte committed Aug 21, 2019
1 parent 90fd56b commit 8078bf2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
29 changes: 29 additions & 0 deletions azuread/resource_service_principal.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func resourceServicePrincipal() *schema.Resource {
return &schema.Resource{
Create: resourceServicePrincipalCreate,
Read: resourceServicePrincipalRead,
Update: resourceServicePrincipalUpdate,
Delete: resourceServicePrincipalDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
Expand All @@ -34,6 +35,11 @@ func resourceServicePrincipal() *schema.Resource {
ValidateFunc: validate.UUID,
},

"app_role_assignment_required": {
Type: schema.TypeBool,
Optional: true,
},

"display_name": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -71,6 +77,11 @@ func resourceServicePrincipalCreate(d *schema.ResourceData, meta interface{}) er
// given there's no way to change it - we'll just default this to true
AccountEnabled: p.Bool(true),
}

if v, ok := d.GetOk("app_role_assignment_required"); ok {
properties.AppRoleAssignmentRequired = p.Bool(v.(bool))
}

if v, ok := d.GetOk("tags"); ok {
properties.Tags = tf.ExpandStringSlicePtr(v.(*schema.Set).List())
}
Expand All @@ -94,6 +105,23 @@ func resourceServicePrincipalCreate(d *schema.ResourceData, meta interface{}) er
return resourceServicePrincipalRead(d, meta)
}

func resourceServicePrincipalUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).servicePrincipalsClient
ctx := meta.(*ArmClient).StopContext

var properties graphrbac.ServicePrincipalUpdateParameters

if d.HasChange("app_role_assignment_required") {
properties.AppRoleAssignmentRequired = p.Bool(d.Get("app_role_assignment_required").(bool))
}

if _, err := client.Update(ctx, d.Id(), properties); err != nil {
return fmt.Errorf("Error patching Azure AD Service Principal with ID %q: %+v", d.Id(), err)
}

return resourceServicePrincipalRead(d, meta)
}

func resourceServicePrincipalRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).servicePrincipalsClient
ctx := meta.(*ArmClient).StopContext
Expand All @@ -113,6 +141,7 @@ func resourceServicePrincipalRead(d *schema.ResourceData, meta interface{}) erro
d.Set("application_id", app.AppID)
d.Set("display_name", app.DisplayName)
d.Set("object_id", app.ObjectID)
d.Set("app_role_assignment_required", app.AppRoleAssignmentRequired)

// tags doesn't exist as a property, so extract it
if err := d.Set("tags", app.Tags); err != nil {
Expand Down
51 changes: 50 additions & 1 deletion azuread/resource_service_principal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestAccAzureADServicePrincipal_basic(t *testing.T) {
resource.TestCheckResourceAttrSet(resourceName, "display_name"),
resource.TestCheckResourceAttrSet(resourceName, "application_id"),
resource.TestCheckResourceAttr(resourceName, "oauth2_permissions.#", "1"),
resource.TestCheckResourceAttr(resourceName, "app_role_assignment_required", "false"),
resource.TestCheckResourceAttr(resourceName, "oauth2_permissions.0.admin_consent_description", fmt.Sprintf("Allow the application to access %s on behalf of the signed-in user.", fmt.Sprintf("acctestApp-%s", id))),
resource.TestCheckResourceAttrSet(resourceName, "object_id"),
),
Expand All @@ -53,6 +54,7 @@ func TestAccAzureADServicePrincipal_complete(t *testing.T) {
Config: testAccADServicePrincipal_complete(id),
Check: resource.ComposeTestCheckFunc(
testCheckADServicePrincipalExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "app_role_assignment_required", "true"),
resource.TestCheckResourceAttr(resourceName, "tags.#", "3"),
resource.TestCheckResourceAttrSet(resourceName, "object_id"),
),
Expand All @@ -66,6 +68,52 @@ func TestAccAzureADServicePrincipal_complete(t *testing.T) {
})
}

func TestAccAzureADServicePrincipal_update(t *testing.T) {
resourceName := "azuread_service_principal.test"
id := uuid.New().String()
updatedId := uuid.New().String()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckADServicePrincipalDestroy,
Steps: []resource.TestStep{
{
Config: testAccADServicePrincipal_basic(id),
Check: resource.ComposeTestCheckFunc(
testCheckADServicePrincipalExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "display_name"),
resource.TestCheckResourceAttrSet(resourceName, "application_id"),
resource.TestCheckResourceAttr(resourceName, "app_role_assignment_required", "false"),
),
},
{
Config: testAccADServicePrincipal_complete(updatedId),
Check: resource.ComposeTestCheckFunc(
testCheckADServicePrincipalExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.#", "3"),
resource.TestCheckResourceAttrSet(resourceName, "object_id"),
resource.TestCheckResourceAttr(resourceName, "app_role_assignment_required", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccADServicePrincipal_basic(id),
Check: resource.ComposeTestCheckFunc(
testCheckADServicePrincipalExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "display_name"),
resource.TestCheckResourceAttrSet(resourceName, "application_id"),
resource.TestCheckResourceAttr(resourceName, "app_role_assignment_required", "false"),
),
},
},
})
}

func testCheckADServicePrincipalExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
Expand Down Expand Up @@ -131,7 +179,8 @@ resource "azuread_application" "test" {
}
resource "azuread_service_principal" "test" {
application_id = "${azuread_application.test.application_id}"
application_id = "${azuread_application.test.application_id}"
app_role_assignment_required = true
tags = ["test", "multiple", "CapitalS"]
}
Expand Down
10 changes: 7 additions & 3 deletions website/docs/r/service_principal.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ page_title: "Azure Active Directory: azuread_service_principal"
sidebar_current: "docs-azuread-resource-azuread-service-principal-x"
description: |-
Manages a Service Principal associated with an Application within Azure Active Directory.
---

# azuread_service_principal

Manages a Service Principal associated with an Application within Azure Active Directory.

-> **NOTE:** If you're authenticating using a Service Principal then it must have permissions to both `Read and write all applications` and `Sign in and read user profile` within the `Windows Azure Active Directory` API. Please see The [Granting a Service Principal permission to manage AAD](../auth/service_principal_configuration.html) for the required steps.
-> **NOTE:** If you're authenticating using a Service Principal then it must have permissions to both `Read and write all applications` and `Sign in and read user profile` within the `Windows Azure Active Directory` API. Please see The [Granting a Service Principal permission to manage AAD](../auth/service_principal_configuration.html) for the required steps.

## Example Usage

Expand All @@ -26,7 +25,8 @@ resource "azuread_application" "example" {
}
resource "azuread_service_principal" "example" {
application_id = "${azuread_application.example.application_id}"
application_id = "${azuread_application.example.application_id}"
app_role_assignment_required = false
tags = ["example", "tags", "here"]
}
Expand All @@ -38,6 +38,8 @@ The following arguments are supported:

* `application_id` - (Required) The ID of the Azure AD Application for which to create a Service Principal.

* `app_role_assignment_required` - (Optional) Does this Service Principal require an AppRoleAssignment to a user or group before Azure AD will issue a user or access token to the application? Defaults to `false`.

* `tags` - (Optional) A list of tags to apply to the Service Principal.

## Attributes Reference
Expand All @@ -52,6 +54,8 @@ The following attributes are exported:

* `display_name` - The Display Name of the Azure Active Directory Application associated with this Service Principal.

* `app_role_assignment_required` - Whether this Service Principal requires an AppRoleAssignment to a user or group before Azure AD will issue a user or access token to the application.

* `oauth2_permissions` - A collection of OAuth 2.0 permissions exposed by the associated application. Each permission is covered by a `oauth2_permission` block as documented below.

---
Expand Down

0 comments on commit 8078bf2

Please sign in to comment.