Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RoleEligibilityScheduleRequestClient #204

Merged
merged 6 commits into from
Jul 14, 2023
Merged

Conversation

JonasBak
Copy link
Contributor

This PR adds a RoleEligibilityScheduleRequestClient, which lets us use the PIM API for managing role eligibilities. This is part of a PR to the https://github.com/hashicorp/terraform-provider-azuread repo, where we would like to be able to manage role eligibilities through terraform.

I havn't written any tests, as I wanted to get some input on how this should be done. The user/service principal requires a role and a permission to be able to use the API. Should I set up the permissions as part of the test (and remove them after)? Should I assume the calling service principal has the correct roles and permissions?

@manicminer
Copy link
Owner

Hi @JonasBak, thanks for submitting this, your contribution is very appreciated! Apologies for the delayed response - this is looking good so far! When it comes to the tests, don't worry about the permissions as we'll add these as needed to our testing principal (it doesn't have the privilege to create its own role assignments anyway).

@JonasBak
Copy link
Contributor Author

I lost access to the "sandbox tenant" I used when I started working on this, so I didn't prioritize it for a while, but it looks like someone created their own PR 🙌 If that gets merged, I'll just update my PR to the terraform provider.

@JonasBak
Copy link
Contributor Author

JonasBak commented May 3, 2023

I rebased and added a basic test

Copy link
Owner

@manicminer manicminer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JonasBak Thanks for continuing to work on this and for adding the test. This is off to a great start and with some extra work to support all the fields and methods for this resource, this will be a great addition. I've made some comments below - if you can take a look at these, I'll be happy to re-review and we can look to try and get this merged. Thanks!

Comment on lines 1970 to 1979
type UnifiedRoleEligibilityScheduleRequest struct {
DirectoryObject

Action *string `json:"action,omitempty"`
DirectoryScopeId *string `json:"directoryScopeId,omitempty"`
Justification *string `json:"justification,omitempty"`
PrincipalId *string `json:"principalId,omitempty"`
RoleDefinitionId *string `json:"roleDefinitionId,omitempty"`
ScheduleInfo *interface{} `json:"scheduleInfo,omitempty"`
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type of object isn't a directoryObject, so it should not embed the DirectoryObject struct and should instead have an Id field, e.g.

	Id                *string      `json:"id,omitempty"`

It looks like the model is missing quite a lot of fields? From the documentation: approvalId, appScopeId, completedDateTime, createdDateTime, directoryScopeId, isValidationOnly, status, targetScheduleId, and ticketInfo.

Additionally, the ScheduleInfo field should have a RequestSchedule struct type defined for it. The Action field should also be a custom aliased type so that we can define constants for the values, e.g.

	Action            UnifiedRoleScheduleRequestAction `json:"action,omitempty"`
	ScheduleInfo      *RequestSchedule                 `json:"scheduleInfo,omitempty"`
// this goes in valuetypes.go
type UnifiedRoleScheduleRequestAction = string

const (
	UnifiedRoleScheduleRequestActionAdminAssign        UnifiedRoleScheduleRequestAction = "adminAssign"
	UnifiedRoleScheduleRequestActionAdminExtend        UnifiedRoleScheduleRequestAction = "adminExtend"
	UnifiedRoleScheduleRequestActionAdminRemove        UnifiedRoleScheduleRequestAction = "adminRemove"
	UnifiedRoleScheduleRequestActionAdminRenew         UnifiedRoleScheduleRequestAction = "adminRenew"
	UnifiedRoleScheduleRequestActionAdminUpdate        UnifiedRoleScheduleRequestAction = "adminUpdate"
	UnifiedRoleScheduleRequestActionSelfActivate       UnifiedRoleScheduleRequestAction = "selfActivate"
	UnifiedRoleScheduleRequestActionSelfDeactivate     UnifiedRoleScheduleRequestAction = "selfDeactivate"
	UnifiedRoleScheduleRequestActionSelfExtend         UnifiedRoleScheduleRequestAction = "selfExtend"
	UnifiedRoleScheduleRequestActionSelfRenew          UnifiedRoleScheduleRequestAction = "selfRenew"
	UnifiedRoleScheduleRequestActionUnknownFutureValue UnifiedRoleScheduleRequestAction = "unknownFutureValue"
)

Lastly, although this is more of a niggle, could we move this struct furthe rup the file to around line 1691 to maintain ordering as much as possible (I realise there are some other structs appended to the end of this file, they'll get tidied up separately).

Comment on lines 13 to 14
var actionAdminAssign string = "adminAssign"
var actionAdminRemove string = "adminRemove"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per above, these values should be constants in valuetypes.go

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will also want to support the List and Cancel operations for this resource

},
})
if err != nil {
return status, fmt.Errorf("RoleAssignments.BaseClient.Get(): %v", err)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to check through all the error messages to make sure they reflect the correct client and method.

@JonasBak
Copy link
Contributor Author

Thanks for the feedback 🙌 I have some problems with the test being flaky, as it sometimes fails with RoleNotFound: The role is not found, what can I do to improve this?

@JonasBak
Copy link
Contributor Author

JonasBak commented May 11, 2023

Also, should I add the recurrence field in requestSchedule? It says that it's unsupported in PIM. I also have some questions regarding how I should implement the Create function. Create in the docs supports multiple actions such as adminAssign to create the assignment, or adminRemove to remove/delete the assignment. I feel like it looks weird to call client.Create(...) to delete the assignment, so I implemented a Create function that sets the action to adminAssign, and a Delete function that sets it to adminRemove. Should I change it to "stay true" to the documentation? If not, how should the other actions be handled?

@manicminer
Copy link
Owner

manicminer commented May 11, 2023

@JonasBak I'd suggest leaving out the recurrence field if the docs explicitly say it doesn't work - I usually decide this based on whether a particular field appears to work even if the docs contradict observations.

I agree it's a little odd to have an effective deletion (i.e. removal/revocation) via the same method and operation as Create. However, for better or worse, this is the way the API is designed and for simplicity it's maybe better to expose this implementation detail to the user and leave it to them to decide how that fits in with their use case. For example with the AzureAD TF provider, we'd still have explicit Create, Update and Destroy operations even if they all call the same 'Create' method but with different arguments.

When it comes to replication delays, the SDK has some built in retry capability but needs to be configured using a ConsistencyFailureFunc so it only retries under appropriate circumstances. A good example of this can be seen in the ServicePrincipalsClient, where the error response is inspected and the operation retried if it's likely the linked application hasn't fully replicated.

Hope this helps!

@JonasBak
Copy link
Contributor Author

JonasBak commented May 23, 2023

Seems like I just didn't understand how the different "role types" work when writing the test 😅 But now it passes ✅

I haven't added a test for the Cancel function, as that requires me to first activate it, which seems to use the roleAssignmentScheduleRequests API, not roleEligibilityScheduleRequests (even though it seems to support a selfActivate action).

Copy link
Owner

@manicminer manicminer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for your work on this @JonasBak. This is looking good to me, I think it's fine to omit the test for the Cancel method for now, we can look at it again once we can support the entire workflow.

The test failure seems unrelated, so I'm happy to merge this. Thanks again!

@manicminer manicminer merged commit c9383c8 into manicminer:main Jul 14, 2023
1 of 2 checks passed
@manicminer manicminer added this to the v0.62.0 milestone Jul 14, 2023
manicminer added a commit that referenced this pull request Jul 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request package/msgraph
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants