Skip to content

Reduce Code Duplication #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Sep 4, 2023
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