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

Add policy config to allow sanity-check on policy in data nodes #17774

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

Conversation

cecemei
Copy link
Contributor

@cecemei cecemei commented Mar 3, 2025

Description

Added PolicyConfig class, and data server can reject query based on the config. E.x. if config set to POLICY_CHECKED_ON_ALL_TABLES_POLICY_MUST_EXIST, querying on TableDataSource directly would be rejected.

Also refactored ServerManagerTest to use Guice bindings (new test dependency), and TestSegmentCacheManager for loading segments.


Key changed/added classes in this PR
  • PolicyConfig
  • ServerManagerTest

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

@cecemei cecemei marked this pull request as ready for review March 5, 2025 06:14
@cryptoe cryptoe requested a review from clintropolis March 6, 2025 04:19
@cecemei cecemei changed the title Some policy config Add policy config to allow sanity-check on policy in data nodes Mar 6, 2025
Comment on lines +134 to +135
@JsonProperty("0") APPLY_WHEN_APPLICABLE(0f),
@JsonProperty("2.0f") POLICY_CHECKED_ON_ALL_TABLES_POLICY_MUST_EXIST(2.0f);
Copy link
Member

Choose a reason for hiding this comment

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

why is securityLevel a float?
what does 2.0f mean?


public boolean allowPolicy(@Nonnull Policy policy)
{
return allowedPolicies.isEmpty() || allowedPolicies.contains(policy.getClass().getSimpleName());
Copy link
Member

Choose a reason for hiding this comment

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

I was not expecting SimpleName trick here...
it seems to me that this kinda sets it in stone that a Policy may not have any state

can you please add a validation that when the PolicyConfig is created its ensured that allowedPolicies are possibly exisitng Policy-s

*
* @see TablePolicySecurityLevel
*/
@JsonProperty
Copy link
Member

Choose a reason for hiding this comment

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

its odd to see that both the field and the corresponding method has @JsonProperty

@@ -37,6 +37,7 @@
import org.apache.druid.segment.loading.StorageLocationConfig;
import org.apache.druid.server.SegmentManager;
import org.apache.druid.server.metrics.DataSourceTaskIdHolder;
import org.apache.druid.test.utils.TestSegmentCacheManager;
Copy link
Member

Choose a reason for hiding this comment

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

nit: are there any relevant changes in this file beyond this import?
do we need all those indentation changes?

serverConfig = new ServerConfig();
authConfig = new AuthConfig();

Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
Copy link
Member

Choose a reason for hiding this comment

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

instead of BoundFieldModule - would it be possible to create the injector and populate the necessary fields from that?

Comment on lines +198 to +201
if (!(theQuery instanceof SegmentMetadataQuery)
&& !dataSourceFromQuery.validate(authConfig.getTableSecurityPolicyConfig())) {
throw new ISE("Failed security validation with dataSource [%s]", dataSourceFromQuery);
}
Copy link
Member

Choose a reason for hiding this comment

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

I think instead of an insteanceof there could be a Query#validate which would dispatch it correctly - but for SegmentMetadataQuery that's overriden.

/**
* Defines how strict we want to enforce the policy on tables during query execution process.
* <ol>
* <li>{@code APPLY_WHEN_APPLICABLE}, the most basic level, restriction is applied whenever seen fit.
Copy link
Member

Choose a reason for hiding this comment

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

I think this line should be an apidoc on the enum value

*/
public enum TablePolicySecurityLevel
{
@JsonProperty("0") APPLY_WHEN_APPLICABLE(0f),
Copy link
Member

Choose a reason for hiding this comment

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

I believe this name is a bit unfortunate; I feel like this wants to be something like "allow all when not blocked"
if yes then it could be: ALLOW_MISSING_POLICY

* Defines how strict we want to enforce the policy on tables during query execution process.
* <ol>
* <li>{@code APPLY_WHEN_APPLICABLE}, the most basic level, restriction is applied whenever seen fit.
* <li>{@code POLICY_CHECKED_ON_ALL_TABLES_POLICY_MUST_EXIST}, every table must have a policy when requests come from external users.
Copy link
Member

Choose a reason for hiding this comment

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

I think a shorter one would be: MANDATORY ; or ENFORCED

* Returns true if the security level requires that, every table must have a policy during query execution stage,
* this means the table must have a non-empty value in the policy map.
*/
public boolean policyMustBeCheckedAndExistOnAllTables()
Copy link
Member

Choose a reason for hiding this comment

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

I was wondering about an alternate way of implementing this:

  • PolicyConfig is a dispatcher
  • it has a list of PolicyValidator -s ; maybe those classes are instantiated with the default constructor?
  • the allowPolicy and other methods are dispatched to the ones below
  • PolicyConfig could also implement the PolicyValidatory interface

I was also wondering if the whole PolicyConfig is a too much - wouldn't it be enough to enable the users to just bind a PolicyValidator they want to use; by specifying its classname somehow - and leave the dispatch or not / etc problems alone :)

@kgyrtkirk
Copy link
Member

left a few comments; happy to talk about it further!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants