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

[Feature] Integrate External Auth Principals management #7539

Merged
merged 22 commits into from
Mar 17, 2024

Conversation

Isan-Rivkin
Copy link
Contributor

@Isan-Rivkin Isan-Rivkin commented Mar 7, 2024

Closes #7536

Change Description

Adding auth management endpoints for external principals management such as AWS IAM roles.

Background

As part of getting token in lakeFS from external principals such as IAM role we need to support for the CRUD operations around those attachments between an external principal and lakeFS user.

Testing Details

Added unit tests.

Breaking Change?

  • No breaking changes.
  • It's disabled by default.

Additional Info

More things that needs to be done before this feature is complete:

  1. Docs
  2. The actual login endpoint

@Isan-Rivkin Isan-Rivkin requested a review from idanovo March 7, 2024 15:16
@Isan-Rivkin Isan-Rivkin self-assigned this Mar 7, 2024
@Isan-Rivkin Isan-Rivkin marked this pull request as draft March 7, 2024 15:16
Copy link

github-actions bot commented Mar 7, 2024

♻️ PR Preview 7600075 has been successfully destroyed since this PR has been closed.

🤖 By surge-preview

Copy link

github-actions bot commented Mar 7, 2024

E2E Test Results - DynamoDB Local - Local Block Adapter

10 passed

Copy link
Contributor

@idanovo idanovo left a comment

Choose a reason for hiding this comment

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

Add a few suggestions/questions.
Overall looks good.

api/swagger.yml Outdated Show resolved Hide resolved
api/swagger.yml Outdated
ExternalPrincipal:
type: object
required:
- users
Copy link
Contributor

Choose a reason for hiding this comment

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

Why users and not only user IDs?
Where do we use the other information?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why users and not only user IDs?

Notice users is of type array[string], user IDs.

Where do we use the other information?

Other information is essentially config that will be digested by the remote authenticator.
For example, in AWS remote auth - when we create principal, this will contain flag indicating if we want to use the session name or not.
It's optional, to stay agile it's not specific to anything so that we don't need to break the API tomorrow.

api/swagger.yml Outdated
@@ -2523,7 +2554,98 @@ paths:
description: too many requests
default:
$ref: "#/components/responses/ServerError"

/auth/external/principals:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure what this API returns.
a list of external principals configured for the current installation?

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 used the exact pattern we use for groups, roles, users.
depends on the HTTP verb, one is a list the other will create attachment.

api/swagger.yml Outdated
Comment on lines 2581 to 2586
post:
tags:
- auth
- external
operationId: createExternalPrincipal
summary: Create principal as external identity connected to lakeFS user
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought that external auth are configurable, not something the user need to make an API call to add

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'm not sure what you mean, perhaps a miss understanding?
As the summary suggests (maybe not that well?) it will create a specific principal.
i.e arn:123:role:abc -> user_a.

Isan-Rivkin and others added 2 commits March 7, 2024 17:43
Co-authored-by: Idan Novogroder <43949240+idanovo@users.noreply.github.com>
api/swagger.yml Outdated Show resolved Hide resolved
@idanovo idanovo added the exclude-changelog PR description should not be included in next release changelog label Mar 7, 2024
@Isan-Rivkin
Copy link
Contributor Author

TODO:

  • list external principals -> user api
  • in externalidentity struct -> not users, just userId

@Isan-Rivkin Isan-Rivkin requested a review from idanovo March 10, 2024 09:57
api/swagger.yml Outdated Show resolved Hide resolved
api/swagger.yml Outdated Show resolved Hide resolved
@Isan-Rivkin Isan-Rivkin requested a review from idanovo March 10, 2024 10:21
@Isan-Rivkin
Copy link
Contributor Author

@idanovo please review
i need to add tests and to handle settings optional (see TODO comment in controller) but i want to first sort out the api and interface correctly it's related to both of us.

@@ -2523,6 +2589,104 @@ paths:
description: too many requests
default:
$ref: "#/components/responses/ServerError"

/auth/external/principals:
get:
Copy link
Contributor

Choose a reason for hiding this comment

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

It's either removing this API or making it useful by returning something more than the id

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that getting the list of principals' IDs we have might be useful.
We should consider changing ExternalPrincipalList to return an actual list of ExternalPrincipals so we will get the user IDs too.

pkg/permissions/actions.go Outdated Show resolved Hide resolved
Copy link
Contributor

@idanovo idanovo 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!
Minor comments


