Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
<email>jannik.hollenbach@iteratec.com</email>
</developer>
<developer>
<id>robert.seedorff</id>
<name>Robert Seedorff</name>
<email>robert.seedorff@iteratec.com</email>
<id>robert.felber</id>
<name>Robert Felber</name>
<email>robert.felber@iteratec.com</email>
</developer>
<developer>
<id>johannes.zahn</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public final class Config {
* Default for {@link #maxPageCountForGets}
*/
static final int DEFAULT_MAX_PAGE_COUNT_FOR_GETS = 100;
/**
* Null pattern object.
*/
public static final Config NULL = new Config("", "", DEFAULT_MAX_PAGE_COUNT_FOR_GETS);

/**
* URL of the host which serves the DefectDojo API.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: the secureCodeBox authors
//
// SPDX-License-Identifier: Apache-2.0

package io.securecodebox.persistence.defectdojo.http;

import io.securecodebox.persistence.defectdojo.config.Config;
import lombok.NonNull;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
* Placeholder to move duplicated code, will be named better later
*/
public final class Foo {
private final Config config;

public Foo(@NonNull final Config config) {
super();
this.config = config;
}

public HttpHeaders getDefectDojoAuthorizationHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Token " + this.config.getApiKey());

String username = System.getProperty("http.proxyUser", "");
String password = System.getProperty("http.proxyPassword", "");

if (!username.isEmpty() || !password.isEmpty()) {
System.out.println("Setting Proxy Auth Header...");
headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString((username + ':' + password).getBytes(StandardCharsets.UTF_8)));
}

return headers;
}

public RestTemplate setupRestTemplate() {
RestTemplate restTemplate;

if (System.getProperty("http.proxyUser") != null && System.getProperty("http.proxyPassword") != null) {
// Configuring Proxy Authentication explicitly as it isn't done by default for spring rest templates :(
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(System.getProperty("http.proxyHost"), Integer.parseInt(System.getProperty("http.proxyPort"))),
new UsernamePasswordCredentials(System.getProperty("http.proxyUser"), System.getProperty("http.proxyPassword"))
);
HttpClientBuilder clientBuilder = HttpClientBuilder.create();

clientBuilder.useSystemProperties();
clientBuilder.setProxy(new HttpHost(System.getProperty("http.proxyHost"), Integer.parseInt(System.getProperty("http.proxyPort"))));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());

CloseableHttpClient client = clientBuilder.build();

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(client);
restTemplate = new RestTemplate(factory);
} else {
restTemplate = new RestTemplate();
}

return restTemplate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: the secureCodeBox authors
//
// SPDX-License-Identifier: Apache-2.0

package io.securecodebox.persistence.defectdojo.http;

import lombok.NonNull;

