Skip to content
Open
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 @@ -18,6 +18,7 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.specification.RequestSpecification;
import org.graylog.testing.completebackend.FullBackendTest;
import org.graylog.testing.completebackend.GraylogBackendConfiguration;
import org.graylog.testing.completebackend.Lifecycle;
Expand All @@ -29,7 +30,6 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;

import java.io.ByteArrayInputStream;
import java.io.IOException;
Expand Down Expand Up @@ -100,47 +100,66 @@ static void tearDown() {
api.users().deleteUser(unprivilegedUser.username());
}

/**
* Request spec for the default admin user. Dumps the Graylog (and search server) container logs on any
* response {@code >= 500}, and logs the request/response whenever a subsequent assertion fails, so that
* an unexpected 500 leaves enough information to diagnose it without having to reproduce it.
*/
private static RequestSpecification req() {
return given()
.config(api.withGraylogBackendFailureConfig())
.spec(api.requestSpecification())
.log().ifValidationFails();
}

private static RequestSpecification req(Users.User user) {
return given()
.config(api.withGraylogBackendFailureConfig())
.spec(api.forUser(user).requestSpecification())
.log().ifValidationFails();
}

// --- Manifest tests ---

@FullBackendTest
void getManifestReturnsLogfiles() {
given()
.spec(api.requestSpecification())
req()
.when()
.get(MANIFEST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.body("entries.logfiles", notNullValue());
}

@FullBackendTest
void getManifestContainsInMemoryLog() {
given()
.spec(api.requestSpecification())
req()
.when()
.get(MANIFEST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.body("entries.logfiles.find { it.id == 'memory' }.name", equalTo("server.mem.log"));
}

@FullBackendTest
void getManifestRequiresReadPermission() {
given()
.spec(api.forUser(unprivilegedUser).requestSpecification())
req(unprivilegedUser)
.when()
.get(MANIFEST_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

@FullBackendTest
void getManifestAccessibleByReaderUser() {
given()
.spec(api.forUser(readerUser).requestSpecification())
req(readerUser)
.when()
.get(MANIFEST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.body("entries.logfiles", notNullValue());
}
Expand All @@ -149,89 +168,89 @@ void getManifestAccessibleByReaderUser() {

@FullBackendTest
void getInMemoryLogFileReturnsContent() {
given()
.spec(api.requestSpecification())
req()
.accept("application/octet-stream")
.when()
.pathParam("id", "memory")
.get(LOGFILE_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.header("Content-Disposition", not(emptyOrNullString()));
}

@FullBackendTest
void getLogFileWithUnknownIdReturns404() {
given()
.spec(api.requestSpecification())
req()
.accept("application/octet-stream")
.when()
.pathParam("id", "nonexistent-log-id")
.get(LOGFILE_URL)
.then()
.log().ifValidationFails()
.statusCode(404);
}

@FullBackendTest
void getLogFileRequiresReadPermission() {
given()
.spec(api.forUser(unprivilegedUser).requestSpecification())
req(unprivilegedUser)
.accept("application/octet-stream")
.when()
.pathParam("id", "memory")
.get(LOGFILE_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

// --- Bundle build, list, download, delete tests ---

@FullBackendTest
void buildBundleReturns202() {
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);
}

@FullBackendTest
void buildBundleRequiresCreatePermission() {
given()
.spec(api.forUser(readerUser).requestSpecification())
req(readerUser)
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

@FullBackendTest
void buildBundleRequiresPermissions() {
given()
.spec(api.forUser(unprivilegedUser).requestSpecification())
req(unprivilegedUser)
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

@FullBackendTest
void listBundlesAfterBuildReturnsNonEmptyList() {
// Build a bundle first
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

// List should contain at least one bundle
given()
.spec(api.requestSpecification())
req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.body("$", hasSize(greaterThan(0)))
.body("[0].file_name", not(emptyOrNullString()))
Expand All @@ -240,128 +259,128 @@ void listBundlesAfterBuildReturnsNonEmptyList() {

@FullBackendTest
void listBundlesRequiresReadPermission() {
given()
.spec(api.forUser(unprivilegedUser).requestSpecification())
req(unprivilegedUser)
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

@FullBackendTest
void downloadBundleReturnsZipContent() {
// Build a bundle
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

// Get the filename from list
final String filename = given()
.spec(api.requestSpecification())
final String filename = req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().path("[0].file_name");

// Download it
given()
.spec(api.requestSpecification())
req()
.accept("application/octet-stream")
.when()
.pathParam("filename", filename)
.get(DOWNLOAD_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.header("Content-Disposition", not(emptyOrNullString()));
}

@FullBackendTest
void downloadBundleRequiresReadPermission() {
// Build a bundle first so we have a filename to attempt
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

final String filename = given()
.spec(api.requestSpecification())
final String filename = req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().path("[0].file_name");

given()
.spec(api.forUser(unprivilegedUser).requestSpecification())
req(unprivilegedUser)
.accept("application/octet-stream")
.when()
.pathParam("filename", filename)
.get(DOWNLOAD_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

@FullBackendTest
void deleteBundleReturns202() {
// Build a bundle to delete
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

final String filename = given()
.spec(api.requestSpecification())
final String filename = req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().path("[0].file_name");

given()
.spec(api.requestSpecification())
req()
.when()
.pathParam("filename", filename)
.delete(DELETE_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

// Verify it's gone
given()
.spec(api.requestSpecification())
req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.body("collect { it.file_name }", not(Matchers.hasItem(filename)));
}

@FullBackendTest
void deleteNonExistentBundleReturns404() {
given()
.spec(api.requestSpecification())
req()
.when()
.pathParam("filename", "nonexistent-bundle.zip")
.delete(DELETE_URL)
.then()
.log().ifValidationFails()
.statusCode(404);
}

@FullBackendTest
void deleteBundleRequiresCreatePermission() {
given()
.spec(api.forUser(readerUser).requestSpecification())
req(readerUser)
.when()
.pathParam("filename", "any-bundle.zip")
.delete(DELETE_URL)
.then()
.log().ifValidationFails()
.statusCode(403);
}

Expand Down Expand Up @@ -428,28 +447,28 @@ void downloadedBundleFileContentsAreValid() throws Exception {
// --- Helpers ---

private Map<String, byte[]> buildAndDownloadBundleEntries() throws IOException {
given()
.spec(api.requestSpecification())
req()
.when()
.post(BUILD_URL)
.then()
.log().ifValidationFails()
.statusCode(202);

final String filename = given()
.spec(api.requestSpecification())
final String filename = req()
.when()
.get(LIST_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().path("[0].file_name");

final byte[] zipBytes = given()
.spec(api.requestSpecification())
final byte[] zipBytes = req()
.accept("application/octet-stream")
.when()
.pathParam("filename", filename)
.get(DOWNLOAD_URL)
.then()
.log().ifValidationFails()
.statusCode(200)
.extract().asByteArray();

Expand Down
Loading