Passed
Push — develop ( b3ec5e...1a1ece )
by Nikolay
12:31
created

AWSCloud   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 10
eloc 43
c 1
b 0
f 1
dl 0
loc 87
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getMetaDataAWS() 0 25 5
A __construct() 0 3 1
A provision() 0 38 4
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2024 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\Core\System\CloudProvisioning;
21
22
use GuzzleHttp\Client;
23
use GuzzleHttp\Exception\GuzzleException;
24
use GuzzleHttp;
25
use MikoPBX\Core\System\SystemMessages;
26
27
class AWSCloud extends CloudProvider
28
{
29
    public const CloudID = 'AWSCloud';
30
31
    private Client $client;
32
33
    public function __construct()
34
    {
35
        $this->client = new Client(['timeout' => self::HTTP_TIMEOUT]);
36
    }
37
38
    /**
39
     * Performs the Amazon Web Services cloud provisioning.
40
     *
41
     * @return bool True if the provisioning was successful, false otherwise.
42
     */
43
    public function provision(): bool
44
    {
45
        // Cloud check
46
        $checkValue = $this->getMetaDataAWS('services/partition');
47
        if ($checkValue!=='aws'){
48
            return false;
49
        }
50
51
        // Get host name
52
        $hostname = $this->getMetaDataAWS('hostname');
53
        if (empty($hostname)) {
54
            return false;
55
        }
56
57
        SystemMessages::echoToTeletype(PHP_EOL);
58
59
        // Update machine name
60
        $this->updateHostName($hostname);
61
62
        // Update LAN settings with the external IP address
63
        $extIp = $this->getMetaDataAWS('public-ipv4');
64
        $this->updateLanSettings($extIp);
65
66
        // Update SSH keys, if available
67
        $sshKey = '';
68
        $sshKeys = $this->getMetaDataAWS('public-keys');
69
        $sshId = explode('=', $sshKeys)[0] ?? '';
70
        if ($sshId !== '') {
71
            $sshKey = $this->getMetaDataAWS("public-keys/$sshId/openssh-key");
72
        }
73
        $this->updateSSHKeys($sshKey);
74
75
        // Update SSH and WEB passwords using some unique identifier from the metadata
76
        $vmId = $this->getMetaDataAWS('instance-id')??'';
77
        $this->updateSSHCredentials('ec2-user', $vmId);
78
        $this->updateWebPassword($vmId);
79
80
        return true;
81
    }
82
83
    /**
84
     * Retrieves metadata from the MCS endpoint.
85
     *
86
     * @param string $url The URL of the metadata endpoint.
87
     * @return string The response body.
88
     */
89
    private function getMetaDataAWS(string $url): string
90
    {
91
        $baseUrl = 'http://169.254.169.254/latest/meta-data/';
92
        $headers = [];
93
        $params = [];
94
        $options = [
95
            'timeout' => self::HTTP_TIMEOUT,
96
            'http_errors' => false,
97
            'headers' => $headers
98
        ];
99
100
        $url = "$baseUrl/$url?" . http_build_query($params);
101
        try {
102
            $res = $this->client->request('GET', $url, $options);
103
            $code = $res->getStatusCode();
104
        } catch (GuzzleHttp\Exception\ConnectException $e) {
105
            $code = 0;
106
        } catch (GuzzleException $e) {
107
            $code = 0;
108
        }
109
        $body = '';
110
        if ($code === 200 && isset($res)) {
111
            $body = $res->getBody()->getContents();
112
        }
113
        return $body;
114
    }
115
}