Add totpcgi role.
This commit is contained in:
parent
07e24f8448
commit
6af7a7b8a7
20 changed files with 1174 additions and 0 deletions
|
@ -41,6 +41,7 @@
|
|||
- rsyncd
|
||||
- fas_server
|
||||
- sudo
|
||||
- totpcgi
|
||||
|
||||
tasks:
|
||||
- include: "{{ tasks }}/yumrepos.yml"
|
||||
|
|
26
roles/totpcgi/files/html/error.html
Normal file
26
roles/totpcgi/files/html/error.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Fedora Project Google Authenticator provisioning - Error</title>
|
||||
<link href="${css_root}provisioning.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainwindow" class="status">
|
||||
<div id="title">Fedora Project - Error</div>
|
||||
<div id="mainarea">
|
||||
<p class="error">
|
||||
$errormsg
|
||||
</p>
|
||||
<p>
|
||||
You can <a href="$action_url">try again</a> or you can contact
|
||||
the Fedora Infrastructure team at <a href="mailto:admin@fedoraproject.org">admin@fedoraproject.org</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div id="copyright">
|
||||
© 2012 Red Hat, Inc. and others.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
49
roles/totpcgi/files/html/login.html
Normal file
49
roles/totpcgi/files/html/login.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Fedora Project Google Authenticator provisioning</title>
|
||||
<link href="${css_root}provisioning.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainwindow" class="login">
|
||||
<div id="title">Fedora Project</div>
|
||||
<div id="mainarea">
|
||||
<div class="message">
|
||||
Please log in to obtain your new Google Authenticator
|
||||
secret.
|
||||
</div>
|
||||
<form id="login_form" name="login_form" action="$action_url" method="post">
|
||||
<table border="0" align="center">
|
||||
<tr>
|
||||
<td class="fieldname">
|
||||
<label for="username">Username:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="username" name="username" class="inputfield"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="fieldname">
|
||||
<label for="pincode">Pincode:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" id="pincode" name="pincode" class="inputfield"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="fieldname"></td>
|
||||
<td>
|
||||
<input type="submit" value="Submit »"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<div id="copyright">
|
||||
© 2012 Red Hat, Inc. and others.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
53
roles/totpcgi/files/html/totp.html
Normal file
53
roles/totpcgi/files/html/totp.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Fedora Project Google Authenticator Provisioning</title>
|
||||
<link href="${css_root}provisioning.css" rel="stylesheet" type="text/css" />
|
||||
<link href="${css_root}provisioning-print.css" rel="stylesheet" media="print" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainwindow" class="totp">
|
||||
<div id="title">Fedora Project Google Authenticator Provisioning</div>
|
||||
<div id="mainarea">
|
||||
<div id="qrcode">
|
||||
$qrcode_embed
|
||||
</div>
|
||||
<div id="explanation">
|
||||
<p>
|
||||
Your new Google Authenticator token has been issued.
|
||||
To import this token into your device, simply go to your
|
||||
Google Authenticator app, select the option to add an
|
||||
account, and then select "Scan Barcode". Point the camera
|
||||
at the QR Barcode displayed next to this message. Google
|
||||
Authenticator will then import your new token into the
|
||||
device. It should be ready to use immediately.
|
||||
</p>
|
||||
</div>
|
||||
<div id="scratch_tokens">
|
||||
<p>
|
||||
If the administrator permitted the use of scratch tokens,
|
||||
you should see them listed below. If you lose access to
|
||||
your Google Authenticator device, you should be able to
|
||||
use one of these tokens to gain emergency access to your
|
||||
account. Please write them down.
|
||||
</p>
|
||||
<div id="scratch_tokens_list">
|
||||
$scratch_tokens
|
||||
</div>
|
||||
</div>
|
||||
<div id="support_requests">
|
||||
<p>
|
||||
If you require any help with your Google Authenticator
|
||||
token or experience any difficulty importing it into
|
||||
your mobile device, please email
|
||||
<a href="mailto:admin@fedoraproject.org">admin@fedoraproject.org</a>.
|
||||
</div>
|
||||
</div>
|
||||
<div id="copyright">
|
||||
© 2012 Red Hat, Inc. and others.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
189
roles/totpcgi/files/index.cgi
Normal file
189
roles/totpcgi/files/index.cgi
Normal file
|
@ -0,0 +1,189 @@
|
|||
#!/usr/bin/python -tt
|
||||
##
|
||||
# Copyright (C) 2012 by Konstantin Ryabitsev and contributors
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import cgi
|
||||
import syslog
|
||||
import logging
|
||||
import urllib2
|
||||
|
||||
import cgitb
|
||||
cgitb.enable()
|
||||
|
||||
import totpcgi
|
||||
import totpcgi.backends
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
# blindly assume it's the config file
|
||||
config_file = sys.argv[1]
|
||||
else:
|
||||
config_file = '/etc/totpcgi/totpcgi.conf'
|
||||
|
||||
import ConfigParser
|
||||
|
||||
from fedora.client import AuthError
|
||||
from fedora.client.fasproxy import FasProxyClient
|
||||
|
||||
config = ConfigParser.RawConfigParser()
|
||||
config.read(config_file)
|
||||
|
||||
require_pincode = config.getboolean('main', 'require_pincode')
|
||||
success_string = config.get('main', 'success_string')
|
||||
|
||||
fas_url = config.get('main', 'fas_url')
|
||||
try:
|
||||
fas = FasProxyClient(fas_url)
|
||||
except Exception, e:
|
||||
syslog.syslog(syslog.LOG_CRIT, 'Problem connecting to fas %s' % e)
|
||||
sys.exit(1)
|
||||
|
||||
backends = totpcgi.backends.Backends()
|
||||
|
||||
try:
|
||||
backends.load_from_config(config)
|
||||
except totpcgi.backends.BackendNotSupported, ex:
|
||||
syslog.syslog(syslog.LOG_CRIT,
|
||||
'Backend engine not supported: %s' % ex)
|
||||
sys.exit(1)
|
||||
|
||||
syslog.openlog('totp.cgi', syslog.LOG_PID, syslog.LOG_AUTH)
|
||||
|
||||
### Begin custom Fedora Functions
|
||||
|
||||
def google_auth_fas_pincode_verify(user, pincode):
|
||||
if not fas.verify_password(user, pincode):
|
||||
raise totpcgi.UserPincodeError('User Password Error')
|
||||
|
||||
backends.pincode_backend.verify_user_pincode = google_auth_fas_pincode_verify
|
||||
|
||||
client_id = '1'
|
||||
|
||||
def parse_token(token):
|
||||
if token > 44:
|
||||
otp = token[-44:]
|
||||
if otp.startswith('ccccc'):
|
||||
return token[:-44], otp
|
||||
|
||||
# Not a password + yubikey
|
||||
return False
|
||||
|
||||
class YubikeyAuthenticator(object):
|
||||
auth_regex = re.compile('^status=(?P<rc>\w{2})')
|
||||
def __init__(self, require_pincode=False):
|
||||
self.require_pincode = require_pincode
|
||||
|
||||
def verify_user_token(self, user, token):
|
||||
# Parse the token apart into a password and token
|
||||
password, otp = parse_token(token)
|
||||
|
||||
# Verify token against yubikey server
|
||||
server_prefix = 'http://localhost/yk-val/verify?id='
|
||||
server_url = server_prefix + client_id + "&otp=" + otp
|
||||
|
||||
fh = urllib2.urlopen(server_url)
|
||||
|
||||
for line in fh:
|
||||
match = self.auth_regex.search(line.strip('\n'))
|
||||
if match:
|
||||
if match.group('rc') == 'OK':
|
||||
# Yubikey token is valid
|
||||
break
|
||||
raise totpcgi.VerifyFailed(line.split('=')[1])
|
||||
else:
|
||||
raise totpcgi.VerifyFailed('yk-val returned malformed response')
|
||||
|
||||
|
||||
# Verify that the yubikey token belongs to the user
|
||||
# As a side effect, verify the password is good as well
|
||||
# if the user+password are wrong, this will raise a fedora.client.AuthError
|
||||
try:
|
||||
response = fas.send_request('/config/list/%s/yubikey' % user,
|
||||
auth_params={'username': user, 'password': password})
|
||||
except AuthError, e:
|
||||
raise totpcgi.VerifyFailed('User Password Error: %s' % e)
|
||||
if not response[1].configs.prefix or not response[1].configs.enabled:
|
||||
raise totpcgi.VerifyFailed('Yubikey OTP unconfigured')
|
||||
elif len(response[1].configs.prefix) != 12:
|
||||
raise totpcgi.VerifyFailed('Invalid Yubikey OTP prefix')
|
||||
if not otp.startswith(response[1].configs.prefix):
|
||||
raise totpcgi.VerifyFailed('Unauthorized/Invalid OTP')
|
||||
|
||||
# Okay, everything passed
|
||||
return 'Valid yubikey returned'
|
||||
|
||||
|
||||
### End of custom Fedora Functions
|
||||
|
||||
def bad_request(why):
|
||||
output = 'ERR\n' + why + '\n'
|
||||
sys.stdout.write('Status: 400 BAD REQUEST\n')
|
||||
sys.stdout.write('Content-type: text/plain\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(output))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(output)
|
||||
sys.exit(0)
|
||||
|
||||
def cgimain():
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
must_keys = ('user', 'token', 'mode')
|
||||
|
||||
for must_key in must_keys:
|
||||
if must_key not in form:
|
||||
bad_request("Missing field: %s" % must_key)
|
||||
|
||||
user = form.getfirst('user')
|
||||
token = form.getfirst('token')
|
||||
mode = form.getfirst('mode')
|
||||
|
||||
remote_host = os.environ['REMOTE_ADDR']
|
||||
|
||||
if mode != 'PAM_SM_AUTH':
|
||||
bad_request('We only support PAM_SM_AUTH')
|
||||
|
||||
if parse_token(token):
|
||||
ga = YubikeyAuthenticator(require_pincode)
|
||||
else:
|
||||
# totp/googleauth
|
||||
ga = totpcgi.GoogleAuthenticator(backends, require_pincode)
|
||||
|
||||
try:
|
||||
status = ga.verify_user_token(user, token)
|
||||
except Exception, ex:
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Failure: user=%s, mode=%s, host=%s, message=%s' % (user, mode,
|
||||
remote_host, str(ex)))
|
||||
bad_request(str(ex))
|
||||
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Success: user=%s, mode=%s, host=%s, message=%s' % (user, mode,
|
||||
remote_host, status))
|
||||
|
||||
sys.stdout.write('Status: 200 OK\n')
|
||||
sys.stdout.write('Content-type: text/plain\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(success_string))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(success_string)
|
||||
|
||||
if __name__ == '__main__':
|
||||
cgimain()
|
21
roles/totpcgi/files/pam_url.conf
Normal file
21
roles/totpcgi/files/pam_url.conf
Normal file
|
@ -0,0 +1,21 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.phx2.fedoraproject.org:8443/"; # URI to fetch
|
||||
returncode = "OK"; # The remote script/cgi should return a 200 http code and this string as its only results
|
||||
userfield = "user"; # userfield name to send
|
||||
passwdfield = "token"; # passwdfield name to send
|
||||
extradata = "&do=login"; # extradata to send
|
||||
prompt = "Password+Token: "; # password prompt
|
||||
};
|
||||
|
||||
ssl:
|
||||
{
|
||||
verify_peer = true; # Should we verify SSL ?
|
||||
verify_host = true; # Should we verify the CN in the SSL cert?
|
||||
client_cert = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side certificate
|
||||
client_key = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side key (can be same file as above if a single cert)
|
||||
ca_cert = "/etc/pki/tls/private/totpcgi-ca.cert";
|
||||
};
|
||||
};
|
21
roles/totpcgi/files/pam_url.conf.fakefas01
Normal file
21
roles/totpcgi/files/pam_url.conf.fakefas01
Normal file
|
@ -0,0 +1,21 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.phx2.fedoraproject.org:8443/"; # URI to fetch
|
||||
returncode = "OK"; # The remote script/cgi should return a 200 http code and this string as its only results
|
||||
userfield = "user"; # userfield name to send
|
||||
passwdfield = "token"; # passwdfield name to send
|
||||
extradata = "&do=login"; # extradata to send
|
||||
prompt = "Password+Token: "; # password prompt
|
||||
};
|
||||
|
||||
ssl:
|
||||
{
|
||||
verify_peer = true; # Should we verify SSL ?
|
||||
verify_host = true; # Should we verify the CN in the SSL cert?
|
||||
client_cert = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side certificate
|
||||
client_key = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side key (can be same file as above if a single cert)
|
||||
ca_cert = "/etc/pki/tls/private/totpcgi-ca.cert";
|
||||
};
|
||||
};
|
21
roles/totpcgi/files/pam_url.conf.stg
Normal file
21
roles/totpcgi/files/pam_url.conf.stg
Normal file
|
@ -0,0 +1,21 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.stg.phx2.fedoraproject.org:8443/"; # URI to fetch
|
||||
returncode = "OK"; # The remote script/cgi should return a 200 http code and this string as its only results
|
||||
userfield = "user"; # userfield name to send
|
||||
passwdfield = "token"; # passwdfield name to send
|
||||
extradata = "&do=login"; # extradata to send
|
||||
prompt = "Password+Token: "; # password prompt
|
||||
};
|
||||
|
||||
ssl:
|
||||
{
|
||||
verify_peer = true; # Should we verify SSL ?
|
||||
verify_host = true; # Should we verify the CN in the SSL cert?
|
||||
client_cert = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side certificate
|
||||
client_key = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side key (can be same file as above if a single cert)
|
||||
ca_cert = "/etc/pki/tls/private/totpcgi-ca.cert";
|
||||
};
|
||||
};
|
21
roles/totpcgi/files/pam_url.conf.vpn
Normal file
21
roles/totpcgi/files/pam_url.conf.vpn
Normal file
|
@ -0,0 +1,21 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.vpn.fedoraproject.org:8443/"; # URI to fetch
|
||||
returncode = "OK"; # The remote script/cgi should return a 200 http code and this string as its only results
|
||||
userfield = "user"; # userfield name to send
|
||||
passwdfield = "token"; # passwdfield name to send
|
||||
extradata = "&do=login"; # extradata to send
|
||||
prompt = "Password+Token: "; # password prompt
|
||||
};
|
||||
|
||||
ssl:
|
||||
{
|
||||
verify_peer = true; # Should we verify SSL ?
|
||||
verify_host = true; # Should we verify the CN in the SSL cert?
|
||||
client_cert = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side certificate
|
||||
client_key = "/etc/pki/tls/private/totpcgi.pem"; # file to use as client-side key (can be same file as above if a single cert)
|
||||
ca_cert = "/etc/pki/tls/private/totpcgi-ca.cert";
|
||||
};
|
||||
};
|
265
roles/totpcgi/files/provisioning.cgi
Normal file
265
roles/totpcgi/files/provisioning.cgi
Normal file
|
@ -0,0 +1,265 @@
|
|||
#!/usr/bin/python -tt
|
||||
##
|
||||
# Copyright (C) 2012 by Konstantin Ryabitsev and contributors
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
import cgi
|
||||
import syslog
|
||||
import logging
|
||||
|
||||
import cgitb
|
||||
cgitb.enable()
|
||||
|
||||
import totpcgi
|
||||
import totpcgi.backends
|
||||
import totpcgi.utils
|
||||
|
||||
import qrcode
|
||||
from qrcode.image import svg
|
||||
from StringIO import StringIO
|
||||
|
||||
from string import Template
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
# blindly assume it's the config file
|
||||
config_file = sys.argv[1]
|
||||
else:
|
||||
config_file = '/etc/totpcgi/provisioning.conf'
|
||||
|
||||
import ConfigParser
|
||||
|
||||
config = ConfigParser.RawConfigParser()
|
||||
config.read(config_file)
|
||||
|
||||
backends = totpcgi.backends.Backends()
|
||||
|
||||
try:
|
||||
backends.load_from_config(config)
|
||||
except totpcgi.backends.BackendNotSupported, ex:
|
||||
syslog.syslog(syslog.LOG_CRIT,
|
||||
'Backend engine not supported: %s' % ex)
|
||||
sys.exit(1)
|
||||
|
||||
syslog.openlog('provisioning.cgi', syslog.LOG_PID, syslog.LOG_AUTH)
|
||||
|
||||
def bad_request(config, why):
|
||||
templates_dir = config.get('secret', 'templates_dir')
|
||||
fh = open(os.path.join(templates_dir, 'error.html'))
|
||||
tpt = Template(fh.read())
|
||||
fh.close()
|
||||
|
||||
vals = {
|
||||
'action_url': config.get('secret', 'action_url'),
|
||||
'css_root': config.get('secret', 'css_root'),
|
||||
'errormsg': cgi.escape(why)
|
||||
}
|
||||
|
||||
out = tpt.safe_substitute(vals)
|
||||
|
||||
sys.stdout.write('Status: 400 BAD REQUEST\n')
|
||||
sys.stdout.write('Content-type: text/html\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(out))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(out)
|
||||
sys.exit(0)
|
||||
|
||||
def show_qr_code(data):
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=5,
|
||||
border=4)
|
||||
|
||||
qr.add_data(data)
|
||||
qr.make(fit=True)
|
||||
|
||||
img = qr.make_image()
|
||||
|
||||
fh = StringIO()
|
||||
img.save(fh)
|
||||
out = fh.getvalue()
|
||||
fh.close()
|
||||
|
||||
sys.stdout.write('Status: 200 OK\n')
|
||||
sys.stdout.write('Content-type: image/png\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(out))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(out)
|
||||
sys.exit(0)
|
||||
|
||||
def show_login_form(config):
|
||||
templates_dir = config.get('secret', 'templates_dir')
|
||||
fh = open(os.path.join(templates_dir, 'login.html'))
|
||||
tpt = Template(fh.read())
|
||||
fh.close()
|
||||
|
||||
vals = {
|
||||
'action_url': config.get('secret', 'action_url'),
|
||||
'css_root': config.get('secret', 'css_root')
|
||||
}
|
||||
|
||||
out = tpt.safe_substitute(vals)
|
||||
|
||||
sys.stdout.write('Status: 200 OK\n')
|
||||
sys.stdout.write('Content-type: text/html\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(out))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(out)
|
||||
sys.exit(0)
|
||||
|
||||
def show_totp_page(config, user, gaus):
|
||||
# generate provisioning URI
|
||||
tpt = Template(config.get('secret', 'totp_user_mask'))
|
||||
totp_user = tpt.safe_substitute(username=user)
|
||||
totp_qr_uri = gaus.totp.provisioning_uri(totp_user)
|
||||
|
||||
action_url = config.get('secret', 'action_url')
|
||||
|
||||
qrcode_embed = '<img src="%s?qrcode=%s"/>' % (action_url, totp_qr_uri)
|
||||
|
||||
templates_dir = config.get('secret', 'templates_dir')
|
||||
fh = open(os.path.join(templates_dir, 'totp.html'))
|
||||
tpt = Template(fh.read())
|
||||
fh.close()
|
||||
|
||||
if gaus.scratch_tokens:
|
||||
scratch_tokens = '<br/>'.join(gaus.scratch_tokens)
|
||||
else:
|
||||
scratch_tokens = ' '
|
||||
|
||||
vals = {
|
||||
'action_url': action_url,
|
||||
'css_root': config.get('secret', 'css_root'),
|
||||
'qrcode_embed': qrcode_embed,
|
||||
'scratch_tokens': scratch_tokens
|
||||
}
|
||||
|
||||
out = tpt.safe_substitute(vals)
|
||||
|
||||
sys.stdout.write('Status: 200 OK\n')
|
||||
sys.stdout.write('Content-type: text/html\n')
|
||||
sys.stdout.write('Content-Length: %s\n' % len(out))
|
||||
sys.stdout.write('\n')
|
||||
|
||||
sys.stdout.write(out)
|
||||
sys.exit(0)
|
||||
|
||||
def generate_secret(config):
|
||||
encrypt_secret = config.getboolean('secret', 'encrypt_secret')
|
||||
window_size = config.getint('secret', 'window_size')
|
||||
rate_limit = config.get('secret', 'rate_limit')
|
||||
|
||||
# scratch tokens don't make any sense with encrypted secret
|
||||
if not encrypt_secret:
|
||||
scratch_tokens_n = config.getint('secret', 'scratch_tokens_n')
|
||||
else:
|
||||
scratch_tokens_n = 0
|
||||
|
||||
(times, secs) = rate_limit.split(',')
|
||||
rate_limit = (int(times), int(secs))
|
||||
|
||||
gaus = totpcgi.utils.generate_secret(rate_limit, window_size,
|
||||
scratch_tokens_n)
|
||||
|
||||
return gaus
|
||||
|
||||
|
||||
def cgimain():
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
if 'qrcode' in form:
|
||||
#if os.environ['HTTP_REFERER'].find(os.environ['SERVER_NAME']) == -1:
|
||||
# bad_request(config, 'Sorry, you failed the HTTP_REFERER check')
|
||||
|
||||
qrcode = form.getfirst('qrcode')
|
||||
show_qr_code(qrcode)
|
||||
|
||||
remote_host = os.environ['REMOTE_ADDR']
|
||||
|
||||
try:
|
||||
trust_http_auth = config.getboolean('secret', 'trust_http_auth')
|
||||
except ConfigParser.NoOptionError:
|
||||
trust_http_auth = False
|
||||
|
||||
if trust_http_auth and os.environ.has_key('REMOTE_USER'):
|
||||
user = os.environ['REMOTE_USER']
|
||||
pincode = None
|
||||
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Success (http-auth): user=%s, host=%s' % (user, remote_host))
|
||||
|
||||
else:
|
||||
must_keys = ('username', 'pincode')
|
||||
|
||||
for must_key in must_keys:
|
||||
if must_key not in form:
|
||||
show_login_form(config)
|
||||
|
||||
user = form.getfirst('username')
|
||||
pincode = form.getfirst('pincode')
|
||||
|
||||
# start by verifying the pincode
|
||||
try:
|
||||
backends.pincode_backend.verify_user_pincode(user, pincode)
|
||||
except Exception, ex:
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Failure: user=%s, host=%s, message=%s' % (user, remote_host,
|
||||
str(ex)))
|
||||
bad_request(config, str(ex))
|
||||
|
||||
# pincode verified
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Success: user=%s, host=%s' % (user, remote_host))
|
||||
|
||||
# is there an existing secret for this user?
|
||||
exists = True
|
||||
|
||||
try:
|
||||
backends.secret_backend.get_user_secret(user, pincode)
|
||||
except totpcgi.UserNotFound:
|
||||
# if we got it, then there isn't an existing secret in place
|
||||
exists = False
|
||||
|
||||
if exists:
|
||||
syslog.syslog(syslog.LOG_NOTICE,
|
||||
'Secret exists: user=%s, host=%s' % (user, remote_host))
|
||||
bad_request(config, 'Existing secret found. It must be removed first.')
|
||||
|
||||
# now generate the secret and store it
|
||||
|
||||
gaus = generate_secret(config)
|
||||
|
||||
# if we don't need to encrypt the secret, set pincode to None
|
||||
encrypt_secret = config.getboolean('secret', 'encrypt_secret')
|
||||
if not encrypt_secret:
|
||||
pincode = None
|
||||
|
||||
backends.secret_backend.save_user_secret(user, gaus, pincode)
|
||||
# purge all old state, as it's now obsolete
|
||||
|
||||
backends.state_backend.delete_user_state(user)
|
||||
|
||||
show_totp_page(config, user, gaus)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cgimain()
|
11
roles/totpcgi/files/sudo.pam
Normal file
11
roles/totpcgi/files/sudo.pam
Normal file
|
@ -0,0 +1,11 @@
|
|||
#%PAM-1.0
|
||||
auth required pam_env.so
|
||||
auth sufficient pam_url.so config=/etc/pam_url.conf
|
||||
auth requisite pam_succeed_if.so uid >= 500 quiet
|
||||
auth required pam_deny.so
|
||||
|
||||
auth include system-auth
|
||||
account include system-auth
|
||||
password include system-auth
|
||||
session optional pam_keyinit.so revoke
|
||||
session required pam_limits.so
|
6
roles/totpcgi/files/sudo.pam.dev.fedoraproject.org
Normal file
6
roles/totpcgi/files/sudo.pam.dev.fedoraproject.org
Normal file
|
@ -0,0 +1,6 @@
|
|||
#%PAM-1.0
|
||||
auth include system-auth
|
||||
account include system-auth
|
||||
password include system-auth
|
||||
session optional pam_keyinit.so revoke
|
||||
session required pam_limits.so
|
6
roles/totpcgi/files/sudo.pam.qa.fedoraproject.org
Normal file
6
roles/totpcgi/files/sudo.pam.qa.fedoraproject.org
Normal file
|
@ -0,0 +1,6 @@
|
|||
#%PAM-1.0
|
||||
auth include system-auth
|
||||
account include system-auth
|
||||
password include system-auth
|
||||
session optional pam_keyinit.so revoke
|
||||
session required pam_limits.so
|
34
roles/totpcgi/files/totpcgi-httpd.conf
Normal file
34
roles/totpcgi/files/totpcgi-httpd.conf
Normal file
|
@ -0,0 +1,34 @@
|
|||
Listen 8443
|
||||
<VirtualHost 10.5.126.30:8443 10.5.126.25:8443 10.5.126.26:8443>
|
||||
# Load this module locally here.
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
|
||||
ServerAdmin admin@fedoraproject.org
|
||||
DocumentRoot /var/www/totpcgi
|
||||
ServerName fas-all.phx2.fedoraproject.org:8443
|
||||
ErrorLog /var/log/httpd/totpcgi-error.log
|
||||
SuexecUserGroup totpcgi totpcgi
|
||||
|
||||
# Use this for totp.cgi
|
||||
AddHandler cgi-script .cgi
|
||||
DirectoryIndex index.cgi
|
||||
|
||||
# Or use this for totp.fcgi:
|
||||
#AddHandler fcgid-script .fcgi
|
||||
#DirectoryIndex index.fcgi
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/pki/totpcgi/totpcgi-server.crt
|
||||
SSLCertificateKeyFile /etc/pki/totpcgi/totpcgi-server.key
|
||||
SSLCACertificateFile /etc/pki/totpcgi/totpcgi-ca.crt
|
||||
|
||||
SSLVerifyClient require
|
||||
SSLVerifyDepth 10
|
||||
|
||||
CustomLog /var/log/httpd/totpcgi-ssl-request-log \
|
||||
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
|
||||
|
||||
<Directory "/var/www/totpcgi">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
</VirtualHost>
|
34
roles/totpcgi/files/totpcgi-httpd.conf.stg
Normal file
34
roles/totpcgi/files/totpcgi-httpd.conf.stg
Normal file
|
@ -0,0 +1,34 @@
|
|||
Listen 8443
|
||||
<VirtualHost *:8443>
|
||||
# Load this module locally here.
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
|
||||
ServerAdmin admin@fedoraproject.org
|
||||
DocumentRoot /var/www/totpcgi
|
||||
ServerName fas-all.stg.phx2.fedoraproject.org:8443
|
||||
ErrorLog /var/log/httpd/totpcgi-error.log
|
||||
SuexecUserGroup totpcgi totpcgi
|
||||
|
||||
# Use this for totp.cgi
|
||||
AddHandler cgi-script .cgi
|
||||
DirectoryIndex index.cgi
|
||||
|
||||
# Or use this for totp.fcgi:
|
||||
#AddHandler fcgid-script .fcgi
|
||||
#DirectoryIndex index.fcgi
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/pki/totpcgi/totpcgi-server.crt
|
||||
SSLCertificateKeyFile /etc/pki/totpcgi/totpcgi-server.key
|
||||
SSLCACertificateFile /etc/pki/totpcgi/totpcgi-ca.crt
|
||||
|
||||
SSLVerifyClient require
|
||||
SSLVerifyDepth 10
|
||||
|
||||
CustomLog /var/log/httpd/totpcgi-ssl-request-log \
|
||||
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
|
||||
|
||||
<Directory "/var/www/totpcgi">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
</VirtualHost>
|
33
roles/totpcgi/files/totpcgi-httpd.conf.vpn
Normal file
33
roles/totpcgi/files/totpcgi-httpd.conf.vpn
Normal file
|
@ -0,0 +1,33 @@
|
|||
<VirtualHost 192.168.1.38:8443 192.168.1.39:8443 192.168.1.49:8443>
|
||||
# Load this module locally here.
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
|
||||
ServerAdmin admin@fedoraproject.org
|
||||
DocumentRoot /var/www/totpcgi
|
||||
ServerName fas-all.vpn.fedoraproject.org:8443
|
||||
ErrorLog /var/log/httpd/totpcgi-error.log
|
||||
SuexecUserGroup totpcgi totpcgi
|
||||
|
||||
# Use this for totp.cgi
|
||||
AddHandler cgi-script .cgi
|
||||
DirectoryIndex index.cgi
|
||||
|
||||
# Or use this for totp.fcgi:
|
||||
#AddHandler fcgid-script .fcgi
|
||||
#DirectoryIndex index.fcgi
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/pki/totpcgi/totpcgi-server-vpn.crt
|
||||
SSLCertificateKeyFile /etc/pki/totpcgi/totpcgi-server-vpn.key
|
||||
SSLCACertificateFile /etc/pki/totpcgi/totpcgi-ca.crt
|
||||
|
||||
SSLVerifyClient require
|
||||
SSLVerifyDepth 10
|
||||
|
||||
CustomLog /var/log/httpd/totpcgi-ssl-request-log \
|
||||
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
|
||||
|
||||
<Directory "/var/www/totpcgi">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
</VirtualHost>
|
220
roles/totpcgi/tasks/main.yml
Normal file
220
roles/totpcgi/tasks/main.yml
Normal file
|
@ -0,0 +1,220 @@
|
|||
- name: install needed packages
|
||||
yum: pkg={{ item }} state=present
|
||||
with_items:
|
||||
- mod_auth_psql
|
||||
- totpcgi
|
||||
- totpcgi-selinux
|
||||
- totpcgi-provisioning
|
||||
- python-qrcode
|
||||
- httpd
|
||||
- mod_ssl
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: add totpcgi user
|
||||
user: name=totpcgi uid=430 state=present home=/var/lib/totpcgi createhome=yes system=yes
|
||||
tags:
|
||||
- config
|
||||
|
||||
- name: Install the cgi apache configuration files
|
||||
template: >
|
||||
src={{ item }}.j2 dest=/etc/httpd/conf.d/{{ item }}
|
||||
owner=root group=root mode=0444
|
||||
with_items:
|
||||
- provisioning-httpd.conf
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
notify:
|
||||
- restart apache
|
||||
|
||||
- name: create directories
|
||||
file: path=/etc/{{ item.path }} state=directory owner=root group=totpcgi mode=750
|
||||
with_items:
|
||||
- pki/totpcgi
|
||||
- totpcgi
|
||||
- totpcgi/templates
|
||||
- totpcgi/totp
|
||||
|
||||
- name: copy index file over
|
||||
copy: >
|
||||
src=html
|
||||
dest=/etc/totpcgi/templates/html
|
||||
owner=root
|
||||
group=totpcgiprov
|
||||
mode=0750
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy index file over
|
||||
copy: >
|
||||
src=provisioning.cgi
|
||||
dest=/var/www/totpcgi-provisioning/index.cgi
|
||||
owner=totpcgiprov
|
||||
group=totpcgiprov
|
||||
mode=0550
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy index file over
|
||||
copy: >
|
||||
src=index.cgi
|
||||
dest=/var/www/totpcgi/index.cgi
|
||||
owner=totpcgiprov
|
||||
group=totpcgiprov
|
||||
mode=0550
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy totpcgi.conf file over
|
||||
template: >
|
||||
src=totpcgi.conf.j2
|
||||
dest=/etc/totpcgi/totpcgi.conf
|
||||
owner=root
|
||||
group=totpcgiprov
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
# staging certs
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/2fa-certs/keys/fas-all.stg.phx2.fedoraproject.org.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "staging"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/fa-certs/keys/fas-all.stg.phx2.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "staging"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src=totpcgi-httpd.conf.stg
|
||||
dest=/etc/httpd/conf.d/totpcgi.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "staging"
|
||||
|
||||
# prod certs
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/2fa-certs/keys/fas-all.phx2.fedoraproject.org.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/fa-certs/keys/fas-all.phx2.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src=totpcgi-httpd.conf
|
||||
dest=/etc/httpd/conf.d/totpcgi.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
# vpn certs
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/2fa-certs/keys/fas-all.phx2.fedoraproject.org.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_secure }}/fa-certs/keys/fas-all.phx2.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src=totpcgi-httpd.conf
|
||||
dest=/etc/httpd/conf.d/totpcgi.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
#
|
||||
# TODO: vpn certs
|
||||
#
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ puppet_private }}/2fa-certs/keys/ca.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-ca.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy server cert file over
|
||||
template: >
|
||||
src=provisioning.conf.j2
|
||||
dest=/etc/totpcgi/provisioning.conf
|
||||
owner=root
|
||||
group=totpcgiprov
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
44
roles/totpcgi/templates/provisioning-httpd.conf.j2
Normal file
44
roles/totpcgi/templates/provisioning-httpd.conf.j2
Normal file
|
@ -0,0 +1,44 @@
|
|||
Listen 8444
|
||||
<VirtualHost *:8444>
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
|
||||
DocumentRoot /var/www/totpcgi-provisioning
|
||||
ServerName fas01.stg.phx2.fedoraproject.org:8444
|
||||
ErrorLog /var/log/httpd/totpcgi-provisioning-error.log
|
||||
SuexecUserGroup totpcgiprov totpcgiprov
|
||||
|
||||
AddHandler cgi-script .cgi
|
||||
DirectoryIndex index.cgi
|
||||
|
||||
Header set Cache-Control no-cache
|
||||
Header set Expires 0
|
||||
|
||||
#SSLEngine on
|
||||
#SSLCertificateFile /etc/pki/totpcgi/totpcgi-server.crt
|
||||
#SSLCertificateKeyFile /etc/pki/totpcgi/totpcgi-server.key
|
||||
#SSLCACertificateFile /etc/pki/totpcgi/totpcgi-ca.crt
|
||||
|
||||
#CustomLog /var/log/httpd/totpcgi-provisioning-ssl-request-log \
|
||||
# "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
|
||||
|
||||
<Directory "/var/www/totpcgi-provisioning">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
|
||||
<Location />
|
||||
AuthType Basic
|
||||
AuthName "Fedora totpcgi"
|
||||
|
||||
Auth_PG_host db-fas
|
||||
Auth_PG_port 5432
|
||||
Auth_PG_user fasreadonly
|
||||
Auth_PG_pwd {{ fasReadOnlyPassword }}
|
||||
Auth_PG_database fas2
|
||||
Auth_PG_pwd_table people
|
||||
Auth_PG_uid_field username
|
||||
Auth_PG_pwd_field password
|
||||
Auth_PG_pwd_whereclause " and status='active'"
|
||||
|
||||
Require valid-user
|
||||
</Location>
|
||||
</VirtualHost>
|
88
roles/totpcgi/templates/provisioning.conf.j2
Normal file
88
roles/totpcgi/templates/provisioning.conf.j2
Normal file
|
@ -0,0 +1,88 @@
|
|||
[secret]
|
||||
# Whether to encrypt the secret when we generate it. Encrypting the secret
|
||||
# with the user's pincode means that even if the .totp file is leaked, an
|
||||
# attacker will not be able to get the secret without knowing the user's
|
||||
# pincode. The downside is that if a user forgets their pincode, both the
|
||||
# pincode and the secret will need to be fully re-provisioned.
|
||||
# Setting to "True" will also turn off scratch-token support.
|
||||
encrypt_secret = False
|
||||
|
||||
# You can allow for some clock drift between the client and server by setting
|
||||
# the permitted window size. Window size is calculated in 10-second intervals,
|
||||
# so a window size of 6 allows clock drift of 60 seconds in either direction.
|
||||
window_size = 3
|
||||
|
||||
# First value is the number of times. Second value is the number of seconds.
|
||||
# So, "3, 30" means "3 falures within 30 seconds"
|
||||
rate_limit = 3, 30
|
||||
|
||||
# How many scratch tokens to generate. Note, that this setting is ignored
|
||||
# if encrypt_secret is set to True.
|
||||
scratch_tokens_n = 5
|
||||
|
||||
# This identifies the token in the Google Authenticator application. It comes
|
||||
# very handy when users have more than one token, so set this to something
|
||||
# descriptive of your environment.
|
||||
{% if environment == "staging" %}
|
||||
totp_user_mask = $username@stg.fedoraproject.org
|
||||
{% else %}
|
||||
totp_user_mask = $username@fedoraproject.org
|
||||
{% endif %}
|
||||
|
||||
# Used by provisioning.cgi
|
||||
# Where the provisioning CGI is located, with regards to the web root.
|
||||
action_url = /totpcgiprovision/index.cgi
|
||||
|
||||
# Used by provisioning.cgi
|
||||
# Where provisioning.css and provisioning-print.css are located with regards
|
||||
# to the web root.
|
||||
css_root = /totpcgiprovision/
|
||||
|
||||
# Used by provisioning.cgi
|
||||
# Where to find the templates files.
|
||||
templates_dir = /etc/totpcgi/templates
|
||||
|
||||
# Used by provisioning.cgi
|
||||
# Whether to rely on HTTP auth to handle authentication.
|
||||
# As we don't get the password, only the username, turning this on
|
||||
# will automatically set encrypt_secret to false.
|
||||
#
|
||||
# Be careful turning this on.
|
||||
trust_http_auth = True
|
||||
|
||||
|
||||
[pincode]
|
||||
# Which hashing mechanism to use. Valid entries: md5, bcrypt, sha256, sha512
|
||||
usehash = sha256
|
||||
|
||||
# Whether to compile the DBM database (only meaningful with the file backend)
|
||||
makedb = True
|
||||
|
||||
# The backends are pretty much the same as in totpcgi.conf, except if you
|
||||
# are using the postgresql secret backend, you need to connect as a user
|
||||
# that is allowed to modify user records (e.g. totpcgi_admin).
|
||||
[secret_backend]
|
||||
;engine = file
|
||||
;secrets_dir = /etc/totpcgi/totp
|
||||
|
||||
; For PostgreSQL backend:
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiadminDBUser }} password={{ totpcgiadminDBPassword }} host=db-fas01 dbname=totpcgi
|
||||
|
||||
[pincode_backend]
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiadminDBUser }} password={{ totpcgiadminDBPassword }} host=db-fas01 dbname=totpcgi
|
||||
|
||||
; For LDAP backend (simple bind auth):
|
||||
;engine = ldap
|
||||
;ldap_url = ldaps://ipa.example.com:636/
|
||||
;ldap_dn = uid=$username,cn=users,cn=accounts,dc=example,dc=com
|
||||
;ldap_cacert = /etc/pki/tls/certs/ipa-ca.crt
|
||||
|
||||
[state_backend]
|
||||
;engine = file
|
||||
;state_dir = /var/lib/totpcgi
|
||||
|
||||
; For PostgreSQL backend:
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiadminDBUser }} password={{ totpcgiadminDBPassword }} host=db-fas01 dbname=totpcgi
|
31
roles/totpcgi/templates/totpcgi.conf.j2
Normal file
31
roles/totpcgi/templates/totpcgi.conf.j2
Normal file
|
@ -0,0 +1,31 @@
|
|||
[main]
|
||||
require_pincode = True
|
||||
success_string = OK
|
||||
{% if env == "staging" %}
|
||||
fas_url = https://admin.stg.fedoraproject.org/accounts/
|
||||
{% else %}
|
||||
fas_url = https://admin.fedoraproject.org/accounts/
|
||||
{% endif %}
|
||||
|
||||
[secret_backend]
|
||||
; For PostgreSQL backend:
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiDBUser }} password={{ totpcgiDBPassword }} host=db-fas01 dbname=totpcgi
|
||||
|
||||
[pincode_backend]
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiDBUser }} password={{ totpcgiDBPassword }} host=db-fas01 dbname=totpcgi
|
||||
|
||||
; For LDAP backend (simple bind auth):
|
||||
;engine = ldap
|
||||
;ldap_url = ldaps://ipa.example.com:636/
|
||||
;ldap_dn = uid=$username,cn=users,cn=accounts,dc=example,dc=com
|
||||
;ldap_cacert = /etc/pki/tls/certs/ipa-ca.crt
|
||||
|
||||
[state_backend]
|
||||
;engine = file
|
||||
;state_dir = /var/lib/totpcgi
|
||||
|
||||
; For PostgreSQL backend:
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiDBUser }} password={{ totpcgiDBPassword }} host=db-fas01 dbname=totpcgi
|
Loading…
Add table
Add a link
Reference in a new issue