guacamole-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Bonnes <da...@bonnes.name>
Subject Re: How-to - Guacamole with Google Authenticator for 2FA
Date Sun, 01 Oct 2017 08:49:30 GMT
Thanks,

For anyone trying, I should warn you that *cas.authn.jdbc.encode* doesn't
look compatible with the salted SHA-256 passwords as stored in Guacamole's
guacamole_db (which is why I used
*cas.authn.jdbc.query[0].fieldPassword=username* (i.e. username rather than
password) for my test-bed; in theory, *cas.authn.jdbc.encode* should works
with a NULL salt, but I couldn't get that working either (I thought maybe
due to upper/lowercase mismatch of hex strings?).

My impression of CAS is that it is notoriously difficult to get working due
to it's relative paucity of documentation / sample configurations, and its
development / release ethos.  On that basis, any write-up would benefit CAS
even more than Guacamole!

The good news regarding TOTP 2FA is that if you look at GUACAMOLE-96
<https://issues.apache.org/jira/browse/GUACAMOLE-96>, there may be some
good news soon enough.


On Sun, 1 Oct 2017 at 02:21 Nick Couchman <vnick@apache.org> wrote:

> David,
> Thanks for the fantastic write-up!  I think using CAS only for Guacamole
> 2FA is probably overkill for most folks, but if you're already using CAS or
> want CAS for 2FA for other stuff, and want to integrate Guacamole into it,
> this is great.  I'll try to take a look at your write-up in detail and
> provide some suggested edits for it.  Don't know exactly where the best
> place to post it would be, but I definitely think it should be made
> available!  I think it probably should be made available to a wider
> audience than just the Guacamole folks, as I think it's probably useful for
> folks who want to do 2FA with CAS, in general.
>
> -Nick
>
> On Fri, Sep 29, 2017 at 6:09 PM, David Bonnes <david@bonnes.name> wrote:
>
>> For humor, I set up a Apereo CAS server as a means to use gauth/TOTP as a
>> second-factor for authenticating with guacmole.  It was working 100%, but
>> personally, I'll be sticking with DUO for now.  However, I think some
>> people would want this feature.
>>
>> I really think the method I used needs writing up somewhere for the
>> benefit of the community (and doubtless for them to improve), but I am not
>> the person to do that...
>>
>> Is someone willing to edit my notes, and post a nice tutorial somewhere?
>> For the right person (i.e. some evidence you'll write up a nice how-to), I
>> am willing to take some time to explain what worked, what didn't, and why.
>>
>> If not, and in any case, here is the bulk of my notes/scripts...
>>
>>
>> #!/bin/bash
>>
>> ####################################################################################################################################
>> #0. Confirm that Guacamole is working with MySQL (have something in the
>> profile)
>> #1. Test basic config of CAS via CAS - need to set log folder
>> #2. Switch to static account (same name as one in 0.) via CAS - consider
>> SHA256 encoding
>> #3. Test auth through guacuamole - should see profile (will need service
>> registry)
>> #4. Switch to jdbc auth (QUERY) on CAS - (may need to set permission for
>> guac_username) - can test auth-d via cas logon page first
>> #5. As above, but with Gauth
>>
>> ####################################################################################################################################
>>
>>
>> ####################################################################################################################################
>> ## Install CAS webapp via the overlay method
>> # can change <cas.version> in pom.xml for other versions...
>>   mkdir /opt; cd /opt
>>   git clone -b 5.2 https://github.com/apereo/cas-overlay-template cas
>>   cd cas
>>   chmod a+x build.sh
>>
>>
>>
>>
>>
>> ####################################################################################################################################
>> # To eliminate: "Non-secure Connection" warning, add secure="true" to
>> 8080 of /var/lib/tomcat8/conf/server.xml
>>
>> ### ./etc/cas/config/log4j2.xml: set <Property
>> name="cas.log.dir">/var/log/tomcat8</Property>
>>   sed -i -e '/"cas.log.dir"/ s:>.*<:>/var/log/tomcat8<:'
>> etc/cas/config/log4j2.xml
>>   mkdir -p /etc/cas/logs; chmod a+w /etc/cas/logs
>>
>> ### ./pom.xml - will need this eventually
>> #       <Property name="cas.version">5.2.0-RC4-SNAPSHOT</Property>
>>
>> ## ./etc/cas/config/cas.properties
>> ## Enable logging...
>>   logging.level.org.apereo: TRACE
>>   logging.config: file:/etc/cas/config/log4j2.xml
>>
>> ## Set CAS server name URL...
>>   cas.server.name:   https://vm-builder.home:8443
>>   cas.server.prefix: ${cas.server.name}/cas
>>
>> ## Enable basic admin pages...
>>   cas.adminPagesSecurity.ip=172\.27\.0\.99
>>   cas.monitor.endpoints.enabled=true
>>   cas.monitor.endpoints.sensitive=false
>>
>>
>>
>>
>> ####################################################################################################################################
>>
>>
>> service tomcat8 stop
>> rm    /var/log/tomcat8/*; rm /etc/cas/logs/*
>> rm -r /var/lib/tomcat8/webapps/cas; rm /var/lib/tomcat8/webapps/cas.war
>> ./build.sh package
>> cp /opt/cas/target/cas.war /var/lib/tomcat8/webapps
>> cp -r etc/cas/ /etc
>> service tomcat8 restart
>> tail -f /var/log/tomcat8/catalina.out
>>
>>
>>
>> ####################################################################################################################################
>> # see:
>> https://apereo.github.io/cas/5.1.x/installation/Whitelist-Authentication.html
>>
>>
>> ### ./etc/cas/config/cas.properties
>> ## A whitelist of users (use SHA-256 password hash)...
>> # cas.authn.accept.users=dbonnes::P@ssw0rd
>>
>> cas.authn.accept.users=dbonnes::d61bcb77d84080738bd59999993b181400992e8c272b372bb4e33522427936
>>   cas.authn.accept.passwordEncoder.type=DEFAULT
>>   cas.authn.accept.passwordEncoder.characterEncoding=UTF-8
>>   cas.authn.accept.passwordEncoder.encodingAlgorithm=SHA-256
>>
>>
>>
>>
>> ####################################################################################################################################
>> # see:
>> https://groups.google.com/a/apereo.org/forum/#!topic/cas-user/jJ8OOyoQoBw
>>
>> ### ./pom.xml
>> <dependency>
>>     <groupId>org.apereo.cas</groupId>
>>     <artifactId>cas-server-support-json-service-registry</artifactId>
>>     <version>${cas.version}</version>
>> </dependency>
>>
>> ### ./etc/cas/config/cas.properties
>> ## Register default services, including: ^(https|imaps)://.* [ **NOT**
>> http://.* ]
>> # cas.serviceRegistry.initFromJson=true
>> ## Register specified services (this is fixed on/before
>> 5.2.0-RC2-SNAPSHOT, but after 5.1.4)
>>   cas.serviceRegistry.json.location=file:/etc/cas/services
>>
>> ### ./etc/cas/services/http-1001.json
>>   mkdir -p etc/cas/services
>>
>>   cat <<EOF > etc/cas/services/http-1001.json
>> {
>>   "@class" : "org.apereo.cas.services.RegexRegisteredService",
>>   "serviceId" : "^(https|http)://.*",
>>   "name" : "HTTP(S), for testbeds only",
>>   "id" : 1001,
>> }
>>
>> EOF
>>
>> ## Check via: cat /var/log/tomcat8/cas.log | grep http
>>
>>
>>
>> ####################################################################################################################################
>> ## Guac says: *appends* Salt to password, see:
>> https://guacamole.incubator.apache.org/doc/gug/jdbc-auth.html
>> # -- Generate salt
>> SET @salt = UNHEX(SHA2(UUID(), 256));
>>
>> # -- Create user and hash password with salt
>> INSERT INTO guacamole_user (username, password_salt, password_hash)
>>      VALUES ('myuser', @salt, UNHEX(SHA2(CONCAT('mypassword',
>> HEX(@salt)), 256)));
>>
>> ## But, CAS says: *prepends* Salt to password
>> # "This password encoding method combines the private Salt and the public
>> salt which it prepends to the password before hashing."
>>
>>
>> ### ./pom.xml
>> <dependency>
>>     <groupId>org.apereo.cas</groupId>
>>     <artifactId>cas-server-support-jdbc</artifactId>
>>     <version>${cas.version}</version>
>> </dependency>
>>
>> <dependency>
>>    <groupId>org.apereo.cas</groupId>
>>    <artifactId>cas-server-support-jdbc-drivers</artifactId>
>>    <version>${cas.version}</version>
>> </dependency>
>>
>> ### ./etc/cas/config/cas.properties [ using QUERY ]
>> ## Disable demo accounts (i.e. casuser::Mellon)
>>   cas.authn.accept.users=
>>
>> # Beware: java.sql.SQLException: Access denied for user 'guac_username'@'172.27.0.999'
>> (using password: YES)
>> ## Using JDBC query authentication...
>>
>> cas.authn.jdbc.query[0].url=jdbc:mysql://lxc-mysql.home:3306/guacamole_db?useSSL=false
>>   cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
>> # cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQL5Dialect
>>   cas.authn.jdbc.query[0].user=guacamole_user
>>   cas.authn.jdbc.query[0].password=guac_Passw0rd
>>
>>   cas.authn.jdbc.query[0].sql=SELECT * FROM guacamole_user WHERE
>> username=?
>>   cas.authn.jdbc.query[0].fieldDisabled=disabled
>>   cas.authn.jdbc.query[0].fieldExpired=expired
>>   cas.authn.jdbc.query[0].fieldPassword=username
>>
>>   cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
>>   cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
>>   cas.authn.jdbc.encode[0].passwordEncoder.encodingAlgorithm=SHA-256
>>
>>
>>
>> ### ./etc/cas/config/cas.properties [ using ENCODE ]
>> ## see:
>> https://apereo.github.io/cas/5.1.x/installation/Configuration-Properties.html#encode-database-authentication
>> ## Using JDBC encode authentication...
>>
>> cas.authn.jdbc.encode[0].url=jdbc:mysql://lxc-mysql.home:3306/guacamole_db?useSSL=false
>>   cas.authn.jdbc.encode[0].driverClass=com.mysql.cj.jdbc.Driver
>>   cas.authn.jdbc.encode[0].dialect=org.hibernate.dialect.MySQL5Dialect
>>   cas.authn.jdbc.encode[0].user=guacamole_user
>>   cas.authn.jdbc.encode[0].password=guac_Passw0rd
>>
>>   cas.authn.jdbc.encode[0].sql=SELECT * FROM guacamole_user WHERE
>> username=?
>>   cas.authn.jdbc.encode[0].fieldDisabled=disabled
>>   cas.authn.jdbc.encode[0].fieldExpired=expired
>>
>> # cas.authn.jdbc.encode[0].numberOfIterations=1
>> # cas.authn.jdbc.encode[0].staticSalt=
>>   cas.authn.jdbc.encode[0].saltFieldName=password_salt
>>   cas.authn.jdbc.encode[0].passwordFieldName=password_hash
>>   cas.authn.jdbc.encode[0].algorithmName=SHA-256
>>
>>
>> ## Check via: mysql -u guacamole_user --password=guac_Passw0rd -h
>> lxc-mysql.home (from (say) lxc-tomcat: apt install -y mysql-client)
>> #  USE guacamole_db;
>> #  SELECT username, disabled, expired FROM guacamole_user;
>> #  SELECT username, LOWER(hex(password_hash)), hex(password_salt) FROM
>> guacamole_user;
>>
>> echo -n 'P@ssw0rd' | sha256sum
>>
>> USE guacamole_db;
>> SET @username = "myuser2";
>> SET @password = "P@ssw0rd";
>> INSERT INTO guacamole_user (username, password_salt, password_hash,
>> password_date)
>>   VALUES (@username, NULL, LOWER(UNHEX(SHA2(@password, 256))), NOW());
>>
>>
>>
>> ####################################################################################################################################
>>
>> ####################################################################################################################################
>>
>> ### ./pom.xml
>> <dependency>
>>      <groupId>org.apereo.cas</groupId>
>>      <artifactId>cas-server-support-gauth</artifactId>
>>      <version>${cas.version}</version>
>> </dependency>
>>
>>
>> ### ./etc/cas/services/
>> # default: failureMode=NOT_SET,bypassEnabled=false
>>   cat <<EOF > etc/cas/services/http-1001.json
>> {
>>
>>   "@class" : "org.apereo.cas.services.RegexRegisteredService",
>>   "serviceId" : "^(https|http)://.*",
>>   "name" : "HTTP(S)/MFA, for testbeds only",
>>   "id" : 1001,
>>   "multifactorPolicy" : {
>>     "@class" :
>> "org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy",
>>     "multifactorAuthenticationProviders" : [ "java.util.LinkedHashSet", [
>> "mfa-gauth" ] ],
>>     "bypassEnabled" : false,
>>     "failureMode" : "CLOSED"
>>   }
>> }
>>
>> EOF
>>
>>
>> ### ./etc/cas/config/cas.properties
>>
>> ## Multifactor Authentication, see:
>> https://apereo.github.io/cas/5.1.x/installation/Configuring-Multifactor-Authentication.html
>> ## Activate MFA globally for all, regardless of other (e.g.
>> service-specific) settings
>>   cas.authn.mfa.globalProviderId=mfa-gauth
>> # Describe the global failure mode in case provider cannot be reached
>> (CLOSED means Auth fails)
>>   cas.authn.mfa.globalFailureMode=CLOSED
>>
>> ## Configure google authenticator
>>   cas.authn.mfa.gauth.windowSize=3
>>   cas.authn.mfa.gauth.codeDigits=6
>>   cas.authn.mfa.gauth.timeStepSize=30
>>   cas.authn.mfa.gauth.trustedDeviceEnabled=true
>>   cas.authn.mfa.gauth.issuer=Guacamole
>>   cas.authn.mfa.gauth.label=ZXlabelZX
>>   cas.authn.mfa.gauth.name=ZXnameZX
>>
>>
>> ## Check via: cat /var/log/tomcat8/catalina.out | grep gauth
>>
>>
>>
>>
>> ####################################################################################################################################
>>
>> ####################################################################################################################################
>>
>> ### Create the Guacamole DB/user ('%' instead of 'localhost' for remote
>> access) for user accounts/profiles:
>>   mysql -u root --password=${sql_root_passwd} <<EOF
>> # MySQL script to create JPA DB & user
>>   CREATE DATABASE gauth_db;
>>   CREATE USER 'gauth_user'@'%' IDENTIFIED BY 'gauth_Passw0rd';
>>   GRANT ALL PRIVILEGES ON gauth_db.* TO 'gauth_user'@'%';
>>   FLUSH PRIVILEGES;
>>   quit
>> EOF
>>
>> ## Check via:  (from (say) lxc-tomcat: apt install -y mysql-client)
>> # mysql -u gauth_user --password=gauth_Passw0rd -h lxc-mysql.home
>> # USE gauth_db;
>> # SHOW tables;
>>
>>
>> ### ./pom.xml (this needs jdbc DB)
>> <dependency>
>>      <groupId>org.apereo.cas</groupId>
>>      <artifactId>cas-server-support-gauth-jpa</artifactId>
>>      <version>${cas.version}</version>
>> </dependency>
>>
>>
>> ### ./etc/cas/config/cas.properties
>> ## jpa
>>
>> cas.authn.mfa.gauth.jpa.database.url=jdbc:mysql://lxc-mysql.home:3306/gauth_db?useSSL=false
>>   cas.authn.mfa.gauth.jpa.database.driverClass=com.mysql.cj.jdbc.Driver
>>
>> cas.authn.mfa.gauth.jpa.database.dialect=org.hibernate.dialect.MySQL5Dialect
>>   cas.authn.mfa.gauth.jpa.database.user=gauth_user
>>   cas.authn.mfa.gauth.jpa.database.password=gauth_Passw0rd
>>   cas.authn.mfa.gauth.jpa.database.healthQuery=SELECT version()
>>
>> # see:
>> https://stackoverflow.com/questions/42135114/how-does-exactly-spring-jpa-hibernate-ddl-auto-property-works-in-spring
>> # see:
>> https://github.com/apereo/cas/blob/1e2497e1836e76e42698f050e7e2fcd53348af2b/docs/cas-server-documentation/installation/Configuration-Properties-Common.md
>> # cas.authn.mfa.gauth.jpa.database.ddlAuto=validate | update | create |
>> create-drop -- create, then (stop tomcat, then) update?
>>   cas.authn.mfa.gauth.jpa.database.ddlAuto=update
>>
>> # cas.authn.mfa.gauth.jpa.database.ddlAuto=none
>> # cas.authn.mfa.gauth.jpa.database.dataSourceName=???
>>
>>
>>
>>
>>
>> ####################################################################################################################################
>>
>> ####################################################################################################################################
>>
>> #ENDS
>>
>>
>> ####################################################################################################################################
>>
>> ####################################################################################################################################
>> ## PreReq: wget -qO- https://api.duosecurity.com/auth/v2/ping | grep OK
>> ##         wget -qO- https://api-2bf290a0.duosecurity.com/rest/v1/ping |
>> grep OK
>>
>>
>> ### ./pom.xml
>> <dependency>
>>      <groupId>org.apereo.cas</groupId>
>>      <artifactId>cas-server-support-duo</artifactId>
>>      <version>${cas.version}</version>
>> </dependency>
>>
>> ## error: NoClassDefFoundError: com/duosecurity/client/Http
>> ## see:
>> https://apereo.github.io/cas/5.1.x/installation/DuoSecurity-Authentication.html
>> ## You may need to add the following repositories to the WAR overlay...
>> <repository>
>>     <id>duo</id>
>>     <url>https://dl.bintray.com/uniconiam/maven</url>
>> </repository>
>> <repository>
>>     <id>duoclient</id>
>>     <url>https://jitpack.io</url>
>> </repository>
>>
>>
>> ### ./etc/cas/config/cas.properties
>>
>> ## Activate MFA globally for all, regardless of other settings
>>   cas.authn.mfa.globalProviderId=mfa-duo
>>
>> ## Describe the global failure mode in case provider cannot be reached
>> # cas.authn.mfa.globalFailureMode=PHANTOM
>>
>> ## Settings for duo
>>   cas.authn.mfa.duo[0].id=mfa-duo
>> # cas.authn.mfa.duo[0].rank=0
>>   cas.authn.mfa.duo[0].duoApiHost=api-2bf29099.duosecurity.com
>>   cas.authn.mfa.duo[0].duoIntegrationKey=DIN8CV999RGLL77VZ
>>   cas.authn.mfa.duo[0].duoSecretKey=23qm5rpZd2hAgRcR1td8fVJi9ww638p099VPBZ
>>   cas.authn.mfa.duo[0].duoApplicationKey=fb1c21e199999935b2ab3f999016786
>> # cas.authn.mfa.duo[0].trustedDeviceEnabled=true
>> # cas.authn.mfa.duo[0].name=
>>
>> # cas.authn.mfa.duo[0].bypass.principalAttributeName=bypass|skip
>> # cas.authn.mfa.duo[0].bypass.principalAttributeValue=true|enabled.+
>> # cas.authn.mfa.duo[0].bypass.authenticationAttributeName=bypass|skip
>> #
>> cas.authn.mfa.duo[0].bypass.authenticationAttributeValue=allowed.+|enabled.+
>> # cas.authn.mfa.duo[0].bypass.authenticationHandlerName=AcceptUsers.+
>> #
>> cas.authn.mfa.duo[0].bypass.authenticationMethodName=LdapAuthentication.+
>> # cas.authn.mfa.duo[0].bypass.credentialClassType=UsernamePassword.+
>>
>>
>> # cas.authn.mfa.gauth.json.config.location=file:/somewhere.json
>>
>>   cat <<EOF > etc/cas/services/http-1001.json
>> {
>>   "@class" : "org.apereo.cas.services.RegexRegisteredService",
>>   "serviceId" : "^(https|http)://.*",
>>   "name" : "App Secured by CAS and Duo",
>>   "id" : 1001,
>>   "description" : "HTTP secured with username/password and Duo MFA
>> protection",
>>   "attributeReleasePolicy" : {
>>     "@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
>>   },
>>
>>   "multifactorPolicy" : {
>>     "@class" :
>> "org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy",
>>     "multifactorAuthenticationProviders" : [ "java.util.LinkedHashSet", [
>> "mfa-duo" ] ],
>>     "bypassEnabled" : false,
>>     "failureMode" : "CLOSED"
>>   },
>>
>>   "evaluationOrder" : 100
>> }
>>
>> EOF
>>
>>
>>
>>
>>
>

Mime
View raw message