Secure way of providing MySQL password in a batch file - mysql

We have a batch file that, among other things, performs some database operations. To keep things non-interactive, currently we pass the DB user id and password information on the command line. We keep getting the following warning messages:
Using a password on the command line interface can be insecure.
Kindly suggest how to pass the DB password information to the batch file so that it remains non-interactive and yet secure.

Put the password into an option file, and specify the option filename to your MySQL client in the batch file.
Say you edit an option file and call it "myoptions.ini". The option file content might look like this:
[client]
user = sandeep
password = ********
Then your command would look like this:
mysql --defaults-file myoptions.ini -h <host> <database> -e <query>
See https://dev.mysql.com/doc/refman/8.0/en/option-files.html

Related

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).

Import sql file into mysql via command line

I have a little weird problem. I would like to import sql file via command line. Command looks like
mysql -u root -p root pdweb-sandbox < C:\Apache24\htdocs\pdweb-sandbox\migrations/init.sql
But if there is password explicitly typed in command it does nothing. No error but also no action. Only if the password is empty it works as expected(but I need type it to the command line). But I would like to have password in the command. It is a part of a script which is triggered automatically. Password comes from phinx.yml config file. Is there a way to do it with password in command?
There are many ways you can do this in a script:
Using mysqlimport. You can find the details here. https://www.toadworld.com/platforms/mysql/w/wiki/6152.mysql-importing-with-mysqlimport
Using mysql, the details about how to use it as below (Copied from https://dev.mysql.com/doc/refman/5.7/en/mysql-command-options.html#option_mysql_password)
--password[=password], -p[password]
The password to use when connecting to the server. If you use the short option form (-p), you cannot have a space between the option and the password. If you omit the password value following the --password or -p option on the command line, mysql prompts for one.
Specifying a password on the command line should be considered insecure. See Section 6.1.2.1, “End-User Guidelines for Password Security”. You can use an option file to avoid giving the password on the command line.
The above two ways are not secure. You can put the password in another option file. Details is here: https://dev.mysql.com/doc/refman/5.7/en/password-security-user.html
`> Store your password in an option file. For example, on Unix, you can list your password in the [client] section of the .my.cnf file in your home directory:
[client]
password=your_pass
To keep the password safe, the file should not be accessible to anyone but yourself. To ensure this, set the file access mode to 400 or 600. For example:
shell> chmod 600 .my.cnf
To name from the command line a specific option file containing the password, use the --defaults-file=file_name option, where file_name is the full path name to the file. For example:
shell> mysql --defaults-file=/home/francis/mysql-opts
Section 4.2.6, “Using Option Files”, discusses option files in more detail.`
Using expect. "man expect". http://www.admin-magazine.com/Articles/Automating-with-Expect-Scripts

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

Security of passwords in bash subcommands

I've heard that directly inputting your password on the command line is a bad idea, because anyone could see the "secret" in
mysql -u root -psecret
by browsing history.
I have a password for my MySQL database stored in a text file with limited read permissions, and was wondering if it is safe to access it in the following way:
mysql -u root -p$(cat ~/.mysql_pass)
Browsing history, I see the command printed, not the literal value. So it seems like it's working the way I want it to.
I'm sure there are better ways of handling passwords, I would just like to know whether or not this one is leaving my password completely out in the open.
You've suggested using the following:
mysql -u root -p$(cat ~/.mysql_pass)
However, the subcommand will be expanded before mysql is executed and so even if this isn't available in the command history, it's entirely possible for someone to view the process list just after invocation and see your password.
I think a better approach is to use a mysql client options file and have the mysql command read the password from the options file.
Just type mysql -u root -p and you'll get a prompt to enter your password and it won't be stored in the history.