认证与授权系统的汇总

作者: 李佶澳   转载请保留:原文地址   更新时间:2017/10/28 12:37:40

摘要

认证(Authentication):核实用户的身份,一般通过密码、证书等。

授权(Authorization):授予用户查询、管理、使用特定资源的权利。

  1. OpenID是现在流行的认证协议,目标服务可以通过与开放OpenID服务的第三方协商,验证用户身份。
  2. OAuth是现在流行的授权协议,资源管理方在得到用户的确认后,授予第三方访问特定资源的权利。
  3. OpenID Connect是基于OAuth2.0的认证协议。
  4. SSO是单点登陆的简称,用户登陆一次之后就可以访问多个服务,只包含认证功能,或者同时支持授权。

OpenID和OAuth每次和第三方交互时,都需要用户进行登陆操作, 这是与SSO的最大区别。

关于SSO

SSO,全称Signle Sign On,常翻译为“单点登陆”。目的是使用户在完成一次身份验证之后,就可以访问多个服务。

SSO是企业用户的刚性需求(特别是对于SaaS用户),有很多种实现方式(商业软件、免费软件、开源软件都有),详情见下面的链接:

https://en.wikipedia.org/wiki/List_of_single_sign-on_implementations

SSO更大的好处在于可以使用一致的方式跨多个应用程序实施访问策略, 并且认证和审计也得到了简化。

将单点登陆扩展到云

SSO的相关协议问世时间很早,例如Kerberos诞生在80年代。当前搜集到的SSO协议有:

Kerberos
CAS
SAML

在搜集资料的过程中,感觉商用的SSO产品大多支持SAML协议。

OpenID

OpenID是现在流行的认证协议,目的是使用户无需在多个服务上进行注册,只需要一个账号,就可以使用多个服务。

OpenID allows you to use an existing account to sign in to multiple websites, without needing to create new passwords.

OpenID开始于2005年,现在由OpenID基金会维护。当前版本是2.0,但是正在被OpenID Connect取代。

OpenID

OpenID wiki

OpenID 2.0迁移到OpenID Connect 1.0的方法

     +--------+  1. request services      +------------------------+
     |        |-------------------------|>|                        |
     |        |<|-------------------------|  Service  Provider     |
     |  User  |  3. redirect to Identify  |                        |
     |        |         Provider          +-.----------------------+
     |        |                            /_\  |        
     |        |                             |   |  
     |        |-----------------------------+   | 
     |        |  6. requst again with User      | 2. establish a
     |        |       info and key             _|_   shared  key 
     |        |                                \ /
     |        |  5. User Info and key     +-----'------------------+
     |        |<|-------------------------|                        |
     |        |                           |   Identify Provider    |
     |        |-------------------------|>|                        |
     +--------+  4. Login  in             +------------------------+

OpenID Connect

OpenID Connect是OpenID基金会制定的一个新的认证协议,基于OAuth2.0,API更为友好。

OpenID Connect 1.0 在2014年发布。

OpenID Connect

OpenID Connect (OIDC) is an authentication layer on top of OAuth 2.0, an authorization framework)
  1. 在OAuth2.0中,Authz Server需要对用户完成认证之后,再分发Token;
  2. 因此如果第三方能够得到有效的Token, 就可以认为用户的身份已经得到了认证;
  3. 同时根据OAuth2.0协议,第三方还可以使用Token, 从认证方获取用户的基本信息。

OAuth

OAuth是现在流行的授权协议,目的是使第三方在不得到用户的登陆凭证的情况下,获得访问用户托管的资源。

OAuth协议开始于2006年,于2012年发布了不向前兼容的2.0版本, OAuth2.0已经被RFC接受。

rfc6750

rfc6749

