ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r1330254 - /ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext
Date Wed, 25 Apr 2012 12:57:35 GMT
Author: jawi
Date: Wed Apr 25 12:57:35 2012
New Revision: 1330254

URL: http://svn.apache.org/viewvc?rev=1330254&view=rev
Log:
Formatting updated.

Modified:
    ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext

Modified: ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext?rev=1330254&r1=1330253&r2=1330254&view=diff
==============================================================================
--- ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext (original)
+++ ace/site/trunk/content/dev-doc/design/ace-authentication.mdtext Wed Apr 25 12:57:35 2012
@@ -1,11 +1,11 @@
 _Enabling authentication in ACE_
 
-last updated: April 24th, 2012
+last updated: April 25th, 2012
 
 
 ## Introduction
 
-When provisioning software (partly) to targets, one has to rely upon the trustworthiness
of both the network and the target. Even if everything is under your control and governance,
one cannot entirely be sure that unwanted access takes place. A first step in order to prevent
unwanted access is *authentication*, which gives you the ability to verify the identity of
someone. Once the identity is known, one can apply *authorization* in order to determine what
actions are allowed and which are not.
+When provisioning software (partly) to targets, one has to rely upon the trustworthiness
of both the network and the target. Even if everything is under your control and governance,
one cannot entirely be sure that unwanted access takes place. A first step in order to prevent
unwanted access is *authentication*, which gives you the ability to verify the identity of
someone. Once the identity is known, one can apply *authentication* in order to determine
what actions are allowed and which are not.
 In this article, the recently added authentication layer of ACE is explained in more depth,
and some details on how extensions can be written for additional mechanisms are given. The
remainder of this article assumes the reader has basic knowledge of the principles behind
ACE, and has sufficient programming skills. For this article, the latest code of ACE (0.8.1-SNAPSHOT,
rev.1329269) was used.
 
 
@@ -13,7 +13,8 @@ In this article, the recently added auth
 
 Before going in more depth on the authentication layer of ACE, we first need to pinpoint
all places were authentication is to be applied. The following figure shows the main components
in ACE and their communication paths, providing a global overview of where authentication
is applicable to ACE.
 
-![Figure 1: Overview of components and communication paths in ACE](auth_main_components.svg
"Figure 1: Overview of components and communication paths")
+![Figure 1: Overview of components and communication paths in ACE](auth_main_components.svg
"Figure 1: Overview of components and communication paths")  
+Figure 1: Overview of components and communication paths.
 
 In figure 1, several communication paths exists (denoted by the circled digits):
 
@@ -40,21 +41,23 @@ The high-level design for security in AC
 
 Based on these requirements, the design of the authentication layer is represented in the
following figure:
 
-![Figure 2: Authentication layer class diagram](auth_api.svg "Figure 2: Authentication layer
class diagram")
+![Figure 2: Authentication layer class diagram](auth_api.svg "Figure 2: Authentication layer
class diagram")  
+Figure 2: Authentication layer class diagram.
 
-The `AuthenticationService` is responsible for authenticating a user based on some piece
of information. This piece of information can be a username/password combination, a `HttpServletRequest`
containing authentication request headers, or any other set of information capable of uniquely
identifying a user. The actual authentication itself is delegated to one or more `AuthenticationProcessor`s,
which know how to handle  a given set of information (e.g., `HttpServletRequest`) and can
map this information to a particular user. In more detail, the calling sequence of `AuthenticationService#authenticate`
would be:
+The <tt>AuthenticationService</tt> is responsible for authenticating a user based
on some piece of information. This piece of information can be a username/password combination,
a <tt>HttpServletRequest</tt> containing authentication request headers, or any
other set of information capable of uniquely identifying a user. The actual authentication
itself is delegated to one or more <tt>AuthenticationProcessor</tt>s, which know
how to handle  a given set of information (e.g., <tt>HttpServletRequest</tt>)
and can map this information to a particular user. In more detail, the calling sequence of
<tt>AuthenticationService#authenticate</tt> would be:
 
-1. `AuthenticationService#authenticate` is called with a blob of data, for example the `HttpServletRequest`;
-2. for each known `AuthenticationProcessor`:
-    - `AuthenticationProcessor#canHandle` is called with that blob of data. An authentication
processor can decide whether the given blob is something it can handle or not;
-    - if it can be handled, the `AuthenticationProcessor#authenticate` is called with that
blob of data, along with an instance of the UserAdmin service. The authentication processor
is now responsible for converting the blob of data to an authenticated user, if possible.
-3. if a `User` object is returned from the authentication service[^3], the authentication
phase will be regarded as successful. If *no* `User` object is returned, the authentication
phase will be regarded unsuccessful.
+1. <tt>AuthenticationService#authenticate</tt> is called with a blob of data,
for example the <tt>HttpServletRequest</tt>;
+2. for each known <tt>AuthenticationProcessor</tt>:
+    - <tt>AuthenticationProcessor#canHandle</tt> is called with that blob of
data. An authentication processor can decide whether the given blob is something it can handle
or not;
+    - if it can be handled, the <tt>AuthenticationProcessor#authenticate</tt>
is called with that blob of data, along with an instance of the UserAdmin service. The authentication
processor is now responsible for converting the blob of data to an authenticated user, if
possible.
+3. if a <tt>User</tt> object is returned from the authentication service[^3],
the authentication phase will be regarded as successful. If *no* <tt>User</tt>
object is returned, the authentication phase will be regarded unsuccessful.
 
 This is only half the story for authentication. As stated before, ACE internally also communicates
through HTTP to access certain services. Without any changes, all those remote calls will
fail due to missing credentials. If we want to leave those means of communications as-is,
we would need to track down all places where remote calls are being made and inject the proper
credentials at those places. However, doing this is not only *very* invasive and error prone
but also not very developer friendly from a service-oriented perspective. Alternatively, we
could try to include the credentials in the URL itself, making it self-contained. Not only
would this approach limit our ability to use any kind of authentication mechanism (it only
works for username/password combos), it also required us to supply the credentials manually
each and every time we want to create a remote connection. Instead, we would like to refrain
from passing around credentials, and leverage the service orien
 ted aspects of OSGi to create remote connections for us. This service could then be responsible
for adding the right credentials for us, leaving the calling party totally unaware about the
fact authentication might be used. Such a service is denoted in the following figure:
 
-![Figure 3: Connection Factory class diagram](auth_connectionfactory.svg "Figure 3: Connection
Factory class diagram")
+![Figure 3: Connection Factory class diagram](auth_connectionfactory.svg "Figure 3: Connection
Factory class diagram")  
+Figure 3: Connection Factory class diagram.
 
-The `ConnectionFactory` is responsible for creating `URLConnection`s, given a "plain" URL.
So, instead of calling `URL#openConnection()` or `URL#openStream()`, we'll now have to call
`ConnectionFactory#createConnection(url)` instead. But, what advantage does this bring us?
In order to allow the connection factory to supply the credentials to `URLConnection`s, it
is also registered as `ManagedServiceFactory` that enables us to provide multiple configurations
of which credentials should be supplied to what (sets of) URLs. The introduction of the connection
factory allows us to abstract the creation of a connection and passing of credentials to it
from the URL. Internally, the connection factory will match each URL given in `createConnection`
with the URLs it is configured with. If a matching URL is found, it will use the credentials
in that configuration to supply to the `URLConnection`.
+The <tt>ConnectionFactory</tt> is responsible for creating <tt>URLConnection</tt>s,
given a "plain" URL. So, instead of calling <tt>URL#openConnection()</tt> or <tt>URL#openStream()</tt>,
we'll now have to call <tt>ConnectionFactory#createConnection(url)</tt> instead.
But, what advantage does this bring us? In order to allow the connection factory to supply
the credentials to <tt>URLConnection</tt>s, it is also registered as <tt>ManagedServiceFactory</tt>
that enables us to provide multiple configurations of which credentials should be supplied
to what (sets of) URLs. The introduction of the connection factory allows us to abstract the
creation of a connection and passing of credentials to it from the URL. Internally, the connection
factory will match each URL given in <tt>createConnection</tt> with the URLs it
is configured with. If a matching URL is found, it will use the credentials in that configuration
to supply to the <tt>URLConnection</tt>.
 
 We've now closed the circle: we not only have defined how remote endpoints can apply authentication,
but also how all calling parties can remain using these remote endpoints without having to
be aware of authentication. 
 
@@ -65,31 +68,31 @@ Before continuing on the details of conf
 
 ### Remote services
 
-All remote services in ACE are configurable with respect to the endpoint through which they
can be accessed. The following table shows an overview of the remote services, including the
default endpoint they use:
+All remote services in ACE are configurable with respect to the endpoint they can be accessed.
The following table shows an overview of the remote services, including the default endpoint
they use:
 
 Name | Description | Default endpoint | Configuration PID
 ------- | --------------- | --------------------- | --------------------- 
-`BundleServlet` | provides access to the OBR (bundle repository) of ACE | `/obr` | `org.apache.ace.obr.servlet`
-`DeploymentServlet` | handles the actual provisioning of deployment packages to a target
| `/deployment` |`org.apache.ace.deployment.servlet`
-`LogServlet` | allows any number of logs for a target to be synchronized and accessed | `/auditlog`[^4]
| `org.apache.ace.server.log.servlet.factory`<br/>**note: this is a configuration factory!**
-`RepositoryServlet` | provides access to the various (artifact/feature/distribution/target)
internal repositories of ACE | `/repository` | `org.apache.ace.repository.servlet.RepositoryServlet`
-`RepositoryReplicationServlet` | allows *relay nodes* to replicate the internal repositories
of ACE | `/replication` | `org.apache.ace.repository.servlet.RepositoryReplicationServlet`
-`RESTClientServlet` | provides the RESTful interface to ACE |`/client` | `org.apache.ace.client.rest`
-`VaadinServlet` | provides the Vaadin web interface | `/ace` | `org.apache.ace.webui.vaadin`
+<tt>BundleServlet</tt> | provides access to the OBR (bundle repository) of ACE
| <tt>/obr</tt> | <tt>org.apache.ace.obr.servlet</tt>
+<tt>DeploymentServlet</tt> | handles the actual provisioning of deployment packages
to a target | <tt>/deployment</tt> |<tt>org.apache.ace.deployment.servlet</tt>
+<tt>LogServlet</tt> | allows any number of logs for a target to be synchronized
and accessed | <tt>/auditlog</tt>[^4] | <tt>org.apache.ace.server.log.servlet.factory</tt><br/>**note:
this is a configuration factory!**
+<tt>RepositoryServlet</tt> | provides access to the various (artifact/feature/distribution/target)
internal repositories of ACE | <tt>/repository</tt> | <tt>org.apache.ace.repository.servlet.RepositoryServlet</tt>
+<tt>RepositoryReplicationServlet</tt> | allows *relay nodes* to replicate the
internal repositories of ACE | <tt>/replication</tt> | <tt>org.apache.ace.repository.servlet.RepositoryReplicationServlet</tt>
+<tt>RESTClientServlet</tt> | provides the RESTful interface to ACE |<tt>/client</tt>
| <tt>org.apache.ace.client.rest</tt>
+<tt>VaadinServlet</tt> | provides the Vaadin web interface | <tt>/ace</tt>
| <tt>org.apache.ace.webui.vaadin</tt>
 
 ### Configuring authentication for remote services
 
-In the section on the design of the authentication layer, we've mentioned that if a remote
service wants to make use of authentication, it can make use of the `AuthenticationService`.
However, one of the design requirements was that authentication should be optional as well.
In order to enable or disable authentication, each remote service needs to do the following:
+In the section on the design of the authentication layer, we've mentioned that if a remote
service wants to make use of authentication, it can make use of the <tt>AuthenticationService</tt>.
However, one of the design requirements was that authentication should be optional as well.
In order to enable or disable authentication, each remote service needs to do the following:
 
 1. add a **mandatory** configuration property `authentication.enabled = false|true` to their
configuration. Although any kind of name for this configuration property can be used, it is
*strongly* advised to stick to the same name for all services;
-2. when the configuration of a remote service is updated, it should add a service dependency
to the `AuthenticationService`. By making this service *required* when authentication is enabled,
and *optional* when authentication is disabled, we can adhere to the requirement of optionality
for authentication;
-3. in case authentication is *enabled*, each request the service obtains needs to be passed
to the `AuthenticationService` first, and depending on its outcome, the request can continue
or not.
+2. when the configuration of a remote service is updated, it should add a service dependency
to the <tt>AuthenticationService</tt>. By making this service *required* when
authentication is enabled, and *optional* when authentication is disabled, we can adhere to
the requirement of optionality for authentication;
+3. in case authentication is *enabled*, each request the service obtains needs to be passed
to the <tt>AuthenticationService</tt> first, and depending on its outcome, the
request can continue or not.
 
-To make this more concrete, an example of how the `BundleServlet` is to be configured:
+To make this more concrete, an example of how the <tt>BundleServlet</tt> is to
be configured:
 
 #### Service configuration
 
-The service configuration, located in `org.apache.ace.obr.servlet.cfg`, looks like:
+The service configuration, located in <tt>org.apache.ace.obr.servlet.cfg</tt>,
looks like:
 
     :::properties
     # Endpoint for this servlet
@@ -97,7 +100,7 @@ The service configuration, located in `o
     # Whether or not authentication is to be used
     authentication.enabled = true
 
-In `BundleServlet` we add the following code:
+In <tt>BundleServlet</tt> we add the following code:
 
     :::java
     private volatile boolean m_useAuth;
@@ -130,10 +133,10 @@ In `BundleServlet` we add the following 
             .setService(AuthenticationService.class)
             .setRequired(m_useAuth)
             .setInstanceBound(true)
-            );
+        );
     }
 
-As almost all of the services in ACE are managed by the Dependency Manager, we can leverage
its dynamics to inject our `BundleServlet` with an instance of the `AuthenticationService`
and provide us with a configuration[^5]. 
+As almost all of the services in ACE are managed by the Dependency Manager, we can leverage
its dynamics to inject our <tt>BundleServlet</tt> with an instance of the <tt>AuthenticationService</tt>
and provide us with a configuration[^5]. 
 
 #### Implemention
 
@@ -152,21 +155,21 @@ The actual authentication implementation
     }
     
     private boolean authenticate(HttpServletRequest request) {
-        User user = null;
         if (m_useAuth) {
             User user = m_authService.authenticate(request);
+            if (user == null) {
+                m_log.log(LogService.LOG_INFO, "Authentication failure!");
+            }
+            return (user != null);
         }
-        if (user == null) {
-            m_log.log(LogService.LOG_INFO, "Authentication failure!");
-        }
-        return (user != null);
+        return true;
     }
 
-Note that this implementation does not tell *how* the authentication should occur, only that
it should occur. How the authentication is performed, is determined internally by the `AuthenticationService`,
with the help of the registered `AuthenticationProcessor`s.
+Note that this implementation does not tell *how* the authentication should occur, only that
it should occur. How the authentication is performed, is determined internally by the <tt>AuthenticationService</tt>,
with the help of the registered <tt>AuthenticationProcessor</tt>s.
 
 ### Configuring the connection factory
 
-Now that the remote service itself is no longer accepting unauthenticated requests, we need
to supply the credentials to access this service to the `ConnectionFactory` service. This
service can be configured using the PID `org.apache.ace.connectionfactory` (*note that it
is a configuration factory!*), which would result in the following configuration for accessing
our `BundleServlet`:
+Now that the remote service itself is no longer accepting unauthenticated requests, we need
to supply the credentials to access this service to the <tt>ConnectionFactory</tt>
service. This service can be configured using the PID <tt>org.apache.ace.connectionfactory</tt>
(*note that it is a configuration factory!*), which would result in the following configuration
for accessing our <tt>BundleServlet</tt>:
 
     :::properties
     # What kind of authentication should we supply
@@ -177,7 +180,7 @@ Now that the remote service itself is no
     # What is the base URL that these credentials apply to:
     authentication.baseURL = http://localhost:8080/obr/
 
-When this configuration is supplied to the `ConnectionFactory`, it will provide a basic HTTP
authentication header to each connection created for any URL starting with "http://localhost:8080/obr/"[^6].

+When this configuration is supplied to the <tt>ConnectionFactory</tt>, it will
provide a basic HTTP authentication header to each connection created for any URL starting
with "<tt>http://localhost:8080/obr/</tt>"[^6]. 
 
 ### Configuring the management agent
 
@@ -188,10 +191,10 @@ When this configuration is supplied to t
 
 [^2]: Assuming that all components in the ACE server are trusted and obtained from trusted
sources. If untrusted components would be allowed, we need to add authentication to these
communication paths as well.
 
-[^3]: It is up to the implementation of `AuthenticationService` whether the *first* found
user is returned, or whether it checks if all authentication processors yield the *same* user,
or any other strategy that is desired.
+[^3]: It is up to the implementation of <tt>AuthenticationService</tt> whether
the *first* found user is returned, or whether it checks if all authentication processors
yield the *same* user, or any other strategy that is desired.
 
 [^4]: Amongst others, any number of log-endpoints can be defined, at least one is needed
for the audit log to be synchronized between target and ACE server.
 
 [^5]: Note that we're using a configuration dependency for this service. This way, the configuration
**must** be present before the service itself is registered, which allows us to determine
if authentication should be used or not.
 
-[^6]: Currently, a simple `String#startsWith()` is used to determine whether or not a URL
matches a configuration. This might change in the future when a more sophisticated URL-matching
strategy is needed.
+[^6]: Currently, a simple <tt>String#startsWith()</tt> is used to determine whether
or not a URL matches a configuration. This might change in the future when a more sophisticated
URL-matching strategy is needed.



Mime
View raw message