We have a masked variable for example called SECRET_JAMES_BOND with value /vault/abc. During the pipeline execution, the log shows as [MASKED]. When we changed the value to ABCDE, the value was shown. Even we don't change it, we can easily get the value from the log if we perform SECRET_JAMES_BOND = $(echo $SECRET_JAMES_BOND) | base64). By echoing the base64 value, it will display on the UI because the value has changed. When we copy the encoded base64 string and decode it, we get the actual secret. How can we prevent a masked variable from echoing if its value has been changed ? Shouldn't masked variables show [MASKED] even the value is different from its original value ?
How can we prevent a masked variable from echoing if its value has been changed
In short: you can't if someone with access is determined to do so.
Masking is not meant to prevent developers with access to control CI steps from revealing secrets through jobs. It is meant to prevent disclosure by accident. There are endless ways that a value could be exfiltrated through the job output it would be impossible to cover them all.
If you wanted to prevent the base64 representation of the secret from being shown, you can register that value as another masked variable, but it must be done in advance.
Shouldn't masked variables show [MASKED] even the value is different from its original value ?
Good arguments could be made that GitLab should mask some common variations of masked variables, such as base64, url-encoded, backwards, etc. Other CI services (Travis CI for example) do this.
However, this would still be ONLY for the purposes of accidental disclosure.
For example, another way I've seen developers accidentally reveal secrets is by using curl with the -v flag.
script:
- curl -v https://myusername:${SECRET_JAMES_BOND}#myhost.example.com/secret
In the above example, the output of curl will show (in part) an output like:
> Authorization: Basic bXl1c2VybmFtZTpzZWNyZXQ=
So, if GitLab also masked base64 variations of a password, it would have prevented this accidental disclosure.
But like I mentioned, there's endless ways to output a secret: url-encoding, Caesar cipher, rot-N (rot16, rot24, rot32, etc) or even custom ways like just echoing each character one line at a time, potentially in reverse order.
So, really, you can only realistically prevent accidents, not malicious exfiltration by a user with access to execute code in a job.
I'd like to prepare a simple script for connecting to some VPN network. The password to the network consists of two elements: pretty complicated pass + randomized token. I don't want to remember this password but store it encrypted in some secure directory. Now, the script I need should ask me for a passphrase and some token, read decrypt a pass from a file and run some commands. All those are pretty easy except one thing: is it possible to decrypt a file to a variable instead of file? I mean I'd like to get something like
PASS=`mdecrypt password.nc`
but as far as I know mdecrypt generates a file as a result instead of returning value. I know I could run something like
`mdecrypt password.nc`
PASS=`cat password`
`unlink password`
but is there some easier (one liner) solution?
uset the -F option
-F Force output on standard output or input from stdin if that is a
terminal. By default mcrypt will not output encrypted data to
terminal
Usually I connect to a database with R using 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 the db using my credentials but I want to protect my username and password. So I plan save the above script as a "Connections.r" file and ask users to source this file.
source("/opt/mount1/Connections.r")
If I give execute only permission to Connections.r others cannot source the file
chmod 710 Connections.r
Only if I give read and execute permission R lets users to source it. If I give the read permission my credentials will be exposed. Is there anyways we could solve this by protecting user credentials?
Unless you were to deeply obfuscate your credentials by making an Rcpp function or package that does the initial JDBC connection (which won't be trivial) one of your only lighter obfuscation mechanisms is to store your credentials in a file and have your sourced R script read them from the file, use them in the call and them rm them from the environment right after that call. That will still expose them, but not directly.
One other way, since the users have their own logins to RStudio Server, is to use Hadley's new secure package (a few of us sec folks are running it through it's paces), add the user keys and have your credentials stored encrypted but have your sourced R script auto-decrypt them. You'll still need to do the rm of any variables you use since they'll be part of environment if you don't.
A final way, since you're giving them access to the data anyway, is to use a separate set of credentials (the way you phrased the question it seems you're using your credentials for this) that only work in read-only mode to the databases & tables required for these analyses. That way, it doesn't matter if the creds leak since there's nothing "bad" that can be done with them.
Ultimately, I'm as confused as to why you can't just setup the users with read only permissions on the database side? That's what role-based access controls are for. It's administrative work, but it's absolutely the right thing to do.
Do you want to give someone access, but not have them be able to see your credentials? That's not possible in this case. If my code can read a file, I can see everything in the file.
Make more accounts on the SQL server. Or make one guest account. But you're trying to solve the problem that account management solves.
Have the credentials sent as command arguments? Here's an example of how one would do that:
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")
Sample run (no 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 of the same name, so looking there may also be useful.
Looking at your code, I'd 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
Jana, it seems odd that you are willing to let the users connect via R but not in any other way. How is that obscuring anything from them?
I don't understand why you would not be satisfied with a guest account that has specific SELECT-only access to certain tables (or even views)?
I need to take the command value from file and execute the command,
in my scenario I am rinning this commands ON Terminal
uci set wireless.#wifi-iface[0].encryption=psk
uci set wireless.#wifi-iface[0].key="your_password"
uci commit wireless
wifi
but i need to pass the value of key i.e "your_password" dynamically i.e from file or from variable where I can store the value taken from python code.
so please tell me how can I pass this value dynamically and execute this commands successfully.
Thanks in Advance!!
Just use shell variable expansion, like this:
password='MYPASSWORD'
uci set wireless.#wifi-iface[0].key="$password"
The important thing here is the dollar sign in $password: which signals the shell that what you want is not the string password itself, but the value the variable password (defined before) points to.
If you want to read password's value from a file instead of defining it in inline, two approaches are available.
First approach
Create a configuration file (e.g. myscript.conf) and source it. E.g., myscript.conf will contain
password='MYPASSWORD`
and myscript will contain
source myscript.conf
uci set wireless.#wifi-iface[0].encryption=psk
uci set wireless.#wifi-iface[0].key="$password"
uci commit wireless
wifi
Be aware that this approach might have security flaws (everything you write into myscript.conf gets actually executed in the shell).
Second approach
Create a password file and just read its content. E.g., the password file will look like this
MYPASSWORD
I.e., it will contain just the password. On the other hand, myscript will be
password=$(cat password_file)
uci set wireless.#wifi-iface[0].encryption=psk
uci set wireless.#wifi-iface[0].key="$password"
uci commit wireless
wifi
Here we read the content of password_file by using cat and storing it into the variable password.
RSA.gen_key function always asks for password when it's used to generate keys. Is there a way to feed it the password from the python code instead of typing it manually?
The only time it asks for a password is if you try to save a key and you choose to use a cipher. Just pass "cipher=None" as an argument.
For example:
key=RSA.gen_key(2048, 65537)
key.save_pem('./privkey',cipher=None)
But as Heikki said, key generation requires no password. Only saving if you choose to use encryption.
It does not ask for passwords as far as I know:
In [1]: from M2Crypto import RSA
In [2]: r=RSA.gen_key(1024, 65537)
..++++++
.......................................++++++
In [3]:
If you don't like that output, you can provide a custom callback function. See documentation and tests.
If you mean that it asks for passphrase when calling save_pem() method, you are right: the default will ask for password. But again, you can provide your own callback that provides the password programmatically.