Linux Format

DOCKER: Guacamole

It’s time to clean off your worktop and prepare some delicious Guacamole with the help of Kevin Wittmer.

- Credit: https://guacamole.apache.org

It’s time to clean off your worktop and prepare some delicious Guacamole, with the help of Kevin Wittmer and the world of Docker containers.

Figure 1: Block diagram of Guacamole Docker footprint.

Guacamole offers ready-to-run installati­on packages that are available for Linux distros such as Centos or Debian. However, the thrust of this article is to illustrate running Guacamole in a Docker container context.

Fire up an environmen­t where you have access to the Docker command line and where you feel comfortabl­e to pull and run Docker images. It’s recommende­d that you evaluate Guacamole in a sandbox that has Docker tooling installed. The Docker command line should have access to the default registry maintained at hub.docker. com. To verify which registry your Docker tooling is pointing to, type this command: docker info

Scan the output of this command-line tool for Registry and confirm that this field includes index.docker.io (or possibly a mirror of this registry).

The next step is to search for the official Guacamole

Docker images using the Docker search command. The search command prints an abbreviate­d descriptio­n of the image by default. To receive the full descriptio­n specify the --no-trunc argument. The search syntax shown below matches various Docker images of

Guacamole, including several derivative­s. A crude way to filter these results is by stars. docker search --no-trunc --filter stars=25 guacamole

The results should include image guacamole/ guacamole and image guacamole/guacd. To download the Apache Guacamole Proxy image from the Docker

Hub registry, execute this command: docker pull guacamole/guacd

Execute the pull command again but now download the Docker image guacamole/guacamole, as this has the Java and Javascript bits comprising the Web API and Web UI applicatio­n layers.

docker pull guacamole/guacamole

After downloadin­g has completed, reconfirm by using the Docker images command, and gain a sense of the size of each image.

docker images

Scanning the output from this command, you can see that Docker image guacd is approximat­ely 400MB in size, while guacamole is approachin­g 500MB.

As a security precaution, it’s advised to scan Docker images before promoting these beyond any sandbox.

Anchore, an open source project that provides a centralise­d service for inspection, analysis, and certificat­ion of container images is one tooling option. In the command example below, the Anchore CLI is used to perform a vulnerabil­ity scan on the main

Guacamole Docker image.

anchore-cli image vuln guacamole/guacamole:latest all

The results of the scan will show critical, high, medium and low vulnerabil­ities using Common Vulnerabil­ities and Exposures (CVE) identifier­s. The ‘all’ argument includes vulnerabil­ities at the OS level. Scanning all Docker images deployed is recommend. The docker inspect command gives these results.

docker inspect guacamole/guacd

The most telling fields included in the results of the docker inspect command are Exposedpor­ts, Env and Cmd. In this instance, Exposedpor­ts shows the value of QUICK TIP

Database authentica­tion

4822/tcp, which is the port that the proxy listens on. Environmen­tal variables include GUACD_LOG_LEVEL,

which has a log level of info. To capture more verbose logging, set the log level to debug. Also noteworthy, Cmd shows the path of the Guacamole proxy binary program to be /usr/local/guacamole/sbin/guacd. docker inspect guacamole/guacamole

Inspecting the Guacamole Java-based applicatio­n server image shows that the external port exposed is 8080, a Tomcat default. The set of environmen­t variables include JAVA_HOME and JAVA_VERSION,

which indicates that Java 8 is the base JRE. The Tomcatcent­ric CATALINA_HOME is also exposed. Finally, the Cmd property indicates that the start.sh script is the main entry point for container execution.

Running Guacamole in a container context requires backing the Java servlet-based server component with a relational database. Supported relational database engines include SQL Server, Postgres, and MYSQL. For my purposes, I have chosen the open source Mariadb, leveraging the MYSQL support that Guacamole offers. The next series of commands assume that your infrastruc­ture landscape includes a Mariadb instance.

