Scalr\Service\Aws\Client\SoapClient::__doRequest PHP Method

__doRequest() public method

See also: SoapClient::__doRequest()
public __doRequest ( $request, $location, $action, $version, $one_way = null )
    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;
    }