/** * Retrieve password for a Windows machine * * @param string $serverId * @throws Exception */ public function xGetWindowsPasswordAction($serverId) { $this->request->restrictAccess(Acl::RESOURCE_SECURITY_RETRIEVE_WINDOWS_PASSWORDS); $password = $encPassword = null; $dbServer = DBServer::LoadByID($serverId); $this->user->getPermissions()->validate($dbServer); if ($dbServer->platform == SERVER_PLATFORMS::EC2) { $env = Scalr_Environment::init()->loadById($dbServer->envId); $ec2 = $env->aws($dbServer->GetCloudLocation())->ec2; $encPassword = $ec2->instance->getPasswordData($dbServer->GetCloudServerID()); $encPassword = str_replace('\\/', '/', trim($encPassword->passwordData)); } elseif ($dbServer->platform == SERVER_PLATFORMS::AZURE) { $password = $dbServer->GetProperty(AZURE_SERVER_PROPERTIES::ADMIN_PASSWORD); } elseif ($dbServer->platform == SERVER_PLATFORMS::GCE) { $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); /* @var $client Google_Service_Compute */ $client = $platform->getClient($this->environment); $ccProps = $this->environment->keychain(SERVER_PLATFORMS::GCE)->properties; /* @var $info Google_Service_Compute_Instance */ $info = $client->instances->get($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId); // More info about following code is available here: // https://cloud.google.com/compute/docs/instances/windows-old-auth // // Check GCE agent version $serialPort = $client->instances->getSerialPortOutput($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId); $serialPortContents = $serialPort->getContents(); preg_match("/GCE Agent started( \\(version ([0-9\\.]+)\\))?\\./", $serialPortContents, $matches); $agentVersion = count($matches) > 1 ? (int) str_replace('.', '', $matches[2]) : 0; // New stuff is supported from version 3.0.0.0 if ($agentVersion > 3000) { // NEW GCE AGENT // Get SSH key $config = array("digest_alg" => "sha512", "private_key_bits" => 2048, "private_key_type" => OPENSSL_KEYTYPE_RSA); $key = openssl_pkey_new($config); $details = openssl_pkey_get_details($key); $userObject = ['userName' => 'scalr', 'modulus' => base64_encode($details['rsa']['n']), 'exponent' => base64_encode($details['rsa']['e']), 'email' => $ccProps[Entity\CloudCredentialsProperty::GCE_SERVICE_ACCOUNT_NAME], 'expireOn' => date("c", strtotime("+10 minute"))]; /* @var $meta Google_Service_Compute_Metadata */ $meta = $info->getMetadata(); $found = false; /* @var $item \Google_Service_Compute_MetadataItems */ foreach ($meta as $item) { if ($item->getKey() === "windows-keys") { $item->setValue(json_encode($userObject, JSON_FORCE_OBJECT)); $found = true; break; } } if (!$found) { $item = new \Google_Service_Compute_MetadataItems(); $item->setKey("windows-keys"); $item->setValue(json_encode($userObject, JSON_FORCE_OBJECT)); $meta[count($meta)] = $item; } $client->instances->setMetadata($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId, $meta); //Monitor serial port #4 for ($i = 0; $i < 10; $i++) { $serialPortInfo = $client->instances->getSerialPortOutput($ccProps[Entity\CloudCredentialsProperty::GCE_PROJECT_ID], $dbServer->cloudLocation, $dbServer->serverId, ['port' => 4]); $lines = explode("\n", $serialPortInfo->getContents()); foreach ($lines as $line) { $obj = json_decode(trim($line)); if (isset($obj->modulus) && $obj->modulus == $userObject['modulus']) { $encPassword = base64_decode($obj->encryptedPassword); break; } } if ($encPassword) { break; } sleep(2); } if ($encPassword) { openssl_private_decrypt($encPassword, $password, $key, OPENSSL_PKCS1_OAEP_PADDING); $encPassword = null; } else { throw new Exception("Windows password is not available yet. Please try again in couple minutes."); } } else { // OLD GCE AGENT foreach ($info->getMetadata() as $meta) { /* @var $meta Google_Service_Compute_MetadataItems */ if ($meta->getKey() == 'gce-initial-windows-password') { $password = $meta->getValue(); break; } } } } elseif (PlatformFactory::isOpenstack($dbServer->platform)) { if (in_array($dbServer->platform, array(SERVER_PLATFORMS::RACKSPACENG_UK, SERVER_PLATFORMS::RACKSPACENG_US))) { $password = $dbServer->GetProperty(OPENSTACK_SERVER_PROPERTIES::ADMIN_PASS); } else { $env = Scalr_Environment::init()->loadById($dbServer->envId); $os = $env->openstack($dbServer->platform, $dbServer->GetCloudLocation()); //TODO: Check is extension supported $encPassword = trim($os->servers->getEncryptedAdminPassword($dbServer->GetCloudServerID())); } } else { throw new Exception("Requested operation is supported by '{$dbServer->platform}' cloud"); } if ($encPassword) { try { $sshKey = (new SshKey())->loadGlobalByFarmId($dbServer->envId, $dbServer->platform, $dbServer->GetCloudLocation(), $dbServer->farmId); $password = CryptoTool::opensslDecrypt(base64_decode($encPassword), $sshKey->privateKey); } catch (Exception $e) { //Do nothing. Error already handled in UI (If no password returned) } } $this->response->data(array('password' => $password, 'encodedPassword' => $encPassword)); }
public function xGetWindowsPasswordAction() { $this->request->restrictAccess(Acl::RESOURCE_SECURITY_RETRIEVE_WINDOWS_PASSWORDS); $this->request->defineParams(array('serverId')); $dbServer = DBServer::LoadByID($this->getParam('serverId')); $this->user->getPermissions()->validate($dbServer); if ($dbServer->platform == SERVER_PLATFORMS::EC2) { $env = Scalr_Environment::init()->loadById($dbServer->envId); $ec2 = $env->aws($dbServer->GetCloudLocation())->ec2; $encPassword = $ec2->instance->getPasswordData($dbServer->GetCloudServerID()); $encPassword = str_replace('\\/', '/', trim($encPassword->passwordData)); } elseif ($dbServer->platform == SERVER_PLATFORMS::GCE) { $platform = PlatformFactory::NewPlatform(SERVER_PLATFORMS::GCE); $client = $platform->getClient($this->environment, $this->getParam('cloudLocation')); /* @var $client Google_Service_Compute */ $info = $client->instances->get($this->environment->getPlatformConfigValue(GoogleCEPlatformModule::PROJECT_ID), $dbServer->cloudLocation, $dbServer->serverId); /* @var $info Google_Service_Compute_Instance */ foreach ($info->getMetadata() as $meta) { /* @var $meta Google_Service_Compute_MetadataItems */ if ($meta->getKey() == 'gce-initial-windows-password') { $password = $meta->getValue(); break; } } } elseif (PlatformFactory::isOpenstack($dbServer->platform)) { if (in_array($dbServer->platform, array(SERVER_PLATFORMS::RACKSPACENG_UK, SERVER_PLATFORMS::RACKSPACENG_US))) { $password = $dbServer->GetProperty(OPENSTACK_SERVER_PROPERTIES::ADMIN_PASS); } else { $env = Scalr_Environment::init()->loadById($dbServer->envId); $os = $env->openstack($dbServer->platform, $dbServer->GetCloudLocation()); //TODO: Check is extension supported $encPassword = trim($os->servers->getEncryptedAdminPassword($dbServer->GetCloudServerID())); } } else { throw new Exception("Requested operation supported only by EC2"); } if ($encPassword) { try { $privateKey = Scalr_SshKey::init()->loadGlobalByFarmId($dbServer->envId, $dbServer->farmId, $dbServer->GetCloudLocation(), $dbServer->platform); $password = CryptoTool::opensslDecrypt(base64_decode($encPassword), $privateKey->getPrivate()); } catch (Exception $e) { //Do nothing. Error already handled in UI (If no password returned) } } $this->response->data(array('password' => $password, 'encodedPassword' => $encPassword)); }