blob: 0eef9aee1e1a82e39819803d28140909b87a7f70 [file] [log] [blame]
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>LDAP authentication &mdash; Apache Guacamole Manual v1.5.0</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/tabs.css" type="text/css" />
<link rel="stylesheet" href="_static/gug.css" type="text/css" />
<!--[if lt IE 9]>
<script src="_static/js/html5shiv.min.js"></script>
<![endif]-->
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<script src="_static/tabs.js"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Retrieving secrets from a vault" href="vault.html" />
<link rel="prev" title="Database authentication" href="jdbc-auth.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="index.html" class="icon icon-home"> Apache Guacamole
</a>
<div class="version">
1.5.0
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Overview</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="introduction.html">Introduction</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">User's Guide</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="guacamole-architecture.html">Implementation and architecture</a></li>
<li class="toctree-l1"><a class="reference internal" href="installing-guacamole.html">Installing Guacamole natively</a></li>
<li class="toctree-l1"><a class="reference internal" href="guacamole-docker.html">Installing Guacamole with Docker</a></li>
<li class="toctree-l1"><a class="reference internal" href="reverse-proxy.html">Proxying Guacamole</a></li>
<li class="toctree-l1"><a class="reference internal" href="configuring-guacamole.html">Configuring Guacamole</a></li>
<li class="toctree-l1"><a class="reference internal" href="jdbc-auth.html">Database authentication</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">LDAP authentication</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#how-guacamole-uses-ldap">How Guacamole uses LDAP</a></li>
<li class="toctree-l2"><a class="reference internal" href="#downloading-the-ldap-extension">Downloading the LDAP extension</a></li>
<li class="toctree-l2"><a class="reference internal" href="#preparing-your-ldap-directory-optional">Preparing your LDAP directory (optional)</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#applying-the-schema-changes-to-openldap">Applying the schema changes to OpenLDAP</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#associating-ldap-with-a-database">Associating LDAP with a database</a></li>
<li class="toctree-l2"><a class="reference internal" href="#installing-ldap-authentication">Installing LDAP authentication</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#configuring-guacamole-for-ldap">Configuring Guacamole for LDAP</a></li>
<li class="toctree-l3"><a class="reference internal" href="#using-multiple-ldap-servers">Using multiple LDAP servers</a></li>
<li class="toctree-l3"><a class="reference internal" href="#completing-the-installation">Completing the installation</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#the-ldap-schema">The LDAP schema</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#users">Users</a></li>
<li class="toctree-l3"><a class="reference internal" href="#connections-and-parameters">Connections and parameters</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="vault.html">Retrieving secrets from a vault</a></li>
<li class="toctree-l1"><a class="reference internal" href="duo-auth.html">Duo two-factor authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="totp-auth.html">TOTP two-factor authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="header-auth.html">HTTP header authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="json-auth.html">Encrypted JSON authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="cas-auth.html">CAS Authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="openid-auth.html">OpenID Connect Authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="saml-auth.html">SAML Authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="radius-auth.html">RADIUS Authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="adhoc-connections.html">Ad-hoc Connections</a></li>
<li class="toctree-l1"><a class="reference internal" href="using-guacamole.html">Using Guacamole</a></li>
<li class="toctree-l1"><a class="reference internal" href="recording-playback.html">Viewing session recordings in-browser</a></li>
<li class="toctree-l1"><a class="reference internal" href="administration.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="troubleshooting.html">Troubleshooting</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Developer's Guide</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="guacamole-protocol.html">The Guacamole protocol</a></li>
<li class="toctree-l1"><a class="reference internal" href="libguac.html">libguac</a></li>
<li class="toctree-l1"><a class="reference internal" href="guacamole-common.html">guacamole-common</a></li>
<li class="toctree-l1"><a class="reference internal" href="guacamole-common-js.html">guacamole-common-js</a></li>
<li class="toctree-l1"><a class="reference internal" href="guacamole-ext.html">guacamole-ext</a></li>
<li class="toctree-l1"><a class="reference internal" href="custom-protocols.html">Adding new protocols</a></li>
<li class="toctree-l1"><a class="reference internal" href="custom-auth.html">Custom authentication</a></li>
<li class="toctree-l1"><a class="reference internal" href="event-listeners.html">Event listeners</a></li>
<li class="toctree-l1"><a class="reference internal" href="writing-you-own-guacamole-app.html">Writing your own Guacamole application</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Appendices</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="protocol-reference.html">Guacamole protocol reference</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">Apache Guacamole</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html" class="icon icon-home"></a> &raquo;</li>
<li>LDAP authentication</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/ldap-auth.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="ldap-authentication">
<h1>LDAP authentication<a class="headerlink" href="#ldap-authentication" title="Permalink to this heading"></a></h1>
<p>Guacamole supports LDAP authentication via an extension available from the main
project website. This extension allows users and connections to be stored
directly within an LDAP directory. If you have a centralized authentication
system that uses LDAP, Guacamole’s LDAP support can be a good way to allow your
users to use their existing usernames and passwords to log into Guacamole.</p>
<p>To use the LDAP authentication extension, you will need:</p>
<ol class="arabic simple">
<li><p>An LDAP directory as storage for all authentication data, such as OpenLDAP.</p></li>
<li><p>The ability to modify the schema of your LDAP directory.</p></li>
</ol>
<p>The instructions here assume you already have an LDAP directory installed and
working, and do not cover the initial setup of such a directory.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>This chapter involves modifying the contents of <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME</span></code> - the
Guacamole configuration directory. If you are unsure where <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME</span></code> is
located on your system, please consult <a class="reference internal" href="configuring-guacamole.html"><span class="doc std std-doc">Configuring Guacamole</span></a> before
proceeding.</p>
</div>
<section id="how-guacamole-uses-ldap">
<span id="ldap-architecture"></span><h2>How Guacamole uses LDAP<a class="headerlink" href="#how-guacamole-uses-ldap" title="Permalink to this heading"></a></h2>
<p>If the LDAP extension is installed, Guacamole will authenticate users against
your LDAP server by attempting a bind as that user. The given username and
password will be submitted to the LDAP server during the bind attempt.</p>
<p>If the bind attempt is successful, the set of available Guacamole connections
is queried from the LDAP directory by executing an LDAP query as the bound
user. Each Guacamole connection is represented within the directory as a
special type of group: <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code>. Attributes associated with the group
define the protocol and parameters of the connection, and users are allowed
access to the connection only if they are associated with that group.</p>
<p>This architecture has a number of benefits:</p>
<ol class="arabic simple">
<li><p>Your users can use their existing usernames and passwords to log into
Guacamole.</p></li>
<li><p>You can manage Guacamole connections using the same tool that you already
use to manage your LDAP directory, such as <a class="reference external" href="https://directory.apache.org/studio/">Apache Directory
Studio</a>.</p></li>
<li><p>Existing security restrictions can limit visibility/accessibility of
Guacamole connections.</p></li>
<li><p>Access to connections can easily be granted and revoked, as each connection
is represented by a group.</p></li>
</ol>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>Though Guacamole connections can be stored within the LDAP directory, this is
not required. Connection data can alternatively be stored within a database
like MySQL or PostgreSQL as long as the LDAP username matches the username of
the database user. Configuring Guacamole to use a database for authentication
or connection storage is covered in <a class="reference internal" href="jdbc-auth.html"><span class="doc std std-doc">Database authentication</span></a> and later in this chapter in
<a class="reference internal" href="#ldap-and-database"><span class="std std-ref">Associating LDAP with a database</span></a>.</p>
</div>
</section>
<section id="downloading-the-ldap-extension">
<span id="ldap-downloading"></span><h2>Downloading the LDAP extension<a class="headerlink" href="#downloading-the-ldap-extension" title="Permalink to this heading"></a></h2>
<p>The LDAP authentication extension is available separately from the main
<code class="docutils literal notranslate"><span class="pre">guacamole.war</span></code>. The link for this and all other officially-supported and
compatible extensions for a particular version of Guacamole are provided on the
release notes for that version. You can find the release notes for current
versions of Guacamole here: <a class="reference external" href="http://guacamole.apache.org/releases/">http://guacamole.apache.org/releases/</a>.</p>
<p>The LDAP authentication extension is packaged as a <code class="docutils literal notranslate"><span class="pre">.tar.gz</span></code> file containing:</p>
<dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">guacamole-auth-ldap-1.5.0.jar</span></code></dt><dd><p>The Guacamole LDAP support extension itself, which must be placed in
<code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME/extensions</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">schema/</span></code></dt><dd><p>LDAP schema files. An <code class="docutils literal notranslate"><span class="pre">.ldif</span></code> file compatible with OpenLDAP is provided, as
well as a <code class="docutils literal notranslate"><span class="pre">.schema</span></code> file compliant with RFC-2252. The <code class="docutils literal notranslate"><span class="pre">.schema</span></code> file can be
transformed into the <code class="docutils literal notranslate"><span class="pre">.ldif</span></code> file automatically.</p>
</dd>
</dl>
</section>
<section id="preparing-your-ldap-directory-optional">
<span id="ldap-schema-changes"></span><h2>Preparing your LDAP directory (optional)<a class="headerlink" href="#preparing-your-ldap-directory-optional" title="Permalink to this heading"></a></h2>
<p>Although your LDAP directory already provides a means of storing and
authenticating users, Guacamole also needs storage of connection configuration
data, such as hostnames and ports, and a means of associating users with
connections that they should have access to. You can do this either through
modifying the LDAP directory schema, or through using a database like MySQL or
PostgreSQL. If you do not wish to use the LDAP directory for connection
storage, skip ahead to <a class="reference internal" href="#ldap-and-database"><span class="std std-ref">Associating LDAP with a database</span></a>.</p>
<p>If you wish to store connection data directly within the LDAP directory, the
required modifications to the LDAP schema are made through applying one of the
provided schema files. These schema files define an additional object class,
<code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code>, which contains all configuration information for a
particular connection, and can be associated with arbitrarily-many users and
groups. Each connection defined by a <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> will be accessible only
by users who are members of that group (specified with the member attribute),
or who are members of associated groups (specified with the <code class="docutils literal notranslate"><span class="pre">seeAlso</span></code>
attribute).</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>The instructions given for applying the Guacamole LDAP schema changes are
specific to OpenLDAP, but other LDAP implementations, including Active
Directory, will have their own methods for updating the schema.</p>
<p>If you are not using OpenLDAP, a standards-compliant schema file is provided
that can be used to update the schema of any LDAP directory supporting
RFC-2252. Please consult the documentation of your LDAP directory to determine
how such schema changes can be applied.</p>
</div>
<p>The schema files are located within the <code class="docutils literal notranslate"><span class="pre">schema/</span></code> directory of the archive
containing the LDAP extension. You will only need one of these files:</p>
<dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">guacConfigGroup.schema</span></code></dt><dd><p>A standards-compliant file describing the schema. This file can be used with
any LDAP directory compliant with RFC-2252.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">guacConfigGroup.ldif</span></code></dt><dd><p>An LDIF file compatible with OpenLDAP. This file was automatically built from
the provided <code class="docutils literal notranslate"><span class="pre">.schema</span></code> file for convenience.</p>
</dd>
</dl>
<p>This chapter will cover applying <code class="docutils literal notranslate"><span class="pre">guacConfigGroup.ldif</span></code> to an OpenLDAP server.
If you are not using OpenLDAP, your LDAP server should provide documentation
for modifying its schema. If this is the case, please consult the documentation
of your LDAP server before proceeding.</p>
<section id="applying-the-schema-changes-to-openldap">
<h3>Applying the schema changes to OpenLDAP<a class="headerlink" href="#applying-the-schema-changes-to-openldap" title="Permalink to this heading"></a></h3>
<p>Schema changes to OpenLDAP are applied using the <strong class="command">ldapadd</strong> utility
with the provided <code class="docutils literal notranslate"><span class="pre">guacConfigGroup.ldif</span></code> file:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span>ldapadd -Q -Y EXTERNAL -H ldapi:/// -f schema/guacConfigGroup.ldif
<span class="go">adding new entry &quot;cn=guacConfigGroup,cn=schema,cn=config&quot;</span>
<span class="gp">#</span>
</pre></div>
</div>
<p>If the <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> object was added successfully, you should see output
as above. You can confirm the presence of the new object class using
<strong class="command">ldapsearch</strong>:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span>ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b <span class="nv">cn</span><span class="o">=</span>schema,cn<span class="o">=</span>config dn
<span class="go">dn: cn=schema,cn=config</span>
<span class="go">dn: cn={0}core,cn=schema,cn=config</span>
<span class="go">dn: cn={1}cosine,cn=schema,cn=config</span>
<span class="go">dn: cn={2}nis,cn=schema,cn=config</span>
<span class="go">dn: cn={3}inetorgperson,cn=schema,cn=config</span>
<span class="go">dn: cn={4}guacConfigGroup,cn=schema,cn=config</span>
<span class="gp">#</span>
</pre></div>
</div>
</section>
</section>
<section id="associating-ldap-with-a-database">
<span id="ldap-and-database"></span><h2>Associating LDAP with a database<a class="headerlink" href="#associating-ldap-with-a-database" title="Permalink to this heading"></a></h2>
<p>If you install both the LDAP authentication as well as support for a database
(following the instructions in <a class="reference internal" href="jdbc-auth.html"><span class="doc std std-doc">Database authentication</span></a>), Guacamole will automatically
attempt to authenticate against both systems whenever a user attempts to log
in. In addition to any visible objects within the LDAP directory, that user
will have access to any data associated with their account in the database, as
well as any data associated with user groups that they belong to. LDAP user
accounts and groups will be considered equivalent to database users and groups
if their unique names are identical, as determined by the attributes given for
<a class="reference internal" href="#guac-ldap-config"><span class="std std-ref">the <code class="docutils literal notranslate"><span class="pre">ldap-username-attribute</span></code> and <code class="docutils literal notranslate"><span class="pre">ldap-group-name-attribute</span></code>
properties</span></a>.</p>
<p>Data can be manually associated with LDAP user accounts or groups by creating
corresponding users or groups within the database which each have the same
names. As long as the names are identical, a successful login attempt against
LDAP will be trusted by the database authentication, and that user’s associated
data will be visible.</p>
<p>If an administrator account (such as the default <code class="docutils literal notranslate"><span class="pre">guacadmin</span></code> user provided with
the database authentication) has a corresponding user in the LDAP directory
with permission to read other LDAP users and groups, the Guacamole
administrative interface will include them in the lists presented to the
administrator, and will allow connections from the database to be associated
with those users or groups directly.</p>
</section>
<section id="installing-ldap-authentication">
<span id="installing-ldap-auth"></span><h2>Installing LDAP authentication<a class="headerlink" href="#installing-ldap-authentication" title="Permalink to this heading"></a></h2>
<p>Guacamole extensions are self-contained <code class="docutils literal notranslate"><span class="pre">.jar</span></code> files which are located within
the <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME/extensions</span></code> directory. To install the LDAP authentication
extension, you must:</p>
<ol class="arabic simple">
<li><p>Create the <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME/extensions</span></code> directory, if it does not already
exist.</p></li>
<li><p>Copy <code class="docutils literal notranslate"><span class="pre">guacamole-auth-ldap-1.5.0.jar</span></code> within <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME/extensions</span></code>.</p></li>
<li><p>Configure Guacamole to use LDAP authentication, as described below.</p></li>
</ol>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>You will need to restart Guacamole by restarting your servlet container in
order to complete the installation. Doing this will disconnect all active
users, so be sure that it is safe to do so prior to attempting installation. If
you do not configure the LDAP authentication properly, Guacamole will not start
up again until the configuration is fixed.</p>
</div>
<section id="configuring-guacamole-for-ldap">
<span id="guac-ldap-config"></span><h3>Configuring Guacamole for LDAP<a class="headerlink" href="#configuring-guacamole-for-ldap" title="Permalink to this heading"></a></h3>
<p>Additional properties may be added to <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code> to describe how
your LDAP directory is organized and how Guacamole should connect (and bind) to
your LDAP server. Among these properties, only the ldap-user-base-dn property
is required:</p>
<dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">ldap-hostname</span></code></dt><dd><p>The hostname of your LDAP server. If omitted, “localhost” will be used by
default. You will need to use a different value if your LDAP server is
located elsewhere.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-port</span></code></dt><dd><p>The port your LDAP server listens on. If omitted, the standard LDAP or LDAPS
port will be used, depending on the encryption method specified with
<code class="docutils literal notranslate"><span class="pre">ldap-encryption-method</span></code> (if any). Unencrypted LDAP uses the standard port of
389, while LDAPS uses port 636. Unless you manually configured your LDAP
server to do otherwise, your LDAP server probably listens on port 389.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-encryption-method</span></code></dt><dd><p>The encryption mechanism that Guacamole should use when communicating with
your LDAP server. Legal values are “none” for unencrypted LDAP, “ssl” for
LDAP over SSL/TLS (commonly known as LDAPS), or “starttls” for STARTTLS. If
omitted, encryption will not be used.</p>
<p>If you do use encryption when connecting to your LDAP server, you will need
to ensure that its certificate chain can be verified using the certificates
in Java’s trust store, often referred to as <code class="docutils literal notranslate"><span class="pre">cacerts</span></code>. If this is not the
case, you will need to use Java’s <code class="docutils literal notranslate"><span class="pre">keytool</span></code> utility to either add the
necessary certificates or to create a new trust store containing those
certificates.</p>
<p>If you will be using your own trust store and not the default <code class="docutils literal notranslate"><span class="pre">cacerts</span></code>, you
will need to specify the full path to that trust store using the system
property <code class="docutils literal notranslate"><span class="pre">javax.net.ssl.trustStore</span></code>. Note that this is a system property and
<em>not</em> a Guacamole property; it must be specified when starting the JVM using
the <code class="docutils literal notranslate"><span class="pre">-D</span></code> option. Your servlet container will provide some means of specifying
startup options for the JVM.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-max-search-results</span></code></dt><dd><p>The maximum number of search results that can be returned by a single LDAP
query. LDAP queries which exceed this maximum will fail. <em>This property is
optional.</em> If omitted, each LDAP query will be limited to a maximum of 1000
results.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-search-bind-dn</span></code></dt><dd><p>The DN (Distinguished Name) of the user to bind as when authenticating users
that are attempting to log in. If specified, Guacamole will query the LDAP
directory to determine the DN of each user that logs in. If omitted, each
user’s DN will be derived directly using the base DN specified with
<code class="docutils literal notranslate"><span class="pre">ldap-user-base-dn</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-search-bind-password</span></code></dt><dd><p>The password to provide to the LDAP server when binding as
<code class="docutils literal notranslate"><span class="pre">ldap-search-bind-dn</span></code> to authenticate other users. This property is only used
if ldap-search-bind-dn is specified. If omitted, but <code class="docutils literal notranslate"><span class="pre">ldap-search-bind-dn</span></code> is
specified, Guacamole will attempt to bind with the LDAP server without a
password.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-user-base-dn</span></code></dt><dd><p>The base of the DN for all Guacamole users. <em>This property is absolutely
required in all cases.</em> All Guacamole users must be descendents of this base
DN.</p>
<p>If a search DN is provided (via <code class="docutils literal notranslate"><span class="pre">ldap-search-bind-dn</span></code>), then Guacamole users
need only be somewhere within the subtree of the specified user base DN.</p>
<p>If a search DN <em>is not</em> provided, then all Guacamole users must be <em>direct
descendents</em> of this base DN, as the base DN will be appended to the username
to derive the user’s DN. For example, if <code class="docutils literal notranslate"><span class="pre">ldap-user-base-dn</span></code> is
<code class="docutils literal notranslate"><span class="pre">ou=people,dc=example,dc=net</span></code>”, and <code class="docutils literal notranslate"><span class="pre">ldap-username-attribute</span></code> is “uid”, then
a person attempting to login as “<code class="docutils literal notranslate"><span class="pre">user</span></code>” would be mapped to the following
full DN: “<code class="docutils literal notranslate"><span class="pre">uid=user,ou=people,dc=example,dc=net</span></code>”.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-username-attribute</span></code></dt><dd><p>The attribute or attributes which contain the username within all Guacamole
user objects in the LDAP directory. Usually, and by default, this will simply
be “uid”. If your LDAP directory contains users whose usernames are dictated
by different attributes, multiple attributes can be specified here, separated
by commas, but beware: <em>doing so requires that a search DN be provided with
<code class="docutils literal notranslate"><span class="pre">ldap-search-bind-dn</span></code></em>.</p>
<p>If a search DN <em>is not</em> provided, then the single username attribute
specified here will be used together with the user base DN to directly derive
the full DN of each user. For example, if <code class="docutils literal notranslate"><span class="pre">ldap-user-base-dn</span></code> is
<code class="docutils literal notranslate"><span class="pre">ou=people,dc=example,dc=net</span></code>”, and <code class="docutils literal notranslate"><span class="pre">ldap-username-attribute</span></code> is “uid”, then
a person attempting to login as “<code class="docutils literal notranslate"><span class="pre">user</span></code>” would be mapped to the following
full DN: “<code class="docutils literal notranslate"><span class="pre">uid=user,ou=people,dc=example,dc=net</span></code>”.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-member-attribute</span></code></dt><dd><p>The attribute which contains the members within all group objects in the LDAP
directory. Usually, and by default, this will simply be “member”. If your
LDAP directory contains groups whose members are dictated by a different
attribute, it can be specified here.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-member-attribute-type</span></code></dt><dd><p>Specify whether the attribute defined in <code class="docutils literal notranslate"><span class="pre">ldap-member-attribute</span></code> (Usually
“member”) identifies a group member by DN or by usercode. Possible values:
“dn” (the default, if not specified) or “uid”.</p>
<p>Example: an LDAP server may present groups using the <code class="docutils literal notranslate"><span class="pre">groupOfNames</span></code>
scheme:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dn: cn=group1,ou=Groups,dc=example,dc=net
objectClass: groupOfNames
cn: group1
gidNumber: 12345
member: user1,ou=People,dc=example,dc=net
member: user2,ou=People,dc=example,dc=net
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">ldap-member-attribute</span></code> is <code class="docutils literal notranslate"><span class="pre">member</span></code> and <code class="docutils literal notranslate"><span class="pre">ldap-member-attribute-type</span></code> is <code class="docutils literal notranslate"><span class="pre">dn</span></code>.</p>
<p>Example: an LDAP server may present groups using the <code class="docutils literal notranslate"><span class="pre">posixGroup</span></code>
scheme:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dn: cn=group1,ou=Groups,dc=example,dc=net
objectClass: posixGroup
cn: group1
gidNumber: 12345
memberUid: user1
memberUid: user2
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">ldap-member-attribute</span></code> is <code class="docutils literal notranslate"><span class="pre">memberUid</span></code> and <code class="docutils literal notranslate"><span class="pre">ldap-member-attribute-type</span></code> is
<code class="docutils literal notranslate"><span class="pre">uid</span></code></p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-user-attributes</span></code></dt><dd><p>The attribute or attributes to retrieve from the LDAP directory for the
currently logged-in user, separated by commas. If specified, the attributes
listed here are retrieved from each authenticated user and dynamically
applied to the parameters of that user’s connections as <a class="reference internal" href="configuring-guacamole.html#parameter-tokens"><span class="std std-ref">parameter
tokens</span></a> with the prefix “<code class="docutils literal notranslate"><span class="pre">LDAP_</span></code>”.</p>
<p>When a user authenticates with LDAP and accesses a particular Guacamole
connection, the values of these tokens will be the values of their
corresponding attributes at the time of authentication. If the attribute has
no value for the current user, then the corresponding token is not applied.
If the attribute has multiple values, then the first value of the attribute
is used.</p>
<p>When converting an LDAP attribute name into a parameter token name, the name
of the attribute is transformed into uppercase with each word separated by
underscores, a naming convention referred to as “uppercase with underscores”
or “<a class="reference external" href="https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers">screaming snake case</a>”.</p>
<p>For example:</p>
<table class="colwidths-auto docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>LDAP Attribute</p></th>
<th class="head"><p>Parameter Token</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">lowercase-with-dashes</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">${LDAP_LOWERCASE_WITH_DASHES}</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">CamelCase</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">${LDAP_CAMEL_CASE}</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">headlessCamelCase</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">${LDAP_HEADLESS_CAMEL_CASE}</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">lettersAndNumbers1234</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">${LDAP_LETTERS_AND_NUMBERS_1234}</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">aRANDOM_mixOf-3NAMINGConventions</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">${LDAP_A_RANDOM_MIX_OF_3_NAMING_CONVENTIONS}</span></code></p></td>
</tr>
</tbody>
</table>
<p>Usage of parameter tokens is discussed in more detail in
<a class="reference internal" href="configuring-guacamole.html"><span class="doc std std-doc">Configuring Guacamole</span></a> in <a class="reference internal" href="configuring-guacamole.html#parameter-tokens"><span class="std std-ref">Parameter tokens</span></a>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-user-search-filter</span></code></dt><dd><p>The search filter used to query the LDAP tree for users that can log into and
be granted privileges in Guacamole. <em>If this property is omitted the default of
<code class="docutils literal notranslate"><span class="pre">(objectClass=*)</span></code> will be used.</em></p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-config-base-dn</span></code></dt><dd><p>The base of the DN for all Guacamole configurations. <em>This property is
optional.</em> If omitted, the configurations of Guacamole connections will
simply not be queried from the LDAP directory. If specified, this base DN
will be used when querying the configurations accessible by a user once they
have successfully logged in.</p>
<p>Each configuration is analogous to a connection. Within Guacamole’s LDAP
support, each configuration functions as a group, having user members (via
the <code class="docutils literal notranslate"><span class="pre">member</span></code> attribute) and optionally group members (via the <code class="docutils literal notranslate"><span class="pre">seeAlso</span></code>
attribute), where each member of a particular configuration group will have
access to the connection defined by that configuration.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-group-base-dn</span></code></dt><dd><p>The base of the DN for all user groups that may be used by other extensions
to define permissions or that may referenced within Guacamole configurations
using the standard seeAlso attribute. All groups which will be used to
control access to Guacamole configurations must be descendents of this base
DN. <em>If this property is omitted, the <code class="docutils literal notranslate"><span class="pre">seeAlso</span></code> attribute will have no effect
on Guacamole configurations.</em></p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-group-name-attribute</span></code></dt><dd><p>The attribute or attributes which define the unique name of user groups in
the LDAP directory. Usually, and by default, this will simply be “cn”. If
your LDAP directory contains groups whose names are dictated by different
attributes, multiple attributes can be specified here, separated by commas.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-group-search-filter</span></code></dt><dd><p>The search filter used to query the LDAP tree for groups that may be used by
other extensions to define permissions. <em>If this property is omitted the
default of <code class="docutils literal notranslate"><span class="pre">(objectClass=*)</span></code> will be used.</em></p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-dereference-aliases</span></code></dt><dd><p>Controls whether or not the LDAP connection follows (dereferences) aliases as
it searches the tree. Possible values for this property are “never” (the
default) so that aliases will never be followed, “searching” to dereference
during search operations after the base object is located, “finding” to
dereference in order to locate the search base, but not during the actual
search, and “always” to always dereference aliases.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-follow-referrals</span></code></dt><dd><p>This option controls whether or not the LDAP module follow referrals when
processing search results from a LDAP search. Referrals can be pointers to
other parts of an LDAP tree, or to a different server/connection altogether.
This is a boolean parameter, with valid options of “true” or “false.” The
default is false. When disabled, LDAP referrals will be ignored when
encountered by the Guacamole LDAP client and the client will move on to the
next result. When enabled, the LDAP client will follow the referral and
process results within the referral, subject to the maximum hops parameter
below.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-max-referral-hops</span></code></dt><dd><p>This option controls the maximum number of referrals that will be processed
before the LDAP client refuses to follow any more referrals. The default is
5. If the <code class="docutils literal notranslate"><span class="pre">ldap-follow-referrals</span></code> property is set to false (the default),
this option has no effect. If the <code class="docutils literal notranslate"><span class="pre">ldap-follow-referrals</span></code> option is set
to true, this will limit the depth of referrals followed to the number
specified.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">ldap-operation-timeout</span></code></dt><dd><p>This option sets the timeout, in seconds, of any single LDAP operation. The
default is 30 seconds. When this timeout is reached LDAP operations will be
aborted.</p>
</dd>
</dl>
<p>Again, even if the defaults are sufficient for the other properties, <em>you must
still specify the <code class="docutils literal notranslate"><span class="pre">ldap-user-base-dn</span></code> property</em>. An absolutely minimal
configuration for LDAP authentication will look like the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># LDAP properties
ldap-user-base-dn: ou=people,dc=example,dc=net
</pre></div>
</div>
</section>
<section id="using-multiple-ldap-servers">
<span id="guac-multi-ldap-config"></span><h3>Using multiple LDAP servers<a class="headerlink" href="#using-multiple-ldap-servers" title="Permalink to this heading"></a></h3>
<p>If you have several LDAP servers that Guacamole should authenticate against, it
is possible to provide the configuration details for multiple servers by
creating or editing a YAML file within <code class="docutils literal notranslate"><span class="pre">GUACAMOLE_HOME</span></code> called
<code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code>. This file consists of a single list of servers (a YAML
array of objects) and any number of corresponding configuration options (the
key/value pairs within each YAML object). The available options correspond
<em>exactly</em> to the properties described above except that they lack an <code class="docutils literal notranslate"><span class="pre">ldap-</span></code>
prefix.</p>
<p>For example, the following <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ldap-hostname: dc1.example.net
ldap-user-base-dn: ou=Users,dc=example,dc=net
ldap-username-attribute: sAMAccountName
ldap-search-bind-dn: cn=Guacamole,ou=Service Users,dc=example,dc=net
ldap-search-bind-password: SomePassword!
</pre></div>
</div>
<p>is exactly equivalent to the following <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code></p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- hostname: dc1.example.net
user-base-dn: ou=Users,dc=example,dc=net
username-attribute: sAMAccountName
search-bind-dn: cn=Guacamole,ou=Service Users,dc=example,dc=net
search-bind-password: SomePassword!
</pre></div>
</div>
<p>The benefit of using <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code> is that the format allows multiple
servers to be defined, relying on the properties within <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code>
as defaults. For example, the following <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code> defines two LDAP
servers:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- hostname: dc1.example.net
user-base-dn: ou=Users,dc=example,dc=net
username-attribute: sAMAccountName
search-bind-dn: cn=Guacamole,ou=Service Users,dc=example,dc=net
search-bind-password: SomePassword!
- hostname: dc2.example.net
user-base-dn: ou=Users,dc=example,dc=net
username-attribute: sAMAccountName
search-bind-dn: cn=Guacamole,ou=Service Users,dc=example,dc=net
search-bind-password: SomePassword!
</pre></div>
</div>
<p>Leveraging the fact that values within <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code> are used as the
default values for all LDAP servers in <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code>, the above can be
abbreviated by moving the common options into <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ldap-user-base-dn: ou=Users,dc=example,dc=net
ldap-username-attribute: sAMAccountName
ldap-search-bind-dn: cn=Guacamole,ou=Service Users,dc=example,dc=net
ldap-search-bind-password: SomePassword!
</pre></div>
</div>
<p>Leaving <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code> containing, simply:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- hostname: dc1.example.net
- hostname: dc2.example.net
</pre></div>
</div>
<p>If multiple LDAP servers are listed within <code class="docutils literal notranslate"><span class="pre">ldap-servers.yml</span></code>, and a user
attempts to log into Guacamole, each defined LDAP server is tried, in order,
until one server successfully authenticates the user or until all servers fail.</p>
<p>If not all LDAP servers are relevant to all users, and it is reasonable to
determine which user is relevant to which LDAP server by the format of their
username, patterns can be specified on a per-server basis to narrow which
servers apply to which login attempts. For example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- hostname: dc1.example.net
match-usernames: COMPANYA\\(.*)
- hostname: dc2.example.net
match-usernames: COMPANYB\\(.*)
</pre></div>
</div>
<p>The value for <code class="docutils literal notranslate"><span class="pre">match-usernames</span></code> can be any regular expression accepted by Java,
where the capturing group dictates the portion that should be considered the
user’s username with respect to Guacamole. If multiple patterns should apply to
a particular LDAP server, this can be specified with a list of patterns for
<code class="docutils literal notranslate"><span class="pre">match-usernames</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>- hostname: dc1.example.net
match-usernames:
- COMPANYA\\(.*)
- (.*)@a\.example\.net
- hostname: dc2.example.net
match-usernames:
- COMPANYB\\(.*)
- (.*)@b\.example\.net
</pre></div>
</div>
</section>
<section id="completing-the-installation">
<h3>Completing the installation<a class="headerlink" href="#completing-the-installation" title="Permalink to this heading"></a></h3>
<p>Guacamole will only reread <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code> and load newly-installed
extensions during startup, so your servlet container will need to be restarted
before the LDAP authentication will take effect. Restart your servlet container
and give the new authentication a try.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>You only need to restart your servlet container. <em>You do not need to restart
guacd</em>.</p>
<p>guacd is completely independent of the web application and does not deal with
<code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code> or the authentication system in any way. Since you are
already restarting the servlet container, restarting guacd as well technically
won’t hurt anything, but doing so is completely pointless.</p>
</div>
<p>If Guacamole does not come back online after restarting your servlet container,
check the logs. Problems in the configuration of the LDAP extension will
prevent Guacamole from starting up, and any such errors will be recorded in the
logs of your servlet container. If properly configured, you will be able to log
in as any user within the defined ldap-user-base-dn.</p>
</section>
</section>
<section id="the-ldap-schema">
<span id="ldap-auth-schema"></span><h2>The LDAP schema<a class="headerlink" href="#the-ldap-schema" title="Permalink to this heading"></a></h2>
<p>Guacamole’s LDAP support allows users and connections to be managed purely
within an LDAP directory defined in <code class="docutils literal notranslate"><span class="pre">guacamole.properties</span></code>. This is
accomplished with a minimum of changes to the standard LDAP schema - all
Guacamole users are traditional LDAP users and share the same mechanism of
authentication. The only new type of object required is a representation for
Guacamole connections, <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code>, which was added to your server’s
schema during the install process above.</p>
<section id="users">
<h3>Users<a class="headerlink" href="#users" title="Permalink to this heading"></a></h3>
<p>All Guacamole users, as far as the LDAP support is concerned, are LDAP users
with standard LDAP credentials. When a user signs in to Guacamole, their
username and password will be used to bind to the LDAP server. If this bind
operation is successful, the available connections are queried from the
directory and the user is allowed in.</p>
</section>
<section id="connections-and-parameters">
<h3>Connections and parameters<a class="headerlink" href="#connections-and-parameters" title="Permalink to this heading"></a></h3>
<p>Each connection is represented by an instance of the <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> object
class, an extended version of the standard LDAP <code class="docutils literal notranslate"><span class="pre">groupOfNames</span></code>, which provides
a protocol and set of parameters. Only members of the <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> will
have access to the corresponding connection.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> object class provides two new attributes in addition to
those provided by <code class="docutils literal notranslate"><span class="pre">groupOfNames</span></code>:</p>
<dl class="simple myst">
<dt><code class="docutils literal notranslate"><span class="pre">guacConfigProtocol</span></code></dt><dd><p>The protocol associated with the connection, such as “<code class="docutils literal notranslate"><span class="pre">vnc</span></code>” or “<code class="docutils literal notranslate"><span class="pre">rdp</span></code>”. This
attribute is required for every <code class="docutils literal notranslate"><span class="pre">guacConfigGroup</span></code> and can be given only once.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">guacConfigParameter</span></code></dt><dd><p>The name and value of a parameter for the specified protocol. This is given
as <code class="docutils literal notranslate"><span class="pre">name=value</span></code>, where “name” is the name of the parameter, as defined by the
documentation for the protocol specified, and “value” is any allowed value for
that parameter.</p>
<p>This attribute can be given multiple times for the same connection.</p>
</dd>
</dl>
<p>For example, to create a new VNC connection which connects to “localhost” at
port 5900, while granting access to <code class="docutils literal notranslate"><span class="pre">user1</span></code> and <code class="docutils literal notranslate"><span class="pre">user2</span></code>, you could create an
<code class="docutils literal notranslate"><span class="pre">.ldif</span></code> file like the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dn: cn=Example Connection,ou=groups,dc=example,dc=net
objectClass: guacConfigGroup
objectClass: groupOfNames
cn: Example Connection
guacConfigProtocol: vnc
guacConfigParameter: hostname=localhost
guacConfigParameter: port=5900
guacConfigParameter: password=secret
member: cn=user1,ou=people,dc=example,dc=net
member: cn=user2,ou=people,dc=example,dc=net
</pre></div>
</div>
<p>The new connection can then be created using the <strong class="command">ldapadd</strong> utility:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>ldapadd -x -D <span class="nv">cn</span><span class="o">=</span>admin,dc<span class="o">=</span>example,dc<span class="o">=</span>net -W -f example-connection.ldif
<span class="go">Enter LDAP Password:</span>
<span class="go">adding new entry &quot;cn=Example Connection,ou=groups,dc=example,dc=net&quot;</span>
<span class="gp">$</span>
</pre></div>
</div>
<p>Where <code class="docutils literal notranslate"><span class="pre">cn=admin,dc=example,dc=net</span></code> is an administrator account with permission
to create new entries, and <code class="docutils literal notranslate"><span class="pre">example-connection.ldif</span></code> is the name of the <code class="docutils literal notranslate"><span class="pre">.ldif</span></code>
file you just created.</p>
<p>There is, of course, no need to use only the standard LDAP utilities to create
connections and users. There are useful graphical environments for manipulating
LDAP directories, such as <a class="reference external" href="https://directory.apache.org/studio/">Apache Directory Studio</a>,
which make many of the tasks given above much easier.</p>
</section>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="jdbc-auth.html" class="btn btn-neutral float-left" title="Database authentication" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="vault.html" class="btn btn-neutral float-right" title="Retrieving secrets from a vault" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>Copyright &copy; 2023 <a href="http://www.apache.org/">The Apache Software Foundation</a>,
Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
Apache Guacamole, Guacamole, Apache, the Apache feather logo, and the Apache Guacamole project logo are
trademarks of The Apache Software Foundation.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
<!-- Google Analytics -->
<script type="text/javascript">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-75289145-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>