1414from zeep import ns
1515from zeep .exceptions import SignatureVerificationFailed
1616from zeep .utils import detect_soap_env
17+ from zeep .wsdl .utils import get_or_create_header
1718from zeep .wsse .utils import ensure_id , get_security_header
1819
1920try :
@@ -61,10 +62,10 @@ def __init__(
6162 self .digest_method = digest_method
6263 self .signature_method = signature_method
6364
64- def apply (self , envelope , headers ):
65+ def apply (self , envelope , headers , signatures = None ):
6566 key = _make_sign_key (self .key_data , self .cert_data , self .password )
6667 _sign_envelope_with_key (
67- envelope , key , self .signature_method , self .digest_method
68+ envelope , key , self .signature_method , self .digest_method , signatures
6869 )
6970 return envelope , headers
7071
@@ -99,10 +100,10 @@ class BinarySignature(Signature):
99100
100101 Place the key information into BinarySecurityElement."""
101102
102- def apply (self , envelope , headers ):
103+ def apply (self , envelope , headers , signatures = None ):
103104 key = _make_sign_key (self .key_data , self .cert_data , self .password )
104105 _sign_envelope_with_key_binary (
105- envelope , key , self .signature_method , self .digest_method
106+ envelope , key , self .signature_method , self .digest_method , signatures
106107 )
107108 return envelope , headers
108109
@@ -123,6 +124,7 @@ def sign_envelope(
123124 password = None ,
124125 signature_method = None ,
125126 digest_method = None ,
127+ signatures = None ,
126128):
127129 """Sign given SOAP envelope with WSSE sig using given key and cert.
128130
@@ -213,10 +215,12 @@ def sign_envelope(
213215 """
214216 # Load the signing key and certificate.
215217 key = _make_sign_key (_read_file (keyfile ), _read_file (certfile ), password )
216- return _sign_envelope_with_key (envelope , key , signature_method , digest_method )
218+ return _sign_envelope_with_key (
219+ envelope , key , signature_method , digest_method , signatures
220+ )
217221
218222
219- def _signature_prepare (envelope , key , signature_method , digest_method ):
223+ def _signature_prepare (envelope , key , signature_method , digest_method , signatures = None ):
220224 """Prepare envelope and sign."""
221225 soap_env = detect_soap_env (envelope )
222226
@@ -241,10 +245,29 @@ def _signature_prepare(envelope, key, signature_method, digest_method):
241245 # Perform the actual signing.
242246 ctx = xmlsec .SignatureContext ()
243247 ctx .key = key
244- _sign_node ( ctx , signature , envelope . find ( QName ( soap_env , "Body" )), digest_method )
248+ # Sign default elements if present
245249 timestamp = security .find (QName (ns .WSU , "Timestamp" ))
246250 if timestamp != None :
247- _sign_node (ctx , signature , timestamp )
251+ _sign_node (ctx , signature , timestamp , digest_method )
252+
253+ # Sign extra elements defined in WSDL
254+ if signatures is not None :
255+ if signatures ["body" ] or signatures ["everything" ]:
256+ _sign_node (
257+ ctx , signature , envelope .find (QName (soap_env , "Body" )), digest_method
258+ )
259+ header = get_or_create_header (envelope )
260+ if signatures ["everything" ]:
261+ for node in header .iterchildren ():
262+ _sign_node (ctx , signature , node , digest_method )
263+ else :
264+ for node in signatures ["header" ]:
265+ _sign_node (
266+ ctx ,
267+ signature ,
268+ header .find (QName (node ["Namespace" ], node ["Name" ])),
269+ digest_method ,
270+ )
248271 ctx .sign (signature )
249272
250273 # Place the X509 data inside a WSSE SecurityTokenReference within
@@ -255,16 +278,20 @@ def _signature_prepare(envelope, key, signature_method, digest_method):
255278 return security , sec_token_ref , x509_data
256279
257280
258- def _sign_envelope_with_key (envelope , key , signature_method , digest_method ):
281+ def _sign_envelope_with_key (
282+ envelope , key , signature_method , digest_method , signatures = None
283+ ):
259284 _ , sec_token_ref , x509_data = _signature_prepare (
260- envelope , key , signature_method , digest_method
285+ envelope , key , signature_method , digest_method , signatures = signatures
261286 )
262287 sec_token_ref .append (x509_data )
263288
264289
265- def _sign_envelope_with_key_binary (envelope , key , signature_method , digest_method ):
290+ def _sign_envelope_with_key_binary (
291+ envelope , key , signature_method , digest_method , signatures = None
292+ ):
266293 security , sec_token_ref , x509_data = _signature_prepare (
267- envelope , key , signature_method , digest_method
294+ envelope , key , signature_method , digest_method , signatures = signatures
268295 )
269296 ref = etree .SubElement (
270297 sec_token_ref ,
0 commit comments