Given a MySQL system with multiple remote users (users of the form 'joecool'#'192.168.1.2'); is there a SQL statement I can use to REQUIRE SSL for all the remote users?
The single user command is:
GRANT USAGE ON *.* TO 'joecool'#'192.168.1.2' REQUIRE SSL;
Having an "all user" version would be especially useful because phpMyAdmin doesn't support the REQUIRE SSL flag when creating or modifying users.
The (formerly) accepted answer by Honza seems incorrect, see its comments. It seems not possible to use a GRANT query to alter multiple users at once since MySQL does not support wildcards for user names.
As you suggested yourself you can alter records in the mysql.user table directly using an UPDATE query and as Marc Delisle suggested, afterwards flush priviliges with:
FLUSH PRIVILEGES;
Also see dba.stackexchange.com > How to grant multiple users privileges.
You can configure mysqld with require_secure_transport.
[mysqld]
...
ssl-ca = ...
ssl-cert = ...
ssl-key = ...
...
require-secure-transport = ON
This capability supplements per-account SSL requirements, which take
precedence. For example, if an account is defined with REQUIRE SSL,
enabling require_secure_transport does not make it possible to use the
account to connect using a Unix socket file.
Yes, you can modify the mysql.user table directly (be careful). Then you just issue a FLUSH PRIVILEGES statement to apply the changes to the running server.
Related
mysql_secure_installation is basically just a couple of SQL commands to make MySQL more secure.
I installed mysql-server 5.7 on Ubuntu 18.04 and ran the commands manually, as described here:
UPDATE mysql.user SET authentication_string='secretpassword' WHERE user='root';
DELETE FROM mysql.user WHERE user='';
DELETE FROM mysql.user WHERE user='root' AND Host NOT IN ('localhost',
'127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
Apart from changing the root password, each of the commands showed no effect at all:
Query OK, 0 rows affected (0.00 sec)
I have two questions:
Why would I want to use mysql_secure_installation if it does not
have any effect?
Why would I want to set a root password if I stick
with the default auth_socket authentification?
Note: As I am interested in the technical details, this is not a 'possible duplicate' of What is Purpose of using mysql_secure_installation? ;-).
Using mysql_secure_installation is not a must. No need to use it if you don't need it. As the document said in your link provided in your question, it is just for helping you implement security recommendation (ie, remote root access, etc) :
mysql_secure_installation helps you implement security recommendations
similar to those described at Section 2.10.4, “Securing the Initial
MySQL Accounts”.
https://dev.mysql.com/doc/refman/5.6/en/mysql-secure-installation.html
The default initiali here https://dev.mysql.com/doc/refman/5.6/en/default-privileges.html
If you are 100% sure will not get any remote attack or access from your local with default root access and any problem described there, actually you can ignore it.
Since this mysql is open source, actually you can know any technical details about any mysql problem with knowledge needed here https://github.com/mysql/mysql-server
I have a MySQL issue which troubles me for long time. Why sometimes a table is able to be SELECT but not able to be UPDATE or INSERT?
Maybe it is the reason of table lock. But I tried "SHOW OPEN TABLES", it doesn't shows table is locked.
Is there any other reason which will cause this problem?
Why sometimes a table is able to be SELECT but not able to be UPDATE
or INSERT?
Most likely because the user you are connecting with does not have UPDATE or INSERT permissions. You can check what GRANTS you have using a command like this in MySQL:
SHOW GRANTS FOR 'user_name'#'localhost';
Be sure to change user_name to the username you are using to connect to the server with. Also be sure localhost matches the host you are connecting to. But that said, MySQL GRANTS can be confusing. For example, I have seen some servers—when I had to clean up someone else’s work—where localhost would not work, but 127.0.0.1 would work so you might need to run the above command like this:
SHOW GRANTS FOR 'user_name'#'127.0.0.1';
And if you need to adjust your GRANTS then you could run this; be sure to change the database_name, user_name, localhost & password to match your setup:
GRANT USAGE ON `database_name`.* TO 'user_name'#'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `database_name`.* TO 'user_name'#'localhost';
The first line GRANT USAGE grants basic usage to the database to the user. The next line grants specific access rights and this is a fairly common stack that allows access to SELECT, UPDATE or INSERT items into the database as well as other sundry items.
That said, based on your comments it seems that this might be an issue where someone—or some code—with access to that database is running a LOCK TABLES statement that would result in the behavior you describe. Tables would be locked while work is done. And then an UNLOCK TABLES would be run afterwards to allow UPDATE and INSERT commands to go through.
If you wish to debug & have server level access you might want to temporarily enable MySQL logging to see what queries are coming through. But remember: Activating the MySQL log is a resource hog & can slow down your server. Only do it during a window when you know you can safely test.
Using an Ubuntu 12.04 serve setup for an example, you would open op the MySQL config file like so:
sudo nano /etc/mysql/my.cnf
Then search for the settings for general_log_file and general_log which should be commented out & look like this:
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
Uncomment both general_log_file and general_log and then restart MySQL like this:
sudo service mysql restart
Now you can follow the MySQL logs like so with tail:
sudo tail -f -n 200 /var/log/mysql/mysql.log
And if you see LOCK TABLES pop up in there, you know that is the cause. To disable logging just comment out those lines & restart MySQL again.
I have a PHP script that calls MySQL's LOAD DATA INFILE to load data from CSV files. However, on production server, I ended up with the following error:
Access denied for user ... (using password: yes)
As a quick workaround, I changed the command to LOAD DATA LOCAL INFILE which worked. However, the same command failed on client's server with this message:
The used command is not allowed with this MySQL version
I assume this has something to do with the server variable: local_infile = off as described here.
Please suggest a workaround that does not involve changing server settings. Note that phpMyAdmin utility installed on the same server appears to accept CSV files though I am not sure it it uses LOAD DATA (LOCAL) INFILE.
Ran into the same issue as root and threw me for a moment
could be an issue with your server settings set with compile
to test login to console with the same user and try your load data command
if you get the same error, try closing console and running
mysql -u USER -p --local-infile=1 DATABASE
now try running load data command again
if it works then you're going to need to restart mysqld with command line option or re-install with configuration option
references (references are for 5.0 but worked for me with 5.5):
http://dev.mysql.com/doc/refman/5.0/en/load-data-local.html
http://dev.mysql.com/doc/refman/5.0/en/mysql-command-options.html#option_mysql_local-infile
I found that I need to connect to database like this:
$dbh=mysql_connect($server,$dbuser,$dbpass,false,128);
Passing 128 in the flags parameter is the key.
See http://www.php.net/manual/en/mysql.constants.php#mysql.client-flags to read more about the flags.
take a look to this permission list, you can add them separately, IE. you can insert but not update, or you can delete but not select, etc...
ALL [PRIVILEGES] Grant all privileges at specified access level except GRANT OPTION
ALTER Enable use of ALTER TABLE
ALTER ROUTINE Enable stored routines to be altered or dropped
CREATE Enable database and table creation
CREATE ROUTINE Enable stored routine creation
CREATE TEMPORARY TABLES Enable use of CREATE TEMPORARY TABLE
CREATE USER Enable use of CREATE USER, DROP USER, RENAME USER, and REVOKE ALL PRIVILEGES
CREATE VIEW Enable views to be created or altered
DELETE Enable use of DELETE
DROP Enable databases, tables, and views to be dropped
EVENT Enable use of events for the Event Scheduler
EXECUTE Enable the user to execute stored routines
FILE Enable the user to cause the server to read or write files
GRANT OPTION Enable privileges to be granted to or removed from other accounts
INDEX Enable indexes to be created or dropped
INSERT Enable use of INSERT
LOCK TABLES Enable use of LOCK TABLES on tables for which you have the SELECT privilege
PROCESS Enable the user to see all processes with SHOW PROCESSLIST
REFERENCES Not implemented
RELOAD Enable use of FLUSH operations
REPLICATION CLIENT Enable the user to ask where master or slave servers are
REPLICATION SLAVE Enable replication slaves to read binary log events from the master
SELECT Enable use of SELECT
SHOW DATABASES Enable SHOW DATABASES to show all databases
SHOW VIEW Enable use of SHOW CREATE VIEW
SHUTDOWN Enable use of mysqladmin shutdown
SUPER Enable use of other administrative operations such as CHANGE MASTER TO, KILL, PURGE BINARY LOGS, SET GLOBAL, and mysqladmin debug command
TRIGGER Enable trigger operations
UPDATE Enable use of UPDATE
USAGE Synonym for “no privileges”
I think you have permision to select, delete, insert, update, but no to do other stuff,
use this command:
SHOW GRANTS
he will show you what you are able to to, in my case.
jcho360> show grants;
+-------------------------------------------------------+
| Grants for jbolivar#localhost |
+-------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'jbolivar'#'localhost' |
+-------------------------------------------------------+
1 row in set (0.00 sec)
I'm creating a bash script which, among other things, gathers some data from a MySQL database. My MySQL user has write privileges, but for safety reasons I would like to temporarily set it to a read only state. Is it possible to do this from a command line?
To answer your original question, you can put your whole database to read only mode by this commands:
FLUSH TABLES WITH READ LOCK;
SET GLOBAL read_only = 1;
and back to normal mode with:
SET GLOBAL read_only = 0;
UNLOCK TABLES;
Beware that this is an operation which will have deep impact on the behavior of the database. So before executing this, read the available documentation to the commands above. A much more common way is to revoke DML privileges from the specific user and afterwards grant them back.
If you're using MySQL 5.6 or newer and InnoDB, you can make a session read-only.
SET SESSION TRANSACTION READ ONLY;
https://dev.mysql.com/doc/refman/5.6/en/set-transaction.html
"READ ONLY" also offers a modest performance benefit.
Well, if the user right now has all privileges first, you need to revoke it
$>mysql -u DB_USER -pDB_PASS --execute="REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'YOUR_USER';"
After that you give him, the select permission
$>mysql -u DB_USER -pDB_PASS --execute="GRANT SELECT ON 'YOUR_DATABASE'#.* TO 'YOUR_USER'#'%';FLUSH PRIVILEGES;"
Do your stuff and after that grant privileges again to the user
$>mysql -u DB_USER -pDB_PASS --execute="GRANT ALL ON 'YOUR_DATABASE'#.* TO 'YOUR_USER'#'%';FLUSH PRIVILEGES;"
And that's all folks
NOTE: Review for quotation, perhaps i forgot something
My requirement is to create a user for remote login but without a password. At my remote space I use a bash script to do inserts, which is something like:
for i in {1..5000}; do
mysql -h 11.40.3.169 -uUser -pPass -DDatabaseName <<<
"insert into DatabaseTableName values('$i','dummy_$i');" &
echo -n "$i "
sleep 1
date
done
The problem is that each insert is taking almost 4 seconds, and I can not pinpoint the problem to anything but authentication at every insert. So, if I could create a user in MySQL with minimal authentication involved...Something like:
# I'm trying to remove this password
GRANT ALL PRIVILEGES TO 'user'#'%' IDENTIFIED BY 'password';
...Anything you can suggest.
Just remove the IDENTIFIED BY part:
GRANT ALL PRIVILEGES ON *.* TO 'user'#'%'
Note that remote login from anywhere without a password is a very insecure thing. You better limit the allowed IP range for this user:
GRANT ALL PRIVILEGES ON *.* TO 'user'#'allowed_remote_machine'
You can do this by creating a user with a password and then placing a .my.cnf file in the home directory of the account which runs the bash script containing the following:
[mysql]
user=user
password=pass
[mysqladmin]
user=user
password=pass
This might be better than creating a user with no password.
I think your problem lies in the fact that you are starting the mysql client for each insert. You should be doing your inserts from a php, java, etc program - not from a shell script.
The startup time of the client (and connection to the host) is killing you. I routinely do 1000s of inserts per minute from a php or java program to a MySQL database with millions of records on a small (CPU/memory) machine.
It's not so good idea to have a user without password and all privileges. I suggest you to create a user without password but just with some privileges (insert to specific table or specific database).
First off, using a client cnf file on the remote machine running the script wont speed this up. MySQL client is still sending logon information and logging in for each insert, it's just reading.a file for uid/pw instead of using cmd line arguments. AFAIK The network and authentication overhead are identical. Even the network packet contents will be the same.
You should still use a cnf file..
The way to.improve performance is to do multi-line linserts:
MySQL --defaults-file=/some/uid/pw/etc/.client.cnf -e \
"Insert into
tbl_name
('fld1','fld2')
values
('r1-fld1','r1-fld2'),
('r2-fld2','r2-fld2'),
...and so on (up to max_allowed_packet_size)
('r500-fld2','r500-fld2');"
Or READ DATA INFILE on server side after shipping over the data file