Introduction to rcreds

Rick Saporta, Mike Reca

2017-10-26

Securely Incorporate Login Credentials Into R Scripts

There are two main functions in rcreds * WRITE functions: write_credentials_to_file() and the database version write_db_credentials_to_file() * READ functions: read_credentials_from_file() and the database version read_db_credentials_from_file()

rcreds allows for a secure way to code scripts that require sensitive inputs such as login credentials to databases, APIs, or other systems. Users can securely write their credentials and other sensitive information to an encrypted file on disk, and then later read those credentials back into R.

The main concept has been adopted from https://github.com/sdoyen/r_password_crypt/blob/master/crypt.R

Overview

Many scripts require login to other systems. The most common example is accessing data from a database.

Most comonly, a user will simply hardcode their credentials right into their code. Avoiding this practice generally involves re-inputting passwords over and over again or nesting scripts within other scripts when scheduling tasks.

We will assume that, by nature of searching out such a package we can avoid here the discussion of the why to implement a different approach (even when “I am the only one who will be using or accessing this”) and simply move on to the how to use.

Note on Documentation:

Generally, a user will save their credentials to a folder in ~/.rcreds We do not want to include that as the default folder in this vignette, as the vignette examples will write meaningless examples to the users home directory. We will use CREDS_PARENT_FOLDER in place of ~/.rcreds.

Usage

Let’s assume you have some function which requires the use of sensitive inputs.

The rcreds approach would be to write the credentials to an encrypted file on disk and then read and decrypt them when needed.

Initial Setup

The user needs to tell rcreds where files should be written to and read from. This can go in your ~/.Rprofile file. Setting the default rcreds folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/credential_files’

## Warning in set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER,
## "db_credential_files"), : Folder '/var/folders/hd/
## 7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/db_credential_files' does not
## exist

Setting the default rcreds db folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/db_credential_files’ Setting the default rcreds key folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/key_files’

Saving Credentials

One time, write to disk Setting the default rcreds folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/credential_files’

## Warning in
## rcreds::set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER, :
## Folder '/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/
## db_credential_files' does not exist

Setting the default rcreds db folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/db_credential_files’ Setting the default rcreds key folder to ‘/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/key_files’

## Creating new key with bytes = 32  and  depth = 8.  seed was not set.
## existing file moved to:  '/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/credential_files/zArchived/for_app123_login.credentials.creds.zarchived_20171026_150414'
## credentials written to file  "/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/credential_files/for_app123_login.credentials.creds"
## key file written to "/var/folders/hd/7sy3m1d139n062t7x4k58f5c0000gn/T//RtmpnSo8ZZ/key_files/.crypt_key.rds"

Then in a script that needs to use the credentials, read from disk and use the list elements. $username [1] “cosmo”

$password [1] “too many secrets”

## some_login_function() received username = 'cosmo' and password = 'too many secrets' and separate_param = 'plain example'
##    (obviously wouldn't normally output like this)

[1] TRUE

## some_login_function() received username = 'cosmo' and password = 'too many secrets' and separate_param = 'do.call example'
##    (obviously wouldn't normally output like this)

[1] TRUE

Troubleshooting

Since we are writing to and reading from files, the user under which R is running must have appropriate permissions to both: the file, and the folder in which the file is located.

When this is not the case you will receive an error that will (usually) end with probable reason 'Permission denied' For example:

Error in gzfile(file, mode) : cannot open the connection
In addition: Warning message:
In gzfile(file, mode) :
  cannot open compressed file '/PATH/TO/FILE/file_name.crypt_key.rds', probable reason 'Permission denied'

NOTE: You will often see this when you create the key or creds file with one user and then try to use the file with a different user. eg, did you use sudo R to create the files?

RESOLUTION: Please ensure that your user has permissions on the folder and file. (On Mac OSX and Linux systems, use chown and/or chmod). Stackoverflow has several questions and answers on this topic.

Issues & Feedback

Please report any issues or bugs at the package’s github page

All pull requests will be gladly considered.

For tips on pull requests, checkout this helpful blog post by codeinthehole