OAuth wiki

  +--------+                               +---------------+
  |        |--(A)- Authorization Request ->|   Resource    |
  |        |                               |     Owner     |
  |        |<-(B)-- Authorization Grant ---|               |
  |        |                               +---------------+
  |        |
  |        |                               +---------------+
  |        |--(C)-- Authorization Grant -->| Authorization |
  | Client |                               |     Server    |
  |        |<-(D)----- Access Token -------|               |
  |        |                               +---------------+
  |        |
  |        |                               +---------------+
  |        |--(E)----- Access Token ------>|    Resource   |
  |        |                               |     Server    |
  |        |<-(F)--- Protected Resource ---|               |
  +--------+                               +---------------+

Kerberos

Kerberos是MIT设计的SSO协议, 开发于80年代,被吸收为RFC,最先版本V5发布于2005年,RFC 4120。

Kerberos wiki

CAS

CAS是Yale设计的SSO协议,2014年发布了3.0。

CAS wiki

CAS

SAML

SAML是OASIS(Organization for the Advancement of Structured Information Standards)设计的一种SSO(单点登陆)协议。

SAML 1.0于2002年发布,当前的版本是2005年发布的SAML2.0。

SAML wiki

SAML 2.0

SSO的实现

OpenID和OAuth的有标准的协议,主要是互联网公司例如github.com、google、tencent等提供了对应服务, 都是按照协议办事。 而SSO的协议多,实现方案也多,同时有很多商用产品。因此这里只分析SSO的实现。

这里还特别关心下面的这些实现在授权方面的支持情况, 如果能在支持SSO的同时,支持灵活的、细力度的授权策略。如果服务 接入了SSO, 不仅不需要自己实现认证功能,而且也不需要实现授权功能,只需要在SSO中修改一下策略就能改变授权模式, 那么将是很有吸引力的。

OpenStack的实现

OpenStack由多个子服务组合而成,通过Keystone实现了SSO。

Keystone的v3版本的api中使用Project代替了租户。

增了domain,一个domain对应一个用户,用户可以在domain中创建多个project。

设计原则

OpenStack由多个子服务(nova、glance、neturon等)组成, OpenStack的用户会直接使用多个子服务。 例如,用户对虚拟机进行管理时,使用的是nova服务;用户管理网络时,使用的是neturon服务。 所以OpenStack的认证授权系统需要满足以下条件:

  1. 所有的子服务共享用户账号;
  2. 用户只需要认证一次,就可以使用所有的子服务;
  3. 所有子服务使用相同的授权模型;
  4. 授权模型要足够灵活。

子服务需要向用户授予以下几种类型的权限:

  1. 查阅资源的权限(读取资源列表,资源详情, 例如,查看Project中的实例列表);
  2. 修改资源的权限(增加、删除、修改状态,例如,创建、删除、启动、关停实例);
  3. 使用资源的权限 (例如,访问实例)。

查阅/修改资源, 都是对资源的管理。

子服务的授权需要满足以下条件:

  1. 使用相同的授权方式对“资源管理”进行授权;
  2. 使用自定义对授权方式对“资源使用”进行授权。

用户账号共享与一次认证

用户账号的管理和用户身份认证是每个子服务都需要的的功能,OpenStack将这两项功能从子服务中 剥离出来,做成了一个独立子服务——keystone。其它的子服务只需要与keystone进行交互,不需要 自行实现这两项功能。

基本原理如下:

  1. 用户账号数据全部存放在keystone中;
  2. 用户只向keystone发起认证,认证通过后,keystone维护一个Token,并将TokenID反馈給用户;
  3. 用户完成认证后,使用获得的TokenID,直接向对应的子服务发起操作请求;
  4. 子服务拒绝所有未提供TokenID的请求, 并将其重定向到keystone的认证界面;
  5. 子服务向keystone查询TokenID对应的Token的属性,从而得知发起请求的用户的身份。

