Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for xmlsec breaking when SHA1 is deprecated: Allow signature and digest algorithm as parameters ... #452

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/satosa/metadata_creation/saml_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,14 @@ def create_signed_entities_descriptor(entity_descriptors, security_context, vali
return xmldoc


def create_signed_entity_descriptor(entity_descriptor, security_context, valid_for=None):
def create_signed_entity_descriptor(entity_descriptor, security_context, valid_for=None, sign_alg=None,
digest_alg=None):
"""
:param entity_descriptor: the entity descriptor to sign
:param security_context: security context for the signature
:param valid_for: number of hours the metadata should be valid
:param sign_alg: signature algorithm from saml2.xmldsig
:param digest_alg: digest algorithm from saml2.xmldsig
:return: the signed XML document

:type entity_descriptor: saml2.md.EntityDescriptor]
Expand All @@ -148,7 +151,9 @@ def create_signed_entity_descriptor(entity_descriptor, security_context, valid_f
if valid_for:
entity_descriptor.valid_until = in_a_while(hours=valid_for)

entity_desc, xmldoc = sign_entity_descriptor(entity_descriptor, None, security_context)
entity_desc, xmldoc = sign_entity_descriptor(entity_descriptor, None, security_context,
sign_alg=sign_alg,
digest_alg=digest_alg)

if not valid_instance(entity_desc):
raise ValueError("Could not construct valid EntityDescriptor tag")
Expand Down
46 changes: 35 additions & 11 deletions src/satosa/scripts/satosa_saml_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import click
from saml2.config import Config
from saml2.sigver import security_context
from saml2 import xmldsig

from ..metadata_creation.saml_metadata import create_entity_descriptors
from ..metadata_creation.saml_metadata import create_entity_descriptor_metadata
Expand All @@ -17,12 +18,22 @@ def _get_security_context(key, cert):
return security_context(conf)


def _create_split_entity_descriptors(entities, secc, valid, sign=True):
def _get_sign_and_digest_alg(signature_algorithm, digest_algorithm):
sign_alg = digest_alg = None
if signature_algorithm:
sign_alg = getattr(xmldsig, signature_algorithm)
if digest_algorithm:
digest_alg = getattr(xmldsig, digest_algorithm)
return sign_alg, digest_alg

def _create_split_entity_descriptors(entities, secc, valid, sign=True, signature_algorithm=None,
digest_algorithm=None):
output = []
sign_alg, digest_alg = _get_sign_and_digest_alg(signature_algorithm, digest_algorithm)
for module_name, eds in entities.items():
for i, ed in enumerate(eds):
ed_str = (
create_signed_entity_descriptor(ed, secc, valid)
create_signed_entity_descriptor(ed, secc, valid, sign_alg=sign_alg, digest_alg=digest_alg)
if sign
else create_entity_descriptor_metadata(ed, valid)
)
Expand All @@ -31,12 +42,14 @@ def _create_split_entity_descriptors(entities, secc, valid, sign=True):
return output


def _create_merged_entities_descriptors(entities, secc, valid, name, sign=True):
def _create_merged_entities_descriptors(entities, secc, valid, name, sign=True, signature_algorithm=None,
digest_algorithm=None):
output = []
sign_alg, digest_alg = _get_sign_and_digest_alg(signature_algorithm, digest_algorithm)
frontend_entity_descriptors = [e for sublist in entities.values() for e in sublist]
for frontend in frontend_entity_descriptors:
ed_str = (
create_signed_entity_descriptor(frontend, secc, valid)
create_signed_entity_descriptor(frontend, secc, valid, sign_alg=sign_alg, digest_alg=digest_alg)
if sign
else create_entity_descriptor_metadata(frontend, valid)
)
Expand All @@ -46,7 +59,8 @@ def _create_merged_entities_descriptors(entities, secc, valid, name, sign=True):


def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend_metadata=False,
split_backend_metadata=False, sign=True):
split_backend_metadata=False, sign=True, signature_algorithm=None,
digest_algorithm=None):
"""
Generates SAML metadata for the given PROXY_CONF, signed with the given KEY and associated CERT.
"""
Expand All @@ -61,14 +75,18 @@ def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_fron
output = []
if frontend_entities:
if split_frontend_metadata:
output.extend(_create_split_entity_descriptors(frontend_entities, secc, valid, sign))
output.extend(_create_split_entity_descriptors(frontend_entities, secc, valid, sign,
signature_algorithm, digest_algorithm))
else:
output.extend(_create_merged_entities_descriptors(frontend_entities, secc, valid, "frontend.xml", sign))
output.extend(_create_merged_entities_descriptors(frontend_entities, secc, valid, "frontend.xml",
sign, signature_algorithm, digest_algorithm))
if backend_entities:
if split_backend_metadata:
output.extend(_create_split_entity_descriptors(backend_entities, secc, valid, sign))
output.extend(_create_split_entity_descriptors(backend_entities, secc, valid, sign, signature_algorithm,
digest_algorithm))
else:
output.extend(_create_merged_entities_descriptors(backend_entities, secc, valid, "backend.xml", sign))
output.extend(_create_merged_entities_descriptors(backend_entities, secc, valid, "backend.xml",
sign, signature_algorithm, digest_algorithm))

for metadata, filename in output:
path = os.path.join(dir, filename)
Expand All @@ -92,5 +110,11 @@ def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_fron
help="Create one entity descriptor per file for the backend metadata")
@click.option("--sign/--no-sign", is_flag=True, type=click.BOOL, default=True,
help="Sign the generated metadata")
def construct_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend, sign):
create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend, sign)
@click.option("--signature-algorithm", type=click.STRING, default="SIG_RSA_SHA256",
help="Algorithm to sign metadata, from xmldsig")
@click.option("--digest-algorithm", type=click.STRING, default="DIGEST_SHA256",
help="Algorithm for the metadata digest, from xmldsig")
def construct_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend, sign,
signature_algorithm, digest_algorithm):
create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend,
sign, signature_algorithm, digest_algorithm)