From d5ec11ce537a578653d30b85a54d95d91be4e631 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Wed, 9 Mar 2022 15:14:26 +0000 Subject: [PATCH] Bump Hamilton to v0.42.0 --- go.mod | 2 +- go.sum | 4 +- .../hamilton/internal/utils/pointers.go | 5 + .../hamilton/msgraph/claims_mapping_policy.go | 174 ++++++++++++++++++ .../manicminer/hamilton/msgraph/models.go | 12 +- .../hamilton/msgraph/serviceprincipals.go | 129 +++++++++++++ .../manicminer/hamilton/odata/odata.go | 2 +- vendor/modules.txt | 2 +- 8 files changed, 323 insertions(+), 7 deletions(-) create mode 100644 vendor/github.com/manicminer/hamilton/msgraph/claims_mapping_policy.go diff --git a/go.mod b/go.mod index ba4f68e99d..a83122c328 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-uuid v1.0.2 github.com/hashicorp/terraform-plugin-sdk/v2 v2.8.0 - github.com/manicminer/hamilton v0.41.1 + github.com/manicminer/hamilton v0.42.0 golang.org/x/text v0.3.6 ) diff --git a/go.sum b/go.sum index c2ca6a4d5f..43498c3770 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,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.41.1 h1:b9XVMIo2tnHBtl7sFTmake2BddbqriW2zdPKWmrxZsc= -github.com/manicminer/hamilton v0.41.1/go.mod h1:IOYn2Dc9SUiZ7Ryw6c8Ay795vPPMnrCZe3MktS447dc= +github.com/manicminer/hamilton v0.42.0 h1:qcQZ7mUd+luGYf/+587+yBKWcCX2YUDA6u396RgR3Oc= +github.com/manicminer/hamilton v0.42.0/go.mod h1:IOYn2Dc9SUiZ7Ryw6c8Ay795vPPMnrCZe3MktS447dc= 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= diff --git a/vendor/github.com/manicminer/hamilton/internal/utils/pointers.go b/vendor/github.com/manicminer/hamilton/internal/utils/pointers.go index 60545f6c28..fc7802079e 100644 --- a/vendor/github.com/manicminer/hamilton/internal/utils/pointers.go +++ b/vendor/github.com/manicminer/hamilton/internal/utils/pointers.go @@ -19,3 +19,8 @@ func Int32Ptr(i int32) *int32 { func StringPtr(s string) *string { return &s } + +// ArrayStringPtr returns a pointer to the provided array of strings. +func ArrayStringPtr(s []string) *[]string { + return &s +} diff --git a/vendor/github.com/manicminer/hamilton/msgraph/claims_mapping_policy.go b/vendor/github.com/manicminer/hamilton/msgraph/claims_mapping_policy.go new file mode 100644 index 0000000000..08e14b1c82 --- /dev/null +++ b/vendor/github.com/manicminer/hamilton/msgraph/claims_mapping_policy.go @@ -0,0 +1,174 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/manicminer/hamilton/odata" +) + +type ClaimsMappingPolicyClient struct { + BaseClient Client +} + +// NewClaimsMappingPolicyClient returns a new ClaimsMappingPolicyClient +func NewClaimsMappingPolicyClient(tenantId string) *ClaimsMappingPolicyClient { + return &ClaimsMappingPolicyClient{ + BaseClient: NewClient(Version10, tenantId), + } +} + +// Create creates a new ClaimsMappingPolicy. +func (c *ClaimsMappingPolicyClient) Create(ctx context.Context, policy ClaimsMappingPolicy) (*ClaimsMappingPolicy, int, error) { + var status int + + body, err := json.Marshal(policy) + if err != nil { + return nil, status, fmt.Errorf("json.Marshal(): %v", err) + } + + resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + OData: odata.Query{Metadata: odata.MetadataFull}, + ValidStatusCodes: []int{http.StatusCreated}, + Uri: Uri{ + Entity: "/policies/claimsMappingPolicies", + HasTenantId: false, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("ClaimsMappingPolicyClient.BaseClient.Post(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var newPolicy ClaimsMappingPolicy + if err := json.Unmarshal(respBody, &newPolicy); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &newPolicy, status, nil +} + +// List returns a list of ClaimsMappingPolicy, optionally queried using OData. +func (c *ClaimsMappingPolicyClient) List(ctx context.Context, query odata.Query) (*[]ClaimsMappingPolicy, int, error) { + query.Metadata = odata.MetadataFull + + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + DisablePaging: query.Top > 0, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/policies/claimsMappingPolicies", + HasTenantId: false, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("ClaimsMappingPolicyClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + ClaimsMappingPolicies []ClaimsMappingPolicy `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.ClaimsMappingPolicies, status, nil +} + +// Get retrieves a ClaimsMappingPolicy. +func (c *ClaimsMappingPolicyClient) Get(ctx context.Context, id string, query odata.Query) (*ClaimsMappingPolicy, int, error) { + query.Metadata = odata.MetadataFull + + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/claimsMappingPolicies/%s", id), + HasTenantId: false, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("ClaimsMappingPolicyClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var claimsMappingPolicies ClaimsMappingPolicy + if err := json.Unmarshal(respBody, &claimsMappingPolicies); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &claimsMappingPolicies, status, nil +} + +// Update amends an existing ClaimsMappingPolicy. +func (c *ClaimsMappingPolicyClient) Update(ctx context.Context, claimsMappingPolicy ClaimsMappingPolicy) (int, error) { + var status int + + if claimsMappingPolicy.ID == nil { + return status, fmt.Errorf("cannot update ClaimsMappingPolicy with nil ID") + } + + claimsMappingPolicyId := *claimsMappingPolicy.ID + claimsMappingPolicy.ID = nil + + body, err := json.Marshal(claimsMappingPolicy) + if err != nil { + return status, fmt.Errorf("json.Marshal(): %v", err) + } + + _, status, _, err = c.BaseClient.Patch(ctx, PatchHttpRequestInput{ + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{ + http.StatusOK, + http.StatusNoContent, + }, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/claimsMappingPolicies/%s", claimsMappingPolicyId), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("ClaimsMappingPolicy.BaseClient.Patch(): %v", err) + } + + return status, nil +} + +// Delete removes a ClaimsMappingPolicy. +func (c *ClaimsMappingPolicyClient) Delete(ctx context.Context, id string) (int, error) { + _, status, _, err := c.BaseClient.Delete(ctx, DeleteHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/claimsMappingPolicies/%s", id), + HasTenantId: false, + }, + }) + if err != nil { + return status, fmt.Errorf("ClaimsMappingPolicyClient.BaseClient.Delete(): %v", err) + } + + return status, nil +} diff --git a/vendor/github.com/manicminer/hamilton/msgraph/models.go b/vendor/github.com/manicminer/hamilton/msgraph/models.go index 95d83333e9..2533fedc78 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/models.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/models.go @@ -540,6 +540,14 @@ type BaseNamedLocation struct { ModifiedDateTime *time.Time `json:"modifiedDateTime,omitempty"` } +type ClaimsMappingPolicy struct { + DirectoryObject + Definition *[]string `json:"definition,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + IsOrganizationDefault *bool `json:"isOrganizationDefault,omitempty"` +} + type CloudAppSecurityControl struct { IsEnabled *bool `json:"isEnabled,omitempty"` CloudAppSecurityType *ConditionalAccessCloudAppSecuritySessionControlType `json:"cloudAppSecurityType,omitempty"` @@ -1250,8 +1258,8 @@ type ScopedRoleMembership struct { // ServicePrincipal describes a Service Principal object. type ServicePrincipal struct { DirectoryObject - Owners *Owners `json:"owners@odata.bind,omitempty"` - + Owners *Owners `json:"owners@odata.bind,omitempty"` + ClaimsMappingPolicies *[]ClaimsMappingPolicy `json:"claimsmappingpolicies@odata.bind,omitempty"` AccountEnabled *bool `json:"accountEnabled,omitempty"` AddIns *[]AddIn `json:"addIns,omitempty"` AlternativeNames *[]string `json:"alternativeNames,omitempty"` diff --git a/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go b/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go index 45fc367e64..1727d9b91d 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go @@ -348,6 +348,135 @@ func (c *ServicePrincipalsClient) RemoveOwners(ctx context.Context, servicePrinc return status, nil } +// AssignClaimsMappingPolicy assigns a claimsMappingPolicy to a servicePrincipal +func (c *ServicePrincipalsClient) AssignClaimsMappingPolicy(ctx context.Context, servicePrincipal *ServicePrincipal) (int, error) { + var status int + + if servicePrincipal.ID == nil { + return status, errors.New("cannot update service principal with nil ID") + } + if servicePrincipal.ClaimsMappingPolicies == nil { + return status, errors.New("cannot update service principal with nil ClaimsMappingPolicies") + } + + for _, policy := range *servicePrincipal.ClaimsMappingPolicies { + // don't fail if an owner already exists + checkPolicyAlreadyExists := func(resp *http.Response, o *odata.OData) bool { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) + } + return false + } + + body, err := json.Marshal(DirectoryObject{ODataId: policy.ODataId}) + if err != nil { + return status, fmt.Errorf("json.Marshal(): %v", err) + } + + _, status, _, err = c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + ValidStatusFunc: checkPolicyAlreadyExists, + Uri: Uri{ + Entity: fmt.Sprintf("/servicePrincipals/%s/claimsMappingPolicies/$ref", *servicePrincipal.ID), + HasTenantId: false, + }, + }) + if err != nil { + return status, fmt.Errorf("ServicePrincipalsClient.BaseClient.Post(): %v", err) + } + } + + return status, nil +} + +// ListClaimsMappingPolicy retrieves the claimsMappingPolicies assigned to the specified Service Principal. +// id is the object ID of the service principal. +func (c *ServicePrincipalsClient) ListClaimsMappingPolicy(ctx context.Context, id string) (*[]ClaimsMappingPolicy, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/servicePrincipals/%s/claimsMappingPolicies", id), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("ServicePrincipalsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + Policies []ClaimsMappingPolicy `json:"value"` + } + + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.Policies, status, nil +} + +// RemoveClaimsMappingPolicy removes a claimsMappingPolicy from a servicePrincipal +func (c *ServicePrincipalsClient) RemoveClaimsMappingPolicy(ctx context.Context, servicePrincipal *ServicePrincipal, policyIds *[]string) (int, error) { + var status int + + if policyIds == nil { + return status, errors.New("cannot remove, nil policyIds") + } + + assignedPolicies, _, err := c.ListClaimsMappingPolicy(ctx, *servicePrincipal.ID) + if err != nil { + return status, fmt.Errorf("ServicePrincipalsClient.BaseClient.ListClaimsMappingPolicy(): %v", err) + } + + if len(*assignedPolicies) == 0 { + return http.StatusNoContent, nil + } + + mapClaimsMappingPolicy := map[string]ClaimsMappingPolicy{} + for _, v := range *assignedPolicies { + mapClaimsMappingPolicy[*v.ID] = v + } + + for _, policyId := range *policyIds { + + // Check if policy is currently assigned + _, ok := mapClaimsMappingPolicy[policyId] + if !ok { + continue + } + + checkPolicyStatus := func(resp *http.Response, o *odata.OData) bool { + if resp != nil && resp.StatusCode == http.StatusNotFound && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorResourceDoesNotExist) + } + return false + } + + _, status, _, err = c.BaseClient.Delete(ctx, DeleteHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + ValidStatusFunc: checkPolicyStatus, + Uri: Uri{ + Entity: fmt.Sprintf("/servicePrincipals/%s/claimsMappingPolicies/%s/$ref", *servicePrincipal.ID, policyId), + HasTenantId: false, + }, + }) + if err != nil { + return status, fmt.Errorf("ServicePrincipalsClient.BaseClient.Delete(): %v", err) + } + } + + return status, nil +} + // ListGroupMemberships returns a list of Groups the Service Principal is member of, optionally queried using OData. func (c *ServicePrincipalsClient) ListGroupMemberships(ctx context.Context, id string, query odata.Query) (*[]Group, int, error) { resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ diff --git a/vendor/github.com/manicminer/hamilton/odata/odata.go b/vendor/github.com/manicminer/hamilton/odata/odata.go index cd1d31f383..38b4a76f4c 100644 --- a/vendor/github.com/manicminer/hamilton/odata/odata.go +++ b/vendor/github.com/manicminer/hamilton/odata/odata.go @@ -19,7 +19,7 @@ func (o Id) MarshalJSON() ([]byte, error) { u, err := url.Parse(id) if err != nil || u.Scheme == "" || u.Host == "" { - matches := regexp.MustCompile(`([a-zA-Z]+)\(['"]([^'"]+)['"]\)`).FindStringSubmatch(id) + matches := regexp.MustCompile(`([^()'"]+)\(['"]([^'"]+)['"]\)`).FindStringSubmatch(id) if len(matches) != 3 { return nil, fmt.Errorf("Marshaling odata.Id: could not match a GUID") } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3748d69d79..d8da21f184 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -229,7 +229,7 @@ github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash -# github.com/manicminer/hamilton v0.41.1 +# github.com/manicminer/hamilton v0.42.0 ## explicit; go 1.16 github.com/manicminer/hamilton/auth github.com/manicminer/hamilton/environments