Authentication, Authorization and Accounting (AAA) Services
===========================================================
The Boron AAA services are based on the Apache Shiro Java Security
Framework. The main configuration file for AAA is located at
“etc/shiro.ini” relative to the ODL karaf home directory.
Terms And Definitions
---------------------
Token
A claim of access to a group of resources on the controller
Domain
A group of resources, direct or indirect, physical, logical, or
virtual, for the purpose of access control. ODL recommends using the
default “sdn" domain in the Boron release.
User
A person who either owns or has access to a resource or group of
resources on the controller
Role
Opaque representation of a set of permissions, which is merely a
unique string as admin or guest
Credential
Proof of identity such as username and password, OTP, biometrics, or
others
Client
A service or application that requires access to the controller
Claim
A data set of validated assertions regarding a user, e.g. the role,
domain, name, etc.
How to enable AAA
-----------------
AAA is enabled through installing the odl-aaa-shiro feature.
odl-aaa-shiro is automatically installed as part of the odl-restconf
offering.
How to disable AAA
------------------
Edit the “etc/shiro.ini” file and replace the following:
::
/** = authcBasic
with
::
/** = anon
Then restart the karaf process.
How application developers can leverage AAA to provide servlet security
-----------------------------------------------------------------------
In order to provide security to a servlet, add the following to the
servlet’s web.xml file as the first filter definition:
::
shiroEnvironmentClass
org.opendaylight.aaa.shiro.web.env.KarafIniWebEnvironment
org.apache.shiro.web.env.EnvironmentLoaderListener
ShiroFilter
org.opendaylight.aaa.shiro.filters.AAAShiroFilter
AAAShiroFilter
/*
.. note::
It is very important to place this AAAShiroFilter as the first
javax.servlet.Filter, as Jersey applies Filters in the order they
appear within web.xml. Placing the AAAShiroFilter first ensures
incoming HTTP/HTTPS requests have proper credentials before any
other filtering is attempted.
AAA Realms
----------
AAA plugin utilizes realms to support pluggable authentication &
authorization schemes. There are two parent types of realms:
- AuthenticatingRealm
- Provides no Authorization capability.
- Users authenticated through this type of realm are treated
equally.
- AuthorizingRealm
- AuthorizingRealm is a more sophisticated AuthenticatingRealm,
which provides the additional mechanisms to distinguish users
based on roles.
- Useful for applications in which roles determine allowed
cabilities.
ODL Contains Four Implementations
- TokenAuthRealm
- An AuthorizingRealm built to bridge the Shiro-based AAA service
with the h2-based AAA implementation.
- Exposes a RESTful web service to manipulate IdM policy on a
per-node basis. If identical AAA policy is desired across a
cluster, the backing data store must be synchronized using an out
of band method.
- A python script located at “etc/idmtool” is included to help
manipulate data contained in the TokenAuthRealm.
- Enabled out of the box.
- ODLJndiLdapRealm
- An AuthorizingRealm built to extract identity information from IdM
data contained on an LDAP server.
- Extracts group information from LDAP, which is translated into ODL
roles.
- Useful when federating against an existing LDAP server, in which
only certain types of users should have certain access privileges.
- Disabled out of the box.
- ODLJndiLdapRealmAuthNOnly
- The same as ODLJndiLdapRealm, except without role extraction.
Thus, all LDAP users have equal authentication and authorization
rights.
- Disabled out of the box.
- ActiveDirectoryRealm
.. note::
More than one Realm implementation can be specified. Realms are
attempted in order until authentication succeeds or all realm
sources are exhausted.
TokenAuthRealm Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TokenAuthRealm stores IdM data in an h2 database on each node. Thus,
configuration of a cluster currently requires configuring the desired
IdM policy on each node. There are two supported methods to manipulate
the TokenAuthRealm IdM configuration:
- idmtool Configuration
- RESTful Web Service Configuration
idmtool Configuration
^^^^^^^^^^^^^^^^^^^^^
A utility script located at “etc/idmtool” is used to manipulate the
TokenAuthRealm IdM policy. idmtool assumes a single domain (sdn), since
multiple domains are not leveraged in the Boron release. General usage
information for idmtool is derived through issuing the following
command:
::
$ python etc/idmtool -h
usage: idmtool [-h] [--target-host TARGET_HOST]
user
{list-users,add-user,change-password,delete-user,list-domains,list-roles,add-role,delete-role,add-grant,get-grants,delete-grant}
...
positional arguments:
user username for BSC node
{list-users,add-user,change-password,delete-user,list-domains,list-roles,add-role,delete-role,add-grant,get-grants,delete-grant}
sub-command help
list-users list all users
add-user add a user
change-password change a password
delete-user delete a user
list-domains list all domains
list-roles list all roles
add-role add a role
delete-role delete a role
add-grant add a grant
get-grants get grants for userid on sdn
delete-grant delete a grant
optional arguments:
-h, --help show this help message and exit
--target-host TARGET_HOST
target host node
Add a user
''''''''''
::
python etc/idmtool admin add-user newUser
Password:
Enter new password:
Re-enter password:
add_user(admin)
command succeeded!
json:
{
"description": "",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "newUser",
"password": "**********",
"salt": "**********",
"userid": "newUser@sdn"
}
.. note::
AAA redacts the password and salt fields for security purposes.
Delete a user
'''''''''''''
::
$ python etc/idmtool admin delete-user newUser@sdn
Password:
delete_user(newUser@sdn)
command succeeded!
List all users
''''''''''''''
::
$ python etc/idmtool admin list-users
Password:
list_users
command succeeded!
json:
{
"users": [
{
"description": "user user",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "user",
"password": "**********",
"salt": "**********",
"userid": "user@sdn"
},
{
"description": "admin user",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "admin",
"password": "**********",
"salt": "**********",
"userid": "admin@sdn"
}
]
}
Change a user’s password
''''''''''''''''''''''''
::
$ python etc/idmtool admin change-password admin@sdn
Password:
Enter new password:
Re-enter password:
change_password(admin)
command succeeded!
json:
{
"description": "admin user",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "admin",
"password": "**********",
"salt": "**********",
"userid": "admin@sdn"
}
Add a role
''''''''''
::
$ python etc/idmtool admin add-role network-admin
Password:
add_role(network-admin)
command succeeded!
json:
{
"description": "",
"domainid": "sdn",
"name": "network-admin",
"roleid": "network-admin@sdn"
}
Delete a role
'''''''''''''
::
$ python etc/idmtool admin delete-role network-admin@sdn
Password:
delete_role(network-admin@sdn)
command succeeded!
List all roles
''''''''''''''
::
$ python etc/idmtool admin list-roles
Password:
list_roles
command succeeded!
json:
{
"roles": [
{
"description": "a role for admins",
"domainid": "sdn",
"name": "admin",
"roleid": "admin@sdn"
},
{
"description": "a role for users",
"domainid": "sdn",
"name": "user",
"roleid": "user@sdn"
}
]
}
List all domains
''''''''''''''''
::
$ python etc/idmtool admin list-domains
Password:
list_domains
command succeeded!
json:
{
"domains": [
{
"description": "default odl sdn domain",
"domainid": "sdn",
"enabled": true,
"name": "sdn"
}
]
}
Add a grant
'''''''''''
::
$ python etc/idmtool admin add-grant user@sdn admin@sdn
Password:
add_grant(userid=user@sdn,roleid=admin@sdn)
command succeeded!
json:
{
"domainid": "sdn",
"grantid": "user@sdn@admin@sdn@sdn",
"roleid": "admin@sdn",
"userid": "user@sdn"
}
Delete a grant
''''''''''''''
::
$ python etc/idmtool admin delete-grant user@sdn admin@sdn
Password:
http://localhost:8181/auth/v1/domains/sdn/users/user@sdn/roles/admin@sdn
delete_grant(userid=user@sdn,roleid=admin@sdn)
command succeeded!
Get grants for a user
'''''''''''''''''''''
::
python etc/idmtool admin get-grants admin@sdn
Password:
get_grants(admin@sdn)
command succeeded!
json:
{
"roles": [
{
"description": "a role for users",
"domainid": "sdn",
"name": "user",
"roleid": "user@sdn"
},
{
"description": "a role for admins",
"domainid": "sdn",
"name": "admin",
"roleid": "admin@sdn"
}
]
}
RESTful Web Service
^^^^^^^^^^^^^^^^^^^
The TokenAuthRealm IdM policy is fully configurable through a RESTful
web service. Full documentation for manipulating AAA IdM data is located
online (https://wiki.opendaylight.org/images/0/00/AAA_Test_Plan.docx),
and a few examples are included in this guide:
Get All Users
'''''''''''''
::
curl -u admin:admin http://localhost:8181/auth/v1/users
OUTPUT:
{
"users": [
{
"description": "user user",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "user",
"password": "**********",
"salt": "**********",
"userid": "user@sdn"
},
{
"description": "admin user",
"domainid": "sdn",
"email": "",
"enabled": true,
"name": "admin",
"password": "**********",
"salt": "**********",
"userid": "admin@sdn"
}
]
}
Create a User
'''''''''''''
::
curl -u admin:admin -X POST -H "Content-Type: application/json" --data-binary @./user.json http://localhost:8181/auth/v1/users
PAYLOAD:
{
"name": "ryan",
"userid": "ryan@sdn",
"password": "ryan",
"domainid": "sdn",
"description": "Ryan's User Account",
"email": "ryandgoulding@gmail.com"
}
OUTPUT:
{
"userid":"ryan@sdn",
"name":"ryan",
"description":"Ryan's User Account",
"enabled":true,
"email":"ryandgoulding@gmail.com",
"password":"**********",
"salt":"**********",
"domainid":"sdn"
}
Create an OAuth2 Token For Admin Scoped to SDN
''''''''''''''''''''''''''''''''''''''''''''''
::
curl -d 'grant_type=password&username=admin&password=a&scope=sdn' http://localhost:8181/oauth2/token
OUTPUT:
{
"expires_in":3600,
"token_type":"Bearer",
"access_token":"5a615fbc-bcad-3759-95f4-ad97e831c730"
}
Use an OAuth2 Token
'''''''''''''''''''
::
curl -H "Authorization: Bearer 5a615fbc-bcad-3759-95f4-ad97e831c730" http://localhost:8181/auth/v1/domains
{
"domains":
[
{
"domainid":"sdn",
"name":"sdn”,
"description":"default odl sdn domain",
"enabled":true
}
]
}
ODLJndiLdapRealm Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LDAP integration is provided in order to externalize identity
management. To configure LDAP parameters, modify "etc/shiro.ini"
parameters to include the ODLJndiLdapRealm:
::
# ODL provides a few LDAP implementations, which are disabled out of the box.
# ODLJndiLdapRealm includes authorization functionality based on LDAP elements
# extracted through and LDAP search. This requires a bit of knowledge about
# how your LDAP system is setup. An example is provided below:
ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm
ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD
ldapRealm.contextFactory.url = ldap://:389
ldapRealm.searchBase = dc=DOMAIN,dc=TLD
ldapRealm.ldapAttributeForComparison = objectClass
ldapRealm.groupRolesMap = "Person":"admin"
# ...
# further down in the file...
# Stacked realm configuration; realms are round-robbined until authentication succeeds or realm sources are exhausted.
securityManager.realms = $tokenAuthRealm, $ldapRealm
This configuration allows federation with an external LDAP server, and
the user’s ODL role parameters are mapped to corresponding LDAP
attributes as specified by the groupRolesMap. Thus, an LDAP operator can
provision attributes for LDAP users that support different ODL role
structures.
ODLJndiLdapRealmAuthNOnly Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit the "etc/shiro.ini" file and modify the following:
::
ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm
ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD
ldapRealm.contextFactory.url = ldap://:389
# ...
# further down in the file...
# Stacked realm configuration; realms are round-robbined until authentication succeeds or realm sources are exhausted.
securityManager.realms = $tokenAuthRealm, $ldapRealm
This is useful for setups where all LDAP users are allowed equal access.
Token Store Configuration Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit the file “etc/opendaylight/karaf/08-authn-config.xml” and edit the
following: .\ **timeToLive**: Configure the maximum time, in
milliseconds, that tokens are to be cached. Default is 360000. Save the
file.
Authorization Configuration
---------------------------
Shiro-Based Authorization
~~~~~~~~~~~~~~~~~~~~~~~~~
OpenDaylight AAA has support for Role Based Access Control based on the
Apache Shiro permissions system. Configuration of the authorization
system is done offline; authorization currently cannot be configured
after the controller is started. Thus, Authorization in this
release is aimed towards supporting coarse-grained security policies,
with the aim to provide more robust configuration capabilities in the
future. Shiro-based Authorization is documented on the Apache Shiro
website (http://shiro.apache.org/web.html#Web-%7B%7B%5Curls%5C%7D%7D).
Enable “admin” Role Based Access to the IdMLight RESTful web service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Edit the “etc/shiro.ini” configuration file and add “/auth/v1/\ **=
authcBasic, roles[admin]” above the line “/** = authcBasic” within the
“urls” section.
::
/auth/v1/** = authcBasic, roles[admin]
/** = authcBasic
This will restrict the idmlight rest endpoints so that a grant for admin
role must be present for the requesting user.
.. note::
The ordering of the authorization rules above is important!
AuthZ Broker Facade
~~~~~~~~~~~~~~~~~~~
ODL includes an experimental Authorization Broker Facade, which allows
finer grained access control for REST endpoints. Since this feature was
not well tested in the Boron release, it is recommended to use the
Shiro-based mechanism instead, and rely on the Authorization Broker
Facade for POC use only.
AuthZ Broker Facade Feature Installation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To install the authorization broker facade, please issue the following
command in the karaf shell:
::
feature:install odl-restconf odl-aaa-authz
Add an Authorization Rule
^^^^^^^^^^^^^^^^^^^^^^^^^
The following shows how one might go about securing the controller so
that only admins can access restconf.
::
curl -u admin:admin -H “Content-Type: application/xml” --data-binary @./rule.json http://localhost:8181/restconf/config/authorization-schema:simple-authorization/policies/RestConfService/
cat ./rule.json
{
"policies": {
"resource": "*",
"service":"RestConfService",
"role": "admin"
}
}
Accounting Configuration
------------------------
All AAA logging is output to the standard karaf.log file.
::
log:set TRACE org.opendaylight.aaa
This command enables the most verbose level of logging for AAA
components.