-
Notifications
You must be signed in to change notification settings - Fork 290
add refresh credentials property to loadTableResult #1164
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 refresh credentials property to loadTableResult #1164
Conversation
return responseBuilder.build(); | ||
if(accessDelegationModes.contains(AccessDelegationMode.VENDED_CREDENTIALS)){ | ||
try { | ||
String hostName = InetAddress.getLocalHost().getCanonicalHostName(); |
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 there a better way to grab the server host here? I don't think this is reliable but I do not know a better way to get the host. Potentially, we can get it from the request header? but it looks like the headers are being filtered out.
if (accessDelegationModes.contains(AccessDelegationMode.VENDED_CREDENTIALS)) { | ||
try { | ||
// String hostName = InetAddress.getLocalHost().getCanonicalHostName(); | ||
String hostName = "localhost"; |
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 not so simple, I'm afraid :) We need to think of proxies too.
At the very minimum, I think we need to get a UriInfo
injected and use uriInfo.getBaseUri()
.
A more robust approach is here: https://github.com/projectnessie/nessie/blob/a9028f12c5152ebc14ba32731b52fdc9a107db94/servers/quarkus-catalog/src/main/java/org/projectnessie/server/catalog/ExternalBaseUriImpl.java#L38
String credentialsEndpoint = | ||
String.format( | ||
"/v1/%s/namespaces/%s/tables/%s/credentials", | ||
catalogName, tableIdentifier.namespace().toString(), tableIdentifier.name()); |
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.
Does this do proper escaping of special chars in the URI path?
Cf. IcebergCatalogAdapter.decodeNamespace()
Map<String, String> vendedCredentialConfig = new HashMap<>(); | ||
String credentialsEndpoint = | ||
String.format( | ||
"/v1/%s/namespaces/%s/tables/%s/credentials", |
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.
IcebergCatalog
does not deal with the REST API at all, but this config requires understanding namespace path encoding/decoding.
I believe it is preferable to inject this config in IcebergCatalogAdapter
(where the decoding code exists).
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 moved the string construction to IcebergCatalogAdapter
where the decoding code exists, but I feel that's a little bit clumsy to pass it all the way down to SupportsCredentialDelegation
. I wonder if you have a more elegant way of doing this
@@ -65,6 +66,11 @@ public PolarisCallContext getPolarisCallContext() { | |||
public Map<String, Object> contextVariables() { | |||
return Map.of(); | |||
} | |||
|
|||
@Override | |||
public URI getBaseUri() { |
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 this change still 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.
This is removed
catalogName, tableIdentifier.namespace().toString(), tableIdentifier.name()); | ||
vendedCredentialConfig.put(AwsClientProperties.REFRESH_CREDENTIALS_ENABLED, "true"); | ||
vendedCredentialConfig.put( | ||
AwsClientProperties.REFRESH_CREDENTIALS_ENDPOINT, credentialsEndpoint); |
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 this property specific to the AWS client? I did not find any formal definition for it in Iceberg.
I believe it would be preferable to have a local constant for it in Polaris to avoid the impression that it is supposed to work only for AWS.
Given apache/iceberg#11281, why do we have to set this property at all? Why is it not discovered automatically?
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.
That was my question to the iceberg team as well, but they insist on having this property set so iceberg knows which endpoint to reach out to.
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.
Regarding the AwsClientProperties
, there's also discussion here
@@ -24,6 +24,7 @@ | |||
import com.auth0.jwt.JWTVerifier; | |||
import com.auth0.jwt.algorithms.Algorithm; | |||
import com.auth0.jwt.interfaces.DecodedJWT; | |||
import java.net.URI; |
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.
unnecessary import?
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 has been removed
@@ -378,6 +378,7 @@ public Response loadTable( | |||
Namespace ns = decodeNamespace(namespace); | |||
TableIdentifier tableIdentifier = TableIdentifier.of(ns, RESTUtil.decodeString(table)); | |||
|
|||
|
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 don't know why these extra blank lines are added
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 has been removed
String credentialsEndpoint = | ||
String.format( | ||
"/v1/%s/namespaces/%s/tables/%s/credentials", | ||
prefix, tableIdentifier.namespace().toString(), tableIdentifier.name()); |
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 needs to be configurable. E.g., some hosts may prefix the URL with /polaris
or with /your_account_name
or any number of prefixes
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.
does that mean they will do something like /polaris-catalog-name
instead of just /catalog-name
? or I'm misunderstanding 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.
prefix
identifies the catalog, does it not? Why would the .../credentials
endpoint for a table in one catalog need to be under a different prefix?
@@ -25,6 +25,7 @@ | |||
import com.google.common.collect.ImmutableMap; | |||
import jakarta.annotation.Nonnull; | |||
import java.lang.reflect.Method; | |||
import java.net.URI; |
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.
unnecessary import?
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 removed.
@@ -21,6 +21,7 @@ | |||
import com.google.auth.oauth2.AccessToken; | |||
import com.google.auth.oauth2.GoogleCredentials; | |||
import jakarta.ws.rs.core.SecurityContext; | |||
import java.net.URI; |
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.
same
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.
sorry, i forgot to do spotlessApply. these should all be fixed now.
@@ -856,6 +857,15 @@ public Map<String, String> getCredentialConfig( | |||
storageInfo.get()); | |||
} | |||
|
|||
@Override | |||
public Map<String, String> getVendedCredentialConfig(TableIdentifier tableIdentifier, String decodedCredentialsPath) { |
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 is this a whole new method rather than just putting this directly in the IcebergCatalogHandler
. You're just putting values into a map, so...
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 see. I thought it can be more organized that way. I removed it.
ifNoneMatch, | ||
snapshots, | ||
delegationModes, | ||
RESTUtil.decodeString(credentialsEndpoint)) |
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 believe this class (or class above it in the call chain) should inject credentialsEndpoint
in this response. We should not push this parameter down to loadTableWithAccessDelegationIfStale
because the lower level class has nothing to do with REST URIs.
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 see. does that mean we should be building the response here instead of having a complete response returned from loadTableAccessDelegationIfStale
?
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 created a function to do the injection at the proper level. Let me know if that's what you have in mind! Thanks for all the feedback! really appreciate it
@wolflex888 : Are you still working on this? Sorry for the delay with reviews. Could you resolve conflicts, please? |
String credentialsEndpoint = | ||
String.format( | ||
"/v1/%s/namespaces/%s/tables/%s/credentials", | ||
prefix, tableIdentifier.namespace().toString(), tableIdentifier.name()); |
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.
(Saw that #1164 (comment) got lost but think it still holds)
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.
Agree the uri should be :
public String tableCredentials(TableIdentifier ident) {
return SLASH.join(
"v1",
prefix,
"namespaces",
RESTUtil.encodeNamespace(ident.namespace()),
"tables",
RESTUtil.encodeString(ident.name()),
"credentials");
}
Hi, Just following up—any updates on this? It should address apache/polaris#2177. I understand this is an open-source project, but this is a small yet important change, especially given this projects role as a backend for enterprise products like Snowflake Open Catalog. Any update or timeline would be greatly appreciated. Thank you. |
cc @singhpk234 |
loadResponseBuilder.addConfig( | ||
AwsClientProperties.REFRESH_CREDENTIALS_ENDPOINT, credentialsEndpoint); | ||
loadResponseBuilder.addConfig(AwsClientProperties.REFRESH_CREDENTIALS_ENABLED, "true"); |
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.
ADLS also now supports creds refresh
String credentialsEndpoint = | ||
String.format( | ||
"/v1/%s/namespaces/%s/tables/%s/credentials", | ||
prefix, tableIdentifier.namespace().toString(), tableIdentifier.name()); |
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.
Agree the uri should be :
public String tableCredentials(TableIdentifier ident) {
return SLASH.join(
"v1",
prefix,
"namespaces",
RESTUtil.encodeNamespace(ident.namespace()),
"tables",
RESTUtil.encodeString(ident.name()),
"credentials");
}
LoadTableResponse.Builder loadResponseBuilder = | ||
LoadTableResponse.builder().withTableMetadata(originalResponse.tableMetadata()); |
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.
do we need to update metadata-location too ?
loadResponseBuilder.addConfig( | ||
AwsClientProperties.REFRESH_CREDENTIALS_ENDPOINT, credentialsEndpoint); | ||
loadResponseBuilder.addConfig(AwsClientProperties.REFRESH_CREDENTIALS_ENABLED, "true"); |
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 should check the credential type too and send this only when storage is AWS
@wolflex888 would you mind rebasing i can help in review |
@jasonf20 : If you have the capacity to make an alternative PR for this, I think it might be a reasonable path forward. If you do, please see my comments about URI handling I made under this PR. |
@dimas-b Please see here: #2341 This PR has gotten a little messy so please leave new comments if I missed anything. I understand everyone’s busy, but I’m a bit concerned that no one from the Snowflake team or other contributors has taken this on yet. I’ll do my best to assist where I can. I don't have a lot of capacity for this, but long as we keep it simple it should be fine. |
I'm gonna be closing this PR as this has gotten a little bit messy. we can move forward with #2341 |
This PR will add necessary refresh-vended-credentials properties to
LoadTableResponse
to allow each IoFile will get appropriate properties to initiateVendedCredentialsProvider
.