Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/twofactor_gateway.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJordan Bieder <jordan.bieder@uliege.be>2020-01-16 18:37:07 +0300
committerJordan Bieder <jordan.bieder@geduld.fr>2020-01-22 00:34:16 +0300
commite2942b1549d5129574f1633642aba85e0bc9dcb3 (patch)
tree4116f54768187c2a530b4fa51a3c3b8799e0dece /lib
parent2772cbeee7edee3f147b61077e22010518b065d6 (diff)
Ovh SMS gateway integration
- Add configuration class - Add Provider class Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Integrate Ovh gateway - add php API with composer - install the new dependencies - Add configuration for ovh - Update ProviderFactory for ovh Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Debug Ovh sms gateway. Has been tested with the test function Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Improve documentation since it seems not that easy Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Update Admin Documentation.md Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Update Admin Documentation.md Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Update Admin Documentation.md Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Fix php syntax Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Bump css-loader from 3.4.1 to 3.4.2 Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.4.1 to 3.4.2. - [Release notes](https://github.com/webpack-contrib/css-loader/releases) - [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/css-loader/compare/v3.4.1...v3.4.2) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> [tx-robot] updated from transifex [tx-robot] updated from transifex Add sms77 to help and fix case selection string Signed-off-by: Olav Seyfarth <nursoda@users.noreply.github.com> Update OVH sms provider to remove ovh/ovh dependency Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Update OVH sms provider to remove ovh/ovh dependency Update ovh endpoints Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Fix typos Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Fix typos bis Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Fix POST request Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Remove ovh/ovh with composer Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Stupid commit to get the DCO ?! Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Add requested corrections Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr> Fix indentation Signed-off-by: Jordan Bieder <jordan.bieder@geduld.fr>
Diffstat (limited to 'lib')
-rw-r--r--lib/Command/Configure.php38
-rw-r--r--lib/Service/Gateway/SMS/Provider/Ovh.php185
-rw-r--r--lib/Service/Gateway/SMS/Provider/OvhConfig.php109
-rw-r--r--lib/Service/Gateway/SMS/Provider/ProviderFactory.php2
4 files changed, 332 insertions, 2 deletions
diff --git a/lib/Command/Configure.php b/lib/Command/Configure.php
index 8808cf2..10c5787 100644
--- a/lib/Command/Configure.php
+++ b/lib/Command/Configure.php
@@ -32,6 +32,7 @@ use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\ClockworkSMSConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\EcallSMSConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\PlaySMSConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\Sms77IoConfig;
+use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\OvhConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\WebSmsConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\PuzzelSMSConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\HuaweiE3531Config;
@@ -105,7 +106,7 @@ class Configure extends Command {
private function configureSms(InputInterface $input, OutputInterface $output) {
$helper = $this->getHelper('question');
- $providerQuestion = new Question('Please choose a SMS provider (websms, playsms, clockworksms, puzzelsms, ecallsms, voipms, huawei_e3531, spryng): ', 'websms');
+ $providerQuestion = new Question('Please choose a SMS provider (websms, playsms, clockworksms, puzzelsms, ecallsms, voipms, huawei_e3531, spryng, sms77io, 'ovh'): ', 'websms');
$provider = $helper->ask($input, $output, $providerQuestion);
/** @var SMSConfig $config */
@@ -236,7 +237,7 @@ class Configure extends Command {
break;
- case 'sms77':
+ case 'sms77io':
$config->setProvider($provider);
/** @var Sms77IoConfig $providerConfig */
$providerConfig = $config->getProvider()->getConfig();
@@ -247,6 +248,39 @@ class Configure extends Command {
$providerConfig->setApiKey($apiKey);
break;
+ case 'ovh':
+ $config->setProvider($provider);
+
+ /** @var OvhConfig $providerConfig */
+ $providerConfig = $config->getProvider()->getConfig();
+
+ $endpointQ = new Question('Please enter the endpoint to use (ovh-eu, ovh-us, ovh-ca, soyoustart-eu, soyoustart-ca, kimsufi-eu, kimsufi-ca, runabove-ca): ');
+ $endpoint = $helper->ask($input, $output, $endpointQ);
+
+ $appKeyQ = new Question('Please enter your application key: ');
+ $appKey = $helper->ask($input, $output, $appKeyQ);
+
+ $appSecretQ = new Question('Please enter your application secret: ');
+ $appSecret = $helper->ask($input, $output, $appSecretQ);
+
+ $consumerKeyQ = new Question('Please enter your consumer key: ');
+ $consumerKey = $helper->ask($input, $output, $consumerKeyQ);
+
+ $accountQ = new Question('Please enter your account (sms-*****): ');
+ $account = $helper->ask($input, $output, $accountQ);
+
+ $senderQ = new Question('Please enter your sender: ');
+ $sender = $helper->ask($input, $output, $senderQ);
+
+ $providerConfig->setApplicationKey($appKey);
+ $providerConfig->setApplicationSecret($appSecret);
+ $providerConfig->setConsumerKey($consumerKey);
+ $providerConfig->setEndpoint($endpoint);
+ $providerConfig->setAccount($account);
+ $providerConfig->setSender($sender);
+ break;
+
+
default:
$output->writeln("Invalid provider $provider");
break;
diff --git a/lib/Service/Gateway/SMS/Provider/Ovh.php b/lib/Service/Gateway/SMS/Provider/Ovh.php
new file mode 100644
index 0000000..6aec22a
--- /dev/null
+++ b/lib/Service/Gateway/SMS/Provider/Ovh.php
@@ -0,0 +1,185 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @author Jordan Bieder <jordan.bieder@geduld.fr>
+ *
+ * Nextcloud - Two-factor Gateway for Ovh
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorGateway\Service\Gateway\SMS\Provider;
+
+use Exception;
+use OCA\TwoFactorGateway\Exception\SmsTransmissionException;
+use OCA\TwoFactorGateway\Exception\InvalidSmsProviderException;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+
+class Ovh implements IProvider {
+
+ const PROVIDER_ID = 'ovh';
+
+ /** @var IClient */
+ private $client;
+
+ /** @var OvhConfig */
+ private $config;
+
+ /**
+ * Url to communicate with Ovh API
+ *
+ * @var array
+ */
+ private $endpoints = [
+ 'ovh-eu' => 'https://api.ovh.com/1.0',
+ 'ovh-us' => 'https://api.us.ovhcloud.com/1.0',
+ 'ovh-ca' => 'https://ca.api.ovh.com/1.0',
+ 'kimsufi-eu' => 'https://eu.api.kimsufi.com/1.0',
+ 'kimsufi-ca' => 'https://ca.api.kimsufi.com/1.0',
+ 'soyoustart-eu' => 'https://eu.api.soyoustart.com/1.0',
+ 'soyoustart-ca' => 'https://ca.api.soyoustart.com/1.0',
+ 'runabove-ca' => 'https://api.runabove.com/1.0',
+ ];
+
+ /**
+ * Array of the 4 needed parameters to connect to the API
+ * @var array
+ */
+ private $attrs = [
+ 'AK' => null,
+ 'AS' => null,
+ 'CK' => null,
+ 'endpoint' => null,
+ 'timedelta' => null
+ ];
+
+
+ public function __construct(IClientService $clientService,
+ OvhConfig $config) {
+ $this->client = $clientService->newClient();
+ $this->config = $config;
+ }
+
+ /**
+ * @param string $identifier
+ * @param string $message
+ *
+ * @throws SmsTransmissionException
+ */
+ public function send(string $identifier, string $message) {
+ $config = $this->getConfig();
+ $endpoint = $config->getEndpoint();
+ $sender = $config->getSender();
+ $smsAccount = $config->getAccount();
+
+ $this->attrs['AK'] = $config->getApplicationKey();
+ $this->attrs['AS'] = $config->getApplicationSecret();
+ $this->attrs['CK'] = $config->getConsumerKey();
+ if (!isset($this->endpoints[$endpoint]))
+ throw new InvalidSmsProviderException("Endpoint $endpoint not found");
+ $this->attrs['endpoint'] = $this->endpoints[$endpoint];
+
+ $this->getTimeDelta();
+
+ $header = $this->getHeader('GET',$this->attrs['endpoint'].'/sms');
+ $response = $this->client->get($this->attrs['endpoint'].'/sms',[
+ 'headers' => $header,
+ ]);
+ $smsServices = json_decode($response->getBody(),true);
+
+ $smsAccountFound = false;
+ foreach ($smsServices as $smsService) {
+ if ($smsService === $smsAccount) {
+ $smsAccountFound = true;
+ break;
+ }
+ }
+ if ($smsAccountFound === false) {
+ throw new InvalidSmsProviderException("SMS account $smsAccount not found");
+ }
+ $content = [
+ "charset"=> "UTF-8",
+ "message"=> $message,
+ "noStopClause"=> true,
+ "priority"=> "high",
+ "receivers"=> [ $identifier ],
+ "senderForResponse"=> false,
+ "sender"=> $sender,
+ "validityPeriod"=> 3600
+ ];
+ $body = json_encode($content);
+
+ $header = $this->getHeader('POST',$this->attrs['endpoint']."/sms/$smsAccount/jobs",$body);
+ $response = $this->client->post($this->attrs['endpoint']."/sms/$smsAccount/jobs",[
+ 'headers' => $header,
+ 'json' => $content,
+ ]);
+ $resultPostJob = json_decode($response->getBody(),true);
+
+ if (count($resultPostJob["validReceivers"]) === 0) {
+ throw new SmsTransmissionException("Bad receiver $identifier");
+ }
+ }
+
+ /**
+ * @return OvhConfig
+ */
+ public function getConfig(): IProviderConfig {
+ return $this->config;
+ }
+
+ /**
+ * Compute time delta between this server and OVH endpoint
+ * @throws InvalidSmsProviderException
+ */
+ private function getTimeDelta() {
+ if (!isset($this->attrs['timedelta'])) {
+ if (!isset($this->attrs['endpoint']))
+ throw new InvalidSmsProviderException('Need to set the endpoint');
+ try {
+ $response = $this->client->get($this->attrs['endpoint'].'/auth/time');
+ $serverTimestamp = (int)$response->getBody();
+ $this->attrs['timedelta'] = $serverTimestamp - time();
+ }
+ catch (Exception $ex) {
+ throw new InvalidSmsProviderException('Unable to calculate time delta:'.$ex->getMessage());
+ }
+ }
+ }
+
+ /**
+ * Make header for Ovh
+ * @param string $method The methode use for the query : GET, POST, PUT, DELETE
+ * @param string $query The fulle URI for the query: https://eu.api.ovh.com/1.0/......
+ * @param string $body JSON encoded body content for the POST request
+ * @return array $header Contains the data for the request need by OVH
+ */
+ private function getHeader($method,$query,$body='') {
+ $timestamp = time() + $this->attrs['timedelta'];
+ $prehash = $this->attrs['AS'].'+'.$this->attrs['CK'].'+'.$method.'+'.$query.'+'.$body.'+'.$timestamp;
+ $header = [
+ 'Content-Type' => 'application/json; charset=utf-8',
+ 'X-Ovh-Application' => $this->attrs['AK'],
+ 'X-Ovh-Timestamp' => $timestamp,
+ 'X-Ovh-Signature' => '$1$'.sha1($prehash),
+ 'X-Ovh-Consumer' => $this->attrs['CK'],
+ ];
+ return $header;
+ }
+
+
+}
diff --git a/lib/Service/Gateway/SMS/Provider/OvhConfig.php b/lib/Service/Gateway/SMS/Provider/OvhConfig.php
new file mode 100644
index 0000000..4703bbd
--- /dev/null
+++ b/lib/Service/Gateway/SMS/Provider/OvhConfig.php
@@ -0,0 +1,109 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @author Jordan Bieder <jordan.bieder@geduld.fr>
+ *
+ * Nextcloud - Two-factor Gateway for Ovh
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorGateway\Service\Gateway\SMS\Provider;
+
+use function array_intersect;
+use OCA\TwoFactorGateway\AppInfo\Application;
+use OCA\TwoFactorGateway\Exception\ConfigurationException;
+use OCP\IConfig;
+
+class OvhConfig implements IProviderConfig {
+
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ private function getOrFail(string $key): string {
+ $val = $this->config->getAppValue(Application::APP_NAME, $key, null);
+ if (is_null($val)) {
+ throw new ConfigurationException();
+ }
+ return $val;
+ }
+
+ public function getApplicationKey(): string {
+ return $this->getOrFail('ovh_application_key');
+ }
+
+ public function getApplicationSecret(): string {
+ return $this->getOrFail('ovh_application_secret');
+ }
+
+ public function getConsumerKey(): string {
+ return $this->getOrFail('ovh_consumer_key');
+ }
+
+ public function getEndpoint(): string {
+ return $this->getOrFail('ovh_endpoint');
+ }
+
+ public function getAccount(): string {
+ return $this->getOrFail('ovh_account');
+ }
+
+ public function getSender(): string {
+ return $this->getOrFail('ovh_sender');
+ }
+
+ public function setApplicationKey(string $appKey){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_application_key', $appKey);
+ }
+
+ public function setApplicationSecret(string $appSecret){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_application_secret', $appSecret);
+ }
+
+ public function setConsumerKey(string $consumerKey){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_consumer_key', $consumerKey);
+ }
+
+ public function setEndpoint(string $endpoint){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_endpoint', $endpoint);
+ }
+
+ public function setAccount($account){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_account', $account);
+ }
+
+ public function setSender($sender){
+ $this->config->setAppValue(Application::APP_NAME, 'ovh_sender', $sender);
+ }
+
+ public function isComplete(): bool {
+ $set = $this->config->getAppKeys(Application::APP_NAME);
+ $expected = [
+ 'ovh_application_key',
+ 'ovh_application_secret',
+ 'ovh_consumer_key',
+ 'ovh_endpoint',
+ 'ovh_account',
+ 'ovh_sender'
+ ];
+ return count(array_intersect($set, $expected)) === count($expected);
+ }
+
+}
diff --git a/lib/Service/Gateway/SMS/Provider/ProviderFactory.php b/lib/Service/Gateway/SMS/Provider/ProviderFactory.php
index b27c341..d3f3614 100644
--- a/lib/Service/Gateway/SMS/Provider/ProviderFactory.php
+++ b/lib/Service/Gateway/SMS/Provider/ProviderFactory.php
@@ -53,6 +53,8 @@ class ProviderFactory {
return $this->container->query(HuaweiE3531::class);
case Sms77Io::PROVIDER_ID:
return $this->container->query(Sms77Io::class);
+ case Ovh::PROVIDER_ID:
+ return $this->container->query(Ovh::class);
case SpryngSMS::PROVIDER_ID:
return $this->container->query(SpryngSMS::class);
default: