GitLab’s SAML Single Sign-On (SSO) and LDAP integration work together to give you centralized, secure user management, but the real magic is how they can enforce access policies across your entire organization without you touching individual user accounts.
Let’s see this in action with a typical scenario: Alice, an employee, needs access to your company’s GitLab instance.
First, Alice logs into her company’s Identity Provider (IdP), say Okta, using her corporate credentials. Okta authenticates her.
# Alice's browser, POST request to GitLab's SAML endpoint
# This is a simplified representation of the SAML assertion
POST /users/auth/saml/callback HTTP/1.1
Host: gitlab.example.com
Content-Type: application/x-www-form-urlencoded
SAMLResponse=PHNhbWw6QWNzZXJ0aW9uIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0Y246U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOmRzZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDIvMTAveG1sZHNlYyMiIHhtbG5zOmV4c2VjPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTG1lY2hhbmlzbWUiIHZlcnNpb249IjIuMCIgSUQ9Il9lY2M2Y2M5YjY3NDZlNTFmNDRiNDQxNDk2YjU5YjA0Yzk0YmY0YTJmIj4KICA8c2Ft: ... (truncated SAML assertion) ...
GitLab receives this SAML assertion. It verifies the signature using the IdP’s public certificate, ensuring the assertion hasn’t been tampered with. It then extracts Alice’s user information (like her email address) from the assertion.
If Alice is a new user, GitLab checks its LDAP configuration. It uses the email address from the SAML assertion to find Alice in the company’s LDAP directory.
# GitLab server, LDAP search query (simplified)
# This happens internally after SAML authentication
# Base DN: dc=example,dc=com
# Filter: (&(mail=alice@example.com)(objectClass=inetOrgPerson))
# Attributes: uid, mail, sn, givenName, cn
GitLab finds Alice in LDAP. It then creates a new user account in GitLab, populating fields like username, name, and email from the LDAP entry. The user is automatically logged into GitLab.
If Alice already exists in GitLab (perhaps created manually or from a previous LDAP sync), GitLab links the SAML identity to her existing account based on the email address.
The problem this solves is twofold:
- User Provisioning: Alice doesn’t need a separate GitLab password. Her access is managed by Okta. When she leaves the company, her Okta account is deactivated, and she automatically loses access to GitLab (via SAML).
- Authentication: Okta handles the heavy lifting of authenticating Alice, adhering to company security policies (like multi-factor authentication). GitLab trusts Okta’s assertion.
Here’s a peek at the GitLab configuration (gitlab.rb for Omnibus installations) that makes this work:
# SAML configuration
gitlab_rails['gitlab_saml_enabled'] = true
gitlab_rails['gitlab_saml_provider_name'] = 'Okta'
gitlab_rails['gitlab_saml_assertion_consumer_service_url'] = 'https://gitlab.example.com/users/auth/saml/callback'
gitlab_rails['gitlab_saml_idp_cert'] = File.read('/etc/gitlab/ssl/okta.crt')
gitlab_rails['gitlab_saml_idp_sso_url'] = 'https://example.okta.com/app/gitlab_example/sso/saml/0oa123abcd/1234567890abcdef'
gitlab_rails['gitlab_saml_idp_metadata_url'] = 'https://example.okta.com/app/gitlab_example/sso/saml/metadata/0oa123abcd' # Or use metadata file
gitlab_rails['gitlab_saml_subject_format'] = 'email'
gitlab_rails['gitlab_saml_attribute_statements'] = {
email: 'email',
name: 'name',
first_name: 'first_name',
last_name: 'last_name'
}
# LDAP configuration
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
main:
label: 'Company LDAP'
host: 'ldap.example.com'
port: 389
uid: 'uid'
method: 'plain' # 'ssl' or 'tls'
attributes:
username: ['uid', 'login']
email: ['mail', 'email', 'emailAddress']
name: 'cn'
first_name: 'givenName'
last_name: 'sn'
sync_ssh_keys: true
sync_groups: false # For this example, we sync users, not groups
base: 'dc=example,dc=com'
user_filter: '(&(objectClass=inetOrgPerson)(memberOf=cn=gitlab-users,ou=groups,dc=example,dc=com))' # Optional: only sync users in a specific group
EOS
After applying these configurations and restarting GitLab (sudo gitlab-ctl reconfigure), a user logging into https://gitlab.example.com will be redirected to Okta. Upon successful authentication with Okta, they are returned to GitLab and logged in, with their GitLab account either created or linked based on their LDAP identity.
The user_filter in the LDAP configuration is a powerful, often overlooked lever. When set, it doesn’t just filter what users can be synced from LDAP; it also dictates which users GitLab will attempt to link during SAML authentication. If a user authenticates via SAML but doesn’t match the user_filter in LDAP, GitLab will refuse to log them in, effectively enforcing group-based access policies through LDAP membership.
The next step is to explore how to manage group synchronization from LDAP to automatically assign users to GitLab groups upon login.