Security Posts

Securing Connection Between Pods in Openshift with SSL

On this post, im trying to create a simple microservices application on top of Openshift 3.11 and each services will do a simple secure connection between it by using a self-sign SSL which are managed by Openshift.

The goal of why Openshift are managing SSL certificate thru Openshift Secret is to have a rolling or rotating certificate feature on each services but can be triggered by Openshift without have to replace SSL on each services manually.

First is generate a p12 certificate by using keytool

cert>keytool -genkey -alias edw 
	-keystore edw.p12 -storetype PKCS12 
	-keyalg RSA -storepass password 
	-validity 730 -keysize 4096
What is your first and last name?
  [Unknown]:  Edwin
What is the name of your organizational unit?
  [Unknown]:  Company 01
What is the name of your organization?
  [Unknown]:  IT
What is the name of your City or Locality?
  [Unknown]:  Jakarta
What is the name of your State or Province?
  [Unknown]:  Jakarta
What is the two-letter country code for this unit?
  [Unknown]:  ID
Is CN=Edwin, OU=Company 01, O=IT, L=Jakarta, ST=Jakarta, C=ID correct?
  [no]:  yes

Next is creating two java projects which are connected one and another,

https://github.com/edwin/ssl-pods-example
https://github.com/edwin/ssl-pods-example-2

There are several part of the code that need mentioning,

First is making sure https option is active on application.properties, include our p12 certificate and make certificate password as parameterized. This parameter later on will be injected as environment variables on Openshift.

server.ssl.key-store-type=PKCS12
server.ssl.key-store=cert/edw.p12
server.ssl.key-store-password=${SSLPASSWORD}
server.ssl.key-alias=edw

server.port=8443
server.ssl.enabled=true

And the next is because we are using a custom certificate, dont forget to include it on RestTemplate.

@Configuration
public class MyRestTemplate {

    @Value("${server.ssl.key-store}")
    private String sslKeyStore;

    @Value("${server.ssl.key-store-password}")
    private String sslPassword;

    @Bean
    public RestTemplate restTemplate() throws Exception {
        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        clientStore.load(new FileInputStream(sslKeyStore), sslPassword.toCharArray());

        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadTrustMaterial(clientStore, new TrustSelfSignedStrategy())
                .build();
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory)
                .build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);

        return new RestTemplate(factory);
    }
}

Deploy those two application to Openshift,

oc new-app registry.access.redhat.com/openjdk/openjdk-11-rhel7~https://github.com/edwin/ssl-pods-example

oc new-app registry.access.redhat.com/openjdk/openjdk-11-rhel7~https://github.com/edwin/ssl-pods-example-2

Deploy certificate as OCP Secret and mount it as a volume on our application,

oc create secret generic cert --from-file=cert\edw.p12

oc set volume dc ssl-pods-example --add -t secret -m /deployments/cert --name cert --secret-name cert
oc set volume dc ssl-pods-example-2 --add -t secret -m /deployments/cert --name cert --secret-name cert

And our certificate password as OCP Secret and inject it as environment variable to our application

oc create secret generic sslpassword --from-literal=SSLPASSWORD=password

oc set env dc ssl-pods-example --from=secret/sslpassword 
oc set env dc ssl-pods-example-2 --from=secret/sslpassword 

After all deployed on OCP, next is give a route for our application. Im using re-encrypt method for ensuring an end to end encryption within the app. In order to do so, we need to include our application CA certificate as our route’s destination certificate. We can do so by exporting our certificate from p12 file using this command,

keytool -exportcert -keystore edw.p12 -storetype PKCS12 -storepass password -alias edw -file edw.crt -rfc

And paste the certificate on our route,

The end result would be like below image,

And as you can see, we are using certificate from end to end for securing our connection.

Google+

Do A Maven Owasp Library Scan from A Restricted Network

When we talk about DevSecOps, we are talking about a continous integration and delivery but embedded with a security scanning along the way. And one of the best tool for doing a security scanning for your application library is OWASP dependency-check, and thankfully we can embed it to our application and run it thru pipeline by using a Maven plugin.

There is a downside tho, Owasp Maven plugin need to update its vulnerability database regularly online from NVD database which is perhaps not convenient for most enterprise environment where online network access is very-very limited.

But there is one workaround, we can use our repository such as Nexus or JFrog to host our NVD vulnerability database. The concept is pretty much we can see on below diagram,