对子服务进行一次成功请求的过程:

                                           Keystone
  +---+                                 +-----------------------------+
  |   |  ---------------------------->  | Users:  name    password    |
  |   |     1. (alice, admin)           |         alice    admin      |
  | A |                                 |         bob      [email protected]      |
  | l |                                 | ------------------------    |
  | i |                                 | Tokens:  ID      Token      |
  | c |  <----------------------------- |         aced..   alice'sXXX |
  | e |     2. (ID: aced...)            |         defx..   bob'sXXXX  |
  |   |                                 +-----------------------------+
  |   |                                               .    |
  |   |                                              /_\   |
  |   |                                               |    |
  |   |                           4. (aced.. is who?) |    | 5. (alice..)
  |   |                                               |   _|_
  |   |                                               |   \|/
  |   |                                 Sub Service   |    ' 
  |   |  ---------------------------->  +-----------------------------+
  |   |  3. (ID is aced..., Please.. )  | +------+   +-----+          |
  |   |                                 | |Alice |   |Bob  |          |
  |   |  <----------------------------  | +------+   +-----+          |
  |   |  6. (Alice, You are welcome)    +-----------------------------+
  +---+
  1. alice向keystone发起认证;
  2. alice的认证通过,得到了TokenID;
  3. alice使用TokenID向子服务发起请求;
  4. 子服务向keystone查询Token属性;
  5. keystone将Token属性告知子服务;
  6. 子服务判定alice有权力发起此请求。

因为每个子服务与keystone之间的交互过程都是雷同的,因此OpenStack将这一交互过程做成了认证组件。 认证组件拦截了向子服务发起的请求,代替子服务完成了与keystone的交互后,再将请求转发給子服务。 该认证组件是一个python代码包,只负责验证token的有效性,只有使用wsgi的python程序可以使用。

统一的授权模型

“如何授权”与子服务的功能是相关的。 OpenStack定义了一个授权的模型,具体的授权策略由每个子服务自己决定。

OpenStack的授权模型:

  1. Keystone将用户分组(Group),按组设置角色(Role),角色必须绑定(Assignment)到一个资源组(Domain、Project);
  2. 每个子服务都对资源进行两级划分,首先将资源按照Project分组,然后将Project按照Domain分组;
  3. 子服务通过比较从keystone中查询到的Token的属性与目标资源的属性决定是否对当前的操作进行授权。

资源的两级划分:

                  Domain1                                            Domain2
                 __  |  __                                          __  |  __        
               _/    |    \__                                     _/    |    \__     
             _/      |       \__                                _/      |       \__  
           _/        |          \_                            _/        |          \_
       Project1    Project2   Project3                    Project1    Project2   Project3
          _            |           _                         _            |           _   
        _/              \           \__                    _/              \           \__
     *******         *******         *******            *******         *******         *******    
   **       **     **       **     **       **        **       **     **       **     **       **  
  *   Port    *   *   Port    *   *   Port    *      *   Port    *   *   Port    *   *   Port    * 
 *    Image    * *    Image    * *    Image    *    *    Image    * *    Image    * *    Image    *
 *  Instance1  * *  Instance1  * *  Instance1  *    *  Instance1  * *  Instance1  * *  Instance1  *
 *  Instance2  * *  Instance2  * *  Instance2  *    *  Instance2  * *  Instance2  * *  Instance2  *
  *    ...    *   *    ...    *   *    ...    *      *    ...    *   *    ...    *   *    ...    * 
   **       **     **       **     **       **        **       **     **       **     **       **  
     *******         *******         *******            *******         *******         *******    

每个子服务都按照这种方式组织资源,都能够知晓自己管理的一个资源属于哪个Project,属于哪个Domain。

Openstack中的Token分为两类,没有指定scope的和指定了scope的,认证时通过设置请求参数scope的取值, 表明期待scope的类型.这样做一个好处是可以为scope(project)设置单独的认证凭证。

从Keystone查询到的未指定scope的Token的属性:

{
    "token": {
        "methods": [
            "token"
            ],
            "expires_at": "2015-11-05T22:00:11.000000Z",
            "extras": {},
            "user": {
                "domain": {
                    "id": "default",
                    "name": "Default"
                },
                "id": "10a2e6e717a245d9acad3e5f97aeca3d",
                "name": "admin"
            },
            "audit_ids": [
                "mAjXQhiYRyKwkB4qygdLVg"
                ],
            "issued_at": "2015-11-05T21:00:33.819948Z"
    }
}

