Skip to content

[FEATURE REQUEST #32] On-Premises S3 / S3 Compatible... #389

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

Closed
wants to merge 22 commits into from

Conversation

lefebsy
Copy link

@lefebsy lefebsy commented Oct 21, 2024

Description (edited) :

This is a S3 proposition of Polaris core storage implementation, copy of the aws + new parameters : endpoint, path style...

It is tested OK with :

This should works with many S3 compatible solutions like Dell ECS, NetApp StorageGRID, etc...

  • By default it is trying to respect the same behavior about credentials than AWS (IAM/STS). The same dynamic policy is applied, limiting the scope to the data queried.

  • Otherwise if STS is not available 'skipCredentialSubscopingIndirection' = true will disabling Polaris "SubScoping" of the credentials

Let me know your opinion about this design proposal.
Thank you

curl -X POST -H "Authorization: Bearer ${SPARK_BEARER_TOKEN}" \
     -H 'Accept: application/json' -H 'Content-Type: application/json' \
     http://${POLARIS_HOST}:8181/api/management/v1/catalogs -d \
      '{
          "name": "my-s3compatible-catalog",
          "id": 100,
          "type": "INTERNAL",
          "readOnly": false,
          "properties": {
            "default-base-location": "${S3_LOCATION}"
          },
          "storageConfigInfo": {
            "storageType": "S3_COMPATIBLE",
            "allowedLocations": ["${S3_LOCATION}/"],
            "s3.endpoint": "https://localhost:9000"
          }
        }'
            # optional:
            "s3.pathStyleAccess": true / false
            "s3.region": "rack-1 or us-east-1"
            "s3.roleArn": "arn:xxx:xxx:xxx:xxxx"
            "s3.credentials.catalog.accessKeyId": "CATALOG_1_ACCESS_KEY_ENV_VARIABLE_NAME"
            "s3.credentials.catalog.secretAccessKey": "CATALOG_1_SECRET_KEY_ENV_VARIABLE_NAME"
            # optional in case STS/IAM is not available :
            "skipCredentialSubscopingIndirection": true
                # optional for skipCredentialSubscopingIndirection - served by catalog to client like spark or trino
                "s3.credentials.client.accessKeyId": "CLIENT_OF_CATALOG_1_ACCESS_KEY_ENV_VARIABLE_NAME"
                "s3.credentials.client.secretAccessKey": "CLIENT_OF_CATALOG_1_SECRET_KEY_ENV_VARIABLE_NAME"

Included Changes:

  • New type of storage "S3_COMPATIBLE".
  • Tested against MinIO with self-signed certificate
  • regtests/run_spark_sql_s3compatible.sh

Type of change:

  • Bug fix (non-breaking change which fixes an issue)
  • Documentation update
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

Please delete options that are not relevant.

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • If adding new functionality, I have discussed my implementation with the community using the linked GitHub issue

