├── .dockerignore ├── .gitignore ├── tutorials ├── guacamole-tutorial │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── webapp │ │ │ ├── WEB-INF │ │ │ │ └── web.xml │ │ │ └── index.html │ │ │ └── java │ │ │ └── org │ │ │ └── apache │ │ │ └── guacamole │ │ │ └── net │ │ │ └── example │ │ │ └── TutorialGuacamoleTunnelServlet.java │ └── pom.xml ├── guacamole-auth-tutorial │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── guac-manifest.json │ │ │ └── java │ │ │ └── org │ │ │ └── apache │ │ │ └── guacamole │ │ │ └── auth │ │ │ ├── TutorialGuacamoleProperties.java │ │ │ └── TutorialAuthenticationProvider.java │ └── pom.xml └── libguac-client-ball │ ├── Makefile.am │ ├── src │ ├── ball.h │ └── ball.c │ ├── configure.ac │ └── .gitignore ├── src ├── images │ ├── edit-user.png │ ├── guac-arch.png │ ├── touchpad.png │ ├── client-panel.png │ ├── client-tiled.png │ ├── edit-group.png │ ├── file-browser.png │ ├── manage-users.png │ ├── totp-enroll.png │ ├── touchscreen.png │ ├── file-transfers.png │ ├── manage-button.png │ ├── manage-groups.png │ ├── manage-history.png │ ├── duo-add-guacamole.png │ ├── duo-auth-factor-1.png │ ├── duo-auth-factor-2.png │ ├── duo-copy-details.png │ ├── edit-connection.png │ ├── edit-user-group.png │ ├── guac-menu-share.png │ ├── guacamole-drive.png │ ├── manage-sessions.png │ ├── player-key-events.png │ ├── ssl-sso-001-link.png │ ├── totp-group-config.png │ ├── totp-user-config.png │ ├── batch-import-start.png │ ├── manage-connections.png │ ├── ssl-sso-003-success.png │ ├── totp-auth-factor-1.png │ ├── totp-auth-factor-2.png │ ├── totp-enroll-detail.png │ ├── auth-restrict-options.png │ ├── batch-import-failure.png │ ├── batch-import-success.png │ ├── client-connection-menu.png │ ├── duo-rename-guacamole.png │ ├── edit-group-memberships.png │ ├── edit-sharing-profile.png │ ├── edit-user-membership.png │ ├── guac-menu-disconnect.png │ ├── guac-menu-share-link.png │ ├── guacamole-home-screen.png │ ├── guacamole-preferences.png │ ├── too-many-failed-logins.png │ ├── batch-import-admin-link.png │ ├── client-tiled-multi-focus.png │ ├── guacamole-drive-download.png │ ├── recording-player-in-use.png │ ├── session-filter-example-1.png │ ├── session-filter-example-2.png │ ├── vault-ksm-002-select-ksm.png │ ├── auth-restrict-connections.png │ ├── guacamole-client-interface.png │ ├── guacamole-settings-sections.png │ ├── ssl-sso-002-browser-prompt.png │ ├── auth-restrict-login-work-week.png │ ├── history-table-with-recordings.png │ ├── vault-ksm-004-generate-token.png │ ├── auth-restrict-connection-failed.png │ ├── auth-restrict-login-block-router.png │ ├── auth-restrict-login-failed-host.png │ ├── auth-restrict-login-failed-time.png │ ├── auth-restrict-login-local-subnet.png │ ├── client-connection-menu-multiple.png │ ├── auth-restrict-login-business-hours.png │ ├── vault-ksm-003a-create-application.png │ ├── vault-ksm-003b-create-application.png │ ├── vault-ksm-001a-create-shared-folder.png │ ├── vault-ksm-001b-create-shared-folder.png │ ├── recording-storage-connection-config-option2.png │ └── recording-storage-connection-config-option1-recommended.png ├── include │ ├── mysql.properties.in │ ├── sqlserver.properties.in │ ├── postgresql.properties.in │ ├── mysql-external.properties.in │ ├── mysql-access-window.properties.in │ ├── mysql-password-age.properties.in │ ├── postgresql-external.properties.in │ ├── sqlserver-external.properties.in │ ├── mysql-concurrent-use.properties.in │ ├── mysql-password-reuse.properties.in │ ├── sqlserver-password-age.properties.in │ ├── postgresql-access-window.properties.in │ ├── postgresql-password-age.properties.in │ ├── sqlserver-access-window.properties.in │ ├── sqlserver-concurrent-use.properties.in │ ├── sqlserver-password-reuse.properties.in │ ├── mysql-password-complexity.properties.in │ ├── postgresql-concurrent-use.properties.in │ ├── postgresql-password-reuse.properties.in │ ├── sqlserver-password-complexity.properties.in │ ├── postgresql-password-complexity.properties.in │ ├── recording-playback.properties.in │ ├── ksm-user-vaults.properties.in │ ├── http-auth.properties.in │ ├── cas.properties.in │ ├── duo-optional.properties.in │ ├── warn-config-changes.md │ ├── jdbc-password-reuse.properties.in │ ├── ksm.properties.in │ ├── jdbc-default-user.md │ ├── jdbc-access-window.properties.in │ ├── ext-client-ips.md │ ├── jdbc-password-age.properties.in │ ├── ssl.properties.in │ ├── jdbc.properties.in │ ├── json-optional.properties.in │ ├── json.properties.in │ ├── quickconnect.properties.in │ ├── totp.properties.in │ ├── ban.properties.in │ ├── ldap.properties.in │ ├── sso-login-behavior.md │ ├── jdbc-password-complexity.properties.in │ ├── jdbc-external.properties.in │ ├── ksm-optional.properties.in │ ├── jdbc-upgrade.md │ ├── totp-bypass-enforce.properties.in │ ├── duo-bypass-enforce.properties.in │ ├── jdbc-concurrent-use.properties.in │ ├── ext-completing.md │ ├── cas-optional.properties.in │ ├── duo.properties.in │ ├── openid-optional.properties.in │ ├── sqlserver-optional.properties.in │ ├── openid.properties.in │ ├── ssl-optional.properties.in │ ├── saml.properties.in │ ├── postgresql-optional.properties.in │ ├── radius.properties.in │ └── mysql-optional.properties.in ├── _templates │ └── footer.html ├── _static │ └── gug.css ├── mfa.md ├── security.md ├── sso.md ├── generate-j2-data.py ├── header-auth.md.j2 ├── jdbc-auth.md ├── auth-ban.md.j2 ├── installing-guacamole.md ├── external-auth.md ├── index.md ├── saml-auth.md.j2 ├── conf.py ├── cas-auth.md.j2 ├── openid-auth.md.j2 ├── duo-auth.md.j2 ├── adhoc-connections.md.j2 ├── radius-auth.md.j2 ├── sqlserver-auth.md.j2 ├── batch-import.md ├── guacamole-common.md ├── guacamole-architecture.md ├── totp-auth.md.j2 ├── postgresql-auth.md.j2 ├── introduction.md └── mysql-auth.md.j2 ├── NOTICE ├── .github └── workflows │ └── pr-build.yml ├── Dockerfile ├── CONTRIBUTING ├── Makefile └── README.md /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | build/ 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *~ 3 | __pycache__ 4 | Pipfile 5 | Pipfile.lock 6 | -------------------------------------------------------------------------------- /tutorials/guacamole-tutorial/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target/ 3 | META-INF/ 4 | -------------------------------------------------------------------------------- /tutorials/guacamole-auth-tutorial/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target/ 3 | META-INF/ 4 | -------------------------------------------------------------------------------- /src/images/edit-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-user.png -------------------------------------------------------------------------------- /src/images/guac-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guac-arch.png -------------------------------------------------------------------------------- /src/images/touchpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/touchpad.png -------------------------------------------------------------------------------- /src/images/client-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/client-panel.png -------------------------------------------------------------------------------- /src/images/client-tiled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/client-tiled.png -------------------------------------------------------------------------------- /src/images/edit-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-group.png -------------------------------------------------------------------------------- /src/images/file-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/file-browser.png -------------------------------------------------------------------------------- /src/images/manage-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-users.png -------------------------------------------------------------------------------- /src/images/totp-enroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-enroll.png -------------------------------------------------------------------------------- /src/images/touchscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/touchscreen.png -------------------------------------------------------------------------------- /src/images/file-transfers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/file-transfers.png -------------------------------------------------------------------------------- /src/images/manage-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-button.png -------------------------------------------------------------------------------- /src/images/manage-groups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-groups.png -------------------------------------------------------------------------------- /src/images/manage-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-history.png -------------------------------------------------------------------------------- /src/images/duo-add-guacamole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/duo-add-guacamole.png -------------------------------------------------------------------------------- /src/images/duo-auth-factor-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/duo-auth-factor-1.png -------------------------------------------------------------------------------- /src/images/duo-auth-factor-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/duo-auth-factor-2.png -------------------------------------------------------------------------------- /src/images/duo-copy-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/duo-copy-details.png -------------------------------------------------------------------------------- /src/images/edit-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-connection.png -------------------------------------------------------------------------------- /src/images/edit-user-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-user-group.png -------------------------------------------------------------------------------- /src/images/guac-menu-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guac-menu-share.png -------------------------------------------------------------------------------- /src/images/guacamole-drive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-drive.png -------------------------------------------------------------------------------- /src/images/manage-sessions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-sessions.png -------------------------------------------------------------------------------- /src/images/player-key-events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/player-key-events.png -------------------------------------------------------------------------------- /src/images/ssl-sso-001-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/ssl-sso-001-link.png -------------------------------------------------------------------------------- /src/images/totp-group-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-group-config.png -------------------------------------------------------------------------------- /src/images/totp-user-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-user-config.png -------------------------------------------------------------------------------- /src/images/batch-import-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/batch-import-start.png -------------------------------------------------------------------------------- /src/images/manage-connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/manage-connections.png -------------------------------------------------------------------------------- /src/images/ssl-sso-003-success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/ssl-sso-003-success.png -------------------------------------------------------------------------------- /src/images/totp-auth-factor-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-auth-factor-1.png -------------------------------------------------------------------------------- /src/images/totp-auth-factor-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-auth-factor-2.png -------------------------------------------------------------------------------- /src/images/totp-enroll-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/totp-enroll-detail.png -------------------------------------------------------------------------------- /src/images/auth-restrict-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-options.png -------------------------------------------------------------------------------- /src/images/batch-import-failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/batch-import-failure.png -------------------------------------------------------------------------------- /src/images/batch-import-success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/batch-import-success.png -------------------------------------------------------------------------------- /src/images/client-connection-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/client-connection-menu.png -------------------------------------------------------------------------------- /src/images/duo-rename-guacamole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/duo-rename-guacamole.png -------------------------------------------------------------------------------- /src/images/edit-group-memberships.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-group-memberships.png -------------------------------------------------------------------------------- /src/images/edit-sharing-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-sharing-profile.png -------------------------------------------------------------------------------- /src/images/edit-user-membership.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/edit-user-membership.png -------------------------------------------------------------------------------- /src/images/guac-menu-disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guac-menu-disconnect.png -------------------------------------------------------------------------------- /src/images/guac-menu-share-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guac-menu-share-link.png -------------------------------------------------------------------------------- /src/images/guacamole-home-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-home-screen.png -------------------------------------------------------------------------------- /src/images/guacamole-preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-preferences.png -------------------------------------------------------------------------------- /src/images/too-many-failed-logins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/too-many-failed-logins.png -------------------------------------------------------------------------------- /src/images/batch-import-admin-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/batch-import-admin-link.png -------------------------------------------------------------------------------- /src/images/client-tiled-multi-focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/client-tiled-multi-focus.png -------------------------------------------------------------------------------- /src/images/guacamole-drive-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-drive-download.png -------------------------------------------------------------------------------- /src/images/recording-player-in-use.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/recording-player-in-use.png -------------------------------------------------------------------------------- /src/images/session-filter-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/session-filter-example-1.png -------------------------------------------------------------------------------- /src/images/session-filter-example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/session-filter-example-2.png -------------------------------------------------------------------------------- /src/images/vault-ksm-002-select-ksm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-002-select-ksm.png -------------------------------------------------------------------------------- /src/images/auth-restrict-connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-connections.png -------------------------------------------------------------------------------- /src/images/guacamole-client-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-client-interface.png -------------------------------------------------------------------------------- /src/images/guacamole-settings-sections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/guacamole-settings-sections.png -------------------------------------------------------------------------------- /src/images/ssl-sso-002-browser-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/ssl-sso-002-browser-prompt.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-work-week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-work-week.png -------------------------------------------------------------------------------- /src/images/history-table-with-recordings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/history-table-with-recordings.png -------------------------------------------------------------------------------- /src/images/vault-ksm-004-generate-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-004-generate-token.png -------------------------------------------------------------------------------- /src/images/auth-restrict-connection-failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-connection-failed.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-block-router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-block-router.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-failed-host.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-failed-host.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-failed-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-failed-time.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-local-subnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-local-subnet.png -------------------------------------------------------------------------------- /src/images/client-connection-menu-multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/client-connection-menu-multiple.png -------------------------------------------------------------------------------- /src/images/auth-restrict-login-business-hours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/auth-restrict-login-business-hours.png -------------------------------------------------------------------------------- /src/images/vault-ksm-003a-create-application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-003a-create-application.png -------------------------------------------------------------------------------- /src/images/vault-ksm-003b-create-application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-003b-create-application.png -------------------------------------------------------------------------------- /src/images/vault-ksm-001a-create-shared-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-001a-create-shared-folder.png -------------------------------------------------------------------------------- /src/images/vault-ksm-001b-create-shared-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/vault-ksm-001b-create-shared-folder.png -------------------------------------------------------------------------------- /src/images/recording-storage-connection-config-option2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/recording-storage-connection-config-option2.png -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache Guacamole 2 | Copyright 2020 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /src/images/recording-storage-connection-config-option1-recommended.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/guacamole-manual/HEAD/src/images/recording-storage-connection-config-option1-recommended.png -------------------------------------------------------------------------------- /src/include/mysql.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-external.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-external.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-access-window.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-access-window.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-password-age.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-password-age.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-external.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-external.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-external.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-external.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-concurrent-use.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-concurrent-use.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-password-reuse.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-password-reuse.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-password-age.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-password-age.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-access-window.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-access-window.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-password-age.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-password-age.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-access-window.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-access-window.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-concurrent-use.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-concurrent-use.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-password-reuse.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-password-reuse.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/mysql-password-complexity.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'mysql-') -%} 4 | {%- include 'include/jdbc-password-complexity.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-concurrent-use.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-concurrent-use.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-password-reuse.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-password-reuse.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/sqlserver-password-complexity.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'sqlserver-') -%} 4 | {%- include 'include/jdbc-password-complexity.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/postgresql-password-complexity.properties.in: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=jproperties.jinja : #} 2 | 3 | {%- filter replace('somesql-', 'postgresql-') -%} 4 | {%- include 'include/jdbc-password-complexity.properties.in' -%} 5 | {%- endfilter -%} 6 | -------------------------------------------------------------------------------- /src/include/recording-playback.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The directory to search for associated session recordings. This property is 3 | # optional. By default, `/var/lib/guacamole/recordings` will be used. 4 | # 5 | recording-search-path: /var/lib/guacamole/recordings 6 | -------------------------------------------------------------------------------- /tutorials/guacamole-auth-tutorial/src/main/resources/guac-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "guacamoleVersion" : "1.6.0", 4 | 5 | "name" : "Tutorial Authentication Extension", 6 | "namespace" : "guac-auth-tutorial", 7 | 8 | "authProviders" : [ 9 | "org.apache.guacamole.auth.TutorialAuthenticationProvider" 10 | ] 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/include/ksm-user-vaults.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # Whether or not users should be allowed to set their own KSM configuration, 3 | # which will be used to pull secrets _only_ when not already provided by the 4 | # global or connection-group-level KSM configuration. A user-level KSM 5 | # configuration will never be used if a matching secret is otherwise available. 6 | # 7 | ksm-allow-user-config: false 8 | -------------------------------------------------------------------------------- /src/include/http-auth.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The HTTP header containing the username of the authenticated user. 3 | # 4 | # This property is optional. If not specified, `REMOTE_USER` will be used by 5 | # default. If your authentication system uses a different HTTP header you can 6 | # use this option to override it and specify the header for Guacamole to 7 | # expect. 8 | # 9 | http-auth-header: REMOTE_USER 10 | -------------------------------------------------------------------------------- /src/include/cas.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The URL of the CAS authentication server. This should be the full path to the 3 | # base of the CAS installation. 4 | # 5 | cas-authorization-endpoint: https://cas.example.net 6 | 7 | # 8 | # The URI to redirect back to upon successful authentication. Normally this 9 | # will be the full URL of your Guacamole installation. 10 | # 11 | cas-redirect-uri: https://guac.example.net 12 | -------------------------------------------------------------------------------- /tutorials/libguac-client-ball/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | AM_CFLAGS = -Werror -Wall -pedantic 5 | 6 | lib_LTLIBRARIES = libguac-client-ball.la 7 | 8 | # All source files of libguac-client-ball 9 | noinst_HEADERS = src/ball.h 10 | libguac_client_ball_la_SOURCES = src/ball.c 11 | 12 | # libtool versioning information 13 | libguac_client_ball_la_LDFLAGS = -version-info 0:0:0 14 | -------------------------------------------------------------------------------- /src/include/duo-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The maximum amount of time to wait for a user to finish authenticating with 3 | # Duo, in minutes. Any authentication attempt that takes longer than this 4 | # amount of time will be rejected, requiring the user to reenter their 5 | # credentials and possibly revalidate their identity with Duo. By default, 6 | # login attempts are allowed to take up to 5 minutes. 7 | # 8 | duo-auth-timeout: 5 9 | -------------------------------------------------------------------------------- /tutorials/libguac-client-ball/src/ball.h: -------------------------------------------------------------------------------- 1 | #ifndef BALL_CLIENT_H 2 | #define BALL_CLIENT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | typedef struct ball_client_data { 9 | 10 | guac_layer* ball; 11 | 12 | int ball_x; 13 | int ball_y; 14 | 15 | int ball_velocity_x; 16 | int ball_velocity_y; 17 | 18 | pthread_t render_thread; 19 | 20 | } ball_client_data; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/include/warn-config-changes.md: -------------------------------------------------------------------------------- 1 | :::{warning} 2 | You will need to restart the Guacamole web application in order to complete 3 | configuration. Doing this will disconnect all active users, so please: 4 | 5 | * **Do this only at a time that you can tolerate service unavailability**, such 6 | as a scheduled maintenance window. 7 | 8 | * Keep in mind that **configuration errors may prevent Guacamole from starting 9 | back up**. 10 | ::: 11 | -------------------------------------------------------------------------------- /src/include/jdbc-password-reuse.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The number of previous passwords remembered for each user, where zero 3 | # represents no history. If set to a non-zero value, users will be restricted 4 | # from reusing any password in their password history. Passwords are remembered 5 | # only in hashed and salted form. By default, previous passwords are not 6 | # remembered and no such restriction is enforced. 7 | # 8 | somesql-user-password-history-size: 6 9 | -------------------------------------------------------------------------------- /src/include/ksm.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The base64-encoded configuration information generated for the application 3 | # you created within KSM to represent Apache Guacamole. The easiest way to 4 | # obtain this value is using [the KSM CLI tool](https://docs.keeper.io/secrets-manager/secrets-manager/secrets-manager-command-line-interface/init-command). 5 | # as described above. *This value is required.* 6 | # 7 | ksm-config: ewogICJjbGllbnRJZCI6ICJTR1ZzYkc4Z2RHaGxjbVVoSUZSb1pYTmxJSEJ5YjNC... 8 | -------------------------------------------------------------------------------- /src/include/jdbc-default-user.md: -------------------------------------------------------------------------------- 1 | The default Guacamole user created by the provided SQL scripts is 2 | "`guacadmin`", with a default password of "`guacadmin`". Once you have verified 3 | that the database authentication is working, **you should [change your password 4 | immediately](changing-password)**. 5 | 6 | Once you have successfully logged in and changed your password, you can begin 7 | using the web UI to create other users, groups, and connections. More detailed 8 | instructions for doing this are given in [](administration). 9 | -------------------------------------------------------------------------------- /src/include/jdbc-access-window.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # Whether time-based access windows should be enforced for active user sessions. 3 | # By default, users will be logged out when an access window closes, even if 4 | # they are currently logged in. To allow logged-in users to continue to use the 5 | # application after an access window closes, set this to "false". Users will 6 | # always be prevented from logging in outside of access windows regardless of 7 | # this setting. 8 | # 9 | somesql-enforce-access-windows-for-active-sessions: true 10 | -------------------------------------------------------------------------------- /src/_templates/footer.html: -------------------------------------------------------------------------------- 1 | {% extends '!footer.html' %} 2 | 3 | {% block contentinfo %} 4 | {%- if show_copyright %} 5 |

Copyright © {{ copyright_year }} The Apache Software Foundation, 6 | Licensed under the Apache License, Version 2.0. 7 | Apache Guacamole, Guacamole, Apache, the Apache feather logo, and the Apache Guacamole project logo are 8 | trademarks of The Apache Software Foundation.

9 | {%- endif %} 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /src/include/ext-client-ips.md: -------------------------------------------------------------------------------- 1 | :::{warning} 2 | If you will be configuring Guacamole to consider users' IP addresses, **it is 3 | important to make sure that Guacamole is receiving correct IP address 4 | information for all clients**. 5 | 6 | If Guacamole is behind a reverse proxy, such as for SSL termination, the IP 7 | addresses of all users will appear to be the IP address of the proxy unless 8 | additional configuration steps are taken. **Be sure to follow [the 9 | documentation for configuring forwarding of client IP 10 | information](reverse-proxy)!** 11 | ::: 12 | -------------------------------------------------------------------------------- /src/include/jdbc-password-age.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The minimum number of days which must elapse before a user may reset their 3 | # password, where zero represents no limit. By default, no minimum number of 4 | # days is required. 5 | # 6 | somesql-user-password-min-age: 7 7 | 8 | # 9 | # The maximum number of days which may elapse before a user is automatically 10 | # required to reset their password, where zero represents no limit. By default, 11 | # users are not automatically required to reset their password based on 12 | # password age. 13 | # 14 | somesql-user-password-max-age: 90 15 | -------------------------------------------------------------------------------- /tutorials/libguac-client-ball/configure.ac: -------------------------------------------------------------------------------- 1 | # Project information 2 | AC_PREREQ([2.61]) 3 | AC_INIT([libguac-client-ball], [0.1.0]) 4 | AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) 5 | AM_SILENT_RULES([yes]) 6 | 7 | AC_CONFIG_MACRO_DIRS([m4]) 8 | 9 | # Check for required build tools 10 | AC_PROG_CC 11 | AC_PROG_CC_C99 12 | AC_PROG_LIBTOOL 13 | 14 | # Check for libguac 15 | AC_CHECK_LIB([guac], [guac_client_stream_png],, 16 | AC_MSG_ERROR("libguac is required for communication via " 17 | "the Guacamole protocol")) 18 | 19 | AC_CONFIG_FILES([Makefile]) 20 | AC_OUTPUT 21 | -------------------------------------------------------------------------------- /src/include/ssl.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The URI that should be used to authenticate users with SSL/TLS client 3 | # authentication. This must be a URI that points to THIS instance of Guacamole, 4 | # but behind SSL termination that requires SSL/TLS client authentication. 5 | # 6 | ssl-auth-uri: https://*.auth.guac.example.net 7 | 8 | # 9 | # The URI of this instance without SSL/TLS client authentication required. This 10 | # must be a URI that points to THIS instance of Guacamole, but behind SSL 11 | # termination that DOES NOT require or request SSL/TLS client authentication. 12 | # 13 | ssl-auth-primary-uri: https://guac.example.net 14 | -------------------------------------------------------------------------------- /src/include/jdbc.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The name of the database that you created for Guacamole. This is given as 3 | # "guacamole_db" in the examples given in this chapter. 4 | # 5 | somesql-database: guacamole_db 6 | 7 | # 8 | # The username of the user that Guacamole should use to connect to the 9 | # database. This is given as "guacamole_user" in the examples given in this 10 | # chapter. 11 | # 12 | somesql-username: guacamole_user 13 | 14 | # 15 | # The password Guacamole should provide when authenticating with the database. 16 | # This is given as "some_password" in the examples given in this chapter. 17 | # 18 | somesql-password: some_password 19 | -------------------------------------------------------------------------------- /src/include/json-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # A comma-separated list of IP addresses or subnets (in CIDR notation) that 3 | # should be allowed to authenticate using encrypted JSON authentication. If 4 | # set, _only_ machines with IP addresses that match the addresses/subnets in 5 | # this list will be allowed to authenticate in this way. All other attempts to 6 | # authenticate with encrypted JSON authentication will fail, regardless of 7 | # whether the JSON is correctly signed and encrypted. 8 | # 9 | # By default, no restriction is placed on which machines may attempt to use 10 | # encrypted JSON authentication. 11 | # 12 | json-trusted-networks: 10.10.0.0/8, 10.11.0.2 13 | -------------------------------------------------------------------------------- /tutorials/libguac-client-ball/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Object code 3 | *.o 4 | *.so 5 | *.lo 6 | *.la 7 | 8 | # gcov files 9 | *.gcda 10 | *.gcov 11 | *.gcno 12 | 13 | # Backup files 14 | *~ 15 | 16 | # Release files 17 | *.tar.gz 18 | 19 | # Files currently being edited by vim or vi 20 | *.swp 21 | 22 | # automake/autoconf 23 | .deps/ 24 | .dirstamp 25 | .libs/ 26 | Makefile 27 | Makefile.in 28 | aclocal.m4 29 | autom4te.cache/ 30 | m4/* 31 | !README 32 | compile 33 | config.guess 34 | config.h 35 | config.h.in 36 | config.log 37 | config.status 38 | config.sub 39 | configure 40 | depcomp 41 | install-sh 42 | libtool 43 | ltmain.sh 44 | missing 45 | stamp-h1 46 | test-driver 47 | 48 | -------------------------------------------------------------------------------- /src/include/json.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The 128-bit value to use to decrypt and verify the signatures of received 3 | # JSON data. This value must be expressed as a 32-digit hexadecimal value. 4 | # 5 | # Any 32-digit hexadecimal value will suffice as long as it is random enough to 6 | # be impractical for a malicious user to guess. An easy way to generate such a 7 | # key is to echo a secure passphrase through the `md5sum` utility. This is the 8 | # technique OpenSSL itself uses to generate 128-bit keys from passphrases. For 9 | # example: 10 | # 11 | # ```console 12 | # $ echo -n "ThisIsATest" | md5sum 13 | # 4c0b569e4c96df157eee1b65dd0e4d41 14 | # ``` 15 | # 16 | json-secret-key: 4c0b569e4c96df157eee1b65dd0e4d41 17 | -------------------------------------------------------------------------------- /src/include/quickconnect.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # An optional list of parameters that are allowed to be used by connections 3 | # that are created and accessed via the quickconnect extension. If provided, 4 | # only parameters in this list will be allowed. 5 | # 6 | quickconnect-allowed-parameters: hostname, port 7 | 8 | # 9 | # An optional list of parameters that are explicitly denied from being used by 10 | # connections created and accessed via the quickconnect extension. If provided, 11 | # any parameters in this list will be removed from the connection configuration 12 | # when it is created, **even if those parameters are otherwise explicitly 13 | # listed as allowed**. 14 | # 15 | quickconnect-denied-parameters: enable-drive, drive-path 16 | -------------------------------------------------------------------------------- /src/include/totp.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The human-readable name of the entity issuing user accounts. If not 3 | # specified, "Apache Guacamole" will be used by default. 4 | # 5 | totp-issuer: Apache Guacamole 6 | 7 | # 8 | # The number of digits which should be included in each generated TOTP code. 9 | # Legal values are 6, 7, or 8. By default, 6-digit codes are generated. 10 | # 11 | totp-digits: 6 12 | 13 | # 14 | # The duration that each generated code should remain valid, in seconds. By 15 | # default, each code remains valid for 30 seconds. 16 | # 17 | totp-period: 30 18 | 19 | # 20 | # The hash algorithm that should be used to generate TOTP codes. Legal values 21 | # are "sha1", "sha256", and "sha512". By default, "sha1" is used. 22 | # 23 | totp-mode: sha1 24 | -------------------------------------------------------------------------------- /.github/workflows/pr-build.yml: -------------------------------------------------------------------------------- 1 | name: Pull request CI build 2 | 3 | # Run build for all pull requests 4 | on: 5 | pull_request: 6 | 7 | # Limit to only one build for a given PR source branch at a time, 8 | # cancelling any in-progress builds 9 | concurrency: 10 | group: guacamole-manual-pr-${{ github.head_ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | 15 | docker_build: 16 | name: Run docker build 17 | runs-on: ubuntu-latest 18 | steps: 19 | 20 | - name: Check out code 21 | uses: actions/checkout@v3 22 | with: 23 | fetch-depth: 0 24 | persist-credentials: false 25 | 26 | - name: Build Docker container 27 | shell: sh 28 | run: | 29 | docker build --pull --no-cache --force-rm . 30 | -------------------------------------------------------------------------------- /src/include/ban.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The number of authentication failures ater which the extension will block 3 | # further logins from the client IP address. This property is optional and 4 | # the default is 5. 5 | # 6 | ban-max-invalid-attempts: 5 7 | 8 | # 9 | # The length of time for which a client IP address will be denied logins 10 | # after the maximum authentication failures, in seconds. This property is 11 | # optional and has a default value of 300 seconds (five minutes). 12 | # 13 | ban-address-duration: 300 14 | 15 | # 16 | # The maximum number of client IP addresses that the extension will track 17 | # in-memory before the oldest client IP is discarded in a Least-Recently 18 | # Used (LRU) fashion. This property is optional and has a default value 19 | # of 10485670 (10 million IP addresses). 20 | # 21 | ban-max-addresses: 10485670 22 | -------------------------------------------------------------------------------- /src/include/ldap.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The base of the DN for all Guacamole users. *This property is absolutely 3 | # required in all cases.* All Guacamole users must be descendents of this base 4 | # DN. 5 | # 6 | # If a search DN is provided (via `ldap-search-bind-dn`), then Guacamole users 7 | # need only be somewhere within the subtree of the specified user base DN. 8 | # 9 | # If a search DN *is not* provided, then all Guacamole users must be *direct 10 | # descendents* of this base DN, as the base DN will be appended to the username 11 | # to derive the user's DN. For example, if `ldap-user-base-dn` is 12 | # "`ou=people,dc=example,dc=net`", and `ldap-username-attribute` is "uid", then 13 | # a person attempting to login as "`user`" would be mapped to the following 14 | # full DN: "`uid=user,ou=people,dc=example,dc=net`". 15 | # 16 | ldap-user-base-dn: ou=people,dc=example,dc=net 17 | -------------------------------------------------------------------------------- /src/include/sso-login-behavior.md: -------------------------------------------------------------------------------- 1 | Guacamole loads authentication extensions in order of priority, and evaluates 2 | authentication attempts in this same order. This has implications for how the 3 | Guacamole login process behaves when an SSO extension is present: 4 | 5 | If the SSO extension has priority: 6 | : Users that are not yet authenticated 7 | will be immediately redirected to the configured identity provider. They will 8 | not see a Guacamole login screen. 9 | 10 | If a non-SSO extension has priority: 11 | : Users that are not yet authenticated 12 | will be presented with a Guacamole login screen. Additionally, links to the 13 | configured identity provider(s) will be available for users that wish to log 14 | in using SSO. 15 | 16 | The default priority of extensions is dictated by their filenames, with 17 | extensions that sort earlier alphabetically having higher priority than others. 18 | This can be overridden by [explicitly setting the extension 19 | priority](initial-setup). 20 | 21 | -------------------------------------------------------------------------------- /tutorials/guacamole-tutorial/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | index.html 12 | 13 | 14 | 15 | 16 | Tunnel servlet. 17 | Tunnel 18 | 19 | org.apache.guacamole.net.example.TutorialGuacamoleTunnelServlet 20 | 21 | 22 | 23 | 24 | Tunnel 25 | /tunnel 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/include/jdbc-password-complexity.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The minimum length required of all user passwords, in characters. By default, 3 | # password length is not enforced. 4 | # 5 | somesql-user-password-min-length: 8 6 | 7 | # 8 | # Whether all user passwords must have at least one lowercase character and one 9 | # uppercase character. By default, no such restriction is imposed. 10 | # 11 | somesql-user-password-require-multiple-case: true 12 | 13 | # 14 | # Whether all user passwords must have at least one non-alphanumeric character 15 | # (symbol). By default, no such restriction is imposed. 16 | # 17 | somesql-user-password-require-symbol: true 18 | 19 | # 20 | # Whether all user passwords must have at least one numeric character (digit). 21 | # By default, no such restriction is imposed. 22 | # 23 | somesql-user-password-require-digit: true 24 | 25 | # 26 | # Whether users are prohibited from including their own username in their 27 | # password. By default, no such restriction is imposed. 28 | # 29 | somesql-user-password-prohibit-username: true 30 | -------------------------------------------------------------------------------- /src/_static/gug.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | /* Hide "Back to top" button when printing the documentation */ 21 | @media print { 22 | #pst-back-to-top { 23 | display: none !important; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/include/jdbc-external.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # Whether a user account within the database is required for authentication to 3 | # succeed, even if the user has been authenticated via another extension. By 4 | # default, successful authentication via any extension is sufficient, and 5 | # database user accounts are not strictly required. 6 | # 7 | somesql-user-required: true 8 | 9 | # 10 | # Whether to automatically create user accounts in the database for users who 11 | # have successfully authenticate through another extension. Users that are 12 | # automatically created are granted `READ` permission on their own user account 13 | # and no other explicit permissions. By default users will not be automatically 14 | # created. 15 | # 16 | somesql-auto-create-accounts: true 17 | 18 | # 19 | # Whether connection history records should be created for connections not 20 | # defined in the database. By default, external connection history will be 21 | # tracked unless this is explicitly disabled by setting this to "false". 22 | # 23 | somesql-track-external-connection-history: true 24 | -------------------------------------------------------------------------------- /src/include/ksm-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # Whether unverified server certificates should be accepted. If set to `true`, 3 | # the server certificate for connections to the KSM service will be accepted even 4 | # if they cannot be verified. **Unless you are a developer testing changes to 5 | # the KSM vault support itself, it is unlikely that you need to set this 6 | # property.** 7 | # 8 | ksm-allow-unverified-cert: false 9 | 10 | # 11 | # Specify the minimum number of milliseconds between calls to the KSM API. The 12 | # API allows a limited number of calls per month, and calls over the included 13 | # amount generate additional cost. Setting this property allows you to 14 | # limit Guacamole's impact on that cost. 15 | # 16 | ksm-api-call-interval: 300000 17 | 18 | # 19 | # Whether or not the Windows domain should be stripped off of the username 20 | # when usernames are retrieved from the KSM vault and placed into its own 21 | # secret. This is optional, and by default it is false - domains will 22 | # not be stripped from the username. 23 | # 24 | ksm-strip-windows-domains: false 25 | -------------------------------------------------------------------------------- /src/mfa.md: -------------------------------------------------------------------------------- 1 | Multi-factor authentication 2 | =========================== 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | Duo 8 | TOTP 9 | ::: 10 | 11 | Multi-factor authentication (MFA) allows you to require that users verify their 12 | identities through additional mechanisms beyond simply entering a username and 13 | password, such as by using a mobile authenticator app. Guacamole supports the 14 | following MFA methods: 15 | 16 | [Duo](duo-auth) 17 | : A proprietary MFA mechanism provided by a third-party commercial company via 18 | their own proprietary mobile app. 19 | 20 | [TOTP](totp-auth) 21 | : A standard, non-proprietary, widely supported algorithm for generating 22 | temporary authentication codes. This is the algorithm used by several common 23 | authenticator apps, including Google Authenticator. 24 | 25 | If you are using a [single sign-on provider](sso), configuring your provider to 26 | require MFA as part of the authentication process is also a possibility. In 27 | this case, leveraging a dedicated Guacamole extension to provide MFA is not 28 | necesary. 29 | -------------------------------------------------------------------------------- /src/include/jdbc-upgrade.md: -------------------------------------------------------------------------------- 1 | If you are upgrading from an older version of Guacamole, you may need to run 2 | one or more database schema upgrade scripts located within the 3 | `schema/upgrade/` directory. Each of these scripts is named 4 | {samp}`upgrade-pre-{VERSION}.sql` where `VERSION` is the version of Guacamole 5 | where those changes were introduced. They need to be run when you are upgrading 6 | from a version of Guacamole older than `VERSION`. 7 | 8 | If there are no {samp}`upgrade-pre-{VERSION}.sql` scripts present in the 9 | `schema/upgrade/` directory which apply to your existing Guacamole database, 10 | then the schema has not changed between your version and the version your are 11 | installing, and there is no need to run any database upgrade scripts. 12 | 13 | These scripts are incremental and, when relevant, *must be run in order*. For 14 | example, if you are upgrading an existing database from version 15 | 0.9.13-incubating to version 1.0.0, you would need to run the 16 | `upgrade-pre-0.9.14.sql` script (because 0.9.13-incubating is older than 17 | 0.9.14), followed by the `upgrade-pre-1.0.0.sql` script (because 18 | 0.9.13-incubating is also older than 1.0.0). 19 | -------------------------------------------------------------------------------- /src/include/totp-bypass-enforce.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # A comma-separated list of all IP addresses and/or subnets (in CIDR notation) 3 | # that SHOULD NOT be required to verify themselves using TOTP when 4 | # authenticating. All other hosts in this list will required to verify with 5 | # TOTP. 6 | # 7 | # **If both bypass and enforce lists are provided, the enforce list takes 8 | # priority and this property is effectively ignored.** 9 | # 10 | # This property is optional. By default, verification will be required for all 11 | # users regardless of their IP address (TOTP is not bypassed for any 12 | # addresses). 13 | # 14 | totp-bypass-hosts: 10.10.0.0/8, 10.11.0.2 15 | 16 | # 17 | # A comma-separated list of all IP addresses and/or subnets (in CIDR notation) 18 | # that SHOULD be required to verify themselves using TOTP when authenticating. 19 | # All other hosts will not be required to verify with TOTP. 20 | # 21 | # **If both bypass and enforce lists are provided, the enforce list takes 22 | # priority and the bypass list is effectively ignored.** 23 | # 24 | # This property is optional. By default, verification will be required for all 25 | # users regardless of their IP address (TOTP is enforced for all addresses). 26 | # 27 | totp-enforce-hosts: 10.12.0.0/8 28 | -------------------------------------------------------------------------------- /src/include/duo-bypass-enforce.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # A comma-separated list of all IP addresses and/or subnets (in CIDR notation) 3 | # that SHOULD NOT be required to verify themselves with Duo when 4 | # authenticating. All other hosts in this list will required to verify against 5 | # Duo. 6 | # 7 | # **If both bypass and enforce lists are provided, the enforce list takes 8 | # priority and this property is effectively ignored.** 9 | # 10 | # This property is optional. By default, verification against Duo will be 11 | # required for all users regardless of their IP address (Duo is not bypassed 12 | # for any addresses). 13 | # 14 | duo-bypass-hosts: 10.10.0.0/8, 10.11.0.2 15 | 16 | # 17 | # A comma-separated list of all IP addresses and/or subnets (in CIDR notation) 18 | # that SHOULD be required to verify themselves with Duo when authenticating. 19 | # All other hosts will not be required to verify against Duo. 20 | # 21 | # **If both bypass and enforce lists are provided, the enforce list takes 22 | # priority and the bypass list is effectively ignored.** 23 | # 24 | # This property is optional. By default, verification against Duo will be 25 | # required for all users regardless of their IP address (Duo is enforced for 26 | # all addresses). 27 | # 28 | duo-enforce-hosts: 10.12.0.0/8 29 | -------------------------------------------------------------------------------- /src/security.md: -------------------------------------------------------------------------------- 1 | Securing a Guacamole install 2 | ============================ 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | SSL termination 8 | Blocking brute-force attacks 9 | ::: 10 | 11 | Secure deployment of Guacamole requires that all communication between users 12 | and Guacamole are encrypted using SSL/TLS. We generally recommend using a 13 | reverse proxy like Apache HTTPD or Nginx and configuring that proxy to provide 14 | SSL termination: 15 | 16 | [](reverse-proxy) 17 | : SSL termination provides proper encryption in front of Guacamole without 18 | tying the configuration of SSL to the servlet container (Tomcat). This 19 | provides greater flexibility while reducing the overhead that otherwise might 20 | be imposed by implementing SSL within Java. 21 | 22 | It is also highly recommended that you deploy some mechanism for brute-force 23 | attack prevention. This ensures that malicious users that repeatedly try to 24 | guess passwords will be automatically blocked: 25 | 26 | [](auth-ban) 27 | : Guacamole provides an extension that automatically recognizes repeated 28 | authentication failures and blocks further attempts from the same IP address. 29 | 30 | This is enabled by default in the `guacamole/guacamole` Docker image. 31 | 32 | The third-party open source project, [fail2ban](https://github.com/fail2ban/fail2ban), 33 | is also an excellent option for blocking brute-force authentication attempts, 34 | and has the benefit of performing its blocking at the firewall level. 35 | 36 | -------------------------------------------------------------------------------- /src/sso.md: -------------------------------------------------------------------------------- 1 | Authenticating with Guacamole using single sign-on 2 | ================================================== 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | CAS 8 | OpenID Connect 9 | SAML 10 | Smart cards / Certificates 11 | ::: 12 | 13 | Single sign-on alows you to leverage a third-party authentication service that 14 | can be shared by multiple applications, including Guacamole. This has the 15 | benefit of streamlining and centralizing authentication when users would 16 | otherwise need to maintain a distinct set of credentials for each application. 17 | Guacamole supports the following single sign-on methods: 18 | 19 | [CAS](cas-auth) 20 | : An open source single sign-on application that implements its own 21 | authentication protocol. 22 | 23 | [OpenID Connect](openid-auth) and [SAML](saml-auth) 24 | : Widely supported open standards for single sign-on. It is extremely common 25 | for commercial identity providers to support at least one of these standards. 26 | 27 | [Smart cards / Certificates](ssl-auth) 28 | : User identification using certificates that are installed on the user's 29 | machine or within smart cards presented by the user. The user identity is 30 | derived from the content of the certificate presented, if valid. This 31 | mechanism makes use of SSL/TLS client authentication via a [reverse 32 | proxy](reverse-proxy). 33 | 34 | :::{hint} 35 | OpenID Connect is commonly confused with "OAuth", with the term "OAuth" 36 | sometimes used incorrectly to refer to OpenID Connect. 37 | ::: 38 | -------------------------------------------------------------------------------- /tutorials/guacamole-auth-tutorial/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | org.apache.guacamole 8 | guacamole-auth-tutorial 9 | jar 10 | 1.6.0 11 | guacamole-auth-tutorial 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.3 25 | 26 | 1.8 27 | 1.8 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | org.apache.guacamole 39 | guacamole-ext 40 | 1.6.0 41 | provided 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/generate-j2-data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # 20 | 21 | # 22 | # generate-j2-data.py - Generates a JSON file containing all substitutions 23 | # defined by myst_substitutions within "conf.py", printing the result to 24 | # STDOUT. This data can be consumed by jinjanator/j2cli to provide context to 25 | # templates and avoid the complexity of using MyST to perform the substitions 26 | # later (which would require double-escaping Jinja expressions). 27 | # 28 | 29 | import json 30 | 31 | # Pull in the contents of the Sphinx conf.py 32 | exec(compile(open('src/conf.py', 'rb').read(), 'src/conf.py', 'exec')) 33 | 34 | # Dump all MyST Parser substitutions as JSON for consumption by 35 | # jinjanator/j2cli 36 | print(json.dumps(myst_substitutions)) 37 | -------------------------------------------------------------------------------- /tutorials/guacamole-tutorial/src/main/java/org/apache/guacamole/net/example/TutorialGuacamoleTunnelServlet.java: -------------------------------------------------------------------------------- 1 | package org.apache.guacamole.net.example; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import org.apache.guacamole.GuacamoleException; 5 | import org.apache.guacamole.net.GuacamoleSocket; 6 | import org.apache.guacamole.net.GuacamoleTunnel; 7 | import org.apache.guacamole.net.InetGuacamoleSocket; 8 | import org.apache.guacamole.net.SimpleGuacamoleTunnel; 9 | import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket; 10 | import org.apache.guacamole.protocol.GuacamoleConfiguration; 11 | import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet; 12 | 13 | public class TutorialGuacamoleTunnelServlet 14 | extends GuacamoleHTTPTunnelServlet { 15 | 16 | @Override 17 | protected GuacamoleTunnel doConnect(HttpServletRequest request) 18 | throws GuacamoleException { 19 | 20 | // Create our configuration 21 | GuacamoleConfiguration config = new GuacamoleConfiguration(); 22 | config.setProtocol("vnc"); 23 | config.setParameter("hostname", "localhost"); 24 | config.setParameter("port", "5901"); 25 | config.setParameter("password", "potato"); 26 | 27 | // Connect to guacd - everything is hard-coded here. 28 | GuacamoleSocket socket = new ConfiguredGuacamoleSocket( 29 | new InetGuacamoleSocket("localhost", 4822), 30 | config 31 | ); 32 | 33 | // Return a new tunnel which uses the connected socket 34 | return new SimpleGuacamoleTunnel(socket); 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/header-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | HTTP header authentication 5 | ========================== 6 | 7 | Guacamole supports delegating authentication to an arbitrary external service, 8 | relying on the presence of an HTTP header which contains the username of the 9 | authenticated user. This authentication method must be layered on top of some 10 | other authentication extension, such as those available from the main project 11 | website, in order to provide access to actual connections. 12 | 13 | :::{danger} 14 | **All external requests must be properly sanitized if this extension is used.** 15 | The chosen HTTP header must be stripped from untrusted requests, such that the 16 | authentication service is the _only_ possible source of that header. 17 | 18 | **If such sanitization is not performed, it will be trivial for malicious users 19 | to add this header manually, and thus gain unrestricted access.** 20 | ::: 21 | 22 | ```{include} include/warn-config-changes.md 23 | ``` 24 | 25 | (header-downloading)= 26 | 27 | Installing/Enabling HTTP header authentication 28 | ---------------------------------------------- 29 | 30 | {{ ext.install('HTTP_AUTH', 'guacamole-auth-header') }} 31 | 32 | (guac-header-config)= 33 | 34 | Configuration (optional) 35 | ------------------------ 36 | 37 | {% call ext.config('http-auth') %} 38 | {{ ext.nothingRequired() }} 39 | {% endcall %} 40 | 41 | (completing-header-install)= 42 | 43 | Completing installation 44 | ----------------------- 45 | 46 | ```{include} include/ext-completing.md 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /src/include/jdbc-concurrent-use.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The maximum number of concurrent connections to allow to any one connection, 3 | # regardless of which user is accessing the connection, where zero denotes 4 | # unlimited. By default, overall concurrent access to individual connections is 5 | # not limited. 6 | # 7 | somesql-default-max-connections: 0 8 | 9 | # 10 | # The maximum number of concurrent connections to allow to any one connection 11 | # group, regardless of which user is accessing the connection group, where zero 12 | # denotes unlimited. By default, overall concurrent access to individual 13 | # connection groups is not limited. 14 | # 15 | somesql-default-max-group-connections: 0 16 | 17 | # 18 | # The maximum number of concurrent connections to allow to any one connection 19 | # by the same user, where zero denotes unlimited. By default, per-user 20 | # concurrent access to individual connections is not limited. 21 | # 22 | somesql-default-max-connections-per-user: 0 23 | 24 | # 25 | # The maximum number of concurrent connections to allow to any one connection 26 | # group by the same user, where zero denotes unlimited. By default, per-user 27 | # concurrent access to connection groups is limited to one user. 28 | # 29 | somesql-default-max-group-connections-per-user: 1 30 | 31 | # 32 | # The maximum number of concurrent connections to allow overall, regardless of 33 | # which connection or connection group is used and regardless of which user is 34 | # accessing the connection/group, where zero denotes unlimited. By default, 35 | # overall concurrent access to Guacamole is not limited. 36 | # 37 | somesql-absolute-max-connections: 0 38 | -------------------------------------------------------------------------------- /src/jdbc-auth.md: -------------------------------------------------------------------------------- 1 | Database authentication 2 | ======================= 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | MariaDB / MySQL 8 | PostgreSQL 9 | SQL Server 10 | ::: 11 | 12 | Guacamole supports providing authentication and storage leveraging any of the 13 | following databases: 14 | 15 | * [MariaDB or MySQL](mysql-auth) 16 | * [PostgreSQL](postgresql-auth) 17 | * [SQL Server](sqlserver-auth) 18 | 19 | Using a database for authentication/storage is _highly recommended_ and 20 | provides additional features, such as the ability to use load-balancing groups, 21 | connection sharing links, and a convenient, web-based administrative interface. 22 | 23 | Using a database alongside other authentication methods 24 | ------------------------------------------------------- 25 | 26 | While most authentication extensions function independently, the database 27 | authentication can act in a subordinate role, allowing users and user groups 28 | from other authentication extensions to be associated with connections within 29 | the database. 30 | 31 | **Users and groups are considered identical to those within the database if they 32 | have the same names** (with the nature of that comparison dictated by [the 33 | application-wide case sensitivity setting](initial-setup)), and the 34 | authentication result of another extension will be trusted if it succeeds. A 35 | user with an account under multiple systems will thus be able to see data from 36 | each system after successfully logging in. 37 | 38 | :::{hint} 39 | For more information on using the database authentication alongside other 40 | mechanisms, see [](ldap-and-database) within [](ldap-auth). 41 | ::: 42 | 43 | -------------------------------------------------------------------------------- /src/include/ext-completing.md: -------------------------------------------------------------------------------- 1 | ::::{tab} {{ native_tab_title }} 2 | Guacamole will only reread its configuration and load newly-installed 3 | extensions during startup, so Tomcat will need to be restarted before these 4 | changes can take effect. Restart Tomcat and give the new functionality a try. 5 | 6 | *You do not need to restart guacd*. 7 | 8 | :::{hint} 9 | If Guacamole does not come back online after restarting Tomcat, **check the 10 | logs**. Configuration problems may prevent Guacamole from starting up, and any 11 | such errors will be recorded in Tomcat's logs. 12 | ::: 13 | :::: 14 | 15 | ::::{tab} {{ container_tab_title }} 16 | The environment variables that configure the behavior of Docker can only be set 17 | at the time the Docker container is created. To apply these configuration 18 | changes, you will need to recreate the container. 19 | 20 | If your Guacamole container was deployed using Docker Compose: 21 | : Simply making the desired changes to your `docker-compose.yml` and running 22 | `docker compose up` is sufficient. Docker Compose will automatically 23 | recognize that the environment variables of the container have changed and 24 | recreate it. 25 | 26 | If your Guacamole container was deployed manually (using `docker run`): 27 | : You wll need to manually use `docker rm` to remove the old container and then 28 | manually recreate it with `docker run` and the new environment variables. 29 | 30 | :::{hint} 31 | If Guacamole does not come back online after recreating the container, **check 32 | the Docker logs**. Configuration problems may prevent Guacamole from starting 33 | up, and any such errors will be recorded in the Docker logs for the Guacamole 34 | container. 35 | ::: 36 | :::: 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | # 21 | # Dockerfile for guacamole-manual 22 | # 23 | # See the README for more information on how to use this file. 24 | 25 | # Set this build arg to any of the available version labels for the httpd image 26 | ARG HTTPD_VERSION=2.4 27 | 28 | # Perform the build itself using Python+Sphinx 29 | FROM sphinxdoc/sphinx AS builder 30 | RUN pip3 install \ 31 | Jinja2 \ 32 | myst-parser \ 33 | sphinx-book-theme \ 34 | sphinx-copybutton \ 35 | sphinx-inline-tabs 36 | 37 | # Set the working directory for the remainder of the build process 38 | WORKDIR /manual 39 | 40 | # Copy the manual source into the working directory and build it 41 | COPY ./ ./ 42 | RUN make 43 | 44 | # For the runtime image, use the official Apache httpd image 45 | FROM httpd:${HTTPD_VERSION} 46 | 47 | # Copy any HTML generated by the build into httpd's document root 48 | COPY --from=builder /manual/build/html/ /usr/local/apache2/htdocs/ 49 | 50 | -------------------------------------------------------------------------------- /tutorials/guacamole-auth-tutorial/src/main/java/org/apache/guacamole/auth/TutorialGuacamoleProperties.java: -------------------------------------------------------------------------------- 1 | package org.apache.guacamole.auth; 2 | 3 | import org.apache.guacamole.properties.StringGuacamoleProperty; 4 | 5 | /** 6 | * Utility class containing all properties used by the custom authentication 7 | * tutorial. The properties defined here must be specified within 8 | * guacamole.properties to configure the tutorial authentication provider. 9 | */ 10 | public class TutorialGuacamoleProperties { 11 | 12 | /** 13 | * This class should not be instantiated. 14 | */ 15 | private TutorialGuacamoleProperties() {} 16 | 17 | /** 18 | * The only user to allow. 19 | */ 20 | public static final StringGuacamoleProperty TUTORIAL_USER = 21 | new StringGuacamoleProperty() { 22 | 23 | @Override 24 | public String getName() { return "tutorial-user"; } 25 | 26 | }; 27 | 28 | /** 29 | * The password required for the specified user. 30 | */ 31 | public static final StringGuacamoleProperty TUTORIAL_PASSWORD = 32 | new StringGuacamoleProperty() { 33 | 34 | @Override 35 | public String getName() { return "tutorial-password"; } 36 | 37 | }; 38 | 39 | 40 | /** 41 | * The protocol to use when connecting. 42 | */ 43 | public static final StringGuacamoleProperty TUTORIAL_PROTOCOL = 44 | new StringGuacamoleProperty() { 45 | 46 | @Override 47 | public String getName() { return "tutorial-protocol"; } 48 | 49 | }; 50 | 51 | 52 | /** 53 | * All parameters associated with the connection, as a comma-delimited 54 | * list of name="value" 55 | */ 56 | public static final StringGuacamoleProperty TUTORIAL_PARAMETERS = 57 | new StringGuacamoleProperty() { 58 | 59 | @Override 60 | public String getName() { return "tutorial-parameters"; } 61 | 62 | }; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/include/cas-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # If using CAS ClearPass to pass the SSO password to Guacamole, this parameter 3 | # specifies the private key file to use to decrypt the password. See [the section 4 | # on ClearPass](cas-clearpass) below. 5 | # 6 | cas-clearpass-key: /path/to/private-key.pem 7 | 8 | # 9 | # The CAS attribute that determines group membership, typically "memberOf". 10 | # This parameter is only required if using CAS to define user group memberships. 11 | # If omitted, groups aren't retrieved from CAS, and all other group-related 12 | # properties for CAS are ignored. 13 | # 14 | cas-group-attribute: memberOf 15 | 16 | # 17 | # The format that CAS will use for its group names. Possible values are 18 | # `plain`, for groups that are simple text names, or `ldap`, for groups that are 19 | # represented as LDAP DNs. If set to `ldap`, group names are always determined 20 | # from the last (leftmost) attribute of the DN. If omitted, `plain` is used by 21 | # default. 22 | # 23 | # This property has no effect if cas-group-attribute is not set. 24 | # 25 | cas-group-format: plain 26 | 27 | # 28 | # The base DN to require for LDAP-formatted CAS groups. If specified, only CAS 29 | # groups beneath this DN will be included, and all other CAS groups will be 30 | # ignored. 31 | # 32 | # This property has no effect if cas-group-format is not `ldap`. 33 | # 34 | cas-group-ldap-base-dn: ou=groups,dc=example,dc=net 35 | 36 | # 37 | # The LDAP attribute to require for LDAP-formatted CAS groups. If specified, 38 | # only CAS groups that use this attribute for the name of the group will be 39 | # included. Note that LDAP group names are *always determined from the last 40 | # (leftmost) attribute of the DN*. Specifying this property will only have the 41 | # effect of ignoring any groups that do not use the specified attribute to 42 | # represent the group name. 43 | # 44 | # This property has no effect if cas-group-format is not `ldap`. 45 | # 46 | cas-group-ldap-attribute: cn 47 | -------------------------------------------------------------------------------- /src/auth-ban.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Securing Guacamole against brute-force attacks 5 | ============================================== 6 | 7 | Version 1.6.0 of Guacamole introduces an extension that allows you to detect 8 | and block brute-force login attacks. When installed, the extension will track 9 | the IP addresses of failed authentication attempts. Once the threshold of 10 | failed logins is reached for a particular IP address, further logins from that 11 | address will be temporarily banned: 12 | 13 | ![](images/too-many-failed-logins.png) 14 | 15 | ```{include} include/warn-config-changes.md 16 | ``` 17 | 18 | Installing/Enabling brute-force authentication detection 19 | -------------------------------------------------------- 20 | 21 | {{ ext.install('BAN', 'guacamole-auth-ban', dockerDefault=True) }} 22 | 23 | (auth-ban-config)= 24 | 25 | Configuration (optional) 26 | ------------------------ 27 | 28 | {% call ext.config('ban') %} 29 | {{ ext.nothingRequired() }} 30 | 31 | :::{list-table} Default brute-force authentication detection threshold and limits 32 | :stub-columns: 1 33 | * - Maximum invalid attempts (authentication failures) 34 | - 5 35 | * - Address ban duration 36 | - 300 (5 minutes) 37 | * - Maximum addresses tracked 38 | - 10485670 39 | ::: 40 | {% endcall %} 41 | 42 | :::{important} 43 | Because the extension tracks authentication failures based on the client 44 | IP address, it is important to make sure that Guacamole is receiving the 45 | correct IP addresses for the clients. This is particularly noteworthy 46 | when Guacamole is behind a reverse proxy. See the manual page on 47 | [proxying Guacamole](reverse-proxy) for more details on configuring 48 | Guacamole behind a proxy. 49 | ::: 50 | 51 | (completing-auth-ban-install)= 52 | 53 | Completing installation 54 | ----------------------- 55 | 56 | ```{include} include/ext-completing.md 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /src/installing-guacamole.md: -------------------------------------------------------------------------------- 1 | Installing Guacamole 2 | ==================== 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | Native installation 8 | Containerized (Docker) installation 9 | ::: 10 | 11 | There are two supported ways of installing Guacamole: 12 | 13 | [Installing Guacamole natively](guacamole-native) 14 | : This involves installing a servlet container like [Apache Tomcat](https://tomcat.apache.org/), 15 | deploying the Guacamole web application beneath Tomcat, and building at least 16 | guacamole-server from source. 17 | 18 | [Installing Guacamole using Docker containers](guacamole-docker) 19 | : This involves running a pair of Docker containers using the provided 20 | `guacamole/guacamole` and `guacamole/guacd` Docker images. 21 | 22 | A typical, standard installation of Guacamole is configured to [use a database 23 | for storage and/or authentication](jdbc-auth). This provides the most features 24 | and flexibility, and enables a convenient [web-based administrative 25 | interface](administration). 26 | 27 | Other, more complex authentication methods which use [LDAP](ldap-auth), various 28 | [multi-factor authentication](mfa) and [single sign-on options](sso), etc. are 29 | discussed in a separate, dedicated chapters. 30 | 31 | :::{note} 32 | There is also a "default" authentication method that reads all users and 33 | connections from a single file called [`user-mapping.xml`](user-mapping). This 34 | simpler, built-in authentication method is not intended for production use, but 35 | rather to serve as a relatively-easy means of verifying that Guacamole has been 36 | properly set up. 37 | 38 | It's reasonable to use this XML-based method for small deployments that don't 39 | need the full feature set of Guacamole, but **the goal should always be to 40 | migrate to a production-ready mechanism like [using a database](jdbc-auth)**. 41 | We do not recommend using `user-mapping.xml` for production or anything 42 | public-facing. 43 | ::: 44 | 45 | -------------------------------------------------------------------------------- /src/include/duo.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The hostname of the Duo API endpoint to be used to verify user identities. 3 | # This will usually be in the form {samp}`api-{XXXXXXXX}.duosecurity.com`, 4 | # where {samp}`{XXXXXXXX}` is some arbitrary alphanumeric value assigned by 5 | # Duo. This value will have been generated by Duo when you added Guacamole as 6 | # a "Web SDK" application, and can be found within the application details in 7 | # the "API hostname" field. *This value is required.* 8 | # 9 | duo-api-hostname: api-XXXXXXXX.duosecurity.com 10 | 11 | # 12 | # The unique client ID provided for Guacamole by Duo. This value will 13 | # have been generated by Duo when you added Guacamole as a "Web SDK" 14 | # application, and can be found within the application details in the 15 | # "Client ID" field. *This value is required.* 16 | # 17 | # This value was formerly known as the "integration key" in older versions of 18 | # Duo's "Web SDK" and was configured with the `duo-integration-key` property 19 | # in older versions of Guacamole. 20 | # 21 | duo-client-id: XXXXXXXXXXXXXXXXXXXX 22 | 23 | # 24 | # The shared secret provided for Guacamole by Duo. This value will have been 25 | # generated by Duo when you added Guacamole as a "Web SDK" application, and can 26 | # be found within the application details in the "Client secret" field. *This 27 | # value is required.* 28 | # 29 | # This value was formerly known as the "secret key" in older versions of Duo's 30 | # "Web SDK" and was configured with the `duo-secret-key` property in older 31 | # versions of Guacamole. 32 | # 33 | duo-client-secret: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 34 | 35 | # 36 | # The URI that should be submitted to the Duo service such that they can 37 | # redirect the authenticated user back to Guacamole after the authentication 38 | # process is complete. This must be the full URL that a user would enter into 39 | # their browser to access Guacamole. *This value is required.* 40 | # 41 | duo-redirect-uri: https://myguac.example.net 42 | -------------------------------------------------------------------------------- /src/include/openid-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The claim type within any valid JWT that contains the authenticated user's 3 | # username. By default, the "`email`" claim type is used. 4 | # 5 | openid-username-claim-type: email 6 | 7 | # 8 | # The claim type within any valid JWT that contains the list of groups of which 9 | # the authenticated user is a member. By default, the "`groups`" claim type is 10 | # used. 11 | # 12 | openid-groups-claim-type: groups 13 | 14 | # 15 | # The list of claims, separated by commas, that should be extracted from the 16 | # JWT token and exposed as `OIDC_` attributes to use in connections. Empty by 17 | # default. 18 | # 19 | openid-attributes-claim-type: email, name 20 | 21 | # 22 | # The space-separated list of OpenID scopes to request. OpenID scopes determine 23 | # the information returned within the OpenID token, and thus affect what values 24 | # can be used as an authenticated user's username. To be compliant with 25 | # OpenID, at least "`openid profile`" must be requested. By default, "`openid 26 | # email profile`" is used. 27 | # 28 | openid-scope: openid email profile 29 | 30 | # 31 | # The amount of clock skew tolerated for timestamp comparisons between the 32 | # Guacamole server and OpenID service clocks, in seconds. By default, clock 33 | # skew of up to 30 seconds is tolerated. 34 | # 35 | openid-allowed-clock-skew: 30 36 | 37 | # 38 | # The maximum amount of time that an OpenID token should remain valid, in 39 | # minutes. By default, each OpenID token remains valid for 300 minutes (5 40 | # hours). 41 | # 42 | openid-max-token-validity: 300 43 | 44 | # 45 | # The maximum amount of time that a nonce generated by the Guacamole server 46 | # should remain valid, in minutes. As each OpenID request has a unique nonce 47 | # value, this imposes an upper limit on the amount of time any particular 48 | # OpenID request can result in successful authentication within Guacamole. By 49 | # default, each generated nonce expires after 10 minutes. 50 | # 51 | openid-max-nonce-validity: 10 52 | -------------------------------------------------------------------------------- /src/include/sqlserver-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The hostname or IP address of the server hosting your database. If not 3 | # specified, "localhost" will be used by default. 4 | # 5 | sqlserver-hostname: localhost 6 | 7 | # 8 | # The port number of the SQL Server database to connect to. If not specified, 9 | # the standard SQL Server port 1433 will be used. 10 | # 11 | sqlserver-port: 1433 12 | 13 | # 14 | # The specific TDS-compatible JDBC driver to expect to have been installed. 15 | # Multiple JDBC drivers are available that support SQL Server. If not using the 16 | # Microsoft driver, this property must be specified to define the driver that 17 | # will be used. Possible values are: 18 | # 19 | # microsoft2005 20 | # : The current [Microsoft JDBC Driver for SQL Server](https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server), 21 | # supporting SQL Server 2005 and later. This is the default. 22 | # 23 | # microsoft 24 | # : The legacy Microsoft driver for SQL Server 2000. 25 | # 26 | # jtds 27 | # : The open source [jTDS](http://jtds.sourceforge.net/) driver. 28 | # 29 | # datadirect 30 | # : [Progress DataDirect’s JDBC Driver for SQL Server](https://www.progress.com/jdbc/microsoft-sql-server). 31 | # 32 | sqlserver-driver: microsoft2005 33 | 34 | # 35 | # The instance name that the SQL Server driver should attempt to connect to, if 36 | # not the default SQL Server instance. This instance name is configured during 37 | # the SQL Server installation. This property is optional, and most installations 38 | # should work without the need to specify an instance name. 39 | # 40 | sqlserver-instance: MSSQLSERVER 41 | 42 | # 43 | # Controls how many objects may be retrieved from the database in a single 44 | # query. If more objects than this number are requested, retrieval of those 45 | # objects will be automatically and transparently split across multiple 46 | # queries. 47 | # 48 | # By default, SQL Server queries will retrieve no more than 500 objects. 49 | # 50 | sqlserver-batch-size: 500 51 | -------------------------------------------------------------------------------- /tutorials/guacamole-tutorial/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Guacamole Tutorial 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 |
16 | 17 | 18 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/external-auth.md: -------------------------------------------------------------------------------- 1 | External authentication 2 | ======================= 3 | 4 | :::{toctree} 5 | :hidden: 6 | 7 | Encrypted, signed JSON 8 | HTTP header 9 | ::: 10 | 11 | :::{important} 12 | **Support for [standard single sign-on methods (SSO)](sso) is also available.** 13 | If simply looking to integrate Guacamole with an established authentication 14 | system that provides SSO, first check whether Guacamole already supports that 15 | SSO method. 16 | ::: 17 | 18 | For cases where Guacamole is embedded within an external application that 19 | performs its own authentication, extensions are provided that allow Guacamole 20 | to easily consume the authentication result of that external application: 21 | 22 | [HTTP header authentication](header-auth) 23 | : Allows your external application to assert the identity of the Guacamole user 24 | by adding an HTTP header to authentication requests sent to Guacamole. The 25 | user's username is read from the HTTP header. 26 | 27 | The details of any underlying connections must come from anoher extension 28 | that supports delegation of authentication, like [any of the supported 29 | databases](jdbc-auth). 30 | 31 | [Encrypted, signed JSON authentication](json-auth) 32 | : Allows your external application to supply both identity and connection 33 | information within an encrypted, signed block of JSON. Encryption ensures 34 | that the JSON can be safely included where it may be visible to users, while 35 | signing ensures the JSON cannot be manipulated. 36 | 37 | Your application must be modified to sign and encrypt JSON as documented. 38 | 39 | :::{hint} 40 | For more complex cases, you may wish to look into [developing your own 41 | Guacamole extension using the extension API ("guacamole-ext")](guacamole-ext). 42 | 43 | The extension API is quite flexible. All authentication and authorization 44 | methods supported by Guacamole out-of-the-box are actually provided through 45 | [extensions written using this publicly documented API](https://github.com/apache/guacamole-client/tree/main/extensions). 46 | ::: 47 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | 2 | ------------------------------------------------------------ 3 | Contributing to Apache Guacamole 4 | ------------------------------------------------------------ 5 | 6 | Thank you for contributing to the Apache Guacamole project! 7 | 8 | There are certain procedures that must be followed for all contributions. These 9 | procedures are necessary to allow us to allocate resources for reviewing and 10 | testing your contribution, as well as communicate effectively with you during 11 | the review process. 12 | 13 | 1) Create an issue in our JIRA 14 | 15 | All changes to Guacamole must have corresponding issues in JIRA so the 16 | change can be properly tracked: 17 | 18 | https://issues.apache.org/jira/browse/GUACAMOLE/ 19 | 20 | If you do not already have an account on the Apache Software Foundation's 21 | JIRA, you will need to create one before creating your new issue. 22 | 23 | 2) Make and test your changes locally 24 | 25 | The Guacamole source is maintained in git repositories hosted on GitHub: 26 | 27 | https://github.com/apache/guacamole-client 28 | https://github.com/apache/guacamole-manual 29 | https://github.com/apache/guacamole-server 30 | https://github.com/apache/guacamole-website 31 | 32 | To make your changes, fork the applicable repositories and make commits 33 | to a topic branch in your fork. Commits should be made in logical units 34 | and must reference the JIRA issue number: 35 | 36 | $ git commit -m "GUACAMOLE-123: High-level message describing the changes." 37 | 38 | Avoid commits which cover multiple, distinct goals that could (and should) 39 | be handled separately. 40 | 41 | If you do not already have an account on GitHub, you will need to create 42 | one before making your changes. 43 | 44 | 3) Submit your changes via a pull request on GitHub 45 | 46 | Once your changes are ready, submit them by creating a pull request for 47 | the corresponding topic branch you created when you began working on your 48 | changes. 49 | 50 | The Guacamole team will then review your changes and, if they pass review, 51 | your changes will be merged. 52 | 53 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | Apache Guacamole Manual 2 | ======================= 3 | 4 | :::{note} 5 | Licensed to the Apache Software Foundation (ASF) under one or more contributor 6 | license agreements. See the [NOTICE] file distributed with this work for 7 | additional information regarding copyright ownership. The ASF licenses this 8 | file to you under the Apache License, Version 2.0 (the "License"); you may not 9 | use this file except in compliance with the License. You may obtain a copy of 10 | the License at: 11 | 12 | 13 | 14 | Unless required by applicable law or agreed to in writing, software distributed 15 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 16 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 17 | specific language governing permissions and limitations under the License. 18 | 19 | [NOTICE]: https://raw.githubusercontent.com/apache/guacamole-manual/master/NOTICE 20 | ::: 21 | 22 | :::{toctree} 23 | :caption: Getting Started 24 | :name: getting-started 25 | :maxdepth: 1 26 | 27 | introduction 28 | guacamole-architecture 29 | installing-guacamole 30 | Database setup 31 | security 32 | ::: 33 | 34 | :::{toctree} 35 | :caption: Using Guacamole 36 | :name: users-guide 37 | :maxdepth: 1 38 | 39 | Configuration 40 | General usage 41 | Administration 42 | troubleshooting 43 | ::: 44 | 45 | :::{toctree} 46 | :caption: Extensions 47 | :name: extensions 48 | :maxdepth: 1 49 | 50 | Active Directory / LDAP 51 | mfa 52 | Single sign-on 53 | vault 54 | external-auth 55 | RADIUS 56 | Ad-hoc connections 57 | Login / Connection restrictions 58 | Session recording player 59 | ::: 60 | 61 | :::{toctree} 62 | :caption: Developer's Guide 63 | :name: developers-guide 64 | :maxdepth: 1 65 | 66 | guacamole-protocol 67 | libguac 68 | guacamole-common 69 | guacamole-common-js 70 | guacamole-ext 71 | custom-protocols 72 | custom-auth 73 | event-listeners 74 | writing-you-own-guacamole-app 75 | ::: 76 | 77 | :::{toctree} 78 | :caption: Appendices 79 | :name: appendices 80 | :maxdepth: 1 81 | 82 | protocol-reference 83 | jdbc-auth-schema 84 | ::: 85 | 86 | -------------------------------------------------------------------------------- /src/saml-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Using SAML for single sign-on 5 | ============================= 6 | 7 | SAML is a widely implemented and used Single Sign On (SSO) provider that allows 8 | applications and services to authenticate in a standard way, and brokers those 9 | authentication requests to one or more back-end authentication providers. The 10 | SAML authentication extension allows Guacamole to redirect to a SAML Identity 11 | Provider (IdP) for authentication and user services. This module does not 12 | provide any capability for storing or retrieving connections, and must be 13 | layered with other authentication extensions that provide connection 14 | management. 15 | 16 | ```{include} include/warn-config-changes.md 17 | ``` 18 | 19 | (saml-downloading)= 20 | 21 | Installing/Enabling the SAML authentication extension 22 | ----------------------------------------------------- 23 | 24 | {{ ext.install('SAML', 'guacamole-auth-sso', 'saml/guacamole-auth-sso-saml') }} 25 | 26 | (guac-saml-config)= 27 | 28 | Configuration 29 | ------------- 30 | 31 | {% call ext.config('saml') %} 32 | The SAML authentication extension provides several configuration properties to 33 | set it up to talk to the IdP. The SAML IdP also must be configured with 34 | Guacamole as a Service Provider (SP). Configuration of the SAML IdP is beyond 35 | the scope of this document, and will vary widely based on the IdP in use. 36 | {% endcall %} 37 | 38 | ### Controlling login behavior 39 | 40 | ```{include} include/sso-login-behavior.md 41 | ``` 42 | 43 | #### Automatically redirecting all unauthenticated users 44 | 45 | To ensure users are redirected to the SAML identity provider immediately 46 | (without a Guacamole login screen), ensure the SAML extension has priority over 47 | all others: 48 | 49 | ``` 50 | extension-priority: saml 51 | ``` 52 | 53 | #### Presenting unauthenticated users with a login screen 54 | 55 | To ensure users are given a normal Guacamole login screen and have the option 56 | to log in with traditional credentials _or_ with SAML, ensure the SAML 57 | extension does not have priority: 58 | 59 | ``` 60 | extension-priority: *, saml 61 | ``` 62 | 63 | (completing-saml-install)= 64 | 65 | Completing installation 66 | ----------------------- 67 | 68 | ```{include} include/ext-completing.md 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /src/include/openid.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The authorization endpoint (URI) of the OpenID service. 3 | # 4 | # This value should be provided to you by the identity provider. For identity 5 | # providers that implement [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html), 6 | # this value can be retrieved from the `authorization_endpoint` property of the 7 | # JSON file hosted at {samp}`{https://identity-provider}/.well-known/openid-configuration`, where 8 | # `https://identity-provider` is the base URL of the identity provider. 9 | # 10 | openid-authorization-endpoint: https://identity-provider/auth 11 | 12 | # 13 | # The endpoint (URI) of the JWKS service which defines how received ID tokens 14 | # ([JSON Web Tokens](https://jwt.io/) or JWTs) shall be validated. 15 | # 16 | # This value should be provided to you by the identity provider. For 17 | # identity providers that implement [OpenID Connect 18 | # Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html), 19 | # this value can be retrieved from the `jwks_uri` property of the JSON 20 | # file hosted at 21 | # {samp}`{https://identity-provider}/.well-known/openid-configuration`, where 22 | # `https://identity-provider` is the base URL of the identity provider. 23 | # 24 | openid-jwks-endpoint: https://identity-provider/jwks 25 | 26 | # 27 | # The issuer to expect for all received ID tokens. 28 | # 29 | # This value should be provided to you by the identity provider. For 30 | # identity providers that implement [OpenID Connect 31 | # Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html), 32 | # this value can be retrieved from the `issuer` property of the JSON 33 | # file hosted at 34 | # {samp}`{https://identity-provider}/.well-known/openid-configuration`, where 35 | # `https://identity-provider` is the base URL of the identity provider. 36 | # 37 | openid-issuer: identity-provider 38 | 39 | # 40 | # The OpenID client ID which should be submitted to the OpenID service when 41 | # necessary. This value is typically provided to you by the OpenID service when 42 | # OpenID credentials are generated for your application. 43 | # 44 | openid-client-id: my-client-id 45 | 46 | # 47 | # The URI that should be submitted to the OpenID service such that they 48 | # can redirect the authenticated user back to Guacamole after the 49 | # authentication process is complete. This must be the full URL that a user 50 | # would enter into their browser to access Guacamole. 51 | # 52 | openid-redirect-uri: https://example.net/guacamole 53 | -------------------------------------------------------------------------------- /tutorials/guacamole-tutorial/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | org.apache.guacamole 8 | guacamole-tutorial 9 | war 10 | 1.6.0 11 | guacamole-tutorial 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.3 25 | 26 | 1.8 27 | 1.8 28 | 29 | 30 | 31 | 32 | 33 | org.apache.maven.plugins 34 | maven-war-plugin 35 | 2.6 36 | 37 | 38 | 39 | org.apache.guacamole 40 | guacamole-common-js 41 | zip 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | javax.servlet 56 | servlet-api 57 | 2.5 58 | provided 59 | 60 | 61 | 62 | 63 | org.apache.guacamole 64 | guacamole-common 65 | 1.6.0 66 | compile 67 | 68 | 69 | 70 | 71 | org.apache.guacamole 72 | guacamole-common-js 73 | 1.6.0 74 | zip 75 | runtime 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | .PHONY: all clean html 21 | 22 | # Whether build should be verbose (default to non-verbose) 23 | V?=0 24 | 25 | # All files which the build depends on 26 | J2_FILES=$(shell find "./src" -name "*.j2") 27 | OTHER_FILES=$(shell find ./src/ -name "__pycache__" -prune -o -type f -not -name "*.j2" -not -name "*.properties.in" -print) 28 | 29 | # Files that will ultimately be processed by Sphinx 30 | SPHINX_INPUT += $(J2_FILES:./src/%.j2=build/in/%) 31 | SPHINX_INPUT += $(OTHER_FILES:./src/%=build/in/%) 32 | 33 | # 34 | # If not explicitly overridden by setting V=1, define a series of macros that 35 | # hide the lengthy commands that are part of the build. These macros 36 | # intentionally mimic the clean output that we get in the guacamole-server 37 | # build via GNU Autotools and AM_SILENT_RULES(). 38 | # 39 | 40 | ifeq ($(V), 0) 41 | CP=@echo " CP " $@; 42 | JINJA=@echo " JINJA " $@; 43 | SPHINX=@echo " SPHINX " $@; 44 | SPHINX_FLAGS?=-q 45 | endif 46 | 47 | # Handy macro-like variable that automatically creates the parent directory for 48 | # the output file of a target 49 | ODIR=mkdir -p `dirname $@` && 50 | 51 | # 52 | # Build entire manual 53 | # 54 | 55 | all: html 56 | 57 | # 58 | # Clean build artifacts 59 | # 60 | 61 | clean: 62 | $(RM) -R build/ 63 | 64 | # 65 | # Copy any source files that don't require additional processing to build input 66 | # 67 | 68 | build/in/%: src/% 69 | $(CP) $(ODIR) cp $< $@ 70 | 71 | # 72 | # Automatic filtering of documentation using Jinja2 73 | # 74 | 75 | # NOTE: The complex usage of relative paths here is necessary to ensure 76 | # filenames included/imported within Jinja templates are always consistently 77 | # interpreted relative to the top-level document root, regardless of whether 78 | # the template is evaluated within "src/" or "build/in/". 79 | build/in/%: src/%.j2 src/conf.py 80 | $(JINJA) $(ODIR) cd src && ./filter-j2.py ../$< ../$@ 81 | 82 | # 83 | # HTML manual build 84 | # 85 | 86 | html: build/html/index.html 87 | 88 | build/html/index.html: $(SPHINX_INPUT) 89 | $(SPHINX) sphinx-build $(SPHINX_FLAGS) -b html -d build/doctrees build/in/ build/html 90 | 91 | -------------------------------------------------------------------------------- /src/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | from datetime import date 20 | import os, sys 21 | 22 | # 23 | # Project, version, and author information 24 | # 25 | 26 | project = u'Apache Guacamole' 27 | version = u'1.6.0' 28 | 29 | year = date.today().year 30 | author = u'The Apache Software Foundation' 31 | copyright = u'%s %s' % (year, author) 32 | 33 | # Include "ext" directory in search path for custom Sphinx extensions 34 | sys.path.insert(0, os.path.abspath('ext')) 35 | 36 | # 37 | # Global options 38 | # 39 | 40 | extensions = [ 41 | 'guac', 42 | 'myst_parser', 43 | 'sphinx_copybutton', 44 | 'sphinx.ext.ifconfig', 45 | 'sphinx.ext.extlinks', 46 | 'sphinx_inline_tabs' 47 | ] 48 | 49 | # Allow shorthand notation for JIRA issue links 50 | extlinks = { 51 | 'jira': ( 'https://issues.apache.org/jira/browse/%s', '%s') 52 | } 53 | 54 | templates_path = [ '_templates' ] 55 | 56 | # Do not parse files within include/ unless they are explicitly included with 57 | # the "include" directive 58 | exclude_patterns = [ 'include/**' ] 59 | 60 | # Do not highlight source unless a Pygments lexer name is explicitly provided 61 | highlight_language = 'none' 62 | 63 | # Exclude prompts and output lines from content copied using the copy button 64 | copybutton_prompt_text = "$ " 65 | copybutton_line_continuation_character = "\\" 66 | 67 | myst_enable_extensions = [ 68 | "colon_fence", 69 | "deflist", 70 | "replacements", 71 | "smartquotes", 72 | "substitution" 73 | ] 74 | 75 | myst_substitutions = { 76 | "version" : version, 77 | "native_tab_title" : "Native Webapp (Tomcat)", 78 | "container_tab_title" : "Container (Docker)" 79 | } 80 | 81 | # 82 | # HTML output options 83 | # 84 | 85 | html_theme = 'sphinx_book_theme' 86 | html_title = u'Apache Guacamole Manual v%s' % version 87 | 88 | html_static_path = [ '_static' ] 89 | html_css_files = [ 'gug.css' ] 90 | 91 | html_context = { 92 | 'copyright_year' : year 93 | } 94 | 95 | html_theme_options = { 96 | 97 | # The set of download links include the Markdown source, but without 98 | # substituting any included templates, making the download nearly useless 99 | 'use_download_button': False 100 | 101 | } 102 | -------------------------------------------------------------------------------- /tutorials/guacamole-auth-tutorial/src/main/java/org/apache/guacamole/auth/TutorialAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package org.apache.guacamole.auth; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import org.apache.guacamole.GuacamoleException; 6 | import org.apache.guacamole.GuacamoleServerException; 7 | import org.apache.guacamole.environment.Environment; 8 | import org.apache.guacamole.environment.LocalEnvironment; 9 | import org.apache.guacamole.net.auth.simple.SimpleAuthenticationProvider; 10 | import org.apache.guacamole.net.auth.Credentials; 11 | import org.apache.guacamole.protocol.GuacamoleConfiguration; 12 | 13 | /** 14 | * Authentication provider implementation intended to demonstrate basic use 15 | * of Guacamole's extension API. The credentials and connection information for 16 | * a single user are stored directly in guacamole.properties. 17 | */ 18 | public class TutorialAuthenticationProvider extends SimpleAuthenticationProvider { 19 | 20 | @Override 21 | public String getIdentifier() { 22 | return "tutorial"; 23 | } 24 | 25 | @Override 26 | public Map 27 | getAuthorizedConfigurations(Credentials credentials) 28 | throws GuacamoleException { 29 | 30 | // Get the Guacamole server environment 31 | Environment environment = LocalEnvironment.getInstance(); 32 | 33 | // Get username from guacamole.properties 34 | String username = environment.getRequiredProperty( 35 | TutorialGuacamoleProperties.TUTORIAL_USER 36 | ); 37 | 38 | // If wrong username, fail 39 | if (!username.equals(credentials.getUsername())) 40 | return null; 41 | 42 | // Get password from guacamole.properties 43 | String password = environment.getRequiredProperty( 44 | TutorialGuacamoleProperties.TUTORIAL_PASSWORD 45 | ); 46 | 47 | // If wrong password, fail 48 | if (!password.equals(credentials.getPassword())) 49 | return null; 50 | 51 | // Successful login. Return configurations. 52 | Map configs = 53 | new HashMap(); 54 | 55 | // Create new configuration 56 | GuacamoleConfiguration config = new GuacamoleConfiguration(); 57 | 58 | // Set protocol specified in properties 59 | config.setProtocol(environment.getRequiredProperty( 60 | TutorialGuacamoleProperties.TUTORIAL_PROTOCOL 61 | )); 62 | 63 | // Set all parameters, splitting at commas 64 | for (String parameterValue : environment.getRequiredProperty( 65 | TutorialGuacamoleProperties.TUTORIAL_PARAMETERS 66 | ).split(",\\s*")) { 67 | 68 | // Find the equals sign 69 | int equals = parameterValue.indexOf('='); 70 | if (equals == -1) 71 | throw new GuacamoleServerException("Required equals sign missing"); 72 | 73 | // Get name and value from parameter string 74 | String name = parameterValue.substring(0, equals); 75 | String value = parameterValue.substring(equals+1); 76 | 77 | // Set parameter as specified 78 | config.setParameter(name, value); 79 | 80 | } 81 | 82 | configs.put("Tutorial Connection", config); 83 | return configs; 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/cas-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Using CAS for single sign-on 5 | ============================ 6 | 7 | CAS is an open-source Single Sign On (SSO) provider that allows multiple 8 | applications and services to authenticate against it and brokers those 9 | authentication requests to a back-end authentication provider. This module 10 | allows Guacamole to redirect to CAS for authentication and user services. This 11 | module must be layered on top of other authentication extensions that provide 12 | connection information, as it only provides user authentication. 13 | 14 | ```{include} include/warn-config-changes.md 15 | ``` 16 | 17 | (cas-downloading)= 18 | 19 | Installing/Enabling the CAS authentication extension 20 | ---------------------------------------------------- 21 | 22 | {{ ext.install('CAS', 'guacamole-auth-sso', 'cas/guacamole-auth-sso-cas') }} 23 | 24 | Required configuration 25 | ---------------------- 26 | 27 | {% call ext.config('cas', required=True) %} 28 | Guacamole's CAS support requires specifying two {{ ext.properties() }} that 29 | describe the CAS authentication server and the Guacamole deployment. 30 | These {{ ext.properties() }} are *absolutely required in all cases*, as they 31 | dictate how Guacamole should connect to CAS and how CAS should redirect users 32 | back to Guacamole once their identity has been confirmed. 33 | {% endcall %} 34 | 35 | Additional configuration (optional) 36 | ----------------------------------- 37 | 38 | {% call ext.config('cas-optional') %} 39 | Additional optional {{ ext.properties() }} are available to control how 40 | CAS-related data is processed, including whether [CAS ClearPass](cas-clearpass) 41 | should be used and how user group memberships should be derived: 42 | {% endcall %} 43 | 44 | ### Controlling login behavior 45 | 46 | ```{include} include/sso-login-behavior.md 47 | ``` 48 | 49 | #### Automatically redirecting all unauthenticated users 50 | 51 | To ensure users are redirected to the CAS identity provider immediately 52 | (without a Guacamole login screen), ensure the CAS extension has priority over 53 | all others: 54 | 55 | ``` 56 | extension-priority: cas 57 | ``` 58 | 59 | #### Presenting unauthenticated users with a login screen 60 | 61 | To ensure users are given a normal Guacamole login screen and have the option 62 | to log in with traditional credentials _or_ with CAS, ensure the CAS extension 63 | does not have priority: 64 | 65 | ``` 66 | extension-priority: *, cas 67 | ``` 68 | 69 | (completing-cas-install)= 70 | 71 | Completing installation 72 | ----------------------- 73 | 74 | ```{include} include/ext-completing.md 75 | ``` 76 | 77 | (cas-clearpass)= 78 | 79 | Using CAS ClearPass 80 | ------------------- 81 | 82 | CAS has a function called ClearPass that can be used to cache the password used 83 | for SSO authentication and make that available to services at a later time. 84 | Configuring the CAS server for ClearPass is beyond the scope of this article - 85 | more information can be found on the Apereo CAS wiki at the following URL: 86 | . 87 | 88 | Once you have CAS configured for credential caching, you need to configure the 89 | service with a keypair for passing the credential securely. The public key gets 90 | installed on the CAS server, while the private key gets configured with the 91 | `cas-clearpass-key property`. The private key file needs to be in RSA PKCS8 92 | format. 93 | 94 | -------------------------------------------------------------------------------- /src/openid-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Using OpenID Connect for single sign-on 5 | ======================================= 6 | 7 | [OpenID Connect](http://openid.net/connect/) is a widely-adopted open standard 8 | for implementing single sign-on (SSO). [Not to be confused with 9 | OAuth](https://oauth.net/articles/authentication/), which is *not* an 10 | authentication protocol, OpenID Connect defines an authentication protocol in 11 | the form of a simple identity layer on top of OAuth 2.0. 12 | 13 | Guacamole's OpenID Connect support implements the "[implicit 14 | flow](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth)" 15 | of the OpenID Connect standard, and allows authentication of Guacamole users to 16 | be delegated to an identity provider which implements OpenID Connect, removing 17 | the need for users to log into Guacamole directly. This module must be layered 18 | on top of other authentication extensions that provide connection information, 19 | such as the [database authentication extension](jdbc-auth), as it only provides 20 | user authentication. 21 | 22 | ```{include} include/warn-config-changes.md 23 | ``` 24 | 25 | (openid-downloading)= 26 | 27 | Installing/Enabling the OpenID Connect authentication extension 28 | --------------------------------------------------------------- 29 | 30 | {{ ext.install('OPENID', 'guacamole-auth-sso', 'openid/guacamole-auth-sso-openid') }} 31 | 32 | (guac-openid-config)= 33 | 34 | Required configuration 35 | ---------------------- 36 | 37 | {% call ext.config('openid', required=True) %} 38 | Guacamole's OpenID connect support requires several {{ ext.properties() }} 39 | which describe both the identity provider and the Guacamole deployment. These 40 | {{ ext.properties() }} are *absolutely required in all cases*, as they dictate 41 | how Guacamole should connect to the identity provider, how it should verify the 42 | identity provider's response, and how the identity provider should redirect 43 | users back to Guacamole once their identity has been confirmed: 44 | {% endcall %} 45 | 46 | Additional configuration (optional) 47 | ----------------------------------- 48 | 49 | {% call ext.config('openid-optional') %} 50 | Additional optional {{ ext.properties() }} are available to control how claims 51 | within received ID tokens are used to derive the user's Guacamole username, any 52 | associated groups, the OpenID scopes requested when user identities are 53 | confirmed, and to control the maximum amount of time allowed for various 54 | aspects of the conversation with the identity provider: 55 | {% endcall %} 56 | 57 | (openid-login)= 58 | 59 | ### Controlling login behavior 60 | 61 | ```{include} include/sso-login-behavior.md 62 | ``` 63 | 64 | #### Automatically redirecting all unauthenticated users 65 | 66 | To ensure users are redirected to the OpenID identity provider immediately 67 | (without a Guacamole login screen), ensure the OpenID extension has priority 68 | over all others: 69 | 70 | ``` 71 | extension-priority: openid 72 | ``` 73 | 74 | #### Presenting unauthenticated users with a login screen 75 | 76 | To ensure users are given a normal Guacamole login screen and have the option 77 | to log in with traditional credentials _or_ with OpenID, ensure the OpenID 78 | extension does not have priority: 79 | 80 | ``` 81 | extension-priority: *, openid 82 | ``` 83 | 84 | (completing-openid-install)= 85 | 86 | Completing installation 87 | ----------------------- 88 | 89 | ```{include} include/ext-completing.md 90 | ``` 91 | 92 | -------------------------------------------------------------------------------- /src/include/ssl-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The name of the header to use to retrieve the URL-encoded client certificate 3 | # from an HTTP request received from an SSL termination service providing 4 | # SSL/TLS client authentication. The certificate must be in PEM format. 5 | # 6 | # By default, the `X-Client-Certificate` header will be used. 7 | # 8 | ssl-auth-client-certificate-header: X-Client-Certificate 9 | 10 | # 11 | # The name of the header to use to retrieve the verification status of the 12 | # certificate an HTTP request received from an SSL termination service 13 | # providing SSL/TLS client authentication. 14 | # 15 | # The value of this header must be "SUCCESS" (all uppercase) if the certificate 16 | # was successfully verified. The full set of accepted values that your reverse 17 | # proxy should submit for this header is: 18 | # 19 | # `SUCCESS` 20 | # : Client certificate verification succeeded. 21 | # 22 | # {samp}`FAILED: {reason}` 23 | # : Client certificate verification failed for the given reason (a 24 | # human-readable description). 25 | # 26 | # `NONE` 27 | # : No client certificate was present. 28 | # 29 | # This matches the values used by both the Apache HTTP Server and Nginx. Any 30 | # value not shown above is interpreted as an authentication failure. 31 | # 32 | # By default, the `X-Client-Verified` header will be used. 33 | # 34 | ssl-auth-client-verified-header: X-Client-Verified 35 | 36 | # 37 | # The amount of time that a temporary authentication token for SSL/TLS 38 | # authentication may remain valid, in minutes. 39 | # 40 | # This token is used to represent the user's asserted identity after it has 41 | # been verified by the SSL termination service. This interval must be long 42 | # enough to allow for network delays in receiving the token, but short enough 43 | # that unused tokens do not consume unnecessary server resources and cannot 44 | # potentially be guessed while the token is still valid. These tokens are 45 | # 256-bit secure random values. 46 | # 47 | # By default, tokens are valid for 5 minutes. 48 | # 49 | ssl-auth-max-token-validity: 5 50 | 51 | # 52 | # The LDAP attribute or attributes that may be used to represent a username 53 | # within the subject DN of a user's X.509 certificate. If the least-significant 54 | # attribute of the subject DN is not one of these attributes, the certificate 55 | # will be rejected. 56 | # 57 | # By default, any attribute is accepted (the least-significant attribute of the 58 | # subject DN is used as the username, regardless of what attribute that may 59 | # be). 60 | # 61 | ssl-auth-subject-username-attribute: cn, uid 62 | 63 | # 64 | # The base DN containing all valid subject DNs. If specified, only certificates 65 | # asserting subject DNs beneath this base DN will be accepted. 66 | # 67 | # By default, all DNs are accepted. 68 | # 69 | ssl-auth-subject-base-dn: ou=Users,dn=example,dn=net 70 | 71 | # 72 | # The amount of time that the temporary, unique subdomain generated for SSL/TLS 73 | # authentication may remain valid, in minutes. This subdomain is used to ensure 74 | # each SSL/TLS authentication attempt is fresh and does not potentially reuse a 75 | # previous authentication attempt that was cached by the browser or OS. This 76 | # interval must be long enough to allow for network delays in authenticating 77 | # the user with the SSL termination service that enforces SSL/TLS client 78 | # authentication, but short enough that an unused domain does not consume 79 | # unnecessary server resources and cannot potentially be guessed while that 80 | # subdomain is still valid. These subdomains are 128-bit secure random values. 81 | # 82 | # By default, generated domains are valid for 5 minutes. 83 | # 84 | ssl-auth-max-domain-validity: 5 85 | -------------------------------------------------------------------------------- /src/include/saml.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The URI of the XML metadata file from the SAML Identity Provider that 3 | # contains all of the information the SAML extension needs in order to know how 4 | # to authenticate with the IdP. This URI can either be a remote server (e.g. 5 | # `https://`) or a local file on the filesystem (e.g. `file://`). Often the 6 | # metadata file contains most of the required properties for SAML 7 | # authentication and the other parameters are not required. 8 | # 9 | saml-idp-metadata-url: file:///etc/guacamole/saml-metadata.xml 10 | 11 | # 12 | # The base URL of the SAML IdP. This is the URL that the SAML authentication 13 | # extension will use to redirect when requesting SAML authentication. If the 14 | # `saml-idp-metadata-url` property is provided, this parameter will be ignored. 15 | # If the metadata file is not provided this property is required. 16 | # 17 | saml-idp-url: https://myidp.example.net 18 | 19 | # 20 | # The entity ID of the Guacamole SAML client, which is generally the URL of the 21 | # Guacamole server, but is not required to be so. This property is required if 22 | # either the `saml-idp-metadata-url` property is not specified, or if the 23 | # provided metadata file does not contain the SAML SP Entity ID for the 24 | # Guacamole Client. 25 | # 26 | saml-entity-id: https://guac.example.net 27 | 28 | # 29 | # The URL that the IdP will use once authentication has succeeded to return to 30 | # the Guacamole web application and provide the authentication details to the 31 | # SAML extension. The SAML extension currently only supports callback as a POST 32 | # operation to this callback URL. This property is required. 33 | # 34 | saml-callback-url: https://guac.example.net 35 | 36 | # 37 | # Require strict security checks during SAML logins. This will insure that 38 | # valid certificates are present for all interactions with SAML servers and 39 | # fail SAML authentication if security restrictions are violated. This property 40 | # is optional, and will default to true, requiring strict security checks. This 41 | # property should only be set to false in non-production environments during 42 | # testing of SAML authentication. 43 | # 44 | saml-strict: true 45 | 46 | # 47 | # Enable additional logging within the supporting SAML library that can assist 48 | # in tracking down issues during SAML logins. This property is optional, and 49 | # will default to false (no debugging). 50 | # 51 | saml-debug: false 52 | 53 | # 54 | # Enable compression of the HTTP requests sent to the SAML IdP. This property 55 | # is optional and will default to true (compression enabled). 56 | # 57 | saml-compress-request: true 58 | 59 | # 60 | # Request that the SAML response returned by the IdP be compressed. This 61 | # property is optional and will default to true (compression will be 62 | # requested). 63 | # 64 | saml-compress-response: true 65 | 66 | # 67 | # The name of the attribute provided by the SAML IdP that contains group 68 | # membership of the user. These groups will be parsed and used to map group 69 | # membership of the user logging in, which can be used for permissions 70 | # management within Guacamole Client, particularly when layered with other 71 | # authentication modules. This property is optional, and defaults to "groups". 72 | # 73 | saml-group-attribute: groups 74 | 75 | # 76 | # The path to a certificate that will be used to sign SAML requests before 77 | # they are sent to the IdP, enhancing the integrity of the SAML authentication 78 | # process. This property is optional, and, if not present, SAML requests 79 | # will not be signed. 80 | # 81 | saml-x509-cert-path: /etc/guacamole/myidp.crt 82 | 83 | # 84 | # The path to a private key file to use to encrypt SAML requests sent to the 85 | # IdP, enhancing the confidentiality and integrity of the authentication 86 | # process. This property is optional, and, if not present, SAML requests 87 | # will not be encrypted before they are sent to the IdP. 88 | # 89 | saml-private-key-path: /etc/guacamole/saml-private.key 90 | -------------------------------------------------------------------------------- /src/include/postgresql-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The hostname or IP address of the server hosting your database. If not 3 | # specified, "localhost" will be used by default. 4 | # 5 | postgresql-hostname: localhost 6 | 7 | # 8 | # The port number of the PostgreSQL database to connect to. If not specified, 9 | # the standard PostgreSQL port 5432 will be used. 10 | # 11 | postgresql-port: 5432 12 | 13 | # 14 | # This property sets the SSL mode that the JDBC extension will attempt to use 15 | # when communicating with the remote PostgreSQL server. The values for this 16 | # property match the standard values supported by the PostgreSQL JDBC driver: 17 | # 18 | # disable 19 | # : Do not use SSL, and fail if the server requires it. 20 | # 21 | # allow 22 | # : If the server requires encryption use it, otherwise prefer unencrypted 23 | # connections. 24 | # 25 | # prefer 26 | # : Try SSL connections, first, but allow unencrypted connections if the server 27 | # does not support SSL or if SSL negotiations fail. This is the 28 | # default. 29 | # 30 | # require 31 | # : Require SSL connections, but implicitly trust all server certificates and 32 | # authorities. 33 | # 34 | # verify-ca 35 | # : Require SSL connections, and verify that the server certificate is issued 36 | # by a known certificate authority. 37 | # 38 | # verify-full 39 | # : Require SSL connections, verifying that the server certificate is issued 40 | # by a known authority, and that the name on the certificate matches the name 41 | # of the server. 42 | # 43 | postgresql-ssl-mode: prefer 44 | 45 | # 46 | # The file containing the client certificate to be used when making an 47 | # SSL-encrtyped connection to the PostgreSQL server, in PEM format. This 48 | # property is optional, and will be ignored if the SSL mode is set to disable. 49 | # 50 | postgresql-ssl-cert-file: /etc/guacamole/postgresql.crt 51 | 52 | # 53 | # The file containing the client private key to be used when making an 54 | # SSL-encrypted connection to the PostgreSQL server, in PEM format. This 55 | # property is optional, and will be ignored if the SSL mode is set to disable. 56 | # 57 | postgresql-ssl-key-file: /etc/guacamole/postgresql.key 58 | 59 | # 60 | # The file containing the root and intermedidate certificates against which the 61 | # server certificate will be verified when making an SSL-encrypted connection 62 | # to the PostgreSQL server. This file should contain one or more PEM-formatted 63 | # authority certificates. This property is optional, and will only be used if 64 | # SSL mode is set to verify-ca or verify-full. 65 | # 66 | # If SSL is set to one of the verification modes and this property is not 67 | # specified, the JDBC driver will attempt to use the `.postgresql/root.crt` 68 | # file from the home directory of the user running the web application server 69 | # (e.g. Tomcat). If this property is not specified and the default file does 70 | # not exist, the PostgreSQL JDBC driver will fail to connect to the server. 71 | # 72 | postgresql-ssl-root-cert-file: /etc/guacamole/postgresql-root.crt 73 | 74 | # 75 | # The password that will be used to access the client private key file, if the 76 | # client private key is encrypted. This property is optional, and is only used 77 | # if the `postgresql-ssl-key-file` property is set and SSL is enabled. 78 | # 79 | postgresql-ssl-key-password: some-password 80 | 81 | # 82 | # The number of seconds the driver will wait for a response from the database, 83 | # before aborting the query. A value of 0 (the default) means the timeout is 84 | # disabled. 85 | # 86 | postgresql-default-statement-timeout: 0 87 | 88 | # 89 | # The number of seconds to wait for socket read operations. If reading from the 90 | # server takes longer than this value, the connection will be closed. This can 91 | # be used to handle network problems such as a dropped connection to the 92 | # database. Similar to `postgresql-default-statement-timeout`, it will also 93 | # abort queries that take too long. A value of 0 (the default) means the 94 | # timeout is disabled. 95 | # 96 | postgresql-socket-timeout: 0 97 | 98 | # 99 | # Controls how many objects may be retrieved from the database in a single 100 | # query. If more objects than this number are requested, retrieval of those 101 | # objects will be automatically and transparently split across multiple 102 | # queries. 103 | # 104 | # By default, PostgreSQL queries will retrieve no more than 5000 objects. 105 | # 106 | postgresql-batch-size: 5000 107 | -------------------------------------------------------------------------------- /src/duo-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Using Duo for multi-factor authentication 5 | ========================================= 6 | 7 | Guacamole's Duo authentication extension allows the third-party Duo service to 8 | be used as an additional authentication factor for users of your Guacamole 9 | installation. If installed, users that attempt to authenticate against 10 | Guacamole will be sent to Duo's service for further verification. 11 | 12 | ```{include} include/warn-config-changes.md 13 | ``` 14 | 15 | :::{note} 16 | Guacamole's Duo support cannot currently be used alongside [single sign-on](sso). If 17 | you use Duo and need both [MFA](mfa) and [SSO](sso) support for Guacamole, you 18 | will need to either use your SSO provider's own Duo integration or use 19 | [TOTP](totp-auth) instead of Duo. 20 | ::: 21 | 22 | (duo-architecture)= 23 | 24 | How Duo works with Guacamole 25 | ---------------------------- 26 | 27 | Duo is strictly a service for verifying the identities of users that have 28 | already been partially verified through another authentication method. Thus, 29 | for Guacamole to make use of Duo, at least one other authentication mechanism 30 | will need be configured, such as [a supported database](jdbc-auth) or 31 | [LDAP](ldap-auth). 32 | 33 | When a user attempts to log into Guacamole, other installed authentication 34 | methods will be queried first: 35 | 36 | ![](images/duo-auth-factor-1.png) 37 | 38 | Only after authentication has succeeded with one of those methods will 39 | Guacamole reach out to Duo to obtain additional verification of user 40 | identity: 41 | 42 | ![](images/duo-auth-factor-2.png) 43 | 44 | If both the initial authentication attempt and verification through Duo 45 | succeed, the user will be allowed in. If either mechanism fails, access 46 | to Guacamole is denied. 47 | 48 | Adding Guacamole to Duo 49 | ----------------------- 50 | 51 | Duo does not provide a specific integration option for Guacamole, but 52 | Guacamole's Duo extension uses Duo's generic authentication API which 53 | they refer to as the "Web SDK". To use Guacamole with Duo, you will need 54 | to add it as a new "Web SDK" application from within the "Applications" 55 | tab of the admin panel of your Duo account: 56 | 57 | ![](images/duo-add-guacamole.png) 58 | 59 | Within the settings of the newly-added application, rename the 60 | application to something more representative than "Web SDK". This 61 | application name is what will be presented to your users when they are 62 | prompted by Duo for additional authentication: 63 | 64 | ![](images/duo-rename-guacamole.png) 65 | 66 | Once you've finished adding Guacamole as a "Web SDK" application, the 67 | information required to configure Guacamole is listed within the application's 68 | "Details" section. You will need to copy the client ID, secret, and API 69 | hostname - they will later be specified within Guacamole's configuration: 70 | 71 | ![](images/duo-copy-details.png) 72 | 73 | (duo-downloading)= 74 | 75 | Installing/Enabling the Duo extension 76 | ------------------------------------- 77 | 78 | {{ ext.install('DUO', 'guacamole-auth-duo') }} 79 | 80 | (guac-duo-config)= 81 | 82 | Required configuration 83 | ---------------------- 84 | 85 | {{ ext.config('duo', required=True) }} 86 | 87 | Additional configuration (optional) 88 | ----------------------------------- 89 | 90 | {% call ext.config('duo-optional') %} 91 | The following additional, optional {{ ext.properties() }} may be set as desired 92 | to tailor the behavior of the Duo support: 93 | {% endcall %} 94 | 95 | ### Bypass/Enforce Duo for Specific Hosts 96 | 97 | {% call ext.config('duo-bypass-enforce') %} 98 | By default, when the Duo module is enabled, Duo-based MFA will be enforced for 99 | all users that attempt to log in to Guacamole, regardless of where they are 100 | connecting from. Depending on your use case, it may be necessary to narrow this 101 | behavior and only enforce Duo-based MFA for certain hosts and bypass it for 102 | others. 103 | 104 | ```{include} include/ext-client-ips.md 105 | ``` 106 | 107 | Duo-based MFA can be explicitly bypassed or enforced on a per-host basis by 108 | providing the relevant, exhaustive list of addresses/networks using either of 109 | the following {{ ext.properties() }}: 110 | {% endcall %} 111 | 112 | (completing-duo-install)= 113 | 114 | Completing installation 115 | ----------------------- 116 | 117 | ```{include} include/ext-completing.md 118 | ``` 119 | 120 | -------------------------------------------------------------------------------- /src/include/radius.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The RADIUS server to authenticate against. If not specified, localhost will 3 | # be used. 4 | # 5 | radius-hostname: localhost 6 | 7 | # 8 | # The RADIUS authentication port on which the RADIUS service is is listening. 9 | # If not specified, the default of 1812 will be used. 10 | # 11 | radius-auth-port: 1812 12 | 13 | # 14 | # The shared secret to use when talking to the RADIUS server. This parameter is 15 | # required and the extension will not load if this is not specified. 16 | # 17 | radius-shared-secret: some-shared-secret 18 | 19 | # 20 | # The authentication protocol to use when talking to the RADIUS server. This 21 | # parameter is required for the extension to operate. Supported values are: 22 | # pap, chap, mschapv1, mschapv2, eap-md5, eap-tls, and eap-ttls. Support for 23 | # PEAP is implemented inside the extension, but, due to a regression in the 24 | # JRadius implementation, it is currently broken. Also, if you specify eap-ttls 25 | # you will also need to specify the `radius-eap-ttls-inner-protocol` parameter 26 | # in order to properly configure the protocol used inside the EAP TTLS tunnel. 27 | # 28 | radius-auth-protocol: eap-tls 29 | 30 | # 31 | # The combination certificate and private key pair to use for TLS-based RADIUS 32 | # protocols that require a client-side certificate. This parameter should specify 33 | # the absolute path to the file. By default the extension will look for a file 34 | # called `radius.key` in the `GUACAMOLE_HOME` directory. 35 | # 36 | radius-key-file: /etc/guacamole/radius.key 37 | 38 | # 39 | # The file type of the keystore specified by the `radius-key-file` parameter. 40 | # Valid keystore types are pem, jceks, jks, and pkcs12. If not specified, this 41 | # defaults to pkcs12, the default used by the JRadius library. 42 | # 43 | radius-key-type: pkcs12 44 | 45 | # 46 | # The password of the private key specified in the `radius-key-file` parameter. 47 | # By default the extension will not use any password when trying to open the 48 | # key file. 49 | # 50 | radius-key-password: some-password 51 | 52 | # 53 | # The absolute path to the file that stores the certificate authority 54 | # certificates for encrypted connections to the RADIUS server. By default a 55 | # file with the name ca.crt in the `GUACAMOLE_HOME` directory will be used. 56 | # 57 | radius-ca-file: /etc/guacamole/ca.crt 58 | 59 | # 60 | # The file type of the keystore used for the certificate authority. Valid 61 | # formats are pem, jceks, jks, and pkcs12. If not specified this defaults to 62 | # pem. 63 | # 64 | radius-ca-type: pem 65 | 66 | # 67 | # The password used to protect the certificate authority store, if any. If 68 | # unspecified the extension will attempt to read the CA store without any 69 | # password. 70 | # 71 | radius-ca-password: some-password 72 | 73 | # 74 | # This parameter controls whether or not the RADIUS extension should trust all 75 | # certificates or verify them against known good certificate authorities. Set 76 | # to true to allow the RADIUS server to connect without validating 77 | # certificates. The default is false, which causes certificates to be 78 | # validated. 79 | # 80 | radius-trust-all: false 81 | 82 | # 83 | # The number of times the client will retry the connection to the RADIUS server 84 | # and not receive a response before giving up. By default the client will try 85 | # the connection at most 5 times. 86 | # 87 | radius-retries: 5 88 | 89 | # 90 | # The timeout for a RADIUS connection in seconds. By default the client will 91 | # wait for a response from the server for at most 60 seconds. 92 | # 93 | radius-timeout: 60 94 | 95 | # 96 | # When EAP-TTLS is used, this parameter specifies the inner (tunneled) protocol 97 | # to use talking to the RADIUS server. It is required when the 98 | # `radius-auth-protocol` parameter is set to eap-ttls. If the 99 | # `radius-auth-protocol` value is set to something other than eap-ttls, this 100 | # parameter has no effect and will be ignored. Valid options for this are any of 101 | # the values for `radius-auth-protocol`, except for eap-ttls. 102 | # 103 | radius-eap-ttls-inner-protocol: chap 104 | 105 | # 106 | # This property allows the server administrator to manually set an IP address 107 | # that will be sent to the RADIUS server to identify this RADIUS client, known 108 | # as the "Network Access Server" (NAS) IP address. When this property is not 109 | # specified, the RADIUS extension attempts to automatically determine the IP 110 | # address of the system on which Guacamole is running and uses that value. 111 | # 112 | radius-nas-ip: 10.11.0.1 113 | -------------------------------------------------------------------------------- /src/adhoc-connections.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Creating ad-hoc connections 5 | =========================== 6 | 7 | The quickconnect extension provides a connection bar on the Guacamole Client 8 | home page that allows users to type in the URI of a server to which they want 9 | to connect and the client will parse the URI and immediately establish the 10 | connection. The purpose of the extension is to allow situations where 11 | administrators want to allow users the flexibility of establishing their own 12 | connections without having to grant them access to edit connections or even to 13 | have to create the connections at all, aside from typing the URI. 14 | 15 | :::{important} 16 | There are several implications of using this extension that should be 17 | well-understood by administrators prior to implementing it: 18 | 19 | * Connections established with this extension are created in-memory and only 20 | persist until the Guacamole session ends. 21 | 22 | * Connections created with this extension are not accessible to other users, 23 | and cannot be shared with other users. 24 | 25 | * This extension provides no functionality for authenticating users - it does 26 | not allow anonymous logins, and requires that users are successfully 27 | authenticated by another authentication module before it can be used. 28 | 29 | * The extension provides users the ability not only to establish connections, 30 | but also to set any of the parameters for a connection. There are security 31 | implications for this - for example, RDP file sharing can be used to pass 32 | through any directory available on the server running guacd to the remote 33 | desktop. This should be taken into consideration when enabling this extension 34 | and making sure that guacd is configured in a way that does not compromise 35 | sensitive system files by allowing access to them. 36 | ::: 37 | 38 | ```{include} include/warn-config-changes.md 39 | ``` 40 | 41 | (quickconnect-downloading)= 42 | 43 | Installing/Enabling the quickconnect extension 44 | ---------------------------------------------- 45 | 46 | {{ ext.install('QUICKCONNECT', 'guacamole-auth-quickconnect') }} 47 | 48 | (guac-quickconnect-config)= 49 | 50 | Configuration (optional) 51 | ------------------------ 52 | 53 | {% call ext.config('quickconnect') %} 54 | {{ ext.nothingRequired() }} 55 | {% endcall %} 56 | 57 | (completing-quickconnect-install)= 58 | 59 | Completing installation 60 | ----------------------- 61 | 62 | ```{include} include/ext-completing.md 63 | ``` 64 | 65 | (using-quickconnect)= 66 | 67 | Using the quickconnect extension 68 | -------------------------------- 69 | 70 | The quickconnect extension provides a field on the home page that allows you to 71 | enter a Uniform Resource Identifier (URI) to create a connection. A URI is in 72 | the form: 73 | 74 | {samp}`{protocol}://{username}:{password}@{host}:{port}/?{parameters}` 75 | 76 | The `protocol` field can have any of the protocols supported by Guacamole, as 77 | documented in [](configuring-guacamole). Many of the protocols define a default 78 | `port` value, with the exception of VNC. The `parameters` field can specify any 79 | of the protocol-specific parameters as documented on the configuration page. 80 | 81 | To establish a connection, simply type in a valid URI and either press "Enter" 82 | or click the connect button. This extension will parse the URI and create a new 83 | connection, and immediately start that connection in the current browser. 84 | 85 | Here are a few examples of URIs: 86 | 87 | `ssh://linux1.example.com/` 88 | : Connect to the server linux1.example.com using the SSH protocol on the 89 | default SSH port (22). This will result in prompting for both username and 90 | password. 91 | 92 | `vnc://linux1.example.com:5900/` 93 | : Connect to the server linux1.example.com using the VNC protocol and 94 | specifying the port as 5900. 95 | 96 | `rdp://localuser@windows1.example.com/?security=rdp&ignore-cert=true&disable-audio=true&enable-drive=true&drive-path=/mnt/usb` 97 | : Connect to the server windows1.example.com using the RDP protocol and the 98 | user "localuser". This URI also specifies several RDP-specific parameters on 99 | the connection, including forcing security mode to RDP (security=rdp), ignoring 100 | any certificate errors (ignore-cert=true), disabling audio pass-through 101 | (disable-audio=true), and enabling filesystem redirection (enable-drive=true) 102 | to the /mnt/usb folder on the system running guacd (drive-path=/mnt/usb). 103 | 104 | -------------------------------------------------------------------------------- /src/radius-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | RADIUS authentication 5 | ===================== 6 | 7 | Guacamole supports delegating authentication to a RADIUS service, such as 8 | FreeRADIUS, to validate username and password combinations, and to support 9 | multi-factor authentication. This authentication method must be layered on top 10 | of some other authentication extension, such as those available from the main 11 | project website, in order to provide access to actual connections. 12 | 13 | ```{include} include/warn-config-changes.md 14 | ``` 15 | 16 | (radius-downloading)= 17 | 18 | Building the RADIUS authentication extension 19 | -------------------------------------------- 20 | 21 | The RADIUS extension depends on software that is covered by a LGPL license, 22 | which is incompatible with the Apache 2.0 license under which Guacamole is 23 | licensed. Due to this dependency, the Guacamole project cannot distribute 24 | binary versions of the RADIUS extension. If you want to use this extension you 25 | will need to build the RADIUS extension from source, either by [building 26 | guacamole-client from source using Maven](building-guacamole-client) or by 27 | manually building the guacamole-client Docker image. 28 | 29 | ::::{tab} {{ native_tab_title }} 30 | 31 | The RADIUS extension must be explicitly enabled during build time in order to 32 | generate the binaries and resulting JAR file. This is done by adding the flag 33 | `-Plgpl-extensions` to the Maven command line during the build, and should 34 | result in the output below: 35 | 36 | :::{code-block} console 37 | :emphasize-lines: 10,19 38 | $ mvn -Plgpl-extensions clean package 39 | [INFO] Scanning for projects... 40 | [INFO] ------------------------------------------------------------------------ 41 | [INFO] Reactor Build Order: 42 | [INFO] 43 | [INFO] guacamole-client [pom] 44 | [INFO] guacamole-common [jar] 45 | [INFO] guacamole-ext [jar] 46 | ... 47 | [INFO] guacamole-auth-radius [jar] 48 | ... 49 | [INFO] ------------------------------------------------------------------------ 50 | [INFO] Reactor Summary for guacamole-client {{ version }}: 51 | [INFO] 52 | [INFO] guacamole-client ................................... SUCCESS [ 12.839 s] 53 | [INFO] guacamole-common ................................... SUCCESS [ 15.446 s] 54 | [INFO] guacamole-ext ...................................... SUCCESS [ 19.988 s] 55 | ... 56 | [INFO] guacamole-auth-radius .............................. SUCCESS [ 10.806 s] 57 | ... 58 | [INFO] ------------------------------------------------------------------------ 59 | [INFO] BUILD SUCCESS 60 | [INFO] ------------------------------------------------------------------------ 61 | [INFO] Total time: 04:36 min 62 | [INFO] Finished at: 2023-01-10T17:27:11-08:00 63 | [INFO] ------------------------------------------------------------------------ 64 | $ 65 | ::: 66 | 67 | After the build completes successfully, the extension will be in the 68 | `extensions/guacamole-auth-radius/target/` directory, and will be called 69 | `guacamole-auth-radius-{{ version }}.jar`. 70 | 71 | To install the RADIUS authentication extension, you must: 72 | 73 | 1. Create the `GUACAMOLE_HOME/extensions` directory, if it does not already 74 | exist. 75 | 76 | 2. Copy `guacamole-auth-radius-{{ version }}.jar` into `GUACAMOLE_HOME/extensions`. 77 | 78 | 3. Configure Guacamole to use RADIUS authentication, as described below. 79 | :::: 80 | 81 | ::::{tab} {{ container_tab_title }} 82 | To build a copy of the `guacamole/guacamole` Docker image with RADIUS support, 83 | the `-Plgpl-extensions` option must be passed to the Docker build process using 84 | the `MAVEN_ARGUMENTS` build argument. The `-DskipTests=true` argument must also 85 | be included, as the build otherwise performs several JavaScript unit tests that 86 | cannot run in a containerized environment: 87 | 88 | ```console 89 | $ docker build \ 90 | --build-arg MAVEN_ARGUMENTS="-Plgpl-extensions -DskipTests=true" \ 91 | -t guacamole/guacamole . 92 | ``` 93 | 94 | Once the build completes, you can use your copy of the `guacamole/guacamole` 95 | image as you would the standard image provided with each Guacamole release. 96 | :::: 97 | 98 | (guac-radius-config)= 99 | 100 | Configuration 101 | ------------- 102 | 103 | {{ ext.config('radius') }} 104 | 105 | (completing-radius-install)= 106 | 107 | Completing installation 108 | ----------------------- 109 | 110 | ```{include} include/ext-completing.md 111 | ``` 112 | 113 | -------------------------------------------------------------------------------- /src/include/mysql-optional.properties.in: -------------------------------------------------------------------------------- 1 | # 2 | # The hostname or IP address of the server hosting your database. If not 3 | # specified, "localhost" will be used by default. 4 | # 5 | mysql-hostname: localhost 6 | 7 | # 8 | # The port number of the MySQL or MariaDB database to connect to. If not 9 | # specified, the standard MySQL / MariaDB port 3306 will be used. 10 | # 11 | mysql-port: 3306 12 | 13 | # 14 | # Controls which JDBC driver the extension attempts to load. By default, the 15 | # installed JDBC driver will be automatically detected. Possible values are: 16 | # 17 | # mysql 18 | # : [The **MySQL** Connector/J JDBC driver](https://dev.mysql.com/downloads/connector/j/). 19 | # 20 | # mariadb 21 | # : [The **MariaDB** Connector/J JDBC driver](https://mariadb.com/kb/en/about-mariadb-connector-j/). 22 | # 23 | mysql-driver: mariadb 24 | 25 | # 26 | # Specifies the timezone the MySQL server is configured to run in. While the 27 | # MySQL driver attempts to auto-detect the timezone in use by the server, there 28 | # are many cases where the timezone provided by the operating system is either 29 | # unknown by Java, or matches multiple timezones. In these cases MySQL may 30 | # either complain or refuse the connection unless the timezone is specified as 31 | # part of the connection. This property allows the timezone of the server to be 32 | # specified so that the connection can continue and the JDBC driver can 33 | # properly translate timestamps. The property accepts timezones in the 34 | # following formats: 35 | # 36 | # Region/Locale 37 | # : Well-known time zone identifiers, in the Region/Locale format, as defined 38 | # by the [IANA time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), 39 | # such as `America/Los_Angeles`, `Africa/Johannesburg`, or `China/Shanghai`. 40 | # 41 | # GMT+/-HH:MM 42 | # : GMT or custom timezones specified by GMT offset, such as `GMT`, `GMT+0130`, 43 | # `GMT+06:00`, or `GMT-9`. 44 | # 45 | mysql-server-timezone: GMT 46 | 47 | # 48 | # This property sets the SSL mode that the JDBC driver will attempt to use when 49 | # communicating with the remote MySQL server. The values for this property 50 | # match the standard values supported by the MySQL and MariaDB JDBC drivers: 51 | # 52 | # disabled 53 | # : Do not use SSL, and fail if the server requires it. For compatibility this 54 | # will also set the legacy JDBC driver property useSSL to false. 55 | # 56 | # preferred 57 | # : Prefer SSL, but fall back to plain-text if an SSL connection cannot be 58 | # negotiated. This is the default. 59 | # 60 | # required 61 | # : Require SSL connections, and fail if SSL cannot be negotiated. This mode 62 | # does not perform any validition checks on the certificate in use by the 63 | # server, the issuer, etc. 64 | # 65 | # verify-ca 66 | # : Require SSL connections, and check to make sure that the certificate issuer 67 | # is known to be valid. 68 | # 69 | # verify-identity 70 | # : Require SSL connections, and check to make sure that the server certificate 71 | # is issued by a known authority, and that the identity of the server 72 | # matches the identity on the certificate. 73 | # 74 | mysql-ssl-mode: preferred 75 | 76 | # 77 | # The file that will store trusted SSL certificates for the JDBC driver to use 78 | # when validating CA and server certificates. This should be a JKS-formatted 79 | # certificate store. This property is optional and defaults to Java's normal 80 | # trusted certificate locations, which vary based on the version of Java in 81 | # use. 82 | # 83 | mysql-ssl-trust-store: /etc/guacamole/mysql-trust.jks 84 | 85 | # 86 | # The password to use to access the SSL trusted certificate store, if one is 87 | # required. By default no password will be used. 88 | # 89 | mysql-ssl-trust-password: some-password 90 | 91 | # 92 | # The file that contains the client certificate to use when making SSL 93 | # connections to the MySQL server. This should be a JKS-formatted certificate 94 | # store that contains a private key and certificate pair. This property is 95 | # optional, and by default no client certificate will be used for the SSL 96 | # connection. 97 | # 98 | mysql-ssl-client-store: /etc/guacamole/mysql-client.jks 99 | 100 | # 101 | # The password to use to access the client certificate store, if one is 102 | # required. By default no password will be used. 103 | # 104 | mysql-ssl-client-password: some-password 105 | 106 | # 107 | # Controls how many objects may be retrieved from the database in a single 108 | # query. If more objects than this number are requested, retrieval of those 109 | # objects will be automatically and transparently split across multiple 110 | # queries. 111 | # 112 | # By default, MySQL/MariaDB queries will retrieve no more than 1000 objects. 113 | # 114 | mysql-batch-size: 1000 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | About this README 2 | ================= 3 | 4 | This README is intended to document the build process of the Apache Guacamole 5 | manual for technical users who wish to contribute or who simply wish to build 6 | the manual themselves. 7 | 8 | The [latest version of the manual](http://guacamole.apache.org/doc/gug/) is 9 | provided on the [Guacamole web site](http://guacamole.apache.org/), and 10 | snapshot copies of each release are included in the [release 11 | archives](http://guacamole.apache.org/releases/). 12 | 13 | 14 | What is guacamole-manual? 15 | ========================= 16 | 17 | The guacamole-manual package is the base documentation for the entire Guacamole 18 | stack. It is largely written in [the "MyST" flavor of Markdown](https://myst-parser.readthedocs.io/en/latest/index.html), 19 | with portions of the documentation written in reStructuredText where necessary 20 | (the Guacamole protocol reference). 21 | 22 | MyST was chosen as the primary format because: 23 | 24 | * As a variant of Markdown, it will be widely approachable and familiar. 25 | * It is supported by Sphinx. 26 | * It provides additional syntax for the features of reStructuredText that are 27 | absent from standard Markdown (like admonitions). 28 | * It provides the features of Markdown that are absent from reStructuredText 29 | (like nested inline formatting, including formatting within links or links 30 | within formatted text). 31 | 32 | reStructuredText is occasionally necessary because: 33 | 34 | * [MyST does not support docstring field lists](https://github.com/executablebooks/MyST-Parser/issues/163#issuecomment-640008632), 35 | a feature of reStructuredText required for documenting APIs. We use this 36 | feature for documenting the Guacamole protocol. 37 | * The MyST solution to supporting docstrings is [embedding blocks of 38 | reStructuredText](https://myst-parser.readthedocs.io/en/latest/using/howto.html#use-sphinx-ext-autodoc-in-markdown-files). 39 | 40 | The build process involves filtering any `.j2` files through Jinja2, generating 41 | configuration documentation from `.properties.in` snippets, and finally running 42 | the Guacamole manual source through the tooling provided by the Sphinx project 43 | (`sphinx-build`). 44 | 45 | 46 | Build requirements 47 | ================== 48 | 49 | Building the Guacamole manual from source requires: 50 | 51 | * **Python 3.8 or later** 52 | * An implementation of "make", such as [GNU 53 | Make](https://www.gnu.org/software/make/) 54 | * [Sphinx](https://pypi.org/project/Sphinx/) 55 | * [sphinx-book-theme](https://pypi.org/project/sphinx-book-theme/) 56 | * [sphinx-inline-tabs](https://pypi.org/project/sphinx-inline-tabs/) 57 | * [sphinx-copybutton](https://pypi.org/project/sphinx-copybutton/) 58 | * [myst-parser](https://pypi.org/project/myst-parser/) 59 | * [Jinja2](https://pypi.org/project/Jinja2/) 60 | 61 | The required Python packages can be installed using the "pip" package manager: 62 | 63 | ```console 64 | $ pip install sphinx sphinx-book-theme sphinx-inline-tabs sphinx-copybutton myst-parser Jinja2 65 | ``` 66 | 67 | On some systems, the Python 3 version of "pip" may instead be named "pip3", to 68 | maintain compatability with users and scripts that expect Python 2: 69 | 70 | ```console 71 | $ pip3 install sphinx sphinx-book-theme sphinx-inline-tabs sphinx-copybutton myst-parser Jinja2 72 | ``` 73 | 74 | Building the manual 75 | =================== 76 | 77 | If all build requirements have beein installed, the manual can be build by 78 | simply running "make": 79 | 80 | ```console 81 | $ make 82 | ``` 83 | 84 | The manual will then be built using Sphinx. Once complete, the entire HTML 85 | version of the manual will be available within the `build/html/` directory in 86 | the root directory of the source tree. 87 | 88 | Building and viewing the manual using Docker 89 | ============================================ 90 | 91 | The guacamole-manual package includes a `Dockerfile` that can be used to build 92 | an Apache httpd Docker image that contains the Guacamole user manual. 93 | 94 | By building and running the resulting container, a developer can work on the 95 | user manual without the need to install Sphinx on their workstation. The 96 | resulting container can also be used to serve the manual to Guacamole users on 97 | a network. 98 | 99 | **Docker CE version 1.6 or later is required to build the image.** 100 | 101 | Build the Guacamole manual container image by running the following command in 102 | the directory that contains this Dockerfile: 103 | 104 | ```console 105 | $ docker image build -t guacamole/manual . 106 | ``` 107 | 108 | Run the resulting container using the following command: 109 | 110 | ```console 111 | $ docker container run -p 8080:80 guacamole/manual 112 | ``` 113 | 114 | You'll see some startup messages from Apache httpd on your terminal when you 115 | start up the container. Once the container is running you can then view the 116 | HTML version of the manual by accessing http://localhost:8080 using your web 117 | browser. 118 | 119 | If another process on the host is already using port 8080, you will need to 120 | change the corresponding argument in the command used to start the container. 121 | 122 | As a developer working on the documentation, it will be necessary to stop the 123 | container and run the build again each time you wish to see changes you've 124 | made to the documentation source. 125 | 126 | 127 | Reporting problems 128 | ================== 129 | 130 | Please report any bugs encountered by opening a new issue in the JIRA system 131 | hosted at: 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/sqlserver-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | {%- import 'include/jdbc-macros.md.j2' as jdbc with context -%} 4 | 5 | Database setup for SQL Server 6 | ============================= 7 | 8 | To use Guacamole with a SQL Server database, you will need: 9 | 10 | 1. An instance of the SQL Server database server. 11 | 12 | 2. Sufficient permission to create new databases, to create new users, and to 13 | grant those users permissions. 14 | 15 | 3. Network access to the database from the Guacamole server. 16 | 17 | If this is not the case, you will need to install SQL Server before continuing 18 | or use a different database. Guacamole additionally supports: 19 | 20 | * [MariaDB / MySQL](mysql-auth) 21 | * [PostgreSQL](postgresql-auth) 22 | 23 | ```{include} include/warn-config-changes.md 24 | ``` 25 | 26 | (sqlserver-auth-database-creation)= 27 | 28 | Creating the Guacamole database 29 | ------------------------------- 30 | 31 | It is best practice to use a dedicated database and user for the Guacamole web 32 | application, and these instructions cover only this method. 33 | 34 | To create the database within SQL Server, execute a `CREATE DATABASE` command 35 | with the `sqlcmd` client: 36 | 37 | ```console 38 | $ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA 39 | Password: 40 | 1> CREATE DATABASE guacamole_db; 41 | 2> GO 42 | 1> quit 43 | ``` 44 | 45 | ### Initializing the database 46 | 47 | ::::{tab} {{ native_tab_title }} 48 | The schema scripts necessary to initialize the SQL Server version of Guacamole's 49 | database are provided within the `sqlserver/schema/` directory of {{ ext.downloadLink('guacamole-auth-jdbc') }}, 50 | which must be downloaded from [the release page for Apache Guacamole {{ version }}](https://guacamole.apache.org/releases/{{ version }}) 51 | and extracted first. 52 | 53 | Running each the two scripts in the `sqlserver/schema/` directory against the 54 | newly created database will initialize it with Guacamole's schema. You can run 55 | these scripts using the standard `sqlcmd` client: 56 | 57 | ```console 58 | $ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -d guacamole_db -i schema/001-create-schema.sql 59 | Password: 60 | Rule bound to data type. 61 | The new rule has been bound to column(s) of the specified user data type. 62 | Rule bound to data type. 63 | The new rule has been bound to column(s) of the specified user data type. 64 | $ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -d guacamole_db -i schema/002-create-admin-user.sql 65 | Password: 66 | 67 | (1 rows affected) 68 | 69 | (3 rows affected) 70 | 71 | (5 rows affected) 72 | $ 73 | ``` 74 | :::: 75 | 76 | ::::{tab} {{ container_tab_title }} 77 | The schema scripts necessary to initialize the SQL Server version of Guacamole's 78 | database are provided within the `/opt/guacamole/extensions/guacamole-auth-jdbc/sqlserver/schema` 79 | directory of the `guacamole/guacamole` image. 80 | 81 | Additionally, an `initdb.sh` script is provided at `/opt/guacamole/bin/initdb.sh` 82 | that can be used to extract the required schema initialization script: 83 | 84 | ```console 85 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --sqlserver > initdb.sql 86 | ``` 87 | 88 | The resulting script can then be run using the `sqlcmd` client: 89 | 90 | ```console 91 | $ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -d guacamole_db -i initdb.sql 92 | ``` 93 | :::: 94 | 95 | Granting Guacamole access to the database 96 | ----------------------------------------- 97 | 98 | For Guacamole to be able to execute queries against the database, you must 99 | create a new user for the database and grant that user sufficient privileges to 100 | manage the contents of all tables in the database. 101 | 102 | The user created for Guacamole needs only `SELECT`, `UPDATE`, `INSERT`, and 103 | `DELETE` permissions on all tables in the Guacamole database. These can 104 | permissions can be easily granted in SQL Server using the `db_datawriter` and 105 | `db_datareader` roles: 106 | 107 | ```console 108 | $ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA 109 | Password: 110 | 1> CREATE LOGIN guacamole_user WITH PASSWORD = 'some_password'; 111 | 2> GO 112 | 1> USE guacamole_db; 113 | 2> GO 114 | 1> CREATE USER guacamole_user; 115 | 2> GO 116 | 1> ALTER ROLE db_datawriter ADD MEMBER guacamole_user; 117 | 2> ALTER ROLE db_datareader ADD MEMBER guacamole_user; 118 | 3> GO 119 | 1> quit 120 | $ 121 | ``` 122 | 123 | (sqlserver-auth-installation)= 124 | 125 | Upgrading an existing Guacamole database 126 | ---------------------------------------- 127 | 128 | {{ jdbc.upgrade('sqlserver') }} 129 | 130 | Installing/Enabling support for SQL Server 131 | ------------------------------------------ 132 | 133 | {% call jdbc.install('sqlserver') %} 134 | Any of the following TDS-compatible JDBC drivers are supported for connecting 135 | Guacamole to SQL Server: 136 | 137 | * [Microsoft JDBC Driver for SQL Server](https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server) 138 | * [jTDS](http://jtds.sourceforge.net/) 139 | * [Progress DataDirect’s JDBC Driver for SQL Server](https://www.progress.com/jdbc/microsoft-sql-server) 140 | * Microsoft SQL Server 2000 JDBC Driver (legacy) 141 | 142 | If you do not have a specific reason to use one driver over the other, it's 143 | recommended that you use the JDBC driver provided by your database vendor. 144 | {% endcall %} 145 | 146 | {# 147 | # Configuration section (template includes all required headers) 148 | # -------------------------------------------------------------- 149 | #} 150 | {{ jdbc.config('sqlserver') }} 151 | 152 | Completing installation 153 | ----------------------- 154 | 155 | ```{include} include/ext-completing.md 156 | ``` 157 | 158 | (sqlserver-auth-default-user)= 159 | 160 | Logging in 161 | ---------- 162 | 163 | ```{include} include/jdbc-default-user.md 164 | ``` 165 | 166 | -------------------------------------------------------------------------------- /src/batch-import.md: -------------------------------------------------------------------------------- 1 | Importing connections from CSV, JSON, or YAML 2 | ============================================= 3 | 4 | Administrators may batch import connections and connection groups from a file, 5 | if the underlying authentication module supports dynamic connection/group creation. 6 | To start a batch import, click the "Import" button on the connection edit tab. 7 | 8 | ![Link to Batch Import](images/batch-import-admin-link.png) 9 | 10 | At this point, the interface will accept a CSV, JSON, or YAML file containing 11 | a list of connections to be imported. 12 | 13 | ![Batch Import Start](images/batch-import-start.png) 14 | 15 | (batch-import-success)= 16 | Success 17 | ----------------- 18 | 19 | On success, the batch import UI will simply display a message indicating 20 | how many connections were imported. 21 | 22 | ![Batch Import Success](images/batch-import-success.png) 23 | 24 | (batch-import-failure)= 25 | Failure 26 | ----------------- 27 | 28 | If import fails, the importer will display a list of the connections, along with 29 | any relevant connection-specific errors, unless a file format error prevents 30 | parsing the file into a list of connections at all. 31 | 32 | ![Batch Import Failure](images/batch-import-failure.png) 33 | 34 | (batch-import-file-format)= 35 | Import file format 36 | ------------------ 37 | 38 | Three file types are supported for connection import: CSV, JSON, and YAML. 39 | The same data may be specified by each file type. This must include the 40 | connection name and protocol. Optionally, a connection group location, a list 41 | of users and/or user groups to grant access, connection parameters, or connection 42 | protocols may also be specified. Any users or user groups that do not exist in 43 | the current data source will be automatically created. Note that any existing 44 | connection permissions will not be removed for updated connections, unless 45 | "Reset permissions" is checked. 46 | 47 | This same file format information is available within the webapp, at the 48 | "View Format Tips" link. 49 | 50 | (batch-import-csv-format)= 51 | ### CSV Format 52 | 53 | A connection import CSV file has one connection record per row. Each column will 54 | specify a connection field. At minimum the connection name and protocol must be 55 | specified. 56 | 57 | The CSV header for each row specifies the connection field. The connection group 58 | ID that the connection should be imported into may be directly specified with 59 | "parentIdentifier", or the path to the parent group may be specified using "group" 60 | as shown below. In most cases, there should be no conflict between fields, but if 61 | needed, an " (attribute)" or " (parameter)" suffix may be added to disambiguate. 62 | Lists of user or user group identifiers must be semicolon-separated. If present, 63 | semicolons can be escaped with a backslash, e.g. "first\;last". 64 | 65 | ``` 66 | name,protocol,username,password,hostname,group,users,groups,guacd-encryption (attribute) 67 | conn1,vnc,alice,pass1,conn1.web.com,ROOT,guac user 1;guac user 2,Connection 1 Users,none 68 | conn2,rdp,bob,pass2,conn2.web.com,ROOT/Parent Group,guac user 1,,ssl 69 | conn3,ssh,carol,pass3,conn3.web.com,ROOT/Parent Group/Child Group,guac user 2;guac user 3,, 70 | conn4,kubernetes,,,,,,, 71 | ``` 72 | 73 | (batch-import-json-format)= 74 | ### JSON Format 75 | A connection import JSON file is a list of connection objects. At minimum the connection 76 | name and protocol must be specified in each connection object. 77 | 78 | The connection group ID that the connection should be imported into may be directly 79 | specified with a "parentIdentifier" field, or the path to the parent group may be 80 | specified using a "group" field as shown below. An array of user and user group 81 | identifiers to grant access to may be specified per connection. 82 | 83 | ``` 84 | [ 85 | { 86 | "name": "conn1", 87 | "protocol": "vnc", 88 | "parameters": { "username": "alice", "password": "pass1", "hostname": "conn1.web.com" }, 89 | "parentIdentifier": "ROOT", 90 | "users": [ "guac user 1", "guac user 2" ], 91 | "groups": [ "Connection 1 Users" ], 92 | "attributes": { "guacd-encryption": "none" } 93 | }, 94 | { 95 | "name": "conn2", 96 | "protocol": "rdp", 97 | "parameters": { "username": "bob", "password": "pass2", "hostname": "conn2.web.com" }, 98 | "group": "ROOT/Parent Group", 99 | "users": [ "guac user 1" ], 100 | "attributes": { "guacd-encryption": "none" } 101 | }, 102 | { 103 | "name": "conn3", 104 | "protocol": "ssh", 105 | "parameters": { "username": "carol", "password": "pass3", "hostname": "conn3.web.com" }, 106 | "group": "ROOT/Parent Group/Child Group", 107 | "users": [ "guac user 2", "guac user 3" ] 108 | }, 109 | { 110 | "name": "conn4", 111 | "protocol": "kubernetes" 112 | } 113 | ] 114 | ``` 115 | 116 | (batch-import-yaml-format)= 117 | ### YAML Format 118 | 119 | A connection import YAML file is a list of connection objects with exactly 120 | the same structure as the JSON format. 121 | 122 | ``` 123 | --- 124 | - name: conn1 125 | protocol: vnc 126 | parameters: 127 | username: alice 128 | password: pass1 129 | hostname: conn1.web.com 130 | group: ROOT 131 | users: 132 | - guac user 1 133 | - guac user 2 134 | groups: 135 | - Connection 1 Users 136 | attributes: 137 | guacd-encryption: none 138 | - name: conn2 139 | protocol: rdp 140 | parameters: 141 | username: bob 142 | password: pass2 143 | hostname: conn2.web.com 144 | group: ROOT/Parent Group 145 | users: 146 | - guac user 1 147 | attributes: 148 | guacd-encryption: none 149 | - name: conn3 150 | protocol: ssh 151 | parameters: 152 | username: carol 153 | password: pass3 154 | hostname: conn3.web.com 155 | group: ROOT/Parent Group/Child Group 156 | users: 157 | - guac user 2 158 | - guac user 3 159 | - name: conn4 160 | protocol: kubernetes 161 | ``` 162 | 163 | -------------------------------------------------------------------------------- /tutorials/libguac-client-ball/src/ball.c: -------------------------------------------------------------------------------- 1 | #include "ball.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | /* Client plugin arguments (empty) */ 14 | const char* TUTORIAL_ARGS[] = { NULL }; 15 | 16 | void* ball_render_thread(void* arg) { 17 | 18 | /* Get data */ 19 | guac_client* client = (guac_client*) arg; 20 | ball_client_data* data = (ball_client_data*) client->data; 21 | 22 | /* Init time of last frame to current time */ 23 | guac_timestamp last_frame = guac_timestamp_current(); 24 | 25 | /* Update ball position as long as client is running */ 26 | while (client->state == GUAC_CLIENT_RUNNING) { 27 | 28 | /* Default to 30ms frames */ 29 | int frame_duration = 30; 30 | 31 | /* Lengthen frame duration if client is lagging */ 32 | int processing_lag = guac_client_get_processing_lag(client); 33 | if (processing_lag > frame_duration) 34 | frame_duration = processing_lag; 35 | 36 | /* Sleep for duration of frame, then get timestamp */ 37 | usleep(frame_duration * 1000); 38 | guac_timestamp current = guac_timestamp_current(); 39 | 40 | /* Calculate change in time */ 41 | int delta_t = current - last_frame; 42 | 43 | /* Update position */ 44 | data->ball_x += data->ball_velocity_x * delta_t / 1000; 45 | data->ball_y += data->ball_velocity_y * delta_t / 1000; 46 | 47 | /* Bounce if necessary */ 48 | if (data->ball_x < 0) { 49 | data->ball_x = -data->ball_x; 50 | data->ball_velocity_x = -data->ball_velocity_x; 51 | } 52 | else if (data->ball_x >= 1024 - 128) { 53 | data->ball_x = (2 * (1024 - 128)) - data->ball_x; 54 | data->ball_velocity_x = -data->ball_velocity_x; 55 | } 56 | 57 | if (data->ball_y < 0) { 58 | data->ball_y = -data->ball_y; 59 | data->ball_velocity_y = -data->ball_velocity_y; 60 | } 61 | else if (data->ball_y >= 768 - 128) { 62 | data->ball_y = (2 * (768 - 128)) - data->ball_y; 63 | data->ball_velocity_y = -data->ball_velocity_y; 64 | } 65 | 66 | guac_protocol_send_move(client->socket, data->ball, 67 | GUAC_DEFAULT_LAYER, data->ball_x, data->ball_y, 0); 68 | 69 | /* End frame and flush socket */ 70 | guac_client_end_frame(client); 71 | guac_socket_flush(client->socket); 72 | 73 | /* Update timestamp */ 74 | last_frame = current; 75 | 76 | } 77 | 78 | return NULL; 79 | 80 | } 81 | 82 | int ball_join_handler(guac_user* user, int argc, char** argv) { 83 | 84 | /* Get client associated with user */ 85 | guac_client* client = user->client; 86 | 87 | /* Get ball layer from client data */ 88 | ball_client_data* data = (ball_client_data*) client->data; 89 | guac_layer* ball = data->ball; 90 | 91 | /* Get user-specific socket */ 92 | guac_socket* socket = user->socket; 93 | 94 | /* Send the display size */ 95 | guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, 1024, 768); 96 | 97 | /* Create background tile */ 98 | guac_layer* texture = guac_client_alloc_buffer(client); 99 | 100 | guac_protocol_send_rect(socket, texture, 0, 0, 64, 64); 101 | guac_protocol_send_cfill(socket, GUAC_COMP_OVER, texture, 102 | 0x88, 0x88, 0x88, 0xFF); 103 | 104 | guac_protocol_send_rect(socket, texture, 0, 0, 32, 32); 105 | guac_protocol_send_cfill(socket, GUAC_COMP_OVER, texture, 106 | 0xDD, 0xDD, 0xDD, 0xFF); 107 | 108 | guac_protocol_send_rect(socket, texture, 32, 32, 32, 32); 109 | guac_protocol_send_cfill(socket, GUAC_COMP_OVER, texture, 110 | 0xDD, 0xDD, 0xDD, 0xFF); 111 | 112 | /* Prepare a curve which covers the entire layer */ 113 | guac_protocol_send_rect(socket, GUAC_DEFAULT_LAYER, 114 | 0, 0, 1024, 768); 115 | 116 | /* Fill curve with texture */ 117 | guac_protocol_send_lfill(socket, 118 | GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, 119 | texture); 120 | 121 | /* Set up ball layer */ 122 | guac_protocol_send_size(socket, ball, 128, 128); 123 | 124 | /* Prepare a circular curve */ 125 | guac_protocol_send_arc(socket, data->ball, 126 | 64, 64, 62, 0, 6.28, 0); 127 | 128 | guac_protocol_send_close(socket, data->ball); 129 | 130 | /* Draw a 4-pixel black border */ 131 | guac_protocol_send_cstroke(socket, 132 | GUAC_COMP_OVER, data->ball, 133 | GUAC_LINE_CAP_ROUND, GUAC_LINE_JOIN_ROUND, 4, 134 | 0x00, 0x00, 0x00, 0xFF); 135 | 136 | /* Fill the circle with color */ 137 | guac_protocol_send_cfill(socket, 138 | GUAC_COMP_OVER, data->ball, 139 | 0x00, 0x80, 0x80, 0x80); 140 | 141 | /* Free texture (no longer needed) */ 142 | guac_client_free_buffer(client, texture); 143 | 144 | /* Mark end-of-frame */ 145 | guac_protocol_send_sync(socket, client->last_sent_timestamp); 146 | 147 | /* Flush buffer */ 148 | guac_socket_flush(socket); 149 | 150 | /* User successfully initialized */ 151 | return 0; 152 | 153 | } 154 | 155 | int ball_free_handler(guac_client* client) { 156 | 157 | ball_client_data* data = (ball_client_data*) client->data; 158 | 159 | /* Wait for render thread to terminate */ 160 | pthread_join(data->render_thread, NULL); 161 | 162 | /* Free client-level ball layer */ 163 | guac_client_free_layer(client, data->ball); 164 | 165 | /* Free client-specific data */ 166 | free(data); 167 | 168 | /* Data successfully freed */ 169 | return 0; 170 | 171 | } 172 | 173 | int guac_client_init(guac_client* client) { 174 | 175 | /* Allocate storage for client-specific data */ 176 | ball_client_data* data = malloc(sizeof(ball_client_data)); 177 | 178 | /* Set up client data and handlers */ 179 | client->data = data; 180 | 181 | /* Allocate layer at the client level */ 182 | data->ball = guac_client_alloc_layer(client); 183 | 184 | /* Start ball at upper left */ 185 | data->ball_x = 0; 186 | data->ball_y = 0; 187 | 188 | /* Move at a reasonable pace to the lower right */ 189 | data->ball_velocity_x = 200; /* pixels per second */ 190 | data->ball_velocity_y = 200; /* pixels per second */ 191 | 192 | /* Start render thread */ 193 | pthread_create(&data->render_thread, NULL, ball_render_thread, client); 194 | 195 | /* This example does not implement any arguments */ 196 | client->args = TUTORIAL_ARGS; 197 | 198 | /* Client-level handlers */ 199 | client->join_handler = ball_join_handler; 200 | client->free_handler = ball_free_handler; 201 | 202 | return 0; 203 | 204 | } 205 | -------------------------------------------------------------------------------- /src/guacamole-common.md: -------------------------------------------------------------------------------- 1 | guacamole-common 2 | ================ 3 | 4 | The Java API provided by the Guacamole project is called guacamole-common. It 5 | provides a basic means of tunneling data between the JavaScript client provided 6 | by guacamole-common-js and the native proxy daemon, guacd, and for dealing with 7 | the Guacamole protocol. The purpose of this library is to facilitate the 8 | creation of custom tunnels between the JavaScript client and guacd, allowing 9 | your Guacamole-driven web application to enforce its own security model, if 10 | any, and dictate exactly what connections are established. 11 | 12 | (java-http-tunnel)= 13 | 14 | HTTP tunnel 15 | ----------- 16 | 17 | The Guacamole Java API implements the HTTP tunnel using a servlet called 18 | `GuacamoleHTTPTunnelServlet`. This servlet handles all requests coming to it 19 | over HTTP from the JavaScript client, and translates them into connect, read, 20 | or write requests, which each get dispatched to the `doConnect()`, `doRead()`, 21 | and `doWrite()` functions accordingly. 22 | 23 | Normally, you wouldn't touch the `doRead()` and `doWrite()` functions, as these 24 | have already been written to properly handle the requests of the JavaScript 25 | tunnel, and if you feel the need to touch these functions, you are probably 26 | better off writing your own tunnel implementation, although such a thing is 27 | difficult to do in a performant way. 28 | 29 | When developing an application based on the Guacamole API, you should use 30 | `GuacamoleHTTPTunnelServlet` by extending it, implementing your own version of 31 | `doConnect()`, which is the only abstract function it defines. The tutorial 32 | later in this book demonstrating how to write a Guacamole-based web application 33 | shows the basics of doing this, but generally, `doConnect()` is an excellent 34 | place for authentication or other validation, as it is the responsibility of 35 | `doConnect()` to create (or not create) the actual tunnel. If `doConnect()` 36 | does not create the tunnel, communication between the JavaScript client and 37 | guacd cannot take place, which is an ideal power to have as an authenticator. 38 | 39 | The `doConnect()` function is expected to return a new `GuacamoleTunnel`, but 40 | it is completely up to the implementation to decide how that tunnel is to be 41 | created. The already-implemented parts of `GuacamoleHTTPTunnelServlet` then 42 | return the unique identifier of this tunnel to the JavaScript client, allowing 43 | its own tunnel implementation to continue to communicate with the tunnel 44 | existing on the Java side. 45 | 46 | Instances of `GuacamoleTunnel` are associated with a `GuacamoleSocket`, which 47 | is the abstract interface surrounding the low-level connection to guacd. 48 | Overall, there is a socket (`GuacamoleSocket`) which provides a TCP connection 49 | to guacd. This socket is exposed to `GuacamoleTunnel`, which provides abstract 50 | protocol access around what is actually (but secretly, through the abstraction 51 | of the API) a TCP socket. 52 | 53 | The Guacamole web application extends this tunnel servlet in order to implement 54 | authentication at the lowest possible level, effectively prohibiting 55 | communication between the client and any remote desktops unless they have 56 | properly authenticated. Your own implementation can be considerably simpler, 57 | especially if you don't need authentication: 58 | 59 | ```java 60 | public class MyGuacamoleTunnelServlet 61 | extends GuacamoleHTTPTunnelServlet { 62 | 63 | @Override 64 | protected GuacamoleTunnel doConnect(HttpServletRequest request) 65 | throws GuacamoleException { 66 | 67 | // Connect to guacd here (this is a STUB) 68 | GuacamoleSocket socket; 69 | 70 | // Return a new tunnel which uses the connected socket 71 | return new SimpleGuacamoleTunnel(socket); 72 | 73 | } 74 | 75 | } 76 | ``` 77 | 78 | (java-protocol-usage)= 79 | 80 | Using the Guacamole protocol 81 | ---------------------------- 82 | 83 | guacamole-common provides basic low-level support for the Guacamole protocol. 84 | This low-level support is leveraged by the HTTP tunnel implementation to 85 | satisfy the requirements of the JavaScript client implementation, as the 86 | JavaScript client expects the handshake procedure to have already taken place. 87 | This support exists through the `GuacamoleReader` and `GuacamoleWriter` 88 | classes, which are similar to Java's `Reader` and `Writer` classes, except that 89 | they deal with the Guacamole protocol specifically, and thus have slightly 90 | different contracts. 91 | 92 | (java-reading-protocol)= 93 | 94 | ### `GuacamoleReader` 95 | 96 | `GuacamoleReader` provides a very basic `read()` function which is required to 97 | return one or more complete instructions in a `char` array. It also provides 98 | the typical `available()` function, which informs you whether `read()` is 99 | likely to block the next time it is called, and an even more abstract version 100 | of `read()` called `readInstruction()` which returns one instruction at a time, 101 | wrapped within a `GuacamoleInstruction` instance. 102 | 103 | Normally, you would not need to use this class yourself. It is used by 104 | `ConfiguredGuacamoleSocket` to complete the Guacamole protocol handshake 105 | procedure, and it is used by `GuacamoleHTTPTunnelServlet` within `doRead()` to 106 | implement the reading half of the tunnel. 107 | 108 | The only concrete implementation of `GuacamoleReader` is 109 | `ReaderGuacamoleReader`, which wraps a Java `Reader`, using that as the source 110 | for data to parse into Guacamole instructions. Again, you would not normally 111 | directly use this class, nor instantiate it yourself. A working, concrete 112 | instance of `GuacamoleReader` can be retrieved from any `GuacamoleSocket` or 113 | `GuacamoleTunnel`. 114 | 115 | (java-writing-protocol)= 116 | 117 | ### `GuacamoleWriter` 118 | 119 | `GuacamoleWriter` provides a very basic `write()` function and a more abstract 120 | version called `writeInstruction()` which writes instances of 121 | `GuacamoleInstruction`. These functions are analogous to the `read()` and 122 | `readInstruction()` functions provided by `GuacamoleReader`, and have similar 123 | restrictions: the contract imposed by `write()` requires that written 124 | instructions be complete. 125 | 126 | The only concrete implementation of `GuacamoleWriter` is 127 | `WriterGuacamoleWriter`, which wraps a Java `Writer`, using that as the 128 | destination for Guacamole instruction data, but you would not normally directly 129 | use this class, nor instantiate it yourself. It is used by 130 | `ConfiguredGuacamoleSocket` to complete the Guacamole protocol handshake 131 | procedure, and it is used by `GuacamoleHTTPTunnelServlet` within `doWrite()` to 132 | implement the writing half of the tunnel. 133 | 134 | If necessary, a `GuacamoleWriter` can be retrieved from any `GuacamoleSocket` 135 | or `GuacamoleTunnel`, but in most cases, the classes provided by the Guacamole 136 | Java API which already use `GuacamoleWriter` will be sufficient. 137 | 138 | -------------------------------------------------------------------------------- /src/guacamole-architecture.md: -------------------------------------------------------------------------------- 1 | Implementation and architecture 2 | =============================== 3 | 4 | Guacamole is not a self-contained web application and is made up of many parts. 5 | The web application is actually intended to be simple and minimal, with the 6 | majority of the gruntwork performed by lower-level components. 7 | 8 | :::{image} images/guac-arch.png 9 | :width: 2.5in 10 | ::: 11 | 12 | Users connect to a Guacamole server with their web browser. The Guacamole 13 | client, written in JavaScript, is served to users by a webserver within the 14 | Guacamole server. Once loaded, this client connects back to the server over 15 | HTTP using the Guacamole protocol. 16 | 17 | The web application deployed to the Guacamole server reads the Guacamole 18 | protocol and forwards it to guacd, the native Guacamole proxy. This proxy 19 | actually interprets the contents of the Guacamole protocol, connecting to any 20 | number of remote desktop servers on behalf of the user. 21 | 22 | The Guacamole protocol combined with guacd provide protocol agnosticism: 23 | neither the Guacamole client nor the web application need to be aware of what 24 | remote desktop protocol is actually being used. 25 | 26 | (guacamole-protocol-architecture)= 27 | 28 | The Guacamole protocol 29 | ---------------------- 30 | 31 | The web application does not understand any remote desktop protocol at all. It 32 | does not contain support for VNC or RDP or any other protocol supported by the 33 | Guacamole stack. It actually only understands the Guacamole protocol, which is 34 | a protocol for remote display rendering and event transport. While a protocol 35 | with those properties would naturally have the same abilities as a remote 36 | desktop protocol, the design principles behind a remote desktop protocol and 37 | the Guacamole protocol are different: the Guacamole protocol is not intended to 38 | implement the features of a specific desktop environment. 39 | 40 | As a remote display and interaction protocol, Guacamole implements a superset 41 | of existing remote desktop protocols. Adding support for a particular remote 42 | desktop protocol (like RDP) to Guacamole thus involves writing a middle layer 43 | which "translates" between the remote desktop protocol and the Guacamole 44 | protocol. Implementing such a translation is no different than implementing any 45 | native client, except that this particular implementation renders to a remote 46 | display rather than a local one. 47 | 48 | The middle layer that handles this translation is guacd. 49 | 50 | guacd 51 | ----- 52 | 53 | guacd is the heart of Guacamole which dynamically loads support for remote 54 | desktop protocols (called "client plugins") and connects them to remote 55 | desktops based on instructions received from the web application. 56 | 57 | guacd is a daemon process which is installed along with Guacamole and runs in 58 | the background, listening for TCP connections from the web application. guacd 59 | also does not understand any specific remote desktop protocol, but rather 60 | implements just enough of the Guacamole protocol to determine which protocol 61 | support needs to be loaded and what arguments must be passed to it. Once a 62 | client plugin is loaded, it runs independently of guacd and has full control of 63 | the communication between itself and the web application until the client 64 | plugin terminates. 65 | 66 | guacd and all client plugins depend on a common library, libguac, which makes 67 | communication via the Guacamole protocol easier and a bit more abstract. 68 | 69 | (web-application)= 70 | 71 | The web application 72 | ------------------- 73 | 74 | The part of Guacamole that a user actually interacts with is the web 75 | application. 76 | 77 | The web application, as mentioned before, does not implement any remote desktop 78 | protocol. It relies on guacd, and implements nothing more than a spiffy web 79 | interface and authentication layer. 80 | 81 | We chose to implement the server side of the web application in Java, but 82 | there's no reason that it can't be written in a different language. In fact, 83 | because Guacamole is intended be an API, we encourage this. 84 | 85 | RealMint 86 | -------- 87 | 88 | Guacamole is now a generalized remote desktop gateway, but this was not always 89 | the case. Guacamole began as a purely text-based Telnet client written in 90 | JavaScript called RealMint ("RealMint" is an anagram for "terminal"). It was 91 | written mainly as a demonstration and, while intended to be useful, its main 92 | claim to fame was only that it was pure JavaScript. 93 | 94 | The tunnel used by RealMint was written in PHP. In contrast to Guacamole's HTTP 95 | tunnel, RealMint's tunnel used only simple long-polling and was inefficient. 96 | RealMint had a decent keyboard implementation which lives on now in parts of 97 | Guacamole's keyboard code, but this was really the extent of RealMint's 98 | features and usability. 99 | 100 | Given that it was just an implementation of a legacy protocol, and that several 101 | other JavaScript terminal emulators exist, most of which well-established and 102 | stable, the project was dropped. 103 | 104 | VNC Client 105 | ---------- 106 | 107 | Once the developers learned of the HTML5 canvas tag, and saw that it was 108 | already implemented in Firefox and Chrome, work started instead on a 109 | proof-of-concept JavaScript VNC client. 110 | 111 | This client was purely JavaScript with a Java server component, and worked by 112 | translating VNC into an XML-based version of the same. Its development was 113 | naturally driven by VNC's features, and its scope was limited to forwarding a 114 | single connection to a set of users. Although relatively slow, the 115 | proof-of-concept worked well enough that the project needed an online place to 116 | live, and was registered with SourceForge as "Guacamole" - an HTML5 VNC client. 117 | 118 | As Guacamole grew and became more than a proof-of-concept, the need for speed 119 | increased, and the old RealMint-style long polling was dropped, as was the use 120 | of XML. 121 | 122 | As WebSocket could not be trusted to be supported at the time, and Java had no 123 | WebSocket standard for servlets, an equivalent HTTP-based tunnel was developed. 124 | This tunnel is still used today if WebSocket cannot be used for any reason. 125 | 126 | (gateway)= 127 | 128 | Remote Desktop Gateway 129 | ---------------------- 130 | 131 | A faster text-based protocol was developed which could present the features of 132 | multiple remote desktop protocols, not just VNC. The entire system was 133 | rearchitected into a standard daemon, guacd, and a common library, libguac, 134 | which drove both the daemon and protocol support, which became extendable. 135 | 136 | The scope of the project expanded from an adequate VNC client to a performant 137 | HTML5 remote desktop gateway and general API. In its current state, Guacamole 138 | can be used as a central gateway to access any number of machines running 139 | different remote desktop servers. It provides extendable authentication, and in 140 | the case you need something more specialized, a general API for HTML5-based 141 | remote access. 142 | 143 | -------------------------------------------------------------------------------- /src/totp-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | 4 | Using TOTP for multi-factor authentication 5 | ========================================== 6 | 7 | Guacamole supports TOTP as a second authentication factor, layered on top of 8 | any other authentication extension, including those available from the main 9 | project website, providing [base requirements for key storage and 10 | enrollment](totp-prerequisites) are met. The TOTP authentication extension 11 | allows users to be additionally verified against a user-specific and secret key 12 | generated during [enrollment of their authentication device](totp-enrollment). 13 | 14 | ```{include} include/warn-config-changes.md 15 | ``` 16 | 17 | (totp-prerequisites)= 18 | 19 | Prerequisites 20 | ------------- 21 | 22 | The enrollment process used by Guacamole's TOTP support needs to be able 23 | to store an automatically-generated key within the user's account. 24 | Another extension must be installed which supports storage of arbitrary 25 | data from other extensions. *Currently the only extensions provided with 26 | Guacamole which support this kind of storage are the [database 27 | authentication extensions](jdbc-auth).* 28 | 29 | It is thus recommended that authentication against a database be fully 30 | configured prior to setting up TOTP. Instructions walking through the setup of 31 | database authentication for Guacamole are provided in [](jdbc-auth). 32 | 33 | (totp-architecture)= 34 | 35 | How TOTP works with Guacamole 36 | ----------------------------- 37 | 38 | Guacamole provides support for TOTP as a second authentication factor. To make 39 | use of the TOTP authentication extension, some other authentication mechanism 40 | will need be configured, as well. When a user attempts to log into Guacamole, 41 | other installed authentication methods will be queried first: 42 | 43 | ![](images/totp-auth-factor-1.png) 44 | 45 | Only after authentication has succeeded with one of those methods will 46 | Guacamole prompt the user to further verify their identity with an 47 | authentication code: 48 | 49 | ![](images/totp-auth-factor-2.png) 50 | 51 | If both the initial authentication attempt and verification using TOTP succeed, 52 | the user will be allowed in. If either mechanism fails, access to Guacamole is 53 | denied. 54 | 55 | (totp-enrollment)= 56 | 57 | ### Enrollment 58 | 59 | If the user does not yet have a TOTP key associated with their account (they 60 | have not yet completed enrollment), they will be required to enroll an 61 | authentication device after passing the first authentication factor. A QR code 62 | containing an automatically-generated key will be presented to the user to be 63 | scanned by their authentication app or device: 64 | 65 | ![](images/totp-enroll.png) 66 | 67 | If the authentication device does not support scanning QR codes for enrollment, 68 | the details within the QR code can be revealed by clicking the "Show" link next 69 | to the "Details" header. These values can then be entered manually: 70 | 71 | ![](images/totp-enroll-detail.png) 72 | 73 | Enrollment is completed once the user enters a valid authentication code 74 | generated by their device using the provided key. 75 | 76 | :::{important} 77 | If the user does not confirm/complete the enrollment process, the next time the 78 | user logs in they will be asked to go through the enrollment process, again, and 79 | the TOTP data will be regenerated. This means the previously-scanned QR code 80 | and TOTP codes generated with the use of that code will be invalid. 81 | ::: 82 | 83 | 84 | (totp-reset-data)= 85 | 86 | ### Reseting TOTP Data 87 | 88 | It may become necessary for certain users to clear their TOTP key and/or force 89 | them to re-confirm enrollment, such as in situations where a user loses their 90 | phone and needs to reconfigure TOTP. The user's existing TOTP key can be cleared 91 | by checking the "Clear TOTP secret" box in the user interface and then saving the 92 | user configuration. The next time that the user logs in, they will be given a new 93 | key (QR code) and forced to re-enroll. 94 | 95 | If you simply want a user to be able to re-configure an existing key, without 96 | resetting the secret, you can un-check the box marked "TOTP key confirmed" and 97 | save the user configuration, and the user will be presented with the QR code 98 | at next login and asked to confirm it. 99 | 100 | (totp-disable-user-group)= 101 | 102 | ### Disabling TOTP for users or groups 103 | 104 | In versions of Guacamole prior to 1.6.0, installing and configuring the TOTP 105 | module meant that all Guacamole users would be required to enroll in and 106 | successfully authenticate via the TOTP factor. Starting with 1.6.0 the TOTP 107 | requirement can be disabled on a per-user or per-group basis, allowing 108 | administrators more flexibility in configuring the TOTP requirement. 109 | 110 | By default all users will still be required to authenticate with TOTP, however 111 | the requirement can be disabled by checking the "Disable TOTP" checkbox. This 112 | can be done for an individual user account, but it can also be disabled for a 113 | group resulting in the TOTP requirement being disabled for any members of the 114 | group. 115 | 116 | ![](images/totp-user-config.png) 117 | 118 | ![](images/totp-group-config.png) 119 | 120 | (totp-downloading)= 121 | 122 | Installing/Enabling the TOTP extension 123 | -------------------------------------- 124 | 125 | {{ ext.install('TOTP', 'guacamole-auth-totp') }} 126 | 127 | (guac-totp-config)= 128 | 129 | Configuration (optional) 130 | ------------------------ 131 | 132 | {% call ext.config('totp') %} 133 | With the exception of [the storage and permission requirements described 134 | above](totp-prerequisites), the TOTP extension should work out-of-the-box 135 | without any additional configuration. Defaults have been chosen for all 136 | configuration parameters such that the TOTP extension will be compatible with 137 | Google Authenticator and similar, popular TOTP implementations. 138 | 139 | :::{warning} 140 | Some TOTP applications *assume these defaults* and *silently ignore any other 141 | values*. **Google Authenticator is such an application.** Be sure your 142 | authenticator application supports the values you intend to use before 143 | overriding the defaults. 144 | ::: 145 | {% endcall %} 146 | 147 | ### Bypass/Enforce TOTP for Specific Hosts 148 | 149 | {% call ext.config('totp-bypass-enforce') %} 150 | By default, when the TOTP module is enabled, TOTP-based MFA will be enforced for 151 | all users that attempt to log in to Guacamole, regardless of where they are 152 | connecting from. Depending on your use case, it may be necessary to narrow this 153 | behavior and only enforce TOTP-based MFA for certain hosts and bypass it for 154 | others. 155 | 156 | ```{include} include/ext-client-ips.md 157 | ``` 158 | 159 | TOTP-based MFA can be explicitly bypassed or enforced on a per-host basis by 160 | providing the relevant, exhaustive list of addresses/networks using either 161 | of the following {{ ext.properties() }}: 162 | {% endcall %} 163 | 164 | (completing-totp-install)= 165 | 166 | Completing installation 167 | ----------------------- 168 | 169 | ```{include} include/ext-completing.md 170 | ``` 171 | 172 | -------------------------------------------------------------------------------- /src/postgresql-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | {%- import 'include/jdbc-macros.md.j2' as jdbc with context -%} 4 | 5 | Database setup for PostgreSQL 6 | ============================= 7 | 8 | To use Guacamole with a PostgreSQL database, you will need: 9 | 10 | 1. An instance of the PostgreSQL database server. 11 | 12 | 2. Sufficient permission to create new databases, to create new users, and to 13 | grant those users permissions. 14 | 15 | 3. Network access to the database from the Guacamole server. 16 | 17 | If this is not the case, install PostgreSQL now. Most distributions will 18 | provide a convenient PostgreSQL package which will set up everything for you. 19 | If you prefer Docker, the [`postgres`](https://hub.docker.com/_/postgres) 20 | Docker image is also a reasonable option. If you don't wish to use PostgreSQL, 21 | Guacamole additionally supports: 22 | 23 | * [MariaDB / MySQL](mysql-auth) 24 | * [SQL Server](sqlserver-auth) 25 | 26 | ```{include} include/warn-config-changes.md 27 | ``` 28 | 29 | (postgresql-auth-database-creation)= 30 | 31 | Creating the Guacamole database 32 | ------------------------------- 33 | 34 | It is best practice to use a dedicated database and user for the Guacamole web 35 | application, and these instructions cover only this method. 36 | 37 | If using the [`postgres`](https://hub.docker.com/_/postgres) Docker image: 38 | : Set the `POSTGRES_DB` environment variable to the desired name of the 39 | database. The Docker image will automatically create this database when the 40 | container starts for the first time. 41 | 42 | If using a native installation of PostgreSQL: 43 | : Manually create a database for PostgreSQL by executing a 44 | `CREATE DATABASE` query with the `psql` client: 45 | 46 | ```sql 47 | CREATE DATABASE guacamole_db; 48 | ``` 49 | 50 | ### Initializing the database 51 | 52 | ::::{tab} {{ native_tab_title }} 53 | The schema scripts necessary to initialize the PostgreSQL version of Guacamole's 54 | database are provided within the `postgresql/schema/` directory of {{ ext.downloadLink('guacamole-auth-jdbc') }}, 55 | which must be downloaded from [the release page for Apache Guacamole {{ version }}](https://guacamole.apache.org/releases/{{ version }}) 56 | and extracted first. 57 | 58 | Running each of these scripts against the newly created database will 59 | initialize it with Guacamole's schema. You can run these scripts using the 60 | standard `psql` client, but the method of running `psql` varies depending on 61 | whether you are using Docker to provide your database. 62 | 63 | If using the [`postgres`](https://hub.docker.com/_/postgres) Docker image: 64 | : The schema initialization scripts should be run against the newly created 65 | database by running the standard `psql` command-line client _within the 66 | container_: 67 | 68 | ```console 69 | $ cat schema/*.sql | docker exec -i some-postgresql \ 70 | psql -U guacamole_user -d guacamole_db -f - 71 | ``` 72 | 73 | If using a native installation of PostgreSQL: 74 | : The schema initialization scripts should be run against the newly created 75 | database using the standard `psql` client directly from the command-line: 76 | 77 | ```console 78 | $ cat schema/*.sql | psql -d guacamole_db -f - 79 | ``` 80 | :::: 81 | 82 | ::::{tab} {{ container_tab_title }} 83 | The schema scripts necessary to initialize the PostgreSQL version of Guacamole's 84 | database are provided within the `/opt/guacamole/extensions/guacamole-auth-jdbc/postgresql/schema` 85 | directory of the `guacamole/guacamole` image. 86 | 87 | Additionally, an `initdb.sh` script is provided at `/opt/guacamole/bin/initdb.sh` 88 | that can be used to extract the required schema initialization script: 89 | 90 | ```console 91 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql > initdb.sql 92 | ``` 93 | 94 | If using the [`postgres`](https://hub.docker.com/_/postgres) Docker image via Docker Compose: 95 | {% filter defListEntry %} 96 | {{ jdbc.volumeInitdb('postgresql') }} 97 | {% endfilter %} 98 | 99 | If using the [`postgres`](https://hub.docker.com/_/postgres) Docker image _without_ Docker Compose: 100 | : Use the `initdb.sh` script included with the `guacamole/guacamole` image to 101 | send the required initialization script to the standard `psql` command-line 102 | client _within the database container_: 103 | 104 | ```console 105 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql | \ 106 | docker exec -i some-postgresql psql -U guacamole_user -d guacamole_db -f - 107 | ``` 108 | 109 | If using a native installation of PostgreSQL: 110 | : Use the `initdb.sh` script included with the `guacamole/guacamole` image to 111 | automatically produce the SQL required to initialize an existing database: 112 | 113 | ```console 114 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql | \ 115 | psql -d guacamole_db -f - 116 | ``` 117 | :::: 118 | 119 | Granting Guacamole access to the database 120 | ----------------------------------------- 121 | 122 | For Guacamole to be able to execute queries against the database, you must 123 | create a new user for the database and grant that user sufficient privileges to 124 | manage the contents of all tables in the database. 125 | 126 | If using the [`postgres`](https://hub.docker.com/_/postgres) Docker image: 127 | : Set the `POSTGRES_USER` environment variable to the desired name of the 128 | dedicated user, and the `POSTGRES_PASSWORD` environment variable to the 129 | desired password. The Docker image will automatically create this user when 130 | the container starts and grant them full access to the Guacamole database. 131 | 132 | If using a native installation of PostgreSQL: 133 | : The dedicated user for Guacamole must be manually created and granted 134 | sufficient privileges. The user created for Guacamole needs only `SELECT`, 135 | `UPDATE`, `INSERT`, and `DELETE` permissions on all tables in the Guacamole 136 | database, as well as `SELECT` and `USAGE` permission on all sequences within 137 | all Guacamole tables. 138 | 139 | ```sql 140 | CREATE USER guacamole_user WITH PASSWORD 'some_password'; 141 | GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA public TO guacamole_user; 142 | GRANT SELECT,USAGE ON ALL SEQUENCES IN SCHEMA public TO guacamole_user; 143 | ``` 144 | 145 | (postgresql-auth-installation)= 146 | 147 | Upgrading an existing Guacamole database 148 | ---------------------------------------- 149 | 150 | {{ jdbc.upgrade('postgresql') }} 151 | 152 | :::{important} 153 | Because the permissions granted to the Guacamole-specific PostgreSQL user when 154 | the database was first created will not automatically be granted for any new 155 | tables and sequences, you will also need to re-grant those permissions after 156 | applying any upgrade relevant scripts: 157 | 158 | ```sql 159 | GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA public TO guacamole_user; 160 | GRANT SELECT,USAGE ON ALL SEQUENCES IN SCHEMA public TO guacamole_user; 161 | ``` 162 | ::: 163 | 164 | Installing/Enabling support for PostgreSQL 165 | ------------------------------------------ 166 | 167 | {% call jdbc.install('postgresql') %} 168 | For PostgreSQL, the proper driver is [the JDBC driver provided by the 169 | PostgreSQL project](https://jdbc.postgresql.org/download/#latest-versions). 170 | {% endcall %} 171 | 172 | {# 173 | # Configuration section (template includes all required headers) 174 | # -------------------------------------------------------------- 175 | #} 176 | {{ jdbc.config('postgresql') }} 177 | 178 | Completing installation 179 | ----------------------- 180 | 181 | ```{include} include/ext-completing.md 182 | ``` 183 | 184 | (postgresql-auth-default-user)= 185 | 186 | Logging in 187 | ---------- 188 | 189 | ```{include} include/jdbc-default-user.md 190 | ``` 191 | 192 | -------------------------------------------------------------------------------- /src/introduction.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | This book is the official Apache Guacamole manual, written by the upstream 5 | developers of the Guacamole project. It is also the official general 6 | documentation, with an online version available at 7 | . It is a work in progress which will be 8 | continuously updated as Guacamole changes with each release. 9 | 10 | We decided to maintain the documentation for Guacamole as a book, as there is 11 | an awful lot that can be done with the Guacamole web application, and even more 12 | that can be done with the API. This book is intended to explore the 13 | possibilities of Guacamole as an application, and to provide documentation 14 | necessary to install, maintain, and use Guacamole. 15 | 16 | For the sake of users and administrators, we have provided a high-level 17 | overview of Guacamole's architecture and technical design, as well as basic 18 | usage instructions and installation instructions for common platforms. 19 | 20 | For the sake of developers, we have provided a protocol reference and tutorials 21 | for common tasks (implementing protocol support, integrating Guacamole into 22 | your own application, etc.) to give a good starting point beyond simply looking 23 | at the Guacamole codebase. 24 | 25 | This particular edition of the Guacamole Manual covers Guacamole version 26 | {{ version }}. New releases which create new features or break compatibility 27 | will result in new editions of the user's guide, as will any necessary 28 | corrections. As the official documentation for the project, this book will 29 | always be freely available in its entirety online. 30 | 31 | (what-is-guac)= 32 | 33 | What is Guacamole? 34 | ------------------ 35 | 36 | Guacamole is an HTML5 web application that provides access to desktop 37 | environments using remote desktop protocols (such as VNC or RDP). 38 | Guacamole is also the project that produces this web application, and 39 | provides an API that drives it. This API can be used to power other 40 | similar applications or services. 41 | 42 | "Guacamole" is most commonly used to refer to the web application 43 | produced by the Guacamole project using their API. This web application 44 | is part of a stack that provides a protocol-agnostic remote desktop 45 | gateway. Written in JavaScript and using only HTML5 and other standards, 46 | the client part of Guacamole requires nothing more than a modern web 47 | browser or web-enabled device when accessing any of the desktops served. 48 | 49 | Historically, Guacamole was an HTML5 VNC client, and before that, a 50 | JavaScript Telnet client called RealMint ("RealMint" is an anagram for 51 | "terminal"), but this is no longer the case. Guacamole's architecture 52 | has grown to encompass remote desktop in general, and can be used as a 53 | gateway for any number of computers. Originally a proof-of-concept, 54 | Guacamole is now performant enough for daily use, and all Guacamole 55 | development is done over Guacamole. 56 | 57 | As an API, Guacamole provides a common and efficient means of streaming 58 | text data over a JavaScript-based tunnel using either HTTP or WebSocket, 59 | and a client implementation which supports the Guacamole protocol and 60 | renders the remote display when combined with a Guacamole protocol 61 | stream from the tunnel. 62 | 63 | It provides cross-browser mouse and keyboard events, an XML-driven 64 | on-screen keyboard, and synchronized nestable layers with 65 | hardware-accelerated compositing. Projects that wish to provide remote 66 | desktop support over HTML5 can leverage the years of research and 67 | development that went into Guacamole by incorporating the API into their 68 | application or service. 69 | 70 | (access-from-anywhere)= 71 | 72 | Why use Guacamole? 73 | ------------------ 74 | 75 | The principle reason to use Guacamole is constant, world-wide, 76 | unfettered access to your computers. 77 | 78 | Guacamole allows access one or more desktops from anywhere remotely, 79 | without having to install a client, particularly when installing a 80 | client is not possible. By setting up a Guacamole server, you can 81 | provide access to any other computer on the network from virtually any 82 | other computer on the internet, anywhere in the world. Even mobile 83 | phones or tablets can be used, without having to install anything. 84 | 85 | As a true web application whose communication is over HTTP or HTTPS 86 | only, Guacamole allows you to access your machines from anywhere without 87 | violating the policy of your workplace, and without requiring the 88 | installation of special clients. The presence of a proxy or corporate 89 | firewall does not prevent Guacamole use. 90 | 91 | (access-from-anything)= 92 | 93 | Access your computers from any device 94 | ------------------------------------- 95 | 96 | As Guacamole requires only a reasonably-fast, standards-compliant 97 | browser, Guacamole will run on many devices, including mobile phones and 98 | tablets. 99 | 100 | Guacamole is specifically designed to not care whether you have a mouse, 101 | keyboard, touchscreen, or any combination of those. 102 | 103 | One of the major design philosophies behind Guacamole is that it should 104 | never assume you have a particular device (ie: a mobile phone) just 105 | because your browser has or is missing a specific feature (ie: touch 106 | events or a smallish screen). Guacamole's codebase provides support for 107 | both mouse and touch events simultaneously, without choosing one over 108 | the other, while the interface is intended to be usable regardless of 109 | screen size. 110 | 111 | Barring bugs, you should be able to use Guacamole on just about any 112 | modern device with a web browser. 113 | 114 | (non-physical-computer)= 115 | 116 | Keep a computer in the "cloud" 117 | ------------------------------ 118 | 119 | Ignoring the buzzword, it's often useful to have a computer that has no 120 | dedicated physical hardware, where its processing and storage power are 121 | handled transparently by redundant systems in some remote datacenter. 122 | 123 | Computers hosted on virtualized hardware are more resilient to failures, 124 | and with so many companies now offering on-demand computing resources, 125 | Guacamole is a perfect way to access several machines that are only 126 | accessible over the internet. 127 | 128 | In fact, all Guacamole development is done on computers like this. This 129 | is partly because we like the mobility, and partly because we want to 130 | ensure Guacamole is always performant enough for daily use. 131 | 132 | (group-access)= 133 | 134 | Provide easy access to a group 135 | ------------------------------ 136 | 137 | Guacamole allows you to centralize access to a large group of machines, 138 | and specify on a per-user basis which machines are accessible. Rather 139 | than remember a list of machines and credentials, users need only log 140 | into a central server and click on one of the connections listed. 141 | 142 | If you have multiple computers which you would like to access remotely, 143 | or you are part of a group where each person has a set of machines that 144 | they need remote access to, Guacamole is a good way to provide that 145 | access while also ensuring that access is available from anywhere. 146 | 147 | (adding-remote-access)= 148 | 149 | Adding HTML5 remote access to your existing infrastructure 150 | ---------------------------------------------------------- 151 | 152 | As Guacamole is an API, not just a web application, the core components 153 | and libraries provided by the Guacamole project can be used to add HTML5 154 | remote access features to an existing application. You need not use the 155 | main Guacamole web application; you can write (or integrate with) your 156 | own rather easily. 157 | 158 | If you host an on-demand computing service, adding HTML5-based remote 159 | access allows users of your service more broad access; users need 160 | nothing more than a web browser to see their computers' screens. 161 | 162 | -------------------------------------------------------------------------------- /src/mysql-auth.md.j2: -------------------------------------------------------------------------------- 1 | {# vim: set filetype=markdown.jinja : #} 2 | {%- import 'include/ext-macros.md.j2' as ext with context -%} 3 | {%- import 'include/jdbc-macros.md.j2' as jdbc with context -%} 4 | 5 | Database setup for MariaDB / MySQL 6 | ================================== 7 | 8 | To use Guacamole with a MariaDB or MySQL database, you will need: 9 | 10 | 1. An instance of the MariaDB or MySQL database server. 11 | 12 | 2. Sufficient permission to create new databases, to create new users, and to 13 | grant those users permissions. 14 | 15 | 3. Network access to the database from the Guacamole server. 16 | 17 | If this is not the case, install your database of choice now. Most 18 | distributions will provide a convenient MariaDB or MySQL package which will set 19 | up everything for you. If you prefer Docker, the [`mysql`](https://hub.docker.com/_/mysql) 20 | and [`mariadb`](https://hub.docker.com/_/mariadb) Docker images are also 21 | reasonable options. If you don't wish to use MariaDB or MySQL, Guacamole 22 | additionally supports: 23 | 24 | * [PostgreSQL](postgresql-auth) 25 | * [SQL Server](sqlserver-auth) 26 | 27 | 28 | ```{include} include/warn-config-changes.md 29 | ``` 30 | 31 | (mysql-auth-database-creation)= 32 | 33 | Creating a new database for Guacamole 34 | ------------------------------------- 35 | 36 | It is best practice to use a dedicated database and user for the Guacamole web 37 | application, and these instructions cover only this method. 38 | 39 | If using the [`mariadb`](https://hub.docker.com/_/mariadb) or [`mysql`](https://hub.docker.com/_/mysql) Docker images: 40 | : Set the `MARIADB_DATABASE` or `MYSQL_DATABASE` environment variables 41 | respectively to the desired name of the database. The Docker image will 42 | automatically create this database when the container starts for the first 43 | time. 44 | 45 | If using a native installation of MariaDB or MySQL: 46 | : Manually create a database for MySQL and MariaDB by executing a 47 | `CREATE DATABASE` query with the `mysql` client: 48 | 49 | ```mysql 50 | CREATE DATABASE guacamole_db; 51 | ``` 52 | 53 | ### Initializing the database 54 | 55 | ::::{tab} {{ native_tab_title }} 56 | The schema scripts necessary to initialize the MySQL version of Guacamole's 57 | database are provided within the `mysql/schema/` directory of {{ ext.downloadLink('guacamole-auth-jdbc') }}, 58 | which must be downloaded from [the release page for Apache Guacamole {{ version }}](https://guacamole.apache.org/releases/{{ version }}) 59 | and extracted first. 60 | 61 | Running each of these scripts against the newly created database will 62 | initialize it with Guacamole's schema. You can run these scripts using the 63 | standard `mysql` client, but the method of running `mysql` varies depending on 64 | whether you are using Docker to provide your database. 65 | 66 | If using the [`mariadb`](https://hub.docker.com/_/mariadb) or [`mysql`](https://hub.docker.com/_/mysql) Docker images: 67 | : The schema initialization scripts should be run against the newly created 68 | database by running the standard `mysql` command-line client _within the 69 | container_: 70 | 71 | ```console 72 | $ cat schema/*.sql | docker exec -i some-mysql \ 73 | sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" guacamole_db' 74 | ``` 75 | 76 | If using a native installation of MariaDB or MySQL: 77 | : The schema initialization scripts should be run against the newly created 78 | database using the standard `mysql` client directly from the command-line: 79 | 80 | ```console 81 | $ cat schema/*.sql | mysql -u root -p guacamole_db 82 | Enter password: 83 | $ 84 | ``` 85 | :::: 86 | 87 | ::::{tab} {{ container_tab_title }} 88 | The schema scripts necessary to initialize the MySQL version of Guacamole's 89 | database are provided within the `/opt/guacamole/extensions/guacamole-auth-jdbc/mysql/schema` 90 | directory of the `guacamole/guacamole` image. 91 | 92 | Additionally, an `initdb.sh` script is provided at `/opt/guacamole/bin/initdb.sh` 93 | that can be used to extract the required schema initialization script: 94 | 95 | ```console 96 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql 97 | ``` 98 | 99 | If using the [`mariadb`](https://hub.docker.com/_/mariadb) or [`mysql`](https://hub.docker.com/_/mysql) Docker images via Docker Compose: 100 | {% filter defListEntry %} 101 | {{ jdbc.volumeInitdb('mysql') }} 102 | {% endfilter %} 103 | 104 | If using the [`mariadb`](https://hub.docker.com/_/mariadb) or [`mysql`](https://hub.docker.com/_/mysql) Docker images _without_ Docker Compose: 105 | : Use the `initdb.sh` script included with the `guacamole/guacamole` image to 106 | send the required initialization script to the standard `mysql` command-line 107 | client _within the database container_: 108 | 109 | ```console 110 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql | \ 111 | docker exec -i some-mysql sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" guacamole_db' 112 | ``` 113 | 114 | If using a native installation of MariaDB or MySQL: 115 | : Use the `initdb.sh` script included with the `guacamole/guacamole` image to 116 | automatically produce the SQL required to initialize an existing database: 117 | 118 | ```console 119 | $ docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql | \ 120 | mysql -u root -p guacamole_db 121 | ``` 122 | :::: 123 | 124 | ### Granting Guacamole access to the database 125 | 126 | For Guacamole to be able to execute queries against the database, you must 127 | create a new user for the database and grant that user sufficient privileges to 128 | manage the contents of all tables in the database. 129 | 130 | If using the [`mariadb`](https://hub.docker.com/_/mariadb) or [`mysql`](https://hub.docker.com/_/mysql) Docker images: 131 | : Set the `MARIADB_USER` or `MYSQL_USER` environment variables respectively to 132 | the desired name of the dedicated user, and the `MARIADB_PASSWORD` (or 133 | `MYSQL_PASSWORD`) environment variable to the desired password. The Docker 134 | image will automatically create this user when the container starts and grant 135 | them full access to the Guacamole database. 136 | 137 | If using a native installation of MariaDB or MySQL: 138 | : The dedicated user for Guacamole must be manually created and granted 139 | sufficient privileges. The user created for Guacamole needs only `SELECT`, 140 | `UPDATE`, `INSERT`, and `DELETE` permissions on all tables in the Guacamole 141 | database. 142 | 143 | ```mysql 144 | CREATE USER 'guacamole_user' IDENTIFIED BY 'some_password'; 145 | GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacamole_user'; 146 | FLUSH PRIVILEGES; 147 | ``` 148 | 149 | (mysql-auth-installation)= 150 | 151 | Upgrading an existing Guacamole database 152 | ---------------------------------------- 153 | 154 | {{ jdbc.upgrade('mysql') }} 155 | 156 | Installing/Enabling support for MariaDB/MySQL 157 | --------------------------------------------- 158 | 159 | {% call jdbc.install('mysql') %} 160 | Either of the following MySQL-compatible JDBC drivers are supported 161 | for connecting Guacamole with MariaDB or MySQL: 162 | 163 | * [MariaDB Connector/J](https://mariadb.com/kb/en/about-mariadb-connector-j/) 164 | * [MySQL Connector/J](http://dev.mysql.com/downloads/connector/j/) (the required `.jar` will be within a `.tar.gz` archive) 165 | 166 | If you do not have a specific reason to use one driver over the other, it's 167 | recommended that you use the JDBC driver provided by your database vendor. 168 | {% endcall %} 169 | 170 | :::{important} 171 | **Older versions of MySQL Connector/J have known issues with SSL 172 | verification.** If you experience problems connecting to SSL-secured MySQL 173 | databases, it is recommended that you update to a current version of the 174 | driver. 175 | ::: 176 | 177 | {# 178 | # Configuration section (template includes all required headers) 179 | # -------------------------------------------------------------- 180 | #} 181 | {{ jdbc.config('mysql') }} 182 | 183 | Completing installation 184 | ----------------------- 185 | 186 | ```{include} include/ext-completing.md 187 | ``` 188 | 189 | (mysql-auth-default-user)= 190 | 191 | Logging in 192 | ---------- 193 | 194 | ```{include} include/jdbc-default-user.md 195 | ``` 196 | 197 | --------------------------------------------------------------------------------