Skip to content

Commit 1adbc3d

Browse files
committed
Use mock oauth2 server in Azure KMS integration tests
Signed-off-by: Robert Young <[email protected]>
1 parent 4684600 commit 1adbc3d

File tree

4 files changed

+110
-45
lines changed

4 files changed

+110
-45
lines changed

.github/renovate.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@
6767
},
6868
{
6969
"customType": "regex",
70-
"fileMatch": ["kroxylicious-integration-tests/src/test/java/io/kroxylicious/proxy/filter/oauthbearer/OauthBearerValidationIT.java"],
70+
"fileMatch": [
71+
"kroxylicious-integration-tests/src/test/java/io/kroxylicious/proxy/filter/oauthbearer/OauthBearerValidationIT.java",
72+
"kroxylicious-kms-providers/kroxylicious-kms-provider-azure-key-vault-kms-test-support/src/main/java/io/kroxylicious/kms/provider/azure/kms/OauthServerContainer.java"
73+
],
7174
"matchStrings": [
7275
"DockerImageName\\.parse\\(\"(?<depName>ghcr.io/navikt/mock-oauth2-server):(?<currentValue>\\d+\\.\\d+.\\d+)\"\\)"
7376
],

kroxylicious-kms-providers/kroxylicious-kms-provider-azure-key-vault-kms-test-support/pom.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@
5353
<groupId>org.testcontainers</groupId>
5454
<artifactId>testcontainers</artifactId>
5555
</dependency>
56-
<dependency>
57-
<groupId>org.wiremock</groupId>
58-
<artifactId>wiremock</artifactId>
59-
<scope>compile</scope>
60-
</dependency>
6156
<dependency>
6257
<groupId>com.github.nagyesta.lowkey-vault</groupId>
6358
<artifactId>lowkey-vault-testcontainers</artifactId>

kroxylicious-kms-providers/kroxylicious-kms-provider-azure-key-vault-kms-test-support/src/main/java/io/kroxylicious/kms/provider/azure/kms/AzureKeyVaultKmsTestKmsFacade.java

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
import com.github.nagyesta.lowkeyvault.http.AuthorityOverrideFunction;
3636
import com.github.nagyesta.lowkeyvault.http.management.LowkeyVaultException;
3737
import com.github.nagyesta.lowkeyvault.testcontainers.LowkeyVaultContainer;
38-
import com.github.tomakehurst.wiremock.WireMockServer;
39-
import com.github.tomakehurst.wiremock.client.WireMock;
4038

4139
import io.kroxylicious.kms.provider.azure.AzureKeyVaultEdek;
4240
import io.kroxylicious.kms.provider.azure.AzureKeyVaultKmsService;
@@ -50,35 +48,21 @@
5048
import io.kroxylicious.proxy.config.secret.InlinePassword;
5149
import io.kroxylicious.proxy.config.tls.Tls;
5250
import io.kroxylicious.proxy.config.tls.TrustStore;
53-
import io.kroxylicious.testing.kafka.common.KeytoolCertificateGenerator;
5451

5552
import edu.umd.cs.findbugs.annotations.Nullable;
5653

5754
import static com.github.nagyesta.lowkeyvault.testcontainers.LowkeyVaultContainerBuilder.lowkeyVault;
58-
import static com.github.tomakehurst.wiremock.client.WireMock.post;
59-
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
6055

6156
@SuppressWarnings("java:S112")
6257
public class AzureKeyVaultKmsTestKmsFacade implements TestKmsFacade<AzureKeyVaultConfig, WrappingKey, AzureKeyVaultEdek> {
6358

64-
public static final String MOCK_AUTH_RESPONSE = """
65-
{
66-
"access_token": "aaa",
67-
"token_type": "Bearer",
68-
"expires_in": 3599,
69-
"scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
70-
"refresh_token": "bbb",
71-
"id_token": "ccc"
72-
}
73-
""";
7459
public static final String TENANT_ID = "identity";
7560
public static final String KEY_VAULT_NAME = "default";
7661

77-
private final KeytoolCertificateGenerator entraCertGen = entraCerts();
7862
@Nullable
7963
private LowkeyVaultContainer kms;
8064
@Nullable
81-
private WireMockServer entraMock;
65+
private OauthServerContainer oauthServer;
8266

8367
protected AzureKeyVaultKmsTestKmsFacade() {
8468
}
@@ -89,36 +73,26 @@ public boolean isAvailable() {
8973
}
9074

9175
public void startKms() {
92-
this.kms = startVault();
93-
this.entraMock = new WireMockServer(wireMockConfig().dynamicPort().keystorePath(entraCertGen.getKeyStoreLocation()).keystorePassword(entraCertGen.getPassword()));
94-
entraMock.start();
95-
entraMock.stubFor(post("/" + TENANT_ID + "/oauth2/v2.0/token")
96-
.willReturn(WireMock.aResponse().withStatus(200).withHeader("Content-type", "application/json").withBody(MOCK_AUTH_RESPONSE)));
97-
entraMock.start();
76+
this.kms = startKeyVault();
77+
this.oauthServer = startMockOauthServer();
9878
}
9979

100-
private static KeytoolCertificateGenerator entraCerts() {
101-
try {
102-
KeytoolCertificateGenerator entraCertGen = new KeytoolCertificateGenerator();
103-
entraCertGen.generateSelfSignedCertificateEntry("[email protected]", "example.com", "Engineering", "kroxylicious.io", null, null, "NZ");
104-
entraCertGen.generateTrustStore(entraCertGen.getCertFilePath(), "website");
105-
return entraCertGen;
106-
}
107-
catch (Exception e) {
108-
throw new TestKmsFacadeException(e);
109-
}
80+
private static OauthServerContainer startMockOauthServer() {
81+
OauthServerContainer oauthServerContainer = new OauthServerContainer();
82+
oauthServerContainer.start();
83+
return oauthServerContainer;
11084
}
11185

11286
public void stopKms() {
11387
if (kms != null) {
11488
kms.stop();
11589
}
116-
if (entraMock != null) {
117-
entraMock.stop();
90+
if (oauthServer != null) {
91+
oauthServer.stop();
11892
}
11993
}
12094

121-
public LowkeyVaultContainer startVault() {
95+
public static LowkeyVaultContainer startKeyVault() {
12296
String image = "nagyesta/lowkey-vault:4.0.0";
12397
final DockerImageName imageName = DockerImageName.parse("mirror.gcr.io/" + image)
12498
.asCompatibleSubstituteFor(DockerImageName.parse(image));
@@ -141,7 +115,7 @@ public AzureKeyVaultConfig getKmsServiceConfig() {
141115
if (kms == null) {
142116
throw new IllegalStateException("kms is not initialized");
143117
}
144-
if (entraMock == null) {
118+
if (oauthServer == null) {
145119
throw new IllegalStateException("entraMock is not initialized");
146120
}
147121
URI defaultVaultBaseUrl = URI.create(kms.getDefaultVaultBaseUrl());
@@ -153,10 +127,12 @@ public AzureKeyVaultConfig getKmsServiceConfig() {
153127
}
154128
TrustStore vaultTrust = new TrustStore(tempFile.getAbsolutePath(), new InlinePassword(kms.getDefaultKeyStorePassword()), defaultKeyStore.getType());
155129
Tls vaultTls = new Tls(null, vaultTrust, null, null);
156-
TrustStore entraTrust = new TrustStore(entraCertGen.getTrustStoreLocation(), new InlinePassword(entraCertGen.getPassword()), defaultKeyStore.getType());
130+
TrustStore entraTrust = new TrustStore(oauthServer.getTrustStoreLocation(), new InlinePassword(oauthServer.getTrustStorePassword()),
131+
oauthServer.getTrustStoreType());
157132
Tls entraTls = new Tls(null, entraTrust, null, null);
158133
return new AzureKeyVaultConfig(
159-
new EntraIdentityConfig(URI.create(entraMock.baseUrl()), TENANT_ID, new InlinePassword("abc"), new InlinePassword("def"), null, entraTls),
134+
new EntraIdentityConfig(oauthServer.getBaseUri(), TENANT_ID, new InlinePassword("abc"), new InlinePassword("def"), null,
135+
entraTls),
160136
KEY_VAULT_NAME, defaultVaultBaseUrl.getHost(), null, defaultVaultBaseUrl.getPort(), vaultTls);
161137
}
162138
catch (Exception e) {
@@ -257,4 +233,5 @@ private static HttpClient createHttpClient(String clientAuthority, String contai
257233
}
258234
}
259235
}
236+
260237
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright Kroxylicious Authors.
3+
*
4+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
7+
package io.kroxylicious.kms.provider.azure.kms;
8+
9+
import java.net.URI;
10+
import java.time.Duration;
11+
12+
import org.testcontainers.containers.GenericContainer;
13+
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
14+
import org.testcontainers.utility.DockerImageName;
15+
import org.testcontainers.utility.MountableFile;
16+
17+
import io.kroxylicious.kms.service.TestKmsFacadeException;
18+
import io.kroxylicious.testing.kafka.common.KeytoolCertificateGenerator;
19+
20+
class OauthServerContainer extends GenericContainer<OauthServerContainer> {
21+
22+
private static final DockerImageName DOCKER_IMAGE_NAME = DockerImageName.parse("ghcr.io/navikt/mock-oauth2-server:3.0.0");
23+
private static final String LOCALHOST = "localhost";
24+
private static final String CERT_FILE_MOUNT_PATH = "/etc/custom-certs";
25+
private final KeytoolCertificateGenerator certs;
26+
private static final int INTERNAL_PORT = 8080;
27+
28+
private static KeytoolCertificateGenerator entraCerts() {
29+
try {
30+
KeytoolCertificateGenerator entraCertGen = new KeytoolCertificateGenerator();
31+
entraCertGen.generateSelfSignedCertificateEntry("[email protected]", LOCALHOST, "Engineering", "kroxylicious.io", null, null, "NZ");
32+
entraCertGen.generateTrustStore(entraCertGen.getCertFilePath(), "website");
33+
return entraCertGen;
34+
}
35+
catch (Exception e) {
36+
throw new TestKmsFacadeException(e);
37+
}
38+
}
39+
40+
OauthServerContainer() {
41+
super(DOCKER_IMAGE_NAME);
42+
this.certs = entraCerts();
43+
LogMessageWaitStrategy strategy = new LogMessageWaitStrategy().withRegEx(".*started server on address.*");
44+
strategy.withStartupTimeout(Duration.ofSeconds(10));
45+
setWaitStrategy(strategy);
46+
withExposedPorts(INTERNAL_PORT);
47+
withEnv("SERVER_PORT", Integer.toString(INTERNAL_PORT));
48+
String config = """
49+
{
50+
"httpServer" : {
51+
"type" : "NettyWrapper",
52+
"ssl" : {
53+
"keyPassword" : "%s",
54+
"keystoreFile" : "%s",
55+
"keystoreType" : "%s",
56+
"keystorePassword" : "%s"
57+
}
58+
}
59+
}
60+
""".formatted(certs.getPassword(), CERT_FILE_MOUNT_PATH, certs.getKeyStoreType(), certs.getPassword());
61+
withEnv("JSON_CONFIG", config);
62+
withEnv("LOG_LEVEL", "DEBUG"); // required to for the startup message to be logged.
63+
withCopyFileToContainer(MountableFile.forHostPath(certs.getKeyStoreLocation()), CERT_FILE_MOUNT_PATH);
64+
}
65+
66+
@Override
67+
public void start() {
68+
super.start();
69+
}
70+
71+
public String getTrustStoreLocation() {
72+
return certs.getTrustStoreLocation();
73+
}
74+
75+
public String getTrustStorePassword() {
76+
return certs.getPassword();
77+
}
78+
79+
public String getTrustStoreType() {
80+
return certs.getTrustStoreType();
81+
}
82+
83+
public URI getBaseUri() {
84+
Integer mappedPort = getMappedPort(INTERNAL_PORT);
85+
if (mappedPort == null) {
86+
throw new IllegalStateException("oauth mock - mappedPort is null for " + INTERNAL_PORT);
87+
}
88+
return URI.create("https://" + LOCALHOST + ":" + mappedPort);
89+
}
90+
}

0 commit comments

Comments
 (0)