-
Notifications
You must be signed in to change notification settings - Fork 3
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
AuthZ: integration and refactoring with core flows #80
Conversation
aayustark007-fk
commented
Jan 9, 2024
•
edited
edited
- Refactoring to AuthZ flows: changed RoleBinding to IamPolicy
- Added test authN mechanism for testing and e2e runs
- Added required permissions for all routes
- Using ResourceHierarchy handlers for passing resource path
- Added roles and permissions in config
- removed PermissionsAuthorization
- test changes to use auth handlers
- enabled authn and authz by default
4926cfd
to
e5e7ab4
Compare
e5e7ab4
to
d8cf28d
Compare
Add permissions authorization for org and team
…nce that can be inferred from the path param
…se the ctx resource heirarchy instead
@@ -212,6 +213,7 @@ private void addResourceContextForLeafNode( | |||
"/projects/%s/subscriptions/%s".formatted(segments[2], segments[3]) | |||
) | |||
)); | |||
// TODO: This fails when action is SET/GET IAM policy on topic or sub. Here, we rely on action since we don't know the leaf resource type. But it breaks in case of IAM actions. |
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.
need to discuss how to address 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.
one possiblity is to differentiate set/get policy based on resource 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.
have added TOPIC_IAM_POLICY_SET/GET and SUBSCRIPTION_IAM_POLICY_SET/GET
@@ -117,7 +95,13 @@ private boolean isResourceValid(String resourceId, ResourceType resourceType) { | |||
String varadhiTopicName = String.join(NAME_SEPARATOR, segments[0], segments[1]); | |||
yield (segments.length == 2) && metaStore.checkTopicExists(varadhiTopicName); | |||
} | |||
case SUBSCRIPTION -> false; //TODO | |||
case SUBSCRIPTION -> { |
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.
added handling for subscription policy
private IamPolicyHelper() { | ||
} | ||
|
||
public static final String AUTH_RESOURCE_NAME_SEPARATOR = ":"; |
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.
capture common utils used by tests, handlers and service
@@ -73,4 +84,24 @@ JWTAuthHandler createJWTHandler(Vertx vertx, AuthenticationOptions.JWTConfig con | |||
throw new VaradhiException("Failed to Initialise JWT Authentication handler.", e); | |||
} | |||
} | |||
|
|||
AuthenticationHandler createTestHandler() { |
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.
test mechanism impl
public AuthorizationHandler build(PermissionAuthorization requiredAuthorization) { | ||
return new AuthorizationHandler(requiredAuthorization); | ||
public AuthorizationHandler build(ResourceAction authorizationOnResource) { | ||
return new AuthorizationHandler(authorizationOnResource); |
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 resource hierarchy is providing complete path, PermissionsAuthorization is not needed and replaced with action only
server/src/main/java/com/flipkart/varadhi/web/AuthorizationHandlerBuilder.java
Show resolved
Hide resolved
@@ -263,27 +265,31 @@ static <T> Response makeHttpPostRequest(String targetUrl, T entityToCreate) { | |||
return getClient() | |||
.target(targetUrl) | |||
.request(MediaType.APPLICATION_JSON_TYPE) | |||
.header(AUTHN_TEST_HEADER, SUPER_USER) |
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 need this now to pass superuser info for authn.
without this tests will fail due to authentication failure
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.
comments
@@ -32,7 +32,8 @@ public <T> T asConfig(Class<T> configClass) { | |||
} | |||
|
|||
public enum Mechanism { | |||
jwt | |||
jwt, | |||
test |
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.
- Any specific reason to use X-Auth-Token header ?
- should we call it user-header instead of test ?
@@ -102,6 +102,9 @@ private List<Pair<ResourceType, ResourceContext>> generateResourceContextHierarc | |||
return List.of(); | |||
} | |||
|
|||
// trim leading and trailing slashes |
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.
What is the expected here and in which case it is getting incorrect ?
thinking if we can ensure correct input/parameter here, instead of doing trim ?
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.
Resource Path as a leading /
which causes blank segment at index 0.
For some cases, there also comes a trailing /
in case of create topic or create sub.
Apart from that it's just a measure to ensure input is sanitised.
server/src/main/java/com/flipkart/varadhi/auth/DefaultAuthorizationProvider.java
Show resolved
Hide resolved
|
||
public RoleBindingNode findRoleBindingNode(ResourceType resourceType, String resourceId) { | ||
return roleBindingMetaStore.getRoleBindingNode(resourceType, resourceId); | ||
public List<IamPolicyRecord> getAll() { |
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 getAll() and getIamPolicyRecords() needed for testing purpose alone ? If yes, possible to avoid it ? (getIamPolicyRecords() is part of interface and hence trying to ensure if it is needed)
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.
removed them
@@ -212,6 +213,7 @@ private void addResourceContextForLeafNode( | |||
"/projects/%s/subscriptions/%s".formatted(segments[2], segments[3]) | |||
) | |||
)); | |||
// TODO: This fails when action is SET/GET IAM policy on topic or sub. Here, we rely on action since we don't know the leaf resource type. But it breaks in case of IAM actions. |
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.
one possiblity is to differentiate set/get policy based on resource type.
server/src/main/java/com/flipkart/varadhi/web/AuthorizationHandlerBuilder.java
Show resolved
Hide resolved
@@ -35,24 +33,25 @@ public AuthorizationHandlerBuilder(List<String> superUsers, AuthorizationProvide | |||
this.provider = Objects.requireNonNull(provider, "Authorization Provider is null"); | |||
} | |||
|
|||
public AuthorizationHandler build(PermissionAuthorization requiredAuthorization) { | |||
return new AuthorizationHandler(requiredAuthorization); | |||
public AuthorizationHandler build(ResourceAction authorizationOnResource) { |
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 Builder still needed or we can just use AuthzHandler i.e. merge builder and handler ?
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 still need to pass the provider and super users list, which would require adding extra args to the constructor
.build(this::getHierarchy, this::get), | ||
RouteDefinition | ||
.post("CreateSubscription", "") | ||
.hasBody() | ||
.bodyParser(this::setSubscription) | ||
.authorize(SUBSCRIPTION_CREATE, "{project}") | ||
.authorize(SUBSCRIPTION_CREATE) |
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.
lets also check CONSUME permission on topic as well (in the API as of now ?)
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 will require larger changes either to pass AuthorizationProvider to SubscriptionHandlers or to make changes to provider contract to handle multiple actions.
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.
it will be taken independently ?
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, I'll raise it as a separate PR
Signed-off-by: aayustark007-fk <aayush.gupta@flipkart.com>
@@ -4,6 +4,7 @@ public class Constants { | |||
public static final int RANDOM_PARTITION_KEY_LENGTH = 5; | |||
public static final String CONTEXT_KEY_BODY = "varadhi.body"; | |||
public static final String CONTEXT_KEY_RESOURCE_HIERARCHY = "varadhi.resourceHierarchy"; | |||
public static final String USER_ID_HEADER = "X-User-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.
Any specific reason for using "X-" as prefix ?
x_ is header which Varadhi recognizes and treats them in specific way.
also header needs to be in lower 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.
replaced X-
with x_
entities/src/main/java/com/flipkart/varadhi/entities/auth/IamPolicyRecord.java
Outdated
Show resolved
Hide resolved
entities/src/main/java/com/flipkart/varadhi/entities/auth/ResourceAction.java
Outdated
Show resolved
Hide resolved
try { | ||
IamPolicyRecord node = | ||
getAuthZService().getIamPolicy(resourceContext.resourceType(), resourceContext.resourceId()); | ||
if (node == null) { |
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.
Are both possible i.e return value null or ResourceNotFoundException ?
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.
added null check for safety
underlying implementation may or may not return null
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 handle only ResourceNotFoundException instead of handling both. Also add a test to ensure getAuthZService().getIamPolicy() throws exception instead of returning null.
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.
removed null check
test is already added to IamPolicyServiceTest to check for the required case
server/src/main/java/com/flipkart/varadhi/services/IamPolicyService.java
Outdated
Show resolved
Hide resolved
.build(this::getHierarchy, this::get), | ||
RouteDefinition | ||
.post("CreateSubscription", "") | ||
.hasBody() | ||
.bodyParser(this::setSubscription) | ||
.authorize(SUBSCRIPTION_CREATE, "{project}") | ||
.authorize(SUBSCRIPTION_CREATE) |
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.
it will be taken independently ?
server/src/main/java/com/flipkart/varadhi/web/v1/authz/IamPolicyHandlers.java
Show resolved
Hide resolved
); | ||
} | ||
|
||
private ResourceHierarchy getHierarchy(RoutingContext ctx, boolean hasBody) { |
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.
getHierarchy() in case of subscription needed ?
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.
hierarchy will always be needed for top-down roles resolution (eg: org-admin trying to update a subscription)
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.
correct. getHierarchy() needs to handle the case of subscription as well, currently it doesn't.
server/src/main/java/com/flipkart/varadhi/web/v1/authz/IamPolicyHandlers.java
Show resolved
Hide resolved
|
||
IAM_POLICY_GET(ResourceType.IAM_POLICY, "get"), | ||
IAM_POLICY_SET(ResourceType.IAM_POLICY, "set"), | ||
IAM_POLICY_DELETE(ResourceType.IAM_POLICY, "delete"); |
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 am not sure of this being common for org/team/project. But its fine for time being, we can change it later if needed.
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.
org/team/project have hierarchal ordering while for the topic/sub/queue they occupy the same level in the resource hierarchy
this is the reason why we can use common resource action for the former (can infer based on path) while for the latter we need more context since we cannot know what type the leaf id is.
…check and throw the same again
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.
done
@@ -4,6 +4,7 @@ public class Constants { | |||
public static final int RANDOM_PARTITION_KEY_LENGTH = 5; | |||
public static final String CONTEXT_KEY_BODY = "varadhi.body"; | |||
public static final String CONTEXT_KEY_RESOURCE_HIERARCHY = "varadhi.resourceHierarchy"; | |||
public static final String USER_ID_HEADER = "x_user_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.
add todo: this user is only for testing and x_ convention may cause it to be sent to the destination during consume
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.
LGTM
); | ||
} | ||
|
||
private ResourceHierarchy getHierarchy(RoutingContext ctx, boolean hasBody) { |
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.
correct. getHierarchy() needs to handle the case of subscription as well, currently it doesn't.