@lefebsy lefebsy changed the title add s3 compatible storage - first commit [FEATURE REQUEST] On-Premise S3... #32 Oct 21, 2024
@lefebsy lefebsy changed the title [FEATURE REQUEST] On-Premise S3... #32 [FEATURE REQUEST #32] On-Premise S3... Oct 21, 2024
@lefebsy lefebsy changed the title [FEATURE REQUEST #32] On-Premise S3... [FEATURE REQUEST #32] On-Premises S3... Oct 21, 2024
@lefebsy

This comment was marked as outdated.

@@ -23,6 +23,8 @@ public enum PolarisCredentialProperty {
AWS_KEY_ID(String.class, "s3.access-key-id", "the aws access key id"),
AWS_SECRET_KEY(String.class, "s3.secret-access-key", "the aws access key secret"),
AWS_TOKEN(String.class, "s3.session-token", "the aws scoped access token"),
AWS_ENDPOINT(String.class, "s3.endpoint", "the aws s3 endpoint"),
AWS_PATH_STYLE_ACCESS(Boolean.class, "s3.path-style-access", "the aws s3 path style access"),
Copy link
Contributor

Choose a reason for hiding this comment

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

whether or not to use path-style access

Copy link
Author

Choose a reason for hiding this comment

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

Many S3COMPATIBLE solutions are deployed without network devices or configurations in front of them allowing support of dynamic hosts names including buckets.
TLS certificate with private AC could also be a challenge for dynamic host name. "*. domain" can also be forbidden by some enterprise security policy

Path style is useful in many cases. In ideal world I agree it should stay deprecated...

Copy link
Contributor

Choose a reason for hiding this comment

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

I think @eric-maynard was asking if we can change the description to something like this:

Suggested change
AWS_PATH_STYLE_ACCESS(Boolean.class, "s3.path-style-access", "the aws s3 path style access"),
AWS_PATH_STYLE_ACCESS(Boolean.class, "s3.path-style-access", "whether or not to use path-style access"),

I also agreed that we should make sure it false by default

Choose a reason for hiding this comment

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

For IBM's watsonx.data product it is set to true by default for Minio and Ceph bucket types, reason being that it's more likely to work. Path style will work regardless of whether the customer has setup wildcard DNS, a TLS certificate with a subject-alternate-name (the wildcard), and the hostname in the zonegroup (for Ceph). Virtual host style will only work if all of those things are done.

It's not a hill I would die on, but it's worthy of consideration.

Copy link
Contributor

Choose a reason for hiding this comment

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

To clarify, I was referring to the Polaris scope default. Users always have the option to set it to true when creating a new catalog.

@lefebsy
Copy link
Author

lefebsy commented Mar 11, 2025

Thanks a lot @lefebsy for working on it. I agreed that we don't have to put Helm change in, so that the github pipeline can pass. We can always add it back as a followup PR. It should be ready to merge as long as we fix this https://github.com/apache/polaris/pull/389/files#r1980741611.

Yes. I have restored helm from main branch. I have probably done a small test modification and forget it. I'm really confused.

@omarsmak
Copy link
Member

Thanks a lot @lefebsy for working on it. I agreed that we don't have to put Helm change in, so that the github pipeline can pass. We can always add it back as a followup PR. It should be ready to merge as long as we fix this https://github.com/apache/polaris/pull/389/files#r1980741611.

Yes. I have restored helm from main branch. I have probably done a small test modification and forget it. I'm really confused.

Thanks @lefebsy . The PR looks now a lot better from helm standpoint. We just need to address last comment from @flyrain to get this PR going 🙂

@omarsmak
Copy link
Member

@lefebsy you have a conflict by the way

lefebsy and others added 3 commits March 12, 2025 20:52
# Conflicts:
#	polaris-core/src/main/java/org/apache/polaris/core/storage/PolarisCredentialProperty.java
@lefebsy
Copy link
Author

lefebsy commented Mar 12, 2025

@omarsmak

=> Hello, the conflict should be resolved since rebased :-)

@omarsmak
Copy link
Member

@omarsmak

=> Hello, the conflict should be resolved since rebased :-)

Thanks @lefebsy . Can you please address this last comment so we have this PR wrapped up? https://github.com/apache/polaris/pull/389/files#r1980741611

Copy link
Contributor

@dimas-b dimas-b left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution @lefebsy ! Overall I think it's a valuable addition to Polaris, but I have a couple of concerns.

s3ConfigModel.getS3PathStyleAccess(),
s3ConfigModel.getS3Region(),
s3ConfigModel.getS3RoleArn(),
new ArrayList<>(allowedLocations));
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: why new array?

return S3CompatibleStorageConfigInfo.builder()
.setStorageType(StorageConfigInfo.StorageTypeEnum.S3_COMPATIBLE)
.setS3Endpoint(s3Config.getS3Endpoint())
.setS3ProfileName(s3Config.getS3ProfileName())
Copy link
Contributor

Choose a reason for hiding this comment

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

these kind of attribute copy blocks of code are easy to mess up by accidental typos... Could you add a unit test for this conversion?

@@ -241,6 +243,7 @@ public void validateMaxAllowedLocations(int maxAllowedLocations) {
/** Polaris' storage type, each has a fixed prefix for its location */
public enum StorageType {
S3("s3://"),
S3_COMPATIBLE("s3://"),
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe s3 is sufficient for this PR because AWS also maps to only s3. Other URIs schemes (like s3a) are applicable to AWS too, but I think it is best to handle that in a follow-up PR.

if (roleArn.contains("aws-cn")) {
return "arn:aws-cn:s3:::";
} else if (roleArn.contains("aws-us-gov")) {
return "arn:aws-us-gov:s3:::";
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this kind of special cases should not be in Polaris code, but it's ok for this PR as I understand it mimics previous AWS-specific logic.

@Nonnull Set<String> allowedReadLocations,
@Nonnull Set<String> allowedWriteLocations) {

String caI = System.getenv(storageConfig.getS3CredentialsCatalogAccessKeyId());
Copy link
Contributor

@dimas-b dimas-b Mar 13, 2025

Choose a reason for hiding this comment

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

I'm strongly opposed to storing credential env. variable name is the storage config (essentially in the catalog config).

The environment and catalog config are different management domains with different concerns.

Using a static env. variable name (e.g. AWS_ACCESS_KEY) is ok in the short term, IMHO.

Is it strictly necessary to support different secrets for different catalogs in this case?

Copy link
Contributor

Choose a reason for hiding this comment

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

StaticCredentialsProvider.create(AwsBasicCredentials.create(caI, caS)));
LOGGER.debug("S3Compatible - stsClient using keys from catalog settings");
}
try (StsClient stsClient = stsBuilder.build()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Creating an StsClient for each request is an overkill, IMHO, but we can probably refactor that later.

@@ -40,7 +40,7 @@ follows:

```shell
./gradlew clean :polaris-quarkus-server:assemble -Dquarkus.container-image.build=true --no-build-cache
docker compose -f ./regtests/docker-compose.yml up --build --exit-code-from regtest
docker-compose -f ./regtests/docker-compose.yml up --build --exit-code-from regtest
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to be unrelated to the purpose of this PR. Please make this change in a separate PR.

- 9000:9000
volumes:
- ./miniodata:/data
- ./certs:/root/.minio/certs/
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this strictly necessary for tests?

* @return A policy limiting scope access
*/
// TODO - add KMS key access
public static IamPolicy policyString(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not reuse the policy from the code the deals with AWS S3?

@dimas-b
Copy link
Contributor

dimas-b commented Mar 17, 2025

@lefebsy : I appreciate your work on this PR, but I'd like to submit an alternative implementation for consideration by the community. Will mention it here, when it's ready.

@flyrain
Copy link
Contributor

flyrain commented Mar 21, 2025

@lefebsy : I appreciate your work on this PR, but I'd like to submit an alternative implementation for consideration by the community. Will mention it here, when it's ready.

Hi @dimas-b , great to know that you will contribute to this as well. Given the PR is WIP for a quite long time, can we merge this first, and make changes later? We can always improve on it and make changes as needed.

@dimas-b
Copy link
Contributor

dimas-b commented Apr 5, 2025

@flyrain :

Given the PR is WIP for a quite long time, can we merge this first, and make changes later? We can always improve on it and make changes as needed.

There are unaddressed concerns with this PR (as commented on specific changes). I believe they need to be resolved before merging.

@flyrain
Copy link
Contributor

flyrain commented Apr 6, 2025

There are unaddressed concerns with this PR (as commented on specific changes). I believe they need to be resolved before merging.

Agreed. I meant merge it after comments are addressed.

@thotz
Copy link

thotz commented Apr 10, 2025

@lefebsy @flyrain I can see this feature is targeted for the 1.0 release on April 15th. Can we expect this change to be available by then?

@flyrain
Copy link
Contributor

flyrain commented Apr 11, 2025

@thotz, I'm also waiting for the original author to make the change.

@eric-maynard
Copy link
Contributor

Hey @lefebsy, do you think we'll be able to revive this? If you're not available we can also copy this into another PR. I think the changes are pretty much ready to go

@dimas-b
Copy link
Contributor

dimas-b commented Apr 17, 2025

I'd prefer not to copy this 1:1 as I have some concerns with some areas of this PR (as commented).

If noone is actively working on this, I'd be willing to open another PR for this feature... maybe next week.

@richban
Copy link

richban commented Apr 28, 2025

@lefebsy Would love this PR to be merged.

@ashokvengala1990
Copy link

ashokvengala1990 commented Apr 30, 2025

@lefebsy, @adutra , @metadaddy , @mmgaggle

We are waiting for this PR to be merged. One of our customers wants to use MinIO or Dell ECS storage for Polaris. Please let me know if I can contribute to this if it is taking longer than expected. Looking forward to your response. Thank you.

@lefebsy
Copy link
Author

lefebsy commented Apr 30, 2025

Hello,

I started this PR 6 months ago, and did not realize that the review process would be so time consuming, that each new review would ask to explain the changes required during the previous review or the previous commenter, or add tests on existing code etc..

Unfortunately, since some weeks I no longer have the ability to devote more personal time to these round trips. Mabe it would be preferable to close or remove this PR. I hope not everything is to throw away. If Dimas-b wants to make another better implementation : +1

@eric-maynard
Copy link
Contributor

No worries @lefebsy! I'm sad to hear that you can't carry the PR forward but I'm thankful for your contributions so far. This is a feature I know a lot of users are excited about and it's unfortunate that it turned out to be so contentious.

@dimas-b, I'll keep an eye out for your PR, thanks for offering to pick this up.

@ryanovas
Copy link

@eric-maynard I am one of those users, I would be incredibly disappointed to see this PR be lost. I have been following it for weeks if not months at this point.

@dimas-b
Copy link
Contributor

dimas-b commented May 1, 2025

Thanks for your contribution @lefebsy !.. even if this PR does not get merged

@dimas-b
Copy link
Contributor

dimas-b commented May 1, 2025

I started related, but somewhat indirect refactoring in #1504

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.