Skip to content

Commit e303893

Browse files
committed
Sign elements required by WSDL
1 parent 77a00f6 commit e303893

File tree

4 files changed

+25
-10
lines changed

4 files changed

+25
-10
lines changed

src/zeep/wsdl/bindings/soap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ def _create(self, operation, args, kwargs, client=None, options=None):
8989
if isinstance(client.wsse, list):
9090
for wsse in client.wsse:
9191
envelope, http_headers = wsse.apply(
92-
envelope, http_headers)
92+
envelope, http_headers, operation_obj.binding.signatures)
9393
else:
9494
envelope, http_headers = client.wsse.apply(
95-
envelope, http_headers)
95+
envelope, http_headers, operation_obj.binding.signatures)
9696

9797
# Add extra http headers from the setings object
9898
if client.settings.extra_http_headers:

src/zeep/wsse/signature.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from zeep import ns
1515
from zeep.exceptions import SignatureVerificationFailed
1616
from zeep.utils import detect_soap_env
17+
from zeep.wsdl.utils import get_or_create_header
1718
from zeep.wsse.utils import ensure_id, get_security_header
1819

1920
try:
@@ -52,9 +53,9 @@ def __init__(self, key_data, cert_data, password=None):
5253
self.cert_data = cert_data
5354
self.password = password
5455

55-
def apply(self, envelope, headers):
56+
def apply(self, envelope, headers, signatures=None):
5657
key = _make_sign_key(self.key_data, self.cert_data, self.password)
57-
_sign_envelope_with_key(envelope, key)
58+
_sign_envelope_with_key(envelope, key, signatures)
5859
return envelope, headers
5960

6061
def verify(self, envelope):
@@ -80,7 +81,7 @@ def check_xmlsec_import():
8081
)
8182

8283

83-
def sign_envelope(envelope, keyfile, certfile, password=None):
84+
def sign_envelope(envelope, keyfile, certfile, password=None, signatures=None):
8485
"""Sign given SOAP envelope with WSSE sig using given key and cert.
8586
8687
Sign the wsu:Timestamp node in the wsse:Security header and the soap:Body;
@@ -170,10 +171,10 @@ def sign_envelope(envelope, keyfile, certfile, password=None):
170171
"""
171172
# Load the signing key and certificate.
172173
key = _make_sign_key(_read_file(keyfile), _read_file(certfile), password)
173-
return _sign_envelope_with_key(envelope, key)
174+
return _sign_envelope_with_key(envelope, key, signatures)
174175

175176

176-
def _sign_envelope_with_key(envelope, key):
177+
def _sign_envelope_with_key(envelope, key, signatures=None):
177178
soap_env = detect_soap_env(envelope)
178179

179180
# Create the Signature node.
@@ -198,8 +199,20 @@ def _sign_envelope_with_key(envelope, key):
198199
# Perform the actual signing.
199200
ctx = xmlsec.SignatureContext()
200201
ctx.key = key
201-
_sign_node(ctx, signature, envelope.find(QName(soap_env, 'Body')))
202+
# Sign default elements
202203
_sign_node(ctx, signature, security.find(QName(ns.WSU, 'Timestamp')))
204+
205+
# Sign extra elements defined in WSDL
206+
if signatures is not None:
207+
if signatures['body'] or signatures['everything']:
208+
_sign_node(ctx, signature, envelope.find(QName(soap_env, 'Body')))
209+
header = get_or_create_header(envelope)
210+
if signatures['everything']:
211+
for node in header.iterchildren():
212+
_sign_node(ctx, signature, node)
213+
else:
214+
for node in signatures['header']:
215+
_sign_node(ctx, signature, header.find(QName(node['Namespace'], node['Name'])))
203216
ctx.sign(signature)
204217

205218
# Place the X509 data inside a WSSE SecurityTokenReference within

src/zeep/wsse/username.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def __init__(self, username, password=None, password_digest=None,
4646
self.created = created
4747
self.use_digest = use_digest
4848

49-
def apply(self, envelope, headers):
49+
def apply(self, envelope, headers, operation_obj=None):
5050
security = utils.get_security_header(envelope)
5151

5252
# The token placeholder might already exists since it is specified in

tests/test_wsse_signature.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ def test_verify_error():
7979
</soapenv:Envelope>
8080
""")
8181

82-
signature.sign_envelope(envelope, KEY_FILE, KEY_FILE)
82+
# Force body signature
83+
signatures = {'everything': False, 'body': True, 'header': []}
84+
signature.sign_envelope(envelope, KEY_FILE, KEY_FILE, signatures=signatures)
8385
nsmap = {'tns': 'http://tests.python-zeep.org/'}
8486

8587
for elm in envelope.xpath('//tns:Argument', namespaces=nsmap):

0 commit comments

Comments
 (0)