从Keystone查询到的指定了scope的Token的属性, 注意多出的Project等:

{
    "token": {
        "methods": [
            "password"
            ],
            "roles": [
            {
                "id": "51cc68287d524c759f47c811e6463340",
                "name": "admin"
            }
        ],
        "expires_at": "2015-11-07T02:58:43.578887Z",
        "project": {
            "domain": {
                "id": "default",
                "name": "Default"
            },
            "id": "a6944d763bf64ee6a275f1263fae0352",
            "name": "admin"
        },
        "catalog": [
            {
                "endpoints": [
                {
                    "region_id": "RegionOne",
                    "url": "http://23.253.248.171:5000/v2.0",
                    "region": "RegionOne",
                    "interface": "public",
                    "id": "068d1b359ee84b438266cb736d81de97"
                },
                {
                    "region_id": "RegionOne",
                    "url": "http://23.253.248.171:35357/v2.0",
                    "region": "RegionOne",
                    "interface": "admin",
                    "id": "8bfc846841ab441ca38471be6d164ced"
                },
                {
                    "region_id": "RegionOne",
                    "url": "http://23.253.248.171:5000/v2.0",
                    "region": "RegionOne",
                    "interface": "internal",
                    "id": "beb6d358c3654b4bada04d4663b640b9"
                }
                ],
                    "type": "identity",
                    "id": "050726f278654128aba89757ae25950c",
                    "name": "keystone"
            },
            {
                ...省略其它的entpoints...
            }
        ],
        "extras": {},
        "user": {
            "domain": {
                "id": "default",
                "name": "Default"
            },
            "id": "ee4dfb6e5540447cb3741905149d9b6e",
            "name": "admin"
        },
        "audit_ids": [
            "3T2dc1CGQxyJsHdDu1xkcw"
            ],
        "issued_at": "2015-11-07T01:58:43.578929Z"
    }
}

Openstack子服务授权策略的实现

Openstack的子服务全部使用REST接口,将授权问题转化为“向用户授予使用某个API的权利”。

Openstack原生的子服务均是使用策略文件(policy.json)来描述具体的授权策略,策略文件中规定了每个API的授权条件。

所谓的授权条件也就是,Token的属性是否与资源的属性相匹配。

以Nova的授权策略文件为例:

{
    "context_is_admin":  "role:admin",
    //admin_or_owner条件成立的含义是: 用户是admin,或者用户的project_id与目标project的id相同
    "admin_or_owner":  "is_admin:True or project_id:%(project_id)s",

    //默认的策略是 admin_or_owner
    "default": "rule:admin_or_owner",   
     ...(省略)...
    //使用"default", 只有admin或者owner才可以使用“compute”服务中的下列操作
    "compute:create": "",
    "compute:create:attach_network": "",
    "compute:create:attach_volume": "",
     ...(省略)...
    //只有admin或者owner才可以使用“compute”服务中的下列操作
    "compute:delete": "rule:admin_or_owner",
    "compute:soft_delete": "rule:admin_or_owne"
     ...(省略)...
}

授权策略中的“compute:create”、“compute:create:attach_network”等是“Target”, 也就是每个REST API的简称。

子服务自行定义Target的名称以及与api的对应关系。

Nova没有提供说明Target与API的映射关系的文档。这里以keystone文档中说明的映射关系为例:

     Target                       API
identity:get_region      GET /v3/regions/{region_id}
identity:list_regions    GET /v3/regions
identity:create_region   POST /v3/regions
....(省略) ....

keystone除了提供认证服务,还要提供用户的管理服务,例如创建用户组(group)、设置角色等,因此它自身也需要有授权策略。

keystone既提供了认证服务,又实现了自己的授权策略,而其它子服务只需要实现自己的授权策略。

Ping Identify

Ping Identity是专业的SSO厂商, 后起之秀,它的产品感觉比其他的厂商要先进很多。

特别是PingAccess提供了基于属性的认证ABAC、RBAC,这一点特别有吸引力。

有四款商用产品: PingID、PingFederate、PingOne、PingAccess。

