[#12131] feat(kms): Define key inspection API#12132
Conversation
|
@lasdf1234, could you also review this KMS API series? The full series is tracked in #12131. |
|
Hi @roryqi and @lasdf1234 — please review this KMS API change. The full series and review scope are tracked in #12131. |
Code Coverage Report
Files
|
|
|
||
| /** The KMS product API that defines key identifier and operation semantics. */ | ||
| @DeveloperApi | ||
| public enum KmsApi { |
There was a problem hiding this comment.
If we want to use enum here and add a new KMS service, it will be difficult.
I prefer using SPI patten. Maybe you can refer to catalog provider and credential provider.
I feel that it would be better to use String.
There was a problem hiding this comment.
Done in 10fb53a. The closed enum is removed: KmsReference.api() and KmsClientFactory.api() now use stable string identifiers, and references reject null/blank values and canonicalize by trimming and lowercasing. The identifier is only a registry key; it is never used as a class name or reflection input. API/common tests, JSON round-trip/canonicalization coverage, Spotless, test-fixture packaging, and Javadocs all pass.
| * <p>Capabilities describe downstream use; this API does not perform cryptographic operations. | ||
| */ | ||
| @DeveloperApi | ||
| public interface KmsKeyProperties { |
There was a problem hiding this comment.
I don't know the concrete scenario? I feel a weird. Because it will common to use a capabilities class instead of properties class. You can refer to our CatalogCapabiities class.
There was a problem hiding this comment.
The proposed CatalogCapability model is not applicable here. KmsKeyProperties describes a specific key’s presence, enabled state, and supported operations. These values vary by key; they are not capabilities of KmsClient.
Client- or provider-level capability discovery is a separate API. It is out of scope and can be added later when there is a concrete requirement.
There was a problem hiding this comment.
Pull request overview
This PR introduces provider-neutral Java contracts in the api module for server-side KMS key inspection/validation (API identification, key references, client/factory SPI, and normalized key properties), along with reusable test fixtures and baseline unit tests to support future provider implementations.
Changes:
- Added
KmsApi,KmsReference,KmsClient,KmsClientFactory, andKmsKeyPropertiesas@DeveloperApicontracts for key inspection. - Added distinct exception types for configuration vs authentication failures (
KmsConfigurationException,KmsAuthenticationException). - Introduced test fixtures (contract tests +
FakeKmsClient) and enabled Gradle test fixtures for theapimodule.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsApi.java | Defines supported KMS APIs and stable wire-value parsing. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsAuthenticationException.java | Adds a KMS-specific authentication failure type layered on ConnectionFailedException. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsClient.java | Introduces the provider-neutral key inspection client contract. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsClientFactory.java | Defines the provider factory SPI for creating source-bound KmsClients. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsConfigurationException.java | Adds a KMS-specific configuration validation exception. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsKeyProperties.java | Defines the normalized key property/capability reporting interface. |
| api/src/main/java/org/apache/gravitino/encryption/kms/KmsReference.java | Adds the typed key reference model (api/source/keyId) with value semantics. |
| api/src/test/java/org/apache/gravitino/encryption/kms/TestFakeKmsClient.java | Applies the shared client contract fixture to FakeKmsClient. |
| api/src/test/java/org/apache/gravitino/encryption/kms/TestKmsApi.java | Unit tests for KmsApi wire parsing and error messaging. |
| api/src/test/java/org/apache/gravitino/encryption/kms/TestKmsClient.java | Unit tests for KmsClient behavior and default close(). |
| api/src/test/java/org/apache/gravitino/encryption/kms/TestKmsReference.java | Unit tests for KmsReference validation and value semantics. |
| api/src/testFixtures/java/org/apache/gravitino/encryption/kms/FakeKmsClient.java | Provides an in-memory test fixture implementation of KmsClient. |
| api/src/testFixtures/java/org/apache/gravitino/encryption/kms/TestKmsClientContract.java | Shared contract tests for provider KmsClient implementations. |
| api/src/testFixtures/java/org/apache/gravitino/encryption/kms/TestKmsClientFactoryContract.java | Shared contract test for provider KmsClientFactory implementations. |
| api/build.gradle.kts | Enables java-test-fixtures and exposes JUnit to fixture consumers. |
| /** | ||
| * Common properties reported for a KMS key. | ||
| * | ||
| * <p>Capabilities describe downstream use; this API does not perform cryptographic operations. | ||
| */ |
There was a problem hiding this comment.
Addressed in cf4a8c9 by making presence structural: KmsClient.getKeyProperties now returns Optional<KmsKeyProperties>, and present() is removed. Optional.empty() is reserved for authoritative provider not-found, while authentication, authorization, timeout, availability, and other indeterminate failures remain exceptions. KmsKeyProperties therefore only describes a located key, and its Javadocs now define the lifecycle and structural-capability semantics.
| Assertions.assertEquals(reference, properties.reference()); | ||
| Assertions.assertFalse(properties.present()); | ||
| } |
There was a problem hiding this comment.
Addressed in cf4a8c9. The reusable provider contract now requires a non-null Optional, asserts Optional.of for a found key, and asserts Optional.empty for authoritative not-found. The fake-client tests also cover a disabled-but-present key, so lifecycle state is independent from presence. API/common tests, Spotless, test-fixture packaging, and Javadocs pass.
| public KmsAuthenticationException(@FormatString String message, Object... args) { | ||
| super(message, args); | ||
| } | ||
| } |
There was a problem hiding this comment.
The API module is mainly the user-facing APIs. These interfaces are more developer-facing APIs. We should not put it here.
We can either put them in connector module. Or, we can put them in the place where we use it.
There was a problem hiding this comment.
KMS should be used for server and client. Maybe we could consider putting it into common module, too.
There was a problem hiding this comment.
Done in 391ec3d. api now retains only the user-facing KmsReference and KmsApi data contracts. KmsClient, KmsClientFactory, key properties, exceptions, the fake client, and shared contract-test fixtures now live in common. Validation passed with :api:test, :common:test, both modules’ Spotless checks, the common test-fixtures JAR, and API/common Javadocs.
|
@nevzheng All the java.class files are located in a single package path. Can different functions of java.class be placed in different packages? |
|
Added canonical JSON persistence for KmsReference and KmsApi plus round-trip coverage. Persisted key references now retain their canonical API, source, and key ID. #12133 has been restacked on this head. |
|
@lasdf1234 Done in 391ec3d. I separated the functions by Gradle module rather than creating several small Java subpackages: the user-facing reference contract remains in |
|
Thanks for the review feedback. I’ve completed the author-side revisions on the current PR:
Local API/common tests, Spotless, test-fixture packaging, and Javadocs pass. GitHub CI currently has no failures; the remaining integration jobs are still running. Current head: @roryqi @lasdf1234 — please take another look and either approve or identify any remaining concrete concerns. |
What changes were proposed in this pull request?
Add provider-neutral Java contracts for server-private KMS key inspection:
KmsReferenceidentifies a key by canonical KMS API, configured source, and provider-native key ID;KmsClientandKmsClientFactorydefine the provider extension contract incommon;KmsKeyPropertiesexposes normalized, point-in-time state for a located key;The user-facing reference value remains in
api. The developer-facing SPI, exceptions, and reusable provider test contracts live incommon.Why are the changes needed?
KMS integrations need a common contract that does not expose credentials or key material. Applications can identify and inspect keys without depending on provider SDK types, while providers remain independently loadable through canonical string identifiers.
This PR defines only the provider-neutral API/SPI. Named-source routing follows in #12133. Concrete providers, provider integration tests, server configuration, and cryptographic operations are outside this PR.
Part of #12131.
Does this PR introduce any user-facing change?
Yes. It adds new
@DeveloperApiJava contracts. It does not add REST APIs, server configuration, concrete providers, or cryptographic operations.How was this patch tested?
./gradlew :api:test :common:test./gradlew :api:spotlessCheck :common:spotlessCheck./gradlew :common:testFixturesJar./gradlew :api:javadoc :common:javadocSeries