From 567b96471617484a61f3da897afb3a4e98aa9e2b Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 16:09:53 +1200 Subject: [PATCH 01/22] Add PIM Group models and valuetypes --- msgraph/models.go | 146 ++++++++++++++++++++++++++++++++++++++++++ msgraph/valuetypes.go | 110 +++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) diff --git a/msgraph/models.go b/msgraph/models.go index 05f8093a..4995c419 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -1342,6 +1342,93 @@ type PhoneAuthenticationMethod struct { PhoneNumber *string `json:"phoneNumber,omitempty"` PhoneType *AuthenticationPhoneType `json:"phoneType,omitempty"` } + +type PrivilegedAccessGroupAssignmentSchedule struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + AssignmentType *PrivilegedAccessGroupAssignmentType `json:"assignmentType,omitempty"` + CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` + CreatedUsing *string `json:"createdUsing,omitempty"` + GroupId *string `json:"groupId,omitempty"` + MemberType *PrivilegedAccessGroupMemberType `json:"memberType,omitempty"` + ModifiedDateTime *time.Time `json:"modifiedDateTime,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + ScheduleInfo *RequestSchedule `json:"scheduleInfo,omitempty"` + Status *string `json:"status,omitempty"` +} + +type PrivilegedAccessGroupAssignmentScheduleInstance struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + AssignmentScheduleId *string `json:"assignmentScheduleId,omitempty"` + AssignmentType *PrivilegedAccessGroupAssignmentType `json:"assignmentType,omitempty"` + EndDateTime *time.Time `json:"createdDateTime,omitempty"` + GroupId *string `json:"groupId,omitempty"` + MemberType *PrivilegedAccessGroupMemberType `json:"memberType,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + StartDateTime *time.Time `json:"startDateTime,omitempty"` +} + +type PrivilegedAccessGroupAssignmentScheduleRequest struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + Action *PrivilegedAccessGroupAssignmentAction `json:"action,omitempty"` + ApprovalId *string `json:"approvalId,omitempty"` + CompletedDateTime *time.Time `json:"completedDateTime,omitempty"` + CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` + CustomData *string `json:"customData,omitempty"` + GroupId *string `json:"groupId,omitempty"` + IsValidationOnly *bool `json:"isValidationOnly,omitempty"` + Justification *string `json:"justification,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + ScheduleInfo *RequestSchedule `json:"scheduleInfo,omitempty"` + Status *string `json:"status,omitempty"` + TargetScheduleId *string `json:"targetScheduleId,omitempty"` + TicketInfo *TicketInfo `json:"ticketInfo,omitempty"` +} + +type PrivilegedAccessGroupEligibilitySchedule struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` + CreatedUsing *string `json:"createdUsing,omitempty"` + GroupId *string `json:"groupId,omitempty"` + MemberType *PrivilegedAccessGroupMemberType `json:"memberType,omitempty"` + ModifiedDateTime *time.Time `json:"modifiedDateTime,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + ScheduleInfo *RequestSchedule `json:"scheduleInfo,omitempty"` + Status *string `json:"status,omitempty"` +} + +type PrivilegedAccessGroupEligibilityScheduleInstance struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + EligibilityScheduleId *string `json:"eligibilityScheduleId,omitempty"` + EndDateTime *time.Time `json:"createdDateTime,omitempty"` + GroupId *string `json:"groupId,omitempty"` + MemberType *PrivilegedAccessGroupMemberType `json:"memberType,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + StartDateTime *time.Time `json:"startDateTime,omitempty"` +} + +type PrivilegedAccessGroupEligibilityScheduleRequest struct { + ID *string `json:"id,omitempty"` + AccessId *PrivilegedAccessGroupRelationship `json:"accessId,omitempty"` + Action *string `json:"action,omitempty"` + ApprovalId *string `json:"approvalId,omitempty"` + CompletedDateTime *time.Time `json:"completedDateTime,omitempty"` + CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` + CustomData *string `json:"customData,omitempty"` + GroupId *string `json:"groupId,omitempty"` + IsValidationOnly *bool `json:"isValidationOnly,omitempty"` + Justification *string `json:"justification,omitempty"` + PrincipalId *string `json:"principalId,omitempty"` + ScheduleInfo *RequestSchedule `json:"scheduleInfo,omitempty"` + Status *string `json:"status,omitempty"` + TargetScheduleId *string `json:"targetScheduleId,omitempty"` + TicketInfo *TicketInfo `json:"ticketInfo,omitempty"` +} + type PublicClient struct { RedirectUris *[]string `json:"redirectUris,omitempty"` } @@ -1717,6 +1804,65 @@ type UnifiedRoleEligibilityScheduleRequest struct { TicketInfo *TicketInfo `json:"ticketInfo,omitempty"` } +type UnifiedRoleManagementPolicy struct { + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + IsOrganizationDefault *bool `json:"isOrganizationDefault,omitempty"` + LastModifiedBy *Identity `json:"lastModifiedBy,omitempty"` + LastModifiedDateTime *time.Time `json:"lastModifiedDateTime,omitempty"` + ScopeId *string `json:"scopeId,omitempty"` + ScopeType *UnifiedRoleManagementPolicyScope `json:"scopeType,omitempty"` +} + +type UnifiedRoleManagementPolicyAssignment struct { + ID *string `json:"id,omitempty"` + PolicyId *string `json:"policyId,omitempty"` + RoleDefinitionId *string `json:"roleDefinitionId,omitempty"` + ScopeId *string `json:"scopeId,omitempty"` + ScopeType *UnifiedRoleManagementPolicyScope `json:"scopeType,omitempty"` +} + +// • +// • unifiedRoleManagementPolicy +// • unifiedRoleManagementPolicyNotificationRule +type UnifiedRoleManagementPolicyApprovalRule struct { + ID *string `json:"id,omitempty"` + Setting *ApprovalSettings `json:"setting,omitempty"` + Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` +} + +type UnifiedRoleManagementPolicyAuthenticationContextRule struct { + ID *string `json:"id,omitempty"` + ClaimValue *string `json:"claimValue,omitempty"` + IsEnabled *bool `json:"isEnabled,omitempty"` + Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` +} + +type UnifiedRoleManagementPolicyEnablementRule struct { + ID *string `json:"id,omitempty"` + EnabledRules *[]string `json:"enabledRules,omitempty"` + Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` +} + +type UnifiedRoleManagementPolicyExpirationRule struct { + ID *string `json:"id,omitempty"` + IsDefaultRecipientsEnabled *bool `json:"isDefaultRecipientsEnabled,omitempty"` + NotificationLevel *UnifiedRoleManagementPolicyRuleNotificationLevel `json:"notificationLevel,omitempty"` + NotificationRecipients *[]string `json:"notificationRecipients,omitempty"` + NotificationType *UnifiedRoleManagementPolicyRuleNotificationType `json:"notificationType,omitempty"` + RecipientType *UnifiedRoleManagementPolicyRuleNotificationRecipientType `json:"recipientType,omitempty"` + Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` +} + +type UnifiedRoleManagementPolicyRuleTarget struct { + Caller *UnifiedRoleManagementPolicyRuleTargetCallerType `json:"caller,omitempty"` + EnforcedSettings *[]string `json:"enforcedSettings,omitempty"` + InheritableSettings *[]string `json:"inheritableSettings,omitempty"` + Level *UnifiedRoleManagementPolicyRuleLevel `json:"level,omitempty"` + Operations *[]UnifiedRoleManagementPolicyRuleOperation `json:"operations,omitempty"` +} + type UnifiedRolePermission struct { AllowedResourceActions *[]string `json:"allowedResourceActions,omitempty"` Condition *StringNullWhenEmpty `json:"condition,omitempty"` diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index e9e321c8..f4183ea3 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -667,6 +667,58 @@ const ( PreferredSingleSignOnModeSaml PreferredSingleSignOnMode = "saml" ) +type PrivilegedAccessGroupAssignmentType = string + +const ( + PrivilegedAccessGroupAssignmentAssigned PrivilegedAccessGroupAssignmentType = "assigned" + PrivilegedAccessGroupAssignmentActivated PrivilegedAccessGroupAssignmentType = "activated" + PrivilegedAccessGroupAssignmentUnknown PrivilegedAccessGroupAssignmentType = "unknownFutureValue" +) + +type PrivilegedAccessGroupAssignmentAction = string + +const ( + PrivilegedAccessGroupAssignmentActionAdminAssign PrivilegedAccessGroupAssignmentAction = "adminAssign" + PrivilegedAccessGroupAssignmentActionAdminUpdate PrivilegedAccessGroupAssignmentAction = "adminUpdate" + PrivilegedAccessGroupAssignmentActionAdminRemove PrivilegedAccessGroupAssignmentAction = "adminRemove" + PrivilegedAccessGroupAssignmentActionAdminExtend PrivilegedAccessGroupAssignmentAction = "adminExtend" + PrivilegedAccessGroupAssignmentActionAdminRenew PrivilegedAccessGroupAssignmentAction = "adminRenew" + PrivilegedAccessGroupAssignmentActionSelfActivate PrivilegedAccessGroupAssignmentAction = "selfActivate" + PrivilegedAccessGroupAssignmentActionSelfDeactivate PrivilegedAccessGroupAssignmentAction = "selfDeactivate" +) + +type PrivilegedAccessGroupAssignmentStatus = string + +const ( + PrivilegedAccessGroupAssignmentStatusCanceled PrivilegedAccessGroupAssignmentStatus = "Canceled" + PrivilegedAccessGroupAssignmentStatusDenied PrivilegedAccessGroupAssignmentStatus = "Denied" + PrivilegedAccessGroupAssignmentStatusFailed PrivilegedAccessGroupAssignmentStatus = "Failed" + PrivilegedAccessGroupAssignmentStatusGranted PrivilegedAccessGroupAssignmentStatus = "Granted" + PrivilegedAccessGroupAssignmentStatusPendingAdminDecision PrivilegedAccessGroupAssignmentStatus = "PendingAdminDecision" + PrivilegedAccessGroupAssignmentStatusPendingApproval PrivilegedAccessGroupAssignmentStatus = "PendingApproval" + PrivilegedAccessGroupAssignmentStatusPendingProvisioning PrivilegedAccessGroupAssignmentStatus = "PendingProvisioning" + PrivilegedAccessGroupAssignmentStatusPendingScheduledCreation PrivilegedAccessGroupAssignmentStatus = "PendingScheduleCreation" + PrivilegedAccessGroupAssignmentStatusProvisioned PrivilegedAccessGroupAssignmentStatus = "Provisioned" + PrivilegedAccessGroupAssignmentStatusRevoked PrivilegedAccessGroupAssignmentStatus = "Revoked" + PrivilegedAccessGroupAssignmentStatusScheduleCreated PrivilegedAccessGroupAssignmentStatus = "ScheduleCreated" +) + +type PrivilegedAccessGroupMemberType = string + +const ( + PrivilegedAccessGroupMemberDirect PrivilegedAccessGroupMemberType = "direct" + PrivilegedAccessGroupMemberGroup PrivilegedAccessGroupMemberType = "group" + PrivilegedAccessGroupMemberUnknown PrivilegedAccessGroupMemberType = "unknownFutureValue" +) + +type PrivilegedAccessGroupRelationship = string + +const ( + PrivilegedAccessGroupRelationshipOwner PrivilegedAccessGroupRelationship = "owner" + PrivilegedAccessGroupRelationshipMember PrivilegedAccessGroupRelationship = "member" + PrivilegedAccessGroupRelationshipUnknown PrivilegedAccessGroupRelationship = "unknownFutureValue" +) + type RecurrencePatternType = string const ( @@ -766,6 +818,64 @@ const ( UnifiedRoleScheduleRequestActionUnknownFutureValue UnifiedRoleScheduleRequestAction = "unknownFutureValue" ) +type UnifiedRoleManagementPolicyScope = string + +const ( + UnifiedRoleManagementPolicyScopeDirectory UnifiedRoleManagementPolicyScope = "Directory" + UnifiedRoleManagementPolicyScopeDirectoryRole UnifiedRoleManagementPolicyScope = "DirectoryRole" + UnifiedRoleManagementPolicyScopeGroup UnifiedRoleManagementPolicyScope = "Group" +) + +type UnifiedRoleManagementPolicyRuleTargetCallerType = string + +const ( + UnifiedRoleManagementPolicyRuleTargetCallerTypeNone UnifiedRoleManagementPolicyRuleTargetCallerType = "None" + UnifiedRoleManagementPolicyRuleTargetCallerTypeAdmin UnifiedRoleManagementPolicyRuleTargetCallerType = "Admin" + UnifiedRoleManagementPolicyRuleTargetCallerTypeEndUser UnifiedRoleManagementPolicyRuleTargetCallerType = "EndUser" +) + +type UnifiedRoleManagementPolicyRuleLevel = string + +const ( + UnifiedRoleManagementPolicyRuleLevelEligibility UnifiedRoleManagementPolicyRuleLevel = "Eligibility" + UnifiedRoleManagementPolicyRuleLevelAssignment UnifiedRoleManagementPolicyRuleLevel = "Assignment" +) + +type UnifiedRoleManagementPolicyRuleNotificationLevel = string + +const ( + UnifiedRoleManagementPolicyRuleNotificationLevelNone UnifiedRoleManagementPolicyRuleNotificationLevel = "None" + UnifiedRoleManagementPolicyRuleNotificationLevelCritical UnifiedRoleManagementPolicyRuleNotificationLevel = "Critical" + UnifiedRoleManagementPolicyRuleNotificationLevelAll UnifiedRoleManagementPolicyRuleNotificationLevel = "All" +) + +type UnifiedRoleManagementPolicyRuleNotificationRecipientType = string + +const ( + UnifiedRoleManagementPolicyRuleNotificationRecipientTypeRequestor UnifiedRoleManagementPolicyRuleNotificationRecipientType = "Requestor" + UnifiedRoleManagementPolicyRuleNotificationRecipientTypeApprover UnifiedRoleManagementPolicyRuleNotificationRecipientType = "Approver" + UnifiedRoleManagementPolicyRuleNotificationRecipientTypeAdmin UnifiedRoleManagementPolicyRuleNotificationRecipientType = "Admin" +) + +type UnifiedRoleManagementPolicyRuleNotificationType = string + +const ( + UnifiedRoleManagementPolicyRuleNotificationTypeEmail UnifiedRoleManagementPolicyRuleNotificationType = "Email" +) + +type UnifiedRoleManagementPolicyRuleOperation = string + +const ( + UnifiedRoleManagementPolicyRuleOperationAll UnifiedRoleManagementPolicyRuleOperation = "All" + UnifiedRoleManagementPolicyRuleOperationActivate UnifiedRoleManagementPolicyRuleOperation = "Activate" + UnifiedRoleManagementPolicyRuleOperationDeactivate UnifiedRoleManagementPolicyRuleOperation = "Deactivate" + UnifiedRoleManagementPolicyRuleOperationAssign UnifiedRoleManagementPolicyRuleOperation = "Assign" + UnifiedRoleManagementPolicyRuleOperationUpdate UnifiedRoleManagementPolicyRuleOperation = "Update" + UnifiedRoleManagementPolicyRuleOperationRemove UnifiedRoleManagementPolicyRuleOperation = "Remove" + UnifiedRoleManagementPolicyRuleOperationExtend UnifiedRoleManagementPolicyRuleOperation = "Extend" + UnifiedRoleManagementPolicyRuleOperationRenew UnifiedRoleManagementPolicyRuleOperation = "Renew" +) + type UsageAuthMethod = string const ( From b378f8b6b85ade47074116a65d83ad37c38f684a Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 16:30:08 +1200 Subject: [PATCH 02/22] Remove stray comment --- msgraph/models.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/msgraph/models.go b/msgraph/models.go index 4995c419..000b12f2 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -1823,9 +1823,6 @@ type UnifiedRoleManagementPolicyAssignment struct { ScopeType *UnifiedRoleManagementPolicyScope `json:"scopeType,omitempty"` } -// • -// • unifiedRoleManagementPolicy -// • unifiedRoleManagementPolicyNotificationRule type UnifiedRoleManagementPolicyApprovalRule struct { ID *string `json:"id,omitempty"` Setting *ApprovalSettings `json:"setting,omitempty"` From f084ce6af6ad2e1f388c198328df387822237bc0 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 16:52:25 +1200 Subject: [PATCH 03/22] Flatten UnifiedRoleManagementPolicyRule structs Is a generic type returned from the graph, which maps to different types --- msgraph/models.go | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/msgraph/models.go b/msgraph/models.go index 000b12f2..ea9d9cb8 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -1823,32 +1823,17 @@ type UnifiedRoleManagementPolicyAssignment struct { ScopeType *UnifiedRoleManagementPolicyScope `json:"scopeType,omitempty"` } -type UnifiedRoleManagementPolicyApprovalRule struct { - ID *string `json:"id,omitempty"` - Setting *ApprovalSettings `json:"setting,omitempty"` - Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` -} - -type UnifiedRoleManagementPolicyAuthenticationContextRule struct { - ID *string `json:"id,omitempty"` - ClaimValue *string `json:"claimValue,omitempty"` - IsEnabled *bool `json:"isEnabled,omitempty"` - Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` -} - -type UnifiedRoleManagementPolicyEnablementRule struct { - ID *string `json:"id,omitempty"` - EnabledRules *[]string `json:"enabledRules,omitempty"` - Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` -} - -type UnifiedRoleManagementPolicyExpirationRule struct { +type UnifiedRoleManagementPolicyRule struct { ID *string `json:"id,omitempty"` + ClaimValue *string `json:"claimValue,omitempty"` + EnabledRules *[]string `json:"enabledRules,omitempty"` IsDefaultRecipientsEnabled *bool `json:"isDefaultRecipientsEnabled,omitempty"` + IsEnabled *bool `json:"isEnabled,omitempty"` NotificationLevel *UnifiedRoleManagementPolicyRuleNotificationLevel `json:"notificationLevel,omitempty"` NotificationRecipients *[]string `json:"notificationRecipients,omitempty"` NotificationType *UnifiedRoleManagementPolicyRuleNotificationType `json:"notificationType,omitempty"` RecipientType *UnifiedRoleManagementPolicyRuleNotificationRecipientType `json:"recipientType,omitempty"` + Setting *ApprovalSettings `json:"setting,omitempty"` Target *UnifiedRoleManagementPolicyRuleTarget `json:"target,omitempty"` } From 2367a86a3c70010e803fba7ccb70d9423b75f012 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 16:55:42 +1200 Subject: [PATCH 04/22] Add Role Management Policies functions --- msgraph/role_management_policies.go | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 msgraph/role_management_policies.go diff --git a/msgraph/role_management_policies.go b/msgraph/role_management_policies.go new file mode 100644 index 00000000..bb1db5d5 --- /dev/null +++ b/msgraph/role_management_policies.go @@ -0,0 +1,101 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type RoleManagementPolicyClient struct { + BaseClient Client +} + +func NewRoleManagementPolicyClient() *RoleManagementPolicyClient { + return &RoleManagementPolicyClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// List retrieves a list of Role Management Policies +func (c *RoleManagementPolicyClient) List(ctx context.Context, query odata.Query) (*[]UnifiedRoleManagementPolicy, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/policies/roleManagementPolicies", + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleManagementPolicyClient.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 { + UnifiedRoleManagementPolicy []UnifiedRoleManagementPolicy `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.UnifiedRoleManagementPolicy, status, nil +} + +// Get retrieves a UnifiedRoleManagementPolicy +func (c *RoleManagementPolicyClient) Get(ctx context.Context, id string, query odata.Query) (*UnifiedRoleManagementPolicy, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s", id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleDefinitionsClient.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 policy UnifiedRoleManagementPolicy + if err := json.Unmarshal(respBody, &policy); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &policy, status, nil +} + +// Update amends an existing UnifiedRoleManagementPolicy. +func (c *RoleManagementPolicyClient) Update(ctx context.Context, policy UnifiedRoleManagementPolicy) (int, error) { + var status int + + body, err := json.Marshal(policy) + 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.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/roleManagement/directory/roleDefinitions/%s", *policy.ID), + }, + }) + if err != nil { + return status, fmt.Errorf("RoleDefinitionsClient.BaseClient.Patch(): %v", err) + } + + return status, nil +} From f112158b7a9df3370254a29d9c05fd65f24c2803 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 16:55:51 +1200 Subject: [PATCH 05/22] Add Role Management Policy Rules functions --- msgraph/role_management_policy_rules.go | 101 ++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 msgraph/role_management_policy_rules.go diff --git a/msgraph/role_management_policy_rules.go b/msgraph/role_management_policy_rules.go new file mode 100644 index 00000000..1ebb61c2 --- /dev/null +++ b/msgraph/role_management_policy_rules.go @@ -0,0 +1,101 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type RoleManagementPolicyRulesClient struct { + BaseClient Client +} + +func NewRoleManagementPolicyRulesClient() *RoleManagementPolicyRulesClient { + return &RoleManagementPolicyRulesClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// List retrieves a list of Role Management Rules for a policy +func (c *RoleManagementPolicyRulesClient) List(ctx context.Context, policyId string, query odata.Query) (*[]UnifiedRoleManagementPolicyRule, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s/rules", policyId), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleManagementPolicyRulesClient.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 { + UnifiedRoleManagementPolicyRule []UnifiedRoleManagementPolicyRule `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.UnifiedRoleManagementPolicyRule, status, nil +} + +// Get retrieves a UnifiedRoleManagementPolicyRule +func (c *RoleManagementPolicyRulesClient) Get(ctx context.Context, id, policyId string, query odata.Query) (*UnifiedRoleManagementPolicyRule, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s/rules/%s", policyId, id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleManagementPolicyRulesClient.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 rule UnifiedRoleManagementPolicyRule + if err := json.Unmarshal(respBody, &rule); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &rule, status, nil +} + +// Update amends an existing UnifiedRoleManagementPolicyRule. +func (c *RoleManagementPolicyRulesClient) Update(ctx context.Context, rule UnifiedRoleManagementPolicyRule, policyId string) (int, error) { + var status int + + body, err := json.Marshal(rule) + 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.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s/rules/%s", policyId, *rule.ID), + }, + }) + if err != nil { + return status, fmt.Errorf("RoleManagementPolicyRulesClient.BaseClient.Patch(): %v", err) + } + + return status, nil +} From 1feabeecb0ecd9606b3eb0f2c00c029b4caedb07 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 17:00:42 +1200 Subject: [PATCH 06/22] Add Role Management Policy Assignments --- msgraph/role_management_policy_assignments.go | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 msgraph/role_management_policy_assignments.go diff --git a/msgraph/role_management_policy_assignments.go b/msgraph/role_management_policy_assignments.go new file mode 100644 index 00000000..bb5080af --- /dev/null +++ b/msgraph/role_management_policy_assignments.go @@ -0,0 +1,77 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type RoleManagementPolicyAssignmentsClient struct { + BaseClient Client +} + +func NewRoleManagementPolicyAssignmentsClient() *RoleManagementPolicyAssignmentsClient { + return &RoleManagementPolicyAssignmentsClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// List retrieves a list of Role Management Assignments for a policy +func (c *RoleManagementPolicyAssignmentsClient) List(ctx context.Context, policyId string, query odata.Query) (*[]UnifiedRoleManagementPolicyAssignment, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s/rules", policyId), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleManagementPolicyAssignmentsClient.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 { + UnifiedRoleManagementPolicyAssignment []UnifiedRoleManagementPolicyAssignment `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.UnifiedRoleManagementPolicyAssignment, status, nil +} + +// Get retrieves a UnifiedRoleManagementPolicyAssignment +func (c *RoleManagementPolicyAssignmentsClient) Get(ctx context.Context, id, policyId string, query odata.Query) (*UnifiedRoleManagementPolicyAssignment, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/roleManagementPolicies/%s/rules/%s", policyId, id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("RoleManagementPolicyAssignmentsClient.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 assignment UnifiedRoleManagementPolicyAssignment + if err := json.Unmarshal(respBody, &assignment); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &assignment, status, nil +} From 883e86277dbf251b3a981f823317851cf024cd1d Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 17:06:42 +1200 Subject: [PATCH 07/22] Add ApprovalStep types --- msgraph/models.go | 11 +++++++++++ msgraph/valuetypes.go | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/msgraph/models.go b/msgraph/models.go index ea9d9cb8..305fb90e 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -563,6 +563,17 @@ type ApprovalStage struct { EscalationApprovers *[]UserSet `json:"escalationApprovers,omitempty"` } +type ApprovalStep struct { + ID *string `json:"id,omitempty"` + AssignedToMe *bool `json:"assignedToMe,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + Justification *string `json:"justification,omitempty"` + ReviewResult *string `json:"reviewResult,omitempty"` + ReviewedBy *[]UserIdentity `json:"reviewedBy,omitempty"` + ReviewedDateTime *time.Time `json:"reviewedDateTime,omitempty"` + Status *ApprovalStepStatus `json:"status,omitempty"` +} + type AssignmentReviewSettings struct { IsEnabled *bool `json:"isEnabled,omitempty"` RecurrenceType AccessReviewRecurranceType `json:"recurrenceType,omitempty"` diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index f4183ea3..7d187e61 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -226,6 +226,15 @@ const ( ApprovalModeSingleStage ApprovalMode = "SingleStage" ) +type ApprovalStepStatus = string + +const ( + ApprovalStepStatusInProgress ApprovalStepStatus = "InProgress" + ApprovalStepStatusInitializing ApprovalStepStatus = "Initializing" + ApprovalStepStatusCompleted ApprovalStepStatus = "Completed" + ApprovalStepStatusExpired ApprovalStepStatus = "Expired" +) + type AttestationLevel = string const ( From 75c524620cee68d60072fecc0f52c63c9937353c Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 18 Jul 2023 17:19:48 +1200 Subject: [PATCH 08/22] Add Approvals and Approval Steps --- msgraph/accesspackageassignmentapproval.go | 46 ++++++++ .../accesspackageassignmentapprovalstep.go | 107 ++++++++++++++++++ msgraph/models.go | 5 + 3 files changed, 158 insertions(+) create mode 100644 msgraph/accesspackageassignmentapproval.go create mode 100644 msgraph/accesspackageassignmentapprovalstep.go diff --git a/msgraph/accesspackageassignmentapproval.go b/msgraph/accesspackageassignmentapproval.go new file mode 100644 index 00000000..8c2661b7 --- /dev/null +++ b/msgraph/accesspackageassignmentapproval.go @@ -0,0 +1,46 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" +) + +type AccessPackageAssignmentApprovalClient struct { + BaseClient Client +} + +func NewAccessPackageAssignmentApprovalClient() *AccessPackageAssignmentApprovalClient { + return &AccessPackageAssignmentApprovalClient{ + BaseClient: NewClient(Version10), + } +} + +// Get will get an approval +func (c *AccessPackageAssignmentApprovalClient) Get(ctx context.Context, id string) (*Approval, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/entitlementManagement/accessPackageAssignmentApprovals/%s", id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AccessPackageAssignmentApprovalClient.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 approval Approval + if err := json.Unmarshal(respBody, &approval); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &approval, status, nil +} diff --git a/msgraph/accesspackageassignmentapprovalstep.go b/msgraph/accesspackageassignmentapprovalstep.go new file mode 100644 index 00000000..8cd525ef --- /dev/null +++ b/msgraph/accesspackageassignmentapprovalstep.go @@ -0,0 +1,107 @@ +package msgraph + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type AccessPackageAssignmentApprovalStepClient struct { + BaseClient Client +} + +func NewAccessPackageAssignmentApprovalStepClient() *AccessPackageAssignmentApprovalStepClient { + return &AccessPackageAssignmentApprovalStepClient{ + BaseClient: NewClient(Version10), + } +} + +// List returns a list of Approval Steps for an approval +func (c *AccessPackageAssignmentApprovalStepClient) List(ctx context.Context, approvalId string, query odata.Query) (*[]ApprovalStep, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + DisablePaging: query.Top > 0, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/entitlementManagement/accessPackageAssignmentApprovals/%s/steps", approvalId), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AccessPackageAssignmentPolicyClient.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 { + ApprovalStep []ApprovalStep `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.ApprovalStep, status, nil +} + +// Get will get an approval step +func (c *AccessPackageAssignmentApprovalStepClient) Get(ctx context.Context, id, approvalId string) (*ApprovalStep, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/entitlementManagement/accessPackageAssignmentApprovals/%s/steps/%s", approvalId, id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AccessPackageAssignmentApprovalStepClient.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 step ApprovalStep + if err := json.Unmarshal(respBody, &step); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &step, status, nil +} + +// Update amends an existing AccessPackageAssignmentPolicy. +func (c *AccessPackageAssignmentApprovalStepClient) Update(ctx context.Context, step ApprovalStep, approvalId string) (int, error) { + var status int + + if step.ID == nil { + return status, errors.New("cannot update ApprovalStep with nil ID") + } + + body, err := json.Marshal(step) + if err != nil { + return status, fmt.Errorf("json.Marshal(): %v", err) + } + + _, status, _, err = c.BaseClient.Put(ctx, PutHttpRequestInput{ //This is usually a patch but this endpoint uses PUT + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/entitlementManagement/accessPackageAssignmentApprovals/%s/steps/%s", approvalId, *step.ID), + }, + }) + if err != nil { + return status, fmt.Errorf("AccessPackageAssignmentApprovalStepClient.BaseClient.Put(): %v", err) + } + + return status, nil +} diff --git a/msgraph/models.go b/msgraph/models.go index 305fb90e..6bbc4415 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -544,6 +544,11 @@ type AppRoleAssignment struct { ResourceId *string `json:"resourceId,omitempty"` } +type Approval struct { + ID *string `json:"id,omitempty"` + Steps *[]ApprovalStep `json:"steps,omitempty"` +} + type ApprovalSettings struct { IsApprovalRequiredForAdd *bool `json:"isApprovalRequiredForAdd,omitempty"` IsApprovalRequiredForUpdate *bool `json:"isApprovalRequiredForUpdate,omitempty"` From 3666064dc3bea671a4c60238c3401a76d7e047c6 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Mon, 31 Jul 2023 11:57:37 +1200 Subject: [PATCH 09/22] Add PIM Group Assigments Fails due to invalid memory adderess when building the POST request --- internal/test/testing.go | 91 ++++++------- ...vilegedaccess_groups_assignment_request.go | 126 ++++++++++++++++++ ...edaccess_groups_assignment_request_test.go | 121 +++++++++++++++++ 3 files changed, 293 insertions(+), 45 deletions(-) create mode 100644 msgraph/privilegedaccess_groups_assignment_request.go create mode 100644 msgraph/privilegedaccess_groups_assignment_request_test.go diff --git a/internal/test/testing.go b/internal/test/testing.go index 6baa8583..67105850 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -90,51 +90,52 @@ type Test struct { Claims *claims.Claims Token *oauth2.Token - AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient - AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient - AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient - AccessPackageClient *msgraph.AccessPackageClient - AccessPackageResourceClient *msgraph.AccessPackageResourceClient - AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient - AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient - AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient - ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient - ApplicationsClient *msgraph.ApplicationsClient - AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient - AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient - B2CUserFlowClient *msgraph.B2CUserFlowClient - ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient - ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient - ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient - DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient - DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient - DirectoryObjectsClient *msgraph.DirectoryObjectsClient - DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient - DirectoryRolesClient *msgraph.DirectoryRolesClient - DomainsClient *msgraph.DomainsClient - EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient - EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient - GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - GroupsClient *msgraph.GroupsClient - IdentityProvidersClient *msgraph.IdentityProvidersClient - InvitationsClient *msgraph.InvitationsClient - MeClient *msgraph.MeClient - NamedLocationsClient *msgraph.NamedLocationsClient - ReportsClient *msgraph.ReportsClient - RoleAssignmentsClient *msgraph.RoleAssignmentsClient - RoleDefinitionsClient *msgraph.RoleDefinitionsClient - RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient - SchemaExtensionsClient *msgraph.SchemaExtensionsClient - ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - ServicePrincipalsClient *msgraph.ServicePrincipalsClient - SignInReportsClient *msgraph.SignInReportsClient - SynchronizationJobClient *msgraph.SynchronizationJobClient - TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient - TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient - UserFlowAttributesClient *msgraph.UserFlowAttributesClient - UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - UsersClient *msgraph.UsersClient - WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient + AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient + AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient + AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient + AccessPackageClient *msgraph.AccessPackageClient + AccessPackageResourceClient *msgraph.AccessPackageResourceClient + AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient + AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient + AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient + ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient + ApplicationsClient *msgraph.ApplicationsClient + AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient + AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient + B2CUserFlowClient *msgraph.B2CUserFlowClient + ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient + ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient + ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient + DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient + DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient + DirectoryObjectsClient *msgraph.DirectoryObjectsClient + DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient + DirectoryRolesClient *msgraph.DirectoryRolesClient + DomainsClient *msgraph.DomainsClient + EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient + EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient + GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + GroupsClient *msgraph.GroupsClient + IdentityProvidersClient *msgraph.IdentityProvidersClient + InvitationsClient *msgraph.InvitationsClient + MeClient *msgraph.MeClient + NamedLocationsClient *msgraph.NamedLocationsClient + PrivilegedAccessGroupAssignmentScheduleRequestClient *msgraph.PrivilegedAccessGroupAssignmentScheduleRequestClient + ReportsClient *msgraph.ReportsClient + RoleAssignmentsClient *msgraph.RoleAssignmentsClient + RoleDefinitionsClient *msgraph.RoleDefinitionsClient + RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient + SchemaExtensionsClient *msgraph.SchemaExtensionsClient + ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + ServicePrincipalsClient *msgraph.ServicePrincipalsClient + SignInReportsClient *msgraph.SignInReportsClient + SynchronizationJobClient *msgraph.SynchronizationJobClient + TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient + TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient + UserFlowAttributesClient *msgraph.UserFlowAttributesClient + UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + UsersClient *msgraph.UsersClient + WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient } func NewTest(t *testing.T) (c *Test) { diff --git a/msgraph/privilegedaccess_groups_assignment_request.go b/msgraph/privilegedaccess_groups_assignment_request.go new file mode 100644 index 00000000..cbc9d86b --- /dev/null +++ b/msgraph/privilegedaccess_groups_assignment_request.go @@ -0,0 +1,126 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type PrivilegedAccessGroupAssignmentScheduleRequestClient struct { + BaseClient Client +} + +func NewPrivilegedAccessGroupAssignmentScheduleRequestClient() *PrivilegedAccessGroupAssignmentScheduleRequestClient { + return &PrivilegedAccessGroupAssignmentScheduleRequestClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// List retrieves a list of PrivilegedAccessGroupAssignmentScheduleRequests +func (c *PrivilegedAccessGroupAssignmentScheduleRequestClient) List(ctx context.Context, query odata.Query) (*[]PrivilegedAccessGroupAssignmentScheduleRequest, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + DisablePaging: query.Top > 0, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/identityGovernance/privilegedAccess/group/assignmentScheduleRequests", + }, + }) + if err != nil { + return nil, status, fmt.Errorf("PrivilegedAccessGroupClient.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 { + Requests []PrivilegedAccessGroupAssignmentScheduleRequest `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.Requests, status, nil +} + +// Create creates a new PrivilegedAccessGroupAssignmentScheduleRequest. +func (c *PrivilegedAccessGroupAssignmentScheduleRequestClient) Create(ctx context.Context, request PrivilegedAccessGroupAssignmentScheduleRequest) (*PrivilegedAccessGroupAssignmentScheduleRequest, int, error) { + var status int + + body, err := json.Marshal(request) + if err != nil { + return nil, status, fmt.Errorf("json.Marshal(): %v", err) + } + + resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + ValidStatusCodes: []int{http.StatusCreated}, + Uri: Uri{ + Entity: "/identityGovernance/privilegedAccess/group/assignmentScheduleRequests", + }, + }) + if err != nil { + return nil, status, fmt.Errorf("PrivilegedAccessGroupAssignmentScheduleRequestClient.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 newRequest PrivilegedAccessGroupAssignmentScheduleRequest + if err := json.Unmarshal(respBody, &newRequest); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &newRequest, status, nil +} + +// Get retrieves a PrivilegedAccessGroupAssignmentScheduleRequest +func (c *PrivilegedAccessGroupAssignmentScheduleRequestClient) Get(ctx context.Context, requestId string) (*PrivilegedAccessGroupAssignmentScheduleRequest, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/privilegedAccess/group/assignmentScheduleRequests/%s", requestId), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("PrivilegedAccessGroupClient.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 request PrivilegedAccessGroupAssignmentScheduleRequest + if err := json.Unmarshal(respBody, &request); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &request, status, nil +} + +// Cancel cancels a PrivilegedAccessGroupAssignmentScheduleRequest +func (c *PrivilegedAccessGroupAssignmentScheduleRequestClient) Cancel(ctx context.Context, requestId string) (int, error) { + _, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/identityGovernance/privilegedAccess/group/assignmentScheduleRequests/%s/cancel", requestId), + }, + }) + if err != nil { + return status, fmt.Errorf("PrivilegedAccessGroupClient.BaseClient.Post(): %v", err) + } + + return status, nil +} diff --git a/msgraph/privilegedaccess_groups_assignment_request_test.go b/msgraph/privilegedaccess_groups_assignment_request_test.go new file mode 100644 index 00000000..a63c89f5 --- /dev/null +++ b/msgraph/privilegedaccess_groups_assignment_request_test.go @@ -0,0 +1,121 @@ +package msgraph_test + +import ( + "fmt" + "testing" + "time" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/manicminer/hamilton/internal/test" + "github.com/manicminer/hamilton/internal/utils" + "github.com/manicminer/hamilton/msgraph" +) + +func TestPrivilegedAccessGroupAssignmentScheduleRequestClient(t *testing.T) { + c := test.NewTest(t) + defer c.CancelFunc() + + self := testDirectoryObjectsClient_Get(t, c, c.Claims.ObjectId) + now := time.Now() + end := now.AddDate(0, 3, 0) + + pimGroup := testGroupsClient_Create(t, c, msgraph.Group{ + DisplayName: utils.StringPtr("test-group"), + MailEnabled: utils.BoolPtr(false), + MailNickname: utils.StringPtr(fmt.Sprintf("test-group-%s", c.RandomString)), + SecurityEnabled: utils.BoolPtr(true), + }) + + reqOwner := testPrivilegedAccessGroupAssignmentScheduleRequestClient_Create(t, c, msgraph.PrivilegedAccessGroupAssignmentScheduleRequest{ + AccessId: utils.StringPtr(msgraph.PrivilegedAccessGroupRelationshipOwner), + Action: utils.StringPtr(msgraph.PrivilegedAccessGroupAssignmentActionAdminAssign), + GroupId: pimGroup.ID(), + PrincipalId: self.ID(), + Justification: utils.StringPtr("Hamilton Testing"), + ScheduleInfo: &msgraph.RequestSchedule{ + StartDateTime: &now, + Expiration: &msgraph.ExpirationPattern{ + EndDateTime: &end, + Type: utils.StringPtr(msgraph.ExpirationPatternTypeAfterDateTime), + }, + }, + }) + + reqMember := testPrivilegedAccessGroupAssignmentScheduleRequestClient_Create(t, c, msgraph.PrivilegedAccessGroupAssignmentScheduleRequest{ + AccessId: utils.StringPtr(msgraph.PrivilegedAccessGroupRelationshipMember), + Action: utils.StringPtr(msgraph.PrivilegedAccessGroupAssignmentActionAdminAssign), + GroupId: pimGroup.ID(), + PrincipalId: self.ID(), + Justification: utils.StringPtr("Hamilton Testing"), + ScheduleInfo: &msgraph.RequestSchedule{ + StartDateTime: &now, + Expiration: &msgraph.ExpirationPattern{ + EndDateTime: &end, + Type: utils.StringPtr(msgraph.ExpirationPatternTypeAfterDateTime), + }, + }, + }) + + testPrivilegedAccessGroupAssignmentScheduleRequestClient_List(t, c) + testPrivilegedAccessGroupAssignmentScheduleRequestClient_Get(t, c, *reqOwner.ID) + testPrivilegedAccessGroupAssignmentScheduleRequestClient_Get(t, c, *reqMember.ID) + testPrivilegedAccessGroupAssignmentScheduleRequestClient_Cancel(t, c, *reqOwner.ID) + testPrivilegedAccessGroupAssignmentScheduleRequestClient_Cancel(t, c, *reqMember.ID) + + testGroupsClient_Delete(t, c, *pimGroup.ID()) +} + +func testPrivilegedAccessGroupAssignmentScheduleRequestClient_Create(t *testing.T, c *test.Test, r msgraph.PrivilegedAccessGroupAssignmentScheduleRequest) (request *msgraph.PrivilegedAccessGroupAssignmentScheduleRequest) { + request, status, err := c.PrivilegedAccessGroupAssignmentScheduleRequestClient.Create(c.Context, r) + if err != nil { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Create(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Create(): invalid status: %d", status) + } + if request == nil { + t.Fatal("PrivilegedAccessGroupAssignmentScheduleRequestClient.Create(): PrivilegedAccessGroupAssignmentScheduleRequest was nil") + } + if request.ID == nil { + t.Fatal("PrivilegedAccessGroupAssignmentScheduleRequestClient.Create(): PrivilegedAccessGroupAssignmentScheduleRequest.ID was nil") + } + return +} + +func testPrivilegedAccessGroupAssignmentScheduleRequestClient_List(t *testing.T, c *test.Test) (requests *[]msgraph.PrivilegedAccessGroupAssignmentScheduleRequest) { + requests, status, err := c.PrivilegedAccessGroupAssignmentScheduleRequestClient.List(c.Context, odata.Query{}) + if err != nil { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.List(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.List(): invalid status: %d", status) + } + if requests == nil { + t.Fatal("PrivilegedAccessGroupAssignmentScheduleRequestClient.List(): PrivilegedAccessGroupAssignmentScheduleRequest was nil") + } + return +} + +func testPrivilegedAccessGroupAssignmentScheduleRequestClient_Get(t *testing.T, c *test.Test, id string) (request *msgraph.PrivilegedAccessGroupAssignmentScheduleRequest) { + request, status, err := c.PrivilegedAccessGroupAssignmentScheduleRequestClient.Get(c.Context, id) + if err != nil { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Get(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Get(): invalid status: %d", status) + } + if request == nil { + t.Fatal("PrivilegedAccessGroupAssignmentScheduleRequestClient.Get(): PrivilegedAccessGroupAssignmentScheduleRequest was nil") + } + return +} + +func testPrivilegedAccessGroupAssignmentScheduleRequestClient_Cancel(t *testing.T, c *test.Test, id string) { + status, err := c.PrivilegedAccessGroupAssignmentScheduleRequestClient.Cancel(c.Context, id) + if err != nil { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Cancel(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("PrivilegedAccessGroupAssignmentScheduleRequestClient.Cancel(): invalid status: %d", status) + } +} From 125f5418ccf868cb878ddc6d360e37bef7adeaac Mon Sep 17 00:00:00 2001 From: bubbletroubles <42738824+bubbletroubles@users.noreply.github.com> Date: Tue, 25 Jul 2023 07:31:29 +1000 Subject: [PATCH 10/22] Add support for `AuthenticationStrengthPolicies` (#249) * Added AuthenticationMethodModes * Updates * Typos * Added client * Updated allowed combinations * Disable paging * Fixed description * Fix Typos * fixed tests * fixed typo * Removed extra defintions * Fixed typo * Added AuthenticationStrength to CA Grant Controls * Update msgraph/models.go Co-authored-by: Tom Bamford * Added tests * Trigger re-test * trigger re-test * Clean up Auth Strengh Policy after testing * Triggered re-test * Updated policy ID * cleanup tool support authentication stength policies --------- Co-authored-by: bubbletroubles Co-authored-by: Tom Bamford --- .../authenticationstrengthpolicies.go | 36 ++++ internal/cmd/test-cleanup/main.go | 1 + internal/test/testing.go | 97 ++++++----- msgraph/authentication_strength_policy.go | 158 ++++++++++++++++++ .../authentication_strength_policy_test.go | 96 +++++++++++ msgraph/conditionalaccesspolicy_test.go | 12 ++ msgraph/models.go | 11 ++ msgraph/valuetypes.go | 30 ++++ 8 files changed, 395 insertions(+), 46 deletions(-) create mode 100644 internal/cmd/test-cleanup/authenticationstrengthpolicies.go create mode 100644 msgraph/authentication_strength_policy.go create mode 100644 msgraph/authentication_strength_policy_test.go diff --git a/internal/cmd/test-cleanup/authenticationstrengthpolicies.go b/internal/cmd/test-cleanup/authenticationstrengthpolicies.go new file mode 100644 index 00000000..8d794903 --- /dev/null +++ b/internal/cmd/test-cleanup/authenticationstrengthpolicies.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "log" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/manicminer/hamilton/msgraph" +) + +func cleanupAuthenticationStrengthPolicies() { + client := msgraph.NewAuthenticationStrengthPoliciesClient() + client.BaseClient.Authorizer = authorizer + + authStrengthPolicies, _, err := client.List(ctx, odata.Query{Filter: fmt.Sprintf("startsWith(displayName, '%s')", displayNamePrefix)}) + if err != nil { + log.Println(err) + return + } + if authStrengthPolicies == nil { + log.Println("bad API response, nil authStrengthPolicies result received") + return + } + for _, policy := range *authStrengthPolicies { + if policy.ID == nil || policy.DisplayName == nil { + log.Println("Authentication Strength Policy returned with nil ID or DisplayName") + continue + } + + log.Printf("Deleting Authentication Strength Policy %q (DisplayName: %q)\n", *policy.ID, *policy.DisplayName) + _, err := client.Delete(ctx, *policy.ID) + if err != nil { + log.Printf("Error when deleting Authentication Strength Policy %q: %v\n", *policy.ID, err) + } + } +} diff --git a/internal/cmd/test-cleanup/main.go b/internal/cmd/test-cleanup/main.go index 265f6bf6..bf8b380b 100644 --- a/internal/cmd/test-cleanup/main.go +++ b/internal/cmd/test-cleanup/main.go @@ -81,6 +81,7 @@ func main() { cleanupConditionalAccessPolicies() cleanupConnectedOrganizations() cleanupNamedLocations() + cleanupAuthenticationStrengthPolicies() cleanupServicePrincipals() cleanupApplications() cleanupGroups() diff --git a/internal/test/testing.go b/internal/test/testing.go index 67105850..1f8e88e5 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -90,52 +90,52 @@ type Test struct { Claims *claims.Claims Token *oauth2.Token - AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient - AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient - AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient - AccessPackageClient *msgraph.AccessPackageClient - AccessPackageResourceClient *msgraph.AccessPackageResourceClient - AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient - AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient - AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient - ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient - ApplicationsClient *msgraph.ApplicationsClient - AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient - AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient - B2CUserFlowClient *msgraph.B2CUserFlowClient - ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient - ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient - ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient - DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient - DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient - DirectoryObjectsClient *msgraph.DirectoryObjectsClient - DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient - DirectoryRolesClient *msgraph.DirectoryRolesClient - DomainsClient *msgraph.DomainsClient - EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient - EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient - GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - GroupsClient *msgraph.GroupsClient - IdentityProvidersClient *msgraph.IdentityProvidersClient - InvitationsClient *msgraph.InvitationsClient - MeClient *msgraph.MeClient - NamedLocationsClient *msgraph.NamedLocationsClient - PrivilegedAccessGroupAssignmentScheduleRequestClient *msgraph.PrivilegedAccessGroupAssignmentScheduleRequestClient - ReportsClient *msgraph.ReportsClient - RoleAssignmentsClient *msgraph.RoleAssignmentsClient - RoleDefinitionsClient *msgraph.RoleDefinitionsClient - RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient - SchemaExtensionsClient *msgraph.SchemaExtensionsClient - ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - ServicePrincipalsClient *msgraph.ServicePrincipalsClient - SignInReportsClient *msgraph.SignInReportsClient - SynchronizationJobClient *msgraph.SynchronizationJobClient - TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient - TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient - UserFlowAttributesClient *msgraph.UserFlowAttributesClient - UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - UsersClient *msgraph.UsersClient - WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient + AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient + AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient + AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient + AccessPackageClient *msgraph.AccessPackageClient + AccessPackageResourceClient *msgraph.AccessPackageResourceClient + AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient + AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient + AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient + ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient + ApplicationsClient *msgraph.ApplicationsClient + AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient + AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient + AuthenticationStrengthPoliciesClient *msgraph.AuthenticationStrengthPoliciesClient + B2CUserFlowClient *msgraph.B2CUserFlowClient + ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient + ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient + ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient + DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient + DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient + DirectoryObjectsClient *msgraph.DirectoryObjectsClient + DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient + DirectoryRolesClient *msgraph.DirectoryRolesClient + DomainsClient *msgraph.DomainsClient + EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient + EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient + GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + GroupsClient *msgraph.GroupsClient + IdentityProvidersClient *msgraph.IdentityProvidersClient + InvitationsClient *msgraph.InvitationsClient + MeClient *msgraph.MeClient + NamedLocationsClient *msgraph.NamedLocationsClient + ReportsClient *msgraph.ReportsClient + RoleAssignmentsClient *msgraph.RoleAssignmentsClient + RoleDefinitionsClient *msgraph.RoleDefinitionsClient + RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient + SchemaExtensionsClient *msgraph.SchemaExtensionsClient + ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + ServicePrincipalsClient *msgraph.ServicePrincipalsClient + SignInReportsClient *msgraph.SignInReportsClient + SynchronizationJobClient *msgraph.SynchronizationJobClient + TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient + TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient + UserFlowAttributesClient *msgraph.UserFlowAttributesClient + UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + UsersClient *msgraph.UsersClient + WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient } func NewTest(t *testing.T) (c *Test) { @@ -247,6 +247,11 @@ func NewTest(t *testing.T) (c *Test) { c.AuthenticationMethodsClient.BaseClient.Endpoint = *endpoint c.AuthenticationMethodsClient.BaseClient.RetryableClient.RetryMax = retry + c.AuthenticationStrengthPoliciesClient = msgraph.NewAuthenticationStrengthPoliciesClient() + c.AuthenticationStrengthPoliciesClient.BaseClient.Authorizer = c.Connections["default"].Authorizer + c.AuthenticationStrengthPoliciesClient.BaseClient.Endpoint = *endpoint + c.AuthenticationStrengthPoliciesClient.BaseClient.RetryableClient.RetryMax = retry + c.B2CUserFlowClient = msgraph.NewB2CUserFlowClient() c.B2CUserFlowClient.BaseClient.Authorizer = c.Connections["b2c"].Authorizer c.B2CUserFlowClient.BaseClient.Endpoint = *endpoint diff --git a/msgraph/authentication_strength_policy.go b/msgraph/authentication_strength_policy.go new file mode 100644 index 00000000..25efbe5e --- /dev/null +++ b/msgraph/authentication_strength_policy.go @@ -0,0 +1,158 @@ +package msgraph + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +// AuthenticationStrengthPoliciesClient performs operations on AuthenticationStrengthPolicy. +type AuthenticationStrengthPoliciesClient struct { + BaseClient Client +} + +// NewAuthenticationStrengthPoliciesClient returns a new AuthenticationStrengthPoliciesClient +func NewAuthenticationStrengthPoliciesClient() *AuthenticationStrengthPoliciesClient { + return &AuthenticationStrengthPoliciesClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// List returns a list of AuthenticationStrengthPolicy, optionally queried using OData. +func (c *AuthenticationStrengthPoliciesClient) List(ctx context.Context, query odata.Query) (*[]AuthenticationStrengthPolicy, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/policies/authenticationStrengthPolicies", + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AuthenticationStrengthPoliciesClient.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 { + AuthenticationStrengthPolicys []AuthenticationStrengthPolicy `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.AuthenticationStrengthPolicys, status, nil +} + +// Create creates a new AuthenticationStrengthPolicy. +func (c *AuthenticationStrengthPoliciesClient) Create(ctx context.Context, authenticationStrengthPolicy AuthenticationStrengthPolicy) (*AuthenticationStrengthPolicy, int, error) { + var status int + body, err := json.Marshal(authenticationStrengthPolicy) + if err != nil { + return nil, status, fmt.Errorf("json.Marshal(): %v", err) + } + + resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + ValidStatusCodes: []int{http.StatusCreated}, + Uri: Uri{ + Entity: "/policies/authenticationStrengthPolicies", + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AuthenticationStrengthPoliciesClient.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 newAuthenticationStrengthPolicy AuthenticationStrengthPolicy + if err := json.Unmarshal(respBody, &newAuthenticationStrengthPolicy); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &newAuthenticationStrengthPolicy, status, nil +} + +// Get retrieves a AuthenticationStrengthPolicy. +func (c *AuthenticationStrengthPoliciesClient) Get(ctx context.Context, id string, query odata.Query) (*AuthenticationStrengthPolicy, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/authenticationStrengthPolicies/%s", id), + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AuthenticationStrengthPoliciesClient.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 AuthenticationStrengthPolicy AuthenticationStrengthPolicy + if err := json.Unmarshal(respBody, &AuthenticationStrengthPolicy); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &AuthenticationStrengthPolicy, status, nil +} + +// Update amends an existing AuthenticationStrengthPolicy. +func (c *AuthenticationStrengthPoliciesClient) Update(ctx context.Context, AuthenticationStrengthPolicy AuthenticationStrengthPolicy) (int, error) { + var status int + + if AuthenticationStrengthPolicy.ID == nil { + return status, errors.New("cannot update AuthenticationStrengthPolicy with nil ID") + } + + body, err := json.Marshal(AuthenticationStrengthPolicy) + 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.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/policies/authenticationStrengthPolicies/%s", *AuthenticationStrengthPolicy.ID), + }, + }) + if err != nil { + return status, fmt.Errorf("AuthenticationStrengthPoliciesClient.BaseClient.Patch(): %v", err) + } + + return status, nil +} + +// Delete removes a AuthenticationStrengthPolicy. +func (c *AuthenticationStrengthPoliciesClient) 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/authenticationStrengthPolicies/%s/$ref", id), + }, + }) + if err != nil { + return status, fmt.Errorf("AuthenticationStrengthPoliciesClient.BaseClient.Delete(): %v", err) + } + + return status, nil +} diff --git a/msgraph/authentication_strength_policy_test.go b/msgraph/authentication_strength_policy_test.go new file mode 100644 index 00000000..b63bf482 --- /dev/null +++ b/msgraph/authentication_strength_policy_test.go @@ -0,0 +1,96 @@ +package msgraph_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" + "github.com/manicminer/hamilton/internal/test" + "github.com/manicminer/hamilton/internal/utils" + "github.com/manicminer/hamilton/msgraph" +) + +func TestAuthenticationStrengthPolicyClient(t *testing.T) { + c := test.NewTest(t) + defer c.CancelFunc() + + policy := testAuthenticationStrengthPoliciesClient_Create(t, c, msgraph.AuthenticationStrengthPolicy{ + DisplayName: utils.StringPtr(fmt.Sprintf("test-policy-%s", c.RandomString)), + Description: utils.StringPtr("Password and Hardware OATH"), + AllowedCombinations: &[]string{"password, hardwareOath"}, + }, + ) + + updatePolicy := msgraph.AuthenticationStrengthPolicy{ + ID: policy.ID, + DisplayName: utils.StringPtr(fmt.Sprintf("test-policy-updated-%s", c.RandomString)), + } + testAuthenticationStrengthPoliciesClient_Update(t, c, updatePolicy) + + testAuthenticationStrengthPoliciesClient_List(t, c) + testAuthenticationStrengthPoliciesClient_Get(t, c, *policy.ID) + testAuthenticationStrengthPoliciesClient_Delete(t, c, *policy.ID) + +} + +func testAuthenticationStrengthPoliciesClient_Create(t *testing.T, c *test.Test, a msgraph.AuthenticationStrengthPolicy) (authenticationStrengthPolicy *msgraph.AuthenticationStrengthPolicy) { + authenticationStrengthPolicy, status, err := c.AuthenticationStrengthPoliciesClient.Create(c.Context, a) + if err != nil { + t.Fatalf("AuthenticationStrengthPolicyClient.Create(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AuthenticationStrengthPolicyClient.Create(): invalid status: %d", status) + } + if authenticationStrengthPolicy == nil { + t.Fatal("AuthenticationStrengthPolicyClient.Create(): authenticationStrengthPolicy was nil") + } + if authenticationStrengthPolicy.ID == nil { + t.Fatal("AuthenticationStrengthPolicyClient.Create(): authenticationStrengthPolicy.ID was nil") + } + return +} + +func testAuthenticationStrengthPoliciesClient_Get(t *testing.T, c *test.Test, id string) (policy *msgraph.AuthenticationStrengthPolicy) { + policy, status, err := c.AuthenticationStrengthPoliciesClient.Get(c.Context, id, odata.Query{}) + if err != nil { + t.Fatalf("AuthenticationStrengthPolicyClient.Get(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AuthenticationStrengthPolicyClient.Get(): invalid status: %d", status) + } + if policy == nil { + t.Fatal("AuthenticationStrengthPolicyClient.Get(): policy was nil") + } + return +} + +func testAuthenticationStrengthPoliciesClient_Update(t *testing.T, c *test.Test, policy msgraph.AuthenticationStrengthPolicy) { + status, err := c.AuthenticationStrengthPoliciesClient.Update(c.Context, policy) + if err != nil { + t.Fatalf("AuthenticationStrengthPolicyClient.Update(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AuthenticationStrengthPolicyClient.Update(): invalid status: %d", status) + } +} + +func testAuthenticationStrengthPoliciesClient_List(t *testing.T, c *test.Test) (policies *[]msgraph.AuthenticationStrengthPolicy) { + policies, _, err := c.AuthenticationStrengthPoliciesClient.List(c.Context, odata.Query{}) + if err != nil { + t.Fatalf("AuthenticationStrengthPolicyClient.List(): %v", err) + } + if policies == nil { + t.Fatal("AuthenticationStrengthPolicyClient.List(): policies was nil") + } + return +} + +func testAuthenticationStrengthPoliciesClient_Delete(t *testing.T, c *test.Test, id string) { + status, err := c.AuthenticationStrengthPoliciesClient.Delete(c.Context, id) + if err != nil { + t.Fatalf("AuthenticationStrengthPolicyClient.Delete(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AuthenticationStrengthPolicyClient.Delete(): invalid status: %d", status) + } +} diff --git a/msgraph/conditionalaccesspolicy_test.go b/msgraph/conditionalaccesspolicy_test.go index ff8034a3..5aa84283 100644 --- a/msgraph/conditionalaccesspolicy_test.go +++ b/msgraph/conditionalaccesspolicy_test.go @@ -20,6 +20,13 @@ func TestConditionalAccessPolicyClient(t *testing.T) { testExcGroup := testGroup_Create(t, c, "test-conditionalAccessPolicy-exc") testUser := testUser_Create(t, c) + authStrengthPolicy := testAuthenticationStrengthPoliciesClient_Create(t, c, msgraph.AuthenticationStrengthPolicy{ + DisplayName: utils.StringPtr(fmt.Sprintf("test-policy-%s", c.RandomString)), + Description: utils.StringPtr("Password and Hardware OATH token"), + AllowedCombinations: &[]string{"password, hardwareOath"}, + }, + ) + policy := testConditionalAccessPolicysClient_Create(t, c, msgraph.ConditionalAccessPolicy{ DisplayName: utils.StringPtr(fmt.Sprintf("test-policy-%s", c.RandomString)), State: utils.StringPtr("enabled"), @@ -42,6 +49,9 @@ func TestConditionalAccessPolicyClient(t *testing.T) { GrantControls: &msgraph.ConditionalAccessGrantControls{ Operator: utils.StringPtr("OR"), BuiltInControls: &[]string{"block"}, + AuthenticationStrength: &msgraph.AuthenticationStrengthPolicy{ + ID: authStrengthPolicy.ID, + }, }, }) @@ -58,6 +68,8 @@ func TestConditionalAccessPolicyClient(t *testing.T) { testGroup_Delete(t, c, testIncGroup) testGroup_Delete(t, c, testExcGroup) testUser_Delete(t, c, testUser) + testAuthenticationStrengthPoliciesClient_Delete(t, c, *authStrengthPolicy.ID) + } func testConditionalAccessPolicysClient_Create(t *testing.T, c *test.Test, a msgraph.ConditionalAccessPolicy) (conditionalAccessPolicy *msgraph.ConditionalAccessPolicy) { diff --git a/msgraph/models.go b/msgraph/models.go index 6bbc4415..1d137eb9 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -598,6 +598,16 @@ type AuditActivityInitiator struct { type AuthenticationMethod interface{} +type AuthenticationStrengthPolicy struct { + AllowedCombinations *[]AuthenticationMethodModes `json:"allowedCombinations,omitempty"` + CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` + ID *string `json:"id,omitempty"` + ModifiedDateTime *time.Time `json:"modifiedDateTime,omitempty"` + PolicyType *AuthenticationStrengthPolicyType `json:"policyType,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` +} + type BaseNamedLocation struct { ODataType *odata.Type `json:"@odata.type,omitempty"` ID *string `json:"id,omitempty"` @@ -662,6 +672,7 @@ type ConditionalAccessFilter struct { type ConditionalAccessGrantControls struct { Operator *string `json:"operator,omitempty"` + AuthenticationStrength *AuthenticationStrengthPolicy `json:"authenticationStrength,omitempty"` BuiltInControls *[]ConditionalAccessGrantControl `json:"builtInControls,omitempty"` CustomAuthenticationFactors *[]string `json:"customAuthenticationFactors,omitempty"` TermsOfUse *[]string `json:"termsOfUse,omitempty"` diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index 7d187e61..b4e070bb 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -260,6 +260,28 @@ const ( AuthenticationMethodKeyStrengthUnknown AuthenticationMethodKeyStrength = "unknown" ) +type AuthenticationMethodModes = string + +const ( + AuthenticationMethodModesEmail AuthenticationMethodModes = "email" + AuthenticationMethodModesFederatedMultiFactor AuthenticationMethodModes = "federatedMultiFactor" + AuthenticationMethodModesFederatedSingleFactor AuthenticationMethodModes = "federatedSingleFactor" + AuthenticationMethodModesFido2 AuthenticationMethodModes = "fido2" + AuthenticationMethodModesHardwareOath AuthenticationMethodModes = "hardwareOath" + AuthenticationMethodModesMicrosoftAuthenticatorPush AuthenticationMethodModes = "microsoftAuthenticatorPush" + AuthenticationMethodModesMicrosoftDeviceBasedPush AuthenticationMethodModes = "deviceBasedPush" + AuthenticationMethodModesPassword AuthenticationMethodModes = "password" + AuthenticationMethodModesSms AuthenticationMethodModes = "sms" + AuthenticationMethodModesSoftwareOath AuthenticationMethodModes = "softwareOath" + AuthenticationMethodModesTemporaryAccessPassMultiUse AuthenticationMethodModes = "temporaryAccessPassMultiUse" + AuthenticationMethodModesTemporaryAccessPassOneTime AuthenticationMethodModes = "temporaryAccessPassOneTime" + AuthenticationMethodModesUnknownFutureValue AuthenticationMethodModes = "unknownFutureValue" + AuthenticationMethodModesVoice AuthenticationMethodModes = "voice" + AuthenticationMethodModesWindowsHelloForBusiness AuthenticationMethodModes = "windowsHelloForBusiness" + AuthenticationMethodModesX509CertificateMultiFactor AuthenticationMethodModes = "x509CertificateMultiFactor" + AuthenticationMethodModesX509CertificateSingleFactor AuthenticationMethodModes = "x509CertificateSingleFactor" +) + type AuthenticationPhoneType = string const ( @@ -268,6 +290,14 @@ const ( AuthenticationPhoneTypeOffice AuthenticationPhoneType = "office" ) +type AuthenticationStrengthPolicyType = string + +const ( + AuthenticationStrengthPolicyTypeBuiltIn AuthenticationStrengthPolicyType = "builtIn" + AuthenticationStrengthPolicyTypeCustom AuthenticationStrengthPolicyType = "custom" + AuthenticationStrengthPolicyTypeUnknownFutureValue AuthenticationStrengthPolicyType = "unknownFutureValue" +) + type BodyType = string const ( From dc272e34695788f7ac711647856e53d460d6e1bf Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Mon, 24 Jul 2023 22:32:29 +0100 Subject: [PATCH 11/22] Changelog for #249 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 484344aa..e48d1324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.63.0 (Unreleased) + +- Support for [Authentication Strength Policies](https://learn.microsoft.com/en-us/graph/api/resources/authenticationstrengthpolicy?view=graph-rest-1.0) ([#249](https://github.com/manicminer/hamilton/pull/249)) + ## 0.62.0 (July 14, 2023) - Support for deleting an `accessPackageResourceRoleScope` ([#245](https://github.com/manicminer/hamilton/pull/245)) From 084645405490dd5d3d406b24362a4a57fb644174 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Tue, 25 Jul 2023 23:41:57 +0100 Subject: [PATCH 12/22] Bugfix: Conditional Access Policies can have grantControls or sessionControls, or both, but must be explicitly null in the `or` case --- msgraph/models.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgraph/models.go b/msgraph/models.go index 1d137eb9..ce1595e1 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -693,10 +693,10 @@ type ConditionalAccessPolicy struct { Conditions *ConditionalAccessConditionSet `json:"conditions,omitempty"` CreatedDateTime *time.Time `json:"createdDateTime,omitempty"` DisplayName *string `json:"displayName,omitempty"` - GrantControls *ConditionalAccessGrantControls `json:"grantControls,omitempty"` + GrantControls *ConditionalAccessGrantControls `json:"grantControls"` ID *string `json:"id,omitempty"` ModifiedDateTime *time.Time `json:"modifiedDateTime,omitempty"` - SessionControls *ConditionalAccessSessionControls `json:"sessionControls,omitempty"` + SessionControls *ConditionalAccessSessionControls `json:"sessionControls"` State *ConditionalAccessPolicyState `json:"state,omitempty"` } From 876c44853709ff20a250ac015098a9bf2ae18cbf Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 01:24:01 +0100 Subject: [PATCH 13/22] Conditional Access Policies: test fixes --- msgraph/conditionalaccesspolicy_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/msgraph/conditionalaccesspolicy_test.go b/msgraph/conditionalaccesspolicy_test.go index 5aa84283..18a05dbf 100644 --- a/msgraph/conditionalaccesspolicy_test.go +++ b/msgraph/conditionalaccesspolicy_test.go @@ -58,6 +58,26 @@ func TestConditionalAccessPolicyClient(t *testing.T) { updatePolicy := msgraph.ConditionalAccessPolicy{ ID: policy.ID, DisplayName: utils.StringPtr(fmt.Sprintf("test-policy-updated-%s", c.RandomString)), + Conditions: &msgraph.ConditionalAccessConditionSet{ + ClientAppTypes: &[]string{"all"}, + Applications: &msgraph.ConditionalAccessApplications{ + IncludeApplications: &[]string{testAppId}, + }, + Users: &msgraph.ConditionalAccessUsers{ + IncludeUsers: &[]string{"All"}, + ExcludeUsers: &[]string{*testUser.ID(), "GuestsOrExternalUsers"}, + IncludeGroups: &[]string{*testIncGroup.ID()}, + ExcludeGroups: &[]string{*testExcGroup.ID()}, + }, + Locations: &msgraph.ConditionalAccessLocations{ + IncludeLocations: &[]string{"All"}, + ExcludeLocations: &[]string{"AllTrusted"}, + }, + }, + GrantControls: &msgraph.ConditionalAccessGrantControls{ + Operator: utils.StringPtr("OR"), + BuiltInControls: &[]string{"block"}, + }, } testConditionalAccessPolicysClient_Update(t, c, updatePolicy) From 35c686d6db9e1ed3f23bf29d5b40674bbc63dc08 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 12:31:08 +0100 Subject: [PATCH 14/22] Changelog for #250 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e48d1324..ffb47bb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.63.0 (Unreleased) - Support for [Authentication Strength Policies](https://learn.microsoft.com/en-us/graph/api/resources/authenticationstrengthpolicy?view=graph-rest-1.0) ([#249](https://github.com/manicminer/hamilton/pull/249)) +- Bugfix: Support for specifying `null` values for `grantControls` or `sessionControls` within [Conditional Access Policies](https://learn.microsoft.com/en-us/graph/api/resources/conditionalaccesspolicy?view=graph-rest-1.0) ([#250](https://github.com/manicminer/hamilton/pull/250)) ## 0.62.0 (July 14, 2023) From ace2a2649e37a8b420d8ade7ce1dcfd2ad6b50be Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 00:32:45 +0100 Subject: [PATCH 15/22] Support `Manager` value for AccessReviewReviewerType --- msgraph/valuetypes.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index b4e070bb..6ac94764 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -131,8 +131,9 @@ const ( type AccessReviewReviewerType = string const ( - AccessReviewReviewerTypeSelf AccessReviewReviewerType = "Self" + AccessReviewReviewerTypeManager AccessReviewReviewerType = "Manager" AccessReviewReviewerTypeReviewers AccessReviewReviewerType = "Reviewers" + AccessReviewReviewerTypeSelf AccessReviewReviewerType = "Self" ) type AccessReviewRecurranceType = string From 7edbccd06dcdf4e2c8cdfa41a7cc424bfe423721 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 14:22:53 +0100 Subject: [PATCH 16/22] Changelog for #251 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb47bb6..cfcf0d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.63.0 (Unreleased) - Support for [Authentication Strength Policies](https://learn.microsoft.com/en-us/graph/api/resources/authenticationstrengthpolicy?view=graph-rest-1.0) ([#249](https://github.com/manicminer/hamilton/pull/249)) +- Support `Manager` value for `AccessReviewReviewerType` ([#251](https://github.com/manicminer/hamilton/pull/251)) - Bugfix: Support for specifying `null` values for `grantControls` or `sessionControls` within [Conditional Access Policies](https://learn.microsoft.com/en-us/graph/api/resources/conditionalaccesspolicy?view=graph-rest-1.0) ([#250](https://github.com/manicminer/hamilton/pull/250)) ## 0.62.0 (July 14, 2023) From 449ebc5fbb1875f72d7552a35ea5a06cac03dce1 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 14:03:12 +0100 Subject: [PATCH 17/22] Fix some constant typos --- msgraph/accesspackageassignmentpolicy_test.go | 2 +- msgraph/accesspackageassignmentrequest_test.go | 2 +- msgraph/models.go | 2 +- msgraph/valuetypes.go | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/msgraph/accesspackageassignmentpolicy_test.go b/msgraph/accesspackageassignmentpolicy_test.go index 770b8d62..36fdde62 100644 --- a/msgraph/accesspackageassignmentpolicy_test.go +++ b/msgraph/accesspackageassignmentpolicy_test.go @@ -31,7 +31,7 @@ func TestAccessPackageAssignmentPolicyClient(t *testing.T) { IsEnabled: utils.BoolPtr(true), StartDateTime: ¤tTimePlusDay, DurationInDays: utils.Int32Ptr(5), - RecurrenceType: msgraph.AccessReviewRecurranceTypeMonthly, + RecurrenceType: msgraph.AccessReviewRecurrenceTypeMonthly, ReviewerType: msgraph.AccessReviewReviewerTypeSelf, IsAccessRecommendationEnabled: utils.BoolPtr(true), IsApprovalJustificationRequired: utils.BoolPtr(true), diff --git a/msgraph/accesspackageassignmentrequest_test.go b/msgraph/accesspackageassignmentrequest_test.go index 4a4398d8..186fba5c 100644 --- a/msgraph/accesspackageassignmentrequest_test.go +++ b/msgraph/accesspackageassignmentrequest_test.go @@ -65,7 +65,7 @@ func TestAccessPackageAssignmentRequestClient(t *testing.T) { IsEnabled: utils.BoolPtr(true), StartDateTime: ¤tTime, DurationInDays: utils.Int32Ptr(5), - RecurrenceType: msgraph.AccessReviewRecurranceTypeMonthly, + RecurrenceType: msgraph.AccessReviewRecurrenceTypeMonthly, ReviewerType: msgraph.AccessReviewReviewerTypeSelf, IsAccessRecommendationEnabled: utils.BoolPtr(true), IsApprovalJustificationRequired: utils.BoolPtr(true), diff --git a/msgraph/models.go b/msgraph/models.go index ce1595e1..14de6960 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -581,7 +581,7 @@ type ApprovalStep struct { type AssignmentReviewSettings struct { IsEnabled *bool `json:"isEnabled,omitempty"` - RecurrenceType AccessReviewRecurranceType `json:"recurrenceType,omitempty"` + RecurrenceType AccessReviewRecurrenceType `json:"recurrenceType,omitempty"` ReviewerType AccessReviewReviewerType `json:"reviewerType,omitempty"` StartDateTime *time.Time `json:"startDateTime,omitempty"` DurationInDays *int32 `json:"durationInDays,omitempty"` diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index 6ac94764..3705032e 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -67,7 +67,7 @@ const ( AccessPackageRequestStateSubmitted AccessPackageRequestState = "submitted" AccessPackageRequestStatePendingApproval AccessPackageRequestState = "pendingApproval" AccessPackageRequestStateDelivering AccessPackageRequestState = "delivering" - AccessPackageRequestStateDelivered AccessPackageRequestState = "delievered" + AccessPackageRequestStateDelivered AccessPackageRequestState = "delivered" AccessPackageRequestStateDeliveryFailed AccessPackageRequestState = "deliveryFailed" AccessPackageRequestStateDenied AccessPackageRequestState = "denied" AccessPackageRequestStateScheduled AccessPackageRequestState = "scheduled" @@ -79,7 +79,7 @@ type AccessPackageRequestType = string const ( AccessPackageRequestTypeNotSpecified AccessPackageRequestType = "notSpecified" - AccessPackageRequestTypeuserAdd AccessPackageRequestType = "userAdd" + AccessPackageRequestTypeUserAdd AccessPackageRequestType = "userAdd" AccessPackageRequestTypeUserExtend AccessPackageRequestType = "UserExtend" AccessPackageRequestTypeUserUpdate AccessPackageRequestType = "userUpdate" AccessPackageRequestTypeUserRemove AccessPackageRequestType = "userRemove" @@ -136,14 +136,14 @@ const ( AccessReviewReviewerTypeSelf AccessReviewReviewerType = "Self" ) -type AccessReviewRecurranceType = string +type AccessReviewRecurrenceType = string const ( - AccessReviewRecurranceTypeWeekly AccessReviewRecurranceType = "weekly" - AccessReviewRecurranceTypeMonthly AccessReviewRecurranceType = "monthly" - AccessReviewRecurranceTypeQuarterly AccessReviewRecurranceType = "quarterly" - AccessReviewRecurranceTypeHalfYearly AccessReviewRecurranceType = "halfyearly" - AccessReviewRecurranceTypeAnnual AccessReviewRecurranceType = "annual" + AccessReviewRecurrenceTypeWeekly AccessReviewRecurrenceType = "weekly" + AccessReviewRecurrenceTypeMonthly AccessReviewRecurrenceType = "monthly" + AccessReviewRecurrenceTypeQuarterly AccessReviewRecurrenceType = "quarterly" + AccessReviewRecurrenceTypeHalfYearly AccessReviewRecurrenceType = "halfyearly" + AccessReviewRecurrenceTypeAnnual AccessReviewRecurrenceType = "annual" ) type AdministrativeUnitVisibility = string From 69c939aa2340fe290b844f38b878fb1e87489fdf Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 14:20:40 +0100 Subject: [PATCH 18/22] Enforce 5 minutes default test timeout --- internal/test/testing.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/test/testing.go b/internal/test/testing.go index 1f8e88e5..0b1b3af5 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -7,6 +7,7 @@ import ( "os" "strconv" "testing" + "time" "github.com/hashicorp/go-azure-sdk/sdk/auth" "github.com/hashicorp/go-azure-sdk/sdk/claims" @@ -140,10 +141,12 @@ type Test struct { func NewTest(t *testing.T) (c *Test) { ctx := context.Background() - var cancel context.CancelFunc = func() {} + var cancel context.CancelFunc if deadline, ok := t.Deadline(); ok { - ctx, cancel = context.WithDeadline(context.Background(), deadline) + ctx, cancel = context.WithDeadline(ctx, deadline) + } else { + ctx, cancel = context.WithTimeout(ctx, 5*time.Minute) } c = &Test{ From d21a29d3162aa1eabe1682a022c294cff891ec9b Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 14:58:26 +0100 Subject: [PATCH 19/22] Changelog for #252 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfcf0d8a..c5f20b73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Support for [Authentication Strength Policies](https://learn.microsoft.com/en-us/graph/api/resources/authenticationstrengthpolicy?view=graph-rest-1.0) ([#249](https://github.com/manicminer/hamilton/pull/249)) - Support `Manager` value for `AccessReviewReviewerType` ([#251](https://github.com/manicminer/hamilton/pull/251)) - Bugfix: Support for specifying `null` values for `grantControls` or `sessionControls` within [Conditional Access Policies](https://learn.microsoft.com/en-us/graph/api/resources/conditionalaccesspolicy?view=graph-rest-1.0) ([#250](https://github.com/manicminer/hamilton/pull/250)) +- Bugfix: correct typo in names of `AccessReviewRecurrenceType` values, and in value of `AccessPackageRequestStateDelivered` ([#252](https://github.com/manicminer/hamilton/pull/252)) ## 0.62.0 (July 14, 2023) From 10bf5e445c41fe475f8b0482f9e3094943fcb2e8 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Thu, 27 Jul 2023 14:58:45 +0100 Subject: [PATCH 20/22] v0.63.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5f20b73..7f98d30a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.63.0 (Unreleased) +## 0.63.0 (July 27, 2023) - Support for [Authentication Strength Policies](https://learn.microsoft.com/en-us/graph/api/resources/authenticationstrengthpolicy?view=graph-rest-1.0) ([#249](https://github.com/manicminer/hamilton/pull/249)) - Support `Manager` value for `AccessReviewReviewerType` ([#251](https://github.com/manicminer/hamilton/pull/251)) From 8b5dfd91190ced03e8c64a59872dcdb727406bc0 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Mon, 31 Jul 2023 17:06:38 +1200 Subject: [PATCH 21/22] Fix testing file --- internal/test/testing.go | 94 ++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/internal/test/testing.go b/internal/test/testing.go index 0b1b3af5..cb56d55c 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -91,52 +91,54 @@ type Test struct { Claims *claims.Claims Token *oauth2.Token - AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient - AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient - AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient - AccessPackageClient *msgraph.AccessPackageClient - AccessPackageResourceClient *msgraph.AccessPackageResourceClient - AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient - AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient - AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient - ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient - ApplicationsClient *msgraph.ApplicationsClient - AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient - AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient - AuthenticationStrengthPoliciesClient *msgraph.AuthenticationStrengthPoliciesClient - B2CUserFlowClient *msgraph.B2CUserFlowClient - ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient - ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient - ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient - DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient - DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient - DirectoryObjectsClient *msgraph.DirectoryObjectsClient - DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient - DirectoryRolesClient *msgraph.DirectoryRolesClient - DomainsClient *msgraph.DomainsClient - EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient - EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient - GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - GroupsClient *msgraph.GroupsClient - IdentityProvidersClient *msgraph.IdentityProvidersClient - InvitationsClient *msgraph.InvitationsClient - MeClient *msgraph.MeClient - NamedLocationsClient *msgraph.NamedLocationsClient - ReportsClient *msgraph.ReportsClient - RoleAssignmentsClient *msgraph.RoleAssignmentsClient - RoleDefinitionsClient *msgraph.RoleDefinitionsClient - RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient - SchemaExtensionsClient *msgraph.SchemaExtensionsClient - ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - ServicePrincipalsClient *msgraph.ServicePrincipalsClient - SignInReportsClient *msgraph.SignInReportsClient - SynchronizationJobClient *msgraph.SynchronizationJobClient - TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient - TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient - UserFlowAttributesClient *msgraph.UserFlowAttributesClient - UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient - UsersClient *msgraph.UsersClient - WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient + AccessPackageAssignmentPolicyClient *msgraph.AccessPackageAssignmentPolicyClient + AccessPackageAssignmentRequestClient *msgraph.AccessPackageAssignmentRequestClient + AccessPackageCatalogClient *msgraph.AccessPackageCatalogClient + AccessPackageClient *msgraph.AccessPackageClient + AccessPackageResourceClient *msgraph.AccessPackageResourceClient + AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient + AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient + AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient + ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient + ApplicationsClient *msgraph.ApplicationsClient + AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient + AuthenticationMethodsClient *msgraph.AuthenticationMethodsClient + AuthenticationStrengthPoliciesClient *msgraph.AuthenticationStrengthPoliciesClient + B2CUserFlowClient *msgraph.B2CUserFlowClient + ClaimsMappingPolicyClient *msgraph.ClaimsMappingPolicyClient + ConditionalAccessPoliciesClient *msgraph.ConditionalAccessPoliciesClient + ConnectedOrganizationClient *msgraph.ConnectedOrganizationClient + DelegatedPermissionGrantsClient *msgraph.DelegatedPermissionGrantsClient + DirectoryAuditReportsClient *msgraph.DirectoryAuditReportsClient + DirectoryObjectsClient *msgraph.DirectoryObjectsClient + DirectoryRoleTemplatesClient *msgraph.DirectoryRoleTemplatesClient + DirectoryRolesClient *msgraph.DirectoryRolesClient + DomainsClient *msgraph.DomainsClient + EntitlementRoleAssignmentsClient *msgraph.EntitlementRoleAssignmentsClient + EntitlementRoleDefinitionsClient *msgraph.EntitlementRoleDefinitionsClient + GroupsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + GroupsClient *msgraph.GroupsClient + IdentityProvidersClient *msgraph.IdentityProvidersClient + InvitationsClient *msgraph.InvitationsClient + MeClient *msgraph.MeClient + NamedLocationsClient *msgraph.NamedLocationsClient + PrivilegedAccessGroupAssignmentScheduleClient *msgraph.PrivilegedAccessGroupAssignmentScheduleClient + PrivilegedAccessGroupAssignmentScheduleRequestClient *msgraph.PrivilegedAccessGroupAssignmentScheduleRequestClient + ReportsClient *msgraph.ReportsClient + RoleAssignmentsClient *msgraph.RoleAssignmentsClient + RoleDefinitionsClient *msgraph.RoleDefinitionsClient + RoleEligibilityScheduleRequestClient *msgraph.RoleEligibilityScheduleRequestClient + SchemaExtensionsClient *msgraph.SchemaExtensionsClient + ServicePrincipalsAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + ServicePrincipalsClient *msgraph.ServicePrincipalsClient + SignInReportsClient *msgraph.SignInReportsClient + SynchronizationJobClient *msgraph.SynchronizationJobClient + TermsOfUseAgreementClient *msgraph.TermsOfUseAgreementClient + TokenIssuancePolicyClient *msgraph.TokenIssuancePolicyClient + UserFlowAttributesClient *msgraph.UserFlowAttributesClient + UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient + UsersClient *msgraph.UsersClient + WindowsAutopilotDeploymentProfilesClient *msgraph.WindowsAutopilotDeploymentProfilesClient } func NewTest(t *testing.T) (c *Test) { From 5389a8502f8f0ad556829ef3d56afb0e01515afe Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 8 Aug 2023 18:20:10 +1200 Subject: [PATCH 22/22] Create Register function to enable group for PIM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally found it, though it is part of the v2 API and not v3 😢 --- internal/test/testing.go | 6 ++++ msgraph/privilegedaccess_groups.go | 44 +++++++++++++++++++++++++ msgraph/privilegedaccess_groups_test.go | 35 ++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 msgraph/privilegedaccess_groups.go create mode 100644 msgraph/privilegedaccess_groups_test.go diff --git a/internal/test/testing.go b/internal/test/testing.go index cb56d55c..6a510bb9 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -122,6 +122,7 @@ type Test struct { InvitationsClient *msgraph.InvitationsClient MeClient *msgraph.MeClient NamedLocationsClient *msgraph.NamedLocationsClient + PrivilegedAccessGroupClient *msgraph.PrivilegedAccessGroupClient PrivilegedAccessGroupAssignmentScheduleClient *msgraph.PrivilegedAccessGroupAssignmentScheduleClient PrivilegedAccessGroupAssignmentScheduleRequestClient *msgraph.PrivilegedAccessGroupAssignmentScheduleRequestClient ReportsClient *msgraph.ReportsClient @@ -347,6 +348,11 @@ func NewTest(t *testing.T) (c *Test) { c.NamedLocationsClient.BaseClient.Endpoint = *endpoint c.NamedLocationsClient.BaseClient.RetryableClient.RetryMax = retry + c.PrivilegedAccessGroupClient = msgraph.NewPrivilegedAccessGroupClient() + c.PrivilegedAccessGroupClient.BaseClient.Authorizer = c.Connections["default"].Authorizer + c.PrivilegedAccessGroupClient.BaseClient.Endpoint = *endpoint + c.PrivilegedAccessGroupClient.BaseClient.RetryableClient.RetryMax = retry + c.ReportsClient = msgraph.NewReportsClient() c.ReportsClient.BaseClient.Authorizer = c.Connections["default"].Authorizer c.ReportsClient.BaseClient.Endpoint = *endpoint diff --git a/msgraph/privilegedaccess_groups.go b/msgraph/privilegedaccess_groups.go new file mode 100644 index 00000000..40d3b238 --- /dev/null +++ b/msgraph/privilegedaccess_groups.go @@ -0,0 +1,44 @@ +package msgraph + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/go-azure-sdk/sdk/odata" +) + +type PrivilegedAccessGroupClient struct { + BaseClient Client +} + +func NewPrivilegedAccessGroupClient() *PrivilegedAccessGroupClient { + return &PrivilegedAccessGroupClient{ + BaseClient: NewClient(VersionBeta), + } +} + +// Register enables a group for PIM. +// Technically this is part of the deprecated v2 PIM API, however there is no equivilent in v3 +// and automatic enablement doesn't work for service principals with assigned permissions. +func (c *PrivilegedAccessGroupClient) Register(ctx context.Context, groupId string) (int, error) { + // We get an unknown 401 error if the group has not fully provisioned before + // attempting to enable PIM. + consistencyFunc := func(resp *http.Response, o *odata.OData) bool { + return o != nil && o.Error != nil && resp.StatusCode == http.StatusUnauthorized + } + + _, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + ConsistencyFailureFunc: consistencyFunc, + Body: []byte(fmt.Sprintf("{\"externalId\": \"%s\"}", groupId)), + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/privilegedAccess/aadGroups/resources/register", + }, + }) + if err != nil { + return status, fmt.Errorf("PrivilegedAccessGroupClient.BaseClient.Post(): %v", err) + } + + return status, nil +} diff --git a/msgraph/privilegedaccess_groups_test.go b/msgraph/privilegedaccess_groups_test.go new file mode 100644 index 00000000..23a930af --- /dev/null +++ b/msgraph/privilegedaccess_groups_test.go @@ -0,0 +1,35 @@ +package msgraph_test + +import ( + "fmt" + "testing" + + "github.com/manicminer/hamilton/internal/test" + "github.com/manicminer/hamilton/internal/utils" + "github.com/manicminer/hamilton/msgraph" +) + +func TestPrivilegedAccessGroupClient(t *testing.T) { + c := test.NewTest(t) + defer c.CancelFunc() + + pimGroup := testGroupsClient_Create(t, c, msgraph.Group{ + DisplayName: utils.StringPtr("test-group"), + MailEnabled: utils.BoolPtr(false), + MailNickname: utils.StringPtr(fmt.Sprintf("test-group-%s", c.RandomString)), + SecurityEnabled: utils.BoolPtr(true), + }) + defer testGroupsClient_Delete(t, c, *pimGroup.ID()) + + testPrivilegedAccessGroupClient_Register(t, c, *pimGroup.ID()) +} + +func testPrivilegedAccessGroupClient_Register(t *testing.T, c *test.Test, groupId string) { + status, err := c.PrivilegedAccessGroupClient.Register(c.Context, groupId) + if err != nil { + t.Fatalf("PrivilegedAccessGroupClient.Register(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("PrivilegedAccessGroupClient.Register(): invalid status: %d", status) + } +}