PingID是一个支持多因素认证的认证服务, 其他服务可以使用PingID的认证服务。

Strong authentication to legacy and cloud applications using a mobile app.
Out of the box integration with PingOne® and PingFederate®.
Support for VPN servers using the RADIUS protocol.
Ability for users to authenticate with the Apple Watch.
Biometrics support on select Apple and Samsung devices.
Offline support using one-time passcode.
Hardtoken support with YubiKey.

相当于一个可以对用户进行多因素验证的OpenID服务。

PingFederate是集成了认证功能、支持SSO(单点登录)授权服务,支持多个认证协议:

Supporting all of the current identity standards including SAML, WS-Federation, WS-Trust, OAuth and OpenID Connect。

PingAccess基于PingFederate, 提供了丰富地访问控制策略:

Identity Attributes (ABAC / RBAC)
Authentication Levels
Network Ranges
Web Session Attributes
OAuth Attributes
OAuth Scopes
Time Ranges
Groovy Scripts
Custom Services (via SDK)

PingOne是用来进行多因素验证的客户端, 可以添加多个登录目标。

IBM DataPower

WebSphere DataPower是IBM的商用产品。对授权的支持情况还未知。

使用IBM WebSphere DataPower实现Salesforce联合单点登陆

OpenAM

OpenAM的前身是OpenSSO。OpenSSO是Sun公司在2005发起的开源项目,在2008年发布了企业版8.0。但是Oracle收购Sun公司后, 关闭了这个项目,ForgeRock公司创建了OpenAM分支来延续OpenSSO。

OpenAM提供比较丰富的授权策略设置方式。

ForgeRock现在仍在推动OpenAM项目的开发:

OpenAM Roadmap

OpenAM Get Start

OpenAM Source

ForgeRock一共有四个项目: OpenAM、OpenDJ、OpenIDM、OpenIG。

OpenDJ是兼容LDAPv3的目录服务。

OpenIDM是认证管理平台,使用javascript描述规则。

OpenIG是一个SAML2网关,用于在不改动应用程序的情况接入OpenAM。

CAS Server

CAS最早是由Yale设计的,2004年成为JASIG(Java in Administration Special Interest Group)的项目,JASIG推动该项目:

CAS Server Source

Open Source licensed under Apache v2; https://github.com/Jasig/cas
CAS protocol (both as an identity provider and a service provider)
OpenID (both as an identity provider and a service provider)
OAuth (both as an identity provider and a service provider)
SAML v1.1 protocol
SAML v2 identity provider; reserved for GoogleApps integration
SAML v2 as a service provider
WsFed protocol (as a service provider to integrate with ADFS)
Clearpass; capture, cache, encrypt and provide the user credential to the application
High availability and clustering via distributed caches such Ehcache, Hazelcast, Memcached, etc
Management interface to handle application registration and metadata
Rich attribute resolution/filtering model
Support for variety of authentication sources such as LDAP, JDBC, SPNEGO, RADIUS, JAAS, etc

JOSSO

JOSSO是另一个开源的SSO项目, 该项目还在活跃,但是维护者的情况还不清楚。

JOSSO对授权对支持情况还未知。

JOSSO

