Configure SSL certificate in Angular 8 with Spring boot Application - java

I read few tutorials to configure LetsEncrypt SSL certificate in spring boot. We have an application developed in spring boot. it is running on embedded tomcat 8080. I have another Angular 8 App which is running on default 4200 port. Both apps are able to communicate with each other properly with the help of JwtToken. Now i want my App/domain should be ssl enabled. So my question is, do we need separate SSL certificates for both apps or it would be enough to configure at spring boot side.

Do we need separate SSL certificates?
If your tomcat server and angular app are under the same domain (sub-domains) you could secure both of them using single certification.
It would be enough to configure at spring boot side?
No, the whole point is to secure the connection from angular to tomcat server, if you used http on angular the page with keep showing not secured.
Please feel free to ask for any more clarification.

Let me post the answer of my question itself, after couple of days R&D.
Do we need separate SSL certificates?
Ans: We need only 1 certificate which we can generate against our domain name lets say someexample.com; Not explaining how to generate ssl certificate in this answer. This particular certificate should be configured with tomcat & nginx server both. If you will not give ssl certificate path in nginx then you will face error in browser network calls(INVALID_CERT_ERROR)
I generated my ssl certificate files at /etc/letsencrypt/live/. It may differ for you.
I edited the tomcat/config/server.xml file
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate hostName="someexample.com" certificateFile="/etc/letsencrypt/live/cert.pem"
certificateKeyFile="/etc/letsencrypt/live/privkey.pem"
certificateChainFile="/etc/letsencrypt/live/chain.pem" />
</SSLHostConfig>
</Connector>
Note that same ssl certificate we required to add in nginx too. Edited ngix.conf file.
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#someexample.com
server {
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/someexample.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/someexample.com/privkey.pem;
server_name someexample.com;
location / {
root html;
index index.html;
}
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256;
}
server {
listen 80;
server_name www.someexample.com someexample.com;
return 301 https://someexample.com;
}
}

Related

How to route HTTPS traffic through ELB to a EC2 container running a Java JHipster webApp

I have a JHipster monolithic application (Angular + Java SpringBoot + Tomcat container, everything together) deployed successfully in a EC2. I could set the security groups in order to enable 8443 incoming requests to the Public DNS and I am able to access it from any browser.
After that, I've requested a public certificate from Amazon for a domain I've already acquired with Route53.
So the idea was to use 443 instead of 8443, and the real domain (instead the Public DNS provided by AWS), so in effect I've created a ELB (all in the same VPC, security group and hosted zone). This ELB is listening in 443 and has a redirect to 8443 as default action.
But.. ERR_CONNECTION_REFUSED is what the browser shows..
It is important to mention that since AWS does not allow us to download the certificate (at least I don't see any option for that in the console) in the JDK of the EC2 where the app runs I've installed a custom certificate (generated with keytools) in order to apply it in Tomcat to listening the already mentioned 8443 port.
I also tried running in 8080 instead of 8443 (and of course updating the security groups) but no change..
Could you give me a clue about what I'm missing? So far the unique way I see is to create a new EC2 with a NGINX to act as a reverse proxy (with a rewrite policy maybe) behind the ELB, but I prefer to avoid additional complexity unless absolutely needed.
Additional data:
Tomcat server configuration:
server:
port: 8443
server.ssl.key-store: keystore.p12
server.ssl.key-store-password: thePassword
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: theKeyAlias
Security group inbound rules:
Custom TCP 8443 with 172.31.0.0/16 (the same range of the ELB)
HTTPS TCP 443 with 0.0.0.0/0 and ::/0
Also the AWS Certificate is enabled and already issued (CNAME record set was created in Route53)
**UPDATE 1 - 04 February 2019 22:21 (GMT-3) **
Guys, I finally decided to have a NGINX behind the ELB. Also I've realized that communication between NGINX and App Server could be HTTP, therefore my app is gonna listen in port 8080, simplifying a bit the scheme. I've realized also that I need only one certificate in order to have the "browser padlock" and encrypted all traffic between clients and ELB, so no matter if it is not possible to download it (it is not needed to install also in NGINX nor App. Server).
At the Apache level you should add a listener on port 443 which would proxy pass the requests on port 8443. This will make sure that all incoming requests on port 443 of the domain will be passed to the application running on port 8443 of the server
listen 443;
location /{
proxy_pass http://127.0.0.1:8443;
}
Finally issue RESOLVED I could make work fine the NGINX and also I had to change another things:
I've passed from an Application Load Balancer to a Classic Load Balancer. The final scheme is like I've explained in the UPDATE of this topic, I mean:
User connects via HTTP or HTTPS through Classic LB and then it goes to EC2 NGINX listening on port 80.
Then from NGINX to WebApp I've used a proxy_pass in this way:
location / {
proxy_pass http://172.x.y.z:8080;
}
And finally an HTTP forward in NGINX to use HTTPS exclusively:
proxy_set_header X-Forwarded-Proto $scheme;
if ( $http_x_forwarded_proto != 'https' )
{
return 301 https://$host$request_uri;
}
Lijo Abraham, your answer helped me to have a clear direction and this post shows the exactly solution applied (thats why I will green tick this post).
Many thanks and regards.
**UPDATE 1 - 10 February 2019 17:21 (GMT-3) ** Finally I've remade all again using Application ELB this time instead of Classic ELB (the latter deprecated) and everything works as expected, don't know why in the beginning ELB Classic didn't work (probably some error in security groups rules configuration or something kind of that).

Apache & Nginx (each as reverse proxy) having very different behavior for self signed backend certificate

I am deploying Angular on Nginx & Apache http server (as reverse proxy web servers) in my UAT environment with the backend being on spring boot on Apache Tomcat (encrypted with https for the java REST apis), I have noticed that Nginx was configured as reverse proxy much easier than Apache BUT that was largely because Apache didn't trust the Java APIs certificate (as it is self signed, so this seems correct)
Can someone explain why this happened? I trust that Nginx is secure but I want to know why it allowed this self signed certificate while Apache by default blocked it (only allowed it with SSLProxyVerify none)?
Nginx config (related part):
location /api {
proxy_pass https://192.168.170.78:7002/;
}
Apache config (the related part):
# SSL proxy config
SSLProxyEngine on
# Why this must be present for the apache to connect to the backend but not for nginx?
SSLProxyCheckPeerName off
# the (proxy) redirection rules for the server
ProxyPass /api/ https://192.168.170.78:7002/
ProxyPassReverse /api/ https://192.168.170.78:7002/

HTTPS - spring web security - how to make server secure

I am creating spring rest service. I wanna secure it with https.
I know that using following solution:
http
.authorizeRequests()
.antMatchers("/secure/**").hasRole("ADMIN")
.anyRequest.hasRole("USER")
.and()
.requiresChannel()
.anyRequest().requiresSecure();
I can force using https. But I do not know what else I have to do. Should I configure something else in spring security or it is enough? I am using tomcat. Should I install certificate? If yes, is existing possibility to install "test certificate"? How it works?
I don't have enough rep to add a comment, so you'll probably need to provide more information to get the answer you really want.
First off, to enable HTTPS, you will need an SSL certificate. If you're just testing/developing, you can generate your own self-signed certificate and ignore certificate warnings from your browser. If however this is a public-facing server, you'll need a valid SSL certificate from a certificate authority like GoDaddy or similar. Generating an SSL cert is probably outside the scope of this question, and there are a lot of guides out there for this (I would post links, but don't have enough rep).
The config you have shown is a valid way to force your application server to only communicate over HTTPS, however, it is not sufficient to actually enable HTTPS for your Tomcat server.
Depending on your setup, you have a few different options for enabling HTTPS.
If you're using Spring Boot with an embedded Tomcat server, then you can enable SSL by setting the server.ssl.* properties of your application.properties file, for example:
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
Where keystore.jks is the path to your Java keystore that holds your SSL certificate. See Spring Boot Docs for more info.
If you're using a standalone Tomcat server, you'll need to modify Tomcat's server.xml in $CATALINA_BASE/conf/server.xml and add an SSL connector. For example:
<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="${user.home}/.keystore" keystorePass="changeit"
clientAuth="false" sslProtocol="TLS"/>
This example is for Tomcat 7, but the process is similar for other Tomcat versions. See Tomcat SSL for more information.
If you are using a proxy/load balancer (like NGINX) you can add an SSL termination there. The proxy/load balancer then intercepts all HTTPS traffic and communicates over non-HTTPS connections to your application servers. This has the added bonus of not having to interfere with your application server to perform SSL-related maintenance like changing your certificate or config.

Why does my Java servlet filter not work over HTTPS?

Spring (Boot) here, although that shouldn't matter at all. I am trying to learn more about how HTTP/S proxies work and am building one to run locally on my machine. I wrote (and registered) a servlet filter that replaces the body of the HTTP response with a silly HTML message:
public class DummyFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
String html = "<html><head><title>Awesome!</title></head><body>Proxy is working!</body></html>";
httpServletResponse.writer.write(html);
httpServletResponse.writer.flush();
return;
}
#Override
public void destroy() {
}
}
I then run my Spring app, and change my browser's proxy settings to point to my app (localhost:8080).
I am now able to go to HTTP websites and see my dummy message ("Proxy is working!") as the HTML output. Success!!! However, I then went to Google's homepage, which apparently uses HTTPS, and the Google homepage rendered just fine.
So I changed my browser to also use my Spring app for proxying SSL (again, localhost:8080) and tried again. This time when I went to Google, my browser gave me an error stating that there was a problem with the connection. I assume this is because my stupid-simple proxy is causing problems with the SSL 'handshake' between the browser and the site requiring SSL (in this case, Google).
I know that using proxies over SSL is certainly possible, because (at the very least) the Charles Proxy can be configured to do this. Apparently, Charles operates by dynamically generating a cert for the site you are trying to access, based off its own root CA cert. Charles and the SSL site use the site's cert, and the communication between the browser and Charles uses Charles' cert.
But knowing that doesn't help me understand why my simple proxy is causing problems in SSL-land in the first place. What would I need to change in my code so that it could behave the same with HTTPS as it does with HTTP?
Update
I'm wondering if the following would work for me:
Create a self-signed wildcard cert for, say *.example.com (anything dot com)
Configure my Sring app to use this wildcart cert and to serve HTTPS from port 443 (HTTPS default)
Configure the browser's SSL proxy settings to point to localhost:443
Add my self-signed wildcard cert to my browser's trust store
Now when I go to any URL under https://example.com, the browser reaches out to my proxy, which serves it back the self-signed cert (which it now trusts), and the proxy can talk with the example.com site's actual cert just fine.
Would this, or something similar, fix my problem?
The problems indicated really are HTTP/S basic ones.
When directing your browser to use a proxy at the given address (localhost:8080), the browser is causing any subsequent HTTP call to the configured "proxy server" indicating to this "proxy" that it should execute a call on behalf of the calling browser to the original URL.
In your case the "proxy" really is returning a canned message and does not really try connecting to the original URL. (At least you did not tell anything about what your "Proxy Server" is going to do in order to contacting the originally targeted site.)
That would be the more material aspect of a proxy basic functionality.
In the case of connecting to a server using HTTPS, it is then important, how you did configured that proxy connection with your browser.
It would be possible to use a plain HTTP connection to the proxy and still request the proxy to using a HTTPS connection for the "external" call. (Such configuration, however, is not so much widespread, as the proxy need to e.g. carefully treat redirects. Also it would invalidate some gains of using HTTPS in the first place (at least on the communication segment from browser to proxy.)
Most likely your browser configuration used an HTTPS connection to the "proxy" (localhost:8080). Then the browser tried an HTTPS request and hit an error as the target "responded" with regular HTTP.
Configuring your proxy servlet to accepting HTTPS calls would "repair" that problem. (Form this, your steps from the "Update" edit will "solve" the errors.) However, you do not need to use port 443 at localhost. Any port will do. Just if you want to provide an HTTP and an HTTPS proxy at the same time do you need to allocate two ports (e.g. you could use 8080 for HTTP and 8081 for HTTPS).
Just to empachase: Seeing the "Proxy is working" message does not prove having a working proxy. It just proves that your browser does talk to your servlet. (As you do not read any header information, it is not different from just calling URL localhost:8080 directly.)
Beyond getting "contacted" a working proxy would need to take the request, analyze the headers passed in and react according to the standards (especially executing the requested "external" call and returning the results).
(Of course, you have read RFCs related to HTTP protocol (e.g. RFC7230)?)
You must create a HTTPS connector.
In order to create an HTTPS connector, you will need a few things; but most importantly, you will need to generate Certificate keystore that is used to encrypt and decrypt the SSL communication with the browser.
If you are using Unix or Mac, you can do it by running the following command:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
On Windows, this could be achieved via the following code:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
During the creation of the keystore, you should enter the information that is appropriate to you, including passwords, name, and so on. For the purpose of Once the execution is complete, a newly generated keystore file will appear in your home directory under the name: .keystore.
Note
You can find more information about preparing the certificate keystore at tomcat.
With the keystore creation complete, you will need to create a separate properties file in order to store your configuration for the HTTPS connector, such as port and others. After that, you will create a configuration property binding object and use it to configure our new connector.
See this example of a prop file. you can cll it whatever name you want : tomcat.https.properties
custom.tomcat.https.port=8443
custom.tomcat.https.secure=true
custom.tomcat.https.scheme=https
custom.tomcat.https.ssl=true
custom.tomcat.https.keystore=${user.home}/.keystore
custom.tomcat.https.keystore-password=changeit
Don't need to change your code.You might be missing configuration.Check whether you configured ssl correctly .
Follow the steps to enable ssl in your spring app:
create Keystore file
keytool -genkey -alias tomcat -keyalg RSA
2.Configuring Tomcat for using the keystore file – SSL config
in your server.xml
Find the following declaration:
<!--
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
Uncomment it and modify it to look like the following:
Connector SSLEnabled="true" acceptCount="100" clientAuth="false"
disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="/Users/prashant/.keystore" keystorePass="password"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />
3.Configuring your app to work with SSL (access through https://localhost:8443/yourApp)
add in your web.xml file of your application.
<security-constraint>
<web-resource-collection>
<web-resource-name>securedapp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
It works for me with my custom filter.
Hope so it will help you..

java tomcat a3 certificate

How to configure TOMCAT to make the browser show the installed certificates (A3; token USB) when a URL (servlet) is called?
I will retriev the X509 certificate on the servlet request parameter.
Your question is a bit difficult to understand, but I'm guessing that you want tomcat to request a certificate from a client.
If this is the case, then you will want to enable what is called mutual authentication in tomcat.
You will have to set the clientAuth attribute of your tomcat ssl connector to either want or true. The ssl connector will be found in your tomcat server.xml file.
'want' asks the client to send a certificate if it has one, but the request will go though if the client doesn't have a certificate and 'true' means the client is required to send a certificate and the request will fail if the client does not provide a certificate.
More information can be found on the tomcat website:
SSL/TLS Configuration HOW-TO

Categories

Resources