Skip to content

Commit

Permalink
Merge pull request #287 from terraform-providers/app/roles-scopes-dup…
Browse files Browse the repository at this point in the history
…-validation

azuread_application: validate values for app_role and oauth2_permissions to screen for duplicates
  • Loading branch information
manicminer authored Jun 30, 2020
2 parents 0c3fe0c + beb62b3 commit 9b56e0c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
42 changes: 42 additions & 0 deletions azuread/resource_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ func resourceApplicationCreate(d *schema.ResourceData, meta interface{}) error {
}
}

if err := adApplicationValidateRolesScopes(d.Get("app_role"), d.Get("oauth2_permissions")); err != nil {
return err
}

appType := d.Get("type")
identUrls, hasIdentUrls := d.GetOk("identifier_uris")
if appType == "native" {
Expand Down Expand Up @@ -420,6 +424,10 @@ func resourceApplicationUpdate(d *schema.ResourceData, meta interface{}) error {
}
}

if err := adApplicationValidateRolesScopes(d.Get("app_role"), d.Get("oauth2_permissions")); err != nil {
return err
}

var properties graphrbac.ApplicationUpdateParameters

if d.HasChange("name") {
Expand Down Expand Up @@ -928,3 +936,37 @@ func adApplicationSetOwnersTo(client graphrbac.ApplicationsClient, ctx context.C

return nil
}

func adApplicationValidateRolesScopes(appRoles, oauth2Permissions interface{}) error {
var values []string

if appRoles != nil {
for _, roleRaw := range appRoles.(*schema.Set).List() {
role := roleRaw.(map[string]interface{})
if val := role["value"].(string); val != "" {
values = append(values, val)
}
}
}

if oauth2Permissions != nil {
for _, scopeRaw := range oauth2Permissions.(*schema.Set).List() {
scope := scopeRaw.(map[string]interface{})
if val := scope["value"].(string); val != "" {
values = append(values, val)
}
}
}

encountered := make([]string, len(values))
for _, val := range values {
for _, en := range encountered {
if en == val {
return fmt.Errorf("validation failed: duplicate app_role / oauth2_permissions value found: %q", val)
}
}
encountered = append(encountered, val)
}

return nil
}
40 changes: 40 additions & 0 deletions azuread/resource_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,22 @@ func TestAccAzureADApplication_preventDuplicateNames(t *testing.T) {
})
}

func TestAccAzureADApplication_duplicateAppRolesOauth2PermissionsValues(t *testing.T) {
ri := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckADApplicationDestroy,
Steps: []resource.TestStep{
{
Config: testAccADApplication_duplicateAppRolesOauth2PermissionsValues(ri),
ExpectError: regexp.MustCompile("validation failed: duplicate app_role / oauth2_permissions value found:"),
},
},
})
}

func testCheckADApplicationExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
Expand Down Expand Up @@ -940,3 +956,27 @@ resource "azuread_application" "duplicate" {
}
`, testAccADApplication_basic(ri))
}

func testAccADApplication_duplicateAppRolesOauth2PermissionsValues(ri int) string {
return fmt.Sprintf(`
resource "azuread_application" "test" {
name = "acctest-APP-%[1]d"
app_role {
allowed_member_types = ["User"]
description = "Admins can manage roles and perform all task actions"
display_name = "Admin"
is_enabled = true
value = "administer"
}
oauth2_permissions {
admin_consent_description = "Administer the application"
admin_consent_display_name = "Administer"
is_enabled = true
type = "Admin"
value = "administer"
}
}
`, ri)
}
2 changes: 2 additions & 0 deletions website/docs/r/application.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ The following arguments are supported:

* `oauth2_permissions` - (Optional) A collection of OAuth 2.0 permission scopes that the web API (resource) app exposes to client apps. Each permission is covered by `oauth2_permissions` blocks as documented below.

-> **Note on roles and scopes/permissions:** in Azure Active Directory, roles (`app_role`) and scopes/permissions (`oauth2_permissions`) exported by an Application share the same namespace and cannot contain duplicate values. Terraform will attempt to detect this at plan time.

* `prevent_duplicate_names` - (Optional) If `true`, will return an error when an existing Application is found with the same name. Defaults to `false`.

---
Expand Down

0 comments on commit 9b56e0c

Please sign in to comment.