You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2022/08/26 16:09:37 UTC
[knox] branch master updated: KNOX-2792 - new REST API endpoint to set Authorization/Bearer header in the response using an environment variable (#627)
This is an automated email from the ASF dual-hosted git repository.
smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new b7f9f2149 KNOX-2792 - new REST API endpoint to set Authorization/Bearer header in the response using an environment variable (#627)
b7f9f2149 is described below
commit b7f9f2149333460f4e870ccc1ed23717d4ef0ad5
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Fri Aug 26 18:09:32 2022 +0200
KNOX-2792 - new REST API endpoint to set Authorization/Bearer header in the response using an environment variable (#627)
---
gateway-service-auth/pom.xml | 5 +
.../gateway/service/auth/AuthBearerResource.java | 76 +++++++++++++++
.../service/auth/AuthBearerResourceTest.java | 102 +++++++++++++++++++++
pom.xml | 7 ++
4 files changed, 190 insertions(+)
diff --git a/gateway-service-auth/pom.xml b/gateway-service-auth/pom.xml
index 0a4615d4d..b68757175 100644
--- a/gateway-service-auth/pom.xml
+++ b/gateway-service-auth/pom.xml
@@ -55,6 +55,11 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>uk.org.webcompere</groupId>
+ <artifactId>system-stubs-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AuthBearerResource.java b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AuthBearerResource.java
new file mode 100644
index 000000000..4b3d1fcda
--- /dev/null
+++ b/gateway-service-auth/src/main/java/org/apache/knox/gateway/service/auth/AuthBearerResource.java
@@ -0,0 +1,76 @@
+/*
+ * 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.knox.gateway.service.auth;
+
+import static javax.ws.rs.core.Response.ok;
+
+import java.util.Locale;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+/**
+ * The service populates HTTP "Authorization" header with the Bearer Token,
+ * obtained from an environment variable.
+ * <p>
+ * This implementation assumes that the token is not rotated as it never gets
+ * exposed to the end-user. Consider alternative ways of obtaining tokens(e.g.
+ * from files) and implement caching/refreshing mechanism if token rotation is
+ * required.
+ */
+@Path(AuthBearerResource.RESOURCE_PATH)
+public class AuthBearerResource {
+ static final String RESOURCE_PATH = "auth/api/v1/bearer";
+ static final String BEARER_AUTH_TOKEN_ENV_CONFIG = "auth.bearer.token.env";
+ static final String DEFAULT_BEARER_AUTH_TOKEN_ENV = "BEARER_AUTH_TOKEN";
+ static final String HEADER_FORMAT = "Bearer %s";
+
+ private String token;
+
+ @Context
+ HttpServletResponse response;
+
+ @Context
+ ServletContext context;
+
+ @PostConstruct
+ public void init() throws ServletException {
+ String bearerTokenEnvVariableName = context.getInitParameter(BEARER_AUTH_TOKEN_ENV_CONFIG);
+ if (bearerTokenEnvVariableName == null) {
+ bearerTokenEnvVariableName = DEFAULT_BEARER_AUTH_TOKEN_ENV;
+ }
+
+ token = System.getenv(bearerTokenEnvVariableName);
+ if (token == null) {
+ throw new ServletException(String.format(Locale.ROOT, "Token environment variable '%s' is not set", bearerTokenEnvVariableName));
+ }
+ }
+
+ @GET
+ public Response doGet() {
+ response.addHeader(HttpHeaders.AUTHORIZATION, String.format(Locale.ROOT, HEADER_FORMAT, token));
+ return ok().build();
+ }
+}
diff --git a/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/AuthBearerResourceTest.java b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/AuthBearerResourceTest.java
new file mode 100644
index 000000000..5ffa311b0
--- /dev/null
+++ b/gateway-service-auth/src/test/java/org/apache/knox/gateway/service/auth/AuthBearerResourceTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.knox.gateway.service.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+
+import org.easymock.EasyMock;
+import org.junit.Rule;
+import org.junit.Test;
+
+import uk.org.webcompere.systemstubs.rules.EnvironmentVariablesRule;
+
+public class AuthBearerResourceTest {
+
+ @Rule
+ public EnvironmentVariablesRule environmentVariablesRule = new EnvironmentVariablesRule();
+
+ private static final String CUSTOM_TOKEN_ENV_VARIABLE = "MY_BEARER_TOKEN_ENV";
+ private static final String TOKEN = "TestBearerToken";
+
+ private ServletContext context;
+ private HttpServletResponse response;
+
+ private void configureCommonExpectations(String bearerTokenEnvVariableName, boolean expectHeader) {
+ context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(context.getInitParameter(AuthBearerResource.BEARER_AUTH_TOKEN_ENV_CONFIG)).andReturn(bearerTokenEnvVariableName).anyTimes();
+ response = EasyMock.createNiceMock(HttpServletResponse.class);
+ if (expectHeader) {
+ response.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + TOKEN);
+ EasyMock.expectLastCall();
+ }
+ EasyMock.replay(context, response);
+ }
+
+ @Test
+ public void testBearerTokenWithDefaultEnvVariableName() throws Exception {
+ testAuthBearerResource(null, true);
+ }
+
+ @Test
+ public void testBearerTokenWithCustomEnvVariableName() throws Exception {
+ testAuthBearerResource(CUSTOM_TOKEN_ENV_VARIABLE, true);
+ }
+
+ @Test
+ public void testNoBearerTokenWithDefaultEnvVariableName() throws Exception {
+ testAuthBearerResource(null, false);
+ }
+
+ @Test
+ public void testNoBearerTokenWithCustomEnvVariableName() throws Exception {
+ testAuthBearerResource(CUSTOM_TOKEN_ENV_VARIABLE, false);
+ }
+
+ private void testAuthBearerResource(String envVariableName, boolean setEnv) {
+ final String expectedEnvVariableName = envVariableName == null ? AuthBearerResource.DEFAULT_BEARER_AUTH_TOKEN_ENV : envVariableName;
+ boolean exceptionThrown = false;
+ try {
+ if (setEnv) {
+ environmentVariablesRule.set(expectedEnvVariableName, TOKEN);
+ }
+ configureCommonExpectations(envVariableName, setEnv);
+ final AuthBearerResource authBearerResource = new AuthBearerResource();
+ authBearerResource.context = context;
+ authBearerResource.response = response;
+ authBearerResource.init();
+ authBearerResource.doGet();
+ EasyMock.verify(response);
+ } catch (ServletException e) {
+ exceptionThrown = true;
+ assertEquals("Token environment variable '" + expectedEnvVariableName + "' is not set", e.getMessage());
+ }
+ if (setEnv) {
+ assertFalse(exceptionThrown);
+ } else {
+ assertTrue(exceptionThrown);
+ }
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index a8eaa4c57..fe6e4f85a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -266,6 +266,7 @@
<spring-vault.version>2.3.2</spring-vault.version>
<stax-ex.version>1.8.3</stax-ex.version>
<stax2-api.version>4.2.1</stax2-api.version>
+ <system-stubs-junit4.version>1.1.0</system-stubs-junit4.version>
<swagger-annotations.version>1.6.2</swagger-annotations.version>
<swagger-maven-plugin.version>3.1.7</swagger-maven-plugin.version>
<taglibs-standard.version>1.2.5</taglibs-standard.version>
@@ -2521,6 +2522,12 @@
<artifactId>hsqldb</artifactId>
<version>${hsql.db.version}</version>
</dependency>
+ <dependency>
+ <groupId>uk.org.webcompere</groupId>
+ <artifactId>system-stubs-junit4</artifactId>
+ <version>${system-stubs-junit4.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>