Security
General
Development life cycle
At Open Analytics we are continuously improving the development life cycle to prevent that malicious code would sneak into the jar/war files we distribute. We use continuous integration and a deployment process to enable automated security checks in the recipe and guarantee fresh JAR/WAR delivery. Should you discover security issues in the code, please contact us ASAP, ideally via e-mail. One can also file an issue on our Github repository; just ensure not to share sensitive information (IP, names, login, passwords, etc.).
Secure your underlying infrastructure
RDepot is relying on different infrastructure components, depending on the deployment strategy: Docker engine, authentication back-end, operating system, etc. The security of those components should be guaranteed and RDepot features have been added to enable our users to build secure infrastructure. In particular when deploying with Docker on a Docker host, there is a well-known issue should a Docker host API be publicly accessible without appropriate access controls. The host could be remotely compromised or arbitrary Docker instances could run on it.
To protect a Docker daemon the below security controls are mandatory:
- isolate Docker host from public/untrusted network
- never bind the Docker daemon API on 0.0.0.0, only on the loopback interface (127.0.0.1)
- should the Docker API be exposed (in case of a swarm or cloud deployment), ensure to use TLS mutual authentication for enabling communication with the Docker API. It’s a more heavy setup as it would require a proper PKI or certificate management/creation solution but exposing the Docker API should be avoided at all costs.
HTTPS (SSL / TLS)
From an architectural point of view it is recommended to support the off-loading of SSL certificates to a separate reverse proxy. Nginx works perfectly fine with RDepot and below an example configuration is given:
server {
listen 80;
server_name rdepot.yourdomain.com;
rewrite ^(.*) https://$server_name$1 permanent;
}
server {
listen 443;
server_name rdepot.yourdomain.com;
access_log /var/log/nginx/rdepot.access.log;
error_log /var/log/nginx/rdepot.error.log error;
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /etc/ssl/certs/yourdomain.com.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.com.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /backend/ {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The configuration:
- redirects http traffic (port 80) to https (port 443)
- serves the RDepot client UI locally from
/usr/share/nginx/html
- sends all backend traffic to the RDepot API which is running on port 8080
Note that nginx will pass RDepot API requests to port 8080 on the loopback interface (127.0.0.1) as indicated in the proxy_pass
directive above.
It is therefore also a good security measure to restrict the RDepot API to bind only on 127.0.0.1 (and not to 0.0.0.0 which is the default). This can be achieved by setting the server.address
in the RDepot application.yaml
configuration file:
# ...
allowed-origin: https://rdepot.yourdomain.com # allow requests from https://rdepot.yourdomain.com
server:
# ...
address: 127.0.0.1 # bind only to 127.0.0.1
port: 8080 # use port 8080
servlet:
context-path: /backend # expect requests from https://rdepot.yourdomain.com/backend
A similar setup can be achieved using Apache HTTPD:
-
first change the global
httpd.conf
to contain at least the following configuration directives:Listen 443 LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule ssl_module modules/mod_ssl.so LoadModule rewrite_module modules/mod_rewrite.so
Note: depending on the Linux distribution you are using, the exact method to enable these modules may depend. For example, on ubuntu this can be achieved by running the following commands (no changes to configuration files are needed):
sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_ssl sudo a2enmod ssl sudo a2enmod rewrite sudo a2enmod headers sudo systemctl restart apache2
-
create an empty directory:
mkdir /srv/rdepot
-
the next step is to create two VirtualHosts for RDepot. The first one is needed to redirect the traffic from HTTP to HTTPS, the second one is needed for serving the RDepot client UI locally from
/srv/rdepot
and proxying the backend traffic to the RDepot API.<VirtualHost *:80> ServerName rdepot.yourdomain.com RewriteEngine On RewriteCond %{SERVER_NAME} =rdepot.yourdomain.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent] </VirtualHost> <VirtualHost *:443> DocumentRoot "/srv/rdepot" ServerName rdepot.yourdomain.com ServerAlias rdepot.yourdomain.com ProxyRequests Off ProxyPreserveHost On ProxyPass /backend/ http://127.0.0.1:8080 ProxyPassReverse /backend/ http://127.0.0.1:8080 SSLEngine on SSLCertificateFile "/etc/ssl/certs/yourdomain.com.crt" SSLCertificateKeyFile "/etc/ssl/private/yourdomain.com.key" # SSLCertificateChainFile "/etc/ssl/certs/yourdomain.com.chain.pem" # this is commonly needed, but depends on your certificates # Add X-Forwarded-Proto header, the other headers are added automatically RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} </VirtualHost>
-
finally, restart apache:
sudo systemctl restart apache2
Forward Headers
When only https is available (i.e. no redirects from http configured in nginx), it is required to configure the RDepot API to use “forward headers”.
server:
forward-headers-strategy: native
Firewalling
If no reverse proxy is put in front of the RDepot API, the port that needs to be accessible to the outside world is the proxy port specified in the application.yaml
file (server.port
field) which, by default, will be port 8080. In principle, all other ports can be filtered in the firewall.
Sensitive Configuration
Configuration parameters that contain sensitive information and cannot be stored in the application.yaml
file can be provided differently. Note that best practice is to sufficiently protect application.yaml
with access rights, but in some cases (e.g. where the configuration is partly maintained via source control) it is useful to externalize sensitive configuration.
- Using a Java System property:
unset HISTFILE
java -jar rdepot-app-2.6.0.war -Ddb.password=abc
Use period as a separator to descend the parameter hierarchy in the application.yaml
file.
- Using environment variables:
unset HISTFILE
export DB_PASSWORD=abc
java -jar rdepot-app-2.6.0.war
Since most operating systems disallow period-separated names, the naming syntax differs slightly. To set the environment variable corresponding to a Java system property, use uppercase and replace all periods with underscores.
- A complete list of external configuration options can be found at https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Secure Dependencies
RDepot makes uses of software libraries such as the Spring Boot framework. It is important that these libraries are updated when they contain a security vulnerability. In order to know which libraries contain vulnerabilities we use the OWASP Dependency Check plugin for Maven.
Checking for vulnerable dependencies:
git clone https://github.com/openanalytics/RDepot
cd RDepot
mvn install -DskipTests
The last command first downloads the NVD CVE database (this may take some time).
Next, it generates a HTML report rdepot-app/target/dependency-check-report.html
that lists all known CVEs in the dependencies.