Support swift v3 authenticationtags/v14.0.0beta1
@@ -755,6 +755,10 @@ matrix: | |||
OBJECT_STORE: s3 | |||
- TESTS: object-store | |||
OBJECT_STORE: swift | |||
SWIFT-AUTH: v2.0 | |||
- TESTS: object-store | |||
OBJECT_STORE: swift | |||
SWIFT-AUTH: v3 | |||
- TESTS: sqlite-php7.0-samba-native | |||
- TESTS: sqlite-php7.0-samba-non-native | |||
- TEST: memcache-memcached |
@@ -36,7 +36,8 @@ use \OCA\Files_External\Lib\Config\IBackendProvider; | |||
use \OCA\Files_External\Lib\Config\IAuthMechanismProvider; | |||
use OCA\Files_External\Lib\Auth\AmazonS3\AccessKey; | |||
use OCA\Files_External\Lib\Auth\OpenStack\Rackspace; | |||
use OCA\Files_External\Lib\Auth\OpenStack\OpenStack; | |||
use OCA\Files_External\Lib\Auth\OpenStack\OpenStackV2; | |||
use OCA\Files_External\Lib\Auth\OpenStack\OpenStackV3; | |||
use OCA\Files_External\Lib\Auth\PublicKey\RSA; | |||
use OCA\Files_External\Lib\Auth\OAuth2\OAuth2; | |||
use OCA\Files_External\Lib\Auth\OAuth1\OAuth1; | |||
@@ -139,7 +140,8 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide | |||
$container->query(RSA::class), | |||
// AuthMechanism::SCHEME_OPENSTACK mechanisms | |||
$container->query(OpenStack::class), | |||
$container->query(OpenStackV2::class), | |||
$container->query(OpenStackV3::class), | |||
$container->query(Rackspace::class), | |||
// Specialized mechanisms |
@@ -29,13 +29,13 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism; | |||
/** | |||
* OpenStack Keystone authentication | |||
*/ | |||
class OpenStack extends AuthMechanism { | |||
class OpenStackV2 extends AuthMechanism { | |||
public function __construct(IL10N $l) { | |||
$this | |||
->setIdentifier('openstack::openstack') | |||
->setScheme(self::SCHEME_OPENSTACK) | |||
->setText($l->t('OpenStack')) | |||
->setText($l->t('OpenStack v2')) | |||
->addParameters([ | |||
new DefinitionParameter('user', $l->t('Username')), | |||
(new DefinitionParameter('password', $l->t('Password'))) |
@@ -0,0 +1,49 @@ | |||
<?php | |||
declare(strict_types=1); | |||
/** | |||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCA\Files_External\Lib\Auth\OpenStack; | |||
use \OCP\IL10N; | |||
use \OCA\Files_External\Lib\DefinitionParameter; | |||
use \OCA\Files_External\Lib\Auth\AuthMechanism; | |||
/** | |||
* OpenStack Keystone authentication | |||
*/ | |||
class OpenStackV3 extends AuthMechanism { | |||
public function __construct(IL10N $l) { | |||
$this | |||
->setIdentifier('openstack::openstackv3') | |||
->setScheme(self::SCHEME_OPENSTACK) | |||
->setText($l->t('OpenStack v3')) | |||
->addParameters([ | |||
new DefinitionParameter('user', $l->t('Username')), | |||
new DefinitionParameter('domain', $l->t('Domain')), | |||
(new DefinitionParameter('password', $l->t('Password'))) | |||
->setType(DefinitionParameter::VALUE_PASSWORD), | |||
new DefinitionParameter('url', $l->t('Identity endpoint URL')) | |||
]) | |||
; | |||
} | |||
} |
@@ -25,7 +25,8 @@ namespace OCA\Files_External\Lib\Backend; | |||
use \OCP\IL10N; | |||
use \OCA\Files_External\Lib\DefinitionParameter; | |||
use \OCA\Files_External\Lib\Auth\AuthMechanism; | |||
use \OCA\Files_External\Lib\Auth\OpenStack\OpenStack; | |||
use \OCA\Files_External\Service\BackendService; | |||
use \OCA\Files_External\Lib\Auth\OpenStack\OpenStackV2; | |||
use \OCA\Files_External\Lib\Auth\OpenStack\Rackspace; | |||
use \OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; | |||
@@ -33,7 +34,7 @@ class Swift extends Backend { | |||
use LegacyDependencyCheckPolyfill; | |||
public function __construct(IL10N $l, OpenStack $openstackAuth, Rackspace $rackspaceAuth) { | |||
public function __construct(IL10N $l, OpenStackV2 $openstackAuth, Rackspace $rackspaceAuth) { | |||
$this | |||
->setIdentifier('swift') | |||
->addIdentifierAlias('\OC\Files\Storage\Swift') // legacy compat |
@@ -156,13 +156,14 @@ class Swift extends \OC\Files\Storage\Common { | |||
public function __construct($params) { | |||
if ((empty($params['key']) and empty($params['password'])) | |||
or empty($params['user']) or empty($params['bucket']) | |||
or (empty($params['user']) && empty($params['userid'])) or empty($params['bucket']) | |||
or empty($params['region']) | |||
) { | |||
throw new StorageBadConfigException("API Key or password, Username, Bucket and Region have to be configured."); | |||
} | |||
$this->id = 'swift::' . $params['user'] . md5($params['bucket']); | |||
$user = $params['user']; | |||
$this->id = 'swift::' . $user . md5($params['bucket']); | |||
$bucketUrl = new Uri($params['bucket']); | |||
if ($bucketUrl->getHost()) { | |||
@@ -180,6 +181,16 @@ class Swift extends \OC\Files\Storage\Common { | |||
$params['autocreate'] = true; | |||
if (isset($params['domain'])) { | |||
$params['user'] = [ | |||
'name' => $params['user'], | |||
'password' => $params['password'], | |||
'domain' => [ | |||
'name' => $params['domain'], | |||
] | |||
]; | |||
} | |||
$this->params = $params; | |||
// FIXME: private class... | |||
$this->objectCache = new \OC\Cache\CappedMemoryCache(); |
@@ -1214,6 +1214,28 @@ $CONFIG = array( | |||
], | |||
], | |||
/** | |||
* To use swift V3 | |||
*/ | |||
'objectstore' => [ | |||
'class' => 'OC\\Files\\ObjectStore\\Swift', | |||
'arguments' => [ | |||
'autocreate' => true, | |||
'user' => [ | |||
'name' => 'swift', | |||
'password' => 'swift', | |||
'domain' => [ | |||
'name' => 'default', | |||
] | |||
], | |||
'tenantName' => 'service', | |||
'serviceName' => 'swift', | |||
'region' => 'regionOne', | |||
'url' => "http://yourswifthost:5000/v3", | |||
'bucket' => 'nextcloud' | |||
], | |||
], | |||
/** | |||
* Sharing |
@@ -31,8 +31,9 @@ use OCP\Files\StorageAuthException; | |||
use OCP\Files\StorageNotAvailableException; | |||
use OCP\ICache; | |||
use OpenStack\Common\Error\BadResponseError; | |||
use OpenStack\Identity\v2\Models\Token; | |||
use OpenStack\Identity\v2\Service; | |||
use OpenStack\Common\Auth\Token; | |||
use OpenStack\Identity\v2\Service as IdentityV2Service; | |||
use OpenStack\Identity\v3\Service as IdentityV3Service; | |||
use OpenStack\OpenStack; | |||
use OpenStack\Common\Transport\Utils as TransportUtils; | |||
use Psr\Http\Message\RequestInterface; | |||
@@ -77,30 +78,49 @@ class SwiftFactory { | |||
// should only be true for tests | |||
$this->params['autocreate'] = false; | |||
} | |||
if (!isset($this->params['username']) && isset($this->params['user'])) { | |||
$this->params['username'] = $this->params['user']; | |||
if (isset($this->params['user']) && is_array($this->params['user'])) { | |||
$userName = $this->params['user']['name']; | |||
} else { | |||
if (!isset($this->params['username']) && isset($this->params['user'])) { | |||
$this->params['username'] = $this->params['user']; | |||
} | |||
$userName = $this->params['username']; | |||
} | |||
if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) { | |||
$this->params['tenantName'] = $this->params['tenant']; | |||
} | |||
$cacheKey = $this->params['username'] . '@' . $this->params['url'] . '/' . $this->params['bucket']; | |||
$cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['bucket']; | |||
$token = $this->getCachedToken($cacheKey); | |||
$hasToken = is_array($token) && (new \DateTimeImmutable($token['expires_at'])) > (new \DateTimeImmutable('now')); | |||
if ($hasToken) { | |||
$this->params['cachedToken'] = $token; | |||
} | |||
$httpClient = new Client([ | |||
'base_uri' => TransportUtils::normalizeUrl($this->params['url']), | |||
'handler' => HandlerStack::create() | |||
]); | |||
$authService = Service::factory($httpClient); | |||
if (isset($this->params['user']) && isset($this->params['user']['name'])) { | |||
return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey); | |||
} else { | |||
return $this->auth(IdentityV2Service::factory($httpClient), $cacheKey); | |||
} | |||
} | |||
/** | |||
* @param IdentityV2Service|IdentityV3Service $authService | |||
* @param string $cacheKey | |||
* @return OpenStack | |||
* @throws StorageAuthException | |||
*/ | |||
private function auth($authService, string $cacheKey) { | |||
$this->params['identityService'] = $authService; | |||
$this->params['authUrl'] = $this->params['url']; | |||
$client = new OpenStack($this->params); | |||
if (!$hasToken) { | |||
if (!isset($this->params['cachedToken'])) { | |||
try { | |||
$token = $authService->generateToken($this->params); | |||
$this->cacheToken($token, $cacheKey); |
@@ -44,6 +44,7 @@ if [ "$OBJECT_STORE" == "swift" ]; then | |||
echo "creating test file" | |||
i=0 | |||
while [ 1 ] | |||
do | |||
sleep 2 | |||
@@ -54,6 +55,12 @@ if [ "$OBJECT_STORE" == "swift" ]; then | |||
then | |||
break | |||
fi | |||
i=$((i + 1)) | |||
if [ "$i" == "20" ] | |||
then | |||
exit -1 | |||
fi | |||
done | |||
echo "deleting test file" |
@@ -36,17 +36,39 @@ if (getenv('OBJECT_STORE') === 's3') { | |||
} | |||
if (getenv('OBJECT_STORE') === 'swift') { | |||
$swiftHost = getenv('DRONE') === 'true' ? 'dockswift' : 'localhost'; | |||
$CONFIG['objectstore'] = [ | |||
'class' => 'OC\\Files\\ObjectStore\\Swift', | |||
'arguments' => array( | |||
'autocreate' => true, | |||
'username' => 'swift', | |||
'tenantName' => 'service', | |||
'password' => 'swift', | |||
'serviceName' => 'swift', | |||
'region' => 'regionOne', | |||
'url' => "http://$swiftHost:5000/v2.0", | |||
'bucket' => 'nextcloud' | |||
) | |||
]; | |||
if (getenv('SWIFT-AUTH') === 'v2.0') { | |||
$CONFIG['objectstore'] = [ | |||
'class' => 'OC\\Files\\ObjectStore\\Swift', | |||
'arguments' => array( | |||
'autocreate' => true, | |||
'username' => 'swift', | |||
'tenantName' => 'service', | |||
'password' => 'swift', | |||
'serviceName' => 'swift', | |||
'region' => 'regionOne', | |||
'url' => "http://$swiftHost:5000/v2.0", | |||
'bucket' => 'nextcloud' | |||
) | |||
]; | |||
} else { | |||
$CONFIG['objectstore'] = [ | |||
'class' => 'OC\\Files\\ObjectStore\\Swift', | |||
'arguments' => array( | |||
'autocreate' => true, | |||
'user' => [ | |||
'name' => 'swift', | |||
'password' => 'swift', | |||
'domain' => [ | |||
'name' => 'default', | |||
] | |||
], | |||
'tenantName' => 'service', | |||
'serviceName' => 'swift', | |||
'region' => 'regionOne', | |||
'url' => "http://$swiftHost:5000/v3", | |||
'bucket' => 'nextcloud' | |||
) | |||
]; | |||
} | |||
} |