func (c *Controller) CreateUserExternalPrincipal(w http.ResponseWriter, r *http.Request, body apigen.CreateUserExternalPrincipalJSONRequestBody, userID, principalID string) {
ctx := r.Context()
if c.Config.IsAuthUISimplified() || !c.Auth.IsExternalPrincipalsEnabled(ctx) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you create a function for this? It's a reused code.

pkg/auth/service_test.go Show resolved Hide resolved
func (a *APIAuthService) IsExternalPrincipalsEnabled(ctx context.Context) bool {
return a.externalPrincipalseEnabled
}
func (a *APIAuthService) CreateUserExternalPrincipal(ctx context.Context, userID, principalID string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if we need to check here user's existence.
WDYT?

Copy link
Contributor Author

@Isan-Rivkin Isan-Rivkin Mar 14, 2024

Choose a reason for hiding this comment

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

I wouldn't want to check this here.

If you look at other requests such as AttachPolicyToUser and DetachPolicyFromUser when using APIAuthService (API service) we let that API decide on the correct authorization.
Especially around external principal implementation i'd rather let the auth service dictate the business logic since the implementation details belong to there.

Copy link
Contributor

@idanovo idanovo left a comment

Choose a reason for hiding this comment

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

LGTM

@Isan-Rivkin Isan-Rivkin marked this pull request as ready for review March 14, 2024 12:15
Copy link
Contributor

@itaiad200 itaiad200 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, it's great to see the progress 💪
Mostly nit, a few blocking comments

user_id:
type: string
description: |
lakeFS user ID to associate with an external principal.
Copy link
Contributor

Choose a reason for hiding this comment

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

Email? something else?

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 have no idea what's the question?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we have many id types for a user in Treeverse, right? I may be wrong..

api/swagger.yml Outdated
properties:
id:
type: string
description: A unique identifier for the external principal
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a string example?

api/swagger.yml Outdated
Comment on lines 1635 to 1636


Copy link
Contributor

Choose a reason for hiding this comment

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

I actually like the blank lines, it's very hard for me to udnerstand where an object ends without them

Comment on lines +1649 to +1651
additionalProperties:
type: string
description: Additional settings to be consumed by the remote authenticator
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand what this is. Is it Opaque? Can you add an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is opaque on purpose to avoid breaking the API.
An example is forcing session_name or only matching based on role_name in IAM.
Another example would be specifying max ttl.

Comment on lines +1652 to +1658
ExternalPrincipalCreation:
type: object
properties:
settings:
type: object
items:
$ref: "#/components/schemas/ExternalPrincipalSettings"
Copy link
Contributor

Choose a reason for hiding this comment

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

Creation has just a list of settings which are strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's currently optional, ExternalPrincipalSettings is an object of key/value with string type.

pkg/auth/service.go Outdated Show resolved Hide resolved
pkg/auth/service.go Outdated Show resolved Hide resolved
pkg/auth/service.go Outdated Show resolved Hide resolved
pkg/auth/service.go Outdated Show resolved Hide resolved
pkg/auth/service.go Show resolved Hide resolved
@Isan-Rivkin Isan-Rivkin requested a review from itaiad200 March 14, 2024 15:52
Copy link
Contributor

@itaiad200 itaiad200 left a comment

Choose a reason for hiding this comment

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

Thanks for the prompt fix! Single non blocking comment

c.LogAction(ctx, "create_user_external_principal", r, "", "", "")

err := c.Auth.CreateUserExternalPrincipal(ctx, userID, principalID)
if c.handleAPIError(ctx, w, r, err) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see what happened here.
You check first thing for isExternalPrincipalNotSupported and then return not implemented. I thought we reach the AuthService that returns an error auth.ErrNotImplemented but I was wrong. When handleAPIError sees an error it doesn't recognize it will return Internal Server Error which is not what we want but also not the case here.

I believe it's slightly better to have the AuthService handle the possible ExternalPrincipals enabled/disabled status in terms of separation of concerns, i.e. it's not the controller responsibility, you have errors as communication protocol between the 2 components. BUT - it is also not a bug, and definitely not a blocking bug.

@Isan-Rivkin Isan-Rivkin added include-changelog PR description should be included in next release changelog and removed exclude-changelog PR description should not be included in next release changelog labels Mar 17, 2024
@Isan-Rivkin Isan-Rivkin merged commit 34b172d into master Mar 17, 2024
41 checks passed
@Isan-Rivkin Isan-Rivkin deleted the external-auth-principals-api branch March 17, 2024 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
include-changelog PR description should be included in next release changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Integrate External Auth Principals management
3 participants