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

Adds CRUD service for Identity Center resources #47609

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

tcsc
Copy link
Contributor

@tcsc tcsc commented Oct 16, 2024

This is just the pure CRUD read/write. Caching & watching support coming as
necessary in subsequent PRs.

@tcsc tcsc added the no-changelog Indicates that a PR does not require a changelog entry label Oct 16, 2024
lib/services/identitycenter.go Outdated Show resolved Hide resolved
CreateAccountAssignment(context.Context, IdentityCenterAccountAssignment) (IdentityCenterAccountAssignment, error)

// GetAccountAssignment fetches a specific Account Assignment record.
GetAccountAssignment(context.Context, IdentityCenterAccountAssignmentID) (IdentityCenterAccountAssignment, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: might be a personal preference but for me It it a bit overkill to hide and wrap only 1 id string parameter with the separate type IdentityCenterAccountAssignmentID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can see that. The rationale for doing this is all in the Identity Center integration code, which you can't see yet.

Rationale is that there are so many different resource types in flight in the IC integration, so I wanted to make using the wrong ID in the wrong place a compile-time error rather than a debugging session. The CRUD service seemed a reasonable boundary to pack/unpack the IDs, so that everything downstream is checked by the compiler.

But yeah, in isolation, it's very much overkill.

lib/services/local/identitycenter.go Show resolved Hide resolved

// UpdateIdentityCenterAccount performs a conditional update on an Identity
// Center Account record, returning the updated record on success.
func (svc *IdentityCenterService) UpdateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (svc *IdentityCenterService) UpdateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
func (svc *IdentityCenterService) UpdateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (*services.IdentityCenterAccount, error) {

// Identity Center Account record, returning the updated record on success.
// Be careful when mixing UpsertIdentityCenterAccount() with resources
// protected by optimistic locking
func (svc *IdentityCenterService) UpsertIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (svc *IdentityCenterService) UpsertIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
func (svc *IdentityCenterService) UpsertIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (*services.IdentityCenterAccount, error) {

}

// GetIdentityCenterAccount fetches a specific Identity Center Account
func (svc *IdentityCenterService) GetIdentityCenterAccount(ctx context.Context, name services.IdentityCenterAccountID) (services.IdentityCenterAccount, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (svc *IdentityCenterService) GetIdentityCenterAccount(ctx context.Context, name services.IdentityCenterAccountID) (services.IdentityCenterAccount, error) {
func (svc *IdentityCenterService) GetIdentityCenterAccount(ctx context.Context, name services.IdentityCenterAccountID) (*services.IdentityCenterAccount, error) {

}

// CreateIdentityCenterAccount creates a new Identity Center Account record
func (svc *IdentityCenterService) CreateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (svc *IdentityCenterService) CreateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (services.IdentityCenterAccount, error) {
func (svc *IdentityCenterService) CreateIdentityCenterAccount(ctx context.Context, acct services.IdentityCenterAccount) (*services.IdentityCenterAccount, error) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The services.IdentityCenterAccount is already just a pointer wrapped in a struct.

I can see making the IdentityCenterService take/return pointers for the sake of consistency, but I didn't think the extra indirection was worth it.

Comment on lines 32 to 33
// allow it to implement the interfaces required for use with the Unified
// Resource listing. IdentityCenterAccount simply wraps a pointer to the
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to confirm. Does the IdentityCenterAccount will be handled in united resource view ?
I thought that in UI the AWS IC account will be represented by Teleport Application not by IdentityCenterAccount resource ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Does the IdentityCenterAccount will be handled in united resource view ?

Not in the proxy but in the auth united resource service. E.g. from the poc implementation we transform IdentityCenterAccount to App Server https://github.com/gravitational/teleport/blob/sshah/idc-dev/lib/services/unified_resource.go#L925

Copy link

@kopiczko kopiczko left a comment

Choose a reason for hiding this comment

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

LGTM after proto.Clone is used as @smallinsky suggested (if possible)

Comment on lines 174 to 182
// IdentityCenterAccountAssignment wraps a raw identitycenterv1.AccountAssignment
// record in a new type to allow it to implement the interfaces required for use
// with the Unified Resource listing. IdentityCenterAccountAssignment simply
// wraps a pointer to the underlying account record, and can be treated as a
// reference-like type.
//
// Copies of an IdentityCenterAccountAssignment will point to the same record.
type IdentityCenterAccountAssignment struct {
*identitycenterv1.AccountAssignment
}

// CloneResource creates a deep copy of the underlying account resource
func (a IdentityCenterAccountAssignment) CloneResource() IdentityCenterAccountAssignment {
var expiry *timestamppb.Timestamp
if a.Metadata.Expires != nil {
expiry = &timestamppb.Timestamp{
Seconds: a.Metadata.Expires.Seconds,
Nanos: a.Metadata.Expires.Nanos,
}
}

return IdentityCenterAccountAssignment{
AccountAssignment: &identitycenterv1.AccountAssignment{
Kind: a.Kind,
SubKind: a.SubKind,
Version: a.Version,
Metadata: &headerv1.Metadata{
Name: a.Metadata.Name,
Namespace: a.Metadata.Namespace,
Description: a.Metadata.Description,
Labels: maps.Clone(a.Metadata.Labels),
Expires: expiry,
Revision: a.Metadata.Revision,
},
Spec: &identitycenterv1.AccountAssignmentSpec{
Display: a.Spec.Display,
AccountId: a.Spec.AccountId,
AccountName: a.Spec.AccountName,
PermissionSet: &identitycenterv1.PermissionSetInfo{
Arn: a.Spec.PermissionSet.Arn,
Name: a.Spec.PermissionSet.Name,
},
},
},
}
}

Choose a reason for hiding this comment

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

Maybe then it makes sense to:

type IdentityCenterAccount identitycenterv1.Account

// CloneResource creates a deep copy of the underlying account resource
func (a *IdentityCenterAccount) CloneResource() *IdentityCenterAccount {
	...
}

I got triggered by those services.IdentityCenterAccount{Account: acct} statements in the implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried that originally - unfortunately it hides all of the other interfaces I need on the Account. I've added some commentary to explain the odd choice of embedding the pointer in a struct.

lib/services/local/identitycenter_test.go Show resolved Hide resolved
lib/services/local/identitycenter_test.go Show resolved Hide resolved
lib/services/local/events_test.go Show resolved Hide resolved
api/types/constants.go Outdated Show resolved Hide resolved
lib/auth/auth.go Outdated Show resolved Hide resolved
Comment on lines 32 to 33
// allow it to implement the interfaces required for use with the Unified
// Resource listing. IdentityCenterAccount simply wraps a pointer to the
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the IdentityCenterAccount will be handled in united resource view ?

Not in the proxy but in the auth united resource service. E.g. from the poc implementation we transform IdentityCenterAccount to App Server https://github.com/gravitational/teleport/blob/sshah/idc-dev/lib/services/unified_resource.go#L925

@marcoandredinis marcoandredinis removed their request for review October 16, 2024 15:09
Copy link
Contributor

@flyinghermit flyinghermit left a comment

Choose a reason for hiding this comment

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

Looks good once existing suggestions by other reviewers are addressed.

lib/services/identitycenter.go Outdated Show resolved Hide resolved
lib/services/identitycenter.go Show resolved Hide resolved
lib/services/local/identitycenter_test.go Outdated Show resolved Hide resolved
lib/services/local/identitycenter_test.go Outdated Show resolved Hide resolved
lib/services/local/identitycenter_test.go Show resolved Hide resolved
lib/services/local/identitycenter_test.go Outdated Show resolved Hide resolved
lib/services/local/identitycenter_test.go Outdated Show resolved Hide resolved
This is just the pure CRUD read/write. Caching & watching support coming as
necessary in subsequent PRs.

Co-authored-by: Pawel Kopiczko <[email protected]>
Co-authored-by: Sakshyam Shah <[email protected]>
}

// CloneResource creates a deep copy of the underlying account resource
func (a *IdentityCenterAccount) CloneResource() IdentityCenterAccount {

Choose a reason for hiding this comment

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

Just spotted this one is a pointer receiver and the other one is a value receiver func (a IdentityCenterAccountAssignment) CloneResource()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-changelog Indicates that a PR does not require a changelog entry size/lg
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants