Skip to content

Commit

Permalink
SAML Single Logout (grafana#27995)
Browse files Browse the repository at this point in the history
* SAML: single logout WIP

* SAML: sign SAML requests

* SAML: remove unnecessary logs

* fix go mod file

* Docs: Single Logout

* SAML: use api endpoint for single logout

* Apply suggestions from code review

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>

* SAML: save context for single logout

* Chore: add SAML dependencies

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
  • Loading branch information
alexanderzobnin and marefr authored Oct 8, 2020
1 parent 46a91f2 commit b55a51e
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 14 deletions.
34 changes: 22 additions & 12 deletions docs/sources/enterprise/saml.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions pkg/api/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/extensions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down
4 changes: 3 additions & 1 deletion pkg/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ type Cfg struct {
OAuthCookieMaxAge int

// SAML Auth
SAMLEnabled bool
SAMLEnabled bool
SAMLSingleLogoutEnabled bool

// Dataproxy
SendUserHeader bool
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit b55a51e

Please sign in to comment.