Results 1 to 2 of 2

Thread: MariaDB - Export Users, Grants and Roles

  1. #1
    Join Date
    Sep 2011
    Location
    Behind you!
    Beans
    1,692
    Distro
    Ubuntu 20.04 Focal Fossa

    Question MariaDB - Export Users, Grants and Roles

    In the past, I've used the following command to export users and their privileges:

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql --skip-column-names --no-auto-rehash | sed 's/$/;/g' > /tmp/db-grants.sql
    MariaDB implemented roles in 2013 with version 10. I have only just now started to utilize roles and found that it broke my backups.

    That same command above will fail will it comes across a role name which is stored as a pseudo-user in the user table. Example:

    Code:
    ERROR 1141 (42000) at line 4: There is no such grant defined for user 'r_myrole' on host '%'
    To keep that syntax error from occurring, I modified the statement with a check for "is_role" as follows:

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>'' AND is_role='N'" | mysql --skip-column-names --no-auto-rehash | sed 's/$/;/g' > /tmp/db-grants.sql
    Now the backup continues but the exported .sql file is worthless. In the database design, all the grants were removed from the users and added to the roles which are not exported in that .sql file. Even though the syntax is correct, the import will not work because it now looks like this:

    Code:
    GRANT `r_myrole` TO `u_myuser`@`localhost`;
    GRANT USAGE ON *.* TO `u_myuser`@`localhost` IDENTIFIED BY PASSWORD 'mypassword';
    #1 - The 1st command will not work when migrating to a new server because r_myrole does not exist AND the u_myuser does not yet exist.
    #2 - The 2nd command will create the user but without any additional privileges (because the privileges are stored in the role).

    So, to fix this, roles need to be exported 1st, then their associated grants, then the users and finally their granted role (with default setting)

    I have yet to see where anyone on the Internet has addressed this since its inception 7 years ago.

    I am thinking about writing a script that will create a usable .sql file to import on a clean system but don't want to re-create the wheel if not necessary.

    Anyone know of a solution using the built-in features (preferred) or 3rd-party utility?

    EDIT #1: Example of commands to create and assign a role:
    Code:
    CREATE ROLE r_db1;
    GRANT SELECT,INSERT,UPDATE,DELETE ON db1.* TO r_db1;
    CREATE USER 'u_db1'@'localhost' IDENTIFIED BY 'InsertPasswordHere';
    GRANT r_db1 TO 'u_db1'@'localhost';
    SET DEFAULT ROLE r_db1 FOR 'u_db1'@'localhost';
    EDIT #2: The 1st roadblock is that this command does not exist:
    Code:
    SHOW CREATE ROLE r_dba1;
    Which means I will have to export a list of roles and manually make each "create role" entry.

    EDIT #3: I also asked this question at MariaDB

    EDIT #4: Please up-vote these issues if you would like to see them resolved:

    MDEV-22311 - implement SHOW CREATE ROLE
    MDEV-22313 - SHOW GRANTS does not prints a user's default role

    LHammonds
    Last edited by LHammonds; October 7th, 2020 at 04:04 PM.

  2. #2
    Join Date
    Sep 2011
    Location
    Behind you!
    Beans
    1,692
    Distro
    Ubuntu 20.04 Focal Fossa

    Re: MariaDB - Export Users, Grants and Roles

    I will document the workaround for getting a good backup of users, grants and roles for the purpose of migrating a complete system from one server to another in this post.

    The order these commands are executed are important so the creation of the commands will take account of this. Role Creation -> Role Grants -> User Creation -> User Grants -> Role Defaults

    Role Creation

    Code:
     mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT User FROM mysql.user WHERE is_role = 'Y';" | sed 's/^/CREATE ROLE /;s/$/;/g;1s/^/## Create Roles ##\n/' > /tmp/role-create.sql
    Example output:
    Code:
    ## Create Roles ##
    CREATE ROLE r_dba;
    CREATE ROLE r_db1;
    CREATE ROLE r_db2;
    Role Grants

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT CONCAT('SHOW GRANTS FOR ''',User,''';') FROM mysql.user WHERE is_role = 'Y'" | mysql --skip-column-names --no-auto-rehash | sed 's/$/;/g;1s/^/## Grants for Roles ##\n/' > /tmp/role-grants.sql
    Example output:
    Code:
    ## Grants for Roles ##
    GRANT USAGE ON *.* TO `r_dba`;
    GRANT ALL PRIVILEGES ON *.* TO `r_dba`;
    GRANT USAGE ON *.* TO `r_db1`;
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ON `db1`.* TO `r_db1`;
    GRANT USAGE ON *.* TO `r_db2`;
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ON `db2`.* TO `r_db2`;
    User Creation

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT User,Host,Password FROM mysql.user WHERE is_role = 'N' AND User NOT IN ('mariadb.sys','root','mysql');" | sed 's/\t/`@`/;s/\t/` IDENTIFIED BY `/;s/^/CREATE USER `/;s/$/`;/;1s/^/## Create Users ##\n/' > /tmp/user-create.sql
    Example output:
    Code:
    ## Create Users ##
    CREATE USER `u_dba`@`localhost` IDENTIFIED BY `*0123456789012345678901234567891234567891`;
    CREATE USER `u_db1`@`localhost` IDENTIFIED BY `*0123456789012345678901234567891234567891`;
    CREATE USER `u_db2`@`localhost` IDENTIFIED BY `*0123456789012345678901234567891234567891`;
    User Grants

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT CONCAT('SHOW GRANTS FOR ''',User,'''@''',Host,''';') FROM mysql.user WHERE User <> '' AND is_role = 'N' AND user NOT IN ('mysql','mariadb.sys','root');" | mysql --skip-column-names --no-auto-rehash | sed 's/$/;/g;1s/^/## Grants for Users ##\n/' > /tmp/user-grants.sql
    Example output:
    Code:
    ## Grants for Users ##
    GRANT `r_dba` TO `u_dba`@`localhost`;
    GRANT USAGE ON *.* TO `u_dba`@`localhost` IDENTIFIED BY PASSWORD `*0123456789012345678901234567891234567891`;
    GRANT `r_db1` TO `u_db1`@`localhost`;
    GRANT USAGE ON *.* TO `u_db1`@`localhost` IDENTIFIED BY PASSWORD `*0123456789012345678901234567891234567891`;
    GRANT `r_db2` TO `u_db2`@`localhost`;
    GRANT USAGE ON *.* TO `u_db2`@`localhost` IDENTIFIED BY PASSWORD `*0123456789012345678901234567891234567891`;
    Role Defaults

    Code:
    mysql --skip-column-names --no-auto-rehash --silent --execute="SELECT default_role,User,Host FROM mysql.user WHERE is_role = 'N' AND User NOT IN ('mariadb.sys','root','mysql') AND default_role <> '';" | sed 's/\t/ FOR `/;s/\t/`@`/;s/^/SET DEFAULT ROLE /;1s/^/## Set Default Roles ##\n/;s/$/`;/' > /tmp/role-default.sql
    Example output:
    Code:
    ## Set Default Roles ##`;
    SET DEFAULT ROLE r_dba FOR `u_dba`@`localhost`;
    SET DEFAULT ROLE r_db1 FOR `u_db1`@`localhost`;
    SET DEFAULT ROLE r_db2 FOR `u_db2`@`localhost`;
    Thanks,
    LHammonds
    Last edited by LHammonds; October 7th, 2020 at 06:44 PM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •