This is an automated email from the ASF dual-hosted git repository.
fanng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new d35e5f526 [#5894] feat(iceberg): support Azure account key credential
(#5938)
d35e5f526 is described below
commit d35e5f526317933a17b9c4ba75607384c0384c5f
Author: JUN <[email protected]>
AuthorDate: Sun Dec 22 11:32:16 2024 +0800
[#5894] feat(iceberg): support Azure account key credential (#5938)
### What changes were proposed in this pull request?
Support Azure account key credential
### Why are the changes needed?
Fix: #5894
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
Unit Test IcebergRESTADLSAccountKeyIT at iceberg 1.6.0
---
.../credential/AzureAccountKeyCredential.java | 109 +++++++++++++++++++++
.../org.apache.gravitino.credential.Credential | 1 +
.../abs/credential/ADLSTokenProvider.java | 14 +--
.../abs/credential/AzureAccountKeyProvider.java | 54 ++++++++++
....apache.gravitino.credential.CredentialProvider | 3 +-
.../gravitino/credential/CredentialConstants.java | 2 +
.../credential/CredentialPropertyUtils.java | 31 ++++--
.../credential/TestCredentialFactory.java | 27 +++++
...ntialConfig.java => AzureCredentialConfig.java} | 6 +-
docs/iceberg-rest-service.md | 43 ++++----
...RESTADLSIT.java => IcebergRESTADLSTokenIT.java} | 13 +--
...LSIT.java => IcebergRESTAzureAccountKeyIT.java} | 98 +-----------------
12 files changed, 262 insertions(+), 139 deletions(-)
diff --git
a/api/src/main/java/org/apache/gravitino/credential/AzureAccountKeyCredential.java
b/api/src/main/java/org/apache/gravitino/credential/AzureAccountKeyCredential.java
new file mode 100644
index 000000000..be24d7cda
--- /dev/null
+++
b/api/src/main/java/org/apache/gravitino/credential/AzureAccountKeyCredential.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.credential;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+
+/** Azure account key credential. */
+public class AzureAccountKeyCredential implements Credential {
+
+ /** Azure account key credential type. */
+ public static final String AZURE_ACCOUNT_KEY_CREDENTIAL_TYPE =
"azure-account-key";
+ /** Azure storage account name */
+ public static final String GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME =
"azure-storage-account-name";
+ /** Azure storage account key */
+ public static final String GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY =
"azure-storage-account-key";
+
+ private String accountName;
+ private String accountKey;
+
+ /**
+ * Constructs an instance of {@link AzureAccountKeyCredential}.
+ *
+ * @param accountName The Azure account name.
+ * @param accountKey The Azure account key.
+ */
+ public AzureAccountKeyCredential(String accountName, String accountKey) {
+ validate(accountName, accountKey);
+ this.accountName = accountName;
+ this.accountKey = accountKey;
+ }
+
+ /**
+ * This is the constructor that is used by credential factory to create an
instance of credential
+ * according to the credential information.
+ */
+ public AzureAccountKeyCredential() {}
+
+ @Override
+ public String credentialType() {
+ return AZURE_ACCOUNT_KEY_CREDENTIAL_TYPE;
+ }
+
+ @Override
+ public long expireTimeInMs() {
+ return 0;
+ }
+
+ @Override
+ public Map<String, String> credentialInfo() {
+ return (new ImmutableMap.Builder<String, String>())
+ .put(GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME, accountName)
+ .put(GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY, accountKey)
+ .build();
+ }
+
+ @Override
+ public void initialize(Map<String, String> credentialInfo, long
expireTimeInMS) {
+ String accountName =
credentialInfo.get(GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME);
+ String accountKey =
credentialInfo.get(GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY);
+ validate(accountName, accountKey);
+ this.accountName = accountName;
+ this.accountKey = accountKey;
+ }
+
+ /**
+ * Get Azure account name
+ *
+ * @return The Azure account name
+ */
+ public String accountName() {
+ return accountName;
+ }
+
+ /**
+ * Get Azure account key
+ *
+ * @return The Azure account key
+ */
+ public String accountKey() {
+ return accountKey;
+ }
+
+ private void validate(String accountName, String accountKey) {
+ Preconditions.checkArgument(
+ StringUtils.isNotBlank(accountName), "Azure account name should not be
empty.");
+ Preconditions.checkArgument(
+ StringUtils.isNotBlank(accountKey), "Azure account key should not be
empty.");
+ }
+}
diff --git
a/api/src/main/resources/META-INF/services/org.apache.gravitino.credential.Credential
b/api/src/main/resources/META-INF/services/org.apache.gravitino.credential.Credential
index f130b4b64..6071cb916 100644
---
a/api/src/main/resources/META-INF/services/org.apache.gravitino.credential.Credential
+++
b/api/src/main/resources/META-INF/services/org.apache.gravitino.credential.Credential
@@ -23,3 +23,4 @@ org.apache.gravitino.credential.GCSTokenCredential
org.apache.gravitino.credential.OSSTokenCredential
org.apache.gravitino.credential.OSSSecretKeyCredential
org.apache.gravitino.credential.ADLSTokenCredential
+org.apache.gravitino.credential.AzureAccountKeyCredential
diff --git
a/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/ADLSTokenProvider.java
b/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/ADLSTokenProvider.java
index e2ee3ed82..c2b684acb 100644
---
a/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/ADLSTokenProvider.java
+++
b/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/ADLSTokenProvider.java
@@ -38,7 +38,7 @@ import org.apache.gravitino.credential.CredentialConstants;
import org.apache.gravitino.credential.CredentialContext;
import org.apache.gravitino.credential.CredentialProvider;
import org.apache.gravitino.credential.PathBasedCredentialContext;
-import org.apache.gravitino.credential.config.ADLSCredentialConfig;
+import org.apache.gravitino.credential.config.AzureCredentialConfig;
/** Generates ADLS token to access ADLS data. */
public class ADLSTokenProvider implements CredentialProvider {
@@ -51,14 +51,14 @@ public class ADLSTokenProvider implements
CredentialProvider {
@Override
public void initialize(Map<String, String> properties) {
- ADLSCredentialConfig adlsCredentialConfig = new
ADLSCredentialConfig(properties);
- this.storageAccountName = adlsCredentialConfig.storageAccountName();
- this.tenantId = adlsCredentialConfig.tenantId();
- this.clientId = adlsCredentialConfig.clientId();
- this.clientSecret = adlsCredentialConfig.clientSecret();
+ AzureCredentialConfig azureCredentialConfig = new
AzureCredentialConfig(properties);
+ this.storageAccountName = azureCredentialConfig.storageAccountName();
+ this.tenantId = azureCredentialConfig.tenantId();
+ this.clientId = azureCredentialConfig.clientId();
+ this.clientSecret = azureCredentialConfig.clientSecret();
this.endpoint =
String.format("https://%s.%s", storageAccountName,
ADLSTokenCredential.ADLS_DOMAIN);
- this.tokenExpireSecs = adlsCredentialConfig.tokenExpireInSecs();
+ this.tokenExpireSecs = azureCredentialConfig.adlsTokenExpireInSecs();
}
@Override
diff --git
a/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/AzureAccountKeyProvider.java
b/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/AzureAccountKeyProvider.java
new file mode 100644
index 000000000..726c4f2d9
--- /dev/null
+++
b/bundles/azure-bundle/src/main/java/org/apache/gravitino/abs/credential/AzureAccountKeyProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.abs.credential;
+
+import java.util.Map;
+import org.apache.gravitino.credential.AzureAccountKeyCredential;
+import org.apache.gravitino.credential.Credential;
+import org.apache.gravitino.credential.CredentialConstants;
+import org.apache.gravitino.credential.CredentialContext;
+import org.apache.gravitino.credential.CredentialProvider;
+import org.apache.gravitino.credential.config.AzureCredentialConfig;
+
+/** Generates Azure account key to access data. */
+public class AzureAccountKeyProvider implements CredentialProvider {
+ private String accountName;
+ private String accountKey;
+
+ @Override
+ public void initialize(Map<String, String> properties) {
+ AzureCredentialConfig azureCredentialConfig = new
AzureCredentialConfig(properties);
+ this.accountName = azureCredentialConfig.storageAccountName();
+ this.accountKey = azureCredentialConfig.storageAccountKey();
+ }
+
+ @Override
+ public void close() {}
+
+ @Override
+ public String credentialType() {
+ return CredentialConstants.AZURE_ACCOUNT_KEY_CREDENTIAL_PROVIDER_TYPE;
+ }
+
+ @Override
+ public Credential getCredential(CredentialContext context) {
+ return new AzureAccountKeyCredential(accountName, accountKey);
+ }
+}
diff --git
a/bundles/azure-bundle/src/main/resources/META-INF/services/org.apache.gravitino.credential.CredentialProvider
b/bundles/azure-bundle/src/main/resources/META-INF/services/org.apache.gravitino.credential.CredentialProvider
index fb53efffa..4c7e7982c 100644
---
a/bundles/azure-bundle/src/main/resources/META-INF/services/org.apache.gravitino.credential.CredentialProvider
+++
b/bundles/azure-bundle/src/main/resources/META-INF/services/org.apache.gravitino.credential.CredentialProvider
@@ -16,4 +16,5 @@
# specific language governing permissions and limitations
# under the License.
#
-org.apache.gravitino.abs.credential.ADLSTokenProvider
\ No newline at end of file
+org.apache.gravitino.abs.credential.ADLSTokenProvider
+org.apache.gravitino.abs.credential.AzureAccountKeyProvider
\ No newline at end of file
diff --git
a/catalogs/catalog-common/src/main/java/org/apache/gravitino/credential/CredentialConstants.java
b/catalogs/catalog-common/src/main/java/org/apache/gravitino/credential/CredentialConstants.java
index 7dd74d084..29f9241c8 100644
---
a/catalogs/catalog-common/src/main/java/org/apache/gravitino/credential/CredentialConstants.java
+++
b/catalogs/catalog-common/src/main/java/org/apache/gravitino/credential/CredentialConstants.java
@@ -32,5 +32,7 @@ public class CredentialConstants {
public static final String ADLS_TOKEN_CREDENTIAL_PROVIDER_TYPE =
"adls-token";
public static final String ADLS_TOKEN_EXPIRE_IN_SECS =
"adls-token-expire-in-secs";
+ public static final String AZURE_ACCOUNT_KEY_CREDENTIAL_PROVIDER_TYPE =
"azure-account-key";
+
private CredentialConstants() {}
}
diff --git
a/common/src/main/java/org/apache/gravitino/credential/CredentialPropertyUtils.java
b/common/src/main/java/org/apache/gravitino/credential/CredentialPropertyUtils.java
index e1803a6dd..d7a3caf06 100644
---
a/common/src/main/java/org/apache/gravitino/credential/CredentialPropertyUtils.java
+++
b/common/src/main/java/org/apache/gravitino/credential/CredentialPropertyUtils.java
@@ -33,12 +33,19 @@ public class CredentialPropertyUtils {
@VisibleForTesting static final String ICEBERG_S3_SECRET_ACCESS_KEY =
"s3.secret-access-key";
@VisibleForTesting static final String ICEBERG_S3_TOKEN = "s3.session-token";
@VisibleForTesting static final String ICEBERG_GCS_TOKEN =
"gcs.oauth2.token";
- @VisibleForTesting static final String ICEBERG_ADLS_TOKEN = "adls.sas-token";
@VisibleForTesting static final String ICEBERG_OSS_ACCESS_KEY_ID =
"client.access-key-id";
@VisibleForTesting static final String ICEBERG_OSS_ACCESS_KEY_SECRET =
"client.access-key-secret";
@VisibleForTesting static final String ICEBERG_OSS_SECURITY_TOKEN =
"client.security-token";
+ @VisibleForTesting static final String ICEBERG_ADLS_TOKEN = "adls.sas-token";
+
+ @VisibleForTesting
+ static final String ICEBERG_ADLS_ACCOUNT_NAME =
"adls.auth.shared-key.account.name";
+
+ @VisibleForTesting
+ static final String ICEBERG_ADLS_ACCOUNT_KEY =
"adls.auth.shared-key.account.key";
+
private static Map<String, String> icebergCredentialPropertyMap =
ImmutableMap.of(
GCSTokenCredential.GCS_TOKEN_NAME,
@@ -54,7 +61,11 @@ public class CredentialPropertyUtils {
OSSTokenCredential.GRAVITINO_OSS_SESSION_ACCESS_KEY_ID,
ICEBERG_OSS_ACCESS_KEY_ID,
OSSTokenCredential.GRAVITINO_OSS_SESSION_SECRET_ACCESS_KEY,
- ICEBERG_OSS_ACCESS_KEY_SECRET);
+ ICEBERG_OSS_ACCESS_KEY_SECRET,
+ AzureAccountKeyCredential.GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME,
+ ICEBERG_ADLS_ACCOUNT_NAME,
+ AzureAccountKeyCredential.GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY,
+ ICEBERG_ADLS_ACCOUNT_KEY);
/**
* Transforms a specific credential into a map of Iceberg properties.
@@ -63,6 +74,14 @@ public class CredentialPropertyUtils {
* @return a map of Iceberg properties derived from the credential
*/
public static Map<String, String> toIcebergProperties(Credential credential)
{
+ if (credential instanceof S3TokenCredential
+ || credential instanceof S3SecretKeyCredential
+ || credential instanceof OSSTokenCredential
+ || credential instanceof OSSSecretKeyCredential
+ || credential instanceof AzureAccountKeyCredential) {
+ return transformProperties(credential.credentialInfo(),
icebergCredentialPropertyMap);
+ }
+
if (credential instanceof GCSTokenCredential) {
Map<String, String> icebergGCSCredentialProperties =
transformProperties(credential.credentialInfo(),
icebergCredentialPropertyMap);
@@ -70,12 +89,7 @@ public class CredentialPropertyUtils {
"gcs.oauth2.token-expires-at",
String.valueOf(credential.expireTimeInMs()));
return icebergGCSCredentialProperties;
}
- if (credential instanceof S3TokenCredential || credential instanceof
S3SecretKeyCredential) {
- return transformProperties(credential.credentialInfo(),
icebergCredentialPropertyMap);
- }
- if (credential instanceof OSSTokenCredential || credential instanceof
OSSSecretKeyCredential) {
- return transformProperties(credential.credentialInfo(),
icebergCredentialPropertyMap);
- }
+
if (credential instanceof ADLSTokenCredential) {
ADLSTokenCredential adlsCredential = (ADLSTokenCredential) credential;
String sasTokenKey =
@@ -87,6 +101,7 @@ public class CredentialPropertyUtils {
icebergADLSCredentialProperties.put(sasTokenKey,
adlsCredential.sasToken());
return icebergADLSCredentialProperties;
}
+
return credential.toProperties();
}
diff --git
a/common/src/test/java/org/apache/gravitino/credential/TestCredentialFactory.java
b/common/src/test/java/org/apache/gravitino/credential/TestCredentialFactory.java
index 75a669e38..6291b8857 100644
---
a/common/src/test/java/org/apache/gravitino/credential/TestCredentialFactory.java
+++
b/common/src/test/java/org/apache/gravitino/credential/TestCredentialFactory.java
@@ -165,4 +165,31 @@ public class TestCredentialFactory {
Assertions.assertEquals(sasToken, adlsTokenCredential.sasToken());
Assertions.assertEquals(expireTime, adlsTokenCredential.expireTimeInMs());
}
+
+ @Test
+ void testAzureAccountKeyCredential() {
+ String storageAccountName = "storage-account-name";
+ String storageAccountKey = "storage-account-key";
+
+ Map<String, String> azureAccountKeyCredentialInfo =
+ ImmutableMap.of(
+ AzureAccountKeyCredential.GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME,
+ storageAccountName,
+ AzureAccountKeyCredential.GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY,
+ storageAccountKey);
+ long expireTime = 0;
+ Credential credential =
+ CredentialFactory.create(
+ AzureAccountKeyCredential.AZURE_ACCOUNT_KEY_CREDENTIAL_TYPE,
+ azureAccountKeyCredentialInfo,
+ expireTime);
+ Assertions.assertEquals(
+ AzureAccountKeyCredential.AZURE_ACCOUNT_KEY_CREDENTIAL_TYPE,
credential.credentialType());
+ Assertions.assertInstanceOf(AzureAccountKeyCredential.class, credential);
+
+ AzureAccountKeyCredential azureAccountKeyCredential =
(AzureAccountKeyCredential) credential;
+ Assertions.assertEquals(storageAccountName,
azureAccountKeyCredential.accountName());
+ Assertions.assertEquals(storageAccountKey,
azureAccountKeyCredential.accountKey());
+ Assertions.assertEquals(expireTime,
azureAccountKeyCredential.expireTimeInMs());
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/credential/config/ADLSCredentialConfig.java
b/core/src/main/java/org/apache/gravitino/credential/config/AzureCredentialConfig.java
similarity index 96%
rename from
core/src/main/java/org/apache/gravitino/credential/config/ADLSCredentialConfig.java
rename to
core/src/main/java/org/apache/gravitino/credential/config/AzureCredentialConfig.java
index e9d368e67..155cc6806 100644
---
a/core/src/main/java/org/apache/gravitino/credential/config/ADLSCredentialConfig.java
+++
b/core/src/main/java/org/apache/gravitino/credential/config/AzureCredentialConfig.java
@@ -29,7 +29,7 @@ import org.apache.gravitino.config.ConfigEntry;
import org.apache.gravitino.credential.CredentialConstants;
import org.apache.gravitino.storage.AzureProperties;
-public class ADLSCredentialConfig extends Config {
+public class AzureCredentialConfig extends Config {
public static final ConfigEntry<String> AZURE_STORAGE_ACCOUNT_NAME =
new ConfigBuilder(AzureProperties.GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME)
@@ -79,7 +79,7 @@ public class ADLSCredentialConfig extends Config {
.intConf()
.createWithDefault(3600);
- public ADLSCredentialConfig(Map<String, String> properties) {
+ public AzureCredentialConfig(Map<String, String> properties) {
super(false);
loadFromMap(properties, k -> true);
}
@@ -110,7 +110,7 @@ public class ADLSCredentialConfig extends Config {
}
@NotNull
- public Integer tokenExpireInSecs() {
+ public Integer adlsTokenExpireInSecs() {
return this.get(ADLS_TOKEN_EXPIRE_IN_SECS);
}
}
diff --git a/docs/iceberg-rest-service.md b/docs/iceberg-rest-service.md
index 8d9d49745..f31aa1368 100644
--- a/docs/iceberg-rest-service.md
+++ b/docs/iceberg-rest-service.md
@@ -106,18 +106,18 @@ The detailed configuration items are as follows:
Gravitino Iceberg REST service supports using static S3 secret key or
generating temporary token to access S3 data.
-| Configuration item | Description
| Default value | Required
| Since Version |
-|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------------------------------------------------|------------------|
-| `gravitino.iceberg-rest.io-impl` | The IO implementation
for `FileIO` in Iceberg, use `org.apache.iceberg.aws.s3.S3FileIO` for S3.
| (none) | No
| 0.6.0-incubating |
-| `gravitino.iceberg-rest.credential-provider-type` | Supports `s3-token` and
`s3-secret-key` for S3. `s3-token` generates a temporary token according to the
query data path while `s3-secret-key` using the s3 secret access key to access
S3 data. | (none) | No
| 0.7.0-incubating |
-| `gravitino.iceberg-rest.s3-access-key-id` | The static access key ID
used to access S3 data.
| (none) | No
| 0.6.0-incubating |
-| `gravitino.iceberg-rest.s3-secret-access-key` | The static secret access
key used to access S3 data.
| (none) | No
| 0.6.0-incubating |
-| `gravitino.iceberg-rest.s3-endpoint` | An alternative endpoint
of the S3 service, This could be used for S3FileIO with any s3-compatible
object storage service that has a different endpoint, or access a private S3
endpoint in a virtual private cloud. | (none) | No
| 0.6.0-incubating |
-| `gravitino.iceberg-rest.s3-region` | The region of the S3
service, like `us-west-2`.
| (none) | No
| 0.6.0-incubating |
-| `gravitino.iceberg-rest.s3-role-arn` | The ARN of the role to
access the S3 data.
| (none) | Yes, when
`credential-provider-type` is `s3-token` | 0.7.0-incubating |
-| `gravitino.iceberg-rest.s3-external-id` | The S3 external id to
generate token, only used when `credential-provider-type` is `s3-token`.
| (none) | No
| 0.7.0-incubating |
-| `gravitino.iceberg-rest.s3-token-expire-in-secs` | The S3 session token
expire time in secs, it couldn't exceed the max session time of the assumed
role, only used when `credential-provider-type` is `s3-token`.
| 3600 | No
| 0.7.0-incubating |
-| `gravitino.iceberg-rest.s3-token-service-endpoint` | An alternative
endpoint of the S3 token service, This could be used with s3-compatible object
storage service like MINIO that has a different STS endpoint. | (none) |
No | 0.8.0-incubating |
+| Configuration item | Description
| Default value | Required
| Since Version |
+|----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------------------------------------------------|------------------|
+| `gravitino.iceberg-rest.io-impl` | The IO implementation
for `FileIO` in Iceberg, use `org.apache.iceberg.aws.s3.S3FileIO` for S3.
| (none) | No
| 0.6.0-incubating |
+| `gravitino.iceberg-rest.credential-provider-type` | Supports `s3-token` and
`s3-secret-key` for S3. `s3-token` generates a temporary token according to the
query data path while `s3-secret-key` using the s3 secret access key to access
S3 data. | (none) | No
| 0.7.0-incubating |
+| `gravitino.iceberg-rest.s3-access-key-id` | The static access key
ID used to access S3 data.
| (none) | No
| 0.6.0-incubating |
+| `gravitino.iceberg-rest.s3-secret-access-key` | The static secret
access key used to access S3 data.
| (none) | No
| 0.6.0-incubating |
+| `gravitino.iceberg-rest.s3-endpoint` | An alternative endpoint
of the S3 service, This could be used for S3FileIO with any s3-compatible
object storage service that has a different endpoint, or access a private S3
endpoint in a virtual private cloud. | (none) | No
| 0.6.0-incubating |
+| `gravitino.iceberg-rest.s3-region` | The region of the S3
service, like `us-west-2`.
| (none) | No
| 0.6.0-incubating |
+| `gravitino.iceberg-rest.s3-role-arn` | The ARN of the role to
access the S3 data.
| (none) | Yes, when
`credential-provider-type` is `s3-token` | 0.7.0-incubating |
+| `gravitino.iceberg-rest.s3-external-id` | The S3 external id to
generate token, only used when `credential-provider-type` is `s3-token`.
| (none) | No
| 0.7.0-incubating |
+| `gravitino.iceberg-rest.s3-token-expire-in-secs` | The S3 session token
expire time in secs, it couldn't exceed the max session time of the assumed
role, only used when `credential-provider-type` is `s3-token`.
| 3600 | No
| 0.7.0-incubating |
+| `gravitino.iceberg-rest.s3-token-service-endpoint` | An alternative endpoint
of the S3 token service, This could be used with s3-compatible object storage
service like MINIO that has a different STS endpoint.
| (none) | No
| 0.8.0-incubating |
For other Iceberg s3 properties not managed by Gravitino like `s3.sse.type`,
you could config it directly by `gravitino.iceberg-rest.s3.sse.type`.
@@ -175,15 +175,16 @@ Please set `gravitino.iceberg-rest.warehouse` to
`gs://{bucket_name}/${prefix_na
Gravitino Iceberg REST service supports generating SAS token to access ADLS
data.
-| Configuration item | Description
| Default value | Required | Since Version |
-|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------------|---------------|----------|------------------|
-| `gravitino.iceberg-rest.io-impl` | The IO implementation
for `FileIO` in Iceberg, use `org.apache.iceberg.azure.adlsv2.ADLSFileIO` for
ADLS. | (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.credential-provider-type` | Supports `adls-token`,
generates a temporary token according to the query data path.
| (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.azure-storage-account-name` | The static storage
account name used to access ADLS data.
| (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.azure-storage-account-key` | The static storage
account key used to access ADLS data.
| (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.azure-tenant-id` | Azure Active Directory
(AAD) tenant ID.
| (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.azure-client-id` | Azure Active Directory
(AAD) client ID used for authentication.
| (none) | Yes | 0.8.0-incubating |
-| `gravitino.iceberg-rest.azure-client-secret` | Azure Active Directory
(AAD) client secret used for authentication.
| (none) | Yes | 0.8.0-incubating |
+| Configuration item | Description
| Default value | Required | Since Version |
+|-----------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|------------------|
+| `gravitino.iceberg-rest.io-impl` | The IO implementation
for `FileIO` in Iceberg, use `org.apache.iceberg.azure.adlsv2.ADLSFileIO` for
ADLS.
| (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.credential-provider-type` | Supports `adls-token`
and `azure-account-key`. `adls-token` generates a temporary token according to
the query data path while `azure-account-key` uses a storage account key to
access ADLS data. | (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.azure-storage-account-name` | The static storage
account name used to access ADLS data.
| (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.azure-storage-account-key` | The static storage
account key used to access ADLS data.
| (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.azure-tenant-id` | Azure Active Directory
(AAD) tenant ID, only used when `credential-provider-type` is `adls-token`.
| (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.azure-client-id` | Azure Active Directory
(AAD) client ID used for authentication, only used when
`credential-provider-type` is `adls-token`.
| (none) | Yes |
0.8.0-incubating |
+| `gravitino.iceberg-rest.azure-client-secret` | Azure Active Directory
(AAD) client secret used for authentication, only used when
`credential-provider-type` is `adls-token`.
| (none) | Yes | 0.8.0-incubating |
+| `gravitino.iceberg-rest.adls-token-expire-in-secs` | The ADLS SAS token
expire time in secs, only used when `credential-provider-type` is
`adls-token`.
| 3600 | No | 0.8.0-incubating |
For other Iceberg ADLS properties not managed by Gravitino like
`adls.read.block-size-bytes`, you could config it directly by
`gravitino.iceberg-rest.adls.read.block-size-bytes`.
diff --git
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java
similarity index 92%
copy from
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
copy to
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java
index 570298d05..b16d504e1 100644
---
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java
@@ -36,7 +36,7 @@ import
org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
@SuppressWarnings("FormatStringAnnotation")
@EnabledIfEnvironmentVariable(named = "GRAVITINO_TEST_CLOUD_IT", matches =
"true")
-public class IcebergRESTADLSIT extends IcebergRESTJdbcCatalogIT {
+public class IcebergRESTADLSTokenIT extends IcebergRESTJdbcCatalogIT {
private String storageAccountName;
private String storageAccountKey;
@@ -49,13 +49,14 @@ public class IcebergRESTADLSIT extends
IcebergRESTJdbcCatalogIT {
void initEnv() {
this.storageAccountName =
System.getenv()
- .getOrDefault("GRAVITINO_ADLS_STORAGE_ACCOUNT_NAME",
"{STORAGE_ACCOUNT_NAME}");
+ .getOrDefault("GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME",
"{STORAGE_ACCOUNT_NAME}");
this.storageAccountKey =
- System.getenv().getOrDefault("GRAVITINO_ADLS_STORAGE_ACCOUNT_KEY",
"{STORAGE_ACCOUNT_KEY}");
- this.tenantId = System.getenv().getOrDefault("GRAVITINO_ADLS_TENANT_ID",
"{TENANT_ID}");
- this.clientId = System.getenv().getOrDefault("GRAVITINO_ADLS_CLIENT_ID",
"{CLIENT_ID}");
+ System.getenv()
+ .getOrDefault("GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY",
"{STORAGE_ACCOUNT_KEY}");
+ this.tenantId = System.getenv().getOrDefault("GRAVITINO_AZURE_TENANT_ID",
"{TENANT_ID}");
+ this.clientId = System.getenv().getOrDefault("GRAVITINO_AZURE_CLIENT_ID",
"{CLIENT_ID}");
this.clientSecret =
- System.getenv().getOrDefault("GRAVITINO_ADLS_CLIENT_SECRET",
"{CLIENT_SECRET}");
+ System.getenv().getOrDefault("GRAVITINO_AZURE_CLIENT_SECRET",
"{CLIENT_SECRET}");
this.warehousePath =
String.format(
"abfss://%s@%s.dfs.core.windows.net/data/test",
diff --git
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java
similarity index 53%
rename from
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
rename to
iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java
index 570298d05..42709162a 100644
---
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSIT.java
+++
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java
@@ -22,7 +22,6 @@ package org.apache.gravitino.iceberg.integration.test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.gravitino.abs.credential.ADLSLocationUtils;
import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
import org.apache.gravitino.credential.CredentialConstants;
import org.apache.gravitino.iceberg.common.IcebergConfig;
@@ -30,32 +29,24 @@ import org.apache.gravitino.integration.test.util.BaseIT;
import org.apache.gravitino.integration.test.util.DownloaderUtils;
import org.apache.gravitino.integration.test.util.ITUtils;
import org.apache.gravitino.storage.AzureProperties;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
@SuppressWarnings("FormatStringAnnotation")
@EnabledIfEnvironmentVariable(named = "GRAVITINO_TEST_CLOUD_IT", matches =
"true")
-public class IcebergRESTADLSIT extends IcebergRESTJdbcCatalogIT {
+public class IcebergRESTAzureAccountKeyIT extends IcebergRESTJdbcCatalogIT {
private String storageAccountName;
private String storageAccountKey;
- private String tenantId;
- private String clientId;
- private String clientSecret;
private String warehousePath;
@Override
void initEnv() {
this.storageAccountName =
System.getenv()
- .getOrDefault("GRAVITINO_ADLS_STORAGE_ACCOUNT_NAME",
"{STORAGE_ACCOUNT_NAME}");
+ .getOrDefault("GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME",
"{STORAGE_ACCOUNT_NAME}");
this.storageAccountKey =
- System.getenv().getOrDefault("GRAVITINO_ADLS_STORAGE_ACCOUNT_KEY",
"{STORAGE_ACCOUNT_KEY}");
- this.tenantId = System.getenv().getOrDefault("GRAVITINO_ADLS_TENANT_ID",
"{TENANT_ID}");
- this.clientId = System.getenv().getOrDefault("GRAVITINO_ADLS_CLIENT_ID",
"{CLIENT_ID}");
- this.clientSecret =
- System.getenv().getOrDefault("GRAVITINO_ADLS_CLIENT_SECRET",
"{CLIENT_SECRET}");
+ System.getenv()
+ .getOrDefault("GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY",
"{STORAGE_ACCOUNT_KEY}");
this.warehousePath =
String.format(
"abfss://%s@%s.dfs.core.windows.net/data/test",
@@ -91,20 +82,13 @@ public class IcebergRESTADLSIT extends
IcebergRESTJdbcCatalogIT {
configMap.put(
IcebergConfig.ICEBERG_CONFIG_PREFIX +
CredentialConstants.CREDENTIAL_PROVIDER_TYPE,
- CredentialConstants.ADLS_TOKEN_CREDENTIAL_PROVIDER_TYPE);
+ CredentialConstants.AZURE_ACCOUNT_KEY_CREDENTIAL_PROVIDER_TYPE);
configMap.put(
IcebergConfig.ICEBERG_CONFIG_PREFIX +
AzureProperties.GRAVITINO_AZURE_STORAGE_ACCOUNT_NAME,
storageAccountName);
configMap.put(
IcebergConfig.ICEBERG_CONFIG_PREFIX +
AzureProperties.GRAVITINO_AZURE_STORAGE_ACCOUNT_KEY,
storageAccountKey);
- configMap.put(
- IcebergConfig.ICEBERG_CONFIG_PREFIX +
AzureProperties.GRAVITINO_AZURE_TENANT_ID, tenantId);
- configMap.put(
- IcebergConfig.ICEBERG_CONFIG_PREFIX +
AzureProperties.GRAVITINO_AZURE_CLIENT_ID, clientId);
- configMap.put(
- IcebergConfig.ICEBERG_CONFIG_PREFIX +
AzureProperties.GRAVITINO_AZURE_CLIENT_SECRET,
- clientSecret);
configMap.put(
IcebergConfig.ICEBERG_CONFIG_PREFIX + IcebergConstants.IO_IMPL,
@@ -130,76 +114,4 @@ public class IcebergRESTADLSIT extends
IcebergRESTJdbcCatalogIT {
String targetDir = String.format("%s/iceberg-rest-server/libs/",
gravitinoHome);
BaseIT.copyBundleJarsToDirectory("azure-bundle", targetDir);
}
-
- @Test
- public void testParseLocationValidInput() {
- String location =
"abfss://[email protected]/data/test/path";
-
- ADLSLocationUtils.ADLSLocationParts parts =
ADLSLocationUtils.parseLocation(location);
-
- Assertions.assertEquals("container", parts.getContainer(), "Container name
should match");
- Assertions.assertEquals("account", parts.getAccountName(), "Account name
should match");
- Assertions.assertEquals("/data/test/path", parts.getPath(), "Path should
match");
- }
-
- @Test
- public void testParseLocationInvalidInput() {
- String location = "abfss://container/invalid/location";
-
- Exception exception =
- Assertions.assertThrows(
- IllegalArgumentException.class,
- () -> {
- ADLSLocationUtils.parseLocation(location);
- });
-
- Assertions.assertTrue(
- exception.getMessage().contains("Invalid location"),
- "Exception message should indicate invalid location");
- }
-
- @Test
- public void testTrimSlashesNullInput() {
- Assertions.assertNull(ADLSLocationUtils.trimSlashes(null), "Null input
should return null");
- }
-
- @Test
- public void testTrimSlashesEmptyInput() {
- Assertions.assertEquals(
- "", ADLSLocationUtils.trimSlashes(""), "Empty input should return
empty string");
- }
-
- @Test
- public void testTrimSlashesNoSlashes() {
- String input = "data/test/path";
- Assertions.assertEquals(
- "data/test/path",
- ADLSLocationUtils.trimSlashes(input),
- "Input without slashes should remain unchanged");
- }
-
- @Test
- public void testTrimSlashesLeadingAndTrailingSlashes() {
- String input = "/data/test/path/";
- Assertions.assertEquals(
- "data/test/path",
- ADLSLocationUtils.trimSlashes(input),
- "Leading and trailing slashes should be trimmed");
- }
-
- @Test
- public void testTrimSlashesMultipleLeadingAndTrailingSlashes() {
- String input = "///data/test/path///";
- Assertions.assertEquals(
- "data/test/path",
- ADLSLocationUtils.trimSlashes(input),
- "Multiple leading and trailing slashes should be trimmed");
- }
-
- @Test
- public void testTrimSlashesOnlySlashes() {
- String input = "////";
- Assertions.assertEquals(
- "", ADLSLocationUtils.trimSlashes(input), "Only slashes should result
in an empty string");
- }
}