There are two repository needed to build for fulfilling Maven Owasp requirement. One for java library, and another one for javascript.

Once done, we can check our Maven Owasp scan by using this command,

mvn org.owasp:dependency-check-maven:check -DfailBuildOnCVSS=8 \
 -DcveUrlModified=http://nexus.example.com/repository/nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz \
 -DcveUrlBase=http://nexus.example.com/repository/nvd/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz \
 -DretireJsUrl=http://nexus.example.com/repository/retireJsUrl/jsrepository.json -DretireJsAnalyzerEnabled=false \ 
 -DossindexAnalyzerEnabled=false

If build is success, we can see that both our newly-created repository folder is now have multiple files there,

And if failed, we can see this error happen

And if you want to ignore Owasp scan result, you can change failBuildOnCVSS parameter to 11.

Google+

Create JWT Token based on Public – Private Key Certificate On Spring Security

Previously im always creating JWT token using a simple 20digit random character string, despite it works well but somehow it feels like there is something wrong. It feels like it is less secure.
Therefore, after spending some time researching, im changing below code where im using a 20 digits random String character


	String signingKey = "V5iwaQYUyqyi71ij3OtP";
	
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        return converter;
    }

To signing and veryfing using a simple public and private key, first we need to create a simple public key file, public.txt

-----BEGIN PUBLIC KEY-----
MIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAgBoDqqgVQd0VX0RFBxquFPI
7o0WabMhCV+BplU3MX+RVq8djCVvkb0FwZSuqZT8d3mvxLtEdHxHXI2vRL9qhOvD
pBgyXw6z+IrzSwYM1LrRj+vM61jCD9lhD5y5kbvzonNbTEGNX2//oJHKC0uwCXWP
ZNx6WdQkWrCD3FDtQyuDkPuGWeuXMqBwuLLrhMg1c4B3CF2DUyVxRLT21WfguRKE
8gkNBI6f9PsG/DAFyTbXJNRHjyqam4Uanc/kuiw/kUUCCdiNC7jUD64pPixJy0pC
8gXKH/iZZ4omSygFBCDHkcTJvCYdVOz36Smzzus8V38i2vx0gP5ri+eYgVdCsPG8
WkaL/8QwUB0zJIM6o7ELb4OyDDX8M99nOTovAsgSMvMu2dCAjsPAwwaJKb6Rnn84
zu3xWuDZNOTox/l4+YqV91p3+nvsizPbme3qiYNM6GJJX6mGUXCX7yaC7t4UEcQS
oLBvo/zXa1SOHrIMZVFhbT9PPpspBXC3YX+zS5/4XR1+m3PWvGiXBOpD47r1+Oz1
MWpZXqq5TT53AsbXOhGIGO54TLKq/m7lPJd1Y8KeKMdR5j+a1gmPy6kv68YBHPOx
npvlrpEvNFujNeBftfNrBoeHtiYCUKZjSTHLquCbuq2/w3FF8kRQNUc04btysTJ8
LdulnXqPagx9egAGjjG4QwIDAQAB
-----END PUBLIC KEY-----

and private key, private.txt. And put both of them under resources folder so accessible by our app

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

And change our code to below,

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.txt");
        Resource privateResource = new ClassPathResource("private.txt");
        String publicKey = null;
        String privateKey = null;
        try {
            publicKey = IOUtils.toString(resource.getInputStream());
            privateKey = IOUtils.toString(privateResource.getInputStream());
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        converter.setSigningKey(privateKey);
        return converter;
    }

The downside of this new signing is it almost doubled the size of my JWT token, but hopefully makes it more secure.

Google+

SSLHandshakeException When Connecting to Let’s Encrypt CA SSL

Found this weird error when connecting to a HTTPS website, using apache commons httpclient.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Very weird because i can connect to almost every other HTTPS website, but only one website causing this exception. After googling for a while, i found a very interesting solution from MKYong, that is to register the website’s certificate on my JVM.

http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

Run this command to generate a new jssecacerts file,

c:\>java InstallCert localhost:443

The only difference is the location where i downloaded InstallCert.java, i downloaded it from this link.

https://github.com/OopsMouse/java-use-examples/blob/master/src/com/aw/ad/util/InstallCert.java

And i also removed the file’s package name, to make it easier to run.

Google+