Skip to content

Commit

Permalink
chore: add request with http client for jwt from zosmf (#3281)
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 Jan 25, 2024
1 parent a3067b9 commit 7b23ae6
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,23 @@
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
import static io.restassured.http.ContentType.XML;
import static org.apache.http.HttpStatus.*;
import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.zowe.apiml.integration.zaas.ZaasTestUtil.*;
import static org.zowe.apiml.util.SecurityUtils.*;
import static org.zowe.apiml.integration.zaas.ZaasTestUtil.COOKIE;
import static org.zowe.apiml.integration.zaas.ZaasTestUtil.ZAAS_TICKET_URI;
import static org.zowe.apiml.util.SecurityUtils.USERNAME;
import static org.zowe.apiml.util.SecurityUtils.generateZoweJwtWithLtpa;
import static org.zowe.apiml.util.SecurityUtils.getConfiguredSslConfig;
import static org.zowe.apiml.util.SecurityUtils.getZosmfJwtToken;
import static org.zowe.apiml.util.SecurityUtils.getZosmfLtpaToken;
import static org.zowe.apiml.util.SecurityUtils.personalAccessToken;
import static org.zowe.apiml.util.SecurityUtils.validOktaAccessToken;

/**
* Verify integration of the API ML PassTicket support with the zOS provider of the PassTicket.
Expand Down Expand Up @@ -81,7 +90,7 @@ void givenValidZosmfToken() {

@Test
void givenValidZoweTokenWithLtpa() throws UnrecoverableKeyException, CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException {
String ltpaToken = getZosmfToken(LTPA_COOKIE);
String ltpaToken = getZosmfLtpaToken();
String zoweToken = generateZoweJwtWithLtpa(ltpaToken);

//@formatter:off
Expand Down
111 changes: 93 additions & 18 deletions integration-tests/src/test/java/org/zowe/apiml/util/SecurityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@
import io.restassured.response.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
Expand All @@ -47,17 +57,34 @@

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URI;
import java.security.*;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
Expand All @@ -69,7 +96,10 @@
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.zowe.apiml.util.requests.Endpoints.*;
import static org.zowe.apiml.util.requests.Endpoints.GENERATE_ACCESS_TOKEN;
import static org.zowe.apiml.util.requests.Endpoints.ROUTED_LOGIN;
import static org.zowe.apiml.util.requests.Endpoints.ROUTED_QUERY;
import static org.zowe.apiml.util.requests.Endpoints.ZOSMF_AUTH_ENDPOINT;

public class SecurityUtils {
public final static String GATEWAY_TOKEN_COOKIE_NAME = "apimlAuthenticationToken";
Expand Down Expand Up @@ -102,7 +132,6 @@ protected static String getUsername() {
return USERNAME;
}


//@formatter:off

public static String getGatewayUrl(String path) {
Expand Down Expand Up @@ -150,7 +179,38 @@ public static String gatewayToken(URI gatewayLoginEndpoint, String username, Str
}

public static String getZosmfJwtToken() {
return getZosmfToken("jwtToken");
return getZosmfTokenWebClient("jwtToken");
}

public static String getZosmfLtpaToken() {
return getZosmfTokenWebClient("LtpaToken2");
}

public static String getZosmfTokenWebClient(String cookie) {
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(getRelaxedSslContext()).build()) { // Can't think of a reason to test SSL connection between Integration test runner and z/OSMF
HttpClientContext context = HttpClientContext.create();
CookieStore cookieStore = new BasicCookieStore();
context.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);

HttpUriRequest request = new HttpPost(String.format("%s://%s:%d%s", zosmfScheme, zosmfHost, zosmfPort, ZOSMF_AUTH_ENDPOINT));
request.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
request.addHeader(HttpHeaders.AUTHORIZATION, String.format("Basic %s", java.util.Base64.getEncoder().encodeToString(String.format("%s:%s", USERNAME, PASSWORD).getBytes())));
request.addHeader("X-CSRF-ZOSMF-HEADER", "csrf");

CloseableHttpResponse response = httpClient.execute(request, context);
if (response.getStatusLine().getStatusCode() == 200) {
return cookieStore.getCookies()
.stream()
.filter(c -> cookie.equals(c.getName()))
.findFirst()
.map(c -> c.getValue())
.orElseThrow(() -> new RuntimeException("Cookie " + cookie + " not found in z/OSMF response"));
} else {
throw new RuntimeException("Request to z/OSMF failed with status code " + response.getStatusLine().getStatusCode() + ": " + response.getStatusLine().getReasonPhrase());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static String getZosmfToken(String cookie) {
Expand Down Expand Up @@ -370,22 +430,37 @@ public static void logoutOnGateway(String url, String jwtToken) {

public static SSLConfig getConfiguredSslConfig() {
TlsConfiguration tlsConfiguration = ConfigReader.environmentConfiguration().getTlsConfiguration();
SSLContext sslContext = getSslContext();
HostnameVerifier hostnameVerifier = tlsConfiguration.isNonStrictVerifySslCertificatesOfServices() ? new NoopHostnameVerifier() : SSLConnectionSocketFactory.getDefaultHostnameVerifier();
SSLSocketFactoryAdapter sslSocketFactory = new SSLSocketFactoryAdapter(new SSLConnectionSocketFactory(sslContext, hostnameVerifier));
return SSLConfig.sslConfig().with().sslSocketFactory(sslSocketFactory);
}

static SSLContext getRelaxedSslContext() {
final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
try {
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(
new File(tlsConfiguration.getKeyStore()),
tlsConfiguration.getKeyStorePassword(),
tlsConfiguration.getKeyPassword(),
(aliases, socket) -> tlsConfiguration.getKeyAlias())
.loadTrustMaterial(
new File(tlsConfiguration.getTrustStore()),
tlsConfiguration.getTrustStorePassword())
return SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
HostnameVerifier hostnameVerifier = tlsConfiguration.isNonStrictVerifySslCertificatesOfServices() ? new NoopHostnameVerifier() : SSLConnectionSocketFactory.getDefaultHostnameVerifier();
SSLSocketFactoryAdapter sslSocketFactory = new SSLSocketFactoryAdapter(new SSLConnectionSocketFactory(sslContext, hostnameVerifier));
return SSLConfig.sslConfig().with().sslSocketFactory(sslSocketFactory);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
throw new RuntimeException(e);
}
}

public static SSLContext getSslContext() {
try {
return SSLContexts.custom()
.loadKeyMaterial(
new File(tlsConfiguration.getKeyStore()),
tlsConfiguration.getKeyStorePassword(),
tlsConfiguration.getKeyPassword(),
(aliases, socket) -> tlsConfiguration.getKeyAlias())
.loadTrustMaterial(
new File(tlsConfiguration.getTrustStore()),
tlsConfiguration.getTrustStorePassword())
.build();
} catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException
| CertificateException | IOException e) {
| CertificateException | IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
Expand Down

0 comments on commit 7b23ae6

Please sign in to comment.