Can I use environment variables in openhab.cfg?

I would prefer not to put passwords for such things as mqtt and mysql in openhab.cfg as that file is source controlled and therefore may be visible to too large an audience. I would prefer to use environment variables for this. Is there a way to do this?

Alternatively is there a better solution to the problem?

Colin

This is a good question and I agree it is a problem.

As far as I know the openhab.conf file reader will not use environment variables. Here are a few ideas though that you could use:

  • Don’t source control openhab.cfg or use your own source control instead of something public like github. This is actually what I do. I have a git server that I push all my changes to which gets backed up.

  • If you are on OH 2 my understanding that the monolithic config file has been replaced with one file per binding so you could just not check in the MQTT binding config but check in the rest.

  • Modify the start script or openhab.service to replace or add the lines that have the username and password with the values in the environment to openhab.cfg when openHAB starts and remove them when openhab stops. You can use sed to accomplish this fairly easily and if you put it into openhab.service you can make the command be a PreExecStart line under [Service].

  • Don’t authenticate. You can enable TLS/SSL to encrypt the traffic but not require the broker to authenticate your client (at least in Mosquitto). Just change the mqtt:broker:url=ssl://<ip>:<port> instead of tcp and comment out user and password. If you are running your broker on your local network and it isn’t exposed to the Internet this is relatively low risk.

You can further protect yourself by running the broker in a VM or a Docker container so even if someone did get in somehow and compromise the broker they have limited access to mess with other stuff, or at least it is more difficult to do so.

I think that clients on different listeners can post/subscribe to the same topics so, in Mosquitto at least, you can set the default listener to only allow connections from localhost (assuming OH and the broker are running on the same host) and not require username and password for those connections and create another listener which does require username and password and TLS for clients that are not localhost. Then you can remove the username and password from openhab.cfg yet be relatively safe because only clients on the localhost can communicate without authentication. Thus, if someone is able to communicate to Mosquitto without authentication, they are already on your machine and you have bigger problems.

If you Dockerize OH and the Broker you can further lock the unauthenticated port down by making it so ONLY OH can communicate to the listener that doesn’t require authentication through Docker’s internal network.

I’m sure there are other approaches you can use (e.g. set up a firewall that only allows OH’s IP to communicate to the Broker’s port) where you can safely and securely allow connections that are not authenticated. However, if you add ACLs to your Mosquitto conf I’m not sure how that would work with unauthenticated users.

Thanks for the detailed reply

That is a great idea, I will get onto that shortly and will post back the script when I have it working. I will try to make it general purpose. I wonder whether I can safely assume that a string of the form $(something) will not not appear in the file for any other reason.

Thanks.

bitbucket.org allows private repos from free accounts, so if you are satisfied with their security practices, it might be an easy option. Setting up a private git server would also work if you are interested in having remote repositories completely under your control.

I already use a private git server, but even within an organisation it is often not desirable to have credentials visible to all. If, for example, contractors are used it may be desirable that they do not have access to such information. For me it is a matter of principle that credentials should not be under source control.

There are other reasons for wanting to use environment vars in the cfg file. The url for an mqtt broker, for example, may vary dependant on which machine the mqtt client is being run on. In particular whether it is in the local network or across the internet.

That seems like a very sound practice. Perhaps openHAB could have a credential vault service for all the bits of authentication data it comes to rely on, and a generalized mechanism to query the vault for credentials after you unlock the vault with a passphrase? Addons could slowly migrate to querying the vault instead of reading plaintext config data. Then you could put your vault under source control with no worry about unauthorized use?

It is your file and presumably you are the only one editing it so you should be able to control for this yourself. I don’t thing anything like this is a safe assumption as each part of the config is specific to each binding and I don’t think there is any way to assume that no bindings will ever use that.

[rant]
As a security guy I agree with the sentiment. However applying rules of thumb which make sense in an organization do not always make sense when applied when working alone. What is the real risk here is I have a personal and private git repo and I put credentials in there? How is that any different from putting the credentials in an environment variable, service file, or start script?

In general security practices are things which get in the way and make things harder for you to do your job, so there must be a real risk with a real likelihood that the risk could be realized to justify the security practice. So, if you are working on OH with other developers or in an organization then this principle is justified. If not I’d argue this practice provides absolutely zero real value.
[end rant]

I’ve actually seen programs that do this using db4o. OH would have a key or a cert that lets it unlock the encrypted db4o database where authentication info is stored. You can then check in the db but not the key. I can’t remember if the encryption was handled by db4o or the using app though but it should take much to find out what db4o offers in this regard.

But even if OH just kept the credentials in separate file one could easily exclude that file from the checkin but preserve everything else.

Though I would propose that user/password info is not the only sensitive information that could be in the config. For example, Mqttitude and weather binding locations are things that someone might want to keep private. It might be nice to be able to protect that info as well.

If you are really paranoid though, having ANY of your HA system posted somewhere publically could be a problem, particularly for folks who are using openHAB as a security system.

Maybe worth starting a discussion over at ESH?

One last thought from me: you could only check into source control a configurations-src directory with %VARIABLES% embedded, and also a bash script or similar that runs these template config files through sed, awk or some other macro replacement language, putting the output in the configurations directory for the runtime to use. But as Rich said, you’ve got to keep the sensitive values somewhere, and not all live in config files, so there may be little achieved by doing that.