summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kanakarakis <ivan.kanak@gmail.com>2018-12-11 14:55:43 +0200
committerGitHub <noreply@github.com>2018-12-11 14:55:43 +0200
commita0c8cb289b03c700ca166ab282719976cb273a91 (patch)
tree91473c8191c3fea06de43730b371db40a85d6331
parent05195ff4764de9e8318a678129fc31c8fba0b96d (diff)
parent8bf0e5cd67ea8a4b8527b61fc4c0f80a07b56a54 (diff)
downloadpysaml2-a0c8cb289b03c700ca166ab282719976cb273a91.tar.gz
Merge pull request #483 from skoranda/mdq_check_signature
Enable signature verification for MDQ
-rw-r--r--docs/howto/config.rst39
-rw-r--r--src/saml2/mdstore.py41
2 files changed, 62 insertions, 18 deletions
diff --git a/docs/howto/config.rst b/docs/howto/config.rst
index 274da303..b5fb80f7 100644
--- a/docs/howto/config.rst
+++ b/docs/howto/config.rst
@@ -183,25 +183,40 @@ the client key in an HTTPS session.
metadata
^^^^^^^^
-Contains a list of places where metadata can be found. This can be either
-a file accessible on the server the service runs on, or somewhere on the net.::
+Contains a list of places where metadata can be found. This can be
+
+* a local file accessible on the server the service runs on
+* a remote URL serving aggregate metadata
+* a metadata query protocol (MDQ) service URL
+
+For example::
"metadata" : {
"local": [
- "metadata.xml", "vo_metadata.xml"
- ],
+ "metadata.xml",
+ "vo_metadata.xml",
+ ],
"remote": [
{
- "url":"https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
- "cert":"kalmar2.cert"
- }],
+ "url": "https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2",
+ "cert": "kalmar2.cert",
+ },
+ ],
+ "mdq": [
+ {
+ "url": "http://mdq.ukfederation.org.uk/",
+ "cert": "ukfederation-mdq.pem",
+ },
+ ],
},
-The above configuration means that the service should read two local
-metadata files, and on top of that load one from the net. To verify the
-authenticity of the file downloaded from the net, the local copy of the
-public key should be used.
-This public key must be acquired by some out-of-band method.
+The above configuration means that the service should read two aggregate local
+metadata files, one aggregate metadata file from a remote server, and query a
+remote MDQ server. To verify the authenticity of the metadata aggregate
+downloaded from the remote server and the MDQ server local copies of the
+metadata signing certificates should be used. These public keys must be
+acquired by some secure out-of-band method before being placed on the local
+file system.
organization
^^^^^^^^^^^^
diff --git a/src/saml2/mdstore.py b/src/saml2/mdstore.py
index ef38c9ac..f5ffbb41 100644
--- a/src/saml2/mdstore.py
+++ b/src/saml2/mdstore.py
@@ -779,7 +779,10 @@ SAML_METADATA_CONTENT_TYPE = 'application/samlmetadata+xml'
class MetaDataMDX(InMemoryMetaData):
- """ Uses the md protocol to fetch entity information
+ """
+ Uses the MDQ protocol to fetch entity information.
+ The protocol is defined at:
+ https://datatracker.ietf.org/doc/draft-young-md-query-saml/
"""
@staticmethod
@@ -787,24 +790,41 @@ class MetaDataMDX(InMemoryMetaData):
return "{{sha1}}{}".format(
hashlib.sha1(entity_id.encode("utf-8")).hexdigest())
- def __init__(self, url, entity_transform=None):
+ def __init__(self, url=None, security=None, cert=None,
+ entity_transform=None, **kwargs):
"""
:params url: mdx service url
+ :params security: SecurityContext()
+ :params cert: certificate used to check signature of signed metadata
:params entity_transform: function transforming (e.g. base64,
sha1 hash or URL quote
hash) the entity id. It is applied to the entity id before it is
concatenated with the request URL sent to the MDX server. Defaults to
sha1 transformation.
"""
- super(MetaDataMDX, self).__init__(None, '')
+ super(MetaDataMDX, self).__init__(None, **kwargs)
+ if not url:
+ raise SAMLError('URL for MDQ server not specified.')
+
self.url = url.rstrip('/')
if entity_transform:
self.entity_transform = entity_transform
else:
-
self.entity_transform = MetaDataMDX.sha1_entity_transform
+ self.cert = cert
+ self.security = security
+
+ # We assume that the MDQ server will return a single entity
+ # described by a single <EntityDescriptor> element. The protocol
+ # does allow multiple entities to be returned in an
+ # <EntitiesDescriptor> element but we will not currently support
+ # that use case since it is unlikely to be leveraged for most
+ # flows.
+ self.node_name = "%s:%s" % (md.EntityDescriptor.c_namespace,
+ md.EntityDescriptor.c_tag)
+
def load(self, *args, **kwargs):
# Do nothing
pass
@@ -906,8 +926,17 @@ class MetadataStore(MetaData):
key = args[1]
_md = MetaDataLoader(self.attrc, args[1], **_args)
elif typ == "mdq":
- key = args[1]
- _md = MetaDataMDX(args[1])
+ if 'url' in kwargs:
+ key = kwargs['url']
+ url = kwargs['url']
+ cert = kwargs.get('cert')
+ security = self.security
+ entity_transform = kwargs.get('entity_transform', None)
+ _md = MetaDataMDX(url, security, cert, entity_transform)
+ else:
+ key = args[1]
+ url = args[1]
+ _md = MetaDataMDX(url)
else:
raise SAMLError("Unknown metadata type '%s'" % typ)
_md.load()