| # Gerrit SAML Authentication Filter |
| |
| This filter allows you to authenticate to Gerrit using a SAML identity |
| provider. |
| |
| ## Installation |
| |
| Gerrit looks for 3 attributes (which are configurable) in the AttributeStatement: |
| |
| - **DisplayName:** the full name of the user. |
| - **EmailAddress:** email address of the user. |
| - **UserName:** username (used for ssh). |
| |
| If any of these attributes is not found in the assertion, their value is |
| taken from the NameId field of the SAML assertion. |
| |
| ### Setting Gerrit in your IdP |
| |
| - [Okta](okta/README.md) |
| - [Keycloak](keycloak/README.md) |
| - [ADFS](adfs/README.md) |
| |
| ### Download the plugin |
| |
| Download Gerrit SAML plugin for the appropriate version of gerrit from the [Gerrit-CI](https://gerrit-ci.gerritforge.com/search/?q=saml) |
| into $gerrit_site/lib/. |
| |
| ### Building the SAML filter |
| |
| This authentication filter is built with Bazel. |
| |
| ## Build in Gerrit tree |
| |
| Clone or link this filter to the plugins directory of Gerrit's |
| source tree. Put the external dependency Bazel build file into |
| the Gerrit /plugins directory, replacing the existing empty one. |
| |
| ``` |
| cd gerrit/plugins |
| rm external_plugin_deps.bzl |
| ln -s @PLUGIN@/external_plugin_deps.bzl . |
| ``` |
| |
| Then issue |
| |
| ``` |
| bazel build plugins/@PLUGIN@ |
| ``` |
| |
| The output is created in |
| |
| ``` |
| bazel-bin/plugins/@PLUGIN@/@PLUGIN@.jar |
| ``` |
| |
| The @PLUGIN@.jar should be deployed to `gerrit_site/lib` directory: |
| |
| ``` |
| cp bazel-bin/plugins/@PLUGIN@/@PLUGIN@.jar `$gerrit_site/lib` |
| ``` |
| |
| __NOTE__: Even though the project is built as a Gerrit plugin, it must be loaded |
| as a Servlet filter by Gerrit and thus needs to be located with the libraries and |
| cannot be dynamically loaded like other plugins. |
| |
| This project can be imported into the Eclipse IDE. |
| Add the plugin name to the `CUSTOM_PLUGINS` set in |
| Gerrit core in `tools/bzl/plugins.bzl`, and execute: |
| |
| ``` |
| ./tools/eclipse/project.py |
| ``` |
| |
| How to build the Gerrit Plugin API is described in the [Gerrit documentation](../../../Documentation/dev-bazel.html#_extension_and_plugin_api_jar_files). |
| |
| ### Configure Gerrit to use the SAML filter: |
| In `$site_path/etc/gerrit.config` file, the `[httpd]` section should contain |
| |
| ``` |
| [httpd] |
| filterClass = com.googlesource.gerrit.plugins.saml.SamlWebFilter |
| ``` |
| |
| ### Configure HTTP authentication for Gerrit: |
| |
| Please make sure you are using Gerrit 2.11.5 or later. |
| |
| In `$site_path/etc/gerrit.config` file, the `[auth]` section should include |
| the following lines: |
| |
| ``` |
| [auth] |
| type = HTTP |
| logoutUrl = https://mysso.example.com/logout |
| httpHeader = X-SAML-UserName |
| httpDisplaynameHeader = X-SAML-DisplayName |
| httpEmailHeader = X-SAML-EmailHeader |
| httpExternalIdHeader = X-SAML-ExternalId |
| ``` |
| |
| The header names are used internally between the SAML plugin and Gerrit to |
| communicate the user's identity. You can use other names (as long as it will |
| not conflict with any other HTTP header Gerrit might expect). |
| |
| ### Create a local keystore |
| |
| In `$gerrit_site/etc` create a local keystore: |
| |
| ``` |
| keytool -genkeypair -alias pac4j -keypass pac4j-demo-password \ |
| -keystore samlKeystore.jks \ |
| -storepass pac4j-demo-password -keyalg RSA -keysize 2048 -validity 3650 |
| ``` |
| |
| ### Configure SAML |
| |
| Add a new `[saml]` section to `$site_path/etc/gerrit.config`: |
| |
| ``` |
| [saml] |
| keystorePath = /path/to/samlKeystore.jks |
| keystorePassword = pac4j-demo-password |
| privateKeyPassword = pac4j-demo-password |
| metadataPath = https://mycompany.okta.com/app/hashash/sso/saml/metadata |
| ``` |
| |
| **saml.metadataPath**: Location of IdP Metadata from your SAML identity provider. |
| The value can be a URL, or a local file (prefix with `file://`) |
| |
| **saml.keystorePath**: Path to the keystore created above. If not absolute, |
| the path is resolved relative to `$site_path`. |
| |
| **saml.privateKeyPassword**: Password protecting the private key of the generated |
| key pair (needs to be the same as the password provided throguh the `keypass` |
| flag above.) |
| |
| **saml.keystorePassword**: Password that is used to protect the integrity of the |
| keystore (needs to be the same as the password provided throguh the `keystore` |
| flag above.) |
| |
| **saml.maxAuthLifetime**: (Optional) Max Authentication Lifetime (secs) configuration. |
| |
| Default is `86400` |
| |
| **saml.displayNameAttr**: Gerrit will look for an attribute with this name in |
| the assertion to find a display name for the user. If the attribute is not |
| found, the NameId from the SAML assertion is used instead. |
| |
| Default is `DisplayName` |
| |
| **saml.computedDisplayName**: Set to compute display name attribute from first |
| and last names. |
| |
| Default is false. |
| |
| **saml.firstNameAttr**: Gerrit will look for an attribute with this name in |
| the assertion to find the first name of the user. Only used, when `computedDisplayName` |
| is set to true. If the attribute is not found, the NameId from the SAML assertion |
| is used instead. |
| |
| Default is `FirstName` |
| |
| **saml.lastNameAttr**: Gerrit will look for an attribute with this name in |
| the assertion to find the last name of the user. Only used, when `computedDisplayName` |
| is set to true. If the attribute is not found, the NameId from the SAML assertion |
| is used instead. |
| |
| Default is `LastName` |
| |
| **saml.emailAddressAttr**: Gerrit will look for an attribute with this name in |
| the assertion to find a the email address of the user. If the attribute is not |
| found, the NameId from the SAML assertion is used instead. |
| |
| Default is `EmailAddress` |
| |
| **saml.userNameAttr**: Gerrit will look for an attribute with this name in the |
| assertion to find a the email address of the user. If the attribute is not |
| found, the NameId from the SAML assertion is used instead. |
| |
| Default is `UserName` |
| |
| **saml.serviceProviderEntityId**: SAML service provider entity id. |
| |
| Default is not set. |
| |
| **saml.identityProviderEntityId**: SAML identity provider entity id. When present |
| a `IDPSSODescriptor` is expected in the SAML metadata document. When absent a |
| saml service provider with its `SPSSODescriptor` is assumed. |
| This value takes precedence over the value in **saml.serviceProviderEntityId**. |
| |
| Default is not set. |
| |
| **saml.memberOfAttr**: Gerrit will look for an attribute with this name in the |
| assertion to find the groups the user is member of. |
| |
| The user will receive these groups prefixed with `saml/` in gerrit. When the |
| groups do not exist, they will be created. When a user its membership is removed |
| this group will also be removed from this user on his next login. |
| |
| As group membership is only updated when a user logs in on the UI, so when a |
| user loses membership to a group in SAML, he will still be able to execute his |
| rights as if he is part of that group as long as he does not log in to the UI. |
| So enabling this feature can be seen as a security risk in certain environments. |
| |
| When this attribute is not set or empty, SAML membership synchronization is disabled. |
| |
| Default is not set. |
| |
| **saml.useNameQualifier**: By SAML specification, the authentication request must not contain a NameQualifier, if the SP entity is in the format nameid-format:entity. However, some IdP require that information to be present. You can force a NameQualifier in the request with the useNameQualifier parameter. For ADFS 3.0 support, set this to `false`. |
| |
| Default is true. |