/**
* This exception indicates a missing proxy config value
*/
public final class MissingProxyConfigValue extends RuntimeException {
MissingProxyConfigValue(@NonNull final ProxyConfigNames name) {
super(String.format("Expected system property '%s' not set!", name.getLiterat()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-FileCopyrightText: the secureCodeBox authors
//
// SPDX-License-Identifier: Apache-2.0

package io.securecodebox.persistence.defectdojo.http;

import lombok.Builder;
import lombok.Value;

/**
* Holds HTTP proxy configuration
* <p>
* This class is immutable by design and therefor thread safe. As defaults it does not use |{@code null} to prevent null
* pointer exceptions. It utilizes sane defaults (empty string or 0) to indicate a not set value. Also it introduces a
* null-object to indicate a not-existing configuration.
* </p>
*/
@Value
@Builder
public class ProxyConfig {
/**
* Null pattern object.
*/
public static final ProxyConfig NULL = ProxyConfig.builder().build();
private static final String DEFAULT_STRING = "";
private static final int DEFAULT_INT = 0;

/**
* Username to authenticate on a proxy.
* <p>
* Defaults to empty string.
* </p>
*/
@Builder.Default
String user = DEFAULT_STRING;

/**
* Password to authenticate on a proxy.
* <p>
* Defaults to empty string.
* </p>
*/
@Builder.Default
String password = DEFAULT_STRING;

/**
* Host name of the proxy.
* <p>
* Defaults to empty string.
* </p>
*/
@Builder.Default
String host = DEFAULT_STRING;

/**
* Port of the proxy.
* <p>
* Defaults to 0 (zero).
* </p>
*/
@Builder.Default
int port = DEFAULT_INT;

/**
* configuration is considered complete if all values are not default values
*
* @return {@code true} if all values are set else {@code false}
*/
public boolean isComplete() {
if (getUser().equals(DEFAULT_STRING)) {
return false;
}

if (getPassword().equals(DEFAULT_STRING)) {
return false;
}

if (getHost().equals(DEFAULT_STRING)) {
return false;
}

if (getPort() == DEFAULT_INT) {
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: the secureCodeBox authors
//
// SPDX-License-Identifier: Apache-2.0

package io.securecodebox.persistence.defectdojo.http;

import lombok.NonNull;

/**
* This class is responsible to create a proxy configuration
* <p>
* This implementation collects the configuration values from Java system properties. It also treats the
* cases of non-present values ot values of incorrect type.
* </p>
* <p>
* This class does not validate for semantic errors of the values, e.g. malformed hostnames or invalid
* port numbers.
* </p>
*/
public final class ProxyConfigFactory {
private final SystemPropertyFinder properties = new SystemPropertyFinder();

public ProxyConfig create() {
final var builder = ProxyConfig.builder();

if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_USER)) {
throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_USER);
}

builder.user(properties.getProperty(ProxyConfigNames.HTTP_PROXY_USER));

if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD)) {
throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_PASSWORD);
}

builder.password(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD));

if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_HOST)) {
throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_HOST);
}

builder.host(properties.getProperty(ProxyConfigNames.HTTP_PROXY_HOST));

if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_PORT)) {
throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_PORT);
}

try {
builder.port(Integer.parseInt(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PORT)));
} catch (final NumberFormatException e) {
throw new IllegalArgumentException(
String.format("Given port for proxy authentication configuration (property '%s') is not a valid number! Given value wa '%s'.",
ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(),
System.getProperty("http.proxyPort")),
e);
}

return builder.build();
}

private static class SystemPropertyFinder {
private boolean hasProperty(@NonNull final ProxyConfigNames name) {
return System.getProperty(name.getLiterat()) != null;
}

private boolean notHasProperty(@NonNull final ProxyConfigNames name) {
return !hasProperty(name);
}

private String getProperty(@NonNull final ProxyConfigNames name) {
return System.getProperty(name.getLiterat());
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: the secureCodeBox authors
//
// SPDX-License-Identifier: Apache-2.0

package io.securecodebox.persistence.defectdojo.http;

import lombok.Getter;

/**
* These properties can be configured by passing them to the running Java process w/ flag {@literal -D}
* <p>
* Example: {@literal java -Dhttp.proxyHost=... -D... -jar ...}
* </p>
* <p>
* <strong>Important</strong>: All four parameters are mandatory. You must set them all
* or none of them!
* </p>
*/
@Getter
public enum ProxyConfigNames {
/**
* System property name for the proxy username
*/
HTTP_PROXY_USER("http.proxyUser"),
/**
* System property name for the proxy user's password
*/
HTTP_PROXY_PASSWORD("http.proxyPassword"),
/**
* System property name for the proxy's hostname
*/
HTTP_PROXY_HOST("http.proxyHost"),
/**
* System property for the proxy's port number
*/
HTTP_PROXY_PORT("http.proxyPort");

private final String literat;

ProxyConfigNames(String literat) {
this.literat = literat;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@

@Data
public class ScanFile {
/**
* A default name must be set
* <p>
* It does not matter however unless the parser pays attention to file endings like json or xml.
* </p>
*/
static final String DEFAULT_NAME = "default-name.txt";

String content;

// a default name must be set, it does not matter however
// unless the parser pays attention to file endings like json or xml
String name = "default-name.txt";
String name;

public ScanFile(String content){
this.content = content;
public ScanFile(String content) {
this(content, DEFAULT_NAME);
}

public ScanFile(String content, String name){
public ScanFile(String content, String name) {
super();
this.content = content;
this.name = name;
}
Expand Down
Loading