Skip to content

Commit

Permalink
Review & small refactor
Browse files Browse the repository at this point in the history
- Remove `description` property as the API doesn't allow it to be set
- Move `azuread_claims_mapping_policy` into new package `Policies`
- Update and tidy docs
- Fix up ID parsing for policy assignments
  • Loading branch information
manicminer committed Apr 7, 2022
1 parent d5154d1 commit 5e92793
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 351 deletions.
16 changes: 7 additions & 9 deletions docs/resources/claims_mapping_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
subcategory: "Policies"
---

# Resource: claims_mapping_policy
# Resource: azuread_claims_mapping_policy

Manages a Claims Mapping Policy within Azure Active Directory.

Expand All @@ -17,7 +17,7 @@ When authenticated with a user principal, this resource requires one of the foll
## Example Usage

```terraform
resource "azuread_claims_mapping_policy" "test" {
resource "azuread_claims_mapping_policy" "my_policy" {
definition = [
jsonencode(
{
Expand All @@ -42,20 +42,18 @@ resource "azuread_claims_mapping_policy" "test" {
}
),
]
description = "hcl-created-policy"
display_name = "hcl-create-policy"
description = "Policy created with Terraform"
display_name = "My Policy"
}
```

## Argument Reference

The following arguments are supported:

* `definition` - (Required) The claims mapping policy. This is a JSON formatted
string, for which the [`jsonencode()` function](https://www.terraform.io/language/functions/jsonencode)
can be used.
* `definition` - (Required) The claims mapping policy. This is a JSON formatted string, for which the [`jsonencode()`](https://www.terraform.io/language/functions/jsonencode) function can be used.
* `description` - (Required) The description for this Claims Mapping Policy.
* `display_name` - (Required) The friendly name for this Claims Mapping Policy.
* `display_name` - (Required) The display name for this Claims Mapping Policy.

## Attributes Reference

Expand All @@ -68,5 +66,5 @@ In addition to all arguments above, the following attributes are exported:
Claims Mapping Policy can be imported using the `id`, e.g.

```shell
terraform import azuread_claims_mapping_policy.id 00000000-0000-0000-0000-000000000000
terraform import azuread_claims_mapping_policy.my_policy 00000000-0000-0000-0000-000000000000
```
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

---
subcategory: "Policies"
subcategory: "Service Principals"
---

# Resource: claims_mapping_policy_assignment
# Resource: azuread_service_principal_claims_mapping_policy_assignment

Manages a Claims Mapping Policy Assignment within Azure Active Directory.

Expand All @@ -18,7 +18,7 @@ When authenticated with a user principal, this resource requires one of the foll
## Example Usage

```terraform
resource "azuread_claims_mapping_policy_assignment" "app" {
resource "azuread_service_principal_claims_mapping_policy_assignment" "app" {
claims_mapping_policy_id = azuread_claims_mapping_policy.my_policy.id
service_principal_id = azuread_service_principal.my_principal.id
}
Expand All @@ -28,8 +28,8 @@ resource "azuread_claims_mapping_policy_assignment" "app" {

The following arguments are supported:

* `claims_mapping_policy_id` - (Required) The `id` of the claims mapping policy to assign.
* `service_principal_id` - (Required) The `id` of the service principal for the policy assignment.
* `claims_mapping_policy_id` - (Required) The ID of the claims mapping policy to assign.
* `service_principal_id` - (Required) The object ID of the service principal for the policy assignment.

## Attributes Reference

Expand All @@ -39,8 +39,8 @@ In addition to all arguments above, the following attributes are exported:

## Import

Claims Mapping Policy can be imported using the `id`, in the form `service-principal-uuid/azuread_claims_mapping_policy/claims-mapping-policy-uuid`, e.g:
Claims Mapping Policy can be imported using the `id`, in the form `service-principal-uuid/claimsMappingPolicy/claims-mapping-policy-uuid`, e.g:

```shell
terraform import azuread_claims_mapping_policy_assignment.app 00000000-0000-0000-0000-000000000000/azuread_claims_mapping_policy/00000000-0000-0000-0000-000000000000
terraform import azuread_service_principal_claims_mapping_policy_assignment.app 00000000-0000-0000-0000-000000000000/claimsMappingPolicy/11111111-0000-0000-0000-000000000000
```
3 changes: 3 additions & 0 deletions internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
domains "github.com/hashicorp/terraform-provider-azuread/internal/services/domains/client"
groups "github.com/hashicorp/terraform-provider-azuread/internal/services/groups/client"
invitations "github.com/hashicorp/terraform-provider-azuread/internal/services/invitations/client"
policies "github.com/hashicorp/terraform-provider-azuread/internal/services/policies/client"
serviceprincipals "github.com/hashicorp/terraform-provider-azuread/internal/services/serviceprincipals/client"
users "github.com/hashicorp/terraform-provider-azuread/internal/services/users/client"
)
Expand All @@ -41,6 +42,7 @@ type Client struct {
Domains *domains.Client
Groups *groups.Client
Invitations *invitations.Client
Policies *policies.Client
ServicePrincipals *serviceprincipals.Client
Users *users.Client
}
Expand All @@ -56,6 +58,7 @@ func (client *Client) build(ctx context.Context, o *common.ClientOptions) error
client.DirectoryRoles = directoryroles.NewClient(o)
client.Groups = groups.NewClient(o)
client.Invitations = invitations.NewClient(o)
client.Policies = policies.NewClient(o)
client.ServicePrincipals = serviceprincipals.NewClient(o)
client.Users = users.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 @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform-provider-azuread/internal/services/domains"
"github.com/hashicorp/terraform-provider-azuread/internal/services/groups"
"github.com/hashicorp/terraform-provider-azuread/internal/services/invitations"
"github.com/hashicorp/terraform-provider-azuread/internal/services/policies"
"github.com/hashicorp/terraform-provider-azuread/internal/services/serviceprincipals"
"github.com/hashicorp/terraform-provider-azuread/internal/services/users"
)
Expand All @@ -23,6 +24,7 @@ func SupportedServices() []ServiceRegistration {
domains.Registration{},
groups.Registration{},
invitations.Registration{},
policies.Registration{},
serviceprincipals.Registration{},
users.Registration{},
}
Expand Down
132 changes: 132 additions & 0 deletions internal/services/policies/claims_mapping_policy_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package policies

import (
"context"
"fmt"
"log"
"net/http"

"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azuread/internal/clients"
"github.com/hashicorp/terraform-provider-azuread/internal/tf"
"github.com/hashicorp/terraform-provider-azuread/internal/utils"
"github.com/manicminer/hamilton/msgraph"
"github.com/manicminer/hamilton/odata"
)

func claimsMappingPolicyResource() *schema.Resource {
return &schema.Resource{
CreateContext: claimsMappingPolicyResourceCreate,
ReadContext: claimsMappingPolicyResourceRead,
UpdateContext: claimsMappingPolicyResourceUpdate,
DeleteContext: claimsMappingPolicyResourceDelete,

Importer: tf.ValidateResourceIDPriorToImport(func(id string) error {
if _, err := uuid.ParseUUID(id); err != nil {
return fmt.Errorf("specified ID (%q) is not valid: %s", id, err)
}
return nil
}),

Schema: map[string]*schema.Schema{
"definition": {
Description: "A string collection containing a JSON string that defines the rules and settings for this policy",
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"display_name": {
Description: "Display name for this policy",
Type: schema.TypeString,
Required: true,
},
},
}
}

func claimsMappingPolicyResourceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*clients.Client).Policies.ClaimsMappingPolicyClient

claimsMappingPolicy := msgraph.ClaimsMappingPolicy{
Definition: tf.ExpandStringSlicePtr(d.Get("definition").([]interface{})),
DisplayName: utils.String(d.Get("display_name").(string)),
}
policy, _, err := client.Create(ctx, claimsMappingPolicy)
if err != nil {
return tf.ErrorDiagF(err, "Could not create Claims Mapping Policy")
}

if policy.ID == nil || *policy.ID == "" {
return tf.ErrorDiagF(fmt.Errorf("Object ID returned for Claims Mapping Policy is nil"), "Bad API response")
}

d.SetId(*policy.ID)

return claimsMappingPolicyResourceRead(ctx, d, meta)
}

func claimsMappingPolicyResourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*clients.Client).Policies.ClaimsMappingPolicyClient
objectId := d.Id()

policy, status, err := client.Get(ctx, objectId, odata.Query{})
if err != nil {
if status == http.StatusNotFound {
log.Printf("[DEBUG] Claims Mapping Policy with Object ID %q was not found - removing from state!", objectId)
d.SetId("")
return nil
}

return tf.ErrorDiagF(err, "retrieving Claims Mapping Policy with object ID: %q", d.Id())
}

tf.Set(d, "definition", policy.Definition)
tf.Set(d, "display_name", policy.DisplayName)

return nil
}

func claimsMappingPolicyResourceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*clients.Client).Policies.ClaimsMappingPolicyClient
objectId := d.Id()

claimsMappingPolicy := msgraph.ClaimsMappingPolicy{
DirectoryObject: msgraph.DirectoryObject{
ID: &objectId,
},
Definition: tf.ExpandStringSlicePtr(d.Get("definition").([]interface{})),
DisplayName: utils.String(d.Get("display_name").(string)),
}
_, err := client.Update(ctx, claimsMappingPolicy)
if err != nil {
return tf.ErrorDiagF(err, "Could not update Claims Mapping Policy with object ID %q", objectId)
}

return claimsMappingPolicyResourceRead(ctx, d, meta)
}

func claimsMappingPolicyResourceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*clients.Client).Policies.ClaimsMappingPolicyClient
objectId := d.Id()

_, status, err := client.Get(ctx, objectId, odata.Query{})
if err != nil {
if status == http.StatusNotFound {
return tf.ErrorDiagPathF(fmt.Errorf("Claims Mapping Policy was not found"), "id", "Retrieving Claims Mapping Policy with object ID %q", objectId)
}

return tf.ErrorDiagPathF(err, "id", "Retrieving Claims Mapping Policy with object ID %q", objectId)
}

status, err = client.Delete(ctx, objectId)
if err != nil {
return tf.ErrorDiagF(err, "Deleting Claims Mapping Policy with object ID %q, received status %d", objectId, status)
}

return nil
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package serviceprincipals_test
package policies_test

import (
"context"
"fmt"
"net/http"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand All @@ -15,60 +14,58 @@ import (
"github.com/manicminer/hamilton/odata"
)

type ServicePrincipalClaimsMappingPolicy struct{}
type ClaimsMappingPolicyResource struct{}

func TestClaimsMappingPolicy_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azuread_claims_mapping_policy", "test")
r := ServicePrincipalClaimsMappingPolicy{}
updatedRegex, _ := regexp.Compile(`updated`)
r := ClaimsMappingPolicyResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.basicClaimsMappingPolicy(data),
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.updateClaimsMappingPolicy(data),
Config: r.update(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("display_name").MatchesRegex(updatedRegex),
),
},
data.ImportStep(),
})
}

func (ServicePrincipalClaimsMappingPolicy) basicClaimsMappingPolicy(data acceptance.TestData) string {
func (ClaimsMappingPolicyResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azuread" {}
resource "azuread_claims_mapping_policy" "test" {
definition = [
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"false\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"employeeid\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\",\"JwtClaimType\":\"name\"},{\"Source\":\"company\",\"ID\":\"tenantcountry\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country\",\"JwtClaimType\":\"country\"}]}}"
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"false\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"employeeid\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\",\"JwtClaimType\":\"name\"},{\"Source\":\"company\",\"ID\":\"tenantcountry\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country\",\"JwtClaimType\":\"country\"}]}}"
]
description = "%[1]s"
display_name = "integration-%[1]s"
display_name = "acctest-%[1]s"
}
`, data.RandomString)
}

func (ServicePrincipalClaimsMappingPolicy) updateClaimsMappingPolicy(data acceptance.TestData) string {
func (ClaimsMappingPolicyResource) update(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azuread" {}
resource "azuread_claims_mapping_policy" "test" {
definition = [
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"employeeid\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\",\"JwtClaimType\":\"name\"},{\"Source\":\"company\",\"ID\":\"tenantcountry\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country\",\"JwtClaimType\":\"country\"}]}}"
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"employeeid\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\",\"JwtClaimType\":\"name\"},{\"Source\":\"company\",\"ID\":\"tenantcountry\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country\",\"JwtClaimType\":\"country\"}]}}"
]
description = "%[1]s updated"
display_name = "integration-%[1]s-updated"
display_name = "acctest-%[1]s-updated"
}
`, data.RandomString)
}

func (r ServicePrincipalClaimsMappingPolicy) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
client := clients.ServicePrincipals.ClaimsMappingPolicyClient
func (r ClaimsMappingPolicyResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
client := clients.Policies.ClaimsMappingPolicyClient
client.BaseClient.DisableRetries = true

exists := false
Expand Down
19 changes: 19 additions & 0 deletions internal/services/policies/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package client

import (
"github.com/hashicorp/terraform-provider-azuread/internal/common"
"github.com/manicminer/hamilton/msgraph"
)

type Client struct {
ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient
}

func NewClient(o *common.ClientOptions) *Client {
claimsMappingPolicyClient := msgraph.NewClaimsMappingPolicyClient(o.TenantID)
o.ConfigureClient(&claimsMappingPolicyClient.BaseClient)

return &Client{
ClaimsMappingPolicyClient: claimsMappingPolicyClient,
}
}
Loading

0 comments on commit 5e92793

Please sign in to comment.