С версии: 27.02.2013
Автор: Vitaliy Demidov (vitaliy@scalr.com)
Наследование: extends SoapClient, implements Scalr\Service\Aws\Client\ClientInterface
Пример #1
0
 /**
  * {@inheritdoc}
  * @see SoapClient::__doRequest()
  */
 public function __doRequest($request, $location, $action, $version, $one_way = null)
 {
     $certKey = openssl_get_privatekey($this->privateKey, '');
     $wsse = new \DOMDocument('1.0', 'UTF-8');
     $wsse->loadXML($request);
     $envelope = $wsse->documentElement;
     $ns = $envelope->namespaceURI;
     $prefix = $envelope->prefix;
     $xpath = new \DOMXPath($wsse);
     $xpath->registerNamespace('wssoap', $ns);
     $xpath->registerNamespace('wswsse', self::WSSENS);
     //Sets security header
     $setActor = null;
     $headers = $xpath->query('//wssoap:Envelope/wssoap:Header');
     $header = $headers->item(0);
     if (!$header) {
         $header = $wsse->createElementNS($ns, $prefix . ':Header');
         $envelope->insertBefore($header, $envelope->firstChild);
     }
     $secNodes = $xpath->query('./wswsse:Security', $header);
     $security = null;
     foreach ($secNodes as $node) {
         $actor = $node->getAttributeNS($ns, 'actor');
         if ($actor == $setActor) {
             $security = $node;
             break;
         }
     }
     if (!$security) {
         $security = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':Security');
         $header->appendChild($security);
         $security->setAttributeNS($ns, $prefix . ':mustUnderstand', '1');
         if (!empty($setActor)) {
             $security->setAttributeNS($ns, $prefix . ':actor', $setActor);
         }
     }
     //Sets timestamp
     $timestamp = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Timestamp');
     $security->insertBefore($timestamp, $security->firstChild);
     $currentTime = time();
     $created = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Created', gmdate('Y-m-d\\TH:i:s', $currentTime) . 'Z');
     $timestamp->appendChild($created);
     $expire = $wsse->createElementNS(self::WSUNS, self::WSUPFX . ':Expires', gmdate('Y-m-d\\TH:i:s', $currentTime + 3600) . 'Z');
     $timestamp->appendChild($expire);
     //Signs document
     $arNodes = array();
     foreach ($security->childNodes as $node) {
         if ($node->nodeType == \XML_ELEMENT_NODE) {
             $arNodes[] = $node;
         }
     }
     foreach ($envelope->childNodes as $node) {
         if ($node->namespaceURI == $ns && $node->localName == 'Body') {
             $arNodes[] = $node;
             break;
         }
     }
     $arOptions = array('prefix' => self::WSUPFX, 'prefix_ns' => self::WSUNS);
     try {
         $sigdoc = new \DOMDocument();
         $sigdoc->loadXML(self::SIGN_TPL);
         $this->sigNode = $sigdoc->documentElement;
         $sigXpath = new \DOMXPath($this->sigNode->ownerDocument);
         $sigXpath->registerNamespace('secdsig', self::XMLDSIGNS);
         $query = './secdsig:SignedInfo';
         $nodeset = $sigXpath->query($query);
         if ($sinfo = $nodeset->item(0)) {
             $canonNode = $this->_createNewSignNode('CanonicalizationMethod');
             $sinfo->insertBefore($canonNode, $sinfo->firstChild);
             $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
         }
         $nodeset = $sigXpath->query("./secdsig:SignedInfo");
         if ($sInfo = $nodeset->item(0)) {
             foreach ($arNodes as $node) {
                 $this->_addRefInternal($sInfo, $node, self::SHA1, null, $arOptions);
             }
         }
         $nodeset = $sigXpath->query("./secdsig:SignedInfo");
         if ($sInfo = $nodeset->item(0)) {
             $nodeset = $sigXpath->query("./secdsig:SignatureMethod", $sInfo);
             $sMethod = $nodeset->item(0);
             $sMethod->setAttribute('Algorithm', "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
             $data = $this->_canonicalizeData($sInfo, $this->canonicalMethod);
             $algo = OPENSSL_ALGO_SHA1;
             if (!openssl_sign($data, $signature, $certKey, $algo)) {
                 throw new \Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
                 return;
             }
             $sigValue = base64_encode($signature);
             $sigValueNode = $this->_createNewSignNode('SignatureValue', $sigValue);
             if ($infoSibling = $sInfo->nextSibling) {
                 $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
             } else {
                 $this->sigNode->appendChild($sigValueNode);
             }
         }
         $this->_insertSignature($security, $security->firstChild);
     } catch (\Exception $e) {
         throw new \Exception("Unable to sign AWS API request. Please, check your X.509 certificate and private key. ");
     }
     $token = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':BinarySecurityToken', self::_get509XCert($this->certificate, true));
     $security->insertBefore($token, $security->firstChild);
     $token->setAttribute('EncodingType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
     $token->setAttributeNS(self::WSUNS, self::WSUPFX . ':Id', self::_generateGuid());
     $token->setAttribute('ValueType', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3');
     $sigdoc = new \DOMDocument();
     $sigdoc->loadXML(self::SIGN_TPL);
     $this->sigNode = $sigdoc->documentElement;
     $sigXpath = new \DOMXPath($this->sigNode->ownerDocument);
     $sigXpath->registerNamespace('secdsig', self::XMLDSIGNS);
     if ($objDSig = $this->_locateSignature($wsse)) {
         $tokenURI = '#' . $token->getAttributeNS(self::WSUNS, "Id");
         $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
         $nodeset = $xpath->query("./secdsig:KeyInfo", $objDSig);
         $keyInfo = $nodeset->item(0);
         if (!$keyInfo) {
             $keyInfo = $this->_createNewSignNode('KeyInfo');
             $objDSig->appendChild($keyInfo);
         }
         $tokenRef = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':SecurityTokenReference');
         $keyInfo->appendChild($tokenRef);
         $reference = $wsse->createElementNS(self::WSSENS, self::WSSEPFX . ':Reference');
         $reference->setAttribute("URI", $tokenURI);
         $tokenRef->appendChild($reference);
     } else {
         throw new \Exception('Unable to locate digital signature');
     }
     $retval = parent::__doRequest($wsse->saveXML(), $location, $action, $version, $one_way);
     if ($retval instanceof \SoapFault && stristr($retval->faultstring, "Could not connect to host")) {
         throw new \Exception($retval->getMessage());
     }
     return $retval;
 }