Skip to content

Commit

Permalink
chore: AT-TLS context configuration tests (#3236)
Browse files Browse the repository at this point in the history
---------

Signed-off-by: Pablo Hernán Carle <[email protected]>
Co-authored-by: Pablo Hernán Carle <[email protected]>
  • Loading branch information
pablocarle and Pablo Hernán Carle authored Dec 13, 2023
1 parent 2aac3b6 commit ce012ca
Show file tree
Hide file tree
Showing 14 changed files with 413 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,5 @@ onboarding-enabler-micronaut/out/
onboarding-enabler-nodejs-sample-app/tools/

file/

zowe-cli-id-federation-plugin/*.jcl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.ContextConfiguration;
import org.zowe.apiml.apicatalog.ApiCatalogApplication;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(
classes = ApiCatalogApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@ContextConfiguration
public abstract class ApiCatalogFunctionalTest {

Expand All @@ -33,6 +37,10 @@ void setUp() {
}

protected String getCatalogUriWithPath(String path) {
return String.format("https://%s:%d", hostname, port) + path;
return getCatalogUriWithPath("https", path);
}

protected String getCatalogUriWithPath(String scheme, String path) {
return String.format("%s://%s:%d/%s", scheme, hostname, port, path);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

package org.zowe.apiml.apicatalog.functional;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.test.context.TestPropertySource;

import javax.net.ssl.SSLException;

import static io.restassured.RestAssured.given;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.fail;

@TestPropertySource(
properties = {
"server.attls.enabled=true",
"server.ssl.enabled=false"
}
)
public class AttlsConfigTest extends ApiCatalogFunctionalTest {

@Nested
class GivenAttlsModeEnabled {

@Nested
class WhenContextLoads {

@Test
void requestFailsWithHttps() {
try {
given()
.log().all()
.when()
.get(getCatalogUriWithPath("containers"))
.then()
.log().all()
.statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
fail("Expected an SSL failure");
} catch (Exception e) {
assertInstanceOf(SSLException.class, e);
}
}

@Test
void requestFailsWithAttlsContextReasonWithHttp() {
given()
.log().all()
.when()
.get(getCatalogUriWithPath("http", "apicatalog/api/v1/containers"))
.then()
.log().all()
.statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR)
.body(containsString("Connection is not secure."))
.body(containsString("AttlsContext.getStatConn"));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
} else {
AttlsErrorHandler.handleError(response, "Inbound AT-TLS context is not initialized or connection is not secure." );
}
} catch (ContextIsNotInitializedException | UnknownEnumValueException | IoctlCallException e) {
} catch (ContextIsNotInitializedException | UnknownEnumValueException | IoctlCallException | UnsatisfiedLinkError e) {
logger.error("Can't read from AT-TLS context", e);
AttlsErrorHandler.handleError(response, "Connection is not secure. " + e.getMessage());
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package org.zowe.apiml.caching;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
Expand All @@ -28,15 +27,13 @@
@EnableApiDiscovery
@EnableRetry
@EnableApimlLogger
@Slf4j
public class CachingService implements ApplicationListener<ApplicationReadyEvent> {

public static void main(String[] args) {
SpringApplication app = new SpringApplication(CachingService.class);
app.setLogStartupInfo(false);

app.run(args);

}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

package org.zowe.apiml.caching.config;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.zowe.apiml.caching.CachingService;
import org.zowe.apiml.util.config.SslContext;

import javax.net.ssl.SSLException;

import static io.restassured.RestAssured.given;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.fail;

@SpringBootTest(
classes = CachingService.class,
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@ActiveProfiles("AttlsConfigTestCachingService")
@TestPropertySource(
properties = {
"server.attls.enabled=true",
"server.ssl.enabled=false"
}
)
@TestInstance(Lifecycle.PER_CLASS)
public class AttlsConfigTest {

@Value("${apiml.service.hostname:localhost}")
String hostname;
@LocalServerPort
int port;


@Nested
class GivenAttlsModeEnabled {

private String getUri(String scheme, String endpoint) {
return String.format("%s://%s:%d/%s/%s", scheme, hostname, port, "api/v1", endpoint);
}

@Nested
class WhenContextLoads {

@Test
void requestFailsWithHttps() {
try {
given()
.config(SslContext.clientCertUnknownUser)
.header("Content-type", "application/json")
.get(getUri("https", "cache"))
.then()
.statusCode(HttpStatus.FORBIDDEN.value());
fail("");
} catch (Exception e) {
assertInstanceOf(SSLException.class, e);
}
}

@Test
void requestFailsWithAttlsReasonWithHttp() {
given()
.config(SslContext.clientCertUnknownUser)
.header("Content-type", "application/json")
.get(getUri("http", "cache"))
.then()
.statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
.body(containsString("Connection is not secure."))
.body(containsString("AttlsContext.getStatConn"));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.zowe.apiml.caching.model.KeyValue;
import org.zowe.apiml.util.config.SslContext;
Expand All @@ -23,7 +23,7 @@
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.is;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class InMemoryFunctionalTest {

@Value("${server.ssl.keyPassword}")
Expand Down
4 changes: 2 additions & 2 deletions config/zowe-api-dev/alternative_start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ _BPX_JOBNAME=${ZOWE_PREFIX}${DISCOVERY_CODE} java -Xms32m -Xmx256m ${QUICK_START
-Dapiml.security.ssl.nonStrictVerifySslCertificatesOfServices=${NONSTRICT_VERIFY_CERTIFICATES:-false} \
-Dserver.ssl.enabled=${APIML_SSL_ENABLED:-true} \
-Dserver.ssl.keyStore="${KEYSTORE}" \
-Dserver.ssl.keyStoreType="${KEYSTORE_TYPE}" \
-Dserver.ssl.keyStoreType="${KEYSTORE_TYPE:-PKCS12}" \
-Dserver.ssl.keyStorePassword="${KEYSTORE_PASSWORD}" \
-Dserver.ssl.keyAlias="${KEY_ALIAS}" \
-Dserver.ssl.keyPassword="${KEYSTORE_PASSWORD}" \
-Dserver.ssl.trustStore="${TRUSTSTORE}" \
-Dserver.ssl.trustStoreType="${KEYSTORE_TYPE}" \
-Dserver.ssl.trustStoreType="${KEYSTORE_TYPE:-PKCS12}" \
-Dserver.ssl.trustStorePassword="${KEYSTORE_PASSWORD}" \
-Djava.protocol.handler.pkgs=com.ibm.crypto.provider \
-Dloader.path=${COMMON_LIB} \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*/

package org.zowe.apiml.discovery.config;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.zowe.apiml.discovery.functional.DiscoveryFunctionalTest;

import java.net.ConnectException;

import static io.restassured.RestAssured.given;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.fail;

@TestPropertySource(
properties = {
"server.attls.enabled=true",
"server.ssl.enabled=false"
}
)
@TestInstance(Lifecycle.PER_CLASS)
@ActiveProfiles("attls")
class AttlsConfigTest extends DiscoveryFunctionalTest {

private String protocol = "http";

@Override
protected String getProtocol() {
return protocol;
}

@Nested
class GivenAttlsModeEnabledAndHttps {

@BeforeEach
void setUp() {
protocol = "https";
}

@Test
void whenContextLoads_RequestFailsWithHttps() {
try {
given()
.log().all()
.when()
.get(getDiscoveryUriWithPath("/application/info"))
.then()
.log().all()
.statusCode(is(HttpStatus.SC_INTERNAL_SERVER_ERROR));
fail("Expected SSL failure");
} catch (Exception e) {
assertInstanceOf(ConnectException.class, e);
}
}
}

@Nested
class GivenAttlsModeEnabledAndHttp {

@BeforeEach
void setUp() {
protocol = "http";
}

@Test
void whenContextLoads_RequestFailsWithAttlsContextReason() {
given()
.log().all()
.when()
.get(getDiscoveryUriWithPath("/eureka/apps"))
.then()
.log().all()
.statusCode(is(HttpStatus.SC_INTERNAL_SERVER_ERROR))
.body(containsString("Connection is not secure."))
.body(containsString("AttlsContext.getStatConn"));
}
}
}
Loading

0 comments on commit ce012ca

Please sign in to comment.