SQL Language Extension: CREATE/ALTER/CREATE_OR_ALTER/DROP MAPPING

Implements capability to control mapping of security objects to and between databases.

Author:

Alex Peshkoff <peshkoff@mail.ru>

Preamble:

Firebird 3 supports multiple security databases. This is great feature, but it raises some problems, missing in systems with single security database. Clusters of databases, using same security database, are efficiently separated and this is what we typically want to achieve using different security databases. But in some cases we need controlled limited interaction between such clusters. As an examples can be provided EXECUTE STATEMENT ON EXTERNAL DATA SOURCE when some data exchange between clusters is required and letting server-wide SYSDBA access databases from other clusters using services. More or less similar problems were already known in windows version of firebird since v. 2.1 due to presence of trusted windows authentication – we had 2 separate lists of users (in security database and OS) and sometimes it was needed to make them be related. For example it appears to be good idea to automatically assign to windows users from some group appropriate firebird role.

Single solution for all this problems is MAPPING login information, assigned to user when it connected to firebird server, to internal security objects in database – current_user and current_role. Mapping rule contains 4 parts of information:

- mapping scope (is mapping local for current database or affects all databases in cluster, including security database),

- mapping name (mappings are named like all the other objects in database),

- from what we map

- to what we map.

Here it's necessary to mention that all versions of firebird had one hardcoded global default rule – users authenticated in security database are always mapped into any database one-to-one. This rule is safe - if we have some security database it makes no use not to trust itself. Therefore (and due to backward compatibility) this rule is kept as is in firebird 3. What about mapping windows users to current_user (which was enabled by default in 2.1 & 2.5 when trusted authentication enabled) in firebird 3 it must be done explicitly. This is required for systems with multiple security databases - not all of them need/use windows trusted authentication.

'From' part of mapping has 4 items:

- authentication source (plugin name or result of mapping in other database or use of serverwide authentication or any method),

- name of database where authentication succeeded,

- name from which mapping is performed,

- type of that name (username, role, OS group – this depends upon plugin which added that name during authentication).

Each item may be ignored (any item is accepted) except type – it's definitely bad idea to mix different types of security objects.

'To' part has 2 items:

- name to which mapping is performed,

- type of that name (only USER/ROLE are accepted here).

Mappings are defined using SQL (DDL) commands.

Syntax:

{CREATE | ALTER | CREATE OR ALTER} [GLOBAL] MAPPING name

USING {PLUGIN name [IN database] |

ANY PLUGIN [IN database | SERVERWIDE] |

MAPPING [IN database] |

'*' [IN database]}

FROM {ANY type | type name}

TO {USER | ROLE} [name]

DROP [GLOBAL] MAPPING name

Description:

Each mapping may be tagged as GLOBAL. Pay attention that global and local maps with same name may exist and they are different objects!

Create, alter and create or alter commands use same set of options. Name of mapping is used to identify it in former DDL commands. USING clause has a most complicated set of options. One can provide explicit plugin name, making it work only for given plugin, or make it use any plugin (but not a result of previous mappings), or make it work only with server-wide plugins, or make it work only with previous mapping results, or let it use any method using asterisk. In almost all cases (except server-wide authentication which is not related with databases) one can also provide name of database in which name from which mapping is performed was “born”. FROM clause must set required parameter – type of name from which mapping is done. When mapping names from plugins type is defined by plugin, when previous mapping results - type can be only user or role. One can provide explicit name which will be taken into an account by this mapping or use ANY keyword to work with any name of given type. In TO clause USER or ROLE (to what mapping is done) must be specified, name is optional - when it is not provided original name (from what mapping is done) is used.

Samples:

All sample are provided for CREATE command, use of ALTER is exactly the same, use of DROP is obvious.

Enable use of windows trusted authentication in all databases that use current security database:

CREATE GLOBAL MAPPING TRUSTED_AUTH USING PLUGIN WIN_SSPI FROM ANY USER TO USER;

Enable SYSDBA-like access for windows admins in current database:

CREATE MAPPING WIN_ADMINS USING PLUGIN WIN_SSPI FROM Predefined_Group DOMAIN_ANY_RID_ADMINS TO ROLE RDB$ADMIN;

(there is no group DOMAIN_ANY_RID_ADMINS in windows, but such name is added by win_sspi plugin to provide exact backwards compatibility)

Enable particular user from other database access current database with other name:

CREATE MAPPING FROM_RT USING PLUGIN SRP IN "rt" FROM USER U1 TO USER U2;

(providing database names/aliases in double quotes is important for operating systems that have case-sensitive file names)

Enable server's SYSDBA (from main security database) access current database (assuming it has non-default security database):

CREATE MAPPING DEF_SYSDBA USING PLUGIN SRP IN "security.db" FROM USER SYSDBA TO USER;

Force people who logged in using legacy authentication plugin have not too much rights:

CREATE MAPPING LEGACY_2_GUEST USING PLUGIN legacy_auth FROM ANY USER TO USER GUEST;

Map windows group to trusted firebird role:

CREATE MAPPING WINGROUP1 USING PLUGIN WIN_SSPI FROM GROUP GROUP_NAME TO ROLE ROLE_NAME;

Here we expect that some windows users may belong to group GROUP_NAME. If needed name of the group may be given in long form, i.e. DOMAIN\GROUP.

Notice:

- Global mapping works best if firebird 3 or higher version database is used as security database. If you plan to use other database as security one (using for example your own provider) please create in it table RDB$AUTH_MAPPING with structure repeating one in firebird 3 database, public read access and SYSDBA-only write access.

- Mappings work only with information, coming from authentication plugins or previously done mapping. Information present in DPB (particular SQL role name) is not affected by mappings and can not be changed using them.

Tip:

It’s relatively easy to accidentally make a database remotely inaccessible using CREATE MAPPING statement. For example:

CREATE MAPPING BREAK_DB_1 USING * FROM ANY USER TO ROLE ROLE1;

CREATE MAPPING BREAK_DB_2 USING * FROM ANY USER TO ROLE ROLE2;

This will disallow any user (including SYSDBA) to connect. Luckily mappings are not processed when database is used in embedded mode, i.e. in such a case one should attach to database using embedded access and fix bad mappings.