Skip to content

Commit 8d1f354

Browse files
committed
Add support for S3 request signing
Fixes #32.
1 parent 83be3b1 commit 8d1f354

File tree

57 files changed

+2104
-282
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2104
-282
lines changed

LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ License: https://www.apache.org/licenses/LICENSE-2.0
216216
This product includes code from Apache Iceberg.
217217

218218
* spec/iceberg-rest-catalog-open-api.yaml
219+
* spec/iceberg-s3-signer-open-api.yaml
219220
* spec/polaris-catalog-apis/oauth-tokens-api.yaml
220221
* integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java
221222
* runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Apache Polaris is organized into the following modules:
5151
- `polaris-api-management-model` - The Polaris management model
5252
- `polaris-api-management-service` - The Polaris management service
5353
- `polaris-api-iceberg-service` - The Iceberg REST service
54+
- `polaris-api-iceberg-aws-sign-service` - The Iceberg REST service for S3 remote signing
5455
- Runtime modules:
5556
- `polaris-runtime-service` - The runtime components of the Polaris server
5657
- `polaris-runtime-defaults` - The runtime configuration defaults

api/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ This directory contains the API modules for Apache Polaris.
3333
Iceberg REST API.
3434
- [`polaris-api-catalog-service`](polaris-catalog-service): contains the service classes for the Polaris
3535
native Catalog REST API.
36+
- [`polaris-api-iceberg-aws-sign-service`](iceberg-aws-sign-service): contains the service classes
37+
for AWS S3 remote signing.
3638

