docs.roxen.comBack to normal mode
DocsRoxen2.1TutorialsDatabase Tutorial
Copyright © 2001, Roxen Internet Software
Suggestions, comments & compliments
manuals@roxen.com

Privileges

A fundamental point, and a very common pitfall, in day-to-day MySQL operations is understanding how the MySQL privileges system works. This chapter is meant to provide only an overview of the basic functionalities. To get more information, it's recommended to read the MySQL manual.

The first noteworthy aspect is that MySQL does *not* use the security features of the host system. It has its own authentication schemes, different from the system's.

This section uses the GRANT and REVOKE commands, which have been implemented in MySQL version 3.22.11. If you have an earlier version, you're suggested to upgrade.

MySQL offers four levels of access control: global, database, table and column. We'll only deal with the first two, as they are the most important. If you think your setup would require finer-grained security, you'll probably also need to hire a knowledgeable Database Administrator: data storage and retrieval is a very sensitive matter, performance- and security-wise.

To manage privileges you'll have to use the GRANT and REVOKE SQL commands. Their (simplified) syntaxes are:


GRANT *priv_type* [, priv_type ...] ON {*.*|database.*} TO
      *user name* [IDENTIFIED BY '*password*']
      [, *user name* [IDENTIFIED BY '*password*'] ,...]
      [WITH GRANT OPTION]

REVOKE *priv_type* ON {*.*|database.*} FROM *user name*
[, *user name*, ...]

Where *priv_type* is a type of privilege, chosen among
ALL [PRIVILEGES]    FILE                RELOAD
ALTER               INDEX               SELECT
CREATE              INSERT              SHUTDOWN
DELETE              PROCESS             UPDATE
DROP                USAGE

"ALL" or "ALL PRIVILEGES" means (guess what?) everything. "USAGE" is the
same as "no privilege". 

If you use the "*.*" syntax, the altered privileges will be at the global level. If you use "database.*", you'll touch the database-level privileges.

The user name can have the form 'username@host', and can have wild-cards ('%' or '_', see later) in both the host or username parts.

If you specify the "IDENTIFIED BY..." clause, you'll set a password for the named user. Users without a password _are_ legal in MySQL, but they are a very serious security hazard.

WITH GRANT OPTION means that the user is given the privilege to grant the same privileges he has to other users. It can be revoked with the syntax

REVOKE GRANT OPTION ON ... FROM *user name*

In the default MySQL setup there is an anonymous user ('%@localhost'), whose existence can cause unexpected results while authenticating other users. It is advised to remove the anonymous user. It can't be done with the GRANT syntax, but you have to do it manually as detailed the examples below. Also, in the default MySQL setup there's an empty database named 'test', open for anonymous use. We'll use throughout this tutorial, but it's advised to remove it ('DROP DATABASE test') after you're done, as it can be a source of denial-of-service attacks.

Always remember: in order to maximize the security of your site, it's always best to give each user the minimal privileges allowing him to do his work.

Create a new user named 'kinkie', having basic data access to the 'test' database.

With Pike:


$ pike
Pike v0.6 release 116 running Hilfe v2.0 (Incremental Pike Frontend)
object o=Sql.sql("mysql://root:*password*@localhost/mysql");
o->query("grant select,insert,update,delete on test.* to kinkie identified by
                 '*password*');
o->query("flush privileges"); 

Or, from the MySQL monitor:


$ mysql -uroot -p*password* mysql
> grant select,insert,update,delete on test.* to kinkie identified by
  '*password*'; 

Create a new user named 'dbmanager' having full SQL access to all databases (but deny him server-related maintainance tasks):

With Pike:


object o=Sql.sql("mysql://root:*password*@localhost/mysql");
o->query("grant select,insert,update,delete,create,drop,alter,index on 
                *.* to dbmanager identified by '*password*'"); 

Disable the 'nasty' user.

With Pike:


object o=Sql.sql("mysql://root:*password*@localhost/mysql");
o->query("revoke all on *.* from nasty"); 
Note! This will _not_ remove the user from the authentication database, only prevent him from connecting. To remove the user completely, you'll have to act directly on the "mysql" database:

With Pike:


object o=Sql.sql("mysql://root:*password*@localhost/mysql");
o->query("delete from user where user='nasty'"); 

Delete the anonymous users and the public-access entries to the test databases:


object o=Sql.sql("mysql://root:*password*@localhost/mysql");
o->query("delete from user where user='');
o->query("delete from db where db like 'test%'); 

You might have noticed there are no Roxen examples in this chapter: these tasks _can_ be executed by Roxen (provided that you give it enough access privileges), but it's not advised to have RXML code perform such critical tasks: one reload too much could make your database useless.