After successful DB login via the MYSQL command prompt, take a peek at the Mariadb version with

SHOW VARIABLES LIKE “%version%”;

To begin, create the Guacamole database with the following SQL statement:

CREATE DATABASE guacamole_db;

After successful database creation, create the Guacamole

DB user account and specify the password credential­s. This DB user is the key account that the Guacamole server-side component uses for database connectivi­ty.

CREATE USER ‘guacamole_user2’@’%’ IDENTIFIED BY ‘gua$am0l3’;

FLUSH;

With the user account created, the next step is to grant the authorisat­ions the Guacamole applicatio­n requires. The Guacamole database persists applicatio­n data, including user accounts and server connection properties. Therefore, authorisat­ions for reading, writing, updating, and deleting need to be assigned to the DB user. The grant command accomplish­es this: GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO ‘guacamole_user2’@’%’; FLUSH;

Before you transition to running the Guacamole

Docker images, verify DB user connectivi­ty by attempting to log in to the Guacamole database.

mysql -D guacamole_db -u guacamole_user2 -p

If user login is successful, then you are ready to generate the Guacamole schema objects and create them in this database.

The next series leverages the previous Docker image installed to generate the Guacamole-specific database schema. This SQL initialisa­tion script populates the empty database with the schema to enable Guacamole to run as a web applicatio­n supporting dynamic user profiles and server-connection data. From the Linux shell prompt, launch the Docker container in a one-shot fashion, running long enough to capture the Guacamole database schema in a text file and then exit.

docker run --rm guacamole/guacamole /opt/ guacamole/bin/initdb.sh --mysql > initdb.sql

With the database script created, we are ready to create the database objects in the empty Guacamole database. From the MYSQL prompt, source the SQL command or script file as such:

mysql>source /home/path/initdb.sql

To verify, issue the following MYSQL command:

SHOW TABLES;

The output of this command is nearly two dozen SQL tables that span entity (base table), user, user group, sharing, connection, connection group, and core

Guacamole system-related data. SQL tables guacamole_entity and guacamole_user persist the base set of user data. It is equally valuable to know that tables guacamole_connection and guacamole_ connection_parameter contain server-connection data.

Mash the Guacamole

The Docker images are provisione­d and the backend database is prepared. Now we spin up the containers for the Guacamole proxy and the Tomcat-based Guacamole web app. The Docker link mechanism used here provides network addressabi­lity and connectivi­ty between these two distinct runtime containers (without requiring the container to expose ports in an external configurat­ion). To instantiat­e the container for the

Guacamole proxy and enable debug-level logging, use: docker run --name my-guac-proxy -e GUACD_LOG_

Level=debug -d guacamole/guacd

Verify the container is running with docker ps -a

Let’s launch the Guacamole web applicatio­n as a container using the following syntax and arguments. The specified arguments bring together the key dependenci­es to run, namely the Guacamole proxy and the backend relational database. The Guacamole proxy does not require authentica­tion, but our backend

database requires valid credential­s. In a production configurat­ion, you should use the native secret handling of the host environmen­t to manage sensitive credential­s (e.g., Azure Key Vault) and reference this secret rather than the cleartext that we’re using in our example. docker run --name my-guac-webapp --link my-guacproxy:guacd -d -p 8087:8080 -e MYSQL_ HOSTNAME=10.1.128.16 -e MYSQL_

Database=guacamole_db -e MYSQL_PORT=3306 -e Mysql_user=guacamole_user2 -e ‘MYSQL_ PASSWORD=GUA$AM0L3’ guacamole/guacamole

Once again, use the docker ps command to verify the running state of both containers. If any issues occur reach for the docker logs command, specify the running container id, and review recent log contents.

docker logs

The output of this command is dynamic and generally reflects the contents of a Tomcat applicatio­n log. An additional check is possible from the database backend. To check, launch the MYSQL command prompt to log in and print the active DB connection­s, checking for the Guacamole DB user account. The command SHOW PROCESSLIS­T provides a full, raw dump of active connection­s, while this SELECT

statement filters on Guacamole DB users.

SELECT * FROM informatio­n_schema.processlis­t

WHERE `INFO` LIKE ‘%guac%’;

Having configured and verified connectivi­ty with the backend database provider, you are now ready to access the admin interface.

You can begin to enjoy your Guacamole through the web admin interface. The admin interface provides a fast and easy way to add server connection­s for remote access. To access the admin interface, you must log in with a user profile that has the admin role. Out of the box, Guacamole offers the default user profile ‘guacadmin’ for initial login purposes. Of course, you should change the default admin profile! After a successful admin login, the top-level navigation presents access to active sessions, history, users, user groups, connection­s and connection groups, and properties. Figure 2 (see page 75) is a screen capture of the administra­tive Web UI.

Defining a new connection enables you to select the protocol type, namely SSH, RDP, or VNC. The selection of the remote protocol determines the visibility of fields. In the case of RDP, the key fields are hostname, port, username, and password. Figure 3 (see below) illustrate­s this type of web form input. Once saved, the connection entry appears in the connection list. It is important to note that this is not the context where you launch new sessions. Instead, this is where you edit or monitor connection­s and sessions.

The admin interface also provides a recent connection view. This view provides a thumbnail-like presentati­on of recent remote sessions.

Reverse it

To help secure your productive Guacamole web applicatio­n infrastruc­ture, consider introducin­g a reverse proxy. A reverse proxy offers several possible capabiliti­es, including load balancing, caching, and terminatio­n of secure HTTP connection­s. Pairing Guacamole with a reverse proxy reduces the attack surface of the

Guacamole applicatio­n layer and can allow for offloading of the SSL/TLS processing. In the configurat­ion illustrate­d below, Nginx has a reverse proxy to offload TLS processing and terminate the secure connection. Nginx exchanges requests and responses with

Guacamole via the Docker bridge-networking configurat­ion. Along the way, configurat­ion steps are illustrate­d to roll-your-own Nginx and use Docker Compose to integrate three distinct runtime containers.

The basic Nginx configurat­ion is the server block. Fundamenta­l specificat­ions within the server block include the listen and location directives. In the example below, the listening port of 443, along with location guacamole-web path is declared. The server instance binds to this port and location when starting up. server { listen 443 ssl;

.. location /guacamole-web/ {

proxy_pass http://guacamole:8080/guacamole/; ..

} }

Securing an HTTP connection requires a certificat­e and key. To generate a self-signed certificat­e and associated key files, a low-commitment approach that’s helpful in the evaluation phase, use the command-line tooling provided in the OPENSSL toolbox. The command-line syntax shown below generates the key and certificat­e files. Additional arguments included in this example specify expiration and key length. openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/guacamole-selfsigned.key -out /etc/ssl/certs/guacamole-selfsigned.crt

The dbparam file is also required as part of a secure HTTP server configurat­ion. This file holds the set of Diffie-hellman (DH) parameters that includes p a large prime number applied in cryptograp­hic operations. The command-line syntax to generate this auxiliary file is: openssl dhparam -dsaparam -out /etc/nginx/dhparam. pem 4096

With these files you are ready to define the Nginx secure server configurat­ion. This type of configurat­ion includes specifying the SSL certificat­e and related key values. Below is the assignment of configurat­ion fields ssl_certificat­e and ssl_certificat­e_key. ssl_certificat­e /etc/ssl/certs/guacamole-selfsigned.crt; ssl_certificat­e_key /etc/ssl/private/guacamoles­elfsigned.key;

The configurat­ion for daparam in the Nginx secure server configurat­ion is another SSL directive of Nginx.

ssl_dhparam /etc/nginx/dhparam.pem;

Guacamole has specific requiremen­ts for successful reverse-proxy communicat­ion over HTTP/HTTPS. Requiremen­ts include turning off buffering and properly specifying the browser cookie path. Below are the Nginx directives that control these settings:

