| <?xml version="1.0" encoding="UTF-8"?> |
| <chapter xml:id="guacamole-ext" xmlns="http://docbook.org/ns/docbook" |
| version="5.0" xml:lang="en" xmlns:xl="http://www.w3.org/1999/xlink" |
| xmlns:xi="http://www.w3.org/2001/XInclude"> |
| <title>guacamole-ext</title> |
| <indexterm> |
| <primary>API</primary> |
| <secondary>Java</secondary> |
| </indexterm> |
| <indexterm> |
| <primary>guacamole-ext</primary> |
| </indexterm> |
| <para>While not strictly part of the Java API provided by the Guacamole |
| project, guacamole-ext is a subset of the API used by the Guacamole web |
| application, exposed within a separate project such that extensions, |
| specifically authentication providers, can be written to tweak Guacamole |
| to fit well in existing deployments.</para> |
| <section> |
| <title>Common configuration</title> |
| <para>For the sake of ease of development and providing a common |
| location for configuration of both Guacamole and its extensions, |
| guacamole-ext provides utility classes for accessing the main |
| configuration file, <filename>guacamole.properties</filename>, and |
| for accessing the main root directory for housing configuration |
| files: <varname>GUACAMOLE_HOME</varname>.</para> |
| <section> |
| <title><classname>GuacamoleProperties</classname></title> |
| <para><classname>GuacamoleProperties</classname> is a utility class |
| for accessing the properties declared within |
| <filename>guacamole.properties</filename>. Each property is |
| typesafe and handles its own parsing - retrieving a property is |
| as simple as calling <methodname>getProperty()</methodname> or |
| <methodname>getRequiredProperty()</methodname>.</para> |
| <para>Because of this ease-of-access to guacamole.properties within |
| Guacamole and all extensions, the |
| <filename>guacamole.properties</filename> file is an ideal |
| place to store unstructured, extension-specific configuration |
| information.</para> |
| </section> |
| <section> |
| <title><classname>GuacamoleHome</classname></title> |
| <para>If you need more structured data than provided by simple |
| properties, placing XML or some other separate file within |
| <varname>GUACAMOLE_HOME</varname> (or a subdirectory |
| thereof) is a decent way to achieve this. The |
| <classname>GuacamoleHome</classname> class provides access |
| to the <varname>GUACAMOLE_HOME</varname> directory, abstracting |
| away the decision process that determines which directory is |
| considered <varname>GUACAMOLE_HOME</varname>.</para> |
| </section> |
| </section> |
| <section xml:id="auth-providers"> |
| <title>Authentication providers</title> |
| <para>The main use of guacamole-ext is to provide custom authentication |
| for Guacamole through the implementation of authentication |
| providers. An authentication provider is any class which implements |
| the <classname>AuthenticationProvider</classname> interface, |
| implementing the only function defined by that interface: |
| <methodname>getUserContext()</methodname>. This function is |
| required to return a "context" which provides access to only those |
| users and configurations accessible with the given credentials, and |
| enforces its own security model.</para> |
| <para>The credentials given are abstract and while Guacamole the web |
| application implements a username/password driven login screen, you |
| are not required to user usernames and passwords; the |
| <classname>Credentials</classname> class given to the |
| authentication provider provides access to all HTTP parameters in |
| general, as well as cookies and SSL information.</para> |
| <para>The Guacamole web application includes a basic authentication |
| provider implementation which parses an XML file to determine which |
| users exist, their corresponding passwords, and what configurations |
| those users have access to. This is the part of Guacamole that reads |
| the <filename>user-mapping.xml</filename> file. If you use a custom |
| authentication provider for your authentication, this file will |
| probably not be required.</para> |
| <para>The community has implemented authentication providers which |
| access databases, use LDAP, or even perform no authentication at |
| all, redirecting all users to a single configuration specified in |
| <filename>guacamole.properties</filename>.</para> |
| <para>A minimal authentication provider is implemented in the tutorials |
| later, and the upstream authentication provider implemented within |
| Guacamole, as well as the authentication providers implemented by |
| the community, are good examples for how authentication can be |
| extended without having to implement a whole new web |
| application.</para> |
| <section> |
| <title><classname>SimpleAuthenticationProvider</classname></title> |
| <para>The <classname>SimpleAuthenticationProvider</classname> class |
| provides a much simpler means of implementing authentication |
| when you do not require the ability to add and remove users and |
| connections. It is an abstract class and requires only one |
| function implementation: |
| <methodname>getAuthorizedConfigurations()</methodname>.</para> |
| <para>This function is required to return a |
| <classname>Map</classname> of unique IDs to configurations, |
| where these configurations are all configurations accessible |
| with the provided credentials. As before, the credentials given |
| are abstract. You are not required to use usernames and |
| passwords.</para> |
| <para>The configurations referred to by the function name are |
| instances of <classname>GuacamoleConfiguration</classname> (part |
| of guacamole-common), which is just a wrapper around a protocol |
| name and set of parameter name/value pairs. The name of the |
| protocol to use and a set of parameters is the minimum |
| information required for other parts of the Guacamole API to |
| complete the handshake required by the Guacamole |
| protocol.</para> |
| <para>When a class that extends |
| <classname>SimpleAuthenticationProvider</classname> is asked |
| for more advanced operations by the web application, |
| <classname>SimpleAuthenticationProvider</classname> simply |
| returns that there is no permission to do so. This effectively |
| disables all administrative functionality within the web |
| interface.</para> |
| <para>If you choose to go the simple route, most of the rest of this |
| chapter is irrelevant. Permissions, security model, and various |
| classes will be discussed that are all handled for you |
| automatically by |
| <classname>SimpleAuthenticationProvider</classname>.</para> |
| </section> |
| <section> |
| <title>The <classname>UserContext</classname></title> |
| <para>The <classname>UserContext</classname> is the root of all |
| operations. It is used to list, create, modify, or delete users |
| and connections, as well as to query available |
| permissions.</para> |
| <para>The Guacamole web application uses permissions queries against |
| the <classname>UserContext</classname> to determine what |
| operations to present, but <emphasis>beware that it is up to the |
| <classname>UserContext</classname> to actually enforce |
| these restrictions</emphasis>. The Guacamole web application |
| will not enforce restrictions on behalf of the |
| <classname>UserContext</classname>.</para> |
| <para>The <classname>UserContext</classname> is the sole means of |
| entry and the sole means of modification available to a |
| logged-in user. If the <classname>UserContext</classname> |
| refuses to perform an operation (by throwing an exception), the |
| user cannot perform the operation at all.</para> |
| </section> |
| <section> |
| <title><classname>Directory</classname> classes</title> |
| <para>Access to users and connections is given through |
| <classname>Directory</classname> classes. These |
| <classname>Directory</classname> classes are similar to Java |
| collections, but they also embody object update semantics. |
| Objects can be retrieved from a <classname>Directory</classname> |
| using its <methodname>get()</methodname> function and added or |
| removed with <methodname>add()</methodname> and |
| <methodname>remove()</methodname> respectively, but objects |
| already in the set can also be updated by passing an updated |
| object to its <methodname>update()</methodname> function.</para> |
| <para>An implementation of a <classname>Directory</classname> can |
| rely on these functions to define the semantics surrounding all |
| operations. The <methodname>add()</methodname> function is |
| called only when creating new objects, the |
| <methodname>update()</methodname> function is called only |
| when updating an object previously retrieved with |
| <methodname>get()</methodname>, and |
| <methodname>remove()</methodname> is called only when |
| removing an existing object by its identifier.</para> |
| <para>When implementing an |
| <classname>AuthenticationProvider</classname>, you must |
| ensure that the <classname>UserContext</classname> will only |
| return <classname>Directory</classname> classes that |
| automatically enforce the permissions associated with all |
| objects and the associated user.</para> |
| </section> |
| <section> |
| <title>Permissions</title> |
| <para>The permissions system within guacamole-ext is the means with |
| which an authentication module communicates with the web |
| application, informing it of what the user is allowed to do. The |
| presence or lack of permissions for certain operations dictates |
| how the web interface displays itself: whether the "Manage" |
| button is displayed, whether the user or connection management |
| sections (or both) are displayed, etc.</para> |
| <para><emphasis>Permissions are not the means through which access |
| is restricted</emphasis>. An implementation may use the |
| permission objects to define restrictions, but this is not |
| required. It is up to the implementation to enforce its own |
| restrictions by throwing exceptions when an operation is not |
| allowed.</para> |
| <section> |
| <title>System permissions</title> |
| <para>System permissions grant access to operations that |
| manipulate the system as a whole, rather than specific |
| objects. This includes the creation of new objects, as |
| object creation directly affects the system, and per-object |
| controls cannot exist before the object is actually |
| created.</para> |
| <variablelist> |
| <varlistentry> |
| <term><type>ADMINISTER</type></term> |
| <listitem> |
| <para>Allows manipulation of system-level |
| permissions. The semantics of the system-level |
| <type>ADMINISTER</type> permission are up to |
| the implementor of the authentication module, |
| but in general this permission implies all other |
| permissions. A user having this permission can |
| implicitly create and manage any object.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>CREATE_CONNECTION</type></term> |
| <listitem> |
| <para>Allows creation of new connections. If a user has this permission, |
| they will see the connection management interface and the "Manage" |
| button. Within this interface, they will be able to create new |
| connections.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>CREATE_CONNECTION_GROUP</type></term> |
| <listitem> |
| <para>Allows creation of new connections groups. If a user has this |
| permission, they will see the connection management interface and |
| the "Manage" button. Within this interface, they will be able to |
| create new connection groups.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>CREATE_USER</type></term> |
| <listitem> |
| <para>Allows creation of new users. If a user has |
| this permission, they will see the user |
| management interface and the "Manage" |
| button.</para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </section> |
| <section> |
| <title>User permissions</title> |
| <para>User permissions grant access to operations that affect a |
| specific user. Each user permission has a definite and |
| single associated user that is the object of the |
| operation.</para> |
| <variablelist> |
| <varlistentry> |
| <term><type>ADMINISTER</type></term> |
| <listitem> |
| <para>Allows changing visibility of the user. A user |
| with <type>ADMINISTER</type> permission on |
| another user can add and remove permissions |
| related to that user. Note that adding or |
| removing permissions on a user implicitly |
| requires <type>UPDATE</type> permission on that |
| user.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>DELETE</type></term> |
| <listitem> |
| <para>Allows deletion of the associated user. This |
| is distinct from the <type>ADMINISTER</type> |
| permission which deals only with modification to |
| the permissions associated with a user. A user |
| with this permission will see the "Delete" |
| button when editing the corresponding |
| user.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>READ</type></term> |
| <listitem> |
| <para>Allows the user to be read. A particular user |
| will not appear in the user management section |
| unless the user viewing it has <type>READ</type> |
| permission on that specific user.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>UPDATE</type></term> |
| <listitem> |
| <para>Allows the user to be updated. This means altering the user's |
| password or adding or removing permissions from that user. Note the |
| difference between <type>UPDATE</type> and <type>ADMINISTER</type>: |
| the <type>UPDATE</type> permission allows the permissions |
| <emphasis>of</emphasis> a user to be changed, while |
| <type>ADMINISTER</type> permission allows permissions |
| <emphasis>relating to</emphasis> a user to be changed. A user |
| with this permission will see the "Manage" button.</para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </section> |
| <section> |
| <title>Connection permissions</title> |
| <para>Connection permissions grant access to operations that |
| affect a specific connection. Each connection permission has |
| a definite and single associated connection that is the |
| object of the operation. The semantics of each operation |
| differ slightly from the similar user permissions, but the |
| general principles behind them are the same.</para> |
| <variablelist> |
| <varlistentry> |
| <term><type>ADMINISTER</type></term> |
| <listitem> |
| <para>Allows changing visibility of the connection. A user with |
| <type>ADMINISTER</type> permission on a connection can add and |
| remove permissions related to that connection, and will see the |
| "Manage" button.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>DELETE</type></term> |
| <listitem> |
| <para>Allows deletion of the associated connection. |
| This is distinct from the |
| <type>ADMINISTER</type> permission which |
| deals only with modification to the permissions |
| associated with a connection. A user with this |
| permission will see the "Delete" button when |
| editing the corresponding connection.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>READ</type></term> |
| <listitem> |
| <para>Allows the connection to be read. A particular connection will not |
| appear in the connection list nor in the connection management |
| section unless the user viewing it has <type>READ</type> permission |
| on that specific connection. <type>READ</type> permission is |
| required for a user to have permission to actually use a connection, |
| unless that connection is part of a balancing connection group for |
| which the user has <type>READ</type> permission.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>UPDATE</type></term> |
| <listitem> |
| <para>Allows the connection to be updated. This means editing the |
| connection's parameters or changing the connection's protocol. A |
| user with this permission will see the "Manage" button.</para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </section> |
| <section> |
| <title>Connection group permissions</title> |
| <para>Connection group permissions grant access to operations that affect a specific |
| connection group. Connection group permissions are extremely similar to |
| connection permissions, with some minor differences.</para> |
| <variablelist> |
| <varlistentry> |
| <term><type>ADMINISTER</type></term> |
| <listitem> |
| <para>Allows changing visibility of the connection group. A user with |
| <type>ADMINISTER</type> permission on a connection group can add |
| and remove permissions related to that connection group, and will |
| see the "Manage" button. Users with <type>ADMINISTER</type> |
| permission on a balancing connection group can see the contents of |
| that group. To users without <type>ADMINISTER</type> permission, a |
| balancing group looks like a connection.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>DELETE</type></term> |
| <listitem> |
| <para>Allows deletion of the associated connection group. This is |
| distinct from the <type>ADMINISTER</type> permission which deals |
| only with modification to the permissions associated with a |
| connection group. A user with this permission will see the "Delete" |
| button when editing the corresponding connection group.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>READ</type></term> |
| <listitem> |
| <para>Allows the connection group to be read. A particular connection |
| group will not appear in the connection list nor in the connection |
| management section unless the user viewing it has <type>READ</type> |
| permission on that specific connection group. <type>READ</type> |
| permission is required for a user to have permission to actually use |
| a connection.</para> |
| <para>A user with <type>READ</type> permission on a group will also be |
| able to see any contained connections or groups for which they also |
| have <type>READ</type> permission. <type>READ</type> permission is |
| not sufficient to see the contents of a balancing group.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><type>UPDATE</type></term> |
| <listitem> |
| <para>Allows the connection group to be updated. This means editing the |
| connection group's name, type, or contents. A user with this |
| permission will see the "Manage" button.</para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </section> |
| </section> |
| <section> |
| <title>Connections and history</title> |
| <para>Authentication modules must return <classname>Connection</classname> objects which |
| each implement a <methodname>connect()</methodname> function. When this function is |
| called, the connection must be made if permission is available.</para> |
| <para>This new separation of concerns makes more sense when you |
| consider that as connecting is an operation on a |
| <classname>Connection</classname>, access to performing that |
| operation must be restricted through the |
| <classname>AuthenticationProvider</classname>, and thus must |
| be enforced within the |
| <classname>AuthenticationProvider</classname>. This |
| separation also opens the door for things like load balancing of |
| connections and restricting concurrent access to |
| connections.</para> |
| <para>When a connection is made or terminated, it is also the duty |
| of the authentication module to maintain the connection history. |
| Each connection has a corresponding list of |
| <classname>ConnectionRecord</classname> objects, each of |
| which is associated with a past connection or a currently-active |
| connection. This information will ultimately be exposed to the |
| user as a history list when they view a connection in the |
| management interface or as a simple active user count on the |
| connection, advising the user of existing activity.</para> |
| </section> |
| </section> |
| <section xml:id="event-listeners"> |
| <title>Event listeners</title> |
| <para>Although not used internally by the web application, the web |
| application provides an event system which can be hooked into with |
| listener objects, such that a class within the classpath of |
| Guacamole can receive events when something noteworthy happens in |
| the application layer, and take some sort of action.</para> |
| <para>Currently, the web application provides events for when the tunnel |
| is opened or closed, and when an authentication attempt succeeds or |
| fails. In most cases, the class listening for these events can also |
| cancel whatever action just occurred.</para> |
| <section xml:id="tunnel-connect-listener"> |
| <title><classname>TunnelConnectListener</classname></title> |
| <para>When a tunnel is connected to by the JavaScript client, |
| Guacamole informs all installed instances of |
| <classname>TunnelConnectListener</classname> by calling |
| their <methodname>tunnelConnected()</methodname> function with a |
| new <classname>TunnelConnectEvent</classname>, which contains |
| the tunnel that was just connected, as well as any associated |
| credentials. If <methodname>tunnelConnected()</methodname> |
| returns <constant>false</constant>, the connect attempt will be |
| overridden and denied.</para> |
| </section> |
| <section xml:id="tunnel-close-listener"> |
| <title><classname>TunnelCloseListener</classname></title> |
| <para>When a tunnel is connected to by the JavaScript client, |
| Guacamole informs all installed instances of |
| <classname>TunnelCloseListener</classname> by calling their |
| <methodname>tunnelClosed()</methodname> function with a new |
| <classname>TunnelCloseEvent</classname>, which contains the |
| tunnel that is about to be closed, as well as any associated |
| credentials. If <methodname>tunnelClosed()</methodname> returns |
| <constant>false</constant>, the attempt close the tunnel |
| will be overridden and denied, and the tunnel will remain |
| open.</para> |
| </section> |
| <section xml:id="authentication-success-listener"> |
| <title><classname>AuthenticationSuccessListener</classname></title> |
| <para>If a user successfully authenticates with the web application, |
| Guacamole informs all installed instances of |
| <classname>AuthenticationSuccessListener</classname> by |
| calling their <methodname>authenticationSucceeded()</methodname> |
| function with a new |
| <classname>AuthenticationSuccessEvent</classname> which |
| contains the credentials used. The implementation of this |
| function has the opportunity to cancel the authentication |
| attempt, effectively denying access despite being otherwise |
| valid, by returning <constant>false</constant>.</para> |
| </section> |
| <section xml:id="authentication-failure-listener"> |
| <title><classname>AuthenticationFailureListener</classname></title> |
| <para>If a user fails to authenticate with the web application, |
| Guacamole informs all installed instances of |
| <classname>AuthenticationFailureListener</classname> by |
| calling their <methodname>authenticationFailed()</methodname> |
| function with a new |
| <classname>AuthenticationFailureEvent</classname> which |
| contains the credentials used. Unlike other listeners, this |
| event cannot be canceled by returning |
| <constant>false</constant>. All failed authentication attempts |
| "succeed" in failing, and an implementation of |
| <classname>AuthenticationFailureListener</classname> cannot |
| force an authentication attempt to succeed by denying that |
| failure.</para> |
| </section> |
| </section> |
| </chapter> |