Thermostat/SecurityConsiderations

From IcedTea

Jump to: navigation, search

Thermostat Home

Contents

1 Thermostat Security Considerations

The preferred way to set up Thermostat securely is to use the web service (a.k.a. using https:// URLs). In order to use the web storage, we advise our users to deploy the Thermostat web application (web archive) in their favorite servlet container and connect agents and clients (gui/shell/other) to it rather than to mongodb directly. In fact, it is recommended to make mongodb:// not accessible to other components other than the web service. Note that the thermostat web archive has been tested with Jetty 8, Tomcat 6, Tomcat 7, JBoss AS 7 final.

1.1 Basic Security Related Features and Best Practices

What follows is list of features in Thermostat which were designed to make Thermostat more secure. Again, in this document we assume that thermostat is set up such that only http(s) style URLs get exposed to agents and clients.

  1. Reads and writes are prepared. Thermostat's PreparedStatement work very similar to Java's PreparedStatement.
  2. ACLs guard web storage servlet entry points (stop-gap).
  3. Thermostat queries get filtered based on ACLs.
  4. All channels should run on top of TLS with host-name-verification turned on.
  5. Securing third-party plug-ins
    1. Categories - think DB tables - which are being used at Thermostat runtime need to be registered at boot-time of the Thermostat web application endpoint.
    2. Plug-in supplied model classes and Categories should be supplied by a separate OSGi bundle. The web service will need to "know" them for JSON serialization purposes.
    3. DAOs and model classes should pass a security review prior installing the jar(s) in the thermostat web application. No unnecessary jars/classes should be on the webapp's classpath.
    4. Prepared statement string descriptors need to be registered with the web service at Thermostat web application boot-time.

1.2 Enabling TLS/SSL on all communication channels

For production deployments enabling transport layer security for thermostat communication channels is strongly advised. These channels are: client/agent => web service link, web service => backing storage link (mongodb) and the client => agent command-channel link.

1.2.1 Enabling SSL for mongodb communication

In order to enable SSL for mongodb communication, the mongod process needs to be configured to enable SSL on its default port, 27518 in the Thermostat case. In order to do this modify $THERMOSTAT_HOME/etc/db.properties as follows:

PORT=27518
BIND=127.0.0.1
SSL_ENABLE=true
SSL_PEM_FILE=/path/to/mongo-ssl.pem
SSL_KEY_PASSWORD=<mongod-server-key-passphrase>

See http://docs.mongodb.org/manual/administration/ssl/ for more information on how to create the mong-ssl-pem file.

(Re)Start thermostat storage:

$ ./bin/thermostat storage --start

Next, we need to communicate to agent, client and/or web service components that mongodb expects an SSL handshake before a connection can be made. In order to do so, we modify $THERMOSTAT_HOME/etc/ssl.properties as follows:

BACKING_STORAGE_CONNECTION_USE_SSL=true

The next time a connection to a mongodb:// URL is made from a client component, this channel will use SSL. A client component can be an agent, a client or web service.

1.2.2 Enabling SSL for Web Storage channels

Steps are as follows:

  1. Make sure your servlet container where the Thermostat web archive is deployed is configured to support https://
  2. Use https:// as the connection URL for both remaining thermostat components, agent and client.

See also section on using a custom keystore configuration.

1.2.3 Enabling SSL for Command channel

In order to enable SSL for the command channel an appropriate Thermostat keystore needs to be set up which contains the key material for the server component. I.e. the keystore needs to contain the certificate and the key for the agent to use. The key material which should be used by thermostat for the server component of the command channel must have the alias 'thermostat'. The file to this keystore is specified in $THERMOSTAT_HOME/etc/ssl.properties. It should look something like the following in order to enable SSL for the command channel:

KEYSTORE_FILE=/path/to/java/keystore/with/keymaterial.keystore
KEYSTORE_PASSWORD=secrit-password
COMMAND_CHANNEL_USE_SSL=true

Then make sure to restart the thermostat agents. The next time command channel interactions occur the communication will be encrypted.

1.3 Thermostat Access Control

See also: Access Control Development Page

The only supported secure configuration of using Thermostat is to use its Web service feature. In this setup the web service acts as storage endpoint for Thermostat clients and agents. This also means that thermostat will require some configuration (usually done by a system administrator) before it can be used meaningfully. By default, Thermostat's ACLs can be configured via two plain-text properties files located in $THERMOSTAT_HOME/etc/ These two files are thermostat-users.properties and thermostat-roles.properties. The former file defines valid thermostat users and their corresponding password. The latter file defines to which roles each user is a member of. By changing the ThermostatJAASDelegate configuration so that it points to a different Java JAAS login module, Thermostat may be configured to use a different means to log in users and assigning them roles. Using LDAP and an appropriate JAAS login module would be one such example.

An important property to ensure while configuring roles for agent and client users is to make sure that command channel roles are set up correctly. For example, agent users should only have the thermostat-cmdc-verify role while client users should only have the thermostat-cmdc-generate role. It is not recommended to grant any one agent or client user both roles.

With that said, Thermostat agent users will require a certain set of basic role memberships. At this point this set of roles for agent users is:

thermostat-prepare-statement
thermostat-write
thermostat-save-file
thermostat-purge
thermostat-register-category
thermostat-cmdc-verify,
thermostat-login
thermostat-realm

Similarly, client users will require the following set of basic role memberships (thermostat grant roles are explained below):

thermostat-realm
thermostat-login
thermostat-query
thermostat-prepare-statement
thermostat-cmdc-generate
thermostat-load-file
thermostat-register-category

In addition to the above roles, client users will likely need some of the following roles granted:

thermostat-agents-grant-read-agentId-*
thermostat-hosts-grant-read-hostname-*
thermostat-vms-grant-read-vmId-*
thermostat-vms-grant-read-username-*
thermostat-cmdc-grant-garbage-collect
thermostat-cmdc-grant-dump-heap
thermostat-cmdc-grant-thread-harvester
thermostat-cmdc-grant-killvm
thermostat-cmdc-grant-ping
thermostat-cmdc-grant-jmx-toggle-notifications
thermostat-files-grant-read-filename-*
thermostat-files-grant-write-filename-*
thermostat-grant-read-ALL

The first 4 roles grant read permission for a specific agent ID, hostname, vmId and username-as-which-the-vm-runs-as respectively. If the suffix is ALL it will grant the user permission to read ALL agent IDs, hostnames, vmIds and usernames, respectively. Example: Membership of role thermostat-agents-grant-read-agentId-ALL grants the user privileges to read all agent IDs (and records pertaining to any agent IDs) available in the DB. Membership of role thermostat-agents-grant-read-agentId-cb8c2172-489d-458f-896a-a9ad132eb421 would grant the user to see agent with ID cb8c2172-489d-458f-896a-a9ad132eb421 (and records pertaining to this agent ID). Agent, host, and both vms grant roles are required. If any of the 4 roles is missing the user will not be allowed to see any records.

thermostat-cmdc-grant-* roles grant a user to perform the given command-channel action. For example role thermostat-cmdc-grant-dump-heap grants a user to perform heap dumps via the agent on a remote machine.

If you want to grant a user read permissions across agents, hosts, vmids and vmusernames you can grant this user role thermostat-grant-read-ALL.

thermostat-files-grant-read-filename-* and thermostat-files-grant-write-filename-* roles grant a user to read and write the given filename respectively. For example role thermostat-files-grant-read-filename-foo grants a user to read filename foo from storage. For those roles corresponding -ALL roles exist as well to grant a user to read/write any file name from/to storage.

1.4 Configuration Reference

1.4.1 Properties for Use in Configuration Files

SSL_ENABLE
boolean If set to true thermostat storage will start the mongodb process with SSL enabled.
SSL_PEM_FILE
String Absolute path to a PEM encoded file containing the server key and certificate. See http://docs.mongodb.org/manual/administration/ssl/ for more information.
SSL_KEY_PASSWORD
String The password for the server key should it be encrypted. If the server key was not encrypted any non-empty password will work.
BACKING_STORAGE_CONNECTION_USE_SSL
boolean Whether or not to initiate an SSL handshake if a connection to a backing storage implementation is made. Applies to agent, client, web service.
KEYSTORE_FILE
String The absolute path to the Java keystore file. If present, key material in it will also be used during validation of self-signed certificates. E.g. if an agent tries to connect to a https:// URL and the server uses a self-signed certificate.
KEYSTORE_PASSWORD
String The password for the Java keystore as specified with KEYSTORE_FILE
COMMAND_CHANNEL_USE_SSL
boolean If set to true, command channel communication will be encrypted. Requires a valid KEYSTORE_FILE to be set up as well, since there would not be any key material which the agent could use during the SSL handshake.
DISABLE_HOSTNAME_VERIFICATION
boolean If set to true, host name verification will not be performed during SSL handshakes. In particular, during handshakes with the backing storage implementation or the command channel.

1.4.2 Thermostat ACL Roles Reference

thermostat-prepare-statement
Role granting a user to prepare statements. Required for reading/writing data.
thermostat-write
Role granting a user to write data to storage. "thermostat-purge" and "thermostat-save-file" are also write operations, but are not covered by this role. This role covers basic record writes such as inserts, updates and deletes.
thermostat-save-file
Role granting a user to save (a.k.a. write) files in storage.
thermostat-purge
Role granting a user to remove data from storage. This role should get granted scarcely.
thermostat-register-category
Role granting a user to register categories (a.k.a. tables) with storage. Required for reading/writing data.
thermostat-cmdc-verify
Role granting a user to verify a provided command-channel auth-token. This should usually be granted to agent users only.
thermostat-login
Role granting a user to log in. The web storage endpoint exposes a login endpoint which can be used for basic functionality testing of configured ACLs. Every thermostat user will need this role.
thermostat-realm
Role used for restricting the thermostat security realm. Any user who is a member of this role will be able to authenticate with the thermostat storage realm.
thermostat-query
Role granting a user to query thermostat storage. See thermostat-{agents,hosts,vms}-grant-read-* roles for more fine grained record read access control.
thermostat-cmdc-generate
Role granting a user command-channel authentication token generate privileges.
thermostat-load-file
Role granting a user to load files from storage.
thermostat-agents-grant-read-agentId-*
Role granting a user read permissions for records pertaining to specific agent IDs. This role is part of the default read filter chain. A special agent ID, ALL, that is role thermostat-agents-grant-read-agentId-ALL, grants a user to read records which was written by any agent.
thermostat-hosts-grant-read-hostname-*
Role granting a user read permissions for records pertaining to specific host names. This role is part of the default read filter chain. A special host name, ALL, that is role thermostat-hosts-grant-read-hostname-ALL, grants a user to read records pertaining to any host name.
thermostat-vms-grant-read-vmId-*
Role granting a user read permissions for records pertaining to specific JVM IDs. This role is part of the default read filter chain. A special JVM ID, ALL, that is role thermostat-vms-grant-read-vmId-ALL, grants a user to read records pertaining to any JVM ID.
thermostat-vms-grant-read-username-*
Role granting a user read permissions for records pertaining to specific JVMs. In particular, to grant a user to see all records of JVM which run as user tomcat, granting that user role thermostat-vms-grant-read-username-tomcat would be appropriate. This role is part of the default read filter chain. A special JVM username, ALL, that is role thermostat-vms-grant-read-username-ALL, grants a user to read records pertaining to any JVM username.
thermostat-grant-read-ALL
Role granting a user to read any records from storage. Granting a user this role essentially disables the read filter chain.
thermostat-cmdc-grant-garbage-collect
Role granting a user to remotely performing garbage collection actions for any JVM.
thermostat-cmdc-grant-dump-heap
Role granting a user permission for remotely performing heap dumps for any JVM.
thermostat-cmdc-grant-thread-harvester
Role granting a user permission for remotely toggling thread recording for any JVM.
thermostat-cmdc-grant-killvm
Role granting a user permission for remotely killing any JVM.
thermostat-cmdc-grant-ping
Role granting a user permission for pinging any agent. The ping action is useful for testing if the command channel is functional.
thermostat-cmdc-grant-jmx-toggle-notifications
Role granting a user permission for remotely toggling JMX notifications.
thermostat-cmdc-grant-profile-vm
Role granting a user permission for remotely starting/stopping JVM profiling runs.
thermostat-files-grant-read-filename-*
Role granting a user to read a file with the given filename from storage. That is, role thermostat-files-grant-read-filename-FOO, grants a user to read file, FOO from storage. The special role, thermostat-files-grant-read-filename-ALL permits a user to read any file from storage. Note that heap dump files are stored in storage as files.
thermostat-files-grant-write-filename-*
Role granting a user to write a file with the given file name from storage. That is, role thermostat-files-grant-write-filename-FOO, grants a user to write file, FOO to storage. The special role, thermostat-files-grant-write-filename-ALL permits a user to write any file to storage. Note that heap dump files are stored in storage as files.

1.5 Example Using Custom Thermostat Keystore + TLS on ALL Channels

This examples describes how you can set up Thermostat to work with your self-signed certificates (signed by your custom CA, henceforth called custom_ca). This example is a walk-through for generating this CA's certificate which we'll use for signing cerfificates for use by mongod and agent. Moreover we'll use openssl commands for the most part. Similar things can be achieved by using the keytool utility provided by the JVM. In fact, we'll use it for part of this walk-through ;-)

1.5.1 Setting up our Custom CA

First, we generate an unencrypted 4096 bit RSA key for our custom CA:

openssl genrsa -out custom_ca.key 4096

File custom_ca.key is the private key of this CA. THIS FILE NEEDS TO BE KEPT SECRET.

Next, we create an unsigned cerfificate for our custom CA. We'll use this as our "root" certificate in order to establish trust in certificates offered by the thermostat agent (for the server component of the command channel) and for the cert offered by mongod. This cert will be valid for 5 years.

openssl req -new -x509 -days 1826 -key custom_ca.key -out custom_ca.crt

File custom_ca.crt is the root certificate we'll use (together with the private key) for signing our agent/mongod server certificates. We'll also import this "trusted" certificate into our keystore so as to indicate that we trust certificates signed by our custom CA for thermostat purposes.

1.5.2 Creating a Key/Certificate for mongod

Mongod uses a PEM encoded file which has the server's private key in it as well as the server's certificate. Here are the steps to create them. If in doubt, use instructions found at: http://docs.mongodb.org/manual/administration/ssl/

Let's generate a 3DES encrypted server key first. Encrypting the server key is optional, of course.

openssl genrsa -des3 -out mongod_server.key 4096

This will prompt for a passphrase. Take note of this passphrase as you'll need to specify it in Thermostat's storage configuration, namely in $USER_THERMOSTAT_HOME/etc/db.properties. If you omit the '-des3' option the server key won't be encrypted and any non-empty passphrase in $THERMOSTAT_HOME/storage/db.properties will do in order for thermostat storage to work.

Next, we'll generate a certificate request, which we'll later sign with our custom_ca. Note that this will prompt for some information. What's most important is to set the common name (CN) appropriately, since thermostat uses host name verification by default. I.e. the common name should be set to "match" the host name/domain the mongod process will be ultimately running on. The following command will also prompt for the passphrase of mongod_server.key. You can leave challenge password and company name empty (it will ask about these last).

openssl req -new -key mongod_server.key -out mongod_server.csr

Next, we sign our certificate request mongod_server.csr with our custom CA. This will produce the mongod server certificate as output.

openssl x509 -req -days 730 -in mongod_server.csr -CA custom_ca.crt -CAkey custom_ca.key -CAcreateserial -CAserial custom_ca.signing.serial -out mongod_server.crt

File mongod_server.crt is the signed certificate, valid for two years. custom_ca.signing.serial a file containing the serial number of signing requests. It solely contains a number which gets incremented with each signing of a certificate request.

Finally, we concatenate the certificate and the server key and call the resulting file mongod_keymaterial.pem. We'll later specify the path to that file in $USER_THERMOSTAT_HOME/etc/db.properties.

cat mongod_server.crt mongod_server.key > mongod_keymaterial.pem

1.5.3 Creating a Java Keystore File for the Thermostat Agent

First, we'll generate a new agent server key, a corresponding signing request for a certificate and sign that request with our custom CA:

openssl genrsa -out agent1_server.key 4096
openssl req -new -key agent1_server.key -out agent1_server.csr
openssl x509 -req -days 730 -in agent1_server.csr -CA custom_ca.crt -CAkey custom_ca.key -CAserial custom_ca.signing.serial -out agent1_server.crt

File agent1_server.key is the server's key and agent1_server.crt the self-signed certificate which the thermostat agent will both use.

Next, we'll convert agent1_server.key and agent1_server.crt to a PKS12 keystore. This we subsequently convert to a Java keystore. Note: This will prompt for an export password. I.e. the keystore will be password protected. It is recommended to use a password of 6 characters or more since the keytool utility requires for keystore passwords to be at least 6 characters. Moreover, we suggest to use the same password for the pkcs12 keystore as for the Java keystore.

openssl pkcs12 -export -in agent1_server.crt -inkey agent1_server.key -out agent1_keystore.pkcs12

File agent1_keystore.pkcs12 is the converted keystore. We now use keytool in order to import this keystore and export it as a JKS formatted Java keystore:

keytool -importkeystore -srckeystore agent1_keystore.pkcs12 -destkeystore agent1.keystore -srcstoretype pkcs12

This produces file agent1.keystore which is the keystore file which we'll tell Thermostat about in $THERMOSTAT_HOME/etc/ssl.properties. Take note of the export password for this keystore file as it needs to be specified in that file as well. We can list the contents of this keystore file with:

keytool -list -v -keystore agent1.keystore

Note that this keystore only contains one entry and should contain output similar to the following:

[...]
Alias name: 1
Creation date: Apr 3, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
[...]

The important part is "Alias name: 1". In order for this key material to work properly with thermostat we need to change the alias to "thermostat". We can do this via the following command:

keytool -changealias -alias 1 -destalias thermostat -keystore agent1.keystore

With this file agent1.keystore is ready to be used with thermostat.

1.5.4 Adding custom_ca.crt to the Thermostat Keystore File

In order to tell Thermostat that certificates signed by our custom CA are trusted, we'll import the CA's certificate into the thermostat keystore file. In this case we use the already existent agent1.keystore file as produced earlier. Alternatively, the certificate can be imported into the cacerts keystore file provided by the JVM.

keytool -import -alias weTrustCustomCA -file custom_ca.crt -keystore agent1.keystore

1.5.5 Configuring Thermostat

For security considerations it is recommended to service mongodb storage from one host, have thermostat web storage run on another host with fast interconnect to the mongodb host, and thermostat agents/clients run on yet other hosts.

Since we've already created mongod_keymaterial.pem and agent1.keystore files in earlier sections, all that's left to do is to tell Thermostat about these files and to enable TLS on all channels. In order to do so we need to modify db.properties and ssl.properties files. The $USER_THERMOSTAT_HOME/etc/db.properties file looks as follows:

PORT=27518
BIND=mongod_server.example.com
SSL_ENABLE=true
SSL_PEM_FILE=/path/to/mongod_keymaterial.pem
SSL_KEY_PASSWORD=<mongod-server-key-passphrase-as-used-earlier>

The bind address should be a host name matching the common name as specified in the section above when we created it. Otherwise host name verification will fail when attempting to connect to mongodb storage. The value for SSL_KEY_PASSWORD is the passphrase used for encrypting the server key (or any non-empty string for keys which aren't encrypted).

Next, we'll need to configure the Thermostat web service so as to use appropriate connection URLs. The web.xml file of the thermostat webapp (a.k.a. web storage/service) should contain the following:

 <!-- ... -->
 <!-- Username to use for connecting to mongod storage -->
 <init-param>
   <param-name>storage.username</param-name>
   <param-value>thermostat-webservice1</param-value>
 </init-param>
 <!-- Password to use for connecting to mongod storage
      implementation -->
 <init-param>
   <param-name>storage.password</param-name>
   <param-value>supersecrit</param-value>
 </init-param>
 <init-param>
   <param-name>storage.endpoint</param-name>
   <!-- host name should match what was used for the SSL certificate -->
   <param-value>mongodb://mongod_server.example.com:27518</param-value>
 </init-param>
 <!-- ... -->
 

Then, we need to configure $USER_THERMOSTAT_HOME/etc/agent.properties so as to use https://. Again, the host name for the webservice needs to match what's the CN in the certificate the webservice is using:

# The listen address needs to match the common name of the
# certificate created above.
CONFIG_LISTEN_ADDRESS=agent1.example.com:12000
DB_URL=https://webservice1.example.com:8443/thermostat/storage

Note that the config listen address is the address/port combination which is going to be used for Thermostat command channel traffic.

Finally, in $USER_THERMOSTAT_HOME/etc/ssl.properties we have the following configuration:

KEYSTORE_FILE=/path/to/agent1.keystore
KEYSTORE_PASSWORD=my-secrit-password
COMMAND_CHANNEL_USE_SSL=true
BACKING_STORAGE_CONNECTION_USE_SSL=true

That's it. In this configuration all Thermostat communication channels will use SSL. Moreover, since agent1.keystore contains the certificate for our custom CA, it will be used in order to establish that certificates used by mongod, by the agent and by the webservice are trusted (yet self-signed).

Personal tools