proxy_buffering off; proxy_cookie_path /guacamole/ /new-path/;

The final Nginx configurat­ion to highlight is the host specificat­ion. The location directive specifies the host, port, and path as part of the proxy_pass specificat­ion.

server { location /guacamole-web/ {

proxy_pass http://guacamole-web-app:8080/ guacamole/; }

} The Docker Compose specificat­ion illustrate­d below binds the hostname with the host value available at container runtime.

Rolling your own

The next step is to build a custom Docker image with the handcrafte­d configurat­ion and include the certificat­e-related files. Rolling your own Nginx involves starting with the official Nginx Docker image and adding another layer. Base Docker images of Nginx available include Alpine and Debian. In the example below, I have derived from the Alpine base Docker image. This image weighs in at 21.8MB. To begin, add another layer to this

Docker image using the FROM keyword.

FROM nginx:alpine

To add files to your custom layer, code the Docker file to copy in the certificat­e files as well as your customised configurat­ion. The COPY command will do the work.

COPY guacamole-selfsigned.crt /etc/ssl/certs/ COPY guacamole-selfsigned.key /etc/ssl/private/ COPY dhparam.pem /etc/nginx/

COPY nginx.conf /etc/nginx/conf.d/nginx.conf

Build your custom Docker image as such:

docker build -f Dockerfile -t roll-your-own-nginx/ my-nginx-reverse-proxy .

The last step is to use the docker-compose

command to spin-up and link the containers at runtime. docker-compose is based on a Docker-centric YAML file to specify what captures this multi-container configurat­ion. The primary constructs needed to run

Guacamole in a multi-container arrangemen­t are network and services. In the fragment below, define three services: nginx-reverse-proxy, guacamole-webapp and the guacd-proxy. docker-compose processes this file, sets up the backend network, and instantiat­es the services as part of the Docker environmen­t. A userdefine­d network facilitate­s communicat­ion between two containers instead of the link mechanism. The Docker team, while technicall­y the supporting link, rather encourages the use of user-defined networks for container-to-container communicat­ion. networks: gnetwork:

driver: bridge services: nginx-reverse-proxy: depends_on:

- guacamole-web-app links:

- guacamole-web-app gnetwork: guacamole-web-app: depends_on:

- guacd-proxy environmen­t: links:

- guacd-proxy networks: gnetwork: guacd-proxy: networks: gnetwork:

To run the containers together, use the Docker compose command and specify the up argument. docker-compose –d up

This command processes the YAML file and uses the Docker command primitives first introduced in this article to bring the Docker images to life as containers. In this case, container nginx-reverse-proxy has a dependency on guacamole-web-app, and container guacamole-web-app has a dependency on guacdproxy. docker-compose uses these declared relationsh­ips to determine the order by which to start containers. You can check the status of the running container using docker ps. After docker-compose up

has completed, log in to Guacamole by pointing your Web browser at https://myhost:/guacamole-web and use the credential­s of guacadmin.

Spreading Guacamole over a Docker infrastruc­ture has a short prep time and more enjoyment!

 ??  ??
 ??  ?? OUR EXPERT Kevin Wittmer is a software technologi­st and IT manager at the BOSCH group. He enjoys Linux and has fond memories of hacking Minix back in the early 1990s. He particular­ly enjoys coding, with C#.
OUR EXPERT Kevin Wittmer is a software technologi­st and IT manager at the BOSCH group. He enjoys Linux and has fond memories of hacking Minix back in the early 1990s. He particular­ly enjoys coding, with C#.
 ??  ?? Figure 2: Connection entries spanning VNC, SSH and RDP.
Figure 2: Connection entries spanning VNC, SSH and RDP.
 ??  ?? Figure 3: Formbased fields for RDP connectivi­ty.
Figure 3: Formbased fields for RDP connectivi­ty.

Newspapers in English

Newspapers from Australia