-
Notifications
You must be signed in to change notification settings - Fork 170
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
Reorder filters and let RealmIdResolver throw UnresolvableRealmException #848
base: main
Are you sure you want to change the base?
Conversation
e542f5c
to
9c45494
Compare
This is now ready for review. |
* The header name for the realm ID. Tests must make sure that Polaris is configured with this | ||
* header name. | ||
*/ | ||
public static String REALM_HEADER = "Polaris-Realm"; |
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.
Would you mind moving this to a (new) method on PolarisServerManager
or Server
so that it is possible to customize?
assertThat(response.getStatus()).isEqualTo(Status.OK.getStatusCode()); | ||
Catalogs roles = response.readEntity(Catalogs.class); | ||
if ("POLARIS".equals(realmId)) { | ||
assertThat(roles.getCatalogs()).extracting(Catalog::getName).contains(internalCatalogName); |
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.
nit: maybe make internalCatalogName
a parameter to this test?
try { | ||
realmId = resolveRealmContext(rc); | ||
} catch (NotAuthorizedException e) { | ||
rc.abortWith(Response.status(Status.UNAUTHORIZED).build()); |
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'm not sure about 401 in this context. I believe it generally means your credentials are not valid, which is not applicable to failures in realm resolution.
I'm thinking that a 404 may fit better. For example, GH gives 404 on accessing repositories (i.e. realms) to which the user has no access.
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.
Makes sense, i will update the PR title and description accordingly.
quarkus/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java
Show resolved
Hide resolved
String requestURL, String method, String path, Map<String, String> headers) { | ||
|
||
String realm; | ||
|
||
if (headers.containsKey(configuration.headerName())) { | ||
realm = headers.get(configuration.headerName()); | ||
if (!configuration.realms().contains(realm)) { | ||
throw new IllegalArgumentException("Unknown realm: " + realm); | ||
throw new NotAuthorizedException("Unknown realm: " + realm); | ||
} | ||
} else { | ||
realm = configuration.defaultRealm(); |
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 it could be valuable to cover this with an explicit config flag. If realms are used in a particular deployment, it is probably not wise to allow potentially malicious clients to try sending requests at the default realm without knowing its 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.
I completely agree, I think that having a default realm is a potential security issue.
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.
Nice improvement to request filters! Thanks, @adutra !
As far as I can tell this change is backward compatible at the REST API / HTTP level.
@@ -49,4 +49,8 @@ public URI managementApiEndpoint() { | |||
public String realm() { | |||
return realm; | |||
} | |||
|
|||
public String realmHeader() { |
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.
Maybe rename to realmHeaderName()
+ realmId()
(latter for consistency w/ Server
)?
@@ -36,4 +39,8 @@ public interface Server extends AutoCloseable { | |||
URI baseUri(); | |||
|
|||
ClientPrincipal adminCredentials(); | |||
|
|||
default String realmHeader() { |
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.
default String realmHeader() { | |
default String realmHeaderName() { |
* <p>Note: this is actually only enforced when using {@link DefaultRealmIdResolver}. When using | ||
* {@link TestRealmIdResolver}, this setting is ignored. |
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.
* <p>Note: this is actually only enforced when using {@link DefaultRealmIdResolver}. When using | |
* {@link TestRealmIdResolver}, this setting is ignored. | |
* <p>Note: this setting is only enforced in production setups. |
* <p>Note: this is actually only enforced when using {@link DefaultRealmIdResolver}. When using | ||
* {@link TestRealmIdResolver}, this setting is ignored. | ||
*/ | ||
boolean requireHeader(); |
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.
Should this be true by default?
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.
Defaulting to true
would be a behaviour change at the REST/HTTP level. I'd prefer to keep old behaviour in this PR and change defaults later.
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.
WFM
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.
Yeah changing this to true would break downstreams. But we can mention this in the "Configuring for production" docs.
rc.getHeaders().entrySet().stream() | ||
.collect( | ||
HashMap::new, | ||
(m, e) -> m.put(e.getKey(), e.getValue().getFirst()), | ||
Map::putAll)); |
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.
Wonder if it makes more sense to change RealmIdResolver
to expect a Function<String, String>
rather than a "full blown map" (and use request::getHeader
here).
@collado-mike : any concerns from your POV? |
Fixes #819.
Summary of changes:
ContainerRequestFilter
RealmIdFilter
introducedRealmIdResolver
now can throwUnresolvableRealmException
=> maps to HTTP 404PolarisApplicationIntegrationTest
RealmIdFilter
QuarkusLoggingMDCFilter
QuarkusTracingFilter
PolarisPrincipalAuthenticatorFilter
PolarisPrincipalRolesProviderFilter
RateLimiterFilter