82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
import sys, subprocess
|
|
from xml.etree import ElementTree as ET
|
|
|
|
fn = "saml-response.xml"
|
|
ns = {
|
|
'p': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
|
's': 'urn:oasis:names:tc:SAML:2.0:assertion',
|
|
'ds': 'http://www.w3.org/2000/09/xmldsig#'
|
|
}
|
|
|
|
try:
|
|
root = ET.parse(fn).getroot()
|
|
except Exception as e:
|
|
print("ERROR: cannot parse saml-response.xml:", e)
|
|
sys.exit(1)
|
|
|
|
def find_text(path, default=""):
|
|
el = root.find(path, ns)
|
|
return el.text.strip() if el is not None and el.text else default
|
|
|
|
# Status (StatusCode Value attribute)
|
|
status_el = root.find('.//p:Status/p:StatusCode', ns)
|
|
status = status_el.get('Value') if status_el is not None else ""
|
|
print("Status: " + status)
|
|
|
|
# NameID
|
|
nameid = find_text('.//s:NameID')
|
|
print("Name: " + nameid)
|
|
|
|
# Audience
|
|
aud = find_text('.//s:Audience')
|
|
print("Audience: " + aud)
|
|
|
|
# Recipient (SubjectConfirmationData @Recipient)
|
|
rec_el = root.find('.//s:Subject/s:SubjectConfirmation/s:SubjectConfirmationData', ns)
|
|
recipient = rec_el.get('Recipient') if rec_el is not None else ""
|
|
print("Recipient: " + recipient)
|
|
|
|
# Extract cert and write PEM with proper line breaks
|
|
cert_el = root.find('.//ds:X509Certificate', ns)
|
|
if cert_el is None or not cert_el.text or not cert_el.text.strip():
|
|
print("no-cert-found")
|
|
sys.exit(0)
|
|
|
|
b64 = "".join(cert_el.text.split())
|
|
pem = "-----BEGIN CERTIFICATE-----\n"
|
|
# wrap at 64 chars per line
|
|
for i in range(0, len(b64), 64):
|
|
pem += b64[i:i+64] + "\n"
|
|
pem += "-----END CERTIFICATE-----\n"
|
|
|
|
with open("google_cert.pem", "w") as f:
|
|
f.write(pem)
|
|
|
|
# Try to print openssl fingerprint
|
|
try:
|
|
out = subprocess.check_output(['openssl','x509','-in','google_cert.pem','-noout','-fingerprint','-sha256'], stderr=subprocess.STDOUT)
|
|
print(out.decode().strip())
|
|
except Exception as e:
|
|
print("openssl-not-available-or-error")
|
|
|
|
# Print all Attribute values for AWS Role and RoleSessionName
|
|
role_attr = root.find('.//s:Attribute[@Name="https://aws.amazon.com/SAML/Attributes/Role"]', ns)
|
|
if role_attr is not None:
|
|
vals = [v.text.strip() for v in role_attr.findall('.//s:AttributeValue', ns) if v.text]
|
|
for v in vals:
|
|
print("ROLE_ATTRIBUTE_VALUE: " + v)
|
|
else:
|
|
print("ROLE_ATTRIBUTE_VALUE: not-present")
|
|
|
|
role_session_attr = root.find('.//s:Attribute[@Name="https://aws.amazon.com/SAML/Attributes/RoleSessionName"]', ns)
|
|
if role_session_attr is not None:
|
|
vals = [v.text.strip() for v in role_session_attr.findall('.//s:AttributeValue', ns) if v.text]
|
|
for v in vals:
|
|
print("ROLE_SESSION_NAME_VALUE: " + v)
|
|
else:
|
|
print("ROLE_SESSION_NAME_VALUE: not-present")
|
|
|
|
|
|
|