Permalink
Browse files

Auth 2.0 support (keystone)

Requires ftp-cloudfs 0.20 or later and python-keystoneclient
  • Loading branch information...
1 parent bc87c22 commit 1a72fea2d5218b87bf04337850cd5d2ceb86c51e Juan J. Martinez committed Feb 7, 2013
Showing with 96 additions and 9 deletions.
  1. +26 −3 README.md
  2. +2 −2 setup.py
  3. +15 −0 sftpcloudfs.conf.example
  4. +4 −0 sftpcloudfs/constants.py
  5. +47 −2 sftpcloudfs/main.py
  6. +2 −2 sftpcloudfs/server.py
View
@@ -1,5 +1,5 @@
-sftpd cloudfs
-=============
+sftp cloudfs
+============
This is a SFTP (Secure File Transfer Protocol) interface to Rackspace
Cloud Files and OpenStack Object Storage, providing a service that
@@ -24,9 +24,13 @@ Requirements:
- paramiko (1.7.6)
- python-cloudfiles (1.7.9)
- python-daemon (1.5.5)
-- ftp-cloudfs (0.19)
+- ftp-cloudfs (0.20)
- python-memcached (1.45)
+Optional, only for Auth 2.0 (Keystone):
+
+- python-keystoneclient 0.1.3.66 or later
+
These are the minimum recommended versions based in our testing
environment.
@@ -68,12 +72,31 @@ that supports following options:
--pid-file=PID_FILE Pid file location when in daemon mode
--uid=UID UID to drop the privileges to when in daemon mode
--gid=GID GID to drop the privileges to when in daemon mode
+ --keystone-auth Use auth 2.0 (Keystone, requires keystoneclient).
+ --keystone-region-name=REGION_NAME
+ Region name to be used in auth 2.0.
+ --keystone-tenant-separator=TENANT_SEPARATOR
+ Character used to separate tenant_name/username in
+ auth 2.0, default: TENANT.USERNAME.
+ --keystone-service-type=SERVICE_TYPE
+ Service type to be used in auth 2.0, default: object-
+ store.
+ --keystone-endpoint-type=ENDPOINT_TYPE
+ Endpoint type to be used in auth 2.0, default:
+ publicURL.
--config=CONFIG Use an alternative configuration file
The default location for the configuration file is /etc/sftpcloudfs.conf.
Memcache is optional but highly recommended for better performance.
+By default Swift auth 1.0 will be used, and is compatible with Rackspace Cloud Files and
+OpenStack Object Storage (Swift) using swauth authentication middleware.
+
+Optionally OpenStack Identity Service 2.0 (*aka* keystone) can be used. Currently python-keystoneclient
+is required to use auth 2.0 and it can be enabled with *--keystone-auth* option. Please check the
+example configuration file for further details.
+
License
-------
View
@@ -10,7 +10,7 @@ def readme():
setup(name='sftp-cloudfs',
version=version,
- description='SFTP interface to Rackspace Cloud Files and Open Stack Object Storage (Swift)',
+ description='SFTP interface to Rackspace Cloud Files and OpenStack Object Storage (Swift)',
long_description=readme(),
author='Nick Craig-Wood',
author_email='nick@memset.com',
@@ -19,7 +19,7 @@ def readme():
include_package_data=True,
zip_safe=False,
install_requires=['paramiko>=1.7.6', 'python-cloudfiles>=1.7.8', 'python-daemon>=1.5',
- 'python-memcached>=1.45', 'ftp-cloudfs>=0.19'],
+ 'python-memcached>=1.45', 'ftp-cloudfs>=0.20'],
scripts=['bin/sftpcloudfs'],
packages = find_packages(exclude=['tests']),
tests_require = ["nose"],
View
@@ -40,5 +40,20 @@
# GID to drop privileges when in daemon mode.
# gid = (empty)
+# Auth 2.0 (Keystone), requires keystoneclient
+# keystone-auth = no
+
+# Region name to be used with Auth 2.0 (optional)
+# keystone-region-name = (empty)
+
+# Tenant separator to be used with Auth 2.0 (eg. TENANT.USERNAME)
+# keystone-tenant-separator = '.'
+
+# Service type to be used with Auth 2.0.
+# keystone-service-type = 'object-store'
+
+# Endpoint type to be used with Auth 2.0.
+# keystone-endpoint-type = 'publicURL'
+
# EOF
View
@@ -2,3 +2,7 @@
project_url = "https://github.com/memset/sftpcloudfs"
config_file = "/etc/sftpcloudfs.conf"
+# keystone defaults
+default_ks_tenant_separator = '.'
+default_ks_service_type = 'object-store'
+default_ks_endpoint_type = 'publicURL'
View
@@ -36,7 +36,8 @@
from Crypto import Random
import paramiko
from sftpcloudfs.server import CloudFilesSFTPServer
-from sftpcloudfs.constants import version, project_url, config_file
+from sftpcloudfs.constants import version, project_url, config_file, default_ks_service_type, \
+ default_ks_tenant_separator, default_ks_endpoint_type
from ftpcloudfs.fs import CloudFilesFS
class PIDFile(object):
@@ -117,6 +118,12 @@ def __init__(self):
'pid-file': None,
'uid': None,
'gid': None,
+ # keystone auth 2.0 support
+ 'keystone-auth': False,
+ 'keystone-region-name': None,
+ 'keystone-tenant-separator': default_ks_tenant_separator,
+ 'keystone-service-type': default_ks_service_type,
+ 'keystone-endpoint-type': default_ks_endpoint_type,
})
if not config.read(config_file) and alt_config_file:
@@ -196,6 +203,37 @@ def __init__(self):
default=config.get('sftpcloudfs', 'gid'),
help="GID to drop the privileges to when in daemon mode")
+ parser.add_option('--keystone-auth',
+ action="store_true",
+ dest="keystone",
+ default=config.get('sftpcloudfs', 'keystone-auth'),
+ help="Use auth 2.0 (Keystone, requires keystoneclient).")
+
+ parser.add_option('--keystone-region-name',
+ type="str",
+ dest="region_name",
+ default=config.get('sftpcloudfs', 'keystone-region-name'),
+ help="Region name to be used in auth 2.0.")
+
+ parser.add_option('--keystone-tenant-separator',
+ type="str",
+ dest="tenant_separator",
+ default=config.get('sftpcloudfs', 'keystone-tenant-separator'),
+ help="Character used to separate tenant_name/username in auth 2.0, " + \
+ "default: TENANT%sUSERNAME." % default_ks_tenant_separator)
+
+ parser.add_option('--keystone-service-type',
+ type="str",
+ dest="service_type",
+ default=config.get('sftpcloudfs', 'keystone-service-type'),
+ help="Service type to be used in auth 2.0, default: %s." % default_ks_service_type)
+
+ parser.add_option('--keystone-endpoint-type',
+ type="str",
+ dest="endpoint_type",
+ default=config.get('sftpcloudfs', 'keystone-endpoint-type'),
+ help="Endpoint type to be used in auth 2.0, default: %s." % default_ks_endpoint_type)
+
parser.add_option('--config',
type="str",
dest="config",
@@ -234,6 +272,11 @@ def __init__(self):
parser.error("pid-file found: %s\nIs the server already running?" % options.pid_file)
options.max_children = config.get('sftpcloudfs', 'max-children')
+
+ if options.keystone:
+ keystone_keys = ('region_name', 'tenant_separator', 'service_type', 'endpoint_type')
+ options.keystone = dict((key, getattr(options, key)) for key in keystone_keys)
+
self.options = options
def setup_log(self):
@@ -271,7 +314,9 @@ def run(self):
server = CloudFilesSFTPServer((self.options.bind_address, self.options.port),
host_key=self.host_key,
authurl=self.options.authurl,
- max_children=self.options.max_children)
+ max_children=self.options.max_children,
+ keystone=self.options.keystone,
+ )
dc = daemon.DaemonContext()
dc.pidfile = self.pidfile
View
@@ -242,10 +242,10 @@ class CloudFilesSFTPServer(ForkingTCPServer, paramiko.ServerInterface):
"""
allow_reuse_address = True
- def __init__(self, address, host_key=None, authurl=None, max_children=20):
+ def __init__(self, address, host_key=None, authurl=None, max_children=20, keystone=None):
self.log = paramiko.util.get_logger("paramiko")
self.log.debug("%s: start server" % self.__class__.__name__)
- self.fs = CloudFilesFS(None, None, authurl=authurl) # unauthorized
+ self.fs = CloudFilesFS(None, None, authurl=authurl, keystone=keystone) # unauthorized
self.host_key = host_key
self.max_children = max_children
ForkingTCPServer.__init__(self, address, CloudFilesSFTPRequestHandler)

0 comments on commit 1a72fea

Please sign in to comment.