Abstract/hide username/password in ruby script

I have a script that will be talking to Windows. Based on what we are
doing, it looks like I need to hard code a windows domain service
account into a ruby script so it can communicate with the destination
windows servers.

However, this service account will be a local admin on those boxes, so
we can’t store it in plain text in the ruby script. How can I
hide/abstract that account information and still be able to pass it via
the script?

My personal approach to user password management in Windows scripts is
an encrypted registry key which I can query for the password. I use
crypt19 for the basic stuff. crypt19-rb | RubyGems.org | your community gem host

Would environment variables work?

I should have been more specific. The call will be coming from a Linux
server. So registry is out. Environment variables might be the way.

I’m also still looking at Kerberos but failing miserably.

On 10/10/2013 08:26 AM, Charlie B. wrote:

I have a script that will be talking to Windows. Based on what we are
doing, it looks like I need to hard code a windows domain service
account into a ruby script so it can communicate with the destination
windows servers.

However, this service account will be a local admin on those boxes, so
we can’t store it in plain text in the ruby script. How can I
hide/abstract that account information and still be able to pass it via
the script?
This really isn’t a problem unique to Ruby or anything. The solutions
available will depend on how important you decide it is to protect the
credentials and how the script is executed.

Easy

If you’re not too paranoid, you could just base64 encode the credential
strings within the script and have the script decode those strings when
necessary. This would protect the credentials from casual or accidental
viewing by a human reading the script, but obviously, they would be
right there if someone really wanted them. Any kind of encoding scheme
would have this limitation, not just base64 encoding.

You could further lock things down by removing read permissions from the
script file so that someone would need to be an administrator to see it
on the system that will run it. However, this doesn’t address how to
protect the script contents in whatever development environment you use
for writing your script.

Safer and Flexible

The next level up would be to put the credentials within a file that the
script can find and read. Again, they could be encoded in some way to
avoid accidental revelation to humans with all the same caveats as
putting the credentials within the script itself. The advantage here is
that now the credentials can be changed more easily since you won’t have
to change the script. You can also keep the credentials secret from the
development environment of the script and even use different credentials
in that development environment while testing.

The only problem is that the credentials file will need to be readable
only by the user running the script. Anyone able to run things as that
user or an administrator would be able to read the credentials as well.

Environment Variables

Jason’s suggestion of using an environment variable isn’t bad. The only
problem is that the environment variable must be populated somehow. If
the system needs to be self-executing, for instance a cron job starts
the script periodically, then the credentials must still be in a file
somewhere on disk so that the automation can load them into the
environment variable given to the script. The nice thing is that the
automation likely runs as an administrator, so the file could be
readable only by that account rather than the user running the script.

If your script is executed via some remote process however, such as
Rundeck or something similar, then using an environment variable is
probably the best solution. The remote system would still need a way to
protect the credentials for its own uses, but the system running the
script wouldn’t have to store the credentials itself at all.

The risk in either case is that the script’s environment while running
may be readable by someone, such as an administrator, so encoding the
credentials may still be a good idea if you’re very paranoid.

The Registry

Joel’s suggestion of using the registry isn’t bad either if your script
runs on Windows, but anyone with knowledge of how your script gets the
credentials could still get them the same way the script would, just as
with the file-based options. Think of the registry as just another
filesystem in Windows. The only real advantage is that people are less
likely to stumble upon a registry key than a file.

Safest but Inconvenient

In the end, the computer must have the raw credentials somehow. You can
obfuscate them all you want, but you can’t absolutely protect them if
you want the script to run in a fully automatic context. If you’re
paranoid enough, the only really safe option is to always require human
interaction to enter the credentials when the script needs them. Watch
out for key loggers! :wink:

-Jeremy

On 10/10/2013 11:03 AM, Charlie B. wrote:

I should have been more specific. The call will be coming from a Linux
server. So registry is out. Environment variables might be the way.

I’m also still looking at Kerberos but failing miserably.

Using Kerberos would still require proof of identity initially. Unless
you have some sort of hardware-based solution, this will likely still
require a username and password to get the initial ticket. That ticket
could be cached for a limited period of time, but human intervention
would still be required to issue a new ticket if automatic renewal of
the existing ticket was not performed.

Furthermore, as long as the cached ticket is valid, the ticket could be
used by others with access to it, just like the file-based approach for
credentials storage. At least the ticket doesn’t expose the original
credentials though.

-Jeremy