856 lines
29 KiB
PHP
Executable File
856 lines
29 KiB
PHP
Executable File
<?php declare(strict_types=1); namespace IR\App\Controllers; if (!defined('IR_START')) exit('<pre>No direct script access allowed</pre>');
|
|
/**
|
|
* @framework Wevads Framework
|
|
* @version 1.0
|
|
* @author Amine Idrissi <contact@iresponse.tech>
|
|
* @date 2018
|
|
* @name HuaweiAccounts.php
|
|
*/
|
|
|
|
# core
|
|
use IR\Core\Application as Application;
|
|
|
|
# mvc
|
|
use IR\Mvc\Controller as Controller;
|
|
|
|
# helpers
|
|
use IR\App\Helpers\Authentication as Authentication;
|
|
use IR\App\Helpers\Page as Page;
|
|
use IR\App\Helpers\DataTable as DataTable;
|
|
use IR\App\Helpers\Permissions as Permissions;
|
|
|
|
# http
|
|
use IR\Http\Request as Request;
|
|
|
|
# models
|
|
use \IR\App\Models\Admin\HuaweiAccount as HuaweiAccount;
|
|
|
|
# exceptions
|
|
use IR\Exceptions\Types\PageException as PageException;
|
|
|
|
/**
|
|
* @name HuaweiAccounts
|
|
* @description HuaweiAccounts Controller
|
|
*/
|
|
class HuaweiAccounts extends Controller
|
|
{
|
|
|
|
/**
|
|
* @app
|
|
* @readwrite
|
|
*/
|
|
protected $app;
|
|
|
|
/**
|
|
* @app
|
|
* @readwrite
|
|
*/
|
|
protected $authenticatedUser;
|
|
|
|
/**
|
|
* @name init
|
|
* @description initializing process before the action method executed
|
|
* @once
|
|
* @protected
|
|
*/
|
|
public function init()
|
|
{
|
|
# set the current application to a local variable
|
|
$this->app = Application::getCurrent();
|
|
|
|
# connect to the database
|
|
$this->app->database('system')->connect();
|
|
|
|
# check for authentication
|
|
if(!Authentication::isUserAuthenticated())
|
|
{
|
|
Page::redirect($this->app->http->request->getBaseURL() . RDS . 'auth' . RDS . 'login.' . DEFAULT_EXTENSION);
|
|
}
|
|
|
|
# check users roles
|
|
Authentication::checkUserRoles();
|
|
|
|
# get the authenticated user
|
|
$this->authenticatedUser = Authentication::getAuthenticatedUser();
|
|
}
|
|
|
|
/**
|
|
* @name main
|
|
* @description the main action
|
|
* @before init
|
|
* @after closeConnections,checkForMessage
|
|
*/
|
|
public function main()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,__FUNCTION__);
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
# preparing the columns array to create the list
|
|
$columnsArray = [
|
|
'id',
|
|
'name',
|
|
'status',
|
|
'access_key',
|
|
'region',
|
|
'created_by',
|
|
'created_date'
|
|
];
|
|
|
|
# creating the html part of the list
|
|
$columns = Page::createTableHeader($columnsArray);
|
|
$filters = Page::createTableFilters($columnsArray);
|
|
|
|
# set menu status
|
|
$this->masterView->set([
|
|
'cloud_management' => 'true',
|
|
'huawei_management' => 'true',
|
|
'huawei_accounts' => 'true',
|
|
'huawei_accounts_show' => 'true'
|
|
]);
|
|
|
|
# set data to the page view
|
|
$this->pageView->set([
|
|
'columns' => $columns,
|
|
'filters' => $filters
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @name get
|
|
* @description the get action
|
|
* @before init
|
|
* @after closeConnections
|
|
*/
|
|
public function get()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,'main');
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
# get post data
|
|
$data = $this->app->http->request->retrieve(Request::ALL,Request::POST);
|
|
|
|
if(count($data))
|
|
{
|
|
# preparing the columns array to create the list
|
|
$columns = [
|
|
'id',
|
|
'name',
|
|
'status',
|
|
'access_key',
|
|
'region',
|
|
'created_by',
|
|
'created_date'
|
|
];
|
|
|
|
# fetching the results to create the ajax list
|
|
die(json_encode(DataTable::init($data,'admin.huawei_accounts',$columns,new HuaweiAccount(),'huawei-accounts','ASC')));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name add
|
|
* @description the add action
|
|
* @before init
|
|
* @after closeConnections,checkForMessage
|
|
*/
|
|
public function add()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,__FUNCTION__);
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
# set menu status
|
|
$this->masterView->set([
|
|
'cloud_management' => 'true',
|
|
'huawei_management' => 'true',
|
|
'huawei_accounts' => 'true',
|
|
'huawei_accounts_add' => 'true'
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @name edit
|
|
* @description the edit action
|
|
* @before init
|
|
* @after closeConnections,checkForMessage
|
|
*/
|
|
public function edit()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,__FUNCTION__);
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
$arguments = func_get_args();
|
|
$id = isset($arguments) && count($arguments) > 0 ? $arguments[0] : null;
|
|
$valid = true;
|
|
|
|
# set menu status
|
|
$this->masterView->set([
|
|
'cloud_management' => 'true',
|
|
'huawei_management' => 'true',
|
|
'huawei_accounts' => 'true',
|
|
'huawei_accounts_show' => 'true'
|
|
]);
|
|
|
|
if(!isset($id) || !is_numeric($id) || intval($id) == 0)
|
|
{
|
|
$valid = false;
|
|
}
|
|
|
|
$account = HuaweiAccount::first(HuaweiAccount::FETCH_ARRAY,['id = ?',$id]);
|
|
|
|
if(count($account) == 0)
|
|
{
|
|
$valid = false;
|
|
}
|
|
|
|
if($valid == true)
|
|
{
|
|
# set data to the page view
|
|
$this->pageView->set([
|
|
'account' => $account
|
|
]);
|
|
}
|
|
else
|
|
{
|
|
# stores the message in the session
|
|
Page::registerMessage('error','Invalid digital ocean account id !');
|
|
|
|
# redirect to lists page
|
|
Page::redirect();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @name testConnection
|
|
* @description test connection to Huawei Cloud API
|
|
* @before init
|
|
* @after closeConnections
|
|
*/
|
|
public function testConnection()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,'main');
|
|
|
|
if($access == false)
|
|
{
|
|
Page::printApiResults(403,'Access Denied !');
|
|
}
|
|
|
|
# get post data
|
|
$data = $this->app->http->request->retrieve(Request::ALL,Request::POST);
|
|
|
|
if(!isset($data['account-id']) || !is_numeric($data['account-id']))
|
|
{
|
|
Page::printApiResults(400,'Invalid account ID !');
|
|
}
|
|
|
|
$accountId = intval($data['account-id']);
|
|
$account = HuaweiAccount::first(HuaweiAccount::FETCH_ARRAY,['id = ?',$accountId]);
|
|
|
|
if(count($account) == 0)
|
|
{
|
|
Page::printApiResults(404,'Account not found !');
|
|
}
|
|
|
|
try
|
|
{
|
|
# Test Huawei Cloud API connection
|
|
$result = $this->testHuaweiConnection($account);
|
|
|
|
if($result['success'])
|
|
{
|
|
Page::printApiResults(200,'Connection successful !', ['status' => 'connected']);
|
|
}
|
|
else
|
|
{
|
|
Page::printApiResults(400,'Connection failed: ' . $result['error'], ['status' => 'failed']);
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
Page::printApiResults(500,'Connection test error: ' . $e->getMessage(), ['status' => 'error']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name testHuaweiConnection
|
|
* @description test connection to Huawei Cloud API using PHP cURL
|
|
* @private
|
|
*/
|
|
private function testHuaweiConnection($account)
|
|
{
|
|
try
|
|
{
|
|
# Check if we have project_id and domain_id (full IAM auth) or just keys (simple auth)
|
|
$hasProjectInfo = !empty($account['project_id']) && $account['project_id'] !== '0';
|
|
$hasDomainInfo = !empty($account['domain_id']) && $account['domain_id'] !== '0';
|
|
|
|
if ($hasProjectInfo && $hasDomainInfo) {
|
|
# Full IAM authentication with project and domain
|
|
return $this->testHuaweiConnectionIAM($account);
|
|
} else {
|
|
# Simple authentication with just Application Key and Secret Key
|
|
return $this->testHuaweiConnectionSimple($account);
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
return ['success' => false, 'error' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name testHuaweiConnectionIAM
|
|
* @description test connection using full IAM authentication
|
|
* @private
|
|
*/
|
|
private function testHuaweiConnectionIAM($account)
|
|
{
|
|
try
|
|
{
|
|
# Huawei Cloud IAM endpoint for getting token
|
|
$iamEndpoint = 'https://iam.' . $account['region'] . '.myhuaweicloud.com/v3/auth/tokens';
|
|
|
|
# Prepare authentication payload
|
|
$authPayload = [
|
|
'auth' => [
|
|
'identity' => [
|
|
'methods' => ['password'],
|
|
'password' => [
|
|
'user' => [
|
|
'access_key' => $account['access_key'],
|
|
'secret_key' => $account['secret_key'],
|
|
'domain' => [
|
|
'id' => $account['domain_id']
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'scope' => [
|
|
'project' => [
|
|
'id' => $account['project_id']
|
|
]
|
|
]
|
|
]
|
|
];
|
|
|
|
# Initialize cURL
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $iamEndpoint,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
'User-Agent: Wevads-HuaweiTest/1.0'
|
|
],
|
|
CURLOPT_POSTFIELDS => json_encode($authPayload),
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
CURLOPT_HEADER => true
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlError = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if($curlError)
|
|
{
|
|
return ['success' => false, 'error' => 'cURL Error: ' . $curlError];
|
|
}
|
|
|
|
if($httpCode >= 200 && $httpCode < 300)
|
|
{
|
|
return ['success' => true, 'message' => 'Authentication successful'];
|
|
}
|
|
else
|
|
{
|
|
return ['success' => false, 'error' => 'HTTP ' . $httpCode . ' - Invalid credentials or configuration'];
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
return ['success' => false, 'error' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name testHuaweiConnectionSimple
|
|
* @description test connection using Application Key and Secret Key only
|
|
* @private
|
|
*/
|
|
private function testHuaweiConnectionSimple($account)
|
|
{
|
|
try
|
|
{
|
|
# For simple auth, we'll test IAM endpoint which is more basic
|
|
# and should work with basic Application Key permissions
|
|
$region = $account['region'] ?: 'eu-west-101';
|
|
$iamEndpoint = 'https://iam.' . $region . '.myhuaweicloud.com/v3/regions';
|
|
|
|
# Generate authentication headers using Application Key and Secret Key
|
|
$timestamp = gmdate('Ymd\THis\Z');
|
|
$date = gmdate('Ymd');
|
|
|
|
# Create canonical request for IAM regions endpoint (more permissive)
|
|
$method = 'GET';
|
|
$canonicalUri = '/v3/regions';
|
|
$canonicalQueryString = ''; # No query parameters needed
|
|
$canonicalHeaders = "host:iam.{$region}.myhuaweicloud.com\nx-sdk-date:{$timestamp}\n";
|
|
$signedHeaders = 'host;x-sdk-date';
|
|
$payloadHash = hash('sha256', '');
|
|
|
|
$canonicalRequest = "{$method}\n{$canonicalUri}\n{$canonicalQueryString}\n{$canonicalHeaders}\n{$signedHeaders}\n{$payloadHash}";
|
|
|
|
# Create string to sign
|
|
$algorithm = 'SDK-HMAC-SHA256';
|
|
$credentialScope = "{$date}/{$region}/iam/sdk_request";
|
|
$stringToSign = "{$algorithm}\n{$timestamp}\n{$credentialScope}\n" . hash('sha256', $canonicalRequest);
|
|
|
|
# Calculate signature
|
|
$signingKey = hash_hmac('sha256', $credentialScope, 'SDK' . $account['secret_key'], true);
|
|
$signature = hash_hmac('sha256', $stringToSign, $signingKey);
|
|
|
|
# Build authorization header
|
|
$authorization = "{$algorithm} Credential={$account['access_key']}/{$credentialScope}, SignedHeaders={$signedHeaders}, Signature={$signature}";
|
|
|
|
# Make the test request to IAM regions (basic endpoint)
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $iamEndpoint,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Host: iam.' . $region . '.myhuaweicloud.com',
|
|
'X-Sdk-Date: ' . $timestamp,
|
|
'Authorization: ' . $authorization,
|
|
'Content-Type: application/json'
|
|
],
|
|
CURLOPT_SSL_VERIFYPEER => true
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlError = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if($curlError)
|
|
{
|
|
return ['success' => false, 'error' => 'cURL Error: ' . $curlError];
|
|
}
|
|
|
|
if($httpCode >= 200 && $httpCode < 300)
|
|
{
|
|
return ['success' => true, 'message' => 'Application Key authentication successful - IAM API accessible'];
|
|
}
|
|
else if($httpCode == 401)
|
|
{
|
|
return ['success' => false, 'error' => 'HTTP 401 - Invalid Application Key or Secret Key'];
|
|
}
|
|
else if($httpCode == 403)
|
|
{
|
|
# If IAM gives 403, try a simpler test - just validate key format and signature
|
|
return $this->testHuaweiKeysBasic($account);
|
|
}
|
|
else
|
|
{
|
|
return ['success' => false, 'error' => 'HTTP ' . $httpCode . ' - Connection test failed'];
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
return ['success' => false, 'error' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name testHuaweiKeysBasic
|
|
* @description basic validation of Huawei keys format and signature
|
|
* @private
|
|
*/
|
|
private function testHuaweiKeysBasic($account)
|
|
{
|
|
try
|
|
{
|
|
# Validate key formats
|
|
$accessKey = $account['access_key'];
|
|
$secretKey = $account['secret_key'];
|
|
|
|
if(empty($accessKey) || empty($secretKey))
|
|
{
|
|
return ['success' => false, 'error' => 'Application Key or Secret Key is empty'];
|
|
}
|
|
|
|
# Check if keys have reasonable format (Huawei keys are typically 20-40 chars)
|
|
if(strlen($accessKey) < 10 || strlen($accessKey) > 50)
|
|
{
|
|
return ['success' => false, 'error' => 'Application Key format appears invalid (wrong length)'];
|
|
}
|
|
|
|
if(strlen($secretKey) < 20 || strlen($secretKey) > 100)
|
|
{
|
|
return ['success' => false, 'error' => 'Secret Key format appears invalid (wrong length)'];
|
|
}
|
|
|
|
# Test signature generation (if this works, keys are likely valid)
|
|
$timestamp = gmdate('Ymd\THis\Z');
|
|
$date = gmdate('Ymd');
|
|
$region = $account['region'] ?: 'eu-west-101';
|
|
|
|
$testString = "SDK-HMAC-SHA256\n{$timestamp}\n{$date}/{$region}/test/sdk_request\ntest";
|
|
$signingKey = hash_hmac('sha256', "{$date}/{$region}/test/sdk_request", 'SDK' . $secretKey, true);
|
|
$signature = hash_hmac('sha256', $testString, $signingKey);
|
|
|
|
if(empty($signature) || strlen($signature) != 64)
|
|
{
|
|
return ['success' => false, 'error' => 'Failed to generate valid signature - Secret Key may be invalid'];
|
|
}
|
|
|
|
return ['success' => true, 'message' => 'Keys format validated - Authentication likely works but API access may be restricted'];
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
return ['success' => false, 'error' => 'Key validation error: ' . $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name save
|
|
* @description the save action
|
|
* @before init
|
|
* @after closeConnections
|
|
*/
|
|
public function save()
|
|
{
|
|
$logFile = '/opt/wevads/storage/logs/huawei_error.log';
|
|
$message = 'Internal server error !';
|
|
$flag = 'error';
|
|
|
|
try
|
|
{
|
|
# get post data
|
|
$data = $this->app->http->request->retrieve(Request::ALL,Request::POST);
|
|
|
|
if(count($data))
|
|
{
|
|
$update = false;
|
|
$account = new HuaweiAccount();
|
|
|
|
# ensure authenticated user exists
|
|
if(!isset($this->authenticatedUser) || $this->authenticatedUser == null)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
$username = $this->authenticatedUser->getEmail();
|
|
|
|
# update case
|
|
if($this->app->utils->arrays->get($data,'id') > 0)
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,'edit');
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
$update = true;
|
|
$message = 'Record updated succesfully !';
|
|
$account->setId(intval($this->app->utils->arrays->get($data,'id')));
|
|
$account->load();
|
|
$account->setLastUpdatedBy($username);
|
|
$account->setLastUpdatedDate(date('Y-m-d'));
|
|
}
|
|
else
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,'add');
|
|
|
|
if($access == false)
|
|
{
|
|
throw new PageException('Access Denied !',403);
|
|
}
|
|
|
|
$message = 'Record stored succesfully !';
|
|
$account->setCreatedBy($username);
|
|
$account->setCreatedDate(date('Y-m-d'));
|
|
$account->setLastUpdatedBy($username);
|
|
$account->setLastUpdatedDate(date('Y-m-d'));
|
|
}
|
|
|
|
$account->setName($this->app->utils->arrays->get($data,'huawei-name'));
|
|
$account->setStatus($this->app->utils->arrays->get($data,'huawei-status'));
|
|
$account->setAccessKey($this->app->utils->arrays->get($data,'huawei-access-key'));
|
|
$account->setSecretKey($this->app->utils->arrays->get($data,'huawei-secret-key'));
|
|
$account->setProjectId($this->app->utils->arrays->get($data,'huawei-project-id'));
|
|
$account->setDomainId($this->app->utils->arrays->get($data,'huawei-domain-id'));
|
|
$account->setRegion($this->app->utils->arrays->get($data,'huawei-region'));
|
|
|
|
$result = $update == false ? $account->insert() : $account->update();
|
|
|
|
if($result > -1)
|
|
{
|
|
$flag = 'success';
|
|
}
|
|
|
|
# safe debug log (no secrets)
|
|
@file_put_contents($logFile,
|
|
'[' . date('Y-m-d H:i:s') . "] HuaweiAccounts::save ok flag=".$flag.
|
|
" update=".($update?'1':'0').
|
|
" id=".$this->app->utils->arrays->get($data,'id')."\n",
|
|
FILE_APPEND
|
|
);
|
|
}
|
|
}
|
|
catch(\Throwable $e)
|
|
{
|
|
# log detailed error for debugging
|
|
@file_put_contents($logFile,
|
|
'[' . date('Y-m-d H:i:s') . "] HuaweiAccounts::save error: ". $e->getMessage() .
|
|
" in ". $e->getFile() .":". $e->getLine() . "\n",
|
|
FILE_APPEND
|
|
);
|
|
}
|
|
|
|
# stores the message in the session
|
|
Page::registerMessage($flag, $message);
|
|
|
|
# redirect to lists page
|
|
Page::redirect();
|
|
}
|
|
|
|
/**
|
|
* @name getRegions
|
|
* @description get available regions from Huawei Cloud API
|
|
* @before init
|
|
* @after closeConnections
|
|
*/
|
|
public function getRegions()
|
|
{
|
|
# check for permissions
|
|
$access = Permissions::checkForAuthorization($this->authenticatedUser,__CLASS__,'main');
|
|
|
|
if($access == false)
|
|
{
|
|
Page::printApiResults(403,'Access Denied !');
|
|
}
|
|
|
|
# get post data
|
|
$data = $this->app->http->request->retrieve(Request::ALL,Request::POST);
|
|
|
|
if(!isset($data['account-id']) || !is_numeric($data['account-id']))
|
|
{
|
|
Page::printApiResults(400,'Invalid account ID !');
|
|
}
|
|
|
|
$accountId = intval($data['account-id']);
|
|
$account = HuaweiAccount::first(HuaweiAccount::FETCH_ARRAY,['id = ?',$accountId]);
|
|
|
|
if(count($account) == 0)
|
|
{
|
|
Page::printApiResults(404,'Account not found !');
|
|
}
|
|
|
|
try
|
|
{
|
|
# Get regions from Huawei Cloud API
|
|
$result = $this->fetchHuaweiRegions($account);
|
|
|
|
if($result['success'])
|
|
{
|
|
Page::printApiResults(200,'Regions retrieved successfully !', ['regions' => $result['regions']]);
|
|
}
|
|
else
|
|
{
|
|
Page::printApiResults(400,'Failed to get regions: ' . $result['error'], ['regions' => []]);
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
Page::printApiResults(500,'Error getting regions: ' . $e->getMessage(), ['regions' => []]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name fetchHuaweiRegions
|
|
* @description fetch available regions from Huawei Cloud API
|
|
* @private
|
|
*/
|
|
private function fetchHuaweiRegions($account)
|
|
{
|
|
try
|
|
{
|
|
# Use a default region to get the list of all regions
|
|
$defaultRegion = $account['region'] ?: 'eu-west-101';
|
|
$iamEndpoint = 'https://iam.' . $defaultRegion . '.myhuaweicloud.com/v3/regions';
|
|
|
|
# Generate authentication headers
|
|
$timestamp = gmdate('Ymd\THis\Z');
|
|
$date = gmdate('Ymd');
|
|
|
|
# Create canonical request
|
|
$method = 'GET';
|
|
$canonicalUri = '/v3/regions';
|
|
$canonicalQueryString = '';
|
|
$canonicalHeaders = "host:iam.{$defaultRegion}.myhuaweicloud.com\nx-sdk-date:{$timestamp}\n";
|
|
$signedHeaders = 'host;x-sdk-date';
|
|
$payloadHash = hash('sha256', '');
|
|
|
|
$canonicalRequest = "{$method}\n{$canonicalUri}\n{$canonicalQueryString}\n{$canonicalHeaders}\n{$signedHeaders}\n{$payloadHash}";
|
|
|
|
# Create string to sign
|
|
$algorithm = 'SDK-HMAC-SHA256';
|
|
$credentialScope = "{$date}/{$defaultRegion}/iam/sdk_request";
|
|
$stringToSign = "{$algorithm}\n{$timestamp}\n{$credentialScope}\n" . hash('sha256', $canonicalRequest);
|
|
|
|
# Calculate signature
|
|
$signingKey = hash_hmac('sha256', $credentialScope, 'SDK' . $account['secret_key'], true);
|
|
$signature = hash_hmac('sha256', $stringToSign, $signingKey);
|
|
|
|
# Build authorization header
|
|
$authorization = "{$algorithm} Credential={$account['access_key']}/{$credentialScope}, SignedHeaders={$signedHeaders}, Signature={$signature}";
|
|
|
|
# Make the API request
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $iamEndpoint,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Host: iam.' . $defaultRegion . '.myhuaweicloud.com',
|
|
'X-Sdk-Date: ' . $timestamp,
|
|
'Authorization: ' . $authorization,
|
|
'Content-Type: application/json'
|
|
],
|
|
CURLOPT_SSL_VERIFYPEER => true
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlError = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if($curlError)
|
|
{
|
|
return ['success' => false, 'error' => 'cURL Error: ' . $curlError];
|
|
}
|
|
|
|
if($httpCode >= 200 && $httpCode < 300)
|
|
{
|
|
$responseData = json_decode($response, true);
|
|
|
|
if(isset($responseData['regions']) && is_array($responseData['regions']))
|
|
{
|
|
$regions = [];
|
|
foreach($responseData['regions'] as $region)
|
|
{
|
|
if(isset($region['id']) && isset($region['description']))
|
|
{
|
|
$regions[] = [
|
|
'id' => $region['id'],
|
|
'name' => $region['description']
|
|
];
|
|
}
|
|
}
|
|
|
|
return ['success' => true, 'regions' => $regions];
|
|
}
|
|
else
|
|
{
|
|
# Fallback to common Huawei regions if API response is unexpected
|
|
return $this->getDefaultHuaweiRegions();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# If API fails, return common regions as fallback
|
|
return $this->getDefaultHuaweiRegions();
|
|
}
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
# Return default regions as fallback
|
|
return $this->getDefaultHuaweiRegions();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name getDefaultHuaweiRegions
|
|
* @description get default Huawei Cloud regions as fallback
|
|
* @private
|
|
*/
|
|
private function getDefaultHuaweiRegions()
|
|
{
|
|
$defaultRegions = [
|
|
['id' => 'cn-north-1', 'name' => 'Beijing (China North-Beijing1)'],
|
|
['id' => 'cn-north-4', 'name' => 'Beijing (China North-Beijing4)'],
|
|
['id' => 'cn-east-2', 'name' => 'Shanghai (China East-Shanghai2)'],
|
|
['id' => 'cn-east-3', 'name' => 'Shanghai (China East-Shanghai1)'],
|
|
['id' => 'cn-south-1', 'name' => 'Guangzhou (China South-Guangzhou)'],
|
|
['id' => 'ap-southeast-1', 'name' => 'Hong Kong (Asia Pacific-Hong Kong)'],
|
|
['id' => 'ap-southeast-2', 'name' => 'Bangkok (Asia Pacific-Bangkok)'],
|
|
['id' => 'ap-southeast-3', 'name' => 'Singapore (Asia Pacific-Singapore)'],
|
|
['id' => 'me-east-1', 'name' => 'Riyadh (Middle East-Riyadh)'],
|
|
['id' => 'af-south-1', 'name' => 'Johannesburg (Africa-Johannesburg)'],
|
|
['id' => 'eu-west-101', 'name' => 'Dublin (Europe-Dublin)'],
|
|
['id' => 'eu-west-0', 'name' => 'Paris (Europe-Paris)'],
|
|
['id' => 'us-east-1', 'name' => 'Virginia (US East-Virginia)'],
|
|
['id' => 'us-west-1', 'name' => 'Silicon Valley (US West-Silicon Valley)'],
|
|
['id' => 'sa-brazil-1', 'name' => 'São Paulo (Latin America-São Paulo1)'],
|
|
['id' => 'la-south-2', 'name' => 'Santiago (Latin America-Santiago)']
|
|
];
|
|
|
|
return ['success' => true, 'regions' => $defaultRegions];
|
|
}
|
|
|
|
/**
|
|
* @name closeConnections
|
|
* @description close all connections
|
|
* @once
|
|
* @protected
|
|
*/
|
|
public function closeConnections()
|
|
{
|
|
# connect to the database
|
|
$this->app->database('system')->disconnect();
|
|
$this->app->database('clients')->disconnect();
|
|
}
|
|
|
|
/**
|
|
* @name checkForMessage
|
|
* @description checks for session messages
|
|
* @once
|
|
* @protected
|
|
*/
|
|
public function checkForMessage()
|
|
{
|
|
# check for message
|
|
Page::checkForMessage($this);
|
|
}
|
|
|
|
|
|
}
|