Skip to content

Commit

Permalink
new: satosa-saml-metadata: make signing optional
Browse files Browse the repository at this point in the history
Allow skipping signing with --no-sign - and in that case, do not require key+cert.

Default to signing enabled (keep existing behaviour).

Mark key and cert args as optional in Click and instead check them explicitly
when signing is enabled.

Add new method create_entity_descriptor_metadata as counterpart
to create_signed_entity_descriptor to also apply `valid` option
to EntityDescriptor but avoid signing.
  • Loading branch information
vladimir-mencl-eresearch committed Mar 21, 2023
1 parent 00c0d05 commit 18667fc
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 14 deletions.
15 changes: 15 additions & 0 deletions src/satosa/metadata_creation/saml_metadata.py
Expand Up @@ -154,3 +154,18 @@ def create_signed_entity_descriptor(entity_descriptor, security_context, valid_f
raise ValueError("Could not construct valid EntityDescriptor tag")

return xmldoc


def create_entity_descriptor_metadata(entity_descriptor, valid_for=None):
"""
:param entity_descriptor: the entity descriptor to create metadata for
:param valid_for: number of hours the metadata should be valid
:return: the EntityDescriptor metadata
:type entity_descriptor: saml2.md.EntityDescriptor]
:type valid_for: Optional[int]
"""
if valid_for:
entity_descriptor.valid_until = in_a_while(hours=valid_for)

return str(entity_descriptor)
45 changes: 31 additions & 14 deletions src/satosa/scripts/satosa_saml_metadata.py
Expand Up @@ -5,6 +5,7 @@
from saml2.sigver import security_context

from ..metadata_creation.saml_metadata import create_entity_descriptors
from ..metadata_creation.saml_metadata import create_entity_descriptor_metadata
from ..metadata_creation.saml_metadata import create_signed_entity_descriptor
from ..satosa_config import SATOSAConfig

Expand All @@ -16,44 +17,58 @@ def _get_security_context(key, cert):
return security_context(conf)


def _create_split_entity_descriptors(entities, secc, valid):
def _create_split_entity_descriptors(entities, secc, valid, sign=True):
output = []
for module_name, eds in entities.items():
for i, ed in enumerate(eds):
output.append((create_signed_entity_descriptor(ed, secc, valid), "{}_{}.xml".format(module_name, i)))
ed_str = (
create_signed_entity_descriptor(ed, secc, valid)
if sign
else create_entity_descriptor_metadata(ed, valid)
)
output.append((ed_str, "{}_{}.xml".format(module_name, i)))

return output


def _create_merged_entities_descriptors(entities, secc, valid, name):
def _create_merged_entities_descriptors(entities, secc, valid, name, sign=True):
output = []
frontend_entity_descriptors = [e for sublist in entities.values() for e in sublist]
for frontend in frontend_entity_descriptors:
output.append((create_signed_entity_descriptor(frontend, secc, valid), name))
ed_str = (
create_signed_entity_descriptor(frontend, secc, valid)
if sign
else create_entity_descriptor_metadata(frontend, valid)
)
output.append((ed_str, name))

return output


def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend_metadata=False,
split_backend_metadata=False):
split_backend_metadata=False, sign=True):
"""
Generates SAML metadata for the given PROXY_CONF, signed with the given KEY and associated CERT.
"""
satosa_config = SATOSAConfig(proxy_conf)
secc = _get_security_context(key, cert)

if sign and (not key or not cert):
raise ValueError("Key and cert are required when signing")
secc = _get_security_context(key, cert) if sign else None

frontend_entities, backend_entities = create_entity_descriptors(satosa_config)

output = []
if frontend_entities:
if split_frontend_metadata:
output.extend(_create_split_entity_descriptors(frontend_entities, secc, valid))
output.extend(_create_split_entity_descriptors(frontend_entities, secc, valid, sign))
else:
output.extend(_create_merged_entities_descriptors(frontend_entities, secc, valid, "frontend.xml"))
output.extend(_create_merged_entities_descriptors(frontend_entities, secc, valid, "frontend.xml", sign))
if backend_entities:
if split_backend_metadata:
output.extend(_create_split_entity_descriptors(backend_entities, secc, valid))
output.extend(_create_split_entity_descriptors(backend_entities, secc, valid, sign))
else:
output.extend(_create_merged_entities_descriptors(backend_entities, secc, valid, "backend.xml"))
output.extend(_create_merged_entities_descriptors(backend_entities, secc, valid, "backend.xml", sign))

for metadata, filename in output:
path = os.path.join(dir, filename)
Expand All @@ -64,8 +79,8 @@ def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_fron

@click.command()
@click.argument("proxy_conf")
@click.argument("key")
@click.argument("cert")
@click.argument("key", required=False)
@click.argument("cert", required=False)
@click.option("--dir",
type=click.Path(exists=True, file_okay=False, dir_okay=True, writable=True, readable=False,
resolve_path=False),
Expand All @@ -75,5 +90,7 @@ def create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_fron
help="Create one entity descriptor per file for the frontend metadata")
@click.option("--split-backend", is_flag=True, type=click.BOOL, default=False,
help="Create one entity descriptor per file for the backend metadata")
def construct_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend):
create_and_write_saml_metadata(proxy_conf, key, cert, dir, valid, split_frontend, split_backend)
@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)

0 comments on commit 18667fc

Please sign in to comment.