Pass password to mysql_config_editor using variable in shell - mysql

I have password stored in a variable $db_pwd and I want to pass it to mysql_config_editor in a shell script. I can not use config file or db_pwd environment variable.
I am doing this
mysql_config_editor set --login-path=local --host=localhost --user=username --password
(https://stackoverflow.com/a/20854048/6487831) .
What it does is ask for password "Enter Password", but I wish to supply the password using variable.
I tried this :
mysql_config_editor set --login-path=local --host=localhost --user=username --password $db_pwd
and
mysql_config_editor set --login-path=local --host=localhost --user=username --password | echo $db_pwd
and
echo "$db_pwd" | mysql_config_editor set --login-path=local --host=localhost --user=username --password
and
expect. But this leads to error in case there are warnings like "This path already exists, rewrite (y/n).
options file, but they still give me variable not found error even when I am using it as the first argument. Is options file compatible with mysql config editor?
Any way to do this? Or should I revert to using mysql instead of mysql_config_editor?

I found the other suggested answer did not work when there was no TTY. So I used this bash script that works in places like Terraform/ssh that doesn't have a terminal:
#!/bin/bash
if [ $# -ne 4 ]; then
echo "Incorrect number of input arguments: $0 $*"
echo "Usage: $0 <login> <host> <username> <password>"
echo "Example: $0 test 10.1.2.3 myuser mypassword"
exit 1
fi
login=$1
host=$2
user=$3
pass=$4
unbuffer expect -c "
spawn mysql_config_editor set --login-path=$login --host=$host --user=$user --password
expect -nocase \"Enter password:\" {send \"$pass\r\"; interact}
"
Test it:
./mysql_config.sh login 10.1.2.3 myuser mypass < /dev/null

The --password argument is designed to explicitly avoid passing a password on the command line, as this is considered bad security.
That being said, you could try to feed the password to mysql_config_editor anyway:
echo "$db_pwd" | mysql_config_editor set --login-path=local --host=localhost --user=username --password
(This may not work if mysql_config_editor insists on getting input from the current terminal instead of standard in; if that is the case, you don't have a way to provide the password from a variable).
As the answer you linked to states, you can use mysql directly to supply the password. Using mysql_config_editor is meant for storing the password in .mylogin.cnf in an encrypted form (i.e. you supply the password once from the terminal, it is then encrypted and saved in the config file, and mysql can use it from there).
Reference: https://dev.mysql.com/doc/refman/5.7/en/mysql-config-editor.html
Update: You may be able to trick mysql_config_editor into thinking it is reading from an interactive terminal, by using the unbuffer utility:
echo "$db_pwd" | unbuffer -p mysql_config_editor set --login-path=local --host=localhost --user=username --password

Ran into this problem as well.
My solution was to run the command once, and supply the password on prompt
mysql_config_editor set --login-path=local --host=localhost --user=username --password
This generates the file .mylogin.cnf in users home directory.
Just copying this file (can be done from a bash script) to the user you want to give access using the --login-path option does the trick.
As I understand .mylogin.cnf is just an obfuscated way of storing a username and password for that particular --login-path

Related

Escaping out password variable with special characters for mysqldump

I'm trying to create a shell script to automatically backup my whole database. My script expects the password in a new line because I don't want to store it anywhere. Here is my code:
#!/bin/bash
echo -n Password:
read -s PASS
echo
docker exec db /usr/bin/mysqldump --all-databases -u admin --password='\''$PASS\'' > backup-$(date "+%Y-%m-%d").sql
The problem is, that I need to put the variable into single quotes because of the $ signs in the password, but I can't read variables in single quotes.
I know there are several similar questions out there, but I could not solve is with them.
So if the password is '$ecretPa$$word', then the actual executed program should be something like this:
docker exec db /usr/bin/mysqldump --all-databases -u admin --password='$ecretPa$$word' > backup-2020-03-03.sql
I managed to make this work. Maybe the problem was not with the escaping but with the way I tried to run this.
My final code:
#!/bin/bash
echo -n Password:
read -s PASS
echo
cmd="docker exec db /usr/bin/mysqldump --all-databases -u admin --password='$PASS' > backup-$(date "+%Y-%m-%d").sql"
eval "$cmd";

combining bash and SQL scripting to create wordpress sites

I am writing a script that will run on a Ubuntu 16.04.1 server. The purpose of the script is to install a wordpress site on the server. I took most of my scripting from this site.
I am trying to create and grant permissions on the database, however my script stops when I enter a mysql environment using mysql -u root -p. As well, variables created in the bash environment are not carried over to the mysql environment. Here is my script for this section.
echo "Please enter the Name of the Database(please make name relevant)"
read -p DBNAME
echo "Please enter the Name of the Database User(Please document username)"
read -p DBUSER
echo "Please enter a Database password(Please document password)"
read -p DBPASSWORD
a=\'
b=$a$DBPASSWORD$a
f='CREATE DATABASE '$DBNAME' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci'
g=$a$f$a
c='GRANT ALL ON '$DBNAME.*'TO '$DBUSER'#localhost'' IDENTIFIED BY '$b
d=$a$c$a
mysql -u root -p -e $g
mysql -u root -p -e $c
mysql -u root -p -e "FLUSH PRIVILEGES"
Any help integrating the environment changes together would be great
When defining f and c use double quotes. Single quotes don't allow your variables to expand.
You log the user in as root to mysql, but don't supply a password, so it will prompt. Perhaps ask for the root password as well.
Perhaps something like the following would do the trick:
echo "Please enter the Name of the Database(please make name relevant)"
read -p DBNAME
echo "Please enter the Name of the Database User(Please document username)"
read -p DBUSER
echo "Please enter a Database password(Please document password)"
read -p DBPASSWORD
echo "Please enter your database's root password"
read -p DBROOTPASSWORD
a=\'
b=$a$DBPASSWORD$a
f="CREATE DATABASE '$DBNAME' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
g=$a$f$a
c="GRANT ALL ON $DBNAME.* TO $DBUSER#localhost IDENTIFIED BY "$b
d=$a$c$a
mysql -u root -p"$DBROOTPASSWORD" -e $g
mysql -u root -p"$DBROOTPASSWORD" -e $c
mysql -u root -p"$DBROOTPASSWORD" -e "FLUSH PRIVILEGES"

mysqldump access denied when being used in bash script

I am trying to create a bash script that uses mysqldump to create a backup of the database that is specified as parameter. However mysqldump fails with an access denied error. Using the same command directly (copying it to the shell an executing it) works without any problem.
#!/bin/bash
# ... use parameters to get db name and password
# build the mysqldump command and execute it...
command="mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u ${database} -p'${pw}' --extended-insert ${database} | gzip > ${path}"
echo "$command"
echo ""
$command
This gives me the following output:
$ ./dbbak DBUSER DBNAME PASSWORD
mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u DBUSER -p'PASSWORD' --extended-insert DBNAME | gzip > /path/to/backup/backup.sql.gz
Warning: Using a password on the command line interface can be insecure.
-- Connecting to 127.0.0.3...
mysqldump: Got error: 1045: Access denied for user 'DBUSER'#'localhost' (using password: YES) when trying to connect
As said before: When I copy the echoed mysqldump command and execute it directly, the backup works just fine.
What is the problem here? Since the command is executed correctly when being used manually all parameters (password, username, etc.) seem to be correct. Additionally the bash script is executed with the same user account as the manual command.
So why does the manual execution work while the bash script fails?
EDIT:
As Jens pointed out in his comment, removing the quotes from the password will solve the problem. ...-p${pw}... will work, BUT this will also lead to a new problem, if the password contains special characters like $ < > ...
I assume that the problem with the quotes is how bash parses the string. Meanwhile I found some docs that say, that it is a bad habit to store commands in variables and execute them. Instead one should execute commands directly. However the following does not work as well:
result=$(mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u ${database} -p'${pw}' --extended-insert ${database} | gzip > ${path})
When executing this with bash -x dbbak the output shows the problem:
...
++ mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u DBUSER '-p'\''DBPASS'\''' --extended-insert DBNAME
While I do understand why the quotes around DBPASS are added ('DBPASS' --> \''DBPASS'\'), I do not understand why there are also quotes around-p`.
How do I get rid of these quotes when executing the command?
You can either:
store the password in an environment variable MYSQL_PWD
store the password in a plain-text file .my.cnf which you need to put into
the home directory of the user that executes the script
use the mysql_config_editor utility to store the password in an encrypted
file
The first one is the easiest to use/implement but obviously the least secure.
I recommend to take a look at the documentation where all the possibilities are described. ;)
Configure it by .cnf file and provide it in --defaults-file
mysqldump --defaults-file=~/my_mysql.cnf db table > table.sql
In ~/my_msyql.cnf
[mysqldump]
user=user_name
password=my_password
host=my_host
This is also safe if you version this. You can save my_mysql.cnf differently per environment.
To remove the single quotes around the password solved for me.

How to pass password from file to mysql command?

I have a shell script which calls the mysql command with one parameter from external file, it looks like this (also I saw this example in other resources):
mysql --user=root --password=`cat /root/.mysql`
Bit it not working:
Failed to connect to MySQL server: Access denied for user 'root'#'localhost' (using password: YES).
I tried different quotes without success. How to pass it?
UPDATE 1:
Found that I can pass password without space symbol. The problem in this, my root pass contains spaces.
Store your password in a protected mysql cnf file:
install -m 700 -d /srv/secrets/
install -m 600 /dev/null /srv/secrets/root#localhost.cnf
editor /srv/secrets/root#localhost.cnf
Store the password in the client.password ini property
[client]
password="password"
Include this file as the first argument in your mysql command:
mysql \
--defaults-extra-file=/srv/secrets/root#localhost.cnf \
--user=root \
--host=localhost \
--no-auto-rehash
Use mysql_config_editor which is installed with the mysql client
mysql_config_editor set --login-path=dev --user=dbuser --host=localhost -p
Enter the password and then you can log in like this
mysql --login-path=dev
You should use the mysql_config_editor for this.
$ mysql_config_editor set \
--login-path=name_of_connection \
--host=server.example.com \
--user=login_as_user \
--password
this will prompt for a password, and save to a .mylogin.cnf file in your homedir.
mysql --login-path=name_of_connection dbname will connect to dbname on server.example.com as login_as_user
If --login-path is used with other options, ex. --silent, --login-path has to be the first argument/option
Finally this line working:
mysql --user=root --password="$(cat /root/.mysql)"
or:
mysql --user=root --password="$(< /root/.mysql)"
Root password must be without quotes: bla bla bla
If your password not contains spaces you can use:
mysql --user=root --password=`cat /root/.mysql`
I am not sure if that is possible, but you could definitely use configuration
file.
Try:
if [ $MYSQL_PASS ]
then
mysql -u "$MYSQL_ROOT" -p "$MYSQL_PASS" -e "SHOW DATABASES"
else
mysql -u "$MYSQL_ROOT" -e "SHOW DATABASES"
fi

mysql create database and user script

Question Rewritten:
HOMEDIR="ftpuser"
REMOTEIP="1.1.1.1"
MYSQLPASS="password"
Q1="DROP USER "$HOMEDIR"_shop;"
Q2="DROP DATABASE "$HOMEDIR"_shop;"
Q3="CREATE DATABASE IF NOT EXISTS "$HOMEDIR"_shop;"
Q4="GRANT ALL ON "$HOMEDIR"_shop TO '"$HOMEDIR"_shop'#'localhost' IDENTIFIED BY '$MYSQLPASS';"
Q5="GRANT ALL ON "$HOMEDIR"_shop TO '"$HOMEDIR"_shop'#'anotherip' IDENTIFIED BY '$MYSQLPASS';"
# Need to grant permissions from another server as well
Q6="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}${Q5}${Q6}"
echo $SQL
echo " "
ssh -p 8899 root#$REMOTEIP "mysql -u root -p "$SQL""
I then run:
/root/testing/migratesite.sh
And get:
bash: DROP: command not found
bash: CREATE: command not found
bash: GRANT: command not found
bash: GRANT: command not found
bash: FLUSH: command not found
What am I missing?
You are missing quotes and a proper mysql client command line:
ssh -p 8899 root#$REMOTEIP "mysql -u root -p -e \"$SQL\""
You need to escape the quotes around the $SQL variable so they get passed to the remote shell, else they get interpreted by the local shell (that's why you get DROP: command not found, the semi colon is interpreted by the shell.) Also, to have the mysql client to execute a command you have to pass the -e command line option.
Did you try this:
ssh -p 8899 root#$REMOTEIP "echo \"$SQL\" | mysql -u root --password=$SQL_PASS"