ldap2pg

repository·master·Indexed 42 days ago

https://github.com/dalibo/ldap2pg

A tool for synchronizing PostgreSQL roles and privileges from LDAP directories or static YAML configurations. It automates the lifecycle of database users, including creation, updates, and privilege management, supporting PostgreSQL versions 9.5 through 17 and various directory services such as OpenLDAP, Microsoft Active Directory, and FreeIPA.

Tokens
19.1K
Snippets
63
Records
90
Agent score
48%

What's inside ldap2pg

  1. What is ldap2pg and what does it do?

    master

    ldap2pg is a tool that automates the creation, update, and removal of PostgreSQL roles and users based on an enterprise directory (LDAP).

    Key capabilities include:

    • Role Lifecycle Management: Creates, alters, and drops PostgreSQL roles derived from LDAP searches.
    • Static Role Creation: Creates roles defined directly in YAML to complement LDAP entries.
    • Privilege Management: Grants or revokes privileges either statically via YAML or dynamically from LDAP entries.
    • Group Management: Manages role parents (aliases for groups).
    • Safety & Observability: Supports dry runs and check modes, logs LDAP searches as ldapsearch(1) commands, and logs every SQL statement executed.

    It is compatible with PostgreSQL versions 9.5 through 18 and works with directory services such as Samba DC, OpenLDAP, FreeIPA, Oracle Internet Directory, and Microsoft Active Directory.

  2. What ldap2pg does: Synchronize Postgres roles from LDAP or YAML

    master

    ldap2pg is a tool designed to automate the management of PostgreSQL roles and privileges. It can:

    • Synchronize from LDAP: Create, alter, and drop PostgreSQL roles based on LDAP searches.
    • Synchronize from YAML: Create static roles defined directly in your configuration file.
    • Manage Privileges: Grant or revoke privileges statically or based on LDAP entries.
    • Manage Role Hierarchy: Handle role parents (groups).

    It supports PostgreSQL versions from 9.5 up to 17. It is compatible with various directory services including Samba Directory, OpenLDAP, FreeIPA, Oracle Internet Directory, and Microsoft Active Directory.

  3. Features of gokrb5

    master

    gokrb5 provides both client and server-side Kerberos capabilities:

    Server Side

    • SPNEGO Authentication: HTTP handler wrapper for Kerberos authentication.
    • Microsoft AD PAC: HTTP handler wrapper that decodes Microsoft Active Directory PAC authorization data and exposes it in the HTTP request context.

    Client Side

    • SPNEGO Client: Authenticate to SPNEGO Kerberos-protected web services.
    • Password Management: Ability to change the client's password.

    General Utilities

    • Custom Integration: Kerberos libraries for building custom implementations.
    • File Parsing: Support for parsing Keytab files, krb5.conf files, and client credentials cache files (e.g., /tmp/krb5cc_$(id -u $(whoami))).
  4. How privilege profiles and ACLs work in ldap2pg

    master

    ldap2pg uses two main abstractions to manage PostgreSQL permissions:

    1. ACL (Access Control List): A set of queries used to inspect, grant, and revoke privileges on a specific class of objects (e.g., DATABASE, SCHEMA, ALL TABLES IN SCHEMA).
    2. Privilege Profile: A named collection of references to privilege types within an ACL. Profiles can include other profiles to build complex permission sets.

    Key Behaviors:

    • Builtin Profiles: These start and end with __ (e.g., __connect__). To use a builtin profile in your own custom profile, you must explicitly include it.
    • Disabling Builtins: ldap2pg disables any profile starting with a single _.
    • Inspection: If multiple profiles reference the same privilege, ldap2pg only inspects it once.
    • Partial Grants: Using ALL ... IN SCHEMA ACLs allows ldap2pg to detect partial grants. It will either revoke unwanted partial grants or regrant them if they are expected.
    privileges:
      ro:
      - __connect__
      - __usage_on_schemas__
      - __select_on_tables__
    
      rw:
      - ro
      - __insert__
      - __update_on_tables__
    
      ddl:
      - rw
      - __all_on_schemas__
      - __all_on_tables__
    
    rules:
    - grant:
        privilege: ddl
        database: mydb
        role: admins
  5. Reference builtin privilege profiles

    master

    Builtin profiles follow specific naming conventions to group privileges:

    • ..._on_all_<type>__: References ALL <TYPE> IN SCHEMA ACLs (e.g., __all_on_tables__).
    • __default_...__: References both global and schema-wide default privileges.
    • __..._on_<type>__: A group that includes both __..._on_all_<type>__ and __default_..._on_<type>__.
    • __all_on_...__: Equivalent to ALL PRIVILEGES in SQL, but implemented by granting each privilege individually.
    • Aliasing: Some object-specific privileges omit the _on_<type> suffix. For example, __delete_on_tables__ is aliased to __delete__.
  6. Manage role membership with unmanaged parents

    master

    ldap2pg manages the parent-child relationships (membership) of roles. While the roles_blacklist_query is applied to parents, ldap2pg will still grant membership to 'unmanaged' parents.

    This behavior allows you to manually create a group in PostgreSQL and then use ldap2pg to manage only the members of that group.

  7. How GSS-API negotiation mechanism works

    master

    GSS-API negotiation follows RFC 4178. The process begins with the client sending an initial negotiation message specifying supported mechanisms in order of preference.

    In this implementation, the NewNegTokenInitKrb5 method generates this message. This message specifies that only the Kerberos v5 (KRB5) mechanism is supported and includes the initial mechanism token for KRB5 as the preferred mechanism.

    The server responds to the client's initial message with one of four states/message types:

    | Message Type/State | Description |
    |--------------------|-------------|
    | accept-completed | indicates that the initiator-selected mechanism was acceptable to the target, and that the security mechanism token embedded in the first negotiation message was sufficient to complete the authentication |
    | accept-incomplete | At least one more message is needed from the client to establish security context. |
    | reject | Negotiation is being terminated. |
    | request-mic | (this state can only be present in the first reply message from the target) indicates that the MIC token exchange is REQUIRED if per-message integrity services are available |
  8. Inject LDAP attributes into parameters

    master

    You can inject LDAP attribute values into various parameters using curly braces {}. ldap2pg expands these placeholders to the corresponding values for each entry found in the LDAP search.

    • Single attributes: Use {attribute_name} (e.g., {cn}).
    • Multiple attributes: If a parameter contains multiple attributes (e.g., {attr1}_{attr2}), ldap2pg expands to all possible combinations of those attributes for each entry.
    • Pseudo attribute: The {dn} attribute is always available and represents the Distinguished Name of the original LDAP entry.

    Example: Given an entry with cn: dimitri and company: external, the format {company}_{cn} results in external_dimitri.

    # Example of attribute injection in YAML
    - ldapsearch: ...
      role: "{company}_{cn}"
  9. Configure synchronization rules in ldap2pg.yaml

    master

    The rules section is the only mandatory parameter in the ldap2pg.yaml configuration file. It is a YAML list where each item (a mapping) defines how to manage PostgreSQL roles or grants. Each mapping can optionally include a description for logging and an ldapsearch section to fetch data from a directory.

    To define roles without an LDAP directory, omit the ldapsearch section. To define roles based on LDAP entries, include ldapsearch and use curly braces {} for attribute injection in role or grant subsections.

    rules:
    - description: "Define DBA roles"
      ldapsearch:
        base: ...
      roles:
      - name: "{cn}"
        options: LOGIN SUPERUSER
  10. Access Relative Distinguished Names (RDN) and trigger sub-searches

    master

    If an LDAP attribute contains a Distinguished Name (DN), you can access specific components of that DN using dot notation: <attribute>.<rdn>.

    Accessing RDNs

    Use the format {attribute.rdn}. Note that if an RDN has multiple values, only the first value is returned.

    Supported RDNs: cn, l, st, o, ou, c, street, dc, and uid.

    Example: If member is cn=toto,cn=Users,dc=bridoulou,dc=fr:

    • {member.cn} returns toto.
    • {member.dc} returns ldap (the first component).

    Triggering Sub-searches

    If you use an RDN that is not in the supported list above, ldap2pg will trigger a sub-search. The format {attribute.unknown_attr} uses the value of attribute as the LDAP search base, narrowed by the unknown_attr attribute.

  11. Run ldap2pg as a non-superuser

    master

    You can manage roles without superuser privileges by using a PostgreSQL role with the CREATEROLE option.

    Important Security Note:

    • PostgreSQL < 15: CREATEROLE is roughly equivalent to a superuser because the user can grant themselves almost any privilege.
    • PostgreSQL 16+: It is safe to run ldap2pg with an unprivileged CREATEROLE user.

    Limitations of non-superuser mode:

    • You cannot manage certain role options like SUPERUSER, BYPASSRLS, or REPLICATION.
    • You cannot detect if a user has been granted these privileges spuriously.
    • Ensure the creator role has sufficient permissions to revoke grants from managed users.