ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r1641501 [1/4] - in /ace/site/trunk/content: ./ dev-doc/ docs/ docs/analysis/ docs/analysis/src/ docs/design/ docs/design/src/ docs/use-cases/ user-doc/
Date Mon, 24 Nov 2014 22:42:03 GMT
Author: jawi
Date: Mon Nov 24 22:42:00 2014
New Revision: 1641501

URL: http://svn.apache.org/r1641501
Log:
Restructured the ACE documentation:

- unified the user/dev docs into a single directory,
  as there is no clear distinction between users and
  developers;
- added a getting started in 5 minutes guide to get
  users up and running;
- updated the users guide to add some more details.


Added:
    ace/site/trunk/content/docs/
    ace/site/trunk/content/docs.mdtext   (with props)
    ace/site/trunk/content/docs/ace-authentication.mdtext   (with props)
    ace/site/trunk/content/docs/ace-deployment-strategies.mdtext   (with props)
    ace/site/trunk/content/docs/ace-roles.mdtext   (with props)
    ace/site/trunk/content/docs/ace_dnd_artifacts.png   (with props)
    ace/site/trunk/content/docs/ace_dnd_artifacts_fail.png   (with props)
    ace/site/trunk/content/docs/ace_dnd_artifacts_ok.png   (with props)
    ace/site/trunk/content/docs/ace_dynamic_association.png   (with props)
    ace/site/trunk/content/docs/ace_server_topology.png   (with props)
    ace/site/trunk/content/docs/ace_server_ui.png   (with props)
    ace/site/trunk/content/docs/ace_static_association.png   (with props)
    ace/site/trunk/content/docs/ace_target_tag_editor.png   (with props)
    ace/site/trunk/content/docs/ace_user_management_admin_ui.png   (with props)
    ace/site/trunk/content/docs/ace_user_management_newuser_ui.png   (with props)
    ace/site/trunk/content/docs/ace_user_management_user_ui.png   (with props)
    ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext   (with props)
    ace/site/trunk/content/docs/analysis/
    ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext   (with props)
    ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext   (with props)
    ace/site/trunk/content/docs/analysis/index.mdtext   (with props)
    ace/site/trunk/content/docs/analysis/security-analysis-flow.svg   (with props)
    ace/site/trunk/content/docs/analysis/security-analysis.mdtext
    ace/site/trunk/content/docs/analysis/src/
    ace/site/trunk/content/docs/analysis/src/security-analysis-flow.graffle   (with props)
    ace/site/trunk/content/docs/analysis/template-mechanism.mdtext
    ace/site/trunk/content/docs/architecture.mdtext   (with props)
    ace/site/trunk/content/docs/auth_api.svg   (with props)
    ace/site/trunk/content/docs/auth_connectionfactory.svg   (with props)
    ace/site/trunk/content/docs/auth_main_components.svg   (with props)
    ace/site/trunk/content/docs/coding-standards.mdtext   (with props)
    ace/site/trunk/content/docs/configuring-relay-servers.mdtext   (with props)
    ace/site/trunk/content/docs/deployment_strategy_classdiagram.svg   (with props)
    ace/site/trunk/content/docs/deployment_strategy_update_seq.svg   (with props)
    ace/site/trunk/content/docs/design/
    ace/site/trunk/content/docs/design/auditlog-protocol.mdtext
    ace/site/trunk/content/docs/design/index.mdtext
    ace/site/trunk/content/docs/design/remote-interfaces-components.svg   (with props)
    ace/site/trunk/content/docs/design/remote-interfaces.mdtext
    ace/site/trunk/content/docs/design/src/
    ace/site/trunk/content/docs/design/src/remote-interfaces-components.graffle   (with props)
    ace/site/trunk/content/docs/design/src/remoteinterfaces-components.graffle   (with props)
    ace/site/trunk/content/docs/getting-started-5-mins.mdtext   (with props)
    ace/site/trunk/content/docs/history-and-background.mdtext   (with props)
    ace/site/trunk/content/docs/relay_functional_overview.png   (with props)
    ace/site/trunk/content/docs/release-guide.mdtext   (with props)
    ace/site/trunk/content/docs/rest-api.mdtext   (with props)
    ace/site/trunk/content/docs/setup-dev-environment.mdtext   (with props)
    ace/site/trunk/content/docs/shell-api.mdtext   (with props)
    ace/site/trunk/content/docs/simple-workflow.png   (with props)
    ace/site/trunk/content/docs/test-script.mdtext   (with props)
    ace/site/trunk/content/docs/use-cases/
    ace/site/trunk/content/docs/use-cases/index.mdtext
    ace/site/trunk/content/docs/use-cases/uc-01.mdtext
    ace/site/trunk/content/docs/use-cases/uc-02.mdtext
    ace/site/trunk/content/docs/use-cases/uc-03.mdtext
    ace/site/trunk/content/docs/use-cases/uc-04.mdtext
    ace/site/trunk/content/docs/use-cases/uc-05.mdtext
    ace/site/trunk/content/docs/use-cases/uc-06.mdtext
    ace/site/trunk/content/docs/use-cases/uc-07.mdtext
    ace/site/trunk/content/docs/use-cases/uc-08.mdtext
    ace/site/trunk/content/docs/use-cases/uc-09.mdtext
    ace/site/trunk/content/docs/use-cases/uc-10.mdtext
    ace/site/trunk/content/docs/use-cases/uc-11.mdtext
    ace/site/trunk/content/docs/use-cases/uc-12.mdtext
    ace/site/trunk/content/docs/use-cases/uc-13.mdtext
    ace/site/trunk/content/docs/use-cases/uc-14.mdtext
    ace/site/trunk/content/docs/use-cases/uc-15.mdtext
    ace/site/trunk/content/docs/use-cases/uc-16.mdtext
    ace/site/trunk/content/docs/use-cases/uc-17.mdtext
    ace/site/trunk/content/docs/use-cases/uc-18.mdtext
    ace/site/trunk/content/docs/use-cases/uc-19.mdtext
    ace/site/trunk/content/docs/use-cases/uc-20.mdtext
    ace/site/trunk/content/docs/use-cases/uc-21.mdtext
    ace/site/trunk/content/docs/use-cases/uc-22.mdtext
    ace/site/trunk/content/docs/use-cases/uc-23.mdtext
    ace/site/trunk/content/docs/use-cases/usecasesview.svg   (with props)
    ace/site/trunk/content/docs/user-guide.mdtext   (with props)
    ace/site/trunk/content/docs/user-management-guide.mdtext   (with props)
    ace/site/trunk/content/docs/using-client-certificates.mdtext   (with props)
    ace/site/trunk/content/docs/writing-tests.mdtext   (with props)
Removed:
    ace/site/trunk/content/dev-doc/
    ace/site/trunk/content/user-doc/

Added: ace/site/trunk/content/docs.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs.mdtext (added)
+++ ace/site/trunk/content/docs.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,61 @@
+Title: Documentation
+
+Apache ACE is a software distribution framework that allows you to manage and deploy
+modular OSGi-based applications to many different clients, also known as "targets" in ACE
+terminology, allowing precise control over which target gets which software. Its key
+features are:
+
+* being able to deploy software to many different targets;
+* atomic upgrades: if an upgrade fails for a target, it is automatically rolled back to the former state;
+* deploy different configurations for different targets;
+* smart redeployments of only the changed artifacts to your targets;
+* complete control on the deployment strategy for your targets.
+
+
+## Getting started
+
+If you are interested in just get Apache ACE up and running, you can read the [getting
+started in 5 minutes](/docs/getting-started-5-mins.html). To get more information about
+the history of Apache ACE, read all about its [history and
+background](/docs/history-and-background.html).
+
+
+## Using Apache ACE
+
+Resources that go into more detail on using Apache ACE:
+
+* read all about using Apache ACE in the [users guide](/docs/user-guide.html);
+* to manage users using ACE's web UI, read the [user management guide](/docs/user-management-guide.html);
+* [information about the various roles used in Apache ACE](/docs/ace-roles.html);
+* accessing Apache ACE [using the Gogo shell](/docs/shell-api.html);
+* accessing Apache ACE from [its REST API](/docs/rest-api.html);
+* to handle a large number of targets, you can make use of [intermediate relay servers](/docs/configuring-relay-servers.html);
+* configuring ACE authentication is described in the [authentication guide](/docs/ace-authentication.html);
+* configuring ACE to use two-way SSL is described in [using client certificates](/docs/using-client-certificates.html);
+* various deployment strategies for Apache ACE are described in the [ACE deployment strategies document](/docs/ace-deployment-strategies.html);
+
+
+## Developing for Apache ACE
+
+There are several resources available on extending and developing for Apache ACE, such as:
+
+* [setting up an development environment for developing for Apache ACE](/docs/setup-dev-environment.html);
+* more details on writing unit and/or integration tests can be found in [this document](/docs/writing-tests.html);
+* all about the coding style and guidelines can be found in the [coding standards](/docs/coding-standards.html);
+* guidelines for releasing Apache ACE can be found in [the release guide](/docs/release-guide.html);
+* more information about the architectural principals can be found in [the architectural guide](/docs/architecture.html);
+* if you are interested in performing load tests, or want to get started with automating ACE deployments, read all about it in our [test script document](/docs/test-script.html);
+* various use cases are described on the [use cases page](/docs/use-cases);
+
+* [adding support for new types of artifacts](/docs/adding-custom-artifact-types.html);
+
+* detailed analysis documentation giving background information on some development principles currently used:
+** [audit log analysis](/docs/analysis/auditlog-analysis.html);
+** [bundle repository analysis](/docs/analysis/bundlerepository-analysis.html);
+** [security analysis](/docs/analysis/security-analysis.html);
+** [template mechanism](/docs/analysis/template-mechanism.html).
+
+* detailed design documentation:
+** [remote interface design](/docs/design/remote-interfaces.html);
+** [audit log details](/docs/design/auditlog-protocol.html);
+

