Secure Elasticsearch installation retrospectively - security

I have an Elasticsearch installation (V7.3.2). Is it possible to secure this retrospectively? This link states that a password can only be set "during the initial configuration of the Elasticsearch". Basically, I require consumers of the restful API to provide a password (?) going forward.

The elastic bootstrap password is used to init the internal/reserved users used by the components or features of the elastic stack (kibana, logstash, beats, monitoring, ...).
If you want to secure the API, you need to create users/roles for your scenario on top.
Please use TLS in your cluster when handling with passwords and don't expose the cluster directly for security reasons.
Here are all informations regarding a secure cluster including some tutorials: https://www.elastic.co/guide/en/elasticsearch/reference/7.3/secure-cluster.html
EDIT: Added links as requested. Feel free to raise a new question here at SO if you're facing serious problems!

Here you can find a complete guide to install and secure ElasticSearch.
Basically the bootstrap password is used initially to setup the built-in ElasticSearch users (like "elastic", "kibana"). Once this is done, you won't be able access ElasticSearch anonymously but only with one of the built in users, e.g. "elastic".
Then you can use "elastic" user to create additional users (with their own password) and roles (e.g. to asses specific indexes only in read-only mode).
As #ibexit wrote it's highly recommended to secure your cluster and don't expose it directly (use a proxy server, secured with SSL).

Related

Spring Security Authentication, making RestTemplate calls avoid using a String for authentication

Hi I'm having issues security my application, enabling authenticated users access to specific endpoints, non-authenticated users access to others and most importantly, continuing to enable the application to communicate with itself, without storing passwords as a String in the case base.
The code base:
My code base consists of numerous packages that communicate via REST and GraphQL calls. With no authentication, this system works fine. Development is in Java 8 with Maven.
Aim:
I am currently in the process of adding authentication to the code base which should enable three things to occur.
The different projects in the application continue to communicate easily.
An "admin" user can log in and make calls either via Swagger or GraphiQL or any methods they require.
The average user will only be able to access specific endpoints such as UI elements (e.g. localhost:8082/user-ui [unique_key])
Current Development:
I've implemented Spring Security In-Memory Authentication (https://www.appsdeveloperblog.com/spring-security-in-memory-authentication/). Which successfully blocks URLs being called and prompts the user for credentials, except on certain predefined endpoints. This fulfilling criteria 3 and part of criteria 2 (as the Admin can access Swagger and GraphiQL).
My Problem:
Unfortunately setting up this system has broken the internal calls as the RestTemplate used to communicate between packages no longer has the correct authentication.
While I could use BasicAuthenticationInterceptor(https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) to provide the authorization, this would mean having to write the password in a String in the code base. As I understand it, this is bad form as the String is then stored in the String pool. Elsewhere I've managed to avoid this using the CharBuffer before encoding the password, however BasicAuthenticationInterceptorrequires a String.
Any advice on how to proceed would be greatly appreciated.
If you are using basic authentication, you will have to provide the password when you are making internal calls with resttemplate. That doesn't mean you need to store the sensitive data (in this case credentials for your basic authentication) in plain text in the code base. One of the most common practices is to use an external file to store the sensitive data and then get the application to use them at run time. You may also want to ignore that file from git repository to prevent that being part of the code base.
If you are using Spring boot have a look at the environment specific properties files, which could be an ideal way to store profile specific configuration and data like these.
https://docs.spring.io/spring-boot/docs/1.5.5.RELEASE/reference/html/boot-features-external-config.html
https://www.baeldung.com/properties-with-spring
If you are worried about storing the credentials in plain text in properties file, you can also encrypt sensitive data in your properties files.
Spring Boot how to hide passwords in properties file

Apache Livy Security

We are trying to build a setup where we have a server that submits jobs of different users to the Livy server via the REST API. We established a kerberos server to authenticate against livy. But we want to prohibit the users to access a different users' data, the filesystem, and the network.
My question would then be, how secure is livy? Users can inject custom code to run on livy, but this gives them the ability to access the filesystem on the host the livy server resides in. Even if we run livy with a different unix user, that has very little permissions on the filesystem, that could be potentially dangerous from my point of view, they could potentially access the keytab on the livy server also. And they could also potentially inject malware and run it.
I know that the session created creates also a JVM, so one session lives in a JVM, and it is impossible to see another session's data etc. without having the kerberos ticket, but could I change the security settings of that JVM to only access specific paths and specific IP addresses only? Would that mean for me to change the source code of livy?
And in the case of using HDFS with active directory to secure the datasystem, so that users need to specify a kerberos key to access their files, how could I manage multiple principals in one server, to get this working?
My conf file is as below:
livy.environment production
livy.impersonation.enabled true
livy.server.csrf_protection.enabled true
livy.server.port 8999
livy.server.session.timeout 3600000
livy.server.auth.kerberos.keytab /home/harun/Documents/incubator-livy/keytabs/new.keytab
livy.server.auth.kerberos.principal HTTP/livyserver.local#EXAMPLE.COM
livy.server.auth.type kerberos
#livy.server.launch.kerberos.keytab /home/harun/Documents/incubator-livy/conf/livy.headless.keytab
#livy.server.launch.kerberos.principal livy#EXAMPLE.COM
livy.server.access_control.enabled = true
livy.server.access_control.users = livy
livy.superusers=livy
PS: Does enabling launch.kerberos provide additional security to protect the keytab?
Any help to any of the questions is very much appriciated,
Thanks in forehand

JMX: How can I support both secure and insecure access at the same time (different URLs)

