This release is a pre-release and may not be stable for production use.
openhound-saml-producer
This library builds the SAML graph nodes and edges for OpenHound extensions.
It is a prototype. It is published on PyPI as openhound-saml-producer.
See Release steps.
Two extensions that see the same SAML endpoint write the same node. For
example, an issuer or an assertion consumer service (ACS) route gets the same
ID in every extension. The ACS is the URL where a service provider receives
SAML assertions. Each extension writes its own environment ID on that node as
environmentid. The correlator later decides the owner's environment.
What it does
- Builds owned nodes for identity providers, service providers, and claim mappings. Their IDs come from the producer name, the environment, and the native key.
- Builds shared nodes for issuers and ACS routes. Their IDs come from the
route strings only. Each shared-node builder takes the producer's environment
ID, which it writes as
environmentid. - Builds account resolution rules and fields (v0.3). A producer gives typed
conditions (
AccountResolutionCondition). The library writes the rule text from the profile templates, so a producer never writes rule text. - Rejects extra properties that do not start with the producer prefix.
- Builds v0.4 set grants (
SetPolicyFact,set_grant_edges), claim projections, eligibility exceptions (EligibilityExceptionFact,eligibility_exception_edge), and claim value residuals (aClaimValueFactwith aset_policy). A fact carries v0.4.0 only when it uses a v0.4 kind or property. All other output stays v0.3.0. - Builds the portable principal set (v0.4), only for a platform that has no group
node in the graph.
PrincipalSetFactgives aSAML_PrincipalSetnode whose ID is the contract's portable set key (principal_set_id).SetMembershipFactgives oneSAML_EffectiveMemberOfPrincipalSetedge. ASetPolicyFactwith the profilesaml_principal_set_membership_v1grants access from that node. A provider should use the portable profile only when the platform has no group node:assert_conformantreturns a warning for a provider that uses both profiles. - Declares the v0.4 edges:
edge_defstakesset_kindsfor set grants and exceptions, andNodeKind.PRINCIPAL_SETdeclares the membership edges. - Writes assertion requirements. A
ServiceProviderFactwithassertion_requirements(registered profile IDs, for exampleaws_iam_role_session_name_v1) is a v0.4.1 fact with the propertyassertion_requirement_profiles. An unknown ID is aFactError. - Writes the same relationship context on every edge.
IdP example
This example writes one identity provider, its tenant issuer, and one route.
from openhound_saml_producer import IssuerFact, Producer, RouteFact
from openhound_saml_producer.conventions import entra_external_route
from openhound_saml_producer.facts import FederationProviderFact
from openhound_saml_producer.idp import federation_provider_edges, federation_provider_node
from openhound_saml_producer.shared import acs_node, issuer_node
TENANT = "11111111-2222-3333-4444-555555555555"
PRODUCER = Producer(name="entra_saml", extension="openhound-entra-saml",
prefix="az_", technology="entra", source_kind="SAML")
provider = FederationProviderFact(
environment_id=f"entra-saml-tenant:{TENANT}",
native_key="22222222-3333-4444-5555-666666666666",
native_kind="AZServicePrincipal",
native_object_id="", # empty: the native key is shown
name="Example app",
enabled=True,
extras={"az_tenant_id": TENANT},
)
issuer = IssuerFact(entity_id=f"https://sts.windows.net/{TENANT}/")
route: RouteFact = entra_external_route(TENANT)
nodes = [
federation_provider_node(PRODUCER, provider),
issuer_node(PRODUCER, provider.environment_id, issuer),
acs_node(PRODUCER, provider.environment_id, route),
]
edges, warnings = federation_provider_edges(
PRODUCER, provider, native=None, issuer=issuer,
routes=[route], claim_mapping_keys=[],
)
warnings holds BuildWarning values. The extension logs them. They are not
graph output.
SP example
This example writes one service provider and its trust of the same issuer.
from openhound_saml_producer.facts import ServiceProviderFact
from openhound_saml_producer.sp import service_provider_edges, service_provider_node
sp = ServiceProviderFact(
environment_id=f"entra-saml-tenant:{TENANT}",
native_key="sp-native-key",
native_kind="ExternalFederation",
native_object_id="",
name="Example trust",
enabled=True,
)
sp_node = service_provider_node(PRODUCER, sp)
sp_edges, sp_warnings = service_provider_edges(
PRODUCER, sp, native=None, trusted_issuer=issuer, routes=[route],
)
The edge ends for issuer and route use the same IDs as the shared nodes
above. You do not compute those IDs yourself.
Limits
- Node and edge IDs use the rules in the shared normalization design. Do not change them without a contract review.
- The library writes no timestamp on nodes. BloodHound adds its own.
- The checks in
openhound_saml_producer.testing.conformancerun on whole payloads.assert_conformantchecks one payload.assert_shared_nodes_agreechecks that two producers' copies of one shared node match, except forenvironmentid. Use them in tests.assert_conformantalso checks the contract and relationship-context versions on every edge, rejects unprefixed extra edge properties, requires eachSAML_*node to carry exactly its own kind andSAML, and applies the correlator's account-evidence rules toSAML_EligibleForandSAML_HasAccountedges. Each fact must carry v0.4.1 if it lists assertion requirements, v0.4.0 if it has other v0.4 content, and v0.3.0 if it has none. The v0.4 rules agree with the correlator. A passing check returns a list of warnings. One warning is for a provider that has a complete set grant and no expanded facts: stop expanded facts only after the rollout gate (design section 14.5) passes.
Release steps
A GitHub Release publishes the package to PyPI. Publication has these steps.
- Set
versioninpyproject.toml, for example0.4.6rc1. Merge the change todev-jimfor a release candidate, or tomainfor a stable version. - In GitHub, create a Release. Set the tag to
saml-producer-v<version>, for examplesaml-producer-v0.4.6rc1. - Set the target branch. Use
dev-jimfor a release candidate andmainfor a stable version. - Set the prerelease flag. Set it for a release candidate (
a,b, orrcversion). Clear it for a stable version. - Publish the Release. The workflow
release-saml-producer.ymlbuilds the files. It checks the version and the branch. It stops if a check fails. - Approve the
pypienvironment deployment in GitHub Actions. PyPI gets the files only after this approval.
Metadata
Release files for openhound-saml-producer 0.4.6rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| openhound_saml_producer-0.4.6rc1.tar.gz | 73.9 kB | Without provenance | Details for openhound_saml_producer-0.4.6rc1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| openhound_saml_producer-0.4.6rc1-py3-none-any.whl | Python 3 | none | any | Details for openhound_saml_producer-0.4.6rc1-py3-none-any.whl |
Total release size: 141.1 kB
Release files / openhound_saml_producer-0.4.6rc1.tar.gz
| Download URL | openhound_saml_producer-0.4.6rc1.tar.gz |
|---|---|
| Size | 73.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a7abbae3aeda1a346dc9a9ba7e8ad139b61b085df85394bfca512362cdb98e3d
|
|
BLAKE2b-256 checksum How to use checksums |
64b7ef71d434945f885ebbf0383f9f288ab4067be51f04c0f40ffea00ec33cf8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.8 {"installer":{"name":"uv","version":"0.13.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / openhound_saml_producer-0.4.6rc1-py3-none-any.whl
| Download URL | openhound_saml_producer-0.4.6rc1-py3-none-any.whl |
|---|---|
| Size | 67.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2b3be340d9d34b773fd22244bcc2088e3be074001ef0f760ee9a963e1fad108c
|
|
BLAKE2b-256 checksum How to use checksums |
c2d29b15c0e36f8f2d0bd6f1e59c9fa33a04ed38b6e6498b315305f0ba44610d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.8 {"installer":{"name":"uv","version":"0.13.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for openhound-saml-producer 0.4.6rc1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.