Protect user credentials when connecting R to databases using JDBC / ODBC drivers

I usually connect to a database with R using the JDBC / ODBC driver. A typical code would look like

library(RJDBC) vDriver = JDBC(driverClass="com.vertica.jdbc.Driver", classPath="/home/Drivers/vertica-jdbc-7.0.1-0.jar") vertica = dbConnect(vDriver, "jdbc:vertica://servername:5433/db", "username", "password") 

I would like others to access db using my credentials, but I want to protect my username and password. Therefore, I plan to save the above script as the file "Connections.r" and ask users to specify this file.

 source("/opt/mount1/Connections.r") 

If I give only permissions to Connections.r, others cannot specify the file

 chmod 710 Connections.r 

Only if I give read and execute permission does R allow users to run it. If I give read permission, my credentials will be disclosed. In any case, can we solve this problem by protecting user credentials?

+5
source share
4 answers

If you will not confuse your credentials deeply by creating a function or Rcpp package that performs the initial JDBC connection (which will not be trivial), one of your only easier obfuscation mechanisms is to store your credentials in a file and have R5 w> 70> read them from the file, use them in the call, and their rm from the environment immediately after this call. This will still show them, but not directly.

Another way, since users have their own logins for RStudio Server, is to use the new secure package (we, some people, run it through it), add user keys and save your credentials in encrypted form, but their R-W370 automatically decrypts them. You still need to make rm any variables that you use, as they will be part of the environment if you don't.

The last way, since you give them access to the data anyway, is to use a separate set of credentials (as you formulated the question, apparently use your credentials for this), which work only in read mode - only for databases and the tables needed for these analyzes. Thus, it does not matter if leaks occur, since there is nothing "bad" that can be done with them.

Ultimately, I'm just as embarrassed as to why you can't just configure read-only users on the database side? This is what role-based access controls are based on. This is administrative work, but it is absolutely the right thing.

+3
source

You want to give someone access, but can you see your credentials? This is not possible in this case. If my code can read the file, I can see everything in the file.

Make more accounts on the SQL server. Or make one guest account. But you are trying to solve the problem that account management solves.

+2
source

Credentials sent as command arguments ? Here is an example of how this can be done:

 suppressPackageStartupMessages(library("argparse")) # create parser object parser <- ArgumentParser() # specify our desired options # by default ArgumentParser will add an help option parser$add_argument("-v", "--verbose", action="store_true", default=TRUE, help="Print extra output [default]") parser$add_argument("-q", "--quietly", action="store_false", dest="verbose", help="Print little output") parser$add_argument("-c", "--count", type="integer", default=5, help="Number of random normals to generate [default %(default)s]", metavar="number") parser$add_argument("--generator", default="rnorm", help = "Function to generate random deviates [default \"%(default)s\"]") parser$add_argument("--mean", default=0, type="double", help="Mean if generator == \"rnorm\" [default %(default)s]") parser$add_argument("--sd", default=1, type="double", metavar="standard deviation", help="Standard deviation if generator == \"rnorm\" [default %(default)s]") # get command line options, if help option encountered print help and exit, # otherwise if options not found on command line then set defaults, args <- parser$parse_args() # print some progress messages to stderr if "quietly" wasn't requested if ( args$verbose ) { write("writing some verbose output to standard error...\n", stderr()) } # do some operations based on user input if( args$generator == "rnorm") { cat(paste(rnorm(args$count, mean=args$mean, sd=args$sd), collapse="\n")) } else { cat(paste(do.call(args$generator, list(args$count)), collapse="\n")) } cat("\n") 

Run example (without parameters):

 usage: example.R [-h] [-v] [-q] [-c number] [--generator GENERATOR] [--mean MEAN] [--sd standard deviation] optional arguments: -h, --help show this help message and exit -v, --verbose Print extra output [default] -q, --quietly Print little output -c number, --count number Number of random normals to generate [default 5] --generator GENERATOR Function to generate random deviates [default "rnorm"] --mean MEAN Mean if generator == "rnorm" [default 0] --sd standard deviation Standard deviation if generator == "rnorm" [default 1] 

The package was apparently inspired by the python package with the same name, so looking there might also be useful.

Looking at my code, I would probably rewrite it as follows:

 library(RJDBC) library(argparse) args <- ArgumentParser() args$add_argument('--driver', dest='driver', default="com.vertica.jdbc.Driver") args$add_argument('--classPath', dest='classPath', default="/home/Drivers/vertica-jdbc-7.0.1-0.jar") args$add_argument('--url', dest='url', default="jdbc:vertica://servername:5433/db") args$add_argument('--user', dest='user', default='username') args$add_argument('--password', dest='password', default='password') parser <- args$parse_args vDriver <- JDBC(driverClass=parser$driver, parser$classPath) vertica <- dbConnect(vDriver, parser$url, parser$user , parser$password) # continue here 
+1
source

Yana, it seems strange that you are ready to allow users to connect via R, but nothing else. How does this hide anything from them?

I don’t understand why you are not satisfied with a guest account that has specific SELECT access only to certain tables (or even views)?

+1
source

Source: https://habr.com/ru/post/1204285/


All Articles