I've been asked to support 2 URLs for JMX access to our server:
A secure one (service:jmx:rmi://localhost/jndi/rmi://localhost:2020/jmxrmi)
An insecure one: (service:jmx:rmi://localhost/jndi/rmi://localhost:2020/insecure-jmxrmi)
The insecure one is primarily for demo purposes - no it won't be used during production.
I can create a custom ConnectorServer for /jmxrmi and provide an interceptor to use our security mechanism to verify credentials. If I just create a vanilla second ConnectorServer (no 'env' properties), however, using jconsole -debug to access it initially tries secure access, and puts up the dialog about that failing, then asking if I want to try it insecurely.
The docs I've read from Oracle/Sun indicate that I can disable password auth and SSL using a couple of command-line -D switches. But then does that not mess with the /jmxrmi secure access?
How do I support both secure and non-secure connections at the same time? Note that I don't need them using the same URL, of course.
Thanks!
This is a tough one. When you disable auth and SSL you do it per JVM.
The JMXRMP protocol can not distinguish between secured and non-secured connection. You either set up the security and it will be used or not. I think the best shot would be using a custom ConnectorServer and put up with the messages JConsole produces.

How to verify an application is the application it says it is?

Here's the situation: we have a common library which can retrieve database connection details from a central configuration store that we have setup. Each application uses this library when working with a database.
Basically, it will call a stored procedure and say "I am {xyz} application, I need to connect o " and it will return the connection details for that applications primary database (server, instance, database, user, and password).
How would one go about locking that down so that only application {xyz} can retrieve the passwords for {xyz} databases (there is a list of database details for each application... i just need to secure the passwords)?
The usual way is to have a different config store per app and give each app a different user/password to connect to the config store.
That doesn't prevent anyone from changing the app and replacing the user/password for app X with the values from app Y but it's a bit more secure, especially when you compile this data in instead of supplying it via a config file.
If you want to be really secure, you must first create a secure connection to the store (so you need a DB drivers that supports this). This connection must be created using a secure key that is unique per application and which can be verified (so no one can just copy them around). You will need to secure the executable with hashes (the app will calculate its own hash somehow and send that to the server who will have a list of valid hashes for each app).
All in all, it's not something trivial which you can just turn on with an obscure option. You will need to learn a lot about security and secure data exchange, first. You'll need a way to safely install your app in an insecure place, verify its integrity, protect the code against debuggers that can be attached at runtime and against it running in the virtual machine, etc.
Off the top of my head, try PKI.
Are you trying to protected yourself from malicous programs, and is this a central database that these applications are connecting to? If so you should probably consider a middle layer between your database and application.
I'm not sure this applies to your case, depending on how what your answers to the abovementioned would be, but by the comments it sounds like you are having a similar case to what this question is about.
Securing your Data Layer in a C# Application
The simplest/most straightforward way would be to store the passwords in encrypted format (storing passwords in plaintext is just plain bad anyhow, as recently demonstrated over at PerlMonks) and make each application responsible for doing its own password encryption/decryption. It would then not matter whether an app retrieved another app's passwords, as it would still be unable to decrypt them.
One possibility is to keep the passwords in the database in an encrypted form, and convey the encryption key to the allowed application(s) in a secure connection.Then, only the application with the encryption key can actually get the passwords and not others.

How to Secure CouchDB

CouchDB access as a rest service seems insecure. Anyone can hit the database and delete/add documents once it is exposed.
What strategies are there to secure the CouchDB?
A lot has changed since 2009, so I'm going to throw an answer in here. This answer is drawn from this page on the wiki.
CouchDB has a _users database that serves the purpose of defining users. Here's the gist straight from the wiki:
An anonymous user can only create a new document.
An authenticated user can only update their own document.
A server or database admin can access and update all documents.
Only server or database admins can create design documents and access views and _all_docs and _changes.
Then, for any given database you can define permissions by name or by role. The way authentication is implemented is through a _session Database. Sending a valid username and password to the _session DB returns an authentication cookie. This is one of several option for CouchDB Authentication. There're a few more options:
This option is a little old 1.0 was a few months back, we're on 1.2 as of today. But it's still very well outlined.
And this one from "The Definitive Guide"
Also, depending on which hosting service you might be using, you'll have the option to restrict access to couch over SSL.
Between Node, Couch, and a variety of other technologies that effectively scale horizontally (adding more servers) there's an interesting kind of pressure or incentive being put on developers to make applications that scale well in that manner. But that's a separate issue all together.
The only thing which really works currently security wise is something like this in your CouchDB configuration.
[couch_httpd_auth]
require_valid_user=true
[admins]
admin = sekrit
This puts basic HTTP auth on all of CouchDB. Even this is not well supportet in client libraries. For python e.g. you need a patched library.
The second approach is to put a proxy in front of CouchDB and let the proxy do the authentication and authorization work. Due to CouchDB's RESTful design this is quite easy.
All other approaches must be considered up to now highly experimental.
This may be a little different from your original question. If your couchdb is only a back-end store for a full server app, you can make a special account for the server app to use and require those credentials for access to couchdb.
On the other hand, a pure couch app that people hit directly through a javascript client needs a lot of care to be secure.
Using rewrites is not optional. You need a vhosts config that forces requests to your domain through your rewrites.
Rewrite routes */_all_docs and /*/_design/* to a 404 page. Otherwise users can list every document or get your whole app.
Rewrite generic object access, ie /dbname/:id to a show that can deny access if the user is not allowed to see the document. Unfortunately there is no equivalent workaround for doc-based access control of attachments.
We used haproxy to filter GET requests on _users. There is no legit reason for someone from outside to get a user record or list all your users. We want users to be able to register so we need write access. Currently couch cannot block read access to a db and simultaneously allow writes. It's a bug. Filtering with something like haproxy is our best workaround for now.
Use your own database to keep contact information that is in addition to what is provided by _users. This allows more control over access.
validate_doc_update should carefully reject any writes that should not be allowed.
In every case you need to imagine what someone who understood the system could do to subvert it and lock down those avenues of attack.
CouchDB does cookies, SSL, oauth, and multi-users just fine:
Here's some actual code in python:
from couchdb import Server
s = Server("https://user:password#example.com:6984")
Request the cookie: url encoded above and below, of course
You have to put the credentials twice to get started with the first cookie
Both in the Server() constructor as well as the _session POST body
code, message, obj = s.resource.post('_session',headers={'Content-Type' : 'application/x-www-form-urlencoded'}, body="name=user&password=password")
assert(code == 200)
Now you have received a cookie, extract it
cookie = message["Set-Cookie"].split(";", 1)[0].strip()
Now, exit python and restart
Next, Request a server object, but without the username and password this time
s = Server("https://example.com:6984")
s.resource.headers["Cookie"] = cookie
Yay, no password, try to access the database:
db = s["database"]
Optionally set the "persistent" cookie option on the server side to make the cookie last longer.
Have you read CouchDB documentation http://couchdb.apache.org/docs/overview.html? It has a "Security and Validation" section that addresses some of your concerns.

Resources