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.
AAA is enabled through installing the odl-aaa-shiro feature. odl-aaa-shiro is automatically installed as part of the odl-restconf offering.
Edit the “etc/shiro.ini” file and replace the following:
/** = authcBasic
with
/** = anon
Then restart the karaf process.
In order to provide security to a servlet, add the following to the servlet’s web.xml file as the first filter definition:
<context-param>
<param-name>shiroEnvironmentClass</param-name>
<param-value>org.opendaylight.aaa.shiro.web.env.KarafIniWebEnvironment</param-value>
</context-param>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.opendaylight.aaa.shiro.filters.AAAShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AAAShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
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 plugin utilizes realms to support pluggable authentication & authorization schemes. There are two parent types of realms:
ODL Contains Four Implementations
Note
More than one Realm implementation can be specified. Realms are attempted in order until authentication succeeds or all realm sources are exhausted.
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:
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
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.
$ python etc/idmtool admin delete-user newUser@sdn
Password:
delete_user(newUser@sdn)
command succeeded!
$ 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"
}
]
}
$ 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"
}
$ 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"
}
$ python etc/idmtool admin delete-role network-admin@sdn
Password:
delete_role(network-admin@sdn)
command succeeded!
$ 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"
}
]
}
$ python etc/idmtool admin list-domains
Password:
list_domains
command succeeded!
json:
{
"domains": [
{
"description": "default odl sdn domain",
"domainid": "sdn",
"enabled": true,
"name": "sdn"
}
]
}
$ 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"
}
$ 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!
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"
}
]
}
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:
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"
}
]
}
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"
}
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"
}
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
}
]
}
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://<URL>: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.
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://<URL>: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.
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.
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).
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!
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.
To install the authorization broker facade, please issue the following command in the karaf shell:
feature:install odl-restconf odl-aaa-authz
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"
}
}
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.