diff --git a/go.mod b/go.mod index 15033f8b2..d14fc92ea 100644 --- a/go.mod +++ b/go.mod @@ -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.28.2 + github.com/manicminer/hamilton v0.29.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 diff --git a/go.sum b/go.sum index b760b34f0..4e3103f81 100644 --- a/go.sum +++ b/go.sum @@ -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.28.2 h1:W+ZRftPTOgWAa9zr3bUW1CzU1yOMFz1ZumHcA5kXqes= -github.com/manicminer/hamilton v0.28.2/go.mod h1:QryxpD/4+cdKuXNi0UjLDvgxYdP0LLmYz7dYU7DAX4U= +github.com/manicminer/hamilton v0.29.0 h1:SmKNUMbuk7Crp9mJUWJTNRKnsFzdIxyIhlvvJ0HjCGk= +github.com/manicminer/hamilton v0.29.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= diff --git a/vendor/github.com/manicminer/hamilton/msgraph/applications.go b/vendor/github.com/manicminer/hamilton/msgraph/applications.go index a7effa11e..158aeaaee 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/applications.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/applications.go @@ -161,9 +161,22 @@ func (c *ApplicationsClient) Update(ctx context.Context, application Application return status, fmt.Errorf("json.Marshal(): %v", err) } + checkApplicationConsistency := func(resp *http.Response, o *odata.OData) bool { + if resp == nil { + return false + } + if resp.StatusCode == http.StatusNotFound { + return true + } + if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorCannotDeleteOrUpdateEnabledEntitlement) + } + return false + } + _, status, _, err = c.BaseClient.Patch(ctx, PatchHttpRequestInput{ Body: body, - ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ConsistencyFailureFunc: checkApplicationConsistency, ValidStatusCodes: []int{http.StatusNoContent}, Uri: Uri{ Entity: fmt.Sprintf("/applications/%s", *application.ID), @@ -428,7 +441,7 @@ func (c *ApplicationsClient) AddOwners(ctx context.Context, application *Applica for _, owner := range *application.Owners { // don't fail if an owner already exists checkOwnerAlreadyExists := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) } return false @@ -478,7 +491,7 @@ func (c *ApplicationsClient) RemoveOwners(ctx context.Context, applicationId str // despite the above check, sometimes owners are just gone checkOwnerGone := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorRemovedObjectReferencesDoNotExist) } return false @@ -583,3 +596,24 @@ func (c *ApplicationsClient) DeleteExtension(ctx context.Context, applicationId, return status, nil } + +// UploadLogo uploads the application logo which should be a gif, jpeg or png image +func (c *ApplicationsClient) UploadLogo(ctx context.Context, applicationId, contentType string, logoData []byte) (int, error) { + var status int + + _, status, _, err := c.BaseClient.Put(ctx, PutHttpRequestInput{ + Body: logoData, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ContentType: contentType, + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/applications/%s/logo", applicationId), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("ApplicationsClient.BaseClient.Put(): %v", err) + } + + return status, nil +} diff --git a/vendor/github.com/manicminer/hamilton/msgraph/client.go b/vendor/github.com/manicminer/hamilton/msgraph/client.go index 6c032205c..1eee9f9b5 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/client.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/client.go @@ -44,6 +44,7 @@ type ValidStatusFunc func(*http.Response, *odata.OData) bool // HttpRequestInput is any type that can validate the response to an HTTP request. type HttpRequestInput interface { GetConsistencyFailureFunc() ConsistencyFailureFunc + GetContentType() string GetValidStatusCodes() []int GetValidStatusFunc() ValidStatusFunc } @@ -140,7 +141,7 @@ func (c Client) performRequest(req *http.Request, input HttpRequestInput) (*http } req.Header.Add("Accept", "application/json") - req.Header.Add("Content-Type", "application/json; charset=utf-8") + req.Header.Add("Content-Type", input.GetContentType()) //req.Header.Add("ConsistencyLevel", "eventual") if c.UserAgent != "" { @@ -265,6 +266,11 @@ func (i DeleteHttpRequestInput) GetConsistencyFailureFunc() ConsistencyFailureFu return i.ConsistencyFailureFunc } +// GetContentType returns the content type for the request, currently only application/json is supported +func (i DeleteHttpRequestInput) GetContentType() string { + return "application/json; charset=utf-8" +} + // GetValidStatusCodes returns a []int of status codes considered valid for a DELETE request. func (i DeleteHttpRequestInput) GetValidStatusCodes() []int { return i.ValidStatusCodes @@ -308,6 +314,11 @@ func (i GetHttpRequestInput) GetConsistencyFailureFunc() ConsistencyFailureFunc return i.ConsistencyFailureFunc } +// GetContentType returns the content type for the request, currently only application/json is supported +func (i GetHttpRequestInput) GetContentType() string { + return "application/json; charset=utf-8" +} + // GetValidStatusCodes returns a []int of status codes considered valid for a GET request. func (i GetHttpRequestInput) GetValidStatusCodes() []int { return i.ValidStatusCodes @@ -421,6 +432,11 @@ func (i PatchHttpRequestInput) GetConsistencyFailureFunc() ConsistencyFailureFun return i.ConsistencyFailureFunc } +// GetContentType returns the content type for the request, currently only application/json is supported +func (i PatchHttpRequestInput) GetContentType() string { + return "application/json; charset=utf-8" +} + // GetValidStatusCodes returns a []int of status codes considered valid for a PATCH request. func (i PatchHttpRequestInput) GetValidStatusCodes() []int { return i.ValidStatusCodes @@ -463,6 +479,11 @@ func (i PostHttpRequestInput) GetConsistencyFailureFunc() ConsistencyFailureFunc return i.ConsistencyFailureFunc } +// GetContentType returns the content type for the request, currently only application/json is supported +func (i PostHttpRequestInput) GetContentType() string { + return "application/json; charset=utf-8" +} + // GetValidStatusCodes returns a []int of status codes considered valid for a POST request. func (i PostHttpRequestInput) GetValidStatusCodes() []int { return i.ValidStatusCodes @@ -494,6 +515,7 @@ func (c Client) Post(ctx context.Context, input PostHttpRequestInput) (*http.Res // PutHttpRequestInput configures a PUT request. type PutHttpRequestInput struct { ConsistencyFailureFunc ConsistencyFailureFunc + ContentType string Body []byte ValidStatusCodes []int ValidStatusFunc ValidStatusFunc @@ -505,6 +527,14 @@ func (i PutHttpRequestInput) GetConsistencyFailureFunc() ConsistencyFailureFunc return i.ConsistencyFailureFunc } +// GetContentType returns the content type for the request, defaults to application/json +func (i PutHttpRequestInput) GetContentType() string { + if i.ContentType != "" { + return i.ContentType + } + return "application/json; charset=utf-8" +} + // GetValidStatusCodes returns a []int of status codes considered valid for a PUT request. func (i PutHttpRequestInput) GetValidStatusCodes() []int { return i.ValidStatusCodes diff --git a/vendor/github.com/manicminer/hamilton/msgraph/directory_roles.go b/vendor/github.com/manicminer/hamilton/msgraph/directory_roles.go index 5612da1d5..98cffad40 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/directory_roles.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/directory_roles.go @@ -79,6 +79,33 @@ func (c *DirectoryRolesClient) Get(ctx context.Context, id string) (*DirectoryRo return &dirRole, status, nil } +// GetByTemplateId retrieves a DirectoryRole manifest for a DirectoryRoleTemplate id. +func (c *DirectoryRolesClient) GetByTemplateId(ctx context.Context, templateId string) (*DirectoryRole, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/directoryRoles/roleTemplateId=%s", templateId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("DirectoryRolesClient.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 dirRole DirectoryRole + if err := json.Unmarshal(respBody, &dirRole); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &dirRole, status, nil +} + // ListMembers retrieves the members of the specified directory role. // id is the object ID of the directory role. func (c *DirectoryRolesClient) ListMembers(ctx context.Context, id string) (*[]string, int, error) { @@ -133,17 +160,13 @@ func (c *DirectoryRolesClient) AddMembers(ctx context.Context, directoryRole *Di for _, member := range *directoryRole.Members { // don't fail if a member already exists checkMemberAlreadyExists := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) } return false } - body, err := json.Marshal(struct { - Member odata.Id `json:"@odata.id"` - }{ - Member: *member.ODataId, - }) + body, err := json.Marshal(DirectoryObject{ODataId: member.ODataId}) if err != nil { return status, fmt.Errorf("json.Marshal(): %v", err) } @@ -242,7 +265,7 @@ func (c *DirectoryRolesClient) Activate(ctx context.Context, roleTemplateID stri // don't fail if a role is already activated checkRoleAlreadyActivated := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorConflictingObjectPresentInDirectory) } return false diff --git a/vendor/github.com/manicminer/hamilton/msgraph/groups.go b/vendor/github.com/manicminer/hamilton/msgraph/groups.go index 816ee9f19..43e3de3a9 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/groups.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/groups.go @@ -63,7 +63,10 @@ func (c *GroupsClient) Create(ctx context.Context, group Group) (*Group, int, er } ownersNotReplicated := func(resp *http.Response, o *odata.OData) bool { - return o != nil && o.Error != nil && o.Error.Match(odata.ErrorResourceDoesNotExist) + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorResourceDoesNotExist) + } + return false } resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ @@ -398,17 +401,13 @@ func (c *GroupsClient) AddMembers(ctx context.Context, group *Group) (int, error for _, member := range *group.Members { // don't fail if an member already exists checkMemberAlreadyExists := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) } return false } - body, err := json.Marshal(struct { - Member odata.Id `json:"@odata.id"` - }{ - Member: *member.ODataId, - }) + body, err := json.Marshal(DirectoryObject{ODataId: member.ODataId}) if err != nil { return status, fmt.Errorf("json.Marshal(): %v", err) } @@ -452,7 +451,7 @@ func (c *GroupsClient) RemoveMembers(ctx context.Context, id string, memberIds * // despite the above check, sometimes members are just gone checkMemberGone := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorRemovedObjectReferencesDoNotExist) } return false @@ -564,17 +563,13 @@ func (c *GroupsClient) AddOwners(ctx context.Context, group *Group) (int, error) for _, owner := range *group.Owners { // don't fail if an owner already exists checkOwnerAlreadyExists := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) } return false } - body, err := json.Marshal(struct { - Owner odata.Id `json:"@odata.id"` - }{ - Owner: *owner.ODataId, - }) + body, err := json.Marshal(DirectoryObject{ODataId: owner.ODataId}) if err != nil { return status, fmt.Errorf("json.Marshal(): %v", err) } @@ -618,7 +613,7 @@ func (c *GroupsClient) RemoveOwners(ctx context.Context, id string, ownerIds *[] // despite the above check, sometimes owners are just gone checkOwnerGone := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorRemovedObjectReferencesDoNotExist) } return false diff --git a/vendor/github.com/manicminer/hamilton/msgraph/models.go b/vendor/github.com/manicminer/hamilton/msgraph/models.go index fed22147f..40c5be9e9 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/models.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/models.go @@ -1099,6 +1099,7 @@ type User struct { DisplayName *string `json:"displayName,omitempty"` EmployeeHireDate *time.Time `json:"employeeHireDate,omitempty"` EmployeeId *StringNullWhenEmpty `json:"employeeId,omitempty"` + EmployeeOrgData *EmployeeOrgData `json:"employeeOrgData,omitempty"` EmployeeType *string `json:"employeeType,omitempty"` ExternalUserState *string `json:"externalUserState,omitempty"` FaxNumber *StringNullWhenEmpty `json:"faxNumber,omitempty"` @@ -1255,3 +1256,8 @@ type WindowsHelloForBusinessAuthenticationMethod struct { ID *string `json:"id,omitempty"` KeyStrength *AuthenticationMethodKeyStrength `json:"authenticationMethodKeyStrength,omitempty"` } + +type EmployeeOrgData struct { + CostCenter *string `json:"costCenter,omitempty"` + Division *string `json:"division,omitempty"` +} diff --git a/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go b/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go index 8aefea256..8f10de725 100644 --- a/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go +++ b/vendor/github.com/manicminer/hamilton/msgraph/serviceprincipals.go @@ -64,7 +64,10 @@ func (c *ServicePrincipalsClient) Create(ctx context.Context, servicePrincipal S } appNotReplicated := func(resp *http.Response, o *odata.OData) bool { - return o != nil && o.Error != nil && o.Error.Match(odata.ErrorServicePrincipalInvalidAppId) + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorServicePrincipalInvalidAppId) + } + return false } resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ @@ -260,17 +263,13 @@ func (c *ServicePrincipalsClient) AddOwners(ctx context.Context, servicePrincipa for _, owner := range *servicePrincipal.Owners { // don't fail if an owner already exists checkOwnerAlreadyExists := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) } return false } - body, err := json.Marshal(struct { - Owner odata.Id `json:"@odata.id"` - }{ - Owner: *owner.ODataId, - }) + body, err := json.Marshal(DirectoryObject{ODataId: owner.ODataId}) if err != nil { return status, fmt.Errorf("json.Marshal(): %v", err) } @@ -314,7 +313,7 @@ func (c *ServicePrincipalsClient) RemoveOwners(ctx context.Context, servicePrinc // despite the above check, sometimes owners are just gone checkOwnerGone := func(resp *http.Response, o *odata.OData) bool { - if resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { return o.Error.Match(odata.ErrorRemovedObjectReferencesDoNotExist) } return false diff --git a/vendor/github.com/manicminer/hamilton/odata/odata.go b/vendor/github.com/manicminer/hamilton/odata/odata.go index 6c7f52936..83d7f2fcd 100644 --- a/vendor/github.com/manicminer/hamilton/odata/odata.go +++ b/vendor/github.com/manicminer/hamilton/odata/odata.go @@ -8,11 +8,12 @@ import ( ) const ( - ErrorAddedObjectReferencesAlreadyExist = "One or more added object references already exist" - ErrorConflictingObjectPresentInDirectory = "A conflicting object with one or more of the specified property values is present in the directory" - ErrorResourceDoesNotExist = "Resource '.+' does not exist or one of its queried reference-property objects are not present" - ErrorRemovedObjectReferencesDoNotExist = "One or more removed object references do not exist" - ErrorServicePrincipalInvalidAppId = "The appId '.+' of the service principal does not reference a valid application object" + ErrorAddedObjectReferencesAlreadyExist = "One or more added object references already exist" + ErrorCannotDeleteOrUpdateEnabledEntitlement = "Permission (scope or role) cannot be deleted or updated unless disabled first" + ErrorConflictingObjectPresentInDirectory = "A conflicting object with one or more of the specified property values is present in the directory" + ErrorResourceDoesNotExist = "Resource '.+' does not exist or one of its queried reference-property objects are not present" + ErrorRemovedObjectReferencesDoNotExist = "One or more removed object references do not exist" + ErrorServicePrincipalInvalidAppId = "The appId '.+' of the service principal does not reference a valid application object" ) type Id string diff --git a/vendor/modules.txt b/vendor/modules.txt index 65562dba1..377960408 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -192,7 +192,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.28.2 +# github.com/manicminer/hamilton v0.29.0 ## explicit github.com/manicminer/hamilton/auth github.com/manicminer/hamilton/environments