J2EE, Spring and Windows Transparent cross-domain/cross-organization Single Sign-On
SAML, OpenID, OpenID Connect, OAuth, WS-Federation support for seamless Cloud/Federated SSO experience
Bundled with GUI Console for a purely point-and-click setup and administration experience
Pluggable Framework to allow the implementation of custom identity components using Spring or built-in IoC container.
"5 minutes" on-the-fly set-up and deployment through custom "enhancement" console
Runs in Apache Tomcat.
Runs in JBoss application server.
Runs in BEA WebLogic 8, 9 and 10 application server
Runs in Websphere CE application server
Runs in Apache Geronimo application server
Runs in Windows IIS as an ISAPI connector
Runs in any JASPI-compatible (JSR196) container such as JBoss 5 and GlassFish
Out-of-the-box compatibility with Liferay Portal, JBoss Portal, JBoss GateIn Portal, Alfresco CMS, OpenCMS, Wavemaker and phpBB
Native Apache Http 2.x support thus enabling transparent SSO with Ruby, PHP, Python, Perl, etc. applications
Integrates with Spring Security for enabling fine-grained authorization.
Provides Identity information to Web applications and EJBs through the standard Servlet and EJB Security API respectively.
Supports Strong Authentication using X.509 client certificates.
Windows Authentication
LDAP support for storing user information and credentials.
Database support for storing user information and credentials.
Includes virtual directory functionality for allowing authentication against multiple disparate identity silos
"Remember Me" support
Password reset support
Client API for PHP. This allows to build SSO-enabled PHP applications.
Client API for Microsoft ASP. This allows to build SSO-enabled ASP applications.
Out-of-the-box branding support
Compatibility with Apache Pluto Portlet Container
Standard Based: SAML2, OSGi, JAAS, Web Services/SOAP, EJB, Struts, Servlet/JSP,J2EE.
100% Java

Keycloak

Keycloak是JBoss公司维护的SSO实现,JBoss已经被Redhat收购, Keycloak项目还在继续。

http://keycloak.jboss.org/

Keycloak Source

OpenID Connect and SAML 2.0 SSO and Single Log Out for browser applications
Social Broker.  Enable Google, Facebook, Yahoo, Twitter social login with no code required.
Identity Broker.  Delegate to an external SAML 2.0 or OIDC broker for auth.
Optional LDAP/Active Directory integration
Optional User Registration, with optional Recaptcha ability
Password and TOTP support (via Google Authenticator).  Client cert auth coming soon.
User session management from both admin and user perspective
Customizable themes for user facing pages: login, grant pages, account management, emails, and admin console all customizable!
OAuth 2.0 Bearer token auth for REST Services
Integrated Browser App to REST Service token propagation
Admin REST API
CORS Support
Completely centrally managed user and role mapping metadata.  Minimal configuration at the application side
Admin Console for managing users, roles, role mappings, applications, user sessions, allowed CORS web origins, and OAuth clients.
Deployable as a WAR, appliance, or an Openshift  cloud service (SaaS).
Supports JBoss AS7, EAP 6.x, Wildfly, Tomcat, Jetty, and Pure Javascript applications.   Plans to support Node.js, RAILS, GRAILS, and other non-Java applications.
HTTP Security Proxy for environments/platforms/languages that don't have a client adapter
Javascript/HTML 5 adapter for pure Javascript apps
Session management from admin console
Claim/assertion mappings.  Make your tokens and assertion XML look however you want.
Revocation policies
Password policies
Impersonation.  Allow your admins to impersonate a user to debug problems.

gluu

gluu是Gluu公司开发开源的SSO实现,Gluu公司成立于2008年,致力于提供简单廉价的SSO。

gluu

history

Gluu Source

Lemon

Lemon

文献

  1. http://developer.openstack.org/api-guide/quick-start/api-quick-start.html
  2. http://developer.openstack.org/api-ref-identity-v3.html#authenticate-v3
  3. http://docs.openstack.org/admin-guide-cloud/identity_service_api_protection.html
  4. http://www.javacodegeeks.com/2013/11/authentication-and-authorization-as-an-open-source-solution-service.html
  5. https://en.wikipedia.org/wiki/OpenSSO
  6. https://en.wikipedia.org/wiki/OpenAM
  7. https://www.atlassian.com/software/crowd/overview/
  8. https://forgerock.org/
  9. https://forgerock.org/projects/getting-the-source-code/
  10. https://en.wikipedia.org/wiki/List_of_single_sign-on_implementations
  11. 将单点登陆扩展到云

本文原创首发于网站:www.lijiaocn.com

QQ交流群

区块链实践互助QQ群:576555864

Kubernetes实践互助QQ群:947371129

Prometheus实践互助QQ群:952461804

Kong/Envoy实践互助QQ群:952503851

Ansible实践互助QQ群:955105412

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作 友情链接: lijiaocn github.com