3739
The classes in these modules are generated from the OpenAPI specification files in the
3840
[`spec`](../spec) directory.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
21+
22+
plugins {
23+
alias(libs.plugins.openapi.generator)
24+
id("polaris-client")
25+
alias(libs.plugins.jandex)
26+
}
27+
28+
dependencies {
29+
implementation(project(":polaris-core"))
30+
31+
implementation(platform(libs.iceberg.bom))
32+
implementation("org.apache.iceberg:iceberg-api")
33+
implementation("org.apache.iceberg:iceberg-core")
34+
implementation("org.apache.iceberg:iceberg-aws")
35+
36+
implementation(libs.jakarta.annotation.api)
37+
implementation(libs.jakarta.inject.api)
38+
implementation(libs.jakarta.validation.api)
39+
implementation(libs.swagger.annotations)
40+
41+
implementation(libs.jakarta.servlet.api)
42+
implementation(libs.jakarta.ws.rs.api)
43+
44+
implementation(platform(libs.micrometer.bom))
45+
implementation("io.micrometer:micrometer-core")
46+
47+
implementation(platform(libs.jackson.bom))
48+
implementation("com.fasterxml.jackson.core:jackson-annotations")
49+
implementation("com.fasterxml.jackson.core:jackson-core")
50+
implementation("com.fasterxml.jackson.core:jackson-databind")
51+
52+
compileOnly(libs.microprofile.fault.tolerance.api)
53+
54+
compileOnly(project(":polaris-immutables"))
55+
annotationProcessor(project(":polaris-immutables", configuration = "processor"))
56+
}
57+
58+
val rootDir = rootProject.layout.projectDirectory
59+
val specsDir = rootDir.dir("spec")
60+
val templatesDir = rootDir.dir("server-templates")
61+
// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the
62+
// whole directory to its task output, but 'generated/' is not exclusive to that task and in turn
63+
// breaks Gradle's caching.
64+
val generatedDir = project.layout.buildDirectory.dir("generated-openapi")
65+
val generatedOpenApiSrcDir = project.layout.buildDirectory.dir("generated-openapi/src/main/java")
66+
67+
openApiGenerate {
68+
// The OpenAPI generator does NOT resolve relative paths correctly against the Gradle project
69+
// directory
70+
inputSpec = provider { specsDir.file("polaris-s3-signer-api.yaml").asFile.absolutePath }
71+
generatorName = "jaxrs-resteasy"
72+
outputDir = provider { generatedDir.get().asFile.absolutePath }
73+
apiPackage = "org.apache.polaris.service.aws.sign.api"
74+
ignoreFileOverride.set(provider { rootDir.file(".openapi-generator-ignore").asFile.absolutePath })
75+
templateDir.set(provider { templatesDir.asFile.absolutePath })
76+
removeOperationIdPrefix.set(true)
77+
globalProperties.put("apis", "S3SignerApi")
78+
globalProperties.put("models", "false")
79+
globalProperties.put("apiDocs", "false")
80+
globalProperties.put("modelTests", "false")
81+
configOptions.put("resourceName", "catalog")
82+
configOptions.put("useTags", "true")
83+
configOptions.put("useBeanValidation", "false")
84+
configOptions.put("sourceFolder", "src/main/java")
85+
configOptions.put("useJakartaEe", "true")
86+
configOptions.put("hideGenerationTimestamp", "true")
87+
additionalProperties.put("apiNamePrefix", "IcebergRest")
88+
additionalProperties.put("apiNameSuffix", "")
89+
additionalProperties.put("metricsPrefix", "polaris")
90+
serverVariables.put("basePath", "api/catalog")
91+
typeMappings =
92+
mapOf("S3SignRequest" to "org.apache.polaris.service.aws.sign.model.PolarisS3SignRequest")
93+
importMappings =
94+
mapOf(
95+
"IcebergErrorResponse" to "org.apache.iceberg.rest.responses.ErrorResponse",
96+
"S3SignRequest" to "org.apache.polaris.service.aws.sign.model.PolarisS3SignRequest",
97+
"SignS3Request200Response" to
98+
"org.apache.polaris.service.aws.sign.model.PolarisS3SignResponse",
99+
)
100+
}
101+
102+
listOf("sourcesJar", "compileJava", "processResources").forEach { task ->
103+
tasks.named(task) { dependsOn("openApiGenerate") }
104+
}
105+
106+
sourceSets { main { java { srcDir(generatedOpenApiSrcDir) } } }
107+
108+
tasks.named<GenerateTask>("openApiGenerate") {
109+
inputs.dir(templatesDir)
110+
inputs.dir(specsDir)
111+
actions.addFirst { delete { delete(generatedDir) } }
112+
doLast {
113+
// Replace S3SignRequest with PolarisS3SignRequest in generated files
114+
fileTree(generatedDir)
115+
.matching { include("**/*.java") }
116+
.forEach { file ->
117+
val content = file.readText()
118+
val updatedContent =
119+
content.replace("S3SignRequest s3SignRequest", "PolarisS3SignRequest s3SignRequest")
120+
file.writeText(updatedContent)
121+
}
122+
}
123+
}
124+
125+
tasks.named("javadoc") { dependsOn("jandex") }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.service.aws.sign.model;
21+
22+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
23+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
24+
import jakarta.annotation.Nullable;
25+
import org.apache.iceberg.aws.s3.signer.S3SignRequest;
26+
import org.apache.polaris.immutables.PolarisImmutable;
27+
import org.immutables.value.Value;
28+
29+
/**
30+
* Request for S3 signing requests.
31+
*
32+
* <p>Copy of {@link S3SignRequest}, because the original does not have Jackson annotations.
33+
*/
34+
@PolarisImmutable
35+
@JsonDeserialize(as = ImmutablePolarisS3SignRequest.class)
36+
@JsonSerialize(as = ImmutablePolarisS3SignRequest.class)
37+
public interface PolarisS3SignRequest extends S3SignRequest {
38+
39+
@Value.Default
40+
@Nullable // Replace javax.annotation.Nullable with jakarta.annotation.Nullable
41+
@Override
42+
default String body() {
43+
return null;
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.service.aws.sign.model;
21+
22+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
23+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
24+
import org.apache.iceberg.aws.s3.signer.S3SignResponse;
25+
import org.apache.polaris.immutables.PolarisImmutable;
26+
27+
/**
28+
* Response for S3 signing requests.
29+
*
30+
* <p>Copy of {@link S3SignResponse}, because the original does not have Jackson annotations.
31+
*/
32+
@PolarisImmutable
33+
@JsonDeserialize(as = ImmutablePolarisS3SignResponse.class)
34+
@JsonSerialize(as = ImmutablePolarisS3SignResponse.class)
35+
public interface PolarisS3SignResponse extends S3SignResponse {}

bom/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ dependencies {
2626
api(rootProject)
2727
api(project(":polaris-api-catalog-service"))
2828
api(project(":polaris-api-iceberg-service"))
29+
api(project(":polaris-api-iceberg-aws-sign-service"))
2930
api(project(":polaris-api-management-model"))
3031
api(project(":polaris-api-management-service"))
3132

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ tasks.register<Exec>("regeneratePythonClient") {
147147
workingDir = project.projectDir
148148
commandLine("bash", "client/templates/regenerate.sh")
149149

150+
dependsOn(":polaris-api-iceberg-aws-sign-service:processResources")
150151
dependsOn(":polaris-api-iceberg-service:processResources")
151152
dependsOn(":polaris-api-management-service:processResources")
152153
dependsOn(":polaris-api-catalog-service:processResources")

gradle/projects.main.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
polaris-bom=bom
2222
polaris-core=polaris-core
23+
polaris-api-iceberg-aws-sign-service=api/iceberg-aws-sign-service
2324
polaris-api-iceberg-service=api/iceberg-service
2425
polaris-api-management-model=api/management-model
2526
polaris-api-management-service=api/management-service

integration-tests/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ dependencies {
3333
implementation(platform(libs.iceberg.bom))
3434
implementation("org.apache.iceberg:iceberg-api")
3535
implementation("org.apache.iceberg:iceberg-core")
36+
implementation("org.apache.iceberg:iceberg-aws")
3637

3738
implementation("org.apache.iceberg:iceberg-api:${libs.versions.iceberg.get()}:tests")
3839
implementation("org.apache.iceberg:iceberg-core:${libs.versions.iceberg.get()}:tests")

0 commit comments

Comments
 (0)