Introduction to rcreds

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.

some_login_function <- function(username, password, separate_param) {
     ## does something with username/password
     ## ... 

      message(sprintf("some_login_function() received username = '%s' and password = '%s' and separate_param = '%s'\n   (obviously wouldn't normally output like this)", username, password, separate_param))

     return(TRUE)
}

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.

## reminder, tempdir() is only for vignette. Normally use:
#  CREDS_PARENT_FOLDER <- "~/.rcreds"
CREDS_PARENT_FOLDER <- tempdir()


library(rcreds)

set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER, "credential_files"))
set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER, "db_credential_files"), DB=TRUE)
set_default_rcreds_key_folder(folder = file.path(CREDS_PARENT_FOLDER, "key_files"))

Saving Credentials

One time, write to disk

## reminder, tempdir() is only for vignette. Normally use:
#  CREDS_PARENT_FOLDER <- "~/.rcreds"
CREDS_PARENT_FOLDER <- tempdir()

## in your .Rprofile, you should set the default folders.
## Replace CREDS_PARENT_FOLDER with correct folder, such as "~/.rcreds"
rcreds::set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER, "credential_files"))
rcreds::set_default_rcreds_folder(file.path(CREDS_PARENT_FOLDER, "db_credential_files"), DB=TRUE)
rcreds::set_default_rcreds_key_folder(folder=file.path(CREDS_PARENT_FOLDER, "key_files"))

library(rcreds)

creds_info <- "for_app123_login" ## some description that will be part of the filename
key_object <- create_key(bytes=32, depth=8, verbose=TRUE)

## Save Credentials
write_credentials_to_file(username="cosmo", password="too many secrets", key=key_object, info.file_name = creds_info, verbose=TRUE)

## Save key file to a different location. 
save_key(key=key_object, zArchive_existing=FALSE, overwrite_existing=TRUE, verbose=TRUE)

Then in a script that needs to use the credentials, read from disk and use the list elements.

## reminder, tempdir() is only for vignette. Normally use:
#  CREDS_PARENT_FOLDER <- "~/.rcreds"
CREDS_PARENT_FOLDER <- tempdir()

key_file   <- file.path(CREDS_PARENT_FOLDER, "key_files", ".crypt_key.rds")
creds_file <- file.path(CREDS_PARENT_FOLDER, "credential_files", "for_app123_login.credentials.creds")


creds <- read_credentials_from_file(file_full_path=creds_file, key=key_file)

## SHOWING CONTENTS FOR DEMO PURPOSES. NORMALLY DON'T DO THIS
print(creds)

## Use the credentials by refering to the elements by name
some_login_function(username = creds$username, password=creds$password, separate_param="plain example")

## altenatively can use do.call
do.call(some_login_function, c(creds, list(separate_param="do.call example")))

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



Try the rcreds package in your browser

Any scripts or data that you put into this service are public.

rcreds documentation built on May 2, 2019, 9:25 a.m.