Protect the password when using Mysql in an unattended bash-script - mysql

I am writing a bash script (for a cron job) that uses mysql:
mysql -uusername -ppassword -e 'something;'
I am looking for a good way to keep the password handy for use in the script, but in a manner that will also keep this information secure from other users on that system. Users who could use ps -ef and users who might read text files...
So how can I safeguard passwords that will be used in an automated script on Linux?

Put all the settings in an option file. You can use your default ~/.my.cnf file, or you can specify an alternate file using --defaults-file==filename. See the documentation 4.2.3.4. Command-Line Options that Affect Option-File Handling
The option file contains default settings for mysql commands. You can put the following in it, for example.
[mysql]
user=username
password=password
database=yourdb
Make the option file readable only by you, so other users can't see your password.

This is an updated answer for users of MySQL 5.6.6+
As documented in 4.6.6 mysql_config_editor — MySQL Configuration Utility, there is now a more secure way to store mySQL passwords, that does not store clear text passwords in a local configuration file.
The mysql_config_editor utility (available as of MySQL 5.6.6) enables
you to store authentication credentials in an encrypted login path
file named .mylogin.cnf. The file location is the %APPDATA%\MySQL
directory on Windows and the current user's home directory on
non-Windows systems. The file can be read later by MySQL client
programs to obtain authentication credentials for connecting to MySQL
Server.
This file can be created by running the following command:
mysql_config_editor set --login-path=client --host=localhost --user=root --password
You can print the existing settings with the following command:
mysql_config_editor print --login-path=client
This will output the current settings:
[client]
user = root
password = *****
host = localhost
Notice the password is encrypted by default.

create a file ~/.my.cnf in the home directory of the user running the cron job. make sure is not readable by other users ( chmod 600 ~/.my.cnf )
[client]
user=username
password=something

Related

mysql best seucrity practices for permitting --local-infile to allow LOAD DATA LOCAL INFILE

Trying to use LOAD DATA LOCAL INFILE to import a csv file revealed the this command is not allowed with this MySQL version error.
So upon further reading I learn that SET GLOBAL --local-infile=1 can only be set if the mysql account is ROOT or setting it in the my.conf file (and restart mysql). For security purposes, my script that needs to import the CSV file is using a non-root mysql admin account. In fact all of my public facing scripts use a non-root admin account to open up mysql sessions. Thus with out a root account, it doesn't look like I can set it on the fly and then disable when the script is done.
Next option is to set it at the server level in my my.conf file and restart mysql. But once I enable --local-infile=1 on the server I have then exposed it to security issues. After that all a client needs to do mysql -u user -p password dbName --local-infile=1 for that session and then that client now has access. This def does not seem ideal...or am I wrong about this assumption?
The other option is then using LOAD DATA INFILE which apparently uses the root file systems /tmp directory to save files to and for mysql LOAD DATA INFILE to read from. But that then requires both the /tmp directory being globally available AND/OR a system admin having access to that directory. Unless I am root on the linux box, I can't write to that directory without opening it up globally. Opening up /tmp globally is itself a security issue.
Ideally, using a mysql non-root account, how can I enable --local-infile=1 temporarily to run my script and then disable it when done? Or...what is another method I can consider that would achieve the same result?

Is there a way to set my root password permanently in MySQL via command line without "mysql -u root -p" every time? [duplicate]

You can avoid re-entering mysql command line password by putting the queries into a file.
In my case, the later queries are not determined until after the first queries have finished.
This happens in a non-interactive script so running a mysql console is not an option.
Is there any notion of a session for mysql command line interactions? Or can I set it up to listen for commands on a local unix socket (the output is required to be returned)? Or something like that?
User #smcjones mentions using the .my.cnf file or mysql_config_editor. Those are good suggestions, I give my +1 vote to him.
Another solution is to put the credentials in any file of your choosing and then specify that file when you invoke MySQL tools:
mysql --defaults-extra-file=my_special.cnf ...other arguments...
And finally, just for completeness, you can use environment variables for some options, like host and password. But strangely, not the user. See http://dev.mysql.com/doc/refman/5.7/en/environment-variables.html
export MYSQL_HOST="mydbserver"
export MYSQL_PWD="Xyzzy"
mysql ...other arguments...
I don't really recommend using an environment variable for the password, since anyone who can run ps on your client host can see the environment variables for the mysql client process.
There are a few ways to handle this in MySQL.
Put password in hidden .my.cnf in the home directory of the user the script is running as.
[client]
user=USER
password=PASSWORD
Use mysql_config_editor
mysql_config_editor set --login-path=client --host=localhost
--user=localuser --password
When prompted to enter your password, enter it like you otherwise would.
IMO this is the worst option, but I'll add it for the sake of completeness.
You could always create a function wrapper for MySQL that appends your set password.
#! /bin/bash
local_mysql_do_file() {
mysql -u localuser -h localhost -pPASSWORD_NO_SPACE < $1
}
# usage
local_mysql_do_file file.sql

Connect to 2 instances of MySQL with no password interaction using command line

I would like to connect to mysql database without interaction for the password (I need for using it during a batch script). I'm using this script, but before start the connection I must insert the password.
mysql -u username#databasename -p "Password" -h hostnamedatabase -P 3344
I have tried this other approach but I have no success
mysql -u username#databasename -pPassword -h hostnamedatabase -P 3344
Is there a way to enter the password directly without typing it in?
New answer
OP is on command line on a remote server (using SSH). From there, mysql needs to be used password-less - so to speak - to create user on INSTANCE1 and INSTANCE2.
That's doable also. You'd use --defaults-group-suffix switch.
~/.my.cnf
Let's start with creating a file called .my.cnf in your home directory (aka ~/.my.cnf). Put this in it.
[client1]
user=INSTANCE1-USERNAME
password=INSTANCE1-PASSWORD
database=INSTANCE1-DATABASE (this could be mysql)
host=INSTANCE1-HOSTNAME-OR-IP
[client2]
user=INSTANCE2-USERNAME
password=INSTANCE2-PASSWORD
database=INSTANCE2-DATABASE (this could be mysql)
host=INSTANCE2-HOSTNAME-OR-IP
Save the file. Do chmod 600 ~/.my.cnf to ensure only your username and root/root-like user can see it.
Now, type this to get to first server:
mysql --defaults-group-suffix=1
Then, use this to get to the second server:
mysql --defaults-group-suffix=2
Explanation
Typically ~/.my.cnf will have the following block
[client]
user=USERNAME
password=PASSWORD
database=DATABASE (this could be mysql)
host=localhost (or whatever hostname/IP)
That allows you to just type mysql and log on. MySQL looks for credentials, host, port etc. in ~/.my.cnf. If it gets that info, it'll use it to log in to MySQL. Cool. Easy enough.
--defaults-group-suffix=2 tells MySQL to look into ~/.my.cnf but not read the [client] block but instead read the [client2] block for credentials/information.
Similarly --defaults-group-suffix=1 tells MySQL to look into ~/.my.cnf and read the [client1] block for credentials/information.
That way, you can have credentials for multiple servers or databases within a single server and log on to MySQL without having to prompt/provide credentials through command line.
You can use this tool with scripts as long as the ~/.my.cnf file is in the username that is running those scripts.
Documentation
https://dev.mysql.com/doc/refman/8.0/en/option-file-options.html
https://dev.mysql.com/doc/refman/8.0/en/option-files.html#option-file-syntax
Another method using --login-path
See https://dev.mysql.com/doc/refman/8.0/en/mysql-config-editor.html. It shows you can log on to mysql using --login-path switch. Since the above method will work well for you, I am just adding this as a reference.
Old answer
You can actually do that. Assuming you are on Linux, create a .my.cnf file under your home directory. Type this in it:
[client]
user=username
password=yourpass
Then, you can do mysql -h host -P 3344 -D databasename
See documentation here: https://dev.mysql.com/doc/refman/8.0/en/option-files.html
Also make sure that this file is adequately protected (do chmod 600 ~/.my.cnf).

Can I enter password once for multiple mysql command line invocations, where the queries are not known upfront?

You can avoid re-entering mysql command line password by putting the queries into a file.
In my case, the later queries are not determined until after the first queries have finished.
This happens in a non-interactive script so running a mysql console is not an option.
Is there any notion of a session for mysql command line interactions? Or can I set it up to listen for commands on a local unix socket (the output is required to be returned)? Or something like that?
User #smcjones mentions using the .my.cnf file or mysql_config_editor. Those are good suggestions, I give my +1 vote to him.
Another solution is to put the credentials in any file of your choosing and then specify that file when you invoke MySQL tools:
mysql --defaults-extra-file=my_special.cnf ...other arguments...
And finally, just for completeness, you can use environment variables for some options, like host and password. But strangely, not the user. See http://dev.mysql.com/doc/refman/5.7/en/environment-variables.html
export MYSQL_HOST="mydbserver"
export MYSQL_PWD="Xyzzy"
mysql ...other arguments...
I don't really recommend using an environment variable for the password, since anyone who can run ps on your client host can see the environment variables for the mysql client process.
There are a few ways to handle this in MySQL.
Put password in hidden .my.cnf in the home directory of the user the script is running as.
[client]
user=USER
password=PASSWORD
Use mysql_config_editor
mysql_config_editor set --login-path=client --host=localhost
--user=localuser --password
When prompted to enter your password, enter it like you otherwise would.
IMO this is the worst option, but I'll add it for the sake of completeness.
You could always create a function wrapper for MySQL that appends your set password.
#! /bin/bash
local_mysql_do_file() {
mysql -u localuser -h localhost -pPASSWORD_NO_SPACE < $1
}
# usage
local_mysql_do_file file.sql

How to use credentials from other files and how to pass dir locations in crons?

I was written a script for My database backup.Now i want to pass user name and password from other config file (i mean i want to use credentials from other config file) how can use it?
From the cron i want to pass backupdir path.how we able to pass variables in the cron ?
EXample of my cron
/usr/local/bin/cronwrap -m host:mlora-pc-bkp.prod.hdkind.com "/usr/bin/mysql-zrm-backup --backup-set mlora_pc --backup-level 0 --socket /var/untd/mysql/mlora/tmp/mysql.sock > /tmp/mysql-zrm-backup_iflora.out 2>&1" "mysql-zrm-backup" penxttx#hdkind.com
All you need to do is just to add a file in your home directory and it will disable the mysqldump password prompting. This is done by creating the file ~/.my.cnf (permissions need to be 600).
Add this to the .my.cnf file
[mysqldump]
user=mysqluser
password=secret
This lets you connect as a MySQL user who requires a password without having to actually enter the password. You don't even need the -p or --password.
Very handy for scripting mysql & mysqldump commands.