Merge "Restructure to better accomodate new functionality"
[docs.git] / docs / user-guide / authentication-and-authorization-services.rst
1 Authentication, Authorization and Accounting (AAA) Services
2 ===========================================================
3
4 Overview
5 --------
6
7 Authentication, Authorization and Accounting (AAA) is a term for a
8 framework controlling access to resources, enforcing policies to use
9 those resources and auditing their usage. These processes are the
10 fundamental building blocks for effective network management and security.
11
12 Authentication provides a way of identifying a user, typically by
13 having the user enter a valid user name and valid password before access
14 is granted. The process of authentication is based on each user having a unique
15 set of criteria for gaining access. The AAA framework compares a user's
16 authentication credentials with other user credentials stored in a database.
17 If the credentials match, the user is granted access to the network.
18 If the credentials don't match, authentication fails and access is denied.
19
20 Authorization is the process of finding out what an authenticated user is
21 allowed to do within the system, which tasks can do, which API can call, etc.
22 The authorization process determines whether the user has the authority
23 to perform such actions.
24
25 Accounting is the process of logging the activity of an authenticated user,
26 for example, the amount of data a user has sent and/or received during a
27 session, which APIs called, etc.
28
29 Terms And Definitions
30 ^^^^^^^^^^^^^^^^^^^^^
31
32 AAA
33     Authentication, Authorization and Accounting.
34
35 Token
36     A claim of access to a group of resources on the controller.
37
38 Domain
39     A group of resources, direct or indirect, physical, logical, or
40     virtual, for the purpose of access control.
41
42 User
43     A person who either owns or has access to a resource or group of
44     resources on the controller.
45
46 Role
47     Opaque representation of a set of permissions, which is merely a
48     unique string as admin or guest.
49
50 Credential
51     Proof of identity such as user name and password, OTP, biometrics, or
52     others.
53
54 Client
55     A service or application that requires access to the controller.
56
57 Claim
58     A data set of validated assertions regarding a user, e.g. the role,
59     domain, name, etc.
60
61 IdP
62     Identity Provider.
63
64 Security Framework for AAA services
65 -----------------------------------
66
67 Since Boron release, the OpenDaylight's AAA services are based on the
68 `Apache Shiro <https://shiro.apache.org/>`_ Java Security Framework. The main
69 configuration file for AAA is located at “etc/shiro.ini” relative to the
70 OpenDaylight Karaf home directory.
71
72
73 How to enable AAA
74 -----------------
75
76 AAA is enabled through installing the odl-aaa-shiro feature. The vast majority
77 of OpenDaylight's northbound APIs (and all RESTCONF APIs) are protected by AAA
78 by default when installing the +odl-restconf+ feature, since the odl-aaa-shiro
79 is automatically installed as part of them. In the cases that APIs are *not*
80 protected by AAA, this will be noted in the per-project release notes.
81
82
83 How to disable AAA
84 ------------------
85
86 Edit the “etc/shiro.ini” file and replace the following:
87
88 ::
89
90     /** = authcBasic
91
92 with
93
94 ::
95
96     /** = anon
97
98 Then restart the Karaf process.
99
100 AAA Realms
101 ----------
102
103 AAA plugin utilizes the Shiro Realms to support pluggable authentication &
104 authorization schemes. There are two parent types of realms:
105
106 -  AuthenticatingRealm
107
108    -  Provides no Authorization capability.
109
110    -  Users authenticated through this type of realm are treated
111       equally.
112
113 -  AuthorizingRealm
114
115    -  AuthorizingRealm is a more sophisticated AuthenticatingRealm,
116       which provides the additional mechanisms to distinguish users
117       based on roles.
118
119    -  Useful for applications in which roles determine allowed
120       capabilities.
121
122 OpenDaylight contains four implementations:
123
124 -  TokenAuthRealm
125
126    -  An AuthorizingRealm built to bridge the Shiro-based AAA service
127       with the h2-based AAA implementation.
128
129    -  Exposes a RESTful web service to manipulate IdM policy on a
130       per-node basis. If identical AAA policy is desired across a
131       cluster, the backing data store must be synchronized using an out
132       of band method.
133
134    -  A python script located at “etc/idmtool” is included to help
135       manipulate data contained in the TokenAuthRealm.
136
137    -  Enabled out of the box. This is the realm configured by default.
138
139 -  ODLJndiLdapRealm
140
141    -  An AuthorizingRealm built to extract identity information from IdM
142       data contained on an LDAP server.
143
144    -  Extracts group information from LDAP, which is translated into
145       OpenDaylight roles.
146
147    -  Useful when federating against an existing LDAP server, in which
148       only certain types of users should have certain access privileges.
149
150    -  Disabled out of the box.
151
152 -  ODLJndiLdapRealmAuthNOnly
153
154    -  The same as ODLJndiLdapRealm, except without role extraction.
155       Thus, all LDAP users have equal authentication and authorization
156       rights.
157
158    -  Disabled out of the box.
159
160 -  ODLActiveDirectoryRealm
161
162    - Wraps the generic ActiveDirectoryRealm provided by Shiro. This allows for
163      enhanced logging as well as isolation of all realms in a single package,
164      which enables easier import by consuming servlets.
165
166 .. note::
167
168     More than one Realm implementation can be specified. Realms are attempted
169     in order until authentication succeeds or all realm sources are exhausted.
170
171
172 TokenAuthRealm
173 ^^^^^^^^^^^^^^
174
175 How it works
176 ~~~~~~~~~~~~
177
178 The TokenAuthRealm is the default Authorization Realm deployed in OpenDaylight.
179 TokenAuthRealm uses a direct authentication mechanism as shown in the following
180 picture:
181
182 .. figure:: ./images/aaa/direct-authentication.png
183    :alt: TokenAuthRealm direct authentication mechanism
184
185    TokenAuthRealm direct authentication mechanism
186
187 A user presents some credentials (e.g., username/password) directly to the
188 OpenDaylight controller token endpoint /oauth2/token and receives an access
189 token, which then can be used to access protected resources on the controller.
190
191 Configuring TokenAuthRealm
192 ~~~~~~~~~~~~~~~~~~~~~~~~~~
193
194 The TokenAuthRealm stores IdM data in an h2 database on each node. Thus,
195 configuration of a cluster currently requires configuring the desired IdM policy
196 on each node. There are two supported methods to manipulate the TokenAuthRealm
197 IdM configuration:
198
199 -  idmtool configuration tool
200
201 -  RESTful Web Service configuration
202
203 **Idmtool**
204 ###########
205
206 A utility script located at “etc/idmtool” is used to manipulate the
207 TokenAuthRealm IdM policy. idmtool assumes a single domain, the default one
208 (sdn), since multiple domains are not supported in the Boron release. General
209 usage information for idmtool is derived through issuing the following command:
210
211 ::
212
213     $ python etc/idmtool -h
214     usage: idmtool [-h] [--target-host TARGET_HOST]
215                    user
216                    {list-users,add-user,change-password,delete-user,list-domains,list-roles,add-role,delete-role,add-grant,get-grants,delete-grant}
217                    ...
218
219     positional arguments:
220       user                  username for BSC node
221       {list-users,add-user,change-password,delete-user,list-domains,list-roles,add-role,delete-role,add-grant,get-grants,delete-grant}
222                             sub-command help
223         list-users          list all users
224         add-user            add a user
225         change-password     change a password
226         delete-user         delete a user
227         list-domains        list all domains
228         list-roles          list all roles
229         add-role            add a role
230         delete-role         delete a role
231         add-grant           add a grant
232         get-grants          get grants for userid on sdn
233         delete-grant        delete a grant
234
235     optional arguments:
236       -h, --help            show this help message and exit
237       --target-host TARGET_HOST
238                             target host node
239
240 Add a user
241 ''''''''''
242
243 ::
244
245     python etc/idmtool admin add-user newUser
246     Password:
247     Enter new password:
248     Re-enter password:
249     add_user(admin)
250
251     command succeeded!
252
253     json:
254     {
255         "description": "",
256         "domainid": "sdn",
257         "email": "",
258         "enabled": true,
259         "name": "newUser",
260         "password": "**********",
261         "salt": "**********",
262         "userid": "newUser@sdn"
263     }
264
265 .. note::
266
267     AAA redacts the password and salt fields for security purposes.
268
269 Delete a user
270 '''''''''''''
271
272 ::
273
274     $ python etc/idmtool admin delete-user newUser@sdn
275     Password:
276     delete_user(newUser@sdn)
277
278     command succeeded!
279
280 List all users
281 ''''''''''''''
282
283 ::
284
285     $ python etc/idmtool admin list-users
286     Password:
287     list_users
288
289     command succeeded!
290
291     json:
292     {
293         "users": [
294             {
295                 "description": "user user",
296                 "domainid": "sdn",
297                 "email": "",
298                 "enabled": true,
299                 "name": "user",
300                 "password": "**********",
301                 "salt": "**********",
302                 "userid": "user@sdn"
303             },
304             {
305                 "description": "admin user",
306                 "domainid": "sdn",
307                 "email": "",
308                 "enabled": true,
309                 "name": "admin",
310                 "password": "**********",
311                 "salt": "**********",
312                 "userid": "admin@sdn"
313             }
314         ]
315     }
316
317 Change a user’s password
318 ''''''''''''''''''''''''
319
320 ::
321
322     $ python etc/idmtool admin change-password admin@sdn
323     Password:
324     Enter new password:
325     Re-enter password:
326     change_password(admin)
327
328     command succeeded!
329
330     json:
331     {
332         "description": "admin user",
333         "domainid": "sdn",
334         "email": "",
335         "enabled": true,
336         "name": "admin",
337         "password": "**********",
338         "salt": "**********",
339         "userid": "admin@sdn"
340     }
341
342 Add a role
343 ''''''''''
344
345 ::
346
347     $ python etc/idmtool admin add-role network-admin
348     Password:
349     add_role(network-admin)
350
351     command succeeded!
352
353     json:
354     {
355         "description": "",
356         "domainid": "sdn",
357         "name": "network-admin",
358         "roleid": "network-admin@sdn"
359     }
360
361 Delete a role
362 '''''''''''''
363
364 ::
365
366     $ python etc/idmtool admin delete-role network-admin@sdn
367     Password:
368     delete_role(network-admin@sdn)
369
370     command succeeded!
371
372 List all roles
373 ''''''''''''''
374
375 ::
376
377     $ python etc/idmtool admin list-roles
378     Password:
379     list_roles
380
381     command succeeded!
382
383     json:
384     {
385         "roles": [
386             {
387                 "description": "a role for admins",
388                 "domainid": "sdn",
389                 "name": "admin",
390                 "roleid": "admin@sdn"
391             },
392             {
393                 "description": "a role for users",
394                 "domainid": "sdn",
395                 "name": "user",
396                 "roleid": "user@sdn"
397             }
398         ]
399     }
400
401 List all domains
402 ''''''''''''''''
403
404 ::
405
406     $ python etc/idmtool admin list-domains
407     Password:
408     list_domains
409
410     command succeeded!
411
412     json:
413     {
414         "domains": [
415             {
416                 "description": "default odl sdn domain",
417                 "domainid": "sdn",
418                 "enabled": true,
419                 "name": "sdn"
420             }
421         ]
422     }
423
424 Add a grant
425 '''''''''''
426
427 ::
428
429     $ python etc/idmtool admin add-grant user@sdn admin@sdn
430     Password:
431     add_grant(userid=user@sdn,roleid=admin@sdn)
432
433     command succeeded!
434
435     json:
436     {
437         "domainid": "sdn",
438         "grantid": "user@sdn@admin@sdn@sdn",
439         "roleid": "admin@sdn",
440         "userid": "user@sdn"
441     }
442
443 Delete a grant
444 ''''''''''''''
445
446 ::
447
448     $ python etc/idmtool admin delete-grant user@sdn admin@sdn
449     Password:
450     http://localhost:8181/auth/v1/domains/sdn/users/user@sdn/roles/admin@sdn
451     delete_grant(userid=user@sdn,roleid=admin@sdn)
452
453     command succeeded!
454
455 Get grants for a user
456 '''''''''''''''''''''
457
458 ::
459
460     python etc/idmtool admin get-grants admin@sdn
461     Password:
462     get_grants(admin@sdn)
463
464     command succeeded!
465
466     json:
467     {
468         "roles": [
469             {
470                 "description": "a role for users",
471                 "domainid": "sdn",
472                 "name": "user",
473                 "roleid": "user@sdn"
474             },
475             {
476                 "description": "a role for admins",
477                 "domainid": "sdn",
478                 "name": "admin",
479                 "roleid": "admin@sdn"
480             }
481         ]
482     }
483
484 **Configuration using the RESTful Web Service**
485 ###############################################
486
487 The TokenAuthRealm IdM policy is fully configurable through a RESTful
488 web service. Full documentation for manipulating AAA IdM data is located
489 online (https://wiki.opendaylight.org/images/0/00/AAA_Test_Plan.docx),
490 and a few examples are included in this guide:
491
492 Get All Users
493 '''''''''''''
494
495 ::
496
497     curl -u admin:admin http://localhost:8181/auth/v1/users
498     OUTPUT:
499     {
500         "users": [
501             {
502                 "description": "user user",
503                 "domainid": "sdn",
504                 "email": "",
505                 "enabled": true,
506                 "name": "user",
507                 "password": "**********",
508                 "salt": "**********",
509                 "userid": "user@sdn"
510             },
511             {
512                 "description": "admin user",
513                 "domainid": "sdn",
514                 "email": "",
515                 "enabled": true,
516                 "name": "admin",
517                 "password": "**********",
518                 "salt": "**********",
519                 "userid": "admin@sdn"
520             }
521         ]
522     }
523
524 Create a User
525 '''''''''''''
526
527 ::
528
529     curl -u admin:admin -X POST -H "Content-Type: application/json" --data-binary @./user.json http://localhost:8181/auth/v1/users
530     PAYLOAD:
531     {
532         "name": "ryan",
533         "userid": "ryan@sdn",
534         "password": "ryan",
535         "domainid": "sdn",
536         "description": "Ryan's User Account",
537         "email": "ryandgoulding@gmail.com"
538     }
539
540     OUTPUT:
541     {
542         "userid":"ryan@sdn",
543         "name":"ryan",
544         "description":"Ryan's User Account",
545         "enabled":true,
546         "email":"ryandgoulding@gmail.com",
547         "password":"**********",
548         "salt":"**********",
549         "domainid":"sdn"
550     }
551
552 Create an OAuth2 Token For Admin Scoped to SDN
553 ''''''''''''''''''''''''''''''''''''''''''''''
554
555 ::
556
557     curl -d 'grant_type=password&username=admin&password=a&scope=sdn' http://localhost:8181/oauth2/token
558
559     OUTPUT:
560     {
561         "expires_in":3600,
562         "token_type":"Bearer",
563         "access_token":"5a615fbc-bcad-3759-95f4-ad97e831c730"
564     }
565
566 Use an OAuth2 Token
567 '''''''''''''''''''
568
569 ::
570
571     curl -H "Authorization: Bearer 5a615fbc-bcad-3759-95f4-ad97e831c730" http://localhost:8181/auth/v1/domains
572     {
573         "domains":
574         [
575             {
576                 "domainid":"sdn",
577                 "name":"sdn”,
578                 "description":"default odl sdn domain",
579                 "enabled":true
580             }
581         ]
582     }
583
584 **Token Store Configuration Parameters**
585 ########################################
586
587 Edit the file “etc/opendaylight/karaf/08-authn-config.xml” and edit the
588 following: .\ **timeToLive**: Configure the maximum time, in milliseconds,
589 that tokens are to be cached. Default is 360000. Save the file.
590
591 ODLJndiLdapRealm
592 ^^^^^^^^^^^^^^^^
593
594 How it works
595 ~~~~~~~~~~~~
596
597 LDAP integration is provided in order to externalize identity
598 management. This configuration allows federation with an external LDAP server.
599 The user’s OpenDaylight role parameters are mapped to corresponding LDAP
600 attributes as specified by the groupRolesMap. Thus, an LDAP operator can
601 provision attributes for LDAP users that support different OpenDaylight role
602 structures.
603
604 Configuring ODLJndiLdapRealm
605 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
606
607 To configure LDAP parameters, modify "etc/shiro.ini"
608 parameters to include the ODLJndiLdapRealm:
609
610 ::
611
612     # OpenDaylight provides a few LDAP implementations, which are disabled out of the box.
613     # ODLJndiLdapRealm includes authorization functionality based on LDAP elements
614     # extracted through and LDAP search.  This requires a bit of knowledge about
615     # how your LDAP system is setup.  An example is provided below:
616     ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm
617     ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD
618     ldapRealm.contextFactory.url = ldap://<URL>:389
619     ldapRealm.searchBase = dc=DOMAIN,dc=TLD
620     ldapRealm.ldapAttributeForComparison = objectClass
621     ldapRealm.groupRolesMap = "Person":"admin"
622     # ...
623     # further down in the file...
624     # Stacked realm configuration;  realms are round-robbined until authentication succeeds or realm sources are exhausted.
625     securityManager.realms = $tokenAuthRealm, $ldapRealm
626
627 ODLJndiLdapRealmAuthNOnly
628 ^^^^^^^^^^^^^^^^^^^^^^^^^
629
630 How it works
631 ~~~~~~~~~~~~
632
633 This is useful for setups where all LDAP users are allowed equal access.
634
635 Configuring ODLJndiLdapRealmAuthNOnly
636 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
637
638 Edit the "etc/shiro.ini" file and modify the following:
639
640 ::
641
642     ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm
643     ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD
644     ldapRealm.contextFactory.url = ldap://<URL>:389
645     # ...
646     # further down in the file...
647     # Stacked realm configuration;  realms are round-robbined until authentication succeeds or realm sources are exhausted.
648     securityManager.realms = $tokenAuthRealm, $ldapRealm
649
650 Authorization Configuration
651 ---------------------------
652
653 OpenDaylight supports two authorization engines at present, both of which are
654 roughly similar in behavior:
655
656 - Shiro-Based Authorization
657
658 - MDAL-Based Dynamic Authorization
659
660 .. note::
661
662     The preferred mechanism for configuring AAA Authentication is the
663     MDSAL-Based Dynamic Authorization. Read the following section.
664
665 Shiro-Based Static Authorization
666 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
667
668 OpenDaylight AAA has support for Role Based Access Control (RBAC) based
669 on the Apache Shiro permissions system. Configuration of the authorization
670 system is done off-line; authorization currently cannot be configured
671 after the controller is started. The Authorization provided by this mechanism
672 is aimed towards supporting coarse-grained security policies, the MDSAL-Based
673 mechanism allows for a more robust configuration capabilities. `Shiro-based
674 Authorization <http://shiro.apache.org/web.html#Web-%7B%7B%5Curls%5C%7D%7D>`_
675 describes how to configure the Authentication feature in detail.
676
677 .. notes::
678
679     The Shiro-Based Authorization that uses the *shiro.ini* URLs section to
680     define roles requirements is **deprecated** and **discouraged** since the
681     changes made to the file are only honored on a controller restart.
682
683     Shiro-Based Authorization is not **cluster-aware**, so the changes made on
684     the *shiro.ini* file have to be replicated on every controller instance
685     belonging to the cluster.
686
687     The URL patterns are matched relative to the Servlet context leaving room
688     for ambiguity, since many endpoints may match (i.e., "/restconf/modules" and
689     "/auth/modules" would both match a "/modules/\**" rule).
690
691 Enable “admin” Role Based Access to the IdMLight RESTful web service
692 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
693
694 Edit the “etc/shiro.ini” configuration file and add “/auth/v1/\**=
695 authcBasic, roles[admin]” above the line “/\** = authcBasic” within the
696 “urls” section.
697
698 ::
699
700     /auth/v1/** = authcBasic, roles[admin]
701     /** = authcBasic
702
703 This will restrict the idmlight rest endpoints so that a grant for admin
704 role must be present for the requesting user.
705
706 .. note::
707
708     The ordering of the authorization rules above is important!
709
710 MDSAL-Based Dynamic Authorization
711 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
712 The MDSAL-Based Dynamic authorization uses the MDSALDynamicAuthorizationFilter
713 engine to restrict access to particular URL endpoint patterns. Users may define
714 a list of policies that are insertion-ordered. Order matters for that list of
715 policies, since the first matching policy is applied. This choice was made to
716 emulate behavior of the Shiro-Based Authorization mechanism.
717
718 A **policy** is a key/value pair, where the key is a **resource**
719 (i.e., a "URL pattern") and the value is a list of **permissions** for the
720 resource. The following describes the various elements of a policy:
721
722 - **Resource**: the resource is a string URL pattern as outlined by
723   Apache Shiro. For more information, see http://shiro.apache.org/web.html.
724
725 - **Description**: an optional description of the URL endpoint and why it is
726   being secured.
727
728 - **Permissions list**: a list of permissions for a particular policy. If more
729   than one permission exists in the permissions list they are evaluated using
730   logical "OR". A permission describes the prerequisites to perform HTTP
731   operations on a particular endpoint. The following describes the various
732   elements of a permission:
733
734   + **Role**: the role required to access the target URL endpoint.
735   + **Actions list**: a leaf-list of HTTP permissions that are allowed for a
736     Subject possessing the required role.
737
738 This an example on how to limit access to the modules endpoint:
739
740 ::
741
742     HTTP Operation:
743     put URL: /restconf/config/aaa:http-authorization/policies
744
745     headers: Content-Type: application/json Accept: application/json
746
747     body:
748       { "aaa:policies":
749         { "aaa:policies":
750           [ { "aaa:resource": "/restconf/modules/**",
751             "aaa:permissions": [ { "aaa:role": "admin",
752                                    "aaa:actions": [ "get",
753                                                     "post",
754                                                     "put",
755                                                     "patch",
756                                                     "delete"
757                                                   ]
758                                  }
759                                ]
760             }
761           ]
762         }
763       }
764
765 The above example locks down access to the modules endpoint (and any URLS
766 available past modules) to the "admin" role. Thus, an attempt from the OOB
767 *admin* user will succeed with 2XX HTTP status code, while an attempt from the
768 OOB *user* user will fail with HTTP status code 401, as the user *user* is not
769 granted the "admin" role.
770
771 Accounting Configuration
772 ------------------------
773
774 Accounting is handled through the standard slf4j logging mechanisms used by the
775 rest of OpenDaylight. Thus, one can control logging verbosity through
776 manipulating the log levels for individual packages and classes directly through
777 the Karaf console, JMX, or etc/org.ops4j.pax.logging.cfg. In normal operations,
778 the default levels exposed do not provide much information about AAA services;
779 this is due to the fact that logging can severely degrade performance.
780
781 All AAA logging is output to the standard karaf.log file. For debugging purposes
782 (i.e., to enable maximum verbosity), issue the following command:
783
784 ::
785
786     log:set TRACE org.opendaylight.aaa
787
788 Enable Successful/Unsuccessful Authentication Attempts Logging
789 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
790
791 By default, successful/unsuccessful authentication attempts are NOT logged. This
792 is due to the fact that logging can severely decrease REST performance.
793 To enable logging of successful/unsuccessful REST attempts, issue the following
794 command in Karaf's console:
795
796 ::
797
798     log:set DEBUG org.opendaylight.aaa.shiro.filters.AuthenticationListener
799
800 It is possible to add custom AuthenticationListener(s) to the Shiro-based
801 configuration, allowing different ways to listen for successful/unsuccessful
802 authentication attempts. Custom AuthenticationListener(s) must implement
803 the org.apache.shiro.authc.AuthenticationListener interface.