Package: net.maurus.authserver
maurus.networks Authentication serverThis is a Python Django based server application that provides single sign-on
services for my own setup. It has OAuth2 endpoints and for applications
that don’t support any of these: a SQL stored procedure database abstraction.As a second application it providesdkimsigner, a daemon that speaks SMTP and
receives mail, then forwards it to another SMTP port after signing it with a
DKIM key from its database.The third included application ismailforwarder. As OpenSMTPD 6.x does not
offer a stable filter API andmy OpenSMTPD setupalreadyrelies onthe “stored procedure API”,mailforwarderprovides
a daemon speaking SMTP that resolves domains and email-addresses inauthserver’sdatabase and can then forward email to one-or-more other
email addresses. Basically a.forwardor.qmailimplementation based on
authserver’s database schema as a Python daemon.It also provides Djangomanage.pycommands for registering OAuth2
applications, users, domains and  Docker registries. Those are useful for
creating configuration entries through configuration management systems.It also includes an implementation of theDocker Token Authentication protocoland can therefore be
used to secure Docker registries for push and pull with SSO credentials. The
includedmanage.pycommand:manage.py dockerauth registry add ...allows script based setup.Finally, it includes acheckpasswordcompatible client application that can
be used to integrate Apache2mod_authnz_externalor DJB checkpassword
compatible clients with authserver.Users can use the admin interface to create “service users” which are specific
aliases for user accounts that can be used with applications that don’t support
OAuth2 so users don’t have to share their passwords with the service
(equivalent to the same feature on Google Gmail).Planned featuresOAuth2 applications can use a SSL client certificate to authenticate for a
non-standard HTTP API to register as an OAuth2 client and get their OAuth2
credentials, cutting down on manual configuration.OpenID Connect supportService-specific username and passwords for systems that don’t support
OAuth2/OIDCCAS support throughmama-casadd Google Authenticator support viadjango-otpInstallationThere is no widely available Docker container available yet, but you can install
from this repository:$virtualenv-ppython3authserver$authserver/bin/pipinstallnet.maurus.authserverOr for Debian 9.0 Stretch:$echo"deb http://repo.maurus.net/release/stretch mn-release main">>/etc/apt/sources.list.d/maurusnet.list$aptupdate$aptinstallauthserverauthclientAPPCONFIG FOLDERThis application uses12factorand in its systemd configuration
loads its configuration from aappconfig folder.Canonical reserved configuration folders for this app:/etc/appconfig/authserver/etc/appconfig/dkimsigner/etc/appconfig/mailforwarderRundjango-admin.pylike this:bin/envdir/etc/appconfig/authserver/envbin/django-admin.py[command]--settings=authserver.settings12factor Environment configurationManaged configurationThese environment variables must be placed in the appconfig folder manually (or
through configuration management). You can just leaveVAULT_*empty and setDATABASE_URLif you’re not planning on using Vault.VariableDescriptionVAULT_CAPinned CA to use to validate that we’re talking to the
right Vault.VAULT_DATABASE_PATHThe key path to read from Vault to get database
credentials for a full access role.DATABASE_PARENTROLEThe role that authserver should “sudo” into (viaSET ROLE) after connecting to the database, i.e. the
primary access role (only used with Vault).DATABASE_NAMEThe name of the database to connect to (only used with
Vault).DATABASE_URLWhen client SSL certificates or usernames and passwords
are used to connect to the database instead of Vault,
then this URL (parsed by dj-database-url) is used to
connect (only used without Vault).Smartstack servicesThis application relies on the following smartstack services being available
on localhost:PortServiceSSL Hostname5432PostgreSQLpostgresql.local8200Vaultvault.localSmartstack registration and loadbalancingBuildingBuild scriptThis application is meant to be built usingGoPythonGo.exportREPO=maurusnetexportAPTLY_DISTRIBUTION=mn-nightlyexportAPTLY_PUBLISH_ENDPOINT=s3:maurusnet:nightly/stretchexportGNUPGHOME=/etc/gpg-managed-keyring/exportVAULTWRAPPER_READ_PATH=secret/gpg/packaging_passphrase/opt/gopythongo/bin/gopythongo-v/usr/local/authserver/path/to/sourceAccess methodsThere are multiple ways to authenticate user accounts against this program.
Offered APIs include OAuth2, CAS and a “if nothing else works” abstraction
layer for direct user database access based on stored procedures.Stored Procedure APISince some applications (like OpenSMTPD and Dovecot) which are used bymy saltshakerneed lowest common denominator
authentication, authserver includes a pgplsql stored procedure API tailored to
OpenSMTPD to validate user accounts.NFunction NameDescription1authserver_get_credentials( varchar)Gets a username password pair for the
provided email address together with
the primary delivery email address.
(Users can log in with every email
alias and their account password.)2authserver_check_domain( varchar)Checks whether the passed domain is a
valid delivery domain.3authserver_resolve_alias(varchar, boolean)Resolves email addresses to knownMNUserorMailingListinstances. Resolving a primary
delivery address will return the
“magic” value “virtmail” pointing to
the system user normally handling
email delivery if the boolean
parameter istrue. If the boolean
parameter isfalseit will return
the primary delivery address again. If
the resolved address is aMailingListit will return the
input unchanged.4authserver_iterate_users()Returns a list of all valid delivery
mailboxes.Access to the stored procedure API is managed by thedjango-admin.pyspapicommand which allows you tograntaccess to database users,installthe
stored procedures on the database andcheckwhether the stored procedures
have been installed or if a specific database user hasexecuteaccess to
the stored procedures. For more information, please run:/usr/local/authserver/bin/envdir/etc/appconfig/authserver/env/\/usr/local/authserver/bin/django-admin.pyspapi--helpOAuth2authserver delivers OAuth2 support over the following endpoints:/o2/authorize//o2/token//o2/revoke_token/You can create client applications and authorization scopes via the Django
admin interface ormanage.py oauth2|permissionsand assign scopes to users
and groups respectively. The authorization view will list the scopes for the
user to approve unless automatic authorization is turned on for the OAuth2
client.Docker Authauthserver supports Docker-compatible JWTs using the “resource owner” OAuth2
flow viadocker loginathttps://your.authserver.domain/docker/token/.
You can generally just usedocker loginhttps://your.authserver.domain/and
create Docker registry instances and access rights to namespaces on that
registry via the Django admin interface or themanage.py dockerauthcommand.Propietary endpoints and mod_authnz_externalThecheckpassword.pycommand-line script, also shipped in theauthclientDebian package is compatible with djb checkpassword and Apache2
mod_authnz_external. It uses two proprietary API endpoints:/checkpassword/which takes a username and optionally a list of
scopes and password (for something akin to the “resource owner” OAuth2 flow)
and issues a JWT that has the user’s assigned scopes and validates the
password (if transmitted)./getkey/exports a RSA public key for a domain registered with authserver
to allow a client to validate an issued JWT.You should prefer OAuth2 where possible as this solution will bring the client
into possession of the user’s password. However, if you trust the client this
is an alternative solution. Obviously it’s also an easy way to integrate legacy
systems.checkpassword.pycan operate in 5 modes:-minituses the getkey API to load a RSA public key for the authserver’s
domain and output it to stdout or into a file.-mcheckbehaves likeinitbut makes no changes, it’s useful to check
whether a domain has a JWT key to export or that key is readable to
checkpassword on the file system.-mauthextand-mcheckpasswordread username and password from stdin
(either in the way specified by mod_authnz_external or djb checkpassword) and
send them to the server to be validated. The program then either exits with
exit code0(success),1if the auth domain is invalid,2if
there are API connection problems and3for anything else.-mauthextgroupvalidates a list of scopes for a username. This doesnotvalidate the user’s password. This is useful for
mod_authnz_external’sGroupExternalconfiguration, but you must
additionally authenticate the user.The API endpoints respond with a JSON Web Token (JWT) with the following
claims:{"sub":"the provided username""canonical_username":"the user's delivery_mailbox name""authenticated":trueorfalsedependingonthestatusofthepasswordcheck"authorized":trueorfalsedependingonwhethertheuserhasallsubmittedscopes,"scopes":["a list of","all the scopes","assigned to this user"],"nbf":int(UnixEpochtimestampofnowminus5seconds),"exp":int(UnixEpochtimestampofnowplus3600seconds),"iss":"the auth domain name","aud":"net.maurus.authclient"}TODOrefactor Vault fullaccess role into actually granting access to new tablesLicensingPlease see theLICENSEdocument for the terms under which this
source code is licensed.This program includes a copy ofdjango12factorwhich is licensed under The MIT License
(MIT) Copyright (c) 2013-2017 Kristian Glass.This program includes a copy ofSelect2 JavaScript librarywhich is licensed user the MIT
License (MIT)
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors