Skip to content

Commit

Permalink
Merge pull request mercedes-benz#3015 from mercedes-benz/develop
Browse files Browse the repository at this point in the history
Update `community` branch
  • Loading branch information
sven-dmlr authored Mar 15, 2024
2 parents 9fd234e + 7fe6a04 commit 6485264
Show file tree
Hide file tree
Showing 89 changed files with 14,580 additions and 192 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/release-webui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ on:
webui-milestone-number:
description: WebUI Milestone number (e.g. 70)
required: true

permissions:
contents: write
issues: write
packages: write
pull-requests: write

env:
ACTIONS_BASE_IMAGE_ALPINE: alpine:3.17
ACTIONS_BASE_IMAGE_DEBIAN: debian:12-slim
ACTIONS_SECHUB_REGISTRY: ghcr.io/mercedes-benz/sechub
ACTIONS_HELM_REGISTRY: "oci://ghcr.io/mercedes-benz/sechub/helm-charts"

jobs:
release-version:
name: Create WebUI release
Expand Down Expand Up @@ -55,6 +68,13 @@ jobs:
with:
cache-read-only: false

- name: Docker login to ghcr.io
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

# ----------------------
# Create pull request if license headers are missing
# ----------------------
Expand Down Expand Up @@ -185,6 +205,28 @@ jobs:
Please close this issue after the release.
milestone: ${{ inputs.webui-milestone-number }}

# Build SecHub WebUI container image + push to ghcr
- name: Build sechub-webui ${{ inputs.webui-version }} container image + push to ghcr
run: |
WEBUI_VERSION="${{ inputs.webui-version }}"
DOCKER_REGISTRY="$ACTIONS_SECHUB_REGISTRY/sechub-webui"
VERSION_TAG="${WEBUI_VERSION}"
cp sechub-webui/build/libs/sechub-webui-${WEBUI_VERSION}.jar sechub-webui-solution/docker/copy/
cd sechub-webui-solution
echo "# Building image $DOCKER_REGISTRY:$VERSION_TAG"
echo " from $ACTIONS_BASE_IMAGE_DEBIAN"
./10-create-image.sh "$DOCKER_REGISTRY" "$VERSION_TAG" "$WEBUI_VERSION" "$ACTIONS_BASE_IMAGE_DEBIAN" copy
echo "# Pushing image $DOCKER_REGISTRY:$VERSION_TAG (latest)"
./20-push-image.sh "$DOCKER_REGISTRY" "$VERSION_TAG" yes
- name: Build sechub-webui Helm chart + push to ghcr
shell: bash
run: |
cd sechub-webui-solution/helm
echo "# Building Helm chart for SecHub WebUI"
helm package sechub-webui
helm push sechub-webui-*.tgz $ACTIONS_HELM_REGISTRY
# -----------------------------------------
# Create a pull request for merging back `master` into `develop`
# -----------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion gradle/libraries.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ ext {
restDocsApiSpec: "0.16.4", // newest version compatible with Spring Boot 2.x

/* Owasp Zap wrapper */
owaspzap_client_api: "1.12.0",
owaspzap_client_api: "1.13.0",
jcommander: "1.82",

thymeleaf_extras_springsecurity5: "3.1.1.RELEASE",
Expand Down
42 changes: 41 additions & 1 deletion sechub-api-java/src/main/resources/reduced-openapi3.json
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,13 @@
"type": "string"
}
},
"use": {
"type": "array",
"description": "Reference to the data section containing a file with the value for this header, e.g if the value is to big for the sechub configuration. Always use 'sources' with a single 'file' instead 'folders'.",
"items": {
"type": "string"
}
},
"name": {
"type": "string",
"description": "Name of the defined HTTP header."
Expand All @@ -1006,7 +1013,7 @@
},
"value": {
"type": "string",
"description": "Value of the defined HTTP header."
"description": "Value of the defined HTTP header. Either specify the header value directly here or reference a data section with 'use' e.g. if the value is to big, but never specify both."
}
}
}
Expand Down Expand Up @@ -1152,6 +1159,10 @@
}
}
},
"ServerVersion": {
"title": "ServerVersion",
"type": "object"
},
"StatusInformation": {
"title": "StatusInformation",
"type": "array",
Expand Down Expand Up @@ -1873,6 +1884,35 @@
]
}
},
"/api/admin/info/version": {
"get": {
"tags": [
"admin"
],
"summary": "Admin checks server version",
"description": "An administrator checks the current SecHub server version. Only administrators are able to check the server version, because knowing the exact server version makes it easier for penetration tester or attacker to attack the system.",
"operationId": "adminChecksServerVersion",
"responses": {
"200": {
"description": "200",
"content": {
"text/plain;charset=UTF-8": {
"schema": {
"$ref": "#/components/schemas/ServerVersion"
}
}
}
}
},
"security": [
{
"basic": [

]
}
]
}
},
"/api/admin/jobs/cancel/{jobUUID}": {
"post": {
"tags": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.slf4j.LoggerFactory;

import com.mercedesbenz.sechub.commons.model.ClientCertificateConfiguration;
import com.mercedesbenz.sechub.commons.model.HTTPHeaderConfiguration;
import com.mercedesbenz.sechub.commons.model.ScanType;
import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel;
import com.mercedesbenz.sechub.commons.model.SecHubDataConfigurationUsageByName;
Expand Down Expand Up @@ -107,6 +108,14 @@ public SecHubFileStructureDataProvider build() {

Optional<ClientCertificateConfiguration> clientCertOpt = webScan.getClientCertificate();
addAllUsages(data, clientCertOpt, false);

Optional<List<HTTPHeaderConfiguration>> httpHeaderConfigsOpt = webScan.getHeaders();
if (httpHeaderConfigsOpt.isEmpty()) {
break;
}
for (HTTPHeaderConfiguration httpHeaderConfig : httpHeaderConfigsOpt.get()) {
addAllUsages(data, Optional.ofNullable(httpHeaderConfig), false);
}
break;
case ANALYTICS:

Expand All @@ -127,24 +136,30 @@ public SecHubFileStructureDataProvider build() {
return data;
}

private void addAllUsages(MutableSecHubFileStructureDataProvider data, Optional<? extends SecHubDataConfigurationUsageByName> scanDefinitionObject,
/*
* Adds all usages of the given configUsageByName to the dataProvider. If
* mustHave is true a runtime exception is thrown when no configUsageByName is
* not present or names are empty.
*
*/
private void addAllUsages(MutableSecHubFileStructureDataProvider dataProvider, Optional<? extends SecHubDataConfigurationUsageByName> configUsageByName,
boolean mustHave) {
if (!scanDefinitionObject.isPresent()) {
if (!configUsageByName.isPresent()) {
if (mustHave) {
new IllegalStateException("For scanType:" + scanType + " the configuration entry is missing.");
new IllegalStateException("For scanType:" + scanType + " the configuration usage by name entry is missing.");
}
return;
}

SecHubDataConfigurationUsageByName usageByName = scanDefinitionObject.get();
SecHubDataConfigurationUsageByName usageByName = configUsageByName.get();

Set<String> names = usageByName.getNamesOfUsedDataConfigurationObjects();
if (names.isEmpty()) {
if (mustHave) {
new SecHubRuntimeException("Confgiguration file problem. For scanType:" + scanType + " at least one data configuration must be referenced");
new SecHubRuntimeException("Configuration file problem. For scanType:" + scanType + " at least one data configuration must be referenced");
}
}
data.addAcceptedReferenceNames(names);
dataProvider.addAcceptedReferenceNames(names);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,13 @@ void for_scantype_webscan_sources_data_section_for_api_and_client_certificate_cr
"fileSystem" : {
"files" : [ "certificate.p12" ]
}
} ]
},
{
"name" : "header-file-ref-for-big-tokens",
"fileSystem" : {
"files" : [ "bearer-token.txt" ]
}
}]
},
"webScan" : {
"url" : "https://localhost",
Expand All @@ -263,7 +269,11 @@ void for_scantype_webscan_sources_data_section_for_api_and_client_certificate_cr
"clientCertificate" : {
"password" : "secret-password",
"use" : [ "client-cert-api-file-reference" ]
}
},
"headers" : [{
"name" : "Authorization",
"use" : [ "header-file-ref-for-big-tokens" ]
}]
}
}
""";
Expand All @@ -274,8 +284,12 @@ void for_scantype_webscan_sources_data_section_for_api_and_client_certificate_cr

/* test */
assertNotNull(dataProvider);
assertTrue(dataProvider.getUnmodifiableSetOfAcceptedReferenceNames().contains("open-api-file-reference"));
assertTrue(dataProvider.getUnmodifiableSetOfAcceptedReferenceNames().contains("client-cert-api-file-reference"));

Set<String> acceptedReferenceNames = dataProvider.getUnmodifiableSetOfAcceptedReferenceNames();

assertTrue(acceptedReferenceNames.contains("open-api-file-reference"));
assertTrue(acceptedReferenceNames.contains("client-cert-api-file-reference"));
assertTrue(acceptedReferenceNames.contains("header-file-ref-for-big-tokens"));
assertFalse(dataProvider.isRootFolderAccepted());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@

public class SimpleStringUtils {

private static final String TRUNCATE_POSTFIX = "...";
private static final String OBFUSCATE_POSTFIX = "*****";

private static final Logger LOG = LoggerFactory.getLogger(SimpleStringUtils.class);
private static final String EMPTY = "";

private SimpleStringUtils() {
}
Expand Down Expand Up @@ -98,16 +102,46 @@ public static String emptyToNull(String value) {
* @throws IllegalArgumentException when max length is smaller than 4
*/
public static String truncateWhenTooLong(String string, int maxLength) {
if (string == null) {
return null;
}
if (maxLength < 4) {
throw new IllegalArgumentException("max length must be at least 4!");
}
if (string == null) {
return null;
}
if (string.length() <= maxLength) {
return string;
}
return string.substring(0, maxLength - 3) + "...";
return string.substring(0, maxLength - TRUNCATE_POSTFIX.length()) + TRUNCATE_POSTFIX;
}

/**
* obfuscates secret strings by showing only the required number of characters,
* trunc the rest and add "*****"
*
* @param string
* @param nonObfuscatedCharacters number of characters that should be shown in
* clear text (eg. 3 -> abc*****), if the value
* is negative, the original characters are shown
* without postfix, if the value is greater than
* the secret length, all characters are shown
* with the postfix
* @return obfuscated string
*/
public static String createObfuscatedString(String string, int nonObfuscatedCharacters) {
if (string == null) {
return null;
}

if (nonObfuscatedCharacters < 0) {
return string;
}

int remaining = nonObfuscatedCharacters;
if (string.length() < remaining) {
remaining = string.length();
}

return string.substring(0, remaining) + OBFUSCATE_POSTFIX;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,50 @@

public class SimpleStringUtilsTest {

@ValueSource(strings = { "a", "ab", "$*abcdefghiujklmnop" })
@ParameterizedTest
void obfuscate_always_obfuscated_when_length_0(String text) {
assertEquals("*****", SimpleStringUtils.createObfuscatedString(text, 0));
}

@Test
void obfuscate_always_obfuscated_when_length_3_but_only_2_chars() {
/* prepare */
String text = "abc";

/* execute + test */
assertEquals("ab*****", SimpleStringUtils.createObfuscatedString(text, 2));
}

@ValueSource(ints = { 3, 5, 100 })
@ParameterizedTest
void obfuscate_always_obfuscated_when_string_length_smaller_than_obfuscation_length(int length) {
/* prepare */
String text = "ab";

/* execute + test */
assertEquals("ab*****", SimpleStringUtils.createObfuscatedString(text, length));
}

@ValueSource(ints = { -1, -5, -100 })
@ParameterizedTest
void do_not_obfuscate_when_length_smaller_0(int lenght) {
/* prepare */
String text = "ab23zr9hfiedlshfl";

/* execute + test */
assertEquals("ab23zr9hfiedlshfl", SimpleStringUtils.createObfuscatedString(text, lenght));
}

@Test
void return_null_when_string_parameter_null() {
/* prepare */
String text = null;

/* execute + test */
assertNull(SimpleStringUtils.createObfuscatedString(text, 0));
}

@ValueSource(strings = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ" })
@ParameterizedTest
void isLatinLetter_valid_values(String value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.commons.model;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class HTTPHeaderConfiguration {
public class HTTPHeaderConfiguration implements SecHubDataConfigurationUsageByName {
public static final String PROPERTY_NAME = "name";
public static final String PROPERTY_VALUE = "value";
public static final String PROPERTY_ONLY_FOR_URLS = "onlyForUrls";
Expand All @@ -18,6 +20,8 @@ public class HTTPHeaderConfiguration {
private Optional<List<String>> onlyForUrls = Optional.empty();
private boolean sensitive = true;

private Set<String> namesOfUsedDataConfigurationObjects = new LinkedHashSet<>();

public String getName() {
return name;
}
Expand Down Expand Up @@ -49,4 +53,9 @@ public boolean isSensitive() {
public void setSensitive(boolean sensitive) {
this.sensitive = sensitive;
}

@Override
public Set<String> getNamesOfUsedDataConfigurationObjects() {
return namesOfUsedDataConfigurationObjects;
}
}
Loading

0 comments on commit 6485264

Please sign in to comment.