mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-22 16:25:17 +00:00
Token mechanism fixes:
* Save token secret to config * OpenVPN profile fixes for Ubuntu 16.04 * Raise correct exceptions for invalid tokens * Display token expiration time in local time
This commit is contained in:
parent
7651c220c8
commit
029ee357fb
@ -1,4 +1,5 @@
|
|||||||
import click
|
import click
|
||||||
|
import falcon
|
||||||
import logging
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
@ -12,12 +13,6 @@ from certidude.auth import login_required, authorize_admin
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
chars = string.ascii_letters + string.digits + '!@#$%^&*()'
|
|
||||||
SECRET = ''.join(random.choice(chars) for i in range(32))
|
|
||||||
|
|
||||||
click.echo("Token secret: %s" % SECRET)
|
|
||||||
|
|
||||||
|
|
||||||
KEYWORDS = (
|
KEYWORDS = (
|
||||||
(u"Android", u"android"),
|
(u"Android", u"android"),
|
||||||
(u"iPhone", u"iphone"),
|
(u"iPhone", u"iphone"),
|
||||||
@ -36,16 +31,17 @@ class TokenResource(object):
|
|||||||
username = req.get_param("u", required=True)
|
username = req.get_param("u", required=True)
|
||||||
user = User.objects.get(username)
|
user = User.objects.get(username)
|
||||||
csum = hashlib.sha256()
|
csum = hashlib.sha256()
|
||||||
csum.update(SECRET)
|
csum.update(config.TOKEN_SECRET)
|
||||||
csum.update(username)
|
csum.update(username)
|
||||||
csum.update(str(timestamp))
|
csum.update(str(timestamp))
|
||||||
|
|
||||||
if csum.hexdigest() != req.get_param("c", required=True):
|
if csum.hexdigest() != req.get_param("c", required=True):
|
||||||
raise # TODO
|
raise falcon.HTTPUnauthorized("Forbidden", "Invalid token supplied, did you copy-paste link correctly?")
|
||||||
if now < timestamp:
|
if now < timestamp:
|
||||||
raise # Token not valid yet
|
raise falcon.HTTPUnauthorized("Forbidden", "Token not valid yet, are you sure server clock is correct?")
|
||||||
if now > timestamp + config.TOKEN_LIFETIME:
|
if now > timestamp + config.TOKEN_LIFETIME:
|
||||||
raise # token expired
|
raise falcon.HTTPUnauthorized("Forbidden", "Token expired")
|
||||||
|
|
||||||
# At this point consider token to be legitimate
|
# At this point consider token to be legitimate
|
||||||
|
|
||||||
common_name = username
|
common_name = username
|
||||||
@ -83,12 +79,17 @@ class TokenResource(object):
|
|||||||
user = User.objects.get(username)
|
user = User.objects.get(username)
|
||||||
timestamp = int(time())
|
timestamp = int(time())
|
||||||
csum = hashlib.sha256()
|
csum = hashlib.sha256()
|
||||||
csum.update(SECRET)
|
csum.update(config.TOKEN_SECRET)
|
||||||
csum.update(username)
|
csum.update(username)
|
||||||
csum.update(str(timestamp))
|
csum.update(str(timestamp))
|
||||||
args = "u=%s&t=%d&c=%s" % (username, timestamp, csum.hexdigest())
|
args = "u=%s&t=%d&c=%s" % (username, timestamp, csum.hexdigest())
|
||||||
token_created = datetime.utcfromtimestamp(timestamp)
|
|
||||||
token_expires = datetime.utcfromtimestamp(timestamp + config.TOKEN_LIFETIME)
|
# Token lifetime in local time, to select timezone: dpkg-reconfigure tzdata
|
||||||
|
token_created = datetime.fromtimestamp(timestamp)
|
||||||
|
token_expires = datetime.fromtimestamp(timestamp + config.TOKEN_LIFETIME)
|
||||||
|
with open("/etc/timezone") as fh:
|
||||||
|
token_timezone = fh.read().strip()
|
||||||
|
|
||||||
context = globals()
|
context = globals()
|
||||||
context.update(locals())
|
context.update(locals())
|
||||||
mailer.send("token.md", to=user, **context)
|
mailer.send("token.md", to=user, **context)
|
||||||
|
@ -790,6 +790,9 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, country,
|
|||||||
rpm("python-setproctitle pyOpenSSL python-falcon python-humanize python-markdown pyxattr")
|
rpm("python-setproctitle pyOpenSSL python-falcon python-humanize python-markdown pyxattr")
|
||||||
pip("gssapi")
|
pip("gssapi")
|
||||||
|
|
||||||
|
# Generate secret for tokens
|
||||||
|
token_secret = ''.join(random.choice(string.letters + string.digits + '!@#$%^&*()') for i in range(50))
|
||||||
|
|
||||||
template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates")
|
template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates")
|
||||||
|
|
||||||
if not directory:
|
if not directory:
|
||||||
|
@ -99,5 +99,6 @@ BUNDLE_FORMAT = cp.get("token", "format")
|
|||||||
OPENVPN_PROFILE_TEMPLATE = cp.get("token", "openvpn profile template")
|
OPENVPN_PROFILE_TEMPLATE = cp.get("token", "openvpn profile template")
|
||||||
TOKEN_URL = cp.get("token", "url")
|
TOKEN_URL = cp.get("token", "url")
|
||||||
TOKEN_LIFETIME = cp.getint("token", "lifetime")
|
TOKEN_LIFETIME = cp.getint("token", "lifetime")
|
||||||
|
TOKEN_SECRET = cp.get("token", "secret")
|
||||||
|
|
||||||
# TODO: Check if we don't have base or servers
|
# TODO: Check if we don't have base or servers
|
||||||
|
@ -9,10 +9,11 @@ To set up OpenVPN for your device:
|
|||||||
* for Android install [OpenVPN Connect](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) app. After importing the OpenVPN profile in OpenVPN application and delete the downloaded .ovpn file.
|
* for Android install [OpenVPN Connect](https://play.google.com/store/apps/details?id=de.blinkt.openvpn) app. After importing the OpenVPN profile in OpenVPN application and delete the downloaded .ovpn file.
|
||||||
* for iOS device install [OpenVPN Connect](https://itunes.apple.com/us/app/openvpn-connect/id590379981) app. Tap on the token URL below, it should be automatically opened with OpenVPN Connect app. Tap connect to establish connection.
|
* for iOS device install [OpenVPN Connect](https://itunes.apple.com/us/app/openvpn-connect/id590379981) app. Tap on the token URL below, it should be automatically opened with OpenVPN Connect app. Tap connect to establish connection.
|
||||||
* for Mac OS X download [Tunnelblick](https://tunnelblick.net/downloads.html)
|
* for Mac OS X download [Tunnelblick](https://tunnelblick.net/downloads.html)
|
||||||
* for Ubuntu and Fedora install OpenVPN plugin for NetworkManager. Open network settings, add connection and select "Import from file ...". Supply the file retrieved via the token URL below.
|
* for Ubuntu install [OpenVPN plugin for NetworkManager](apt://network-manager-openvpn-gnome), click on the token link below to download OpenVPN profile. Click on the NetworkManager icon, select "Edit Connections...", click on "Add" button to add a connection. From the dropdown menu select "Import a saved VPN configuration..." and supply the downloaded file.
|
||||||
* for Windows you need to install OpenVPN community edition from [here](https://swupdate.openvpn.org/community/releases/openvpn-install-2.3.14-I601-x86_64.exe) and TAP driver from [here](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe)
|
* for Fedora install OpenVPN plugin for NetworkManager. Open network settings, add connection and select "Import a saved VPN configuration...". Supply the file retrieved via the token URL below.
|
||||||
|
* for Windows install OpenVPN community edition from [here](https://swupdate.openvpn.org/community/releases/openvpn-install-2.3.14-I601-x86_64.exe) and TAP driver from [here](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe)
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
Click [here]({{ config.TOKEN_URL }}?{{ args }}) to claim the token.
|
Click [here]({{ config.TOKEN_URL }}?{{ args }}) to claim the token.
|
||||||
Token is usable until {{ token_expires }} (UTC).
|
Token is usable until {{ token_expires }} ({{ token_timezone }} time).
|
||||||
|
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
# Copy this file to /etc/certidude/template.ovpn and customize gateway IP addresses
|
# Copy this file to /etc/certidude/template.ovpn and customize as you see fit
|
||||||
|
|
||||||
# Run as client
|
# Note: don't append comments to lines, Ubuntu 16.04 NetworkManager importer is very picky
|
||||||
client # tls-client; pull
|
# See more potential problems here:
|
||||||
nobind
|
# https://askubuntu.com/questions/761684/error-the-plugin-does-not-support-import-capability-when-attempting-to-import
|
||||||
|
|
||||||
|
# Run as OpenVPN client, pull routes, DNS server, DNS suffix from gateway
|
||||||
|
client
|
||||||
|
|
||||||
# OpenVPN gateway(s), uncomment remote-random to load balance
|
# OpenVPN gateway(s), uncomment remote-random to load balance
|
||||||
comp-lzo
|
comp-lzo
|
||||||
proto udp
|
nobind
|
||||||
|
;proto udp
|
||||||
|
;port 1194
|
||||||
{% if servers %}
|
{% if servers %}
|
||||||
remote-random
|
remote-random
|
||||||
{% for server in servers %}
|
{% for server in servers %}
|
||||||
remote {{ server }} 1194
|
remote {{ server }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
remote 1.2.3.4 1194
|
remote 1.2.3.4
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Virtual network interface settings
|
# Virtual network interface settings
|
||||||
|
@ -157,8 +157,13 @@ services template = {{ template_path }}/bootstrap.conf
|
|||||||
# Token mechanism allows authority administrator to send invites for users.
|
# Token mechanism allows authority administrator to send invites for users.
|
||||||
# Token URL could be for example exposed on the internet via proxypass.
|
# Token URL could be for example exposed on the internet via proxypass.
|
||||||
url = http://{{ common_name }}/api/token
|
url = http://{{ common_name }}/api/token
|
||||||
|
|
||||||
|
# Token lifetime in seconds
|
||||||
lifetime = 3600
|
lifetime = 3600
|
||||||
|
|
||||||
|
# Secret for generating and validating tokens, regenerate occasionally
|
||||||
|
secret = {{ token_secret }}
|
||||||
|
|
||||||
# Profile format, uncomment specific one to enable token mechanism
|
# Profile format, uncomment specific one to enable token mechanism
|
||||||
format =
|
format =
|
||||||
;format = p12
|
;format = p12
|
||||||
|
Loading…
Reference in New Issue
Block a user