Issue
I apologize if this is too similar to many other questions asked; I searched and reviewed multiple solutions suggested, but there doesn't seem to be a general solution to this type of problem -- the same problem in different environments, judging by the answered questions, seems to entail very different solutions.
I have built several Ruby client scripts that collect information from various servers in my network and inject said information into a MySQL database. The Ruby scripts must authenticate to those servers as users, thus they need authentication credentials to connect. The connections in question are from the Ruby client, to the receiving server, and via (respectively):
SOAP (via the savon gem):
soap_client = Savon.client(wsdl: '[URL]')
login_response = soap_client.call(:login, message: { 'userName' => [SOAP CLIENT USERNAME], 'password' => [SOAP CLIENT PASSWORD] })
MySQL (via the mysql2 gem):
@mysql_client = Mysql2::Client.new(:host => [DATABASE HOSTNAME], :username => [DATABASE USERNAME], :password => [DATABASE PASSWORD], :database => [DATABASE NAME])
HTTPS (via the net/https gem):
OpenSSL::PKey::RSA.new(pem,"[KEY DECRYPTION PASSWORD]")
The HTTPS client doesn't need a username/password to authenticate to the HTTPS server. It requires a certificate with key, and the password stored in the source code is necessary to decrypt the key. I can store the key in cleartext, thus eliminating this password from the source code, but then the security issue becomes how to secure the cleartext key file.
The problem I'm trying to solve is that I have cleartext passwords stored in my source code. I can store the passwords in an encrypted text file, then decrypt that file at run time, but then I'm back to a similar problem -- how do I securely store the decryption keys?
The environment is:
- CentOS Linux 7.6.1810
- ruby 2.4.2
Thank you for reading, and please let me know if my question requires further clarity!
Solution
This is how we treat secret information that is required by scripts:
Source Control:
- We never store sensitive information in the source code.
Development:
- All sensitive information that is needed by any script is coming from environment variables (so, in Ruby:
some_password = ENV['SOME_PASSWORD']
) - All the developers have direnv installed, and they each have a
.envrc
file in the project folder that sets up their personal passwords and other secrets. - We make sure that
.envrc
is never committed to source control by adding a global gitignore to.envrc
(global = not per project, but per environment).
Testing / CI:
- All CI systems support entering secret environment variables, so this is how it is solved for this use case.
Production:
- Depends on your production infrastructure, these environment variables and secrets are also entered at deploy time or stored in the secrets facility provided by the environment.
Answered By - DannyB