-
Notifications
You must be signed in to change notification settings - Fork 677
SMQ-2627 - Align PATs with new architecture #3295
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3295 +/- ##
==========================================
- Coverage 79.16% 74.09% -5.07%
==========================================
Files 109 179 +70
Lines 13203 19953 +6750
==========================================
+ Hits 10452 14784 +4332
- Misses 2133 4277 +2144
- Partials 618 892 +274 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
7aa84c3 to
8976860
Compare
pkg/authn/authsvc/authn.go
Outdated
| } | ||
|
|
||
| if strings.HasPrefix(token, patPrefix) { | ||
| tokenType := authn.TokenType(res.GetTokenType()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates possible misconfiguration issue. I.e. what if token prefix here and tokenType returned from the service are not the same? While we are not able to validate token - we are able to parse it locally (even if only for prefix) and we can do this verification to prevent mismatch.
channels/middleware/authorization.go
Outdated
| } else { | ||
| req.Operation = auth.ListOp | ||
| } | ||
| req.Operation = auth.ChannelDisconnectClientOp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's stay consistent in naming, compare this to ClientConnectToChannelOp.
auth/pat.go
Outdated
| UnshareOp | ||
| PublishOp | ||
| SubscribeOp | ||
| ClientCreateOp Operation = iota + 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to reuse the existing service Operations ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we will have cyclic imports
d2f93f8 to
9632e74
Compare
81bc751 to
30bd274
Compare
auth/pat.go
Outdated
| return err | ||
| } | ||
|
|
||
| var ValidOperationsForEntity = map[EntityType][]Operation{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed here that we have not included domains as an entity, does this mean that pats can not be used for actions on domains?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From past discussion with @arvindh123, PATs are being used for entities like channels, clients, groups, dashboards and messages. It is not used to create users and domains. @dborovcanin can you confirm this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine; we can limit PATS to this at the moment. I.e. PATS are used for users to manage entities within the domain.
auth/pat.go
Outdated
| } | ||
|
|
||
| if !IsValidOperationForEntity(s.EntityType, s.Operation) { | ||
| return errors.Wrap(apiutil.ErrInvalidQueryParams, errors.New("operation not valid for entity type")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can define this error, instead of calling new each time
internal/proto/auth/v1/auth.proto
Outdated
| string user_id = 2; // User id | ||
| string pat_id = 3; // Pat id | ||
| uint32 entity_type = 4; // Entity type | ||
| string optional_domain_id = 5; // Optional domain id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not optional string domain_id = 5?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since users was remove I think it should be optional
7a0353a to
7937796
Compare
arvindh123
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have idea now, no need to implement in this PR.
We can have the permission map in auth service only
And in policy request we can send only the operations
Since PAT also sends the operation , we can make the users authz to send the operation instead of permission and
In auth service we can convert operations to Permissions
What do you think?
This is a good idea. It would simplify the authorization process and have no need of having the permissions file for all the entities. |
pkg/authn/authsvc/authn.go
Outdated
| if isPAT && tokenType != authn.PersonalAccessToken { | ||
| return authn.Session{}, errTokenTypeMismatch | ||
| } | ||
| if !isPAT && tokenType == authn.PersonalAccessToken { | ||
| return authn.Session{}, errTokenTypeMismatch | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic can be we merged into single case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or something like this
if isPAT != (tokenType == authn.PersonalAccessToken) {
return authn.Session{}, errTokenTypeMismatch
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is library, i think we don't want to do this check here
We can do this check in Auth Service itself and believe response that auth service has returned
pkg/authz/authsvc/authz.go
Outdated
| if pr.PatID != "" && pr.TokenType == authn.PersonalAccessToken { | ||
| patReq := grpcAuthV1.AuthZReq{ | ||
| TokenType: uint32(pr.TokenType), | ||
| Policy: &grpcAuthV1.PolicyReq{ | ||
| Domain: pr.Domain, | ||
| SubjectType: pr.SubjectType, | ||
| SubjectKind: pr.SubjectKind, | ||
| SubjectRelation: pr.SubjectRelation, | ||
| Subject: pr.Subject, | ||
| Relation: pr.Relation, | ||
| Permission: pr.Permission, | ||
| Object: pr.Object, | ||
| ObjectType: pr.ObjectType, | ||
| Subject: pr.UserID, | ||
| PatId: pr.PatID, | ||
| ObjectType: pr.EntityType.String(), | ||
| Domain: pr.DomainID, | ||
| Operation: uint32(pr.Operation), | ||
| Object: pr.EntityID, | ||
| }, | ||
| } | ||
| patRes, err := a.authSvcClient.Authorize(ctx, &patReq) | ||
| if err != nil { | ||
| return errors.Wrap(errors.ErrAuthorization, err) | ||
| } | ||
| if !patRes.GetAuthorized() { | ||
| return errors.ErrAuthorization | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nyagamunene I have question, Does this TokenType is needed?
How this TokenType is helpfull for us
pkg/permissions/config.go
Outdated
| if err != nil { | ||
| return nil, nil, fmt.Errorf("failed to get permissions for %s: %w", entityType, err) | ||
| } | ||
| func (pc *PermissionConfig) GetAuthOperations(entityType string) (map[string]string, map[string]string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to reuse the existing GetPermission(et string, op K) , instead of GetAuthOperations
Or
Could please explain the reason for choosing having the new function GetAuthOperations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATs requires us to extract auth_operation from the permission yaml file.
internal/proto/auth/v1/auth.proto
Outdated
| message AuthZReq { | ||
| oneof auth_type { | ||
| PolicyReq policy = 1; // Policy-based authorization | ||
| PATReq pat = 2; // PAT authorization | ||
| } | ||
| PolicyReq policy = 1; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can convert PolicyReq to AuthZReq, Since AuthZReq have only one field
cmd/domains/main.go
Outdated
|
|
||
| authOps := make(map[string]auth.Operation) | ||
| for opName, opInfo := range domainRoleOps { | ||
| if opInfo.AuthOperation != "" { | ||
| if authOp, err := auth.ParseOperation(opInfo.AuthOperation); err == nil { | ||
| authOps[opName] = authOp | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authOps is needed now, Since we have remove GetAuthOperations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Its the operations used by the PATs
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
What type of PR is this?
What does this do?
Which issue(s) does this PR fix/relate to?
Have you included tests for your changes?
Did you document any new/modified feature?
Notes