Cleanup AAA dev-guide
[aaa.git] / docs / dev-guide.rst
1 .. _aaa-dev-guide:
2
3 Authentication, Authorization and Accounting (AAA) Services - Developer guide
4 =============================================================================
5
6 Overview
7 --------
8
9 Authentication, Authorization and Accounting (AAA) is a term for a
10 framework controlling access to resources, enforcing policies to use
11 those resources and auditing their usage. These processes are the
12 fundamental building blocks for effective network management and security.
13
14 Authentication provides a way of identifying a user, typically by
15 having the user enter a valid user name and valid password before access
16 is granted. The process of authentication is based on each user having a unique
17 set of criteria for gaining access. The AAA framework compares a user's
18 authentication credentials with other user credentials stored in a database.
19 If the credentials match, the user is granted access to the network.
20 If the credentials don't match, authentication fails and access is denied.
21
22 Authorization is the process of finding out what an authenticated user is
23 allowed to do within the system, which tasks can do, which API can call, etc.
24 The authorization process determines whether the user has the authority
25 to perform such actions.
26
27 Accounting is the process of logging the activity of an authenticated user,
28 for example, the amount of data a user has sent and/or received during a
29 session, which APIs called, etc.
30
31 Terms And Definitions
32 ^^^^^^^^^^^^^^^^^^^^^
33
34 AAA
35     Authentication, Authorization and Accounting.
36
37 Token
38     A claim of access to a group of resources on the controller.
39
40 Domain
41     A group of resources, direct or indirect, physical, logical, or
42     virtual, for the purpose of access control.
43
44 User
45     A person who either owns or has access to a resource or group of
46     resources on the controller.
47
48 Role
49     Opaque representation of a set of permissions, which is merely a
50     unique string as admin or guest.
51
52 Credential
53     Proof of identity such as user name and password, OTP, biometrics, or
54     others.
55
56 Client
57     A service or application that requires access to the controller.
58
59 Claim
60     A data set of validated assertions regarding a user, e.g. the role,
61     domain, name, etc.
62
63 IdP
64     Identity Provider.
65
66
67 Quick Start
68 -----------
69
70 Building
71 ^^^^^^^^
72 Get the code:
73
74 .. code-block:: bash
75
76     git clone https://git.opendaylight.org/gerrit/aaa
77
78 Build it:
79
80 .. code-block:: bash
81
82     cd aaa && mvn clean install
83
84
85 Installing
86 ^^^^^^^^^^
87
88 AAA is automatically installed upon installation of odl-restconf, but you can
89 install it yourself directly from the Karaf console through the following
90 command:
91
92 ::
93
94     feature:install odl-aaa-shiro
95
96 Pushing changes
97 ^^^^^^^^^^^^^^^
98
99 The following are basic instructions to push your contributions to the project's
100 GIT repository:
101
102 .. code-block:: bash
103
104     git add .
105     git commit -s
106     # make changes, add change id, etc.
107     git commit --amend
108     git push ssh://{username}@git.opendaylight.org:29418/aaa.git HEAD:refs/for/master
109
110 AAA Framework implementations
111 -----------------------------
112
113 Since Boron release, the OpenDaylight's AAA services are based on the
114 `Apache Shiro <https://shiro.apache.org/>`_ Java Security Framework. The main
115 configuration file for AAA is located at “etc/shiro.ini” relative to the
116 OpenDaylight Karaf home directory.
117
118 Known limitations
119 ^^^^^^^^^^^^^^^^^
120
121 The database (H2) used by ODL AAA Authentication store is not-cluster enabled.
122 When deployed in a clustered environment each node needs to have its AAA user
123 file synchronized using out of band means.
124
125 How to enable AAA
126 -----------------
127
128 AAA is enabled through installing the odl-aaa-shiro feature. The vast majority
129 of OpenDaylight's northbound APIs (and all RESTCONF APIs) are protected by AAA
130 by default when installing the +odl-restconf+ feature, since the odl-aaa-shiro
131 is automatically installed as part of them.
132
133 How to disable AAA
134 ------------------
135
136 Edit the “etc/opendaylight/datastore/initial/config/aaa-app-config.xml” file and replace the following:
137
138 ::
139
140     /** = authcBasic
141
142 with
143
144 ::
145
146     /** = anon
147
148 Then, restart the Karaf process.
149
150 How application developers can leverage AAA to provide servlet security
151 -----------------------------------------------------------------------
152
153 Previously the servlet's web.xml was edited to add the AAAShiroFilter. This has been replaced with programmatic initialization.
154
155 The Neutron project uses this new style the Neutron `blueprint.xml <https://git.opendaylight.org/gerrit/gitweb?p=neutron.git;a=blob;f=northbound-api/src/main/resources/OSGI-INF/blueprint/blueprint.xml;h=a9dc57a97091d6c90da3e216a13523adbe698887;hb=refs/heads/master>`_ and Neutron `WebInitializer.java <https://git.opendaylight.org/gerrit/gitweb?p=neutron.git;a=blob;f=northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/WebInitializer.java;h=a615d02343505cef0d4cdd54b2f07f2a9fee9b75;hb=refs/heads/master>`_ are helpful references.
156
157 AAA Realms
158 ----------
159
160 AAA plugin utilizes the Shiro Realms to support pluggable authentication &
161 authorization schemes. There are two parent types of realms:
162
163 -  AuthenticatingRealm
164
165    -  Provides no Authorization capability.
166
167    -  Users authenticated through this type of realm are treated
168       equally.
169
170 -  AuthorizingRealm
171
172    -  AuthorizingRealm is a more sophisticated AuthenticatingRealm,
173       which provides the additional mechanisms to distinguish users
174       based on roles.
175
176    -  Useful for applications in which roles determine allowed
177       capabilities.
178
179 OpenDaylight contains five implementations:
180
181 -  TokenAuthRealm
182
183    -  An AuthorizingRealm built to bridge the Shiro-based AAA service
184       with the h2-based AAA implementation.
185
186    -  Exposes a RESTful web service to manipulate IdM policy on a
187       per-node basis. If identical AAA policy is desired across a
188       cluster, the backing data store must be synchronized using an out
189       of band method.
190
191    -  A python script located at “etc/idmtool” is included to help
192       manipulate data contained in the TokenAuthRealm.
193
194    -  Enabled out of the box. This is the realm configured by default.
195
196 -  ODLJndiLdapRealm
197
198    -  An AuthorizingRealm built to extract identity information from IdM
199       data contained on an LDAP server.
200
201    -  Extracts group information from LDAP, which is translated into
202       OpenDaylight roles.
203
204    -  Useful when federating against an existing LDAP server, in which
205       only certain types of users should have certain access privileges.
206
207    -  Disabled out of the box.
208
209 -  ODLJndiLdapRealmAuthNOnly
210
211    -  The same as ODLJndiLdapRealm, except without role extraction.
212       Thus, all LDAP users have equal authentication and authorization
213       rights.
214
215    -  Disabled out of the box.
216
217 -  ODLActiveDirectoryRealm
218
219    -  Wraps the generic ActiveDirectoryRealm provided by Shiro. This allows for
220       enhanced logging as well as isolation of all realms in a single package,
221       which enables easier import by consuming servlets.
222
223    -  Disabled out of the box.
224
225 -  KeystoneAuthRealm
226
227    -  This realm authenticates OpenDaylight users against the OpenStack's
228       Keystone server by using the
229       `Keystone's Identity API v3 <https://developer.openstack.org/api-ref/identity/v3/>`_
230       or later.
231
232    - Disabled out of the box.
233
234 .. note::
235
236     More than one Realm implementation can be specified. Realms are attempted
237     in order until authentication succeeds or all realm sources are exhausted.
238     Edit the **securityManager.realms = $tokenAuthRealm** property in shiro.ini
239     and add all the realms needed separated by commas.
240
241 TokenAuthRealm
242 ^^^^^^^^^^^^^^
243
244 How it works
245 ~~~~~~~~~~~~
246
247 The TokenAuthRealm is the default Authorization Realm deployed in OpenDaylight.
248 TokenAuthRealm uses a direct authentication mechanism as shown in the following
249 picture:
250
251 .. figure:: ./images/aaa/direct-authentication.png
252    :alt: TokenAuthRealm direct authentication mechanism
253
254    TokenAuthRealm direct authentication mechanism
255
256 A user presents some credentials (e.g., username/password) directly to the
257 OpenDaylight controller and receives a session cookie, which can be then
258 used to access protected resources on the controller.
259
260 How to access the H2 database
261 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262
263 The H2 database provides an optional front-end Web interface, which can be very
264 useful for new users. From the KARAF_HOME directory, you can run the following
265 command to enable the user interface:
266
267 .. code-block:: bash
268
269     java -cp ./system/com/h2database/h2/2.1.214/h2-2.1.214.jar org.h2.tools.Server \
270         -trace -pg -web -webAllowOthers
271
272
273 You can navigate to the following and login via the browser:
274
275 ::
276
277     http://{IP}:8082/
278
279 Within the browser, you can log in to the H2 database by providing your credentials and the path to the database.
280 The default configuration is as follows:
281
282 ::
283
284     JDBC URL:   jdbc:h2:[ABSOLUTE_PATH_TO_KARAF_FOLDER]/data/idmlight.db
285     User Name:  foo
286     Password:   bar
287
288 ODLJndiLdapRealm
289 ^^^^^^^^^^^^^^^^
290
291 How it works
292 ~~~~~~~~~~~~
293
294 LDAP integration is provided in order to externalize identity management.
295 This configuration allows federation with an external LDAP server.
296 The user’s OpenDaylight role parameters are mapped to corresponding LDAP
297 attributes as specified by the groupRolesMap. Thus, an LDAP operator can
298 provision attributes for LDAP users that support different OpenDaylight role
299 structures.
300
301 ODLJndiLdapRealmAuthNOnly
302 ^^^^^^^^^^^^^^^^^^^^^^^^^
303
304 How it works
305 ~~~~~~~~~~~~
306
307 This is useful for setups where all LDAP users are allowed equal access.
308
309 KeystoneAuthRealm
310 ^^^^^^^^^^^^^^^^^
311
312 How it works
313 ~~~~~~~~~~~~
314
315 This realm authenticates OpenDaylight users against the OpenStack's Keystone
316 server. This realm uses the
317 `Keystone's Identity API v3 <https://developer.openstack.org/api-ref/identity/v3/>`_
318 or later.
319
320 .. figure:: ./images/aaa/keystonerealm-authentication.png
321    :alt: KeystoneAuthRealm authentication mechanism
322
323    KeystoneAuthRealm authentication/authorization mechanism
324
325 As can shown on the above diagram, once configured, all the RESTCONF APIs calls
326 will require sending **user**, **password** and optionally **domain** (1). Those
327 credentials are used to authenticate the call against the Keystone server (2) and,
328 if the authentication succeeds, the call will proceed to the MDSAL (3). The
329 credentials must be provisioned in advance within the Keystone Server. The user
330 and password are mandatory, while the domain is optional, in case it is not
331 provided within the REST call, the realm will default to (**Default**),
332 which is hard-coded. The default domain can be also configured through the
333 *shiro.ini* file (see the :doc:`AAA User Guide <user-guide>`).
334
335 The protocol between the Controller and the Keystone Server (2) can be either
336 HTTPS or HTTP. In order to use HTTPS the Keystone Server's certificate
337 must be exported and imported on the Controller (see the :ref:`Certificate Management <aaa-certificate-management>` section).
338
339 Authorization Configuration
340 ---------------------------
341
342 OpenDaylight supports two authorization engines at present, both of which are
343 roughly similar in behavior:
344
345 - Shiro-Based Authorization
346
347 - MDSAL-Based Dynamic Authorization
348
349 .. note::
350
351     The preferred mechanism for configuring AAA Authentication is the
352     MDSAL-Based Dynamic Authorization. Read the following section.
353
354 Shiro-Based Static Authorization
355 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
356
357 OpenDaylight AAA has support for Role Based Access Control (RBAC) based
358 on the Apache Shiro permissions system. Configuration of the authorization
359 system is done off-line; authorization currently cannot be configured
360 after the controller is started. The Authorization provided by this mechanism
361 is aimed towards supporting coarse-grained security policies, the MDSAL-Based
362 mechanism allows for a more robust configuration capabilities. `Shiro-based
363 Authorization <http://shiro.apache.org/web.html#Web-%7B%7B%5Curls%5C%7D%7D>`_
364 describes how to configure the Authentication feature in detail.
365
366 .. note::
367
368     The Shiro-Based Authorization that uses the *shiro.ini* URLs section to
369     define roles requirements is **deprecated** and **discouraged** since the
370     changes made to the file are only honored on a controller restart.
371
372     Shiro-Based Authorization is not **cluster-aware**, so the changes made on
373     the *shiro.ini* file have to be replicated on every controller instance
374     belonging to the cluster.
375
376     The URL patterns are matched relative to the Servlet context leaving room
377     for ambiguity, since many endpoints may match (i.e., "/restconf/modules" and
378     "/auth/modules" would both match a "/modules/\**" rule).
379
380 MDSAL-Based Dynamic Authorization
381 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
382 The MDSAL-Based Dynamic authorization uses the MDSALDynamicAuthorizationFilter
383 engine to restrict access to particular URL endpoint patterns. Users may define
384 a list of policies that are insertion-ordered. Order matters for that list of
385 policies, since the first matching policy is applied. This choice was made to
386 emulate behavior of the Shiro-Based Authorization mechanism.
387
388 A **policy** is a key/value pair, where the key is a **resource**
389 (i.e., a "URL pattern") and the value is a list of **permissions** for the
390 resource. The following describes the various elements of a policy:
391
392 - **Resource**: the resource is a string URL pattern as outlined by
393   Apache Shiro. For more information, see http://shiro.apache.org/web.html.
394
395 - **Description**: an optional description of the URL endpoint and why it is
396   being secured.
397
398 - **Permissions list**: a list of permissions for a particular policy. If more
399   than one permission exists in the permissions list they are evaluated using
400   logical "OR". A permission describes the prerequisites to perform HTTP
401   operations on a particular endpoint. The following describes the various
402   elements of a permission:
403
404   + **Role**: the role required to access the target URL endpoint.
405   + **Actions list**: a leaf-list of HTTP permissions that are allowed for a
406     Subject possessing the required role.
407
408 This an example on how to limit access to the modules endpoint:
409
410 ::
411
412     HTTP Operation:
413     put URL: /rests/data/aaa:http-authorization/policies
414
415     headers: Content-Type: application/json Accept: application/json
416
417     body:
418       {
419           "aaa:policies": {
420               "aaa:policies": [
421                   {
422                       "aaa:resource": "/restconf/modules/**",
423                       "aaa:index": 1,
424                       "aaa:permissions": [
425                           {
426                               "aaa:role": "admin",
427                               "aaa:actions": [
428                                   "get",
429                                   "post",
430                                   "put",
431                                   "patch",
432                                   "delete"
433                               ]
434                           }
435                       ]
436                   }
437               ]
438           }
439       }
440
441 The above example locks down access to the modules endpoint (and any URLS
442 available past modules) to the "admin" role. Thus, an attempt from the OOB
443 *admin* user will succeed with 2XX HTTP status code, while an attempt from the
444 OOB *user* user will fail with HTTP status code 401, as the user *user* is not
445 granted the "admin" role.
446
447 Accounting Configuration
448 ------------------------
449
450 Accounting is handled through the standard slf4j logging mechanisms used by the
451 rest of OpenDaylight. Thus, one can control logging verbosity through
452 manipulating the log levels for individual packages and classes directly through
453 the Karaf console, JMX, or etc/org.ops4j.pax.logging.cfg. In normal operations,
454 the default levels exposed do not provide much information about AAA services;
455 this is due to the fact that logging can severely degrade performance.
456
457 All AAA logging is output to the standard karaf.log file. For debugging purposes
458 (i.e., to enable maximum verbosity), issue the following command:
459
460 ::
461
462     log:set TRACE org.opendaylight.aaa
463
464 Enable Successful/Unsuccessful Authentication Attempts Logging
465 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
466
467 By default, successful/unsuccessful authentication attempts are NOT logged. This
468 is due to the fact that logging can severely decrease REST performance.
469
470 It is possible to add custom AuthenticationListener(s) to the Shiro-based
471 configuration, allowing different ways to listen for successful/unsuccessful
472 authentication attempts. Custom AuthenticationListener(s) must implement
473 the org.apache.shiro.authc.AuthenticationListener interface.
474
475 .. _aaa-certificate-management:
476
477 Certificate Management
478 ----------------------
479
480 The **Certificate Management Service** is used to manage the keystores and
481 certificates at the OpenDaylight distribution to easily provides the TLS
482 communication.
483
484 The Certificate Management Service managing two keystores:
485
486 1. **OpenDaylight Keystore** which holds the OpenDaylight distribution
487    certificate self sign certificate or signed certificate from a root CA based
488    on generated certificate request.
489
490 2. **Trust Keystore** which holds all the network nodes certificates that shall
491    to communicate with the OpenDaylight distribution through TLS communication.
492
493 The Certificate Management Service stores the keystores (OpenDaylight & Trust)
494 as *.jks* files under configuration/ssl/ directory. Also the keystores
495 could be stored at the MD-SAL datastore in case OpenDaylight distribution
496 running at cluster environment. When the keystores are stored at MD-SAL,
497 the Certificate Management Service rely on the **Encryption-Service** to encrypt
498 the keystore data before storing it to MD-SAL and decrypted at runtime.
499
500 How to use the Certificate Management Service to manage the TLS communication
501 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
502
503 The following are the steps to configure the TLS communication within your
504 feature or module:
505
506 1. It is assumed that there exists an already created OpenDaylight distribution
507    project following `this guide
508    <https://docs.opendaylight.org/en/latest/developer-guides/developing-apps-on-the-opendaylight-controller.html#building-an-example-module>`_.
509
510 2. In the implementation bundle the following artifact must be added to its
511    *pom.xml* file as dependency.
512
513 .. code-block:: xml
514
515     <dependency>
516       <groupId>org.opendaylight.aaa</groupId>
517       <artifactId>aaa-cert</artifactId>
518       <version>0.5.0-SNAPSHOT</version>
519     </dependency>
520
521 3. Using the provider class in the implementation bundle needs to define a
522    variable holding the Certificate Manager Service as in the following example:
523
524 .. code-block:: java
525
526     import org.opendaylight.aaa.cert.api.ICertificateManager;
527     import org.opendaylight.controller.md.sal.binding.api.DataBroker;
528
529     public class UseCertManagerExampleProvider {
530       private final DataBroker dataBroker;
531       private final ICertificateManager caManager;
532
533       public EncSrvExampleProvider(final DataBroker dataBroker, final ICertificateManager caManager) {
534         this.dataBroker = dataBroker;
535         this.caManager = caManager;
536       }
537       public SSLEngine createSSLEngine() {
538         final SSLContext sslContext = caManager.getServerContext();
539         if (sslContext != null) {
540           final SSLEngine sslEngine = sslContext.createSSLEngine();
541           sslEngine.setEnabledCipherSuites(caManager.getCipherSuites());
542           // DO the Implementation
543           return sslEngine;
544         }
545       }
546       public void init() {
547           // TODO
548       }
549       public void close() {
550           // TODO
551       }
552     }
553
554 4. The Certificate Manager Service provides two main methods that are needed to
555    establish the *SSLEngine* object, *getServerContext()* and *getCipherSuites()*
556    as the above example shows. It also provides other methods such as
557    *getODLKeyStore()* and *getTrustKeyStore()* that gives access to the
558    OpenDaylight and Trust keystores.
559
560 5. Now the *ICertificateManager* need to be passed as an argument to the
561    *UseCertManagerExampleProvider* within the implementation bundle blueprint
562    configuration. The following example shows how:
563
564 .. code-block:: xml
565
566     <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
567       xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
568       odl:use-default-for-reference-types="true">
569       <reference id="dataBroker"
570         interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
571         odl:type="default" />
572       <reference id="aaaCertificateManager"
573         interface="org.opendaylight.aaa.cert.api.ICertificateManager"
574         odl:type="default-certificate-manager" />
575       <bean id="provider"
576         class="org.opendaylight.UseCertManagerExample.impl.UseCertManagerExampleProvider"
577         init-method="init" destroy-method="close">
578         <argument ref="dataBroker" />
579         <argument ref="aaaCertificateManager" />
580       </bean>
581     </blueprint>
582
583 6. After finishing the bundle implementation the feature module needs to be
584    updated to include the *aaa-cert* feature in its feature bundle pom.xml file.
585
586 .. code-block:: xml
587
588     <properties>
589       <aaa.version>0.5.0-SNAPSHOT</aaa.version>
590     </properties>
591     <dependency>
592       <groupId>org.opendaylight.aaa</groupId>
593       <artifactId>features-aaa</artifactId>
594       <version>${aaa.version}</version>
595       <classifier>features</classifier>
596       <type>xml</type>
597     </dependency>
598
599 7. Now, in the feature.xml file add the Certificate Manager Service feature and
600    its repository.
601
602 .. code-block:: xml
603
604     <repository>mvn:org.opendaylight.aaa/features-aaa/{VERSION}/xml/features</repository>
605
606 The Certificate Manager Service feature can be included inside the
607 implementation bundle feature as shown in the following example:
608
609 .. code-block:: xml
610
611     <feature name='odl-UseCertManagerExample' version='${project.version}'
612       description='OpenDaylight :: UseCertManagerExample'>
613       <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
614       <feature version='${aaa.version}'>odl-aaa-cert</feature>
615       <bundle>mvn:org.opendaylight.UseCertManagerExample/UseCertManagerExample-impl/{VERSION}</bundle>
616     </feature>
617
618 8. Now the project can be built and the OpenDaylight distribution started to
619    continue with the configuration process. See the User Guide for more details.
620
621 Encryption Service
622 ------------------
623
624 The **AAA Encryption Service** is used to encrypt the OpenDaylight users'
625 passwords and TLS communication certificates. This section shows how to use the
626 AAA Encryption Service with an OpenDaylight distribution project to encrypt data.
627
628 1. It is assumed that there exists an already created OpenDaylight distribution
629    project following `this guide
630    <https://docs.opendaylight.org/en/latest/developer-guides/developing-apps-on-the-opendaylight-controller.html#building-an-example-module>`_.
631
632 2. In the implementation bundle the following artifact must be added to its
633    *pom.xml* file as dependency.
634
635 .. code-block:: xml
636
637     <dependency>
638       <groupId>org.opendaylight.aaa</groupId>
639       <artifactId>aaa-encrypt-service</artifactId>
640       <version>0.5.0-SNAPSHOT</version>
641     </dependency>
642
643 3. Using the provider class in the implementation bundle needs to define a
644    variable holding the Encryption Service as in the following example:
645
646 .. code-block:: java
647
648     import org.opendaylight.aaa.encrypt.AAAEncryptionService;
649     import org.opendaylight.controller.md.sal.binding.api.DataBroker;
650
651     public class EncSrvExampleProvider {
652     private final DataBroker dataBroker;
653       private final AAAEncryptionService encryService;
654
655       public EncSrvExampleProvider(final DataBroker dataBroker, final AAAEncryptionService encryService) {
656         this.dataBroker = dataBroker;
657         this.encryService = encryService;
658       }
659       public void init() {
660         // TODO
661       }
662       public void close() {
663         // TODO
664       }
665     }
666
667 The AAAEncryptionService can be used to encrypt and decrypt any data based on
668 project's needs.
669
670 4. Now the *AAAEncryptionService* needs to be passed as an argument to the
671    *EncSrvExampleProvider* within the implementation bundle blueprint
672    configuration. The following example shows how:
673
674 .. code-block:: xml
675
676     <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
677       xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
678       odl:use-default-for-reference-types="true">
679       <reference id="dataBroker"
680         interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
681         odl:type="default" />
682       <reference id="encryService" interface="org.opendaylight.aaa.encrypt.AAAEncryptionService"/>
683       <bean id="provider"
684         class="org.opendaylight.EncSrvExample.impl.EncSrvExampleProvider"
685         init-method="init" destroy-method="close">
686         <argument ref="dataBroker" />
687         <argument ref="encryService" />
688       </bean>
689     </blueprint>
690
691 5. After finishing the bundle implementation the feature module needs to be
692    updated to include the *aaa-encryption-service* feature in its feature bundle
693    pom.xml file.
694
695 .. code-block:: xml
696
697     <dependency>
698       <groupId>org.opendaylight.aaa</groupId>
699       <artifactId>features-aaa</artifactId>
700       <version>${aaa.version}</version>
701       <classifier>features</classifier>
702       <type>xml</type>
703     </dependency>
704
705 It is also necessary to add the *aaa.version* in the properties section:
706
707 .. code-block:: xml
708
709     <properties>
710       <aaa.version>0.5.0-SNAPSHOT</aaa.version>
711     </properties>
712
713 6. Now, in the feature.xml file add the Encryption Service feature and its
714    repository.
715
716 .. code-block:: xml
717
718     <repository>mvn:org.opendaylight.aaa/features-aaa/{VERSION}/xml/features</repository>
719
720 The Encryption Service feature can be included inside the implementation bundle
721 feature as shown in the following example:
722
723 .. code-block:: xml
724
725     <feature name='odl-EncSrvExample' version='${project.version}' description='OpenDaylight :: EncSrvExample'>
726       <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
727       <feature version='${aaa.version}'>odl-aaa-encryption-service</feature>
728       <feature version='${project.version}'>odl-EncSrvExample-api</feature>
729       <bundle>mvn:org.opendaylight.EncSrvExample/EncSrvExample-impl/{VERSION}</bundle>
730     </feature>
731
732 7. Now the project can be built and the OpenDaylight distribution started to
733    continue with the configuration process. See the User Guide for more details.