Skip to content
Closed
3 changes: 3 additions & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
plugins {
`maven-publish`
`java-test-fixtures`
id("java")
id("idea")
}
Expand All @@ -32,6 +33,8 @@ dependencies {
testImplementation(libs.junit.jupiter.api)
testImplementation(libs.junit.jupiter.params)
testRuntimeOnly(libs.junit.jupiter.engine)

testFixturesApi(libs.junit.jupiter.api)
}

tasks.build {
Expand Down
85 changes: 85 additions & 0 deletions api/src/main/java/org/apache/gravitino/encryption/kms/KmsApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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.encryption.kms;

import java.util.Arrays;
import java.util.Locale;
import java.util.stream.Collectors;
import org.apache.gravitino.annotation.DeveloperApi;

/** The KMS product API that defines key identifier and operation semantics. */
@DeveloperApi
public enum KmsApi {
/** Amazon Web Services Key Management Service. */
AWS_KMS("aws-kms"),

/** Google Cloud Key Management Service. */
GOOGLE_CLOUD_KMS("google-cloud-kms"),

/** Microsoft Azure Key Vault. */
AZURE_KEY_VAULT("azure-key-vault"),

/** The OpenBao Transit secrets engine API. */
OPENBAO_TRANSIT("openbao-transit"),

/** The HashiCorp Vault Transit secrets engine API. */
VAULT_TRANSIT("vault-transit");

private final String wireValue;

KmsApi(String wireValue) {
this.wireValue = wireValue;
}

/**
* Returns the stable configuration value for this API.
*
* @return the configuration value
*/
public String wireValue() {
return wireValue;
}

/**
* Parses a configured API value.
*
* @param value configured API value
* @return the matching API
* @throws IllegalArgumentException if the value is null, blank, or unsupported
*/
public static KmsApi fromWireValue(String value) {
if (value == null || value.trim().isEmpty()) {
throw new IllegalArgumentException("KMS API cannot be blank");
}

String normalized = value.trim().toLowerCase(Locale.ROOT);
return Arrays.stream(values())
.filter(api -> api.wireValue.equals(normalized))
.findFirst()
.orElseThrow(
() ->
new IllegalArgumentException(
String.format(
"Unsupported KMS API '%s'; supported values are %s",
value,
Arrays.stream(values())
.map(KmsApi::wireValue)
.collect(Collectors.joining(", ")))));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.encryption.kms;

import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;
import org.apache.gravitino.exceptions.ConnectionFailedException;

/** Indicates that a KMS backend rejected or could not resolve configured credentials. */
public class KmsAuthenticationException extends ConnectionFailedException {

/**
* Creates an authentication exception with the specified cause and detail message.
*
* @param cause the cause
* @param message the detail message
* @param args the arguments to the message
*/
@FormatMethod
public KmsAuthenticationException(Throwable cause, @FormatString String message, Object... args) {
super(cause, message, args);
}

/**
* Creates an authentication exception with the specified detail message.
*
* @param message the detail message
* @param args the arguments to the message
*/
@FormatMethod
public KmsAuthenticationException(@FormatString String message, Object... args) {
super(message, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.encryption.kms;

import org.apache.gravitino.annotation.DeveloperApi;
import org.apache.gravitino.exceptions.ConnectionFailedException;

/**
* Inspects keys managed by a configured KMS.
*
* <p>This is a server-side operation client, not a credential-vending API. Provider credentials
* authenticate calls made by the client and must never be returned to callers. This client does not
* perform cryptographic operations.
*/
@DeveloperApi
public interface KmsClient extends AutoCloseable {

/**
* Reads the provider-reported properties of a key.
*
* @param reference key to inspect
* @return normalized key properties
* @throws IllegalArgumentException if the reference does not belong to this client
* @throws ConnectionFailedException if the provider cannot be queried
*/
KmsKeyProperties getKeyProperties(KmsReference reference);

/** Releases resources owned by this client. */
@Override
default void close() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.encryption.kms;

import java.util.Map;
import org.apache.gravitino.annotation.DeveloperApi;
import org.apache.gravitino.exceptions.ConnectionFailedException;

/** Creates server-side KMS clients for one supported KMS API. */
@DeveloperApi
public interface KmsClientFactory {

/**
* Returns the KMS API implemented by this factory.
*
* @return the supported KMS API
*/
KmsApi api();

/**
* Creates a client bound to a configured KMS source.
*
* <p>Provider credentials are private implementation details of the returned client. They must
* not be exposed as Gravitino credentials or key properties.
*
* @param source logical name of the configured KMS instance
* @param properties provider-specific configuration
* @return the configured client
* @throws IllegalArgumentException if the source or configuration is invalid
* @throws ConnectionFailedException if required external initialization fails
*/
KmsClient create(String source, Map<String, String> properties);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.encryption.kms;

import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;

/** Indicates invalid KMS configuration detected during initialization. */
public class KmsConfigurationException extends IllegalArgumentException {

/**
* Creates a configuration exception with the specified detail message.
*
* @param message the detail message
* @param args the arguments to the message
*/
@FormatMethod
public KmsConfigurationException(@FormatString String message, Object... args) {
super(args.length == 0 ? message : String.format(message, args));
}

/**
* Creates a configuration exception with the specified cause and detail message.
*
* @param cause the cause
* @param message the detail message
* @param args the arguments to the message
*/
@FormatMethod
public KmsConfigurationException(Throwable cause, @FormatString String message, Object... args) {
super(args.length == 0 ? message : String.format(message, args), cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.encryption.kms;

import org.apache.gravitino.annotation.DeveloperApi;

/**
* Common properties reported for a KMS key.
*
* <p>Capabilities describe downstream use; this API does not perform cryptographic operations.
*/
@DeveloperApi
public interface KmsKeyProperties {

/**
* Returns the requested key reference.
*
* @return the key reference
*/
KmsReference reference();

/**
* Returns whether the provider reports that the key exists.
*
* @return whether the key exists
*/
boolean present();

/**
* Returns whether the provider reports that the key is enabled.
*
* @return whether the key is enabled
*/
boolean enabled();

/**
* Returns whether the key supports wrapping data-encryption keys.
*
* @return whether wrapping is supported
*/
boolean supportsWrapping();

/**
* Returns whether the key supports unwrapping data-encryption keys.
*
* @return whether unwrapping is supported
*/
boolean supportsUnwrapping();
}
Loading
Loading