From 49239c5a52fc2d9c2ea3ce337fcd1b65fb9e4521 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Wed, 1 Jul 2026 00:14:25 +0100 Subject: [PATCH 1/8] chore: resolve merge conflicts from stash Signed-off-by: Chukwuemeka David --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 209c866..be6f8d2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ - package: mvn package clean: mvn clean - rm -f *.log *.err + rm -f *.log *.err \ No newline at end of file From 2f6cc2b7e612826c60b2ae106778f6cda2a01f6e Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Fri, 3 Jul 2026 19:06:03 +0100 Subject: [PATCH 2/8] Add API key authentication to ApiServer with unit tests Signed-off-by: Chukwuemeka David --- .../csl/dcoes/apis/tools/web/ApiServer.java | 39 +++++++++++++++++ .../apis/tools/web/ApiServerAuthTest.java | 43 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java diff --git a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java index ea058f7..d17b1b7 100755 --- a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java +++ b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java @@ -13,6 +13,7 @@ import jp.co.sony.csl.dcoes.apis.tools.web.api_handler.DealGeneration; import jp.co.sony.csl.dcoes.apis.tools.web.api_handler.ErrorGeneration; import jp.co.sony.csl.dcoes.apis.tools.web.api_handler.LogConfiguration; +import java.security.MessageDigest; /** * These Verticles provide various Web API for controlling APIS from the @@ -69,6 +70,7 @@ public class ApiServer extends AbstractVerticle { * @param startFuture {@inheritDoc} * @throws Exception {@inheritDoc} */ + @Override public void start(Promise startPromise) throws Exception { startHttpService_(resHttp -> { @@ -95,6 +97,28 @@ public void stop() throws Exception { log.trace("stopped : " + deploymentID()); } + + /** + * Starts authenticates request to our server. + * Gets providedKey from request and authenticates, by matching with our servers apiKey. + * + * @param req the request object hitting our server + * @param apiKey the configured apiKey from our server + */ + static Integer checkAuth(HttpServerRequest req, String apiKey) { + if (apiKey == null || apiKey.isEmpty()) { + return 500; + } + String providedKey = req.getHeader("X-API-Key"); + if (providedKey == null || !MessageDigest.isEqual(apiKey.getBytes(), providedKey.getBytes())) { + return 401; + } + return null; // auth passed + } + + + + //// /** @@ -110,12 +134,27 @@ public void stop() throws Exception { */ private void startHttpService_(Handler> completionHandler) { Integer port = VertxConfig.config.getInteger(DEFAULT_PORT, "apiServer", "port"); + // fetches the config api-key + String apiKey = VertxConfig.apiServerApiKey(); + + vertx.createHttpServer().requestHandler(req -> { req.exceptionHandler(t -> { log.error("exceptionHandler", t); req.response().setChunked(true).putHeader("content-type", "text/plain").setStatusCode(500) .end("exceptionHandler : " + t + '\n'); }); + + + // --- start auth check --- + Integer authFail = checkAuth(req, apiKey); + if (authFail != null) { + req.response().setStatusCode(authFail).end(authFail == 500 ? "server misconfigured\n" : "unauthorized\n"); + return; + } + // --- end auth check --- + + try { for (ApiHandler apiHandler : apiHandlers_) { if (apiHandler.canHandleRequest(req)) { diff --git a/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java new file mode 100644 index 0000000..d57583e --- /dev/null +++ b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java @@ -0,0 +1,43 @@ +package jp.co.sony.csl.dcoes.apis.tools.web; + +import io.vertx.core.http.HttpServerRequest; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + + +public class ApiServerAuthTest { + + @Test + public void nullApiKey_returns500() { + HttpServerRequest req = mock(HttpServerRequest.class); + assertEquals(Integer.valueOf(500), ApiServer.checkAuth(req, null)); + } + + @Test + public void emptyApiKey_returns500() { + HttpServerRequest req = mock(HttpServerRequest.class); + assertEquals(Integer.valueOf(500), ApiServer.checkAuth(req, "")); + } + + @Test + public void missingHeader_returns401() { + HttpServerRequest req = mock(HttpServerRequest.class); + when(req.getHeader("X-API-Key")).thenReturn(null); + assertEquals(Integer.valueOf(401), ApiServer.checkAuth(req, "secret")); + } + + @Test + public void wrongKey_returns401() { + HttpServerRequest req = mock(HttpServerRequest.class); + when(req.getHeader("X-API-Key")).thenReturn("wrong"); + assertEquals(Integer.valueOf(401), ApiServer.checkAuth(req, "secret")); + } + + @Test + public void correctKey_returnsNull() { + HttpServerRequest req = mock(HttpServerRequest.class); + when(req.getHeader("X-API-Key")).thenReturn("secret"); + assertNull(ApiServer.checkAuth(req, "secret")); + } +} \ No newline at end of file From a82fdd3e823524191d3cd3f58f3808e7b2652577 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Tue, 14 Jul 2026 19:36:37 +0100 Subject: [PATCH 3/8] style: added new line at the end of file Signed-off-by: Chukwuemeka David --- .../jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java index d57583e..3a3ba05 100644 --- a/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java +++ b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java @@ -40,4 +40,4 @@ public void correctKey_returnsNull() { when(req.getHeader("X-API-Key")).thenReturn("secret"); assertNull(ApiServer.checkAuth(req, "secret")); } -} \ No newline at end of file +} From 5bb304fa2d3ae0e2031de752e6f35714fb255f18 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Tue, 14 Jul 2026 19:53:30 +0100 Subject: [PATCH 4/8] refactor: replace wildcard imports with explicit named imports Signed-off-by: Chukwuemeka David --- .../co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java index 3a3ba05..43e238b 100644 --- a/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java +++ b/src/test/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServerAuthTest.java @@ -2,8 +2,10 @@ import io.vertx.core.http.HttpServerRequest; import org.junit.Test; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class ApiServerAuthTest { From 6633506197fa00d9c8e12f93b7aee0609dded641 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Mon, 20 Jul 2026 11:51:43 +0100 Subject: [PATCH 5/8] config: added api-key to api-server at [config.json] Signed-off-by: Chukwuemeka David --- exe/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exe/config.json b/exe/config.json index d229192..b956306 100644 --- a/exe/config.json +++ b/exe/config.json @@ -19,7 +19,8 @@ "port" : 43900 }, "apiServer" : { - "port" : 9999 + "port" : 9999, + "apiKey":"DEV_INTERNAL_API_KEY" }, "watchdog" : { From e9b625cec43c33b013fb99e956a9760b4b54b3f7 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Mon, 20 Jul 2026 12:04:32 +0100 Subject: [PATCH 6/8] config: added [sample env] Signed-off-by: Chukwuemeka David --- .env.sample | 6 ++++++ .gitignore | 3 +++ 2 files changed, 9 insertions(+) create mode 100644 .env.sample diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..09a4160 --- /dev/null +++ b/.env.sample @@ -0,0 +1,6 @@ +# ============================================================================== +# APIS_WEB APPLICATION CONFIGURATION (SAMPLE) +# Copy this file to '.env' and fill in your actual local configuration. +# ============================================================================== + +DEV_INTERNAL_API_KEY="replace-with-a-generated-secret" # openssl rand -hex 32 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3f127e4..85239d3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ build *.log.lck *.err *.err.lck +.env +.env.local +.env.*.local From 0b061ace071674bb96cd777c031643a0caa08b31 Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Mon, 20 Jul 2026 12:15:06 +0100 Subject: [PATCH 7/8] refactor(api-server): load API key from environment variable Signed-off-by: Chukwuemeka David --- .../jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java index d17b1b7..9a7d1e6 100755 --- a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java +++ b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java @@ -106,13 +106,21 @@ public void stop() throws Exception { * @param apiKey the configured apiKey from our server */ static Integer checkAuth(HttpServerRequest req, String apiKey) { + if (apiKey == null || apiKey.isEmpty()) { return 500; } + + if (apiKey.startsWith("DEV_INTERNAL")){ + apiKey = System.getenv("DEV_INTERNAL_API_KEY"); + } + String providedKey = req.getHeader("X-API-Key"); + if (providedKey == null || !MessageDigest.isEqual(apiKey.getBytes(), providedKey.getBytes())) { return 401; } + return null; // auth passed } From 34bf4bb5cf2ea794ea89bb00aa1883b56ece0bac Mon Sep 17 00:00:00 2001 From: Chukwuemeka David Date: Tue, 21 Jul 2026 09:00:25 +0100 Subject: [PATCH 8/8] fix: guard against NPE when DEV_INTERNAL_API_KEY unset Signed-off-by: Chukwuemeka David --- .../java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java index 9a7d1e6..7d87bcb 100755 --- a/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java +++ b/src/main/java/jp/co/sony/csl/dcoes/apis/tools/web/ApiServer.java @@ -113,6 +113,9 @@ static Integer checkAuth(HttpServerRequest req, String apiKey) { if (apiKey.startsWith("DEV_INTERNAL")){ apiKey = System.getenv("DEV_INTERNAL_API_KEY"); + if (apiKey == null || apiKey.isEmpty()) { + return 500; + } } String providedKey = req.getHeader("X-API-Key");