Closed cmgrote closed 4 years ago
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 20 days if no further activity occurs. Thank you for your contributions.
I will enable HTTPS (and disable HTTP) for server-chassis also. The default used certificate will be by default self signed and included in the source code.
It might affect notebooks and docker images that are using 8080 port and HTTP protocol.
As the UI is using by default 8443 port for HTTPS, in order to be able to run on the same machine my proposal is server-chassis to use by default 9443 port.
Please make sur you include the updates to the tutorials and labs in your PR so there is no disruption to those consuming Egeria.
Of course. Not sure I know all the places where changes are needed, but I'll add you, @planetf1 and @cmgrote as reviewers.
Thanks -- Can I suggest leaving the PR (when created) as 'draft' so we don't accidentally merge - as the notebooks etc will definately break without being updated accordingly.
I also think we need a way to support existing behaviour though I agree overall that the change should be done, and disabling should be discouraged
A sensible roll-out might be to make this optional initially (including docs on how to simply configure), to add support to notebooks/charts to support it, then only once working we can consider flipping the default
Not sure how important is the default self-signed certificate, but I generated default self signed cert that will stay in the resources inside the jar like:
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: Egeria ODPi
What is the name of your organizational unit?
[Unknown]: Egeria
What is the name of your organization?
[Unknown]: ODPi
What is the name of your City or Locality?
[Unknown]: San Francisco
What is the name of your State or Province?
[Unknown]: CA
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=Egeria ODPi, OU=Egeria, O=ODPi, L=San Francisco, ST=CA, C=US correct?
A very good question.. I'd be inclined to go with your suggestion.
Changed to CN=*, OU=Egeria, O=ODPi, L=San Francisco, ST=CA, C=US Java checks the CN match to hostname but allows wildcards
Truststore and cert will be also included. Unfortunately truststore it is alway interpreted as a filesystem path which makes distribution inside jar not an option and makes distribution difficult.
So making different platforms and UI able to communicate there are following option:
java -Djavax.net.ssl.trustStore=[path/to/truststorer] -Djavax.net.ssl.trustStorePassword=[truststore_pass] -jar server-chassis-[version].jar
java -jar server-chassis-[version].jar --server.ssl.trust-store=[path/totruststore] --server.ssl.trust-store-password=[truststore_pass]
override certificates keystore and truststore with prefered ones
disable SSL is also possible by using --server.ssl.enable=false
The above focuses on the inbound user requests to server chassis
We could stop at this point - using http only within the egeria environment (restricting access at the network level) & only have https for consumers -- but this seems very inadequate. We also have intensive interaction using https between platforms. I wonder if we may need a self-signed CA, and then generate multiple certificates for each server actor? (as well as documenting how to configure them for a production environment)
Each time egeria makes a connection we need to ensure that supports/is configurable to use SSL with appropriate certs
In terms of the current container setup, ultimately it should support security. STRICT_SSL works well for disabling cert checking - though a further change would be the expected change/addition of port used by server chassis from 8080 to perhaps 8443 - this will mean all the port numbers in our examples, in the Dockerfiles, docker-compose definitions & k8s scripts. Not technically difficult though. Allowing both ports in the medium term makes sense.
We also
By default, all the platforms are using the same self signed certificate, included in jar.
For production env, is a common procedure well known by dev-ops. Every platform needs a keystore and a truststore.
PR #3056 has extensive updates on the current state of testing & what is working so far.
Changes made:
This first phase is for interoparability - ie ensuring egeria can be used, even if certificate checking is enabled.
Testing:
Known Issues & todos
Once this PR is complete we will continue with proper use/checks of SSL certs IN A NEW PR - which will include removing, or allowing configuration of some bypasses added above.
@planetf1 thanks for the summary, but I don't understand all the Knowns Issues. What versions of chrome and safari are you referring to, because in my tests all are working (and tested multiple versions of chrome and firefox and one safari). All works fine after accept the certificate. Are you sure you are not using a proxy pack from the company in this 2 browsers that blocks the certificate?
My Chrome is: Google Chrome is up to date Version 83.0.4103.61 (Official Build) (64-bit)
Certificate validation is not Spring related but JVM related, so I do not understand the statements regarding spring rest connector. The validation is made by JVM against default truststore of JVM and fails being self-signed. That's why a truststore was added.
Default running of the jar
java -jar egeria-ui-or-chassis .jar
makes JVM to look into truststore.p12 located into jvm working folder instead of the default jvm cacerts.
Of corse this can be override by using JVM ooptions like:
java -Djavax.net.ssl.trustStore=/the/path/to/truststore.p12 -Djavax.net.ssl.trustStorePassword=egeria -jar egeria-ui-or-chassis .jar
On browsers under MacOS:
Need to look at whether either of the newer browsers are showing bugs (as beta) are are just failing as they are a few weeks ahead of stable -- if so we have a pending issue. Safari tech preview is a little odd and I need to dig into more depth - but Chrome in particular is very clear:
Notice that there is no path given for the user to bypass - at least not without manual certificate import (perhaps). This is the primary concern.
Some products are now generating keys dynamically on install to avoid this issue - but that's a whole lot more infrastructure.
Ref certificate validation - in the clients this is related to the behaviour of restTemplate in particular. I am working with each of our code samples to ensure they work, but need to do more debugging
Limited resource this week due to our Egeria dojo sessions
Having checked the security officer omas
Not updating screenshots for this intermediate update as we may need to do again once we have security certs properly checked. Added to todo list for evaluating next set of changes. Many files / time to work through so seems sensible to combine. Meanwhile the explanatary text is correct.
Autoclosed in error.
The first part is now merged to master. Continuing with part 2 - will move todo list below:
Work for the next PR - or new issues. Keeping as a todo list. Some may be deferred beyond this first pass
I will likely make unique issues out of some of these as easier to track across multiple owners
Core functional changes:
Testing: (in addition to per-PR tests)
Documentation
Follow-on activities
On #1087 there appears no compelling reason to make this change purely to make the security changes required here easier. For both WebClient & restTemplate in order to modify truststore or change validation we need to define an SSL context, which is then used by a specified httpclient, and this is then passed to the builder for either webClient or restTemplate, thus they appear to operate similarly.
Whilst such a change is more futureproof, it is also another variable and in that regards is probably best done as an independent change. The ssl/http code will be pretty much the same.
Thus we will not make that change here.
Multiple certificates (per 'server' not 'platform') ?
When we switch to using https, we are enabling TLS ie Transport Layer Security - this is effectively just above the TCP level, and is established at the socket layer, targetting a particular host:port .
During the connection process a handshake establishes a cipher, and the server presents a certificate, which may be validated by the client. Session keys are then created which encrypt the traffic.
Only once this connection is established do we start dealing with http requests like GET /index.html . The certificate has already been presented.
It's possible to service multiple virtual hosts by using multiple IPs However a single cert is still needed . More recently web servers like apache httpd can use a single IP -- this approach is known as 'TLS Extension Server Name Indication (SNI)'
However in all these cases it's one cert=one host ('platform' in egeria)
If an egeria deployment wanted to use unique certs, the approach would be to create multiple virtual hosts (and perhaps domains), and handle the certs in a reverse-proxy - maybe envoy (/ istio) - the backend certs between the proxy and egeria itself then would merely be an internal hidden aspect.
The conclusion is that we can implement TLS/certs in Egeria server only per-platform @mandy-chessell
Note that this is distinct from authorization of http requests themselves which is another discussion ...
The clients can more flexibly decide when a request is made which certs to check against, but for simplicity I would keep it at the same granularity of host/port (ie 'platform')
Making socket connections (client role)
Any client code needs to be able to validate the certificate returned from a server (egeria platform)
Standard java approach for this is to add
-Djavax.net.ssl.trustStore=/path/to/truststore.p12
-Djavax.net.ssl.trustStorePassword=egeria
-Djavax.net/ssl.trustStoreType=p12
This should work, but has to be specified on launch.
Note that if we do not configure with the spring mechanism, then this approach should still work
The Standard spring mechanism (after all - it provides restTeamplte) for this might LOOK to be:
server.ssl.trust-store=truststore.p12
server.ssl.trust-store-password=egeria
However these are actually only used by a server in validating the client certificates for mutual SSL - they are passed to embedded tomcat. They ARE NOT used for the client checking the authenticity of the server certificates. They are server functionality.
To specify the the client checks we need to create a custom SSL context & manage the certificates there.
A variety of approaches seem viable for this including
As with our workaround - where we implement an all-trusting trust manager, we also here will need to load in the right truststore (from a client perspective) in addition to allowing skipping of ssl checks
The values to be used could likely still be picked up as spring properties - so we might use 'http.client.truststore' or similar to distinguish them from the server configuration. Spring has no built in support for this.
(note: Tip for debugging: -Djavax.net.debug=ssl )
At this point we have 1 way SSL. The server is presenting a certificate, which the client is validating (or not) but the client is not presenting a cert to the server.
Adding this moves us to Mutual (2 way) TLS. EACH CLIENT would have it's own certificate, which means plenty to manage…
This is where the spring values above become relevant ie server.ssl.trust-store
. Whilst there are some reports of this not working, it's possible there was confusion with it's use in restTemplate. By setting the truststore here we are configuring how the server (tomcat) validates client certificates - the opposite way around to the first problem.
Summary of cert/ca usage:
server side
certificate that server offers to client to prove it's authenticity (and contains it's public key) certificate of a client, or more likely the certitication authority to validate the client IF using mutual SSL client side
certificate of the server stored locally, or more likely the certification authority to validate the server client's OWN certificate, if using mutual SSL, which is then sent back to the server Within that there's a few controls to consider
How much certificate validation is done (most often for self-signed server certs or cas) - this can extend to hostname for example, and is something we need to bypass in a typical dev env.
Most of the time in browser-server interaction we'll be using 1 way SSL, but both can be used -- and browsers support both. For the most secure environments mutual SSL should be used everywhere and the plan is for egeria to support (IMO!)
So to summarize the planned changes
Next
Then
@planetf1 Some questions so I am on the same page as you on your summary:
The creates are one-off (for now), not created dynamically. Just a development activity, only the end result will be added into a deployment -- but we really do need to emphasize this is ONLY to allow a dev to get up and running. They really really really should create a cert/CA at the first opportunity. I will provide sample instructions on doing this, but using normal java/OS tools - nothing egeria specific.
The self signed CA is only to provide something we ship with. In any real deployment the 'user' would be expected to create any relevant certificates (maybe CAs) and refer to them as we document (tbd).
Whether they use one CA or multiple is entirely up to them. We will support one server certificate per PLATFORM. we cannot do it at the egeria server level. How that relates to real 'tenants' (as in an org) is deployment specific. I'm also planning we use the same server cert for all platforms (as it's in the distro) but again it's essential the user can deploy one unique cert per platform.
The 'update ssl context' is relating to modifying the current code we have in spring rest template. Currently we do fudge the global ssl context, but it's better to do it with a new instance of the SSL context and effectively use that when we construct a restTemplate. The code also needs extending to use the correct truststore. The client can just use the CA - it doesn't need each certificate. HOWEVER it must also be possible to have a list of certificates in the truststore instead as it will be deployment specific
Hi @planetf1 , Ok - I am not too familiar with this - but is sounds reasonable. At the high level what do you think needs to change for the presentation server? I assume I need to do something equivalent to the sslContext change you are making. I am not sure how many scenarios I need to deal with. My guess is I need to deal with the following scenarios:
I’ll work through the base code first part of next week. I suggest we return to this then. I need to limit moving parts in the next step
To elaborate a little more
We have the client and server role - in terms of socket communications - happening in multiple places. For example between an egeria OMAS client and the server chassis, or between a view service and the OMAS server, maybe more levels, then (sorry am not up in full on the UI arch) finally between the user's browser and the web server.
So each of these involves client/server communication, and in each case there is potentially server - side -- a certificate to present client - side - known certs or a CA to check against AND if using mutual TLS server - side - known certs or CA to check the clients against.
So each component, say the view service could be playing both roles in this exchange. Indeed the server chassis itself does, since it also communicates with other metadata repositories.
Generally when we are storing a certificate to send, we use what we call a keystore, whilst when we are doing verification we call it a truststore - but typically it's using the same technology
In my view from reading the spring etc docs & posts there's quite a bit of confusion in this space which I've tried to dig into and clarify. YET at the same time it's new-ish in detail to me, so I may be wrong too.
Also we have some glossary conflicts - such as using terms like client, server - or even omas client.. and indeed description of some configration is conflated. I'll take that as a point to try and create some pictures once I've proven I'm going on the right lines :-)
Therefore I'm planning next to take what I've understood and apply it in the more central levels of the stack - server chassis, omas's and some client samples to prove it. There actually shouldn't be much core at all, it's just about seperation of concerns, and config.
The UI - both traditional and node-based adds another few layers that won't help the verification, but should be able to follow the same pattern, albeit with different implementatinos due to language.
Hope that explains.
I needed to spend a little time sorting out the release. That has now gone so I expect to progress with some implementation activities at the beginning of next week.
@planetf1 makes sense.
As observed in #3543 we will need to rework the UI accordingly.
In particular a chrome-valid certificate is still needed which should be consolidated with our other certs/docs
I have opened additional issues above to track specific changes we now need moving forward.
The additional configuration added in #3238 may be revisited at a future point, but for now the current behaviour will be documented, including how to use standard java/spring configuration. The main client configuration we do really need is the ability to bypass SSL check, and so there is issue #3869 to do this.
Any other deficiencies/bugs/enhancements should be raised as issues
(This is required for gold status under CII.)
The software produced by the project MUST support secure protocols for all of its network communications, such as SSHv2 or later, TLS1.2 or later (HTTPS), IPsec, SFTP, and SNMPv3. Insecure protocols such as FTP, HTTP, telnet, SSLv3 or earlier, and SSHv1 MUST be disabled by default, and only enabled if the user specifically configures it.
(see: https://github.com/coreinfrastructure/best-practices-badge/blob/master/doc/other.md#crypto_used_network)