summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-01-19 17:47:56 -0500
committerPatrick Uiterwijk <puiterwijk@redhat.com>2015-01-29 20:06:51 +0100
commit0d5c4ff5229880b6eba12a4e7e5bfbab2f415caa (patch)
tree49635c00dd383fdf385110b603662d4007266640
parentc9ce29a7610b8b2232422623e28d35417b81fe76 (diff)
Add expiration to Idp metadata
Also regenerate it frequently, so that any change in configuration can be automatically reflected in the metadata downloaded my clients over time. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Patrick Uiterwijk <puiterwijk@redhat.com>
-rw-r--r--ipsilon/providers/saml2idp.py37
-rw-r--r--ipsilon/util/page.py10
2 files changed, 41 insertions, 6 deletions
diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py
index 298a205..1778307 100644
--- a/ipsilon/providers/saml2idp.py
+++ b/ipsilon/providers/saml2idp.py
@@ -26,8 +26,10 @@ from ipsilon.util.user import UserSession
from ipsilon.util.plugin import PluginObject
from ipsilon.util import config as pconfig
import cherrypy
+from datetime import timedelta
import lasso
import os
+import time
class Redirect(AuthenticateRequest):
@@ -96,15 +98,39 @@ class SSO(ProviderPageBase):
self.Continue = Continue(*args, **kwargs)
+# one week
+METADATA_RENEW_INTERVAL = 60 * 60 * 24 * 7
+# 30 days
+METADATA_VALIDITY_PERIOD = 30
+
+
class Metadata(ProviderPageBase):
def GET(self, *args, **kwargs):
- with open(self.cfg.idp_metadata_file) as m:
- body = m.read()
+
+ body = self._get_metadata()
cherrypy.response.headers["Content-Type"] = "text/xml"
cherrypy.response.headers["Content-Disposition"] = \
'attachment; filename="metadata.xml"'
return body
+ def _get_metadata(self):
+ if os.path.isfile(self.cfg.idp_metadata_file):
+ s = os.stat(self.cfg.idp_metadata_file)
+ if s.st_mtime > time.time() - METADATA_RENEW_INTERVAL:
+ with open(self.cfg.idp_metadata_file) as m:
+ return m.read()
+
+ # Otherwise generate and save
+ idp_cert = Certificate()
+ idp_cert.import_cert(self.cfg.idp_certificate_file,
+ self.cfg.idp_key_file)
+ meta = IdpMetadataGenerator(self.instance_base_url(), idp_cert,
+ timedelta(METADATA_VALIDITY_PERIOD))
+ body = meta.output()
+ with open(self.cfg.idp_metadata_file, 'w+') as m:
+ m.write(body)
+ return body
+
class SAML2(ProviderPageBase):
@@ -244,8 +270,8 @@ Provides SAML 2.0 authentication infrastructure. """
class IdpMetadataGenerator(object):
- def __init__(self, url, idp_cert):
- self.meta = metadata.Metadata(metadata.IDP_ROLE)
+ def __init__(self, url, idp_cert, expiration=None):
+ self.meta = metadata.Metadata(metadata.IDP_ROLE, expiration)
self.meta.set_entity_id('%s/saml2/metadata' % url)
self.meta.add_certs(idp_cert, idp_cert)
self.meta.add_service(metadata.SAML2_SERVICE_MAP['sso-post'],
@@ -292,7 +318,8 @@ class Installer(object):
if opts['secure'].lower() == 'no':
proto = 'http'
url = '%s://%s/%s' % (proto, opts['hostname'], opts['instance'])
- meta = IdpMetadataGenerator(url, cert)
+ meta = IdpMetadataGenerator(url, cert,
+ timedelta(METADATA_VALIDITY_PERIOD))
if 'krb' in opts and opts['krb'] == 'yes':
meta.meta.add_allowed_name_format(
lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS)
diff --git a/ipsilon/util/page.py b/ipsilon/util/page.py
index 0929961..d2ccb51 100644
--- a/ipsilon/util/page.py
+++ b/ipsilon/util/page.py
@@ -51,6 +51,14 @@ class Page(Log):
self.default_headers = dict()
self.auth_protect = False
+ def get_url(self):
+ return cherrypy.url(relative=False)
+
+ def instance_base_url(self):
+ url = self.get_url()
+ s = urlparse(unquote(url))
+ return '%s://%s%s' % (s.scheme, s.netloc, self.basepath)
+
def _check_referer(self, referer, url):
r = urlparse(unquote(referer))
u = urlparse(unquote(url))
@@ -82,7 +90,7 @@ class Page(Log):
if callable(op):
# Basic CSRF protection
if cherrypy.request.method != 'GET':
- url = cherrypy.url(relative=False)
+ url = self.get_url()
if 'referer' not in cherrypy.request.headers:
self._debug("Missing referer in %s request to %s"
% (cherrypy.request.method, url))