Propchange: ace/site/trunk/content/docs.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/ace-authentication.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace-authentication.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/ace-authentication.mdtext (added)
+++ ace/site/trunk/content/docs/ace-authentication.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,248 @@
+Title: ACE Authentication
+
+_Enabling authentication in ACE_
+
+Revision 1.0, last updated: April 26th, 2012.
+
+[TOC]
+
+## 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.
+In this article, the recently added authentication layer of ACE is explained in more depth and how to configure authentication to your situation.  
+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.
+
+
+## Communication paths
+
+Before going in more detail on the design and configuration of the authentication layer in ACE, we first need to pinpoint all places were authentication needs 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 the above figure, several of the communication paths (denoted by the circled digits) that can be identified in ACE are represented:
+
+1. the client communicates to the ACE server by means of both direct calls to its services as well as remote (HTTP[^1]) calls;
+2. a management agent (representing the target) communicates to the ACE server through remote calls;
+3. the REST API exposes the entire client and server APIs in a RESTful way. Communication to the client occurs by both direct and remote calls;
+4. the Vaadin Web UI exposes the entire client API as web application. Similar as the REST API, it communicates both directly as remotely with the client.
+
+As can be seen from the above figure, most of the communication paths are remoted. The reason for this is twofold:
+
+1. It allows reuse of components; for example access to the OBR-servlet is used by the both the client-API as well the web UI to upload new artifacts;
+2. it enables scalability by allowing components to be deployed on different machines; for example, one does not need to run the client on the same machine as the server. This could be useful for working on high-latency networks.
+
+All direct (i.e., non remoted) communication paths do not need to be authenticated, as they require that both caller and callee run in the same virtual machine, making it impossible to be used outside the virtual machine[^2]. Hence, we only need to add an authentication layer to the remote endpoints. However, adding authentication to all remote endpoints poses us with the challenge to let the "internal" communication paths that use remote calls to authenticate themselves as well. Not doing so would prevent ACE from functioning correctly. A disadvantage of this approach is that it is an all-or-nothing approach, either all users of the remote endpoints use authentication, or none of them. However, the way users authenticate themselves can be different, meaning that one set of users can use basic authentication to identify themselves, while another set uses client certificates to identify themselves.
+
+
+## Authentication design
+
+The high-level design for security in ACE is explained in the [remote interface design](/docs/design/remote-interfaces.html). From this design, we can derive several requirements for the design of ACE's authentication layer:
+
+1. should be applicable and configurable for all remoted endpoints. If a new endpoint is added to ACE, it should be easy to add and configure authentication for it;
+2. should be optional. If no authentication is desired, one should be able to remove its services from the ACE distribution;
+3. should be pluggable. Various ways of authentication exist, and new ones can emerge. Making the authentication mechanism pluggable allows new ways of authentication to be used easily.
+
+Based on these requirements, the design of the authentication layer is represented in the following figure: {#fig2}
+
+![Figure 2: Authentication layer class diagram](auth_api.svg "Figure 2: Authentication layer class diagram")  
+**Figure 2**: Authentication layer class diagram.
+
+The <tt>AuthenticationService</tt> is responsible for authenticating a user based on some piece of information. This piece of information can be an array containing a username/password combination, a <tt>HttpServletRequest</tt> containing authentication request headers, or any other type 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. <tt>AuthenticationService#authenticate</tt> is called with a blob of data, for example a <tt>HttpServletRequest</tt>;
+2. for each known <tt>AuthenticationProcessor</tt>:
+    - <tt>AuthenticationProcessor#canHandle</tt> is called with that blob of data. In this method, 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 <tt>UserAdmin</tt> 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 remote endpoints to access certain services. Without any changes, all those remote calls will fail due to missing credentials. If we would leave those means of communications as-is, we need to track down all places where remote calls are being made and inject the proper credentials at each of 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 o
 riented 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 (or not). 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.
+
+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 give 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 thus 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>.
+
+
+### Remote services
+
+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. The only thing left, is a summary of which remote endpoints currently exist in ACE.  
+All remote services 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 | Endpoint | Configuration PID[^4]
+------- | --------------- | ------------ | --------------------- 
+<tt>BundleServlet</tt> | provides access to the OBR (bundle repository) of ACE | <tt>/obr</tt> | <tt>o.a.a.obr.servlet</tt>
+<tt>DeploymentServlet</tt> | handles the actual provisioning of deployment packages to a target | <tt>/deployment</tt> |<tt>o.a.a.deployment.servlet</tt>
+<tt>LogServlet</tt> | allows any number of logs for a target to be synchronized and accessed | <tt>/auditlog</tt>[^5] | <tt>o.a.a.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>o.a.a.repository.servlet.<br/>RepositoryServlet</tt>
+<tt>RepositoryReplicationServlet</tt> | allows *relay nodes* to replicate the internal repositories of ACE | <tt>/replication</tt> | <tt>o.a.a.repository.servlet.<br/>RepositoryReplicationServlet</tt>
+<tt>RESTClientServlet</tt> | provides the RESTful interface to ACE |<tt>/client</tt> | <tt>o.a.a.client.rest</tt>
+<tt>VaadinServlet</tt> | provides the Vaadin web interface | <tt>/ace</tt> | <tt>o.a.a.webui.vaadin</tt>
+&#160; | &#160; | &#160; | &#160;
+
+## Configuring authentication
+
+Now we have discussed the design of the authentication layer in ACE in rather detail, lets continue with how we can configure the authentication. Note that in order to make use of this functionality, you need to use the latest TRUNK of ACE, as explained in the introduction.
+
+### 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 <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 <tt>authentication.enabled = false|true</tt> 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 <tt>AuthenticationService</tt>. By making this service **required** if 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, we walk through an example of how the <tt>BundleServlet</tt> is to be configured. As this is a servlet (as almost all other remote endpoints in ACE), we can intercept all service requests by overriding the <tt>Servlet#service()</tt> method and perform our authentication check there. If this check is successful, we continue passing the service request, and return a "401 - Unauthorized" when the check is unsuccessful. 
+
+#### Configuring the authentication
+
+The service configuration, denoted by the <tt>org.apache.ace.obr.servlet.cfg</tt> in the stock ACE distribution, looks like:
+
+    :::properties
+    # Endpoint for this servlet
+    org.apache.ace.server.servlet.endpoint = /obr
+    # Whether or not authentication is to be used
+    authentication.enabled = true
+
+Note that we've added the <tt>authentication.enabled</tt> property that allows us to enable or disable the authentication check for this servlet.
+
+#### Making use of the service configuration
+
+To let the servlet pick up our configuration, it should be registered as <tt>ManagedService(Factory)</tt>. To make use of the configuration, we need to add the following code to our <tt>BundleServlet</tt>:
+
+    :::java
+    private volatile boolean m_useAuth;
+    private volatile AuthenticationService m_authService;
+    
+    // ...
+    
+    public void updated(Dictionary settings) throws ConfigurationException {
+        if (settings != null) {
+            String useAuthString = (String) settings.get("authentication.enabled");
+            if (useAuthString == null || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString))) {
+                throw new ConfigurationException("authentication.enabled", "Missing or invalid value!");
+            }
+            
+            m_useAuth = Boolean.parseBoolean(useAuthString);
+        }
+        else {
+            m_useAuth = false;
+        }
+    }
+    
+    // ...
+    
+    /**
+     * Called by Dependency Manager upon initialization of this component.
+     */
+    protected void init(Component comp) {
+        comp.add(m_dm.createServiceDependency()
+            .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 <tt>BundleServlet</tt> with an instance of the <tt>AuthenticationService</tt> and provide us with a configuration[^6]. In the <tt>updated()</tt> method, we perform a check whether the prior mentioned <tt>authentication.enabled</tt> property is present in the given configuration, and if so, whether it represents a valid boolean value. The actual boolean value itself will be held in a field (<tt>m_useAuth</tt>) for later use.
+
+#### Implementing the authentication check
+
+The actual authentication implementation itself is rather trivial: we simply intercept all incoming requests in our servlet and verify whether it resolves to a valid user:
+
+    :::java
+    @Override
+    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        if (!authenticate(req)) {
+            // Authentication failed; don't proceed with the original request...
+            resp.sendError(SC_UNAUTHORIZED);
+        } else {
+            // Authentication successful, proceed with original request...
+            super.service(req, resp);
+        }
+    }
+    
+    private boolean authenticate(HttpServletRequest request) {
+        if (m_useAuth) {
+            User user = m_authService.authenticate(request);
+            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 <tt>AuthenticationService</tt>, with the help of the registered <tt>AuthenticationProcessor</tt>s.  
+Also note that the <tt>authenticate</tt> method itself uses the previously defined field (<tt>m_useAuth</tt>) to determine whether or not the authentication check should be performed. If it is *not* performed, we consider the request to be always authenticated, in order to obtain the same semantics as we would have without this check.
+
+### 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 <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, accepting multiple configurations!  
+For accessing our <tt>BundleServlet</tt>, we need to supply it the following configuration:
+
+    :::properties
+    # What kind of authentication should we supply
+    authentication.type = basic
+    # The actual credentials for basic authentication
+    authentication.user.name = d
+    authentication.user.password = f
+    # What is the base URL that these credentials apply to:
+    authentication.baseURL = http://localhost:8080/obr/
+
+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>"[^7].  
+To disable authentication for a particular URL, the <tt>authentication.type</tt> option can be set to <tt>none</tt>. 
+
+### Configuring the management agent
+
+The management agent itself also needs to use authentication to communicate with the remote services of the ACE server. It reuses the <tt>ConnectionFactory</tt> service for this, so it needs to obtain the same set of configurations as described in the previous section. The only thing we need to do is tell the management agent were it can find those configuration file(s):
+
+    :::sh
+    [localhost:~/]$ java -jar org.apache.ace.launcher-0.8.1-SNAPSHOT.jar \
+     discovery=http://localhost:8080/ \
+     identification=MyTarget \
+     auth=/path/to/connectionfactory/config/file(s)
+
+Alternatively, one could adapt the code of the management agent to use the <tt>ConfigAdmin</tt> service directly for creating the individual configurations using the service factory PID <tt>org.apache.ace.connectionfactory</tt>. 
+
+### Configuring users
+
+In order to successfully authenticate a user, it needs a corresponding <tt>User</tt> that can be obtained from the <tt>UserAdmin</tt> service. Initially, ACE imports a small set of users and roles defined in the "<tt>org.apache.ace.server.repository.factory/ace-user.cfg</tt>" configuration file. One could update this file in order to add users[^8], or add them, for example, to an LDAP-service and make the <tt>UserAdmin</tt> service retrieve users from this backend. The exact details on how to configure this are beyond this article.
+
+
+## Troubleshooting
+
+If after configuring the authentication of ACE things no longer work, it can be hard to find the exact cause of this. In this section, some pointers are given to help you to find the probably cause of the problem.
+
+I've enabled authentication, but I can still use all services without passing any credentials!
+: If you've updated the configuration files of a running server or management agent, the configuration files are not automatically picked up by default. You need to stop the server/management agent, clean its felix-cache folder and start it again.
+
+With authentication enabled, how can I test whether the endpoints accept my credentials?
+: In order to test the remote endpoints of ACE, you can use a tool like [REST client](http://code.google.com/p/rest-client/). It allows you to enter credentials for any given URL.
+
+After enabling authentication, I do not get any errors after starting the ACE server, but it doesn't function correctly!
+: Is the connection factory properly configured? Are *all* <tt>authentication.type</tt> options correctly set to <tt>basic</tt> and are the username/passwords correctly set? Are the configured base URLs not overlapping each other (e.g.: <tt>baseURL = http://localhost:8080/</tt> and <tt>baseURL = http://localhost:8080/obr</tt>)?
+
+After enabling authentication, the management agent(s) no longer functions/I do not see them added in the web UI.
+: Did you pass the <tt>auth=/path/to/config/file(s)</tt> option to the management agent to configure the connection factory? Are those files correctly stating the "<tt>authentication.type = basic</tt>", including the username and password for the desired URLs? Can you access the URLs mentioned in the configuration files with a tool like [REST client](http://code.google.com/p/rest-client/)?
+
+I do not want basic HTTP authentication, I want to use (fill in the kind of authentication)!
+: The current implementation is quite simple and basic, but it can be extended by means of custom authentication processors.
+
+
+## Notes
+
+[^1]: Other communication protocols could be used as well. However, currently, only HTTP is natively supported by ACE. For the remainder of this article, we'll assume HTTP as protocol.
+
+[^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 <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]:  The common prefix of the shown configuration PIDs are abbreviated, so "<tt>o.a.a</tt>" stands for "<tt>org.apache.ace</tt>".
+
+[^5]: 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.
+
+[^6]: 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.
+
+[^7]: 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.
+
+[^8]: Make sure to clean the <tt>felix-cache</tt> directory before restarting the server, otherwise the new configuration files will not be picked up!

Propchange: ace/site/trunk/content/docs/ace-authentication.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/ace-deployment-strategies.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace-deployment-strategies.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/ace-deployment-strategies.mdtext (added)
+++ ace/site/trunk/content/docs/ace-deployment-strategies.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,218 @@
+Title: Deployment Strategies
+
+_Implementing custom update policies_
+
+last updated: April 19th, 2012
+
+## Introduction
+
+This article describes how ACE deploys new deployment packages to targets and how this strategy can be adapted to support more sophisticated scenario's.  
+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.1326140) was used.
+
+## Provisioning
+
+Apache ACE is all about provisioning software artifacts to targets. Software artifacts, or simply, artifacts, can be compiled code, configuration files, or any other artifact needed for a software system to operate. Provisioned artifacts are bundled in so-called "deployment packages", that is comprised of the differences between the target's current artifacts and the to-be-deployed artifacts. To distinguish between deployment packages, each one is given its own version. The increment of versions is done automatically by ACE when changes are committed to its repository.  
+When a new deployment package is available, it is not automatically sent to the target as the communication between target and management server (ACE) is unidirectional and initiated by the target. A target has to periodically check whether new deployment packages are available, and if so, do something with it.
+
+## Understanding ACE's deployment strategy
+
+Upon startup, the management agent, which represents a target, schedules several tasks that periodically synchronize the local state with that of the management server. Two of these tasks relate to the handling of deployment packages: `DeploymentCheckTask` and `DeploymentUpdateTask`. Figure 1 shows the relationship between the various components.
+
+![Figure 1: class diagram](deployment_strategy_classdiagram.svg "Figure 1: class diagram")  
+Figure 1: deployment strategy class diagram.
+
+The `DeploymentCheckTask` is responsible for periodically checking the management server for newer versions of deployment packages and if found emits an event. The `DeploymentUpdateTask` also periodically checks the management server, and if it finds a newer version, automatically downloads and installs it.
+
+![Figure 2: sequence diagram](deployment_strategy_update_seq.svg "Figure 2: sequence diagram")  
+Figure 2: deployment strategy sequence diagram.
+
+Figure 2 shows a more detailed sequence diagram of the deployment update strategy in ACE. The scheduler in the management agent calls the run()-method of the DeploymentUpdateTask once every _N_ seconds. This method in its turn makes several calls to the `DeploymentService`, which acts as a facade for other services in ACE. The `DeploymentService` is queried for the highest local and remote versions. If the remote version is newer than the local version, a deployment package containing the changes between the local and the remote version is installed. Note that this installation is done in a best effort strategy: if it fails, all changes are rolled back to what they were. As a consequence, if the installation fails one time, it probably will fail the next time as well. 
+
+### Tweaking the deployment strategy
+
+By default, the management agent allows the interval in which the update task is run to be customized. To change this interval, the management agent should be started with the extra system property "`-Dsyncinterval=1500`". The value of this property is interpreted as the interval time in milliseconds. Note that this property also changes the interval of other tasks as well, so setting it to a lower interval could potentially raise lots of traffic to your management server.
+
+Another thing you can customize is whether or not the update task should run at all. This is done by starting the management agent with the system property "`-Dorg.apache.ace.deployment.task=disabled`". While this option is not really useful out-of-the-box (the target is not be able to obtain any version at all) it opens up a possibility for providing custom deployment strategies.
+
+## Implementing a custom deployment strategy
+
+To implement our own deployment strategy, we need to create a bundle that provides the management agent with our update task. We will start with an update task that simply prints something to the console each time it is run and expand it later on. As can be seen in figure 1, a task is anything that implements the `Runnable` interface, so our update task needs to do as well. Furthermore, we will use the DependencyManager component from Felix to provide us with the right dependent services, the most important one being the `DeploymentService`.  
+The (stub) code for our update task looks like:
+
+    #!java
+    package net.luminis.ace.updatetask;
+    
+    import org.apache.ace.deployment.service.DeploymentService;
+    import org.osgi.service.log.LogService;
+    
+    public class MyUpdateTask implements Runnable {
+        // injected by DependencyManager
+        private DeploymentService m_service; 
+        private LogService m_logService;
+        
+        public void run() {
+            System.out.println("Hello from MyUpdateTask: " + new java.util.Date());
+        }
+    }
+
+The bundle activator that registers our update task as service:
+
+    #!java
+    package net.luminis.ace.updatetask;
+    
+    import java.util.Properties;
+    
+    import org.apache.ace.deployment.service.DeploymentService;
+    import org.apache.ace.scheduler.constants.SchedulerConstants;
+    import org.apache.felix.dm.DependencyActivatorBase;
+    import org.apache.felix.dm.DependencyManager;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.service.log.LogService;
+    
+    public class Activator extends DependencyActivatorBase {
+      public void init(BundleContext context, DependencyManager manager) throws Exception {
+        Properties props = new Properties();
+        props.put(SchedulerConstants.SCHEDULER_NAME_KEY, MyUpdateTask.class.getName());
+        props.put(SchedulerConstants.SCHEDULER_DESCRIPTION_KEY, "My own deployment update service.");
+        props.put(SchedulerConstants.SCHEDULER_RECIPE, "5000");
+    
+        manager.add(createComponent()
+          .setInterface(Runnable.class.getName(), props)
+          .setImplementation(new MyUpdateTask())
+          .add(createServiceDependency()
+            .setService(DeploymentService.class)
+            .setRequired(true)
+          )
+          .add(createServiceDependency()
+            .setService(LogService.class)
+            .setRequired(false)
+          )
+        );
+      }
+    
+      public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+        // Nothing
+      }
+    }
+
+The activator isn't that different from any other one, the only interesting part is the service properties that we register along with our update task. The three properties are used by the ACE's scheduler to determine that our service is actually a scheduled task. With the "recipe" key, the scheduler is told what interval (in milliseconds) is to be used to execute our task. In our case the recipe is set to 5000, causing our task to be run once every five seconds.  
+To complete the whole cycle, we need some build scripting. For this, we use [BndTools](http://bndtools.org):
+
+    :::text
+    Bundle-Name: My Update Task
+    Bundle-Version: 0.0.1
+    Bundle-SymbolicName: net.luminis.ace.updatetask
+    Bundle-Activator: net.luminis.ace.updatetask.Activator
+    Private-Package: net.luminis.ace.updatetask
+    Import-Package: *
+    -buildpath: org.apache.ace.deployment.task.base;version=0.8,\
+         org.apache.ace.scheduler.api;version=0.8,\
+         org.apache.felix.dependencymanager;version=3.0,\
+         osgi.core;version=4.2.0,\
+         osgi.cmpn;version=4.2.0
+
+To let the management agent to find and use our custom update task bundle, we need to add the JAR-file to its class path, and start the management agent with the following options:
+
+    :::sh
+    [localhost:~/]$ java -Dorg.apache.ace.deployment.task=disabled \
+     -cp org.apache.ace.launcher-0.8.1-SNAPSHOT.jar:net.luminis.ace.updatetask-1.0.0.jar \
+     org.apache.ace.launcher.Main \
+     bundle=net.luminis.ace.updatetask.Activator \
+     identification=myTarget \
+     discovery=http://localhost:8080
+
+Note that besides adding our bundle to the class path, we also have added the `bundle` argument to tell the management agent to include our bundle activator in its startup.  
+If everything went well, one of the first few lines printed out on the console should be something like:
+
+    Adding additional bundle activator: net.luminis.ace.updatetask.Activator
+    Not starting activator org.apache.ace.deployment.task.
+    ...
+
+After startup, our update task should print a message stating its existence to the console every five seconds.
+
+With the boiler plating in place, its time to make our update task a little more interesting. We change the code of our update task to the following (for brevity, only the run() method is shown):
+
+    #!java
+    public void run() {
+        try {
+            Version local = m_service.getHighestLocalVersion();
+            Version remote = m_service.getHighestRemoteVersion();
+    
+            if ((remote != null) && ((local == null) || (remote.compareTo(local) > 0))) {
+                // Ask user whether this update should proceed...
+                System.out.println("Update available! Upgrade from " + local + " to " + remote + " [Y/N]?");
+    
+                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+                String result = reader.readLine();
+    
+                if ("y".equalsIgnoreCase(result)) {
+                    // Ask the deployer service to install this update...
+                    m_service.installVersion(remote, local);
+    
+                    m_logService.log(LogService.LOG_INFO, "Update installed!");
+                }
+            }
+        } catch (IOException e) {
+            m_logService.log(LogService.LOG_WARNING, "Update failed!", e);
+        } catch (Exception e) {
+            m_logService.log(LogService.LOG_WARNING, "Update failed!", e);
+    }
+
+This new implementation first asks the `DeploymentService` what the current local (= version current running on management agent) and remote (= version available in the management server) versions are. If the remote version is newer/higher than the local version, than we ask the user for permission to install the update. When given, the `DeploymentService` is requested to upgrade from the local version to the remote version.  
+If you would run this code, you'll notice that if the user doesn't respond within the task's interval, a new task is started, causing an ever increasing number of tasks to be waiting for user input in case an update is available. Currently, due to the current implementation of ACE's scheduler, there is no way of disabling this behavior (although it is not really difficult to resolve this problem locally in your task).
+
+## Taking it a step further…
+
+So far, we've reused the `DeploymentService` facade from ACE to tweak the update process of the management agent a bit. However, there still some magic going on in the installation of newer versions (all the logic behind `DeploymentService#installVersion`).  
+Let's explore this method a bit more into detail. The `installVersion` method roughly (some details are left out for brevity) has the following implementation:
+
+    #!java
+    // injected by Felix' dependency manager
+    volatile Deployment m_deployer;
+    volatile EventAdmin m_eventAdmin;
+    volatile Identification m_identification;
+    // denotes the host + port where ACE is listening, e.g. http://192.168.1.1:8080/
+    final String m_host;
+    
+    /**
+     * @see org.apache.ace.deployment.service.impl.DeploymentServiceImpl#installVersion
+    */
+    public void installVersion(Version highestRemoteVersion, Version highestLocalVersion) throws Exception {
+        InputStream inputStream = null;
+    
+        try {
+            String version = highestRemoteVersion.toString();
+            URL baseURL = new URL(m_host, "deployment/" + m_identification.getID() + "/versions/");
+            if (highestLocalVersion != null) {
+                version += "?current=" + highestLocalVersion.toString();
+            }
+            URL dataURL = new URL(baseURL, version);
+            inputStream = dataURL.openStream();
+    
+            // Post event for audit log
+            String topic = "org/apache/ace/deployment/INSTALL";
+            m_eventAdmin.postEvent(createEvent(topic, version, dataURL));
+    
+            m_deployer.install(inputStream);
+        }
+        finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                }
+                catch (Exception ex) {
+                    // Not much we can do.
+                }
+            }
+        }
+    }
+
+Basically, the method builds up an URL to access the deployment service of ACE. Through this URL, the deployment-service creates a deployment package containing the changed artifacts between the given local and remote version. The `InputStream` containing this deployment package is given to the `Deployment` service (a facade to the standard DeploymentAdmin service) to be installed. Note that if the installation of the deployment package fails, an exception is thrown. As mentioned earlier, the installation of deployment packages is done in a "all or nothing" strategy, meaning that if it fails, all changes are reverted. For more details on this, you can read the DeploymentAdmin specification (see [2], chapter 114).  
+Aside the actual installation of the deployment package, an event is also posted to keep track of this installation. This event is picked up by the `AuditLog` service of ACE to track all changes made to the management agent (_one can argue whether this shouldn't be a responsibility of the Deployment facade_). 
+
+Now we have seen how the installation of deployment packages is implemented in ACE, we can even tweak that process a bit. For example, we could first download the deployment package entirely to a temporary location, and install it from there. Or, as we have access to the deployment package, we could also provide the user additional information about its contents, perhaps showing a change log or a summary of its contents, before installing it.
+
+## References
+
+1. [ACE subversion](http://svn.apache.org/repos/asf/ace/);
+2. [OSGi 4.2 compendium specification](http://www.osgi.org/Download/Release4V42).

Propchange: ace/site/trunk/content/docs/ace-deployment-strategies.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/ace-roles.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace-roles.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/ace-roles.mdtext (added)
+++ ace/site/trunk/content/docs/ace-roles.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,43 @@
+Title: Roles
+
+These are the different roles in the system. Users of the system can be assigned one or more roles. The roles are also used in the different [use cases](use-cases/).
+
+## Release Manager
+
+The release manager manages the software configuration, linking artifacts to features and features to distributions.
+
+## Target Manager
+
+The target manager manages the total population of targets and assigns them to target operators.
+
+## Target Operator
+
+The target operator manages a (limited) set of targets designated to him by the target manager. He is responsible for accepting changes to the software configuration for those targets.
+
+## Remote Target Operator
+
+Like the target operator, the remote target operator manages a limited set of targets.
+
+## License Manager
+
+The license manager manages the relationship between the targets and the distributions.
+
+## Administrator
+
+The administrator manages the users, system settings, rights and security certificates for the whole ecosystem.
+
+## Target
+
+A target runs the management agent that is responsible for updating the target.
+
+## Server
+
+The server manages all the metadata that expresses what artifacts should be installed on what targets over time. It also contains an OBR for managing the actual artifacts.
+
+## Relay server
+
+The relay server acts as a cache for the server. It synchronizes with the server and might only contain a subset of the metadata to service a subset of the targets.
+
+## Software Developer
+
+The software developer provides artifacts that will be added to the OBR.

Propchange: ace/site/trunk/content/docs/ace-roles.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/ace_dnd_artifacts.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_dnd_artifacts.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_dnd_artifacts.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_dnd_artifacts_fail.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_dnd_artifacts_fail.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_dnd_artifacts_fail.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_dnd_artifacts_ok.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_dnd_artifacts_ok.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_dnd_artifacts_ok.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_dynamic_association.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_dynamic_association.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_dynamic_association.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_server_topology.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_server_topology.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_server_topology.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_server_ui.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_server_ui.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_server_ui.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_static_association.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_static_association.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_static_association.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_target_tag_editor.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_target_tag_editor.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_target_tag_editor.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_user_management_admin_ui.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_user_management_admin_ui.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_user_management_admin_ui.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_user_management_newuser_ui.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_user_management_newuser_ui.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_user_management_newuser_ui.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/ace_user_management_user_ui.png
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/ace_user_management_user_ui.png?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/ace_user_management_user_ui.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext (added)
+++ ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,234 @@
+Title: Adding custom artifact types
+
+Out of the box, ACE comes with support for bundles and configuration files that follow the
+Auto Configuration specification. However, it is possible to extend ACE with support for
+new types of artifacts. Doing so requires you to do three things:
+
+1. Write a resource processor, according to the Deployment Admin specification.
+2. Write an ArtifactRecognizer service implementation.
+3. Write an ArtifactHelper service implementation.
+
+This document explains how to write each of these, and how to subsequently deploy them
+appropriately.
+
+## Writing a resource processor
+
+A resource processor implements the ResourceProcessor interface as defined in the
+Deployment Admin specification (OSGi Compendium 114.10). It describes in detail the
+contract that needs to be implemented and also contains an example. If you want to get
+started quickly, you can use the following code:
+
+	:::java
+	public class Processor implements ResourceProcessor {
+	    private volatile DeploymentSession m_session;
+	    private String m_deploymentPackageName;
+	    private List<String> m_toInstall;
+	    private List<String> m_toRemove;
+
+	    /**
+	     * Sets up the necessary environment for a deployment session.
+	     */
+	    private void startSession(DeploymentSession session) {
+	        if (m_session != null) {
+	            throw new IllegalArgumentException("This resource processor is currently processing another deployment session, installing deploymentpackage" + m_session.getTargetDeploymentPackage().getName());
+	        }
+	        m_session = session;
+	        m_toInstall = new ArrayList<String>();
+	        m_toRemove = new ArrayList<String>();
+	        String fromSource = session.getSourceDeploymentPackage().getName();
+	        String fromTarget = session.getTargetDeploymentPackage().getName();
+	        if (fromSource.equals("")) {
+	            m_deploymentPackageName = fromTarget;
+	        }
+	        else {
+	            m_deploymentPackageName = fromSource;
+	        }
+	    }
+
+	    /**
+	     * Ends a deployment session.
+	     */
+	    private void endSession() {
+	        m_session = null;
+	        m_deploymentPackageName = null;
+	        m_toInstall = null;
+	        m_toRemove = null;
+	    }
+
+	    private void ensureSession()  {
+	        if (m_session == null) {
+	            throw new IllegalStateException("This resource processor is currently not part of a deployment session.");
+	        }
+	    }
+
+	    public void begin(DeploymentSession session) {
+	        startSession(session);
+	    }
+
+	    public void process(String name, InputStream stream) throws ResourceProcessorException {
+	        ensureSession();
+	        m_toInstall.add(name);
+	    }
+
+	    public void dropped(String resource) throws ResourceProcessorException {
+	        ensureSession();
+	        m_toRemove.add(resource);
+	    }
+
+	    public void dropAllResources() throws ResourceProcessorException {
+	        ensureSession();
+	        m_toRemove.addAll(Collections.EMPTY_LIST /* should be a list of all current resources */);
+	    }
+
+	    public void prepare() throws ResourceProcessorException {
+	        ensureSession();
+	    }
+
+	    public void commit() {
+	        ensureSession();
+	        while (!m_toInstall.isEmpty()) {
+	        	System.out.println("installing: " + m_toInstall.remove(0));
+	        }
+	        while (!m_toRemove.isEmpty()) {
+	        	System.out.println("removing: " + m_toRemove.remove(0));
+	        }
+	        endSession();
+	    }
+
+	    public void rollback() {
+	        // nothing special to do.
+	        ensureSession();
+	        endSession();
+	    }
+
+	    public void cancel() {
+	        ensureSession();
+	        // Nothing to do: we have no long-running operation, we only read the stream.
+	    }
+	}
+
+This should be enough to get you started, but the code takes a few shortcuts so please do
+take some time to read the specification and implement each method correctly.
+
+The next step then is to publish this processor as an OSGi service. Don't forget to add
+the <tt>SERVICE_PID</tt> property and set its value, because that is how the processor is
+later recognized. Package everything up in an OSGi bundle and make sure to include these
+two headers in its manifest:
+
+	Deployment-ProvidesResourceProcessor: org.apache.ace.resourceprocessor.custom
+	DeploymentPackage-Customizer: true
+
+The first one should match the PID you used earlier.
+
+## Writing an ArtifactHelper and ArtifactRecognizer
+
+These services can usually just be implemented by the same class. The artifact recognizer
+is used to identify an artifact as being of this specific type. How it does that is up to
+the implementation. It might do something as simple as look at the file extension, but a
+lot of recognizers will also inspect (part of) the actual file. The artifact helper then
+contains all kinds of methods to help ACE deal with this specific type of artifact. The
+API documentation of these two interfaces explains the methods in detail. Again, let's get
+started with an implementation of both for a very simple artifact: a file with a specific
+extension:
+
+	:::java
+	public class CustomArtifactHelper implements ArtifactRecognizer, ArtifactHelper {
+	    public static final String KEY_FILENAME = "filename";
+	    public static final String MIMETYPE = "application/vnd.apache.ace.custom";
+	    public static final String PROCESSOR = "org.apache.ace.resourceprocessor.custom";
+
+		@Override
+		public boolean canUse(ArtifactObject object) {
+	        return (object == null) ? false : MIMETYPE.equals(object.getMimetype());
+		}
+
+		@Override
+		public ArtifactPreprocessor getPreprocessor() {
+			return null;
+		}
+
+		@Override
+		public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
+	        return "(" + ArtifactObject.KEY_ARTIFACT_NAME + "=" + obj.getAttribute(ArtifactObject.KEY_ARTIFACT_NAME) + ")";
+		}
+
+		@Override
+		public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
+	        return Integer.MAX_VALUE;
+		}
+
+		@Override
+		public Comparator<ArtifactObject> getComparator() {
+			return null;
+		}
+
+		@Override
+		public Map<String, String> checkAttributes(Map<String, String> attributes) {
+			return attributes;
+		}
+
+	    public String[] getDefiningKeys() {
+	        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+	    }
+
+	    public String[] getMandatoryAttributes() {
+	        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+	    }
+
+		@Override
+		public String recognize(ArtifactResource artifact) {
+			// here we can examine the stream to check the contents of the artifact
+			// for this demo, our check is just for the extension of the URL, which is
+			// a bit simplistic
+			if (artifact.getURL().toExternalForm().endsWith(".custom")) {
+				return MIMETYPE;
+			}
+			return null;
+		}
+
+		@Override
+		public Map<String, String> extractMetaData(ArtifactResource artifact) throws IllegalArgumentException {
+	        Map<String, String> result = new HashMap<String, String>();
+	        result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+	        result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+	        String name = new File(artifact.getURL().getFile()).getName();
+	        result.put(ArtifactObject.KEY_ARTIFACT_NAME, name);
+	        result.put(KEY_FILENAME, name);
+	        return result;
+		}
+
+		@Override
+		public boolean canHandle(String mimetype) {
+			return MIMETYPE.equals(mimetype);
+		}
+
+		@Override
+		public String getExtension(ArtifactResource artifact) {
+			return ".custom";
+		}
+	}
+
+Again, this is no production code, but it should get you started quickly. This code will
+recognize artifacts that have the ".custom" file extension. No effort is done here to look
+at the contents of the file just to keep the example simple. Publish this instance as both
+an ArtifactHelper and an ArtifactRecognizer and make sure to add a service property for
+the mime type: <tt>ArtifactObject.KEY_MIMETYPE</tt>,
+<tt>CustomArtifactHelper.MIMETYPE</tt>.
+
+Wrap it up in a bundle, and you're ready to use your custom artifact in ACE.
+
+## Installing everything in ACE
+
+To add the new artifact type to ACE, you first have to take the bundle that contained the
+ArtifactHelper and ArtifactRecognizer service and add that to ACE. The bundle should be
+part of the ACE client. If you use the "all in one" server, add it to that.
+
+The second step is to upload the resource processor to ACE. You can do that like you
+upload any other bundle. Just add it to the artifact column. After adding it, it will not
+show up in the column, but ACE will send it to a target if that target needs an artifact
+of this type.
+
+Should you ever discover that you made a mistake in your resource processor, you can
+simply upload a newer one. Just make sure you bump the version and ACE will ensure that
+everybody gets this latest version.
+

Propchange: ace/site/trunk/content/docs/adding-custom-artifact-types.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext (added)
+++ ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,112 @@
+Title: Audit Log Analysis
+
+An audit log is a full historic account of all events that are relevant for a certain object. In this case, we keep audit logs of each target that is managed by the provisioning server.
+
+Problem
+=======
+
+The first issue is where to maintain the audit log. On the one hand, one can maintain it on the target, but since the management agent talks to the server, it could keep the log too.
+
+Then there is the question of how to maintain the log. What events should be in it, and what is an event?
+
+Finally, the audit log should be readable and query-able, so people can review it.
+
+The following use cases can be defined:
+
+* Store event. Stores a new event to the audit log.
+* Get events. Queries (a subset of) events.
+* Merge events. Merges a set of (new) events with the existing events.
+
+Context
+=======
+
+We basically have two contexts:
+
+* Target, limited resources, so we should use something really "lean and mean".
+* Server, scalable solution, expect people to query for (large numbers of) events.
+
+Possible solutions
+==================
+
+As with all repositories, there should be one location where it is edited. In this case, the logical place to do that is on the target itself, since that is where the changes actually occur. In theory, the server also knows, but that theory breaks down if things fail on the target or other parties start manipulating the life cycle of bundles. The target itself can detect such activities.
+
+The next question is what needs to be logged. And how do we get access to these events?
+
+When storing events, each event can get a unique sequence number. Sequence numbers start with 1 and can be used to determine if you have the complete log.
+
+Assuming the target has limited storage, it might not be possible to keep the full log available locally. There are a couple of reasons to replicate this log to a central server:
+
+* space, as said the full log might not fit;
+* safety, when the target is somehow (partly) erased or compromised, we don't want to loose the log;
+* remote diagnostics, we want to get an overview of the audit log without actually connecting to the target directly.
+
+When replicating, the following scenarios can occur:
+
+1. The target has lost its whole log and really wants to (re)start from sequence number 1.
+2. The server has lost its whole log and receives a partial log.
+
+Starting with the second scenario, the server always simply collects incoming audit logs, so its memory can be restored from any number of targets or relay servers that report everything they know (again). Hopefully that will lead to a complete log again. If not, there's not much we can do.
+
+The first scenario is potentially more problematic, since the target has no way of knowing (for sure) at which sequence number it had arrived when everything was lost. In theory it might ask (relay) servers, but even those might not have been up to date, so that does not work. The only thing it can do here is: Start a new log at sequence number 1. That means we can have more than one log in these cases, and that again means we need to be able to identify which log (of each target) we're talking about. Therefore, when a new log is created, it should contain some unique identifier for that log (an identifier that should not depend on stored information, so for example we could use the current time in milliseconds, that should be fairly unique, or just some random number).
+
+How to find the central server? Use the discovery service!? This is not that big of a deal.
+
+Events should at least contain:
+
+* a datestamp, indicating when the event occurred;
+* a checksum and/or signature;
+* a short, human readable message explaining the event;
+* details:
+    * in the form of a (possibly multi-line) document
+    * in the form of a set of properties
+
+The server will add:
+
+* the target ID of the target that logged the event.
+
+Storage will be resolve differently on the server and target. On the target, using any kind of database would amount to having to include a considerable library, which makes these solutions impractical there. We might want to consider something like that for the server though. The options we have, are:
+
+* Relational database
+* Object database
+* XML
+* DIY
+
+How do events get logged?
+
+* explicitly, our management agent calls an AuditLog service method;
+* implicitly, by logging (certain) events in the system;
+
+Implicit algorithms can be build on top of the AuditLog service. What we need to monitor is the life cycle layer, which basically means adding a BundleListener and an FrameworkListener. Those capture all state changes of the framework. Technically we can either directly add those listeners, or use EventAdmin if that is available.
+
+What would be the best way for the target to send audit log updates to the server? I don't think we want the server to poll here, so the target should send updates (periodically). So how does it know what to send?
+
+* it could keep track of the last event it sent, sending newer ones after that;
+* it could ask for the list of events the server has;
+* it could send its highest log event number, and get back a list of missing events on the server, and then respond with the missing events.
+* it could just send everything.
+
+Discussion
+==========
+
+Having two layers for the audit log makes sense:
+
+* The first, lowest, layer is the AuditLog service that gives access to the log. On the one hand it allows people to log messages, on the other it should provide query access. Those should be split into two different interfaces.
+* The second layer can build on top of that. It can either be removed completely, which means the responsibility for logging becomes that of the application (probably the management agent). It can be implemented using listeners. Finally, it can be implemented using events.
+
+On the target we should implement a storage solution ourselves, to keep the actual code small. The code should be able to log events quickly (as that will happen far more often than retrieving them).
+
+Communication between the target and server should be initiated by the target. The target can basically send two commands to the server:
+
+1. My audit log contains sequence number 4-8, tell me your numbers. The server then responds (for example) with 1-6. This indicates we need to send 7-8.
+2. Here you have events 7-8, can you send me 1-3? The server stores its missing events, and sends you the events it has (always check if what you get is what you requested).
+
+This is setup in this way so the same commands can also be used by relay servers to replicate logs between server and target.
+
+Conclusion
+==========
+
+* The audit log is maintained on the target.
+* On the target, we implement the storage mechanism ourselves to ensure we have a solution with a very small footprint.
+* On the server, we use an XStream based solution to store the logs of all the targets.
+* Our communication protocol between target and (relay)server however, should probably not rely on XML.
+* Our communication protocol between server and (relay)server might rely on XML (determine at design time what makes most sense).

Propchange: ace/site/trunk/content/docs/analysis/auditlog-analysis.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext (added)
+++ ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,45 @@
+Title: Bundle Repository Analysis
+
+The bundle repository stores actual bundles and other artifacts. It is kept external to be able to leverage existing repositories and better protect the intellectual property of our users.
+
+Problem
+=======
+
+The bundle repository is an external repository that stores the actual bundle data and other artifacts. We keep this data external to our system to better protect the intellectual property of our users. Having only the meta-data in our system ensures the bundles and artifacts themselves can remain on a separate, protected network, even when the provisioning server itself is used in a hosted or cloud environment.
+
+Access to the bundle repository is URL based.
+
+The use cases are:
+
+* Get bundle, which returns the full bundle. This use case is mandatory, as this is the main goal for having a bundle repository.
+* Get bundle meta-data, which returns only the meta-data. This one is nice to have, as it would help us on slow connections when we only want metadata.
+* Get a list of (a subset of) all bundles in the repository. When provisioning, we already know what we want. When managing the shop we might have use for querying features and we should seriously look at OBR as an implementation. Also, as part of the Equinox provisioning effort, they are defining a similar model.
+* Install/update bundle. Makes the repository editable from the outside.
+* Delete bundle. Mentioned separately here because of the dangers of deleting bundles that might still be in use (the repository has no way of knowing what's in use).
+
+Context
+=======
+
+Whilst we will no doubt create our own bundle repository, it would be a big bonus if we could work with other bundle repositories. OBR comes to mind, but there might be others. Therefore it's important to create an implementation that maps easily onto (for example) an HTTP based repository.
+
+Our requirement to have URL based access to bundles ensures we can do that.
+
+Possible solutions
+==================
+
+As mentioned before, we basically have two solutions:
+
+1. use an existing solution;
+2. creating our own.
+
+Discussion
+==========
+
+Most use cases can be done either way. If you look at the OSGi Alliance's RFC-112 for OBR, the only thing it does not support is manipulating a repository. You could argue that's because it is beyond the scope, and because currently, OBR can be implemented using any webserver (it's basically just a set of bundles and a single XML descriptor).
+
+Conclusion
+==========
+
+I think we should create our own implementation of OBR, extending it with editing capabilities, and perhaps subsetting it (at least initially, we might not want a whole requirements, capability and dependency mechanism in there right now, as that's something we deal with inside our provisioning system).
+
+At the same time, adding these editing capabilities should not mean we cannot still generate static files that can be deployed on an external HTTP server. We do want to add an API for editing, but we don't want to make the whole repository depend on the capability to run code on that server, since we might want to do all maintenance on some client that simply uploads files to a server.
\ No newline at end of file

Propchange: ace/site/trunk/content/docs/analysis/bundlerepository-analysis.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/analysis/index.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/analysis/index.mdtext?rev=1641501&view=auto
==============================================================================
--- ace/site/trunk/content/docs/analysis/index.mdtext (added)
+++ ace/site/trunk/content/docs/analysis/index.mdtext Mon Nov 24 22:42:00 2014
@@ -0,0 +1,7 @@
+Title: Analysis
+
+* [Security Analysis](security-analysis.html)
+* [Template Mechanism](template-mechanism.html)
+* [Audit Log Analysis](auditlog-analysis.html)
+* [Bundle Repository Analysis](bundlerepository-analysis.html)
+

Propchange: ace/site/trunk/content/docs/analysis/index.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native

Added: ace/site/trunk/content/docs/analysis/security-analysis-flow.svg
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/docs/analysis/security-analysis-flow.svg?rev=1641501&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ace/site/trunk/content/docs/analysis/security-analysis-flow.svg
------------------------------------------------------------------------------
    svn:mime-type = image/svg+xml



Mime
View raw message