Well, I'm new to Spring Boot Security and I have a question. I have the simple settings to enable https on the server, as follows:
server:
port: 8443
ssl:
key-store-type: PKCS12
key-store: classpath: keystore.p12
key-store-password: mypass
key-alias: testkey
So far so good. The issue is that clients accessing the endpoints of that server, as a simple curl for example, receive certificate verification failure. From what I could read, the https communication is made over TSL (or SSL) and it requires the user to validate the certificate issued by the server to enable a security channel.
I did not want all clients to have to carry the certificate with them to access the endpoints, because it's a Rest API I'm developing.
Some urls of apis that enable https but do not require the certificate:
https://api.github.com/*
https://api.twitter.com/1.1/search/*
...
What way should I follow in order to keep encryption enabled, ie keep https, but also not require client-side certificate validation?
PS: By the browser I can access my services and get the answers, but a java client, python, or the curl, does not work.
EDIT
I did not want to set the client on the option to make the request insecure, I wanted to keep https but did not require the client to carry the certificate with him. Maybe I can not even do this, so I'm asking because I'm definitely a beginner. If there is no way to do it, I await an answer in that direction, more complete if possible
This depends on each individual client. For example, you do this by ignoring the security warning in your browser. For curl, use -k or --insecure for wget use --no-check-certificate, you'll have to research how to ignore ssl in whatever client you are using. There is no way to control this from the server as that would defeat the entire purpose of SSL/TLS.
Related
Our client has provided self signed certificate for one of the internal service. We are acceessing this service in our shell script using curl. In order to connect to that service we need to provide certiface in our curl command or we can disable ssl verification using -k in our curl command. We wanted to know is it safe to disable ssl verification on production?
NO
Disabling certificate verification removes all security properties from the HTTPS connection. It is strongly advised that you do not disable it.
I'm currently trying to setup GlusterFS integration for a Kubernetes cluster. Volume provisioning is done with Heketi.
GlusterFS-cluster has a pool of 3 VMs
1st node has Heketi server and client configured. Heketi API is secured with a self-signed certificate OpenSSL and can be accessed.
e.g. curl https://heketinodeip:8080/hello -k
returns the expected response.
StorageClass definition sets the "resturl" to Heketi API https://heketinodeip:8080
When storageclass was created successfully and I try to create a PVC, this fails:
"x509: certificate signed by unknown authority"
This is expected, as ususally one has to allow this insecure HTTPS-connection or explicitly import the issuer CA (e.g. a file simply containing the pem-String)
But: How is this done for Kubernetes? How do I allow this insecure connection to Heketi from Kubernetes, allowing insecure self-signed cert HTTPS or where/how do I import a CA?
It is not an DNS/IP problem, this was resolved with correct subjectAltName settings.
(seems that everybody is using Heketi, and it seems to be still a standard usecase for GlusterFS integration, but always without SSL, if connected to Kubernetes)
Thank you!
To skip verification of server cert, caller just need specify InsecureSkipVerify: true. Refer this github issue for more information (https://github.com/heketi/heketi/issues/1467)
In this page, they have specified a way to use self signed certificate. Not explained thoroughly but still can be useful (https://github.com/gluster/gluster-kubernetes/blob/master/docs/design/tls-security.md#self-signed-keys).
Currently, I have a ngnix server (on port 5001) behind which a gRPC server is running, nginx having TLS enabled. All gRPC clients need to send the request to nginx port which forwards to gRPC server running. Initially for testing had gRPC request using usePlaintext() and it all worked fine, but the end goal is to use TLS. The requirement here is (as this are internal applications), gRPC channel request need not pass certificate but do a "skip certificate" when creating the channel.
After Googling around, I found examples on TLS but all of them does take .cert, .key file. Below is snippet which i tried and it failed at the server end couldn't validate the certificate
(java code)
ManagedChannel channel = NettyChannelBuilder.forAddress(<server IP address>, 5001).sslContext(GrpcSslContexts.forClient().trustManager
(new File(<.cert file>).build())
.build();
Doing some more research, i see Golang has InsecureSkipVerify() using which i can skip ceritifcate check (pls correct me if i am wrong)
tc := credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true,
})
Now how do I accomplish the same in java?
TLS with disabled certificate checking is of questionable usefulness because it can be trivially MITMed and so is not "supported" by gRPC. I highly recommend providing the client with proper root certificates to verify the server.
That said, you can go around gRPC's API to do this by passing Netty's InsecureTrustManagerFactory to SslContextBuilder.trustManager(TrustManagerFactory):
NettyChannelBuilder.forAddress("<server IP address>", 5001)
.sslContext(GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build())
.build();
I've always been an end consumer of HTTPS and have never really understood it that well but am looking to change that.
I am calling a RESTful web service over HTTPS. For example...
curl -X GET \
https://myCompanydns/rest/connect/v1.4/myEndpoint
With all my requests I send a basic authentication header i.e a username and password.
When I make these calls via my application I was expecting to have to add a certificate into like a jks (which I've had to do in the past) but on this occasion I've found that I can call the HTTPS web service without that.
For HTTPS to work I believe there is an SSL handshake? How is that happening successfully is this scenario without a jks?
Again, sorry for this beginner type question.
When doing a https://... request the client needs to verify that the servers certificate is the expected one - and not some man in the middle. This is done (among other things) by making sure that the servers certificate was issued by a trusted certificate authority (CA). Which CA is trusted is setup in the local trust store (i.e. local to the client). In the above call where no explicit trust store is given curl is using its default trust store. In the case where you've explicitly gave a jks you've provided the application with a specific trust store it should use.
For more on how the server certificates gets validated see SSL Certificate framework 101: How does the browser actually verify the validity of a given server certificate?.
I'm using Spring Security for X.509 preauthentication.
To make sure the client sends its certificate per HTTP request, is it necessary to:
Modify pom.xml to set <wantClientAuth> and <needClientAuth> to true
Set Apache's SSLVerifyClient to require reference
Based on reading, the web server must tell the client-side to sends its certificate in order for the client to actually send it. I'm confused if Spring Security AND Apache configuration is required to achieve this.
Spring Security configuration has nothing to do with whether the client sends a certificate or not. That's decided at the SSL protocol level and hence by the negotiation between the client and the server. Your question is a bit unclear in that it refers to a maven pom and an Apache configuration without explaining how your system is set up. Are you running the maven Jetty plugin with an Apache server in front?
Spring Security's X.509 authentication won't work if the SSL connection doesn't terminate at the servlet container. So if you have HTTPS between the client and Apache, and a non-SSL connection from Apache to the servlet container, then the client certificate won't normally be available.
If you are using an AJP connector, then you can configure Apache to pass the certificate on to the back end using the ExportCertData option. If you aren't, you can still take the exported certificate and pass it as a request header (you'll find examples of this elsewhere on SO). You would also need to customize the Spring Security X.509 code to extract the certificate from the header, rather than the standard java property name which it uses by default.