jenkinsci/hpe-application-automation-tools-plugin

View on GitHub
src/main/java/com/microfocus/application/automation/tools/rest/RestClient.java

Summary

Maintainability
A
35 mins
Test Coverage

Enable server certificate validation on this SSL/TLS connection.
Open

            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

Validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks.

The certificate chain validation includes these steps:

  • The certificate is issued by its parent Certificate Authority or the root CA trusted by the system.
  • Each CA is allowed to issue certificates.
  • Each certificate in the chain is not expired.

This rule raises an issue when an implementation of X509TrustManager is not controlling the validity of the certificate (ie: no exception is raised). Empty implementations of the X509TrustManager interface are often created to disable certificate validation. The correct solution is to provide an appropriate trust store.

Noncompliant Code Example

class TrustAllManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  // Noncompliant, nothing means trust any client
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, this method never throws exception, it means trust any server
        LOG.log(Level.SEVERE, ERROR_MESSAGE);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

See

Change this code to use a stronger protocol.
Open

            sslcontext = SSLContext.getInstance("SSL");

This rule raises an issue when an insecure TLS protocol version is used (ie: a protocol different from "TLSv1.2", "TLSv1.3", "DTLSv1.2" or "DTLSv1.3").

Noncompliant Code Example

javax.net.ssl.SSLContext library:

context = SSLContext.getInstance("TLSv1.1"); // Noncompliant

okhttp library:

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
      .tlsVersions(TlsVersion.TLS_1_1) // Noncompliant
      .build();

Compliant Solution

javax.net.ssl.SSLContext library:

context = SSLContext.getInstance("TLSv1.2"); // Compliant

okhttp library:

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
      .tlsVersions(TlsVersion.TLS_1_2) // Compliant
      .build();

See

Enable server hostname verification on this SSL/TLS connection.
Open

                    return true;

To establish a SSL/TLS connection not vulnerable to man-in-the-middle attacks, it's essential to make sure the server presents the right certificate.

The certificate's hostname-specific data should match the server hostname.

It's not recommended to re-invent the wheel by implementing custom hostname verification.

TLS/SSL libraries provide built-in hostname verification functions that should be used.

This rule raises an issue when:

  • HostnameVerifier.verify() method always returns true
  • a JavaMail's javax.mail.Session is created with a Properties object having no mail.smtp.ssl.checkserveridentity or mail.smtps.ssl.checkserveridentity not configured to true
  • a Apache Common Emails's org.apache.commons.mail.SimpleEmail is used with setSSLOnConnect(true) or setStartTLSEnabled(true) or setStartTLSRequired(true) without a call to setSSLCheckServerIdentity(true)

Noncompliant Code Example

URL url = new URL("https://example.org/");
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setHostnameVerifier(new HostnameVerifier() {
  @Override
  public boolean verify(String requestedHost, SSLSession remoteServerSession) {
    return true;  // Noncompliant
  }
});
InputStream in = urlConnection.getInputStream();

SimpleEmail example:

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true); // Noncompliant; setSSLCheckServerIdentity(true) should also be called before sending the email
email.send();

JavaMail's example:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // Noncompliant; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("username@gmail.com", "password");
  }
});

Compliant Solution

URL url = new URL("https://example.org/");
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
// Compliant; Use the default HostnameVerifier
InputStream in = urlConnection.getInputStream();

SimpleEmail example:

Email email = new SimpleEmail();
email.setSmtpPort(465);
email.setAuthenticator(new DefaultAuthenticator(username, password));
email.setSSLOnConnect(true);
email.setSSLCheckServerIdentity(true); // Compliant
email.send();

JavaMail's example:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.ssl.checkserveridentity", true); // Compliant
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("username@gmail.com", "password");
  }
});

See

Enable server certificate validation on this SSL/TLS connection.
Open

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

Validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks.

The certificate chain validation includes these steps:

  • The certificate is issued by its parent Certificate Authority or the root CA trusted by the system.
  • Each CA is allowed to issue certificates.
  • Each certificate in the chain is not expired.

This rule raises an issue when an implementation of X509TrustManager is not controlling the validity of the certificate (ie: no exception is raised). Empty implementations of the X509TrustManager interface are often created to disable certificate validation. The correct solution is to provide an appropriate trust store.

Noncompliant Code Example

class TrustAllManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  // Noncompliant, nothing means trust any client
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Noncompliant, this method never throws exception, it means trust any server
        LOG.log(Level.SEVERE, ERROR_MESSAGE);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

See

Make this anonymous inner class a lambda (sonar.java.source not set. Assuming 8 or greater.)
Open

            new HostnameVerifier(){

Before Java 8, the only way to partially support closures in Java was by using anonymous inner classes. But the syntax of anonymous classes may seem unwieldy and unclear.

With Java 8, most uses of anonymous inner classes should be replaced by lambdas to highly increase the readability of the source code.

Note that this rule is automatically disabled when the project's sonar.java.source is lower than 8.

Noncompliant Code Example

myCollection.stream().map(new Mapper<String,String>() {
  public String map(String input) {
    return new StringBuilder(input).reverse().toString();
  }
});

Predicate<String> isEmpty = new Predicate<String> {
    boolean test(String myString) {
        return myString.isEmpty();
    }
}

Compliant Solution

myCollection.stream().map(input -> new StringBuilder(input).reverse().toString());

Predicate<String> isEmpty = myString -> myString.isEmpty();

Return an empty array instead of null.
Open

                return null;

Returning null instead of an actual array or collection forces callers of the method to explicitly test for nullity, making them more complex and less readable.

Moreover, in many cases, null is used as a synonym for empty.

Noncompliant Code Example

public static List<Result> getResults() {
  return null;                             // Noncompliant
}

public static Result[] getResults() {
  return null;                             // Noncompliant
}

public static void main(String[] args) {
  Result[] results = getResults();

  if (results != null) {                   // Nullity test required to prevent NPE
    for (Result result: results) {
      /* ... */
    }
  }
}

Compliant Solution

public static List<Result> getResults() {
  return Collections.emptyList();          // Compliant
}

public static Result[] getResults() {
  return new Result[0];
}

public static void main(String[] args) {
  for (Result result: getResults()) {
    /* ... */
  }
}

See

  • CERT, MSC19-C. - For functions that return an array, prefer returning an empty array over a null value
  • CERT, MET55-J. - Return an empty array or collection instead of a null value for methods that return an array or collection

Identical blocks of code found in 2 locations. Consider refactoring.
Open

        if (headers != null) {
            Iterator<Entry<String, String>> headersIterator = headers.entrySet().iterator();
            while (headersIterator.hasNext()) {
                Entry<String, String> header = headersIterator.next();
                connnection.setRequestProperty(header.getKey(), header.getValue());
src/main/java/com/microfocus/application/automation/tools/mc/HttpUtils.java on lines 196..202

Duplicated Code

Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).

Tuning

This issue has a mass of 46.

We set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.

The threshold configuration represents the minimum mass a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.

If the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.

See codeclimate-duplication's documentation for more information about tuning the mass threshold in your .codeclimate.yml.

Refactorings

Further Reading

There are no issues that match your filters.

Category
Status