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 :
@@ -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
0 commit comments