diff --git a/go.mod b/go.mod
index 2f1de60d88..49c951b477 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/hashicorp/go-uuid v1.0.3
 	github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0
 	github.com/hashicorp/terraform-plugin-testing v1.5.1
-	github.com/manicminer/hamilton v0.68.0
+	github.com/manicminer/hamilton v0.70.0
 	golang.org/x/text v0.14.0
 )
 
diff --git a/go.sum b/go.sum
index 23761cc43b..c6eace182f 100644
--- a/go.sum
+++ b/go.sum
@@ -111,8 +111,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 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.68.0 h1:2ZKQRTegktxJIoLBWxI43HczpTiwXl6brvwTXy75gPk=
-github.com/manicminer/hamilton v0.68.0/go.mod h1:u80g9rPtJpCG7EC0iayttt8UfeAp6jknClixgZGE950=
+github.com/manicminer/hamilton v0.70.0 h1:XMgVcwVtUGq2aBXqVAynaUDZdPXCXC8/rd7D5Zsg3UM=
+github.com/manicminer/hamilton v0.70.0/go.mod h1:u80g9rPtJpCG7EC0iayttt8UfeAp6jknClixgZGE950=
 github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
diff --git a/internal/services/directoryroles/directory_role_eligibility_schedule_request_resource_test.go b/internal/services/directoryroles/directory_role_eligibility_schedule_request_resource_test.go
index e4981be4d6..e8627e7ca7 100644
--- a/internal/services/directoryroles/directory_role_eligibility_schedule_request_resource_test.go
+++ b/internal/services/directoryroles/directory_role_eligibility_schedule_request_resource_test.go
@@ -19,13 +19,27 @@ import (
 
 type RoleEligibilityScheduleRequestResource struct{}
 
-func TestAccRoleEligibilityScheduleRequest_basic(t *testing.T) {
+func TestAccRoleEligibilityScheduleRequest_builtin(t *testing.T) {
 	data := acceptance.BuildTestData(t, "azuread_directory_role_eligibility_schedule_request", "test")
 	r := RoleEligibilityScheduleRequestResource{}
 
 	data.ResourceTest(t, r, []acceptance.TestStep{
 		{
-			Config: r.basic(data),
+			Config: r.builtin(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+			),
+		},
+	})
+}
+
+func TestAccRoleEligibilityScheduleRequest_custom(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azuread_directory_role_eligibility_schedule_request", "test")
+	r := RoleEligibilityScheduleRequestResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.custom(data),
 			Check: acceptance.ComposeTestCheckFunc(
 				check.That(data.ResourceName).ExistsInAzure(r),
 			),
@@ -48,7 +62,7 @@ func (r RoleEligibilityScheduleRequestResource) Exists(ctx context.Context, clie
 	return pointer.To(resr.ID != nil && *resr.ID == state.ID), nil
 }
 
-func (r RoleEligibilityScheduleRequestResource) basic(data acceptance.TestData) string {
+func (r RoleEligibilityScheduleRequestResource) builtin(data acceptance.TestData) string {
 	return fmt.Sprintf(`
 provider "azuread" {}
 
@@ -74,3 +88,36 @@ resource "azuread_directory_role_eligibility_schedule_request" "test" {
 }
 `, data.RandomInteger, data.RandomPassword)
 }
+
+func (r RoleEligibilityScheduleRequestResource) custom(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azuread" {}
+
+data "azuread_domains" "test" {
+  only_initial = true
+}
+
+resource "azuread_user" "test" {
+  user_principal_name = "acctestManager.%[1]d@${data.azuread_domains.test.domains.0.domain_name}"
+  display_name        = "acctestManager-%[1]d"
+  password            = "%[2]s"
+}
+
+resource "azuread_custom_directory_role" "test" {
+  display_name = "acctestCustomRole-%[1]d"
+  enabled      = true
+  version      = "1.0"
+
+  permissions {
+    allowed_resource_actions = ["microsoft.directory/applications/standard/read"]
+  }
+}
+
+resource "azuread_directory_role_eligibility_schedule_request" "test" {
+  role_definition_id = azuread_custom_directory_role.test.object_id
+  principal_id       = azuread_user.test.object_id
+  directory_scope_id = "/"
+  justification      = "abc"
+}
+`, data.RandomInteger, data.RandomPassword)
+}
diff --git a/internal/services/identitygovernance/access_package_assignment_policy_resource_test.go b/internal/services/identitygovernance/access_package_assignment_policy_resource_test.go
index 8e1ea7c69a..0215150035 100644
--- a/internal/services/identitygovernance/access_package_assignment_policy_resource_test.go
+++ b/internal/services/identitygovernance/access_package_assignment_policy_resource_test.go
@@ -76,6 +76,13 @@ func TestAccAccessPackageAssignmentPolicy_update(t *testing.T) {
 			),
 		},
 		data.ImportStep(),
+		{
+			Config: r.simple(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+			),
+		},
+		data.ImportStep(),
 		{
 			Config: r.complete(data),
 			Check: acceptance.ComposeTestCheckFunc(
diff --git a/internal/services/identitygovernance/identitygovernance.go b/internal/services/identitygovernance/identitygovernance.go
index bd77c36c0b..8142de5a6c 100644
--- a/internal/services/identitygovernance/identitygovernance.go
+++ b/internal/services/identitygovernance/identitygovernance.go
@@ -131,6 +131,17 @@ func expandAssignmentReviewSettings(input []interface{}) (*msgraph.AssignmentRev
 
 	result.Reviewers = expandUserSets(in["reviewer"].([]interface{}))
 
+	if result.AccessReviewTimeoutBehavior == "" &&
+		(result.DurationInDays == nil || *result.DurationInDays == 0) &&
+		(result.IsAccessRecommendationEnabled == nil || !*result.IsAccessRecommendationEnabled) &&
+		(result.IsApprovalJustificationRequired == nil || !*result.IsApprovalJustificationRequired) &&
+		(result.IsEnabled == nil || !*result.IsEnabled) &&
+		result.RecurrenceType == "" &&
+		result.ReviewerType == "" &&
+		(result.Reviewers == nil || len(*result.Reviewers) == 0) {
+		return nil, nil
+	}
+
 	return &result, nil
 }
 
diff --git a/vendor/github.com/manicminer/hamilton/msgraph/application_templates.go b/vendor/github.com/manicminer/hamilton/msgraph/application_templates.go
index ca24bf8c57..1aeac9db4b 100644
--- a/vendor/github.com/manicminer/hamilton/msgraph/application_templates.go
+++ b/vendor/github.com/manicminer/hamilton/msgraph/application_templates.go
@@ -95,8 +95,9 @@ func (c *ApplicationTemplatesClient) Instantiate(ctx context.Context, applicatio
 	}
 
 	resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{
-		Body:             body,
-		ValidStatusCodes: []int{http.StatusCreated},
+		Body:                   body,
+		ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
+		ValidStatusCodes:       []int{http.StatusCreated},
 		Uri: Uri{
 			Entity: fmt.Sprintf("/applicationTemplates/%s/instantiate", *applicationTemplate.ID),
 		},
diff --git a/vendor/github.com/manicminer/hamilton/msgraph/attribute_set.go b/vendor/github.com/manicminer/hamilton/msgraph/attribute_set.go
new file mode 100644
index 0000000000..05ded44645
--- /dev/null
+++ b/vendor/github.com/manicminer/hamilton/msgraph/attribute_set.go
@@ -0,0 +1,165 @@
+package msgraph
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+
+	"github.com/hashicorp/go-azure-sdk/sdk/odata"
+)
+
+const (
+	attributeSetEntity = "/directory/attributeSets"
+)
+
+type AttributeSetClient struct {
+	BaseClient Client
+}
+
+func NewAttributeSetClient() *AttributeSetClient {
+	return &AttributeSetClient{
+		BaseClient: NewClient(Version10),
+	}
+}
+
+func (c *AttributeSetClient) List(ctx context.Context, query odata.Query) (*[]AttributeSet, int, error) {
+	resp, status, _, err := c.BaseClient.Get(
+		ctx,
+		GetHttpRequestInput{
+			OData:            query,
+			ValidStatusCodes: []int{http.StatusOK},
+			Uri: Uri{
+				Entity: attributeSetEntity,
+			},
+		},
+	)
+	if err != nil {
+		return nil, status, fmt.Errorf("AttributeSet.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 {
+		AttributeSets []AttributeSet `json:"value"`
+	}
+
+	if err := json.Unmarshal(respBody, &data); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
+	}
+
+	return &data.AttributeSets, status, nil
+}
+
+func (c *AttributeSetClient) Create(ctx context.Context, attributeSet AttributeSet) (*AttributeSet, int, error) {
+	var status int
+	var newAttributeSet AttributeSet
+
+	body, err := json.Marshal(attributeSet)
+	if err != nil {
+		return nil, status, fmt.Errorf("json.Marshal(): %v", err)
+	}
+
+	requestInput := PostHttpRequestInput{
+		Body: body,
+		OData: odata.Query{
+			Metadata: odata.MetadataFull,
+		},
+		ValidStatusCodes: []int{
+			http.StatusCreated,
+			http.StatusOK,
+		},
+		Uri: Uri{
+			Entity: attributeSetEntity,
+		},
+	}
+
+	resp, status, _, err := c.BaseClient.Post(ctx, requestInput)
+	if err != nil {
+		return nil, status, fmt.Errorf("AttributeSetClient.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)
+	}
+
+	if err := json.Unmarshal(respBody, &newAttributeSet); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal():%v", err)
+	}
+
+	return &newAttributeSet, status, nil
+}
+
+func (c *AttributeSetClient) Get(ctx context.Context, id string, query odata.Query) (*AttributeSet, int, error) {
+	var AttributeSet AttributeSet
+
+	resp, status, _, err := c.BaseClient.Get(
+		ctx,
+		GetHttpRequestInput{
+			ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
+			OData:                  query,
+			ValidStatusCodes:       []int{http.StatusOK},
+			Uri: Uri{
+				Entity: fmt.Sprintf("%s/%s", attributeSetEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return nil, status, fmt.Errorf("AttributeSetClient.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)
+	}
+
+	if err := json.Unmarshal(respBody, &AttributeSet); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
+	}
+
+	return &AttributeSet, status, nil
+}
+
+func (c *AttributeSetClient) Update(ctx context.Context, AttributeSet AttributeSet) (int, error) {
+	var status int
+
+	if AttributeSet.ID == nil {
+		return status, fmt.Errorf("cannot update AttributeSet with a nil ID")
+	}
+
+	id := *AttributeSet.ID
+	AttributeSet.ID = nil
+
+	body, err := json.Marshal(AttributeSet)
+	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("%s/%s", attributeSetEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return status, fmt.Errorf("AttributeSetClient.BaseClient.Patch(): %v", err)
+	}
+
+	return status, nil
+}
diff --git a/vendor/github.com/manicminer/hamilton/msgraph/custom_security_attributes.go b/vendor/github.com/manicminer/hamilton/msgraph/custom_security_attributes.go
new file mode 100644
index 0000000000..d3337e783e
--- /dev/null
+++ b/vendor/github.com/manicminer/hamilton/msgraph/custom_security_attributes.go
@@ -0,0 +1,226 @@
+package msgraph
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+
+	"github.com/hashicorp/go-azure-sdk/sdk/odata"
+	"github.com/manicminer/hamilton/internal/utils"
+)
+
+const (
+	// customSecurityAttributeDefinitionEntity is a static string used by all methods on the
+	// CustomSecurityAttributeDefinitionClient struct
+	customSecurityAttributeDefinitionEntity = "/directory/customSecurityAttributeDefinitions"
+)
+
+// CustomSecurityAttributeDefinitionClient returns a BaseClient to enable interaction with the
+// graph API
+type CustomSecurityAttributeDefinitionClient struct {
+	BaseClient Client
+}
+
+// NewCustomSecurityAttributeDefinitionClient returns a new instance of
+// CustomSecurityAttributeDefinitionClient
+func NewCustomSecurityAttributeDefinitionClient() *CustomSecurityAttributeDefinitionClient {
+	return &CustomSecurityAttributeDefinitionClient{
+		BaseClient: NewClient(Version10),
+	}
+}
+
+// List returns a slice of CustomSecurityAttributeDefinition, the HTTP status code and any errors
+func (c *CustomSecurityAttributeDefinitionClient) List(ctx context.Context, query odata.Query) (*[]CustomSecurityAttributeDefinition, int, error) {
+	resp, status, _, err := c.BaseClient.Get(
+		ctx,
+		GetHttpRequestInput{
+			OData:            query,
+			ValidStatusCodes: []int{http.StatusOK},
+			Uri: Uri{
+				Entity: customSecurityAttributeDefinitionEntity,
+			},
+		},
+	)
+	if err != nil {
+		return nil, status, fmt.Errorf("CustomSecurityAttributeDefinition.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 {
+		CustomSecurityAttributeDefinitions []CustomSecurityAttributeDefinition `json:"value"`
+	}
+
+	if err := json.Unmarshal(respBody, &data); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
+	}
+
+	return &data.CustomSecurityAttributeDefinitions, status, nil
+}
+
+// Create will create a CustomSecurityAttributeDefinition and return the result, HTTP status code
+// as well as any errors
+func (c *CustomSecurityAttributeDefinitionClient) Create(ctx context.Context, customSecurityAttributeDefinition CustomSecurityAttributeDefinition) (*CustomSecurityAttributeDefinition, int, error) {
+	var status int
+	var newCustomSecurityAttributeDefinition CustomSecurityAttributeDefinition
+
+	body, err := json.Marshal(customSecurityAttributeDefinition)
+	if err != nil {
+		return nil, status, fmt.Errorf("json.Marshal(): %v", err)
+	}
+
+	requestInput := PostHttpRequestInput{
+		Body: body,
+		OData: odata.Query{
+			Metadata: odata.MetadataFull,
+		},
+		ValidStatusCodes: []int{http.StatusCreated},
+		Uri: Uri{
+			Entity: customSecurityAttributeDefinitionEntity,
+		},
+	}
+
+	resp, status, _, err := c.BaseClient.Post(ctx, requestInput)
+	if err != nil {
+		return nil, status, fmt.Errorf("CustomSecurityAttributeDefinitionClient.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)
+	}
+
+	if err := json.Unmarshal(respBody, &newCustomSecurityAttributeDefinition); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal():%v", err)
+	}
+
+	return &newCustomSecurityAttributeDefinition, status, nil
+}
+
+// Get returns a single CustomSecurityAttributeDefinition, HTTP status code, and any errors
+func (c *CustomSecurityAttributeDefinitionClient) Get(ctx context.Context, id string, query odata.Query) (*CustomSecurityAttributeDefinition, int, error) {
+	var customSecurityAttributeDefinition CustomSecurityAttributeDefinition
+
+	resp, status, _, err := c.BaseClient.Get(
+		ctx,
+		GetHttpRequestInput{
+			ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
+			OData:                  query,
+			ValidStatusCodes:       []int{http.StatusOK},
+			Uri: Uri{
+				Entity: fmt.Sprintf("%s/%s", customSecurityAttributeDefinitionEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return nil, status, fmt.Errorf("CustomSecurityAttributeDefinitionClient.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)
+	}
+
+	if err := json.Unmarshal(respBody, &customSecurityAttributeDefinition); err != nil {
+		return nil, status, fmt.Errorf("json.Unmarshal(): %v", err)
+	}
+
+	return &customSecurityAttributeDefinition, status, nil
+}
+
+// Update will update a single CustomSecurityAttributeDefinition entity returning the HTTP status
+// code and any errors
+func (c *CustomSecurityAttributeDefinitionClient) Update(ctx context.Context, customSecurityAttributeDefinition CustomSecurityAttributeDefinition) (int, error) {
+	var status int
+
+	if customSecurityAttributeDefinition.ID == nil {
+		return status, fmt.Errorf("cannot update customSecurityAttributeDefinition with a nil ID")
+	}
+
+	id := *customSecurityAttributeDefinition.ID
+	customSecurityAttributeDefinition.ID = nil
+
+	body, err := json.Marshal(customSecurityAttributeDefinition)
+	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("%s/%s", customSecurityAttributeDefinitionEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return status, fmt.Errorf("CustomSecurityAttributeDefinitionClient.BaseClient.Patch(): %v", err)
+	}
+
+	return status, nil
+}
+
+// Delete removes an instance of CustomSecurityAttributeDefinition by `id`
+func (c *CustomSecurityAttributeDefinitionClient) 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("%s/%s", customSecurityAttributeDefinitionEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return status, fmt.Errorf("CustomSecurityAttributeDefinitionClient.BaseClient.Delete(): %v", err)
+	}
+
+	return status, nil
+}
+
+func (c *CustomSecurityAttributeDefinitionClient) Deactivate(ctx context.Context, id string) (int, error) {
+	var status int
+	var customSecurityAttributeDefinition CustomSecurityAttributeDefinition
+
+	customSecurityAttributeDefinition.Status = utils.StringPtr("Deprecated")
+
+	body, err := json.Marshal(customSecurityAttributeDefinition)
+	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("%s/%s", customSecurityAttributeDefinitionEntity, id),
+			},
+		},
+	)
+	if err != nil {
+		return status, fmt.Errorf("customSecurityAttributeDefinitionClient.BaseClient.Patch(): %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 66d89bf9e4..d542facbca 100644
--- a/vendor/github.com/manicminer/hamilton/msgraph/models.go
+++ b/vendor/github.com/manicminer/hamilton/msgraph/models.go
@@ -64,7 +64,7 @@ type AccessPackageAssignmentRequest struct {
 
 type AccessPackageAssignmentPolicy struct {
 	AccessPackageId         *string                   `json:"accessPackageId,omitempty"`
-	AccessReviewSettings    *AssignmentReviewSettings `json:"accessReviewSettings,omitempty"`
+	AccessReviewSettings    *AssignmentReviewSettings `json:"accessReviewSettings"`
 	CanExtend               *bool                     `json:"canExtend,omitempty"`
 	CreatedBy               *string                   `json:"createdBy,omitempty"`
 	CreatedDateTime         *time.Time                `json:"createdDateTime,omitempty"`
@@ -2242,3 +2242,21 @@ type UserFlowAttribute struct {
 	UserFlowAttributeType *string                    `json:"userFlowAttributeType,omitempty"`
 	DataType              *UserflowAttributeDataType `json:"dataType,omitempty"`
 }
+
+type AttributeSet struct {
+	ID                  *string `json:"id,omitempty"`
+	Description         *string `json:"description,omitempty"`
+	MaxAttributesPerSet *int32  `json:"maxAttributesPerSet,omitempty"`
+}
+
+type CustomSecurityAttributeDefinition struct {
+	AttributeSet            *string `json:"attributeSet,omitempty"`
+	Description             *string `json:"description,omitempty"`
+	ID                      *string `json:"id,omitempty"`
+	IsCollection            *bool   `json:"isCollection,omitempty"`
+	IsSearchable            *bool   `json:"isSearchable,omitempty"`
+	Name                    *string `json:"name,omitempty"`
+	Status                  *string `json:"status,omitempty"`
+	Type                    *string `json:"type,omitempty"`
+	UsePreDefinedValuesOnly *bool   `json:"usePreDefinedValuesOnly,omitempty"`
+}
diff --git a/vendor/github.com/manicminer/hamilton/msgraph/users.go b/vendor/github.com/manicminer/hamilton/msgraph/users.go
index a68db85137..e6cdf53b4e 100644
--- a/vendor/github.com/manicminer/hamilton/msgraph/users.go
+++ b/vendor/github.com/manicminer/hamilton/msgraph/users.go
@@ -424,3 +424,20 @@ func (c *UsersClient) DeleteManager(ctx context.Context, id string) (int, error)
 
 	return status, nil
 }
+
+// UploadThumbnailPhoto uploads a thumbnail photo for the specified user which should be a gif, jpeg or png image.
+func (c *UsersClient) UploadThumbnailPhoto(ctx context.Context, userId, contentType string, thumbnailData []byte) (int, error) {
+	_, status, _, err := c.BaseClient.Put(ctx, PutHttpRequestInput{
+		Body:                   thumbnailData,
+		ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc,
+		ContentType:            contentType,
+		ValidStatusCodes:       []int{http.StatusOK},
+		Uri: Uri{
+			Entity: fmt.Sprintf("/users/%s/photo/$value", userId),
+		},
+	})
+	if err != nil {
+		return status, fmt.Errorf("UsersClient.BaseClient.Put(): %v", err)
+	}
+	return status, nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index fb108cc0f6..00d5ddebea 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -209,7 +209,7 @@ github.com/hashicorp/terraform-svchost
 # github.com/hashicorp/yamux v0.1.1
 ## explicit; go 1.15
 github.com/hashicorp/yamux
-# github.com/manicminer/hamilton v0.68.0
+# github.com/manicminer/hamilton v0.70.0
 ## explicit; go 1.21
 github.com/manicminer/hamilton/errors
 github.com/manicminer/hamilton/internal/utils