This repository has been archived by the owner on Jul 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from strimzi/kms-vault
Kms vault
- Loading branch information
Showing
6 changed files
with
258 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>io.strimzi</groupId> | ||
<artifactId>topic-encryption</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>kms-vault</artifactId> | ||
<name>KMS - Vault</name> | ||
<description>Implementation of the KeyManagementSystem with Vault as the underlying KMS.</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.strimzi</groupId> | ||
<artifactId>common</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.strimzi</groupId> | ||
<artifactId>kms</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-api</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-slf4j-impl</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.github.spotbugs</groupId> | ||
<artifactId>spotbugs-annotations</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-annotations</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-databind</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
152 changes: 152 additions & 0 deletions
152
kms-vault/src/main/java/io/strimzi/kafka/topicenc/kms/vault/VaultKms.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
* Copyright Strimzi authors. | ||
* License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
*/ | ||
package io.strimzi.kafka.topicenc.kms.vault; | ||
|
||
import static java.util.Objects.isNull; | ||
|
||
import java.io.IOException; | ||
import java.io.UnsupportedEncodingException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.URLEncoder; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.net.http.HttpResponse.BodyHandlers; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import javax.crypto.SecretKey; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
import io.strimzi.kafka.topicenc.common.EncUtils; | ||
import io.strimzi.kafka.topicenc.kms.KeyMgtSystem; | ||
import io.strimzi.kafka.topicenc.kms.KmsDefinition; | ||
import io.strimzi.kafka.topicenc.kms.KmsException; | ||
|
||
/** | ||
* Key Management System interface implemented with Vault. | ||
*/ | ||
public class VaultKms implements KeyMgtSystem { | ||
|
||
public static final String VAULT_TOKEN_HEADER = "X-Vault-Token"; | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(VaultKms.class); | ||
private static final ObjectMapper OBJ_MAPPER = new ObjectMapper(); | ||
private static final String KEY_PATH = "/data/data/%s"; | ||
|
||
private HttpClient client; | ||
private KmsDefinition config; | ||
|
||
public VaultKms() { | ||
} | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param config a valid KmsDefiniton instance containing the info to interact | ||
* with Vault. | ||
*/ | ||
public VaultKms(KmsDefinition config) { | ||
if (isNull(config)) { | ||
throw new IllegalArgumentException("Null KmsConfig argument."); | ||
} | ||
if (isNull(config.getUri())) { | ||
throw new IllegalArgumentException("Required argument 'baseUri' is missing."); | ||
} | ||
if (isNull(config.getCredential())) { | ||
throw new IllegalArgumentException("Required argument 'token' is missing."); | ||
} | ||
this.config = config; | ||
this.client = HttpClient.newBuilder().build(); | ||
LOGGER.debug("Vault KMS created"); | ||
} | ||
|
||
/** | ||
* Return the key corresponding to the requested key reference. | ||
*/ | ||
@Override | ||
public SecretKey getKey(String keyReference) throws KmsException { | ||
|
||
URI uri = createKeyUri(config.getUri(), keyReference); | ||
|
||
// create request | ||
HttpRequest request = HttpRequest.newBuilder() | ||
.uri(uri) | ||
.header(VAULT_TOKEN_HEADER, config.getCredential()) | ||
.GET() | ||
.build(); | ||
|
||
// send request | ||
HttpResponse<String> rsp; | ||
try { | ||
rsp = client.send(request, BodyHandlers.ofString()); | ||
} catch (IOException | InterruptedException e) { | ||
throw new KmsException("Error requesting key.", e); | ||
} | ||
|
||
// check HTTP status code | ||
if (rsp.statusCode() != 200) { | ||
LOGGER.error("Error requesting key from Vault: HTTP {}", rsp.statusCode()); | ||
throw new KmsException("Error accessing Vault instance: HTTP " + rsp.statusCode()); | ||
} | ||
|
||
// parse out key, decode and return: | ||
String key = getKey(rsp.body(), keyReference); | ||
LOGGER.debug("Vault KMS returned key"); | ||
return EncUtils.base64Decode(key); | ||
} | ||
|
||
public static URI createKeyUri(URI baseUri, String keyRef) | ||
throws KmsException { | ||
String uriStr; | ||
try { | ||
uriStr = String.format("%s/%s", | ||
baseUri.toString(), | ||
URLEncoder.encode(keyRef, StandardCharsets.UTF_8.toString())); | ||
} catch (UnsupportedEncodingException e) { | ||
throw new KmsException("Error encoding URL", e); | ||
} | ||
try { | ||
return new URI(uriStr); | ||
} catch (URISyntaxException e) { | ||
throw new KmsException("Error creating Vault URL", e); | ||
} | ||
} | ||
|
||
/** | ||
* Utility to process the JSON response to a key request and return the key | ||
* payload. | ||
* | ||
* @param jsonStr a JSON response document | ||
* @param keyReference the reference of the key to return. | ||
* @return a String in base64 encoding | ||
* @throws KmsException if any error occurs or the requested key is not | ||
* returned. | ||
*/ | ||
private String getKey(String jsonStr, String keyReference) throws KmsException { | ||
JsonNode jsonObj; | ||
try { | ||
jsonObj = OBJ_MAPPER.readTree(jsonStr); | ||
} catch (JsonProcessingException e) { | ||
throw new KmsException("Error processing KMS response", e); | ||
} | ||
String path = String.format(KEY_PATH, keyReference); | ||
JsonNode keyNode = jsonObj.at(path); | ||
if (keyNode != null) { | ||
String key = keyNode.asText(); | ||
if (key != null) { | ||
return key; | ||
} | ||
} | ||
// key not found: | ||
throw new KmsException("Key " + keyReference + " not found"); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
kms-vault/src/main/java/io/strimzi/kafka/topicenc/kms/vault/VaultKmsFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright Strimzi authors. | ||
* License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
*/ | ||
package io.strimzi.kafka.topicenc.kms.vault; | ||
|
||
import io.strimzi.kafka.topicenc.kms.KeyMgtSystem; | ||
import io.strimzi.kafka.topicenc.kms.KmsDefinition; | ||
import io.strimzi.kafka.topicenc.kms.KmsException; | ||
import io.strimzi.kafka.topicenc.kms.KmsFactory; | ||
|
||
/** | ||
* A KmsFactory, made available over the Java SPI, for creating instance of | ||
* VaultKms. | ||
*/ | ||
public class VaultKmsFactory implements KmsFactory { | ||
|
||
@Override | ||
public KeyMgtSystem createKms(KmsDefinition kmsDef) throws KmsException { | ||
return new VaultKms(kmsDef); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return VaultKmsFactory.class.getName(); | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
kms-vault/src/main/resources/META-INF/services/io.strimzi.kafka.topicenc.kms.KmsFactory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
io.strimzi.kafka.topicenc.kms.vault.VaultKmsFactory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters