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

AuthZ: integration and refactoring with core flows #80

Merged
merged 43 commits into from
Mar 27, 2024
Merged

Conversation

aayustark007-fk
Copy link
Collaborator

@aayustark007-fk aayustark007-fk commented Jan 9, 2024

  • 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

@aayustark007-fk aayustark007-fk changed the title <wip> AuthZ: address prev PR comments AuthZ: integration and refactoring with core flows Feb 28, 2024
@@ -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.
Copy link
Collaborator Author

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

Copy link
Collaborator

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.

Copy link
Collaborator Author

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 -> {
Copy link
Collaborator Author

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 = ":";
Copy link
Collaborator Author

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() {
Copy link
Collaborator Author

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);
Copy link
Collaborator Author

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

@@ -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)
Copy link
Collaborator Author

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

Copy link
Collaborator Author

@aayustark007-fk aayustark007-fk left a 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
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Any specific reason to use X-Auth-Token header ?
  2. 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
Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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.


public RoleBindingNode findRoleBindingNode(ResourceType resourceType, String resourceId) {
return roleBindingMetaStore.getRoleBindingNode(resourceType, resourceId);
public List<IamPolicyRecord> getAll() {
Copy link
Collaborator

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)

Copy link
Collaborator Author

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.
Copy link
Collaborator

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.

@@ -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) {
Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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)
Copy link
Collaborator

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 ?)

Copy link
Collaborator Author

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.

Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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

@@ -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";
Copy link
Collaborator

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

replaced X- with x_

try {
IamPolicyRecord node =
getAuthZService().getIamPolicy(resourceContext.resourceType(), resourceContext.resourceId());
if (node == null) {
Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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

Copy link
Collaborator

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.

Copy link
Collaborator Author

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

.build(this::getHierarchy, this::get),
RouteDefinition
.post("CreateSubscription", "")
.hasBody()
.bodyParser(this::setSubscription)
.authorize(SUBSCRIPTION_CREATE, "{project}")
.authorize(SUBSCRIPTION_CREATE)
Copy link
Collaborator

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 ?

);
}

private ResourceHierarchy getHierarchy(RoutingContext ctx, boolean hasBody) {
Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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)

Copy link
Collaborator

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.


IAM_POLICY_GET(ResourceType.IAM_POLICY, "get"),
IAM_POLICY_SET(ResourceType.IAM_POLICY, "set"),
IAM_POLICY_DELETE(ResourceType.IAM_POLICY, "delete");
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

@aayustark007-fk aayustark007-fk left a 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";
Copy link
Collaborator Author

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

Copy link
Collaborator

@kmrdhruv kmrdhruv left a 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) {
Copy link
Collaborator

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.

@aayustark007-fk aayustark007-fk merged commit 5abbd15 into master Mar 27, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants