Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
package org.zowe.apiml.integration.authentication.providers;

import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.Cookie;
import io.restassured.specification.RequestSpecification;
import org.apache.http.message.BasicNameValuePair;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Nested;
Expand All @@ -30,8 +32,7 @@
import java.util.Optional;

import static io.restassured.RestAssured.given;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.*;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.core.Is.is;
Expand All @@ -43,11 +44,11 @@
class ZosmfLoginTest implements TestWithStartedInstances {

private final static boolean ZOS_TARGET = Boolean.parseBoolean(System.getProperty("environment.zos.target", "false"));
private final static String USERNAME = ConfigReader.environmentConfiguration().getCredentials().getClientUser();
private final static String ZOSMF_SERVICE_ID = ConfigReader.environmentConfiguration().getZosmfServiceConfiguration().getServiceId();
private static final String ZOSMF_CONTEXT_ROOT = ConfigReader.environmentConfiguration().getZosmfServiceConfiguration().getContextRoot();
private final static String ZOSMF_ENDPOINT_GW = "/" + ZOSMF_SERVICE_ID + "/api/v1/" + (StringUtils.hasText(ZOSMF_CONTEXT_ROOT) ? ZOSMF_CONTEXT_ROOT + "/" : "") + "restfiles/ds";
private final static String USERNAME = ConfigReader.environmentConfiguration().getCredentials().getClientUser();
private final static String ZOSMF_ENDPOINT_MOCK = "/" + ZOSMF_SERVICE_ID + "/api/zosmf/restfiles/ds";
private final static String ZOSMF_ENDPOINT_GW = "/" + ZOSMF_SERVICE_ID + "/api/v1/" + (StringUtils.hasText(ZOSMF_CONTEXT_ROOT) ? ZOSMF_CONTEXT_ROOT + "/" : "") + "restfiles/";
private final static String ZOSMF_ENDPOINT_MOCK = "/" + ZOSMF_SERVICE_ID + "/api/zosmf/restfiles/";

Check warning on line 51 in integration-tests/src/test/java/org/zowe/apiml/integration/authentication/providers/ZosmfLoginTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reorder the modifiers to comply with the Java Language Specification.

See more on https://sonarcloud.io/project/issues?id=zowe_api-layer&issues=AZ7UpbP2r4OGdoFC4-NI&open=AZ7UpbP2r4OGdoFC4-NI&pullRequest=4721
private final static String ZOSMF_ENDPOINT = ZOS_TARGET ? ZOSMF_ENDPOINT_GW : ZOSMF_ENDPOINT_MOCK;

@BeforeAll
Expand All @@ -65,20 +66,52 @@
String dsname1 = "SYS1.PARMLIB";
String dsname2 = "SYS1.PROCLIB";

URI uri = HttpRequestUtils.getUriFromGateway(ZOSMF_ENDPOINT, new BasicNameValuePair("dslevel", "sys1.p*"));
URI uri = HttpRequestUtils.getUriFromGateway(ZOSMF_ENDPOINT + "ds", new BasicNameValuePair("dslevel", "sys1.p*"));

given()
.config(SslContext.clientCertUser)
.header("X-CSRF-ZOSMF-HEADER", "")
.when()
.when()
.get(uri)
.then()
.then()
.statusCode(is(SC_OK))
.body(
"items.dsname", hasItems(dsname1, dsname2)
)
.body("items.dsname", hasItems(dsname1, dsname2))
.onFailMessage("Accessing " + uri);
}

@Test
void givenValidCertificate_whenPathContainsEncodedCharacters_thenReturnBadRequest() {
URI uri = HttpRequestUtils.getRawUriFromGateway(ZOSMF_ENDPOINT + "fs%2Fc%2Fuser%2Ffile.txt");
RequestSpecification mySpec = new RequestSpecBuilder().setUrlEncodingEnabled(false).build();
given()
.config(SslContext.clientCertUser)
.log().all()
.spec(mySpec)
.header("X-CSRF-ZOSMF-HEADER", "")
.when()
.get(uri)
.then()
.log().all()
.statusCode(is(SC_BAD_REQUEST))
.onFailMessage("Accessing " + uri);
}

@Test
void givenValidCertificate_whenQueryParamsEncoded_thenReturnFile() {
URI uri = HttpRequestUtils.getRawUriFromGateway(ZOSMF_ENDPOINT + "fs?path=c%2Fuser%2Ffile.txt");
RequestSpecification mySpec = new RequestSpecBuilder().setUrlEncodingEnabled(false).build();
given()
.config(SslContext.clientCertUser)
.log().all()
.spec(mySpec)
.header("X-CSRF-ZOSMF-HEADER", "")
.when()
.get(uri)
.then()
.log().all()
.statusCode(is(SC_OK));
}

}

@Nested
Expand All @@ -92,9 +125,9 @@
given()
.config(SslContext.clientCertValid)
.noContentType()
.when()
.when()
.post(loginUrl)
.then()
.then()
.statusCode(is(SC_NO_CONTENT))
.cookie(COOKIE_NAME, not(is(emptyString())))
.onFailMessage("Accessing " + loginUrl)
Expand All @@ -112,9 +145,9 @@
.config(SslContext.clientCertValid)
.auth().basic("Bob", "The Builder")
.noContentType()
.when()
.when()
.post(loginUrl)
.then()
.then()
.statusCode(is(SC_NO_CONTENT))
.cookie(COOKIE_NAME, not(is(emptyString())))
.onFailMessage("Accessing " + loginUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,27 @@ public static URI getUriFromGateway(String endpoint, NameValuePair...arguments)
return getUriFromService(ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(), endpoint, arguments);
}

/**
* Build a gateway URI from a raw (already percent-encoded) path without re-encoding.
* Use this instead of {@link #getUriFromGateway} when the path contains encoded characters
* like {@code %2F} that must not be double-encoded.
*/
public static URI getRawUriFromGateway(String rawPath) {
var config = ConfigReader.environmentConfiguration().getGatewayServiceConfiguration();
var host = config.getHost();
var hostnameTokenizer = new StringTokenizer(host, ",");
host = hostnameTokenizer.nextToken();
if (StringUtils.isNotBlank(config.getDvipaHost())) {
host = config.getDvipaHost();
}
try {
return new URI(config.getScheme() + "://" + host + ":" + config.getPort() + rawPath);
} catch (URISyntaxException e) {
log.error("Can't create raw URI for path '{}'", rawPath);
return null;
}
}

public static URI getUriFromGateway(String endpoint, String gatewayHostname, NameValuePair...arguments) {
return getUriFromService(ConfigReader.environmentConfiguration().getGatewayServiceConfiguration(), endpoint, s -> gatewayHostname, arguments);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@

package org.zowe.apiml.client.api;

import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import org.zowe.apiml.client.services.AparBasedService;

import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;

@RestController
Expand All @@ -27,11 +27,20 @@ public class FilesController {
private final AparBasedService files;

@GetMapping(value = "/zosmf/restfiles/ds", produces = "application/json; charset=utf-8")
public ResponseEntity<?> readFiles(
public ResponseEntity<?> readDatasets(
HttpServletResponse response,
@RequestHeader Map<String, String> headers
) {
return files.process("files", "read", response, headers);
}

@GetMapping(value = {"/zosmf/restfiles/fs/**", "/zosmf/restfiles/fs"}, produces = "application/json; charset=utf-8")
public ResponseEntity<?> readFile(
HttpServletResponse response,
@RequestHeader Map<String, String> headers
) {
return files.process("files", "readFile", response, headers);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.HashMap;

@SuppressWarnings({"squid:S1452", "squid:S1172"})
public class FunctionalApar implements Apar {
Expand Down Expand Up @@ -89,7 +90,11 @@ public Optional<ResponseEntity<?>> apply(Object... parameters) {
}

if (calledService.equals("files")) {
result = handleFiles(headers);
if ("readFile".equals(calledMethod)) {
result = handleFileContent(headers);
} else {
result = handleFiles(headers);
}
}

if (calledService.equals("jwtKeys")) {
Expand Down Expand Up @@ -160,6 +165,15 @@ protected ResponseEntity<?> handleFiles(Map<String, String> headers) {
return null;
}

/**
* Override to provide a response entity when a specific file content is requested.
*/
protected ResponseEntity<?> handleFileContent(Map<String, String> headers) {
var body = new HashMap<String, String>();
body.put("file", "content");
return new ResponseEntity<>(body, HttpStatus.OK);
}

protected boolean noAuthentication(Map<String, String> headers) {
String basicAuth = getAuthorizationHeader(headers);
String cookie = getAuthCookie(headers);
Expand Down
Loading