totpcgi / 2fa: remove old totpci and files and roles.
Note: there are still some calls here in old fas in openshift, but we will remove those when we remove old fas (likely as soon as zodbot is ported over to noggin). Signed-off-by: Kevin Fenzi <kevin@scrye.com>
This commit is contained in:
parent
6ac5a89b14
commit
f23fd1b7a1
28 changed files with 0 additions and 1524 deletions
|
@ -1,21 +0,0 @@
|
|||
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";
|
||||
};
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
{% if env == 'staging' %}
|
||||
url = "https://fas-all.stg.phx2.fedoraproject.org:8443/"; # URI to fetch
|
||||
{% elif datacenter == 'iad2' %}
|
||||
url = "https://fas-all.iad2.fedoraproject.org:8443/"; # URI to fetch
|
||||
{% else %}
|
||||
url = "https://fas-all.vpn.fedoraproject.org:8443/"; # URI to fetch
|
||||
{% endif %}
|
||||
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";
|
||||
};
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
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";
|
||||
};
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
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";
|
||||
};
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
#%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
|
||||
account include system-auth
|
||||
password include system-auth
|
||||
session optional pam_keyinit.so revoke
|
||||
session required pam_limits.so
|
|
@ -1,6 +0,0 @@
|
|||
#%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
|
|
@ -94,16 +94,6 @@ backend freemedia-backend
|
|||
#{% endif %}
|
||||
# option httpchk GET /packages/_heartbeat
|
||||
|
||||
frontend totpcgiprovision-frontend
|
||||
bind 0.0.0.0:10019
|
||||
default_backend totpcgiprovision-backend
|
||||
|
||||
backend totpcgiprovision-backend
|
||||
balance hdr(appserver)
|
||||
http-check expect status 401
|
||||
server fas01 fas01:8444 check inter 5s rise 1 fall 2
|
||||
option httpchk GET /index.cgi
|
||||
|
||||
frontend blockerbugs-frontend
|
||||
bind 0.0.0.0:10022
|
||||
default_backend blockerbugs-backend
|
||||
|
@ -289,28 +279,6 @@ backend ipa-backend
|
|||
{% endif %}
|
||||
option httpchk GET /ipa/ui/
|
||||
|
||||
# This is for TOTPCGI (legacy 2fa). It goes to the Openshift routers, which then passthrough TLS to the totpcgi pods
|
||||
frontend totp-frontend
|
||||
mode tcp
|
||||
bind 0.0.0.0:8443
|
||||
default_backend totp-backend
|
||||
|
||||
backend totp-backend
|
||||
mode tcp
|
||||
option tcplog
|
||||
balance roundrobin
|
||||
maxconn 16384
|
||||
timeout queue 5000
|
||||
timeout server 86400000
|
||||
timeout connect 86400000
|
||||
server os-node01 os-node01:443 weight 1 maxconn 16384
|
||||
server os-node02 os-node02:443 weight 1 maxconn 16384
|
||||
server os-node03 os-node03:443 weight 1 maxconn 16384
|
||||
server os-node04 os-node04:443 weight 1 maxconn 16384
|
||||
{% if env == "production" %}
|
||||
server os-node05 os-node05:443 weight 1 maxconn 16384
|
||||
{% endif %}
|
||||
|
||||
frontend krb5-frontend
|
||||
mode tcp
|
||||
bind 0.0.0.0:1088
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?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>
|
|
@ -1,49 +0,0 @@
|
|||
<?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>
|
|
@ -1,53 +0,0 @@
|
|||
<?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>
|
|
@ -1,200 +0,0 @@
|
|||
#!/usr/bin/python -ttW ignore::DeprecationWarning
|
||||
##
|
||||
# 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 logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
import urllib2
|
||||
|
||||
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:
|
||||
logging.exception("Problem connecting to FAS")
|
||||
sys.exit(1)
|
||||
|
||||
backends = totpcgi.backends.Backends()
|
||||
|
||||
try:
|
||||
backends.load_from_config(config)
|
||||
except totpcgi.backends.BackendNotSupported, ex:
|
||||
logging.exception("Backend engine not supported")
|
||||
sys.exit(1)
|
||||
|
||||
### 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://yubikey:8080/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:
|
||||
logging.warning(
|
||||
"TOKEN FAILURE! user=%s, mode=%s, host=%s, message=%s",
|
||||
user,
|
||||
mode,
|
||||
remote_host,
|
||||
str(ex))
|
||||
bad_request(str(ex))
|
||||
|
||||
logging.info(
|
||||
"Token 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__':
|
||||
try:
|
||||
cgimain()
|
||||
except Exception:
|
||||
logging.exception("Server error during processing")
|
||||
output = 'ERR\nInternal server error\n'
|
||||
sys.stdout.write('Status: 500 SERVER ERROR\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)
|
|
@ -1,21 +0,0 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.iad2.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";
|
||||
};
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.iad2.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";
|
||||
};
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
pam_url:
|
||||
{
|
||||
settings:
|
||||
{
|
||||
url = "https://fas-all.stg.iad2.fedoraproject.org/"; # 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";
|
||||
};
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
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";
|
||||
};
|
||||
};
|
|
@ -1,265 +0,0 @@
|
|||
#!/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(display=0, logdir="/tmp")
|
||||
|
||||
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()
|
|
@ -1,11 +0,0 @@
|
|||
#%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
|
|
@ -1,6 +0,0 @@
|
|||
#%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
|
|
@ -1,6 +0,0 @@
|
|||
#%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
|
|
@ -1,236 +0,0 @@
|
|||
- name: add totpcgi user
|
||||
user: name=totpcgi uid=501 state=present home=/var/lib/totpcgi createhome=yes system=yes
|
||||
tags:
|
||||
- config
|
||||
|
||||
- name: install needed packages
|
||||
package: name={{ item }} state=present
|
||||
with_items:
|
||||
- mod_auth_pgsql
|
||||
- totpcgi
|
||||
- totpcgi-selinux
|
||||
- totpcgi-provisioning
|
||||
- python-qrcode
|
||||
- httpd
|
||||
- mod_ssl
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: Install the cgi apache configuration files
|
||||
template: >
|
||||
src={{ item.file }}.j2 dest=/etc/httpd/conf.d/{{ item.dest }}
|
||||
owner=root group=root mode=0444
|
||||
with_items:
|
||||
- {file: provisioning-httpd.conf, dest: totpcgi-provisioning.conf }
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
notify:
|
||||
- restart apache
|
||||
|
||||
- name: create directories
|
||||
file: path=/etc/{{ item }} state=directory owner=root group=totpcgi mode=750
|
||||
with_items:
|
||||
- pki/totpcgi
|
||||
- totpcgi/totp
|
||||
|
||||
- name: create template directory for totpcgiprov
|
||||
file: path=/etc/{{ item }} state=directory owner=root group=totpcgiprov mode=750
|
||||
with_items:
|
||||
- totpcgi/templates
|
||||
|
||||
- name: create /etc/totpcgi with the proper rights and owners
|
||||
file: path=/etc/{{ item }} state=directory owner=totpcgiprov group=totpcgi mode=750
|
||||
with_items:
|
||||
- totpcgi
|
||||
|
||||
- name: copy html files over
|
||||
copy: >
|
||||
src=html
|
||||
dest=/etc/totpcgi/templates
|
||||
owner=root
|
||||
group=totpcgiprov
|
||||
mode=0750
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy provisioning 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=totpcgi
|
||||
group=totpcgi
|
||||
mode=0550
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy totpcgi.conf file over
|
||||
template: >
|
||||
src=totpcgi.conf.j2
|
||||
dest=/etc/totpcgi/totpcgi.conf
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
# staging certs
|
||||
|
||||
- name: copy staging server cert file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.stg.iad2.fedoraproject.org.crt
|
||||
dest=/etc/pki/tls/certs/totpcgi-server.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "staging"
|
||||
|
||||
- name: copy staging server key file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.stg.iad2.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "staging"
|
||||
|
||||
- name: copy staging server conf file over
|
||||
template: >
|
||||
src=totpcgi-httpd.conf.stg.j2
|
||||
dest=/etc/httpd/conf.d/totpcgi.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
- sslciphers
|
||||
when: env == "staging"
|
||||
|
||||
# prod certs
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.iad2.fedoraproject.org.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
notify:
|
||||
- reload httpd
|
||||
when: env == "production"
|
||||
|
||||
- name: copy server cert file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.iad2.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
notify:
|
||||
- reload httpd
|
||||
when: env == "production"
|
||||
|
||||
- name: copy totpcgi httpd config
|
||||
template: >
|
||||
src=totpcgi-httpd.conf.j2
|
||||
dest=/etc/httpd/conf.d/totpcgi.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
- sslciphers
|
||||
notify:
|
||||
- reload httpd
|
||||
when: env == "production"
|
||||
|
||||
# vpn certs
|
||||
|
||||
- name: copy VPN server cert file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.vpn.fedoraproject.org.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-server-vpn.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
notify:
|
||||
- reload httpd
|
||||
when: env == "production"
|
||||
|
||||
- name: copy VPN server cert file over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/fas-all.vpn.fedoraproject.org.key
|
||||
dest=/etc/pki/totpcgi/totpcgi-server-vpn.key
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
when: env == "production"
|
||||
|
||||
- name: copy VPN server cert file over
|
||||
template: >
|
||||
src=totpcgi-httpd.conf.vpn.j2
|
||||
dest=/etc/httpd/conf.d/totpcgi-vpn.conf
|
||||
owner=root
|
||||
group=root
|
||||
mode=0444
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
- sslciphers
|
||||
when: env == "production"
|
||||
|
||||
- name: copy ca cert over
|
||||
copy: >
|
||||
src={{ private }}/files/2fa-certs/keys/ca.crt
|
||||
dest=/etc/pki/totpcgi/totpcgi-ca.crt
|
||||
owner=root
|
||||
group=totpcgi
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
||||
|
||||
- name: copy provisioning.conf over
|
||||
template: >
|
||||
src=provisioning.conf.j2
|
||||
dest=/etc/totpcgi/provisioning.conf
|
||||
owner=root
|
||||
group=totpcgiprov
|
||||
mode=0640
|
||||
tags:
|
||||
- files
|
||||
- config
|
|
@ -1,138 +0,0 @@
|
|||
{% macro load_file(filename) %}{% include filename %}{%- endmacro -%}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
{% if objectname == "configmap-totpcgi-vpn.yml" %}
|
||||
name: totpcgi-vpn
|
||||
{% else %}
|
||||
name: totpcgi
|
||||
{% endif %}
|
||||
labels:
|
||||
app: fas
|
||||
data:
|
||||
totpcgi-ca.crt: |-
|
||||
{{ lookup('file', '{{ private }}/files/2fa-certs/keys/ca.crt') | indent() }}
|
||||
provisioning.conf: |-
|
||||
{{ load_file('provisioning.conf.j2') | indent() }}
|
||||
totpcgi.conf: |-
|
||||
{{ load_file('totpcgi.conf.j2') | indent() }}
|
||||
start.sh: |-
|
||||
set -xe
|
||||
rm -rf /httpdir/*
|
||||
mkdir /httpdir/run
|
||||
ln -s /etc/httpd/modules /httpdir/modules
|
||||
truncate --size=0 /httpdir/accesslog /httpdir/errorlog
|
||||
tail -qf /httpdir/accesslog /httpdir/errorlog &
|
||||
exec /usr/sbin/httpd.worker -f /etc/totpcgi/httpd.conf -DFOREGROUND -DNO_DETACH
|
||||
httpd.conf: |-
|
||||
ServerRoot "/httpdir"
|
||||
PidFile "/httpdir/httpd.pid"
|
||||
LoadModule authn_file_module modules/mod_authn_file.so
|
||||
LoadModule authn_anon_module modules/mod_authn_anon.so
|
||||
LoadModule authz_user_module modules/mod_authz_user.so
|
||||
LoadModule authz_host_module modules/mod_authz_host.so
|
||||
LoadModule include_module modules/mod_include.so
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
LoadModule env_module modules/mod_env.so
|
||||
LoadModule ext_filter_module modules/mod_ext_filter.so
|
||||
LoadModule expires_module modules/mod_expires.so
|
||||
LoadModule headers_module modules/mod_headers.so
|
||||
LoadModule mime_module modules/mod_mime.so
|
||||
LoadModule dir_module modules/mod_dir.so
|
||||
LoadModule alias_module modules/mod_alias.so
|
||||
LoadModule version_module modules/mod_version.so
|
||||
LoadModule ssl_module modules/mod_ssl.so
|
||||
LoadModule auth_pgsql_module modules/mod_auth_pgsql.so
|
||||
LoadModule cgi_module modules/mod_cgi.so
|
||||
|
||||
# There's so much in python(-fedora) that wants a valid homedir....
|
||||
SetEnv HOME /httpdir
|
||||
|
||||
Listen 0.0.0.0:8080
|
||||
Listen 0.0.0.0:8443 https
|
||||
|
||||
StartServers 4
|
||||
MaxClients 300
|
||||
MinSpareThreads 25
|
||||
MaxSpareThreads 75
|
||||
ThreadsPerChild 25
|
||||
MaxRequestsPerChild 0
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
CustomLog /httpdir/accesslog combined
|
||||
ErrorLog /httpdir/errorlog
|
||||
LogLevel info
|
||||
TypesConfig /etc/mime.types
|
||||
AddDefaultCharset UTF-8
|
||||
CoreDumpDirectory /tmp
|
||||
|
||||
DirectoryIndex index.cgi
|
||||
|
||||
<VirtualHost *:8080>
|
||||
Header set Cache-Control no-cache
|
||||
Header set Expires 0
|
||||
Alias /totpcgiprovision /var/www/totpcgi-provisioning
|
||||
{% if env == "staging" %}
|
||||
Alias /totpcgiprovision/ /var/www/totpcgi-provisioning
|
||||
{% endif %}
|
||||
AddHandler cgi-script .cgi
|
||||
|
||||
DocumentRoot /var/www/totpcgi-provisioning
|
||||
<Directory "/var/www/totpcgi-provisioning">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
|
||||
<Location />
|
||||
AuthType Basic
|
||||
AuthName "Fedora totpcgi"
|
||||
|
||||
Auth_PG_host db-fas{{ env_suffix }}
|
||||
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>
|
||||
|
||||
<VirtualHost *:8443>
|
||||
{% if env == "staging" %}
|
||||
ServerName fas-all.stg.iad2.fedoraproject.org:8443
|
||||
{% elif objectname == "configmap-totpcgi-vpn.yml" %}
|
||||
ServerName fas-all.vpn.fedoraproject.org:8443
|
||||
{% elif datacenter == 'iad2' %}
|
||||
ServerName fas-all.iad2.fedoraproject.org:8443
|
||||
{% endif %}
|
||||
SSLEngine on
|
||||
{% if objectname == "configmap-totpcgi-vpn.yml" %}
|
||||
SSLCertificateFile /etc/pki/totp/tls.crt
|
||||
SSLCertificateKeyFile /etc/pki/totp/tls.key
|
||||
{% else %}
|
||||
SSLCertificateFile /etc/pki/totp/tls.crt
|
||||
SSLCertificateKeyFile /etc/pki/totp/tls.key
|
||||
{% endif %}
|
||||
SSLCACertificateFile /etc/totpcgi/totpcgi-ca.crt
|
||||
SSLHonorCipherOrder On
|
||||
SSLCipherSuite {{ ssl_ciphers }}
|
||||
SSLProtocol {{ ssl_protocols }}
|
||||
AddHandler cgi-script .cgi
|
||||
|
||||
SSLVerifyClient require
|
||||
SSLVerifyDepth 10
|
||||
|
||||
DocumentRoot /var/www/totpcgi
|
||||
<Directory "/var/www/totpcgi">
|
||||
Options ExecCGI
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
error.html: |-
|
||||
{{ lookup('file', '{{ roles_path }}/totpcgi/files/html/error.html') | indent() }}
|
||||
login.html: |-
|
||||
{{ lookup('file', '{{ roles_path }}/totpcgi/files/html/login.html') | indent() }}
|
||||
totp.html: |-
|
||||
{{ lookup('file', '{{ roles_path }}/totpcgi/files/html/totp.html') | indent() }}
|
|
@ -1,44 +0,0 @@
|
|||
Listen 8444
|
||||
<VirtualHost *:8444>
|
||||
LoadModule suexec_module modules/mod_suexec.so
|
||||
|
||||
DocumentRoot /var/www/totpcgi-provisioning
|
||||
ServerName fas01.stg.iad2.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>
|
|
@ -1,88 +0,0 @@
|
|||
[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 = 6
|
||||
|
||||
# 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 env == "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
|
||||
|
||||
# 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{{ env_suffix }}.{{ datacenter }}.fedoraproject.org dbname=totpcgi
|
||||
|
||||
[pincode_backend]
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiadminDBUser }} password={{ totpcgiadminDBPassword }} host=db-fas01{{ env_suffix }}.{{ datacenter }}.fedoraproject.org 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{{ env_suffix }}.{{ datacenter }}.fedoraproject.org dbname=totpcgi
|
|
@ -1,37 +0,0 @@
|
|||
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.iad2.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
|
||||
SSLHonorCipherOrder On
|
||||
SSLCipherSuite {{ ssl_ciphers }}
|
||||
SSLProtocol {{ ssl_protocols }}
|
||||
|
||||
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>
|
|
@ -1,37 +0,0 @@
|
|||
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.iad2.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
|
||||
SSLHonorCipherOrder On
|
||||
SSLCipherSuite {{ ssl_ciphers }}
|
||||
SSLProtocol {{ ssl_protocols }}
|
||||
|
||||
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>
|
|
@ -1,36 +0,0 @@
|
|||
<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
|
||||
SSLHonorCipherOrder On
|
||||
SSLCipherSuite {{ ssl_ciphers }}
|
||||
SSLProtocol {{ ssl_protocols }}
|
||||
|
||||
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>
|
|
@ -1,31 +0,0 @@
|
|||
[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{{ env_suffix }}.{{ datacenter }}.fedoraproject.org dbname=totpcgi
|
||||
|
||||
[pincode_backend]
|
||||
engine = pgsql
|
||||
pg_connect_string = user={{ totpcgiDBUser }} password={{ totpcgiDBPassword }} host=db-fas01{{ env_suffix }}.{{ datacenter }}.fedoraproject.org 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{{ env_suffix }}.{{ datacenter }}.fedoraproject.org dbname=totpcgi
|
|
@ -1,40 +0,0 @@
|
|||
---
|
||||
- name: install pam_url
|
||||
package: name=pam_url state=present
|
||||
tags:
|
||||
- packages
|
||||
- 2fa
|
||||
|
||||
- name: /etc/pki/tls/private/totpcgi.pem
|
||||
copy: src="{{ private }}/files/2fa-certs/keys/{{ inventory_hostname }}.pem" dest=/etc/pki/tls/private/totpcgi.pem mode=0400
|
||||
tags:
|
||||
- config
|
||||
- 2fa
|
||||
|
||||
- name: /etc/pki/tls/private/totpcgi-ca.cert
|
||||
copy: src="{{ private }}/files/2fa-certs/keys/ca.crt" dest=/etc/pki/tls/private/totpcgi-ca.cert mode=0400
|
||||
tags:
|
||||
- config
|
||||
- 2fa
|
||||
|
||||
- name: /etc/pam_url.conf - split for staging/phx2/everyone else
|
||||
template: src={{ item }} dest=/etc/pam_url.conf mode=0644
|
||||
with_first_found:
|
||||
- "{{ files }}/2fa/pam_url.conf.{{ inventory_hostname }}"
|
||||
- "{{ files }}/2fa/pam_url.conf.{{ ansible_domain }}"
|
||||
- "{{ files }}/2fa/pam_url.conf.{{ datacenter }}"
|
||||
- "{{ files }}/2fa/pam_url.conf.j2"
|
||||
tags:
|
||||
- config
|
||||
- pam_url
|
||||
- 2fa
|
||||
|
||||
- name: /etc/pam.d/sudo
|
||||
copy: src={{ item }} dest=/etc/pam.d/sudo mode=0644
|
||||
with_first_found:
|
||||
- "{{ files }}/2fa/sudo.pam.{{ inventory_hostname }}"
|
||||
- "{{ files }}/2fa/sudo.pam.{{ ansible_domain }}"
|
||||
- "{{ files }}/2fa/sudo.pam"
|
||||
tags:
|
||||
- config
|
||||
- 2fa
|
Loading…
Add table
Add a link
Reference in a new issue