Skip to content

Commit

Permalink
Fixes #332 - Rework Azure Key Vault simulator to host just one KeyVau…
Browse files Browse the repository at this point in the history
…lt (#333)
  • Loading branch information
mnriem authored Jan 18, 2024
1 parent 036f42b commit 28e0f91
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 46 deletions.
48 changes: 48 additions & 0 deletions azure-keyvault/src/main/java/keyvault/IndexHtmlResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package keyvault;

import jakarta.inject.Singleton;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* Expose the /index.html resource.
*
* @author Manfred Riem ([email protected])
*/
@Path("")
@Singleton
public class IndexHtmlResource {

/**
* Constructor.
*/
public IndexHtmlResource() {
}

/**
* /index.html.
*
* @param request the HTTP servlet request.
* @return ""
*/
@Path(value = "")
@GET
@Produces(value = "text/html")
public StreamingOutput indexHtml(@Context HttpServletRequest request) {
return new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException, WebApplicationException {
InputStream inputStream = request.getServletContext().getResourceAsStream("/index.html");
inputStream.transferTo(output);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
*
* @author Manfred Riem ([email protected])
*/
@ApplicationPath("api")
@ApplicationPath("")
public class KeyVaultApplication extends Application {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@
import java.nio.file.Files;

/**
* Certificate download endpoint.
* Keystore download endpoint.
*
* @author Manfred Riem ([email protected])
*/
@Path("certificate")
@Path("keystore")
@Singleton
public class CertificateResource {
public class KeystoreResource {

/**
* Constructor.
*/
public CertificateResource() {
public KeystoreResource() {
}

/**
* Download the certificate
* Download the keystore
*
* @return the certificate.
* @return the keystore.
*/
@Path("")
@GET
public byte[] download() {
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
try {
java.nio.file.Path certificatePath = new File("/usr/local/tomcat/conf/certs/keystore").toPath();
java.nio.file.Path certificatePath = new File("/home/piranha/certs/keystore").toPath();
Files.copy(certificatePath, byteOutput);
} catch(IOException ioe) {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@
import java.util.Map;

/**
* REST API for Azure KeyVault.
* REST API for Azure KeyVault Secrets.
*
* <p>
* Reworked as the Azure SDK for .NET does validation on the secret id and as
* a consequence we cannot host multiple key vaults on the same base URL. See
* https://github.com/Azure/azure-sdk-for-net/blob/4abfa9feb47a6422ba627ca6517ed3e4014c67f9/sdk/keyvault/Azure.Security.KeyVault.Shared/src/KeyVaultIdentifier.cs#L54
* </p>
*
* @author Manfred Riem ([email protected])
*/
@Path("keyvault")
@Path("secrets")
@Singleton
public class KeyVaultResource {
public class SecretResource {

/**
* Stores the secrets.
*/
private Map<String, Map<String, SecretBundle>> secrets = new HashMap<>();
private final Map<String, SecretBundle> secrets = new HashMap<>();

/**
* Get the secret.
Expand All @@ -38,16 +44,14 @@ public class KeyVaultResource {
* https://learn.microsoft.com/en-us/rest/api/keyvault/secrets/get-secret/get-secret?tabs=HTTP
* </p>
*
* @param keyVault the key vault.
* @param secretName the secret name.
* @return the secret value.
*/
@Path("{name}/secrets/{secretName}")
@Path("{secretName}")
@GET
public Response getSecret(
@PathParam("name") String keyVault,
@PathParam("secretName") String secretName) {
return getSecretWithVersion(keyVault, secretName, null);
return getSecretWithVersion(secretName, null);
}

/**
Expand All @@ -58,23 +62,17 @@ public Response getSecret(
* https://learn.microsoft.com/en-us/rest/api/keyvault/secrets/get-secret/get-secret?tabs=HTTP
* </p>
*
* @param keyVault the key vault.
* @param secretName the secret name.
* @param secretVersion the secret version.
* @return the secret value.
*/
@Path("{name}/secrets/{secretName}/{secretVersion}")
@Path("{secretName}/{secretVersion}")
@GET
public Response getSecretWithVersion(
@PathParam("name") String keyVault,
@PathParam("secretName") String secretName,
@PathParam("secretVersion") String secretVersion) {

SecretBundle secret = null;
Map<String, SecretBundle> secretsMap = secrets.get(keyVault);
if (secretsMap != null) {
secret = secretsMap.get(secretName);
}
SecretBundle secret = secrets.get(secretName);
return Response.ok(secret).header("Connection", "close").build();
}

Expand All @@ -86,16 +84,14 @@ public Response getSecretWithVersion(
* https://learn.microsoft.com/en-us/rest/api/keyvault/secrets/set-secret/set-secret?tabs=HTTP
* </p>
*
* @param keyVault the key vault.
* @param secretName the secret name.
* @param inputStream the input stream.
* @param contentLength the content length.
* @return the response.
*/
@Path("{name}/secrets/{secretName}")
@Path("{secretName}")
@PUT
public Response setSecret(
@PathParam("name") String keyVault,
@PathParam("secretName") String secretName,
@HeaderParam("Content-Length") Integer contentLength,
InputStream inputStream) {
Expand Down Expand Up @@ -125,16 +121,10 @@ public Response setSecret(
}

if (secret.getId() == null) {
secret.setId(getBaseUrl() + "/keyvault/" + keyVault + "/secrets/" + secretName + "/1");
}

Map<String, SecretBundle> secretsMap = secrets.get(keyVault);
if (secretsMap == null) {
secretsMap = new HashMap<>();
secrets.put(keyVault, secretsMap);
secret.setId(getBaseUrl() + "/secrets/" + secretName + "/1");
}

secretsMap.put(secretName, secret);
secrets.put(secretName, secret);
return Response.ok(secret).header("Connection", "close").build();
}

Expand Down
2 changes: 1 addition & 1 deletion azure-keyvault/src/main/webapp/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ <h1>Azure Key Vault simulator</h1>
</p>
<h2>Java guidance</h2>
<ol>
<li>Download the certificate <a href="api/certificate">here</a></li>
<li>Download the Java keystore <a href="keystore">here</a></li>
</ol>
</body>
</html>
19 changes: 10 additions & 9 deletions azure-keyvault/src/test/java/keyvault/KeyVaultIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -18,23 +17,25 @@
*/
public class KeyVaultIT {

/**
* Stores the credential.
*/
private TokenCredential credential;

public KeyVaultIT() {
}

/**
* Setup the credential.
*/
@BeforeEach
public void setUp() {
credential = new BasicAuthenticationCredential("username", "password");
}

@AfterEach
public void tearDown() {
}

/**
* Test setting and then getting a secret.
*/
@Test
public void testGetSecret() {
String keyVaultUri = "https://localhost:8200/api/keyvault/myKeyvault";
String keyVaultUri = "https://localhost:8200";

SecretClient keyClient = new SecretClientBuilder()
.vaultUrl(keyVaultUri)
Expand Down
2 changes: 1 addition & 1 deletion azure-keyvault/src/test/java/keyvault/PingResourceIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PingResourceIT {
@Test
void testPing() throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(new URI("http://localhost:8100/api/ping")).build();
HttpRequest request = HttpRequest.newBuilder(new URI("http://localhost:8100/ping")).build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
assertEquals("OK", response.body());
}
Expand Down

0 comments on commit 28e0f91

Please sign in to comment.