Merge pull request #8359 from nextcloud/swift-v3
Support swift v3 authentication
This commit is contained in:
commit
8867629cf1
|
@ -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'
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue