diff --git a/docs/sources/enterprise/saml.md b/docs/sources/enterprise/saml.md index 332d8932069db..507cb6b9148b4 100644 --- a/docs/sources/enterprise/saml.md +++ b/docs/sources/enterprise/saml.md @@ -41,24 +41,26 @@ In terms of initiation: The table below describes all SAML configuration options. Continue reading below for details on specific options. Like any other Grafana configuration, you can apply these options as [environment variables]({{< relref "../administration/configuration.md#configure-with-environment-variables" >}}). -| Setting | Required | Description | Default | -| ----------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------- | ------------- | +| Setting | Required | Description | Default | +| ----------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------- | ------------- | | `enabled` | No | Whether SAML authentication is allowed | `false` | +| `single_logout` | No | Whether SAML Single Logout enabled | `false` | | `certificate` or `certificate_path` | Yes | Base64-encoded string or Path for the SP X.509 certificate | | | `private_key` or `private_key_path` | Yes | Base64-encoded string or Path for the SP private key | | +| `signature_algorithm` | No | Signature algorithm used for signing requests to the IdP. Supported values are rsa-sha1, rsa-sha256, rsa-sha512. | | | `idp_metadata`, `idp_metadata_path`, or `idp_metadata_url` | Yes | Base64-encoded string, Path or URL for the IdP SAML metadata XML | | | `max_issue_delay` | No | Duration, since the IdP issued a response and the SP is allowed to process it | `90s` | -| `metadata_valid_duration` | No | Duration, for how long the SP metadata is valid | `48h` | -| `assertion_attribute_name` | No | Friendly name or name of the attribute within the SAML assertion to use as the user name | `displayName` | -| `assertion_attribute_login` | No | Friendly name or name of the attribute within the SAML assertion to use as the user login handle | `mail` | -| `assertion_attribute_email` | No | Friendly name or name of the attribute within the SAML assertion to use as the user email | `mail` | -| `assertion_attribute_groups` | No | Friendly name or name of the attribute within the SAML assertion to use as the user groups | | -| `assertion_attribute_role` | No | Friendly name or name of the attribute within the SAML assertion to use as the user roles | | -| `assertion_attribute_org` | No | Friendly name or name of the attribute within the SAML assertion to use as the user organization | | +| `metadata_valid_duration` | No | Duration, for how long the SP metadata is valid | `48h` | +| `assertion_attribute_name` | No | Friendly name or name of the attribute within the SAML assertion to use as the user name | `displayName` | +| `assertion_attribute_login` | No | Friendly name or name of the attribute within the SAML assertion to use as the user login handle | `mail` | +| `assertion_attribute_email` | No | Friendly name or name of the attribute within the SAML assertion to use as the user email | `mail` | +| `assertion_attribute_groups` | No | Friendly name or name of the attribute within the SAML assertion to use as the user groups | | +| `assertion_attribute_role` | No | Friendly name or name of the attribute within the SAML assertion to use as the user roles | | +| `assertion_attribute_org` | No | Friendly name or name of the attribute within the SAML assertion to use as the user organization | | | `allowed_organizations` | No | List of comma- or space-separated organizations. User should be a member of at least one organization to log in. | | -| `org_mapping` | No | List of comma- or space-separated Organization:OrgId mappings | | -| `role_values_editor` | No | List of comma- or space-separated roles which will be mapped into the Editor role | | -| `role_values_admin` | No | List of comma- or space-separated roles which will be mapped into the Admin role | | +| `org_mapping` | No | List of comma- or space-separated Organization:OrgId mappings | | +| `role_values_editor` | No | List of comma- or space-separated roles which will be mapped into the Editor role | | +| `role_values_admin` | No | List of comma- or space-separated roles which will be mapped into the Admin role | | | `role_values_grafana_admin` | No | List of comma- or space-separated roles which will be mapped into the Grafana Admin (Super Admin) role | | ### Enable SAML authentication @@ -77,6 +79,10 @@ Grafana supports two ways of specifying both the `certificate` and `private_key` You can only use one form of each configuration option. Using multiple forms, such as both `certificate` and `certificate_path`, results in an error. +### Signature algorithm + +The SAML standard recommends using digital signature for some types of messages, like authentication or logout requests. If `signature_algorithm` option configured, Grafana will put digital signature into SAML requests. Supported signature types are `rsa-sha1`, `rsa-sha256`, `rsa-sha512`. This option should match your IdP configuration, otherwise, signature won't be validated by the IdP. Grafana uses key and certificate configured with `private_key` and `certificate` options for signing SAML requests. + ### IdP metadata You also need to define the public part of the IdP for message verification. The SAML IdP metadata XML defines where and how Grafana exchanges user information. @@ -107,6 +113,10 @@ The integration provides two key endpoints as part of Grafana: - The `/saml/metadata` endpoint, which contains the SP metadata. You can either download and upload it manually, or youmake the IdP request it directly from the endpoint. Some providers name it Identifier or Entity ID. - The `/saml/acs` endpoint, which is intended to receive the ACS (Assertion Customer Service) callback. Some providers name it SSO URL or Reply URL. +### Single Logout + +Single Logout feature allows user to log out from all applications associated with current IdP session established via SAML SSO. If `single_logout` option set to `true` and user logs out, Grafana requests IdP to terminate user session. Then IdP triggers logout process for all other applications which user logged in with the same IdP session (application should support single logout). And conversely, if another application connected to the same IdP initiates single logout, Grafana gets logout request from IdP and terminates user session. + ### Assertion mapping During the SAML SSO authentication flow, Grafana receives the ACS callback. The callback contains all the relevant information of the user under authentication embedded in the SAML response. Grafana parses the response to create (or update) the user within its internal database. diff --git a/go.mod b/go.mod index 851da3fc2b68f..d49cc764c41ed 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f github.com/aws/aws-sdk-go v1.33.12 + github.com/beevik/etree v1.1.0 github.com/benbjohnson/clock v0.0.0-20161215174838-7dc76406b6d3 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b github.com/centrifugal/centrifuge v0.11.0 @@ -67,7 +68,7 @@ require ( github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 github.com/robfig/cron/v3 v3.0.0 - github.com/russellhaering/goxmldsig v0.0.0-20200902171629-2e1fbc2c5593 // indirect + github.com/russellhaering/goxmldsig v0.0.0-20200902171629-2e1fbc2c5593 github.com/smartystreets/goconvey v1.6.4 github.com/stretchr/testify v1.6.1 github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf diff --git a/pkg/api/login.go b/pkg/api/login.go index 1090d668ebbde..d2818d7a5b6ea 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -254,6 +254,11 @@ func (hs *HTTPServer) loginUserWithUser(user *models.User, c *models.ReqContext) } func (hs *HTTPServer) Logout(c *models.ReqContext) { + if hs.Cfg.SAMLEnabled && hs.Cfg.SAMLSingleLogoutEnabled { + c.Redirect(setting.AppSubUrl + "/logout/saml") + return + } + if err := hs.AuthTokenService.RevokeToken(c.Req.Context(), c.UserToken); err != nil && err != models.ErrUserTokenNotFound { hs.log.Error("failed to revoke auth token", "error", err) } diff --git a/pkg/extensions/main.go b/pkg/extensions/main.go index d31e757668ece..18a2ef4e1d502 100644 --- a/pkg/extensions/main.go +++ b/pkg/extensions/main.go @@ -4,6 +4,7 @@ import ( // Upgrade ldapsync from cron to cron.v3 and // remove the cron (v1) dependency + _ "github.com/beevik/etree" _ "github.com/crewjam/saml" _ "github.com/gobwas/glob" "github.com/grafana/grafana/pkg/registry" @@ -15,6 +16,7 @@ import ( _ "github.com/pkg/errors" _ "github.com/robfig/cron" _ "github.com/robfig/cron/v3" + _ "github.com/russellhaering/goxmldsig" _ "github.com/stretchr/testify/require" _ "github.com/timberio/go-datemath" _ "gopkg.in/square/go-jose.v2" diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 9bd751b060597..1b8a06e54f48b 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -287,7 +287,8 @@ type Cfg struct { OAuthCookieMaxAge int // SAML Auth - SAMLEnabled bool + SAMLEnabled bool + SAMLSingleLogoutEnabled bool // Dataproxy SendUserHeader bool @@ -998,6 +999,7 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) { // SAML auth cfg.SAMLEnabled = iniFile.Section("auth.saml").Key("enabled").MustBool(false) + cfg.SAMLSingleLogoutEnabled = iniFile.Section("auth.saml").Key("single_logout").MustBool(false) // anonymous access AnonymousEnabled = iniFile.Section("auth.anonymous").Key("enabled").MustBool(false)