Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-14443

DENY clause for access control a.k.a. "negative grants"

Details

    Description

      Summary:

      Implement a way to ensure that a user can not get access to a particular resource.
      DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

      For example:

      GRANT SELECT on *.* to alice;
      DENY SELECT on db.secret_table to alice;

      alice will not be able to select from secret_table.

      Syntax:

             DENY <privilege-list> ON <object-list> TO   <user-or-role>
       
      REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>

      User cases

      https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
      https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one&#45;mysql (18k views)
      https://dba.stackexchange.com/questions/68957/block-user-access-to-certain&#45;tables (13k views)

      Details:

      1. Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in show databases.
      2. DENY works on roles (as well as PUBLIC when it is implemented)
      3. Enabling a role activates that role's denies as well.
      4. Denies will be visible in SHOW GRANTS [FOR] if:
        • User has read or write access to mysql database.
        • User has read or write access to corresponding mysql privilege table. (TODO for as a separate MDEV for SHOW GRANTS)
      5. Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
      6. Introduce a form of SUPER privilege, say IGNORE_DENIES, to allow a "superuser" to ignore denies (this is compatible with SQL Server DENY behavior)

      Compatiblity with other databases (Potential future work)

      SQL Server

      • Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via SQL_MODE=MSSQL) GRANT can also cancel a DENY.
      • An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

      MySQL

      • MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
      • To allow MySQL compatibility, a possible extension in the future is: @@partial_revokes=1 -> REVOKE also works as DENY.

      Implementation details:

      • Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
        • Does this user have denies for databases? (if global privileges met all required access bits).
        • Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
        • Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
      • Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

      Milestones (each milestone includes test cases showcasing functionality):

      1. Grammar
      2. Global denies
      3. Database denies
      4. Table level denies
      5. Column level denies
      6. Stored procedure denies
      7. Information schema tables

      Attachments

        Issue Links

          Activity

            hanzhi Hanzhi (Inactive) created issue -
            serg Sergei Golubchik made changes -
            Field Original Value New Value
            Summary MariaDB privilege system does not have backlist for access control MariaDB privilege system does not have blacklist for access control
            serg Sergei Golubchik made changes -
            Summary MariaDB privilege system does not have blacklist for access control Blacklist for access control a.k.a. "negative grants"
            serg Sergei Golubchik made changes -
            Description Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others. Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ----
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a suubset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            serg Sergei Golubchik made changes -
            Description Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ----
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a suubset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ----
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a subset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            serg Sergei Golubchik made changes -
            Labels gsoc18
            ralf.gebhardt Ralf Gebhardt made changes -
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.4 [ 22408 ]
            serg Sergei Golubchik made changes -
            Description Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ----
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a subset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ---
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a subset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            cvicentiu Vicențiu Ciorbaru made changes -
            Assignee Vicentiu Ciorbaru [ cvicentiu ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Status Open [ 1 ] In Progress [ 3 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Assignee Vicentiu Ciorbaru [ cvicentiu ] Rutuja Surve [ rutuja ]
            serg Sergei Golubchik made changes -
            julien.fritsch Julien Fritsch made changes -
            julien.fritsch Julien Fritsch made changes -
            julien.fritsch Julien Fritsch made changes -
            Epic Link PT-73 [ 68549 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Priority Major [ 3 ] Critical [ 2 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Rank Ranked higher
            ralf.gebhardt Ralf Gebhardt added a comment - - edited

            cvicentiu, rutuja, Please add a rough estimate for the remaining work

            ralf.gebhardt Ralf Gebhardt added a comment - - edited cvicentiu , rutuja , Please add a rough estimate for the remaining work
            ralf.gebhardt Ralf Gebhardt made changes -
            Team Server DEV Foundation
            ralf.gebhardt Ralf Gebhardt made changes -
            Assignee Rutuja Surve [ rutuja ] Vicentiu Ciorbaru [ cvicentiu ]
            rutuja Rutuja Surve (Inactive) made changes -
            Attachment Rutuja-Reverse-Priv-Dec-18.pdf [ 47132 ]

            Current status:
            1. User level (Global) deny works with and without an initial GRANT.
            2. Database level deny works without an initial GRANT.
            Attaching the detailed approach followed for the same shortly.

            rutuja Rutuja Surve (Inactive) added a comment - Current status: 1. User level (Global) deny works with and without an initial GRANT. 2. Database level deny works without an initial GRANT. Attaching the detailed approach followed for the same shortly.
            ratzpo Rasmus Johansson (Inactive) made changes -
            Labels gsoc18 gsoc18 gsoc19
            greenman Ian Gilfillan made changes -
            Labels gsoc18 gsoc19 gsoc18
            cvicentiu Vicențiu Ciorbaru made changes -
            Fix Version/s 10.5 [ 23123 ]
            Fix Version/s 10.4 [ 22408 ]

            Current status of implementation:
            User and database level denies work end to end.
            Work in progress for table and column level deny (estimate 1 week)
            Routine level deny (estimate 1 week)
            Testing and review (estimate 2 weeks)

            rutuja Rutuja Surve (Inactive) added a comment - Current status of implementation: User and database level denies work end to end. Work in progress for table and column level deny (estimate 1 week) Routine level deny (estimate 1 week) Testing and review (estimate 2 weeks)
            ralf.gebhardt Ralf Gebhardt made changes -
            Epic Link PT-73 [ 68549 ]
            serg Sergei Golubchik made changes -
            Status In Progress [ 3 ] Stalled [ 10000 ]
            serg Sergei Golubchik made changes -
            Fix Version/s 10.5 [ 23123 ]
            ben Ben Stillman added a comment -

            As discussed with Max a while back, this functionality is highly desired by the SkySQL team to revoke access to system schemas.

            ben Ben Stillman added a comment - As discussed with Max a while back, this functionality is highly desired by the SkySQL team to revoke access to system schemas.
            rupert Rupert Harwood (Inactive) made changes -

            The problem I see with that is just that if you later grant some privileges
            that contradict the earlier REVOKE, then what will the expected behavior
            be? I like the idea of a DENY that overrides any existing or future grants.

            JP

            On Thu, May 20, 2021 at 7:13 AM Ralf Gebhardt (Jira) <jira@mariadb.org>

            jim.parks@mariadb.com Jim Parks (Inactive) added a comment - The problem I see with that is just that if you later grant some privileges that contradict the earlier REVOKE, then what will the expected behavior be? I like the idea of a DENY that overrides any existing or future grants. JP On Thu, May 20, 2021 at 7:13 AM Ralf Gebhardt (Jira) <jira@mariadb.org>
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.8 [ 26121 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Description Currently, MariaDB privilege system only perform whiltelist check for access control to certain database, table and column. This makes it difficult if we need to block access to certain database/table/column while allow for all others.
            ---
            A good solution would be to allow to {{REVOKE}} anything that a user is able to do — not only exactly those grants that were granted to a user, but also a subset. Like
            {code:sql}
            GRANT SELECT ON some_database.* TO a_user@%;
            REVOKE SELECT ON some_database.secret_table FROM a_user@%;
            {code}
            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            * User has read or write access to {{mysql}} database.
            * User has read or write access to corresponding {{mysql}} privilege table.
            * User has some form of SUPER privilege. (SAY IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            serg Sergei Golubchik made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            * User has read or write access to {{mysql}} database.
            * User has read or write access to corresponding {{mysql}} privilege table.
            * User has some form of SUPER privilege. (SAY IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            * User has read or write access to {{mysql}} database.
            * User has read or write access to corresponding {{mysql}} privilege table.
            * User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            cvicentiu Vicențiu Ciorbaru made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            * User has read or write access to {{mysql}} database.
            * User has read or write access to corresponding {{mysql}} privilege table.
            * User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** User has read or write access to corresponding {{mysql}} privilege table.
            ** User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            cvicentiu Vicențiu Ciorbaru made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** User has read or write access to corresponding {{mysql}} privilege table.
            ** User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            ** User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            cvicentiu Vicențiu Ciorbaru made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            ** User has some form of SUPER privilege. (say IGNORE DENIES)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
            # Introduce a form of SUPER privilege, say IGNORE_DENIES, to allow a "superuser" to ignore denies.

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            serg Sergei Golubchik made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
            # Introduce a form of SUPER privilege, say IGNORE_DENIES, to allow a "superuser" to ignore denies.

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
            # Introduce a form of SUPER privilege, say IGNORE_DENIES, to allow a "superuser" to ignore denies (this is compatible with SQL Server DENY behavior)

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            manjot Manjot Singh (Inactive) made changes -

            If there is a DENY on mysql.* for a user and they try to run:

            mysql < mydump.sql

            the full dump should load but avoid the mysql.* tables (or have only warnings related).

            manjot Manjot Singh (Inactive) added a comment - If there is a DENY on mysql.* for a user and they try to run: mysql < mydump.sql the full dump should load but avoid the mysql.* tables (or have only warnings related).

            if there is a DENY on mysql.* .. GRANT and related syntax should still be allowed

            manjot Manjot Singh (Inactive) added a comment - if there is a DENY on mysql.* .. GRANT and related syntax should still be allowed
            cvicentiu Vicențiu Ciorbaru made changes -
            Status Stalled [ 10000 ] In Progress [ 3 ]

            manjot DENY cancels out privileges.

            For example if a user could create a user with CREATE USER privilege, but otherwise didn't have INSERT/UPDATE rights on mysql.* database, then the same would be true if the user had DENY INSERT UPDATE on mysql.*.

            I assume this is in line with your statements, correct?

            cvicentiu Vicențiu Ciorbaru added a comment - manjot DENY cancels out privileges. For example if a user could create a user with CREATE USER privilege, but otherwise didn't have INSERT/UPDATE rights on mysql.* database, then the same would be true if the user had DENY INSERT UPDATE on mysql.* . I assume this is in line with your statements, correct?
            serg Sergei Golubchik made changes -
            Workflow MariaDB v3 [ 83893 ] MariaDB v4 [ 131822 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.9 [ 26905 ]
            Fix Version/s 10.8 [ 26121 ]
            ralf.gebhardt Ralf Gebhardt made changes -

            A current status update on the feature:

            In order to facilitate the feature, I have done the following cleanups:

            1. Move check_xxx_access functions to sql_acl.cc.
            2. Uniform privilege modification functions for mysql.user and the newer mysql.global_priv table. This is to facilitate writing denies into mysql.global_priv table.
            3. Optimize Sql_cmd_grant class, to use composition instead of inheritance. This also had the added benefit of reducing memory usage for Grant commands, avoiding an extra copy in LEX structure.
            4. Clean up the sql_acl.h exposed API. Many of the functions are now behind Sql_cmd_grant::execute calls.
            5. Remove code duplication by converting double acl_get calls checking for user and role privileges into a single function. This will facilitate DENY checks as well.
            6. Introduce a Priv_spec class that defines a delta of privileges. This is used uniformly by replace_xxxx_table functions to apply privilege deltas. This facilitates DENY and /REVOKE DENY grants.
            7. Split mysql_grant function into separate components. This facilitates individual DENY level grants (Global, Database, Proxy) This has the added benefit of only locking the modified privilege tables when doing a grant update.
            8. Cache get_current_user results in Sql_cmd_grant, before calling mysql_grant_xxx functions. This simplifies a lot of the mysql_grant_xxx functions.
            9. Refactor test_if_create_new_users, similar to get_current_user caching. This will facilitate hooking up denies too.
            10. Extend gramar in sql_yacc.yy to cover DENY clause.
            11. Code to read DENY specification from mysql.global_priv table. The JSON format at this point is:

                    {
                      "global": int
                      "db": [
                        {
                          "name": str
                          "access": int
                        },
                      ]
                      "table": [
                        {
                          "name": str
                          "access": int
                        },
                      ]
                }
              The format will be extended to cover finer level denies (table columns) too.
              

            12. JSON reader class, used to parse the DENY json and create in-memory HASH tables for all deny entries - per user.
            13. Extend mysql_show_grants to also output denies.
            14. Wrote test cases to cover currently implemented functionality, as well as tests that currently fail (because denies are not properly enforced). Using effectively test driven development to ensure all code paths are covered.

            TODO items:

            1. Adjust privilege check call sites to do proper deny evaluation. Ideally, create a uniform API that abstracts away both user and role current grants and denies.
            2. Extend information schema tables to present user denies.
            3. Create a new privilege (IGNORE_DENIES) to allow a user to bypass denies.
            4. Extend mysql_show_grants to output grants for users who have denies, but do not have the rights to see those denies. This requires a dedicated algorithm to generate the equivalent set of rights that are available.
            5. Extend test coverage.
            6. Code documentation - both within source as well as in the KB.
            cvicentiu Vicențiu Ciorbaru added a comment - A current status update on the feature: In order to facilitate the feature, I have done the following cleanups: Move check_xxx_access functions to sql_acl.cc. Uniform privilege modification functions for mysql.user and the newer mysql.global_priv table. This is to facilitate writing denies into mysql.global_priv table. Optimize Sql_cmd_grant class, to use composition instead of inheritance. This also had the added benefit of reducing memory usage for Grant commands, avoiding an extra copy in LEX structure. Clean up the sql_acl.h exposed API. Many of the functions are now behind Sql_cmd_grant::execute calls. Remove code duplication by converting double acl_get calls checking for user and role privileges into a single function. This will facilitate DENY checks as well. Introduce a Priv_spec class that defines a delta of privileges. This is used uniformly by replace_xxxx_table functions to apply privilege deltas. This facilitates DENY and /REVOKE DENY grants. Split mysql_grant function into separate components. This facilitates individual DENY level grants (Global, Database, Proxy) This has the added benefit of only locking the modified privilege tables when doing a grant update. Cache get_current_user results in Sql_cmd_grant, before calling mysql_grant_xxx functions. This simplifies a lot of the mysql_grant_xxx functions. Refactor test_if_create_new_users , similar to get_current_user caching. This will facilitate hooking up denies too. Extend gramar in sql_yacc.yy to cover DENY clause. Code to read DENY specification from mysql.global_priv table. The JSON format at this point is: { "global": int "db": [ { "name": str "access": int }, ] "table": [ { "name": str "access": int }, ] } The format will be extended to cover finer level denies (table columns) too. JSON reader class, used to parse the DENY json and create in-memory HASH tables for all deny entries - per user. Extend mysql_show_grants to also output denies. Wrote test cases to cover currently implemented functionality, as well as tests that currently fail (because denies are not properly enforced). Using effectively test driven development to ensure all code paths are covered. TODO items: Adjust privilege check call sites to do proper deny evaluation. Ideally, create a uniform API that abstracts away both user and role current grants and denies. Extend information schema tables to present user denies. Create a new privilege (IGNORE_DENIES) to allow a user to bypass denies. Extend mysql_show_grants to output grants for users who have denies, but do not have the rights to see those denies. This requires a dedicated algorithm to generate the equivalent set of rights that are available. Extend test coverage. Code documentation - both within source as well as in the KB.
            ivenn Isaac Venn (Inactive) made changes -
            cvicentiu Vicențiu Ciorbaru made changes -
            Status In Progress [ 3 ] Stalled [ 10000 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Status Stalled [ 10000 ] In Progress [ 3 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.10 [ 27530 ]
            Fix Version/s 10.9 [ 26905 ]
            manjot Manjot Singh (Inactive) made changes -
            manjot Manjot Singh (Inactive) made changes -
            manjot Manjot Singh (Inactive) made changes -
            ralf.gebhardt Ralf Gebhardt made changes -
            cvicentiu Vicențiu Ciorbaru made changes -
            Status In Progress [ 3 ] Stalled [ 10000 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.11 [ 27614 ]
            Fix Version/s 10.10 [ 27530 ]

            cvicentiu the Xpand team is going to start implementing this feature as well. Is there a build that we could use to compare notes?

            clieu Christine Lieu (Inactive) added a comment - cvicentiu the Xpand team is going to start implementing this feature as well. Is there a build that we could use to compare notes?
            AirFocus AirFocus made changes -
            Description h2. Summary:
            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:
            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret_table.


            h2. Syntax:
            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}


            h3. User cases
            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS \[FOR\]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
            # Introduce a form of SUPER privilege, say IGNORE_DENIES, to allow a "superuser" to ignore denies (this is compatible with SQL Server DENY behavior)

            h4. Compatiblity with other databases (Potential future work)
            *SQL Server*
            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*
            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} -> REVOKE also works as DENY.

            h3. Implementation details:
            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):
            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables

            h2. Summary:

            Implement a way to ensure that a user can not get access to a particular resource.
            DENY will function as a separate set of rules for access control. If any resource (global, database, table, column, procedure, function, etc.) has a deny on one particular privilege, it is impossible to gain that privilege unless the DENY is revoked.

            For example:

            {code:sql}
            GRANT SELECT on *.* to alice;
            DENY SELECT on db.secret_table to alice;
            {code}

            {{alice}} will not be able to select from secret\_table.

            h2. Syntax:

            {code:sql}
                   DENY <privilege-list> ON <object-list> TO <user-or-role>

            REVOKE DENY <privilege-list> ON <object-list> FROM <user-or-role>
            {code}

            h3. User cases

            https://stackoverflow.com/questions/6288554/mysql-grant-all-privileges-to-database-except-one-table (32k views)
            https://dba.stackexchange.com/questions/98949/grant-select-on-all-databases-except-one\-mysql (18k views)
            https://dba.stackexchange.com/questions/68957/block-user-access-to-certain\-tables (13k views)

            h3. Details:

            # Users should not be able to see that a DENY is assigned to them. Similar to how databases that the user can not access are not visible in {{show databases}}.
            # DENY works on roles (as well as PUBLIC when it is implemented)
            # Enabling a role activates that role's denies as well.
            # Denies will be visible in {{SHOW GRANTS [FOR]}} if:
            ** User has read or write access to {{mysql}} database.
            ** -User has read or write access to corresponding {{mysql}} privilege table.- (TODO for as a separate MDEV for SHOW GRANTS)
            # (?) Methods of querying denies: INFORMATION_SCHEMA.USER_PRIVILEGES
            # Introduce a form of SUPER privilege, say IGNORE\_DENIES, to allow a "superuser" to ignore denies (this is compatible with SQL Server DENY behavior)

            h4. Compatiblity with other databases (Potential future work)

            *SQL Server*

            * Compared to SQL Server, DENY can only be revoked via REVOKE DENY. Future possibility for SQL Server compatibility (via {{SQL_MODE=MSSQL}}) GRANT can also cancel a DENY.
            * An SQL Server quirk is that column level denies take precedence over table level denies. This is a deprecated functionality of SQL Server, meant for backwards compatibility.

            *MySQL*

            * MySQL treats revokes as "holes" that are filled when the privilege is granted (directly or via a a higher level grant). Deny will remain in effect in our implementation.
            * To allow MySQL compatibility, a possible extension in the future is: {{@@partial_revokes=1}} \-> REVOKE also works as DENY.

            h3. Implementation details:

            * Current privilege checking order first checks global, database, table, column privileges (in this order). If at any point the needed privileges are met, the privilege checking code stops execution. Introducing denies will require an additional lookup, one for each individual resource accessed. Some form of quick lookup must be made to answer:
            ** Does this user have denies for databases? (if global privileges met all required access bits).
            ** Does this user have denies for tables in a particular database (if database level privileges met all required access bits).
            ** Does this user have denies on table columns for a particular table (if table level privileges met all required access bits).
            * (?) Should denies be stored in global_priv only, or should corresponding mysql.db, mysql.table_priv, etc. tables also have a "DENY" column?

            h3. Milestones (each milestone includes test cases showcasing functionality):

            # Grammar
            # Global denies
            # Database denies
            # Table level denies
            # Column level denies
            # Stored procedure denies
            # Information schema tables
            ralf.gebhardt Ralf Gebhardt made changes -
            Status Stalled [ 10000 ] In Progress [ 3 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            cvicentiu Vicențiu Ciorbaru made changes -

            Hi Sergei!

            Once you are done with reviewing MDEV-29458 & MDEV-29465, please start looking at the code here:

            https://github.com/MariaDB/server/pull/2258

            Things currently not completely operational:
            1. SHOW GRANTS currently only shows up-to database level denies.
            2. Wildcard DB denies.

            I'm looking for general input on architecture changes as well as functionality. I expect that by the time you get to the end of the commit tree that the missing items will also be present.

            cvicentiu Vicențiu Ciorbaru added a comment - Hi Sergei! Once you are done with reviewing MDEV-29458 & MDEV-29465 , please start looking at the code here: https://github.com/MariaDB/server/pull/2258 Things currently not completely operational: 1. SHOW GRANTS currently only shows up-to database level denies. 2. Wildcard DB denies. I'm looking for general input on architecture changes as well as functionality. I expect that by the time you get to the end of the commit tree that the missing items will also be present.
            cvicentiu Vicențiu Ciorbaru made changes -
            Assignee Vicențiu Ciorbaru [ cvicentiu ] Sergei Golubchik [ serg ]
            Status In Progress [ 3 ] In Review [ 10002 ]
            serg Sergei Golubchik made changes -
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.12 [ 28320 ]
            Fix Version/s 10.11 [ 27614 ]
            clieu Christine Lieu (Inactive) made changes -
            Summary Blacklist for access control a.k.a. "negative grants" DENY list for access control a.k.a. "negative grants"
            ralf.gebhardt Ralf Gebhardt made changes -
            Summary DENY list for access control a.k.a. "negative grants" DENY clause for access control a.k.a. "negative grants"
            todorov Todor Todorov (Inactive) made changes -
            bbancroft Bryan Bancroft (Inactive) made changes -
            serg Sergei Golubchik made changes -
            julien.fritsch Julien Fritsch made changes -
            Fix Version/s 11.1 [ 28549 ]
            Fix Version/s 11.0 [ 28320 ]
            sanja Oleksandr Byelkin made changes -
            Assignee Sergei Golubchik [ serg ] Oleksandr Byelkin [ sanja ]
            sanja Oleksandr Byelkin made changes -
            Assignee Oleksandr Byelkin [ sanja ] Vicențiu Ciorbaru [ cvicentiu ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 11.2 [ 28603 ]
            Fix Version/s 11.1 [ 28549 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Status In Review [ 10002 ] Stalled [ 10000 ]
            cvicentiu Vicențiu Ciorbaru made changes -
            Status Stalled [ 10000 ] In Progress [ 3 ]

            One status update on this:

            I've rebased on top of 11.2.

            As discussed with Sergei Golubchik, I've implemented the separation of denies between users and roles. The implementation still requires testing and I am uncovering edge cases, bugs and an occasional crash. I expect around a week worth of work to stabilize this, then it should be ready for one final review.

            cvicentiu Vicențiu Ciorbaru added a comment - One status update on this: I've rebased on top of 11.2. As discussed with Sergei Golubchik, I've implemented the separation of denies between users and roles. The implementation still requires testing and I am uncovering edge cases, bugs and an occasional crash. I expect around a week worth of work to stabilize this, then it should be ready for one final review.
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 11.3 [ 28565 ]
            Fix Version/s 11.2 [ 28603 ]
            serg Sergei Golubchik made changes -
            Fix Version/s 11.4 [ 29301 ]
            Fix Version/s 11.3 [ 28565 ]
            julien.fritsch Julien Fritsch made changes -
            Assignee Vicențiu Ciorbaru [ cvicentiu ] Julien Fritsch [ julien.fritsch ]
            julien.fritsch Julien Fritsch made changes -
            Status In Progress [ 3 ] Stalled [ 10000 ]
            julien.fritsch Julien Fritsch made changes -
            Assignee Julien Fritsch [ julien.fritsch ] Vicențiu Ciorbaru [ cvicentiu ]
            julien.fritsch Julien Fritsch made changes -
            Issue Type Task [ 3 ] New Feature [ 2 ]
            serg Sergei Golubchik made changes -
            Fix Version/s 11.5 [ 29506 ]
            Fix Version/s 11.4 [ 29301 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 11.6 [ 29515 ]
            Fix Version/s 11.5 [ 29506 ]
            serg Sergei Golubchik made changes -
            Fix Version/s 11.7 [ 29815 ]
            Fix Version/s 11.6 [ 29515 ]
            AirFocus AirFocus made changes -
            Labels gsoc18 gsoc18 triage
            mariadb-jira-automation Jira Automation (IT) made changes -
            Zendesk Related Tickets 120370 202301
            serg Sergei Golubchik made changes -
            Fix Version/s 11.8 [ 29921 ]
            Fix Version/s 11.7 [ 29815 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Assignee Vicențiu Ciorbaru [ cvicentiu ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 11.9 [ 29945 ]
            Fix Version/s 11.8 [ 29921 ]
            julien.fritsch Julien Fritsch made changes -
            Assignee Vicențiu Ciorbaru [ cvicentiu ]
            serg Sergei Golubchik made changes -
            Assignee Vicențiu Ciorbaru [ cvicentiu ]
            ralf.gebhardt Ralf Gebhardt made changes -
            serg Sergei Golubchik made changes -
            Assignee Alexander Barkov [ bar ]
            sanja Oleksandr Byelkin made changes -
            Assignee Alexander Barkov [ bar ] Vladislav Vaintroub [ wlad ]

            Per this announcement in the Slack triage channel: https://mariadb.slack.com/archives/C05S0ANJ8BE/p1739890335402039, we will now only use the "triage" label to indicate an ongoing customer-engineering escalation. Also, I will remove it, and if it's still needed, let me know.

            julien.fritsch Julien Fritsch added a comment - Per this announcement in the Slack triage channel: https://mariadb.slack.com/archives/C05S0ANJ8BE/p1739890335402039 , we will now only use the "triage" label to indicate an ongoing customer-engineering escalation. Also, I will remove it, and if it's still needed, let me know.
            julien.fritsch Julien Fritsch made changes -
            Labels gsoc18 triage gsoc18
            serg Sergei Golubchik made changes -
            Fix Version/s 12.1 [ 29992 ]
            Fix Version/s 12.0 [ 29945 ]
            croser Christian Roser added a comment -

            After talking to Vicențiu we came to the conclusion that for our usecase DENY on database level would be sufficient and relatively easy to implement. We mainly want to prevent users with global privileges from accessing mysql schema.
            Is there a chance to get a DENY feature with limited scope implemented earlier than in 12.1?

            regards
            Christian

            croser Christian Roser added a comment - After talking to Vicențiu we came to the conclusion that for our usecase DENY on database level would be sufficient and relatively easy to implement. We mainly want to prevent users with global privileges from accessing mysql schema. Is there a chance to get a DENY feature with limited scope implemented earlier than in 12.1? regards Christian

            People

              wlad Vladislav Vaintroub
              hanzhi Hanzhi (Inactive)
              Votes:
              8 Vote for this issue
              Watchers:
              32 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.