Merge "Keyring support for openstackclient."

This commit is contained in:
Jenkins 2012-08-22 20:49:54 +00:00 committed by Gerrit Code Review
commit a5aa06c92f
4 changed files with 112 additions and 1 deletions

View File

@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
modules=setup
modules=setup,openstackkeyring
# The base module to hold the copy of openstack.common
base=openstackclient

View File

@ -0,0 +1,65 @@
# Copyright 2011 OpenStack LLC.
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
"""
Keyring backend for Openstack, to store encrypted password in a file.
"""
from Crypto.Cipher import AES
import crypt
import keyring
import os
KEYRING_FILE = os.path.join(os.path.expanduser('~'), '.openstack-keyring.cfg')
class OpenstackKeyring(keyring.backend.BasicFileKeyring):
""" Openstack Keyring to store encrypted password """
filename = KEYRING_FILE
def supported(self):
""" applicable for all platforms, but not recommend """
pass
def _init_crypter(self):
""" initialize the crypter using the class name """
block_size = 32
padding = '0'
# init the cipher with the class name, upto block_size
password = __name__[block_size:]
password = password + (block_size - len(password) % \
block_size) * padding
return AES.new(password, AES.MODE_CFB)
def encrypt(self, password):
""" encrypt the given password """
crypter = self._init_crypter()
return crypter.encrypt(password)
def decrypt(self, password_encrypted):
""" decrypt the given password """
crypter = self._init_crypter()
return crypter.decrypt(password_encrypted)
def os_keyring():
""" initialize the openstack keyring """
return keyring.core.load_keyring(None,
'openstackclient.common.openstackkeyring.OpenstackKeyring')

View File

@ -29,10 +29,12 @@ from cliff.commandmanager import CommandManager
from openstackclient.common import clientmanager
from openstackclient.common import exceptions as exc
from openstackclient.common import openstackkeyring
from openstackclient.common import utils
VERSION = '0.1'
KEYRING_SERVICE = 'openstack'
def env(*vars, **kwargs):
@ -123,6 +125,18 @@ class OpenStackShell(App):
default=env('OS_URL'),
help='Defaults to env[OS_URL]')
env_os_keyring = env('OS_USE_KEYRING', default=False)
if type(env_os_keyring) == str:
if env_os_keyring.lower() in ['true', '1']:
env_os_keyring = True
else:
env_os_keyring = False
parser.add_argument('--os-use-keyring',
default=env_os_keyring,
action='store_true',
help='Use keyring to store password, '
'default=False (Env: OS_USE_KEYRING)')
return parser
def authenticate_user(self):
@ -149,12 +163,14 @@ class OpenStackShell(App):
"You must provide a username via"
" either --os-username or env[OS_USERNAME]")
self.get_password_from_keyring()
if not self.options.os_password:
# No password, if we've got a tty, try prompting for it
if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
# Check for Ctl-D
try:
self.options.os_password = getpass.getpass()
self.set_password_in_keyring()
except EOFError:
pass
# No password because we did't have a tty or the
@ -188,6 +204,34 @@ class OpenStackShell(App):
)
return
def init_keyring_backend(self):
"""Initialize openstack backend to use for keyring"""
return openstackkeyring.os_keyring()
def get_password_from_keyring(self):
"""Get password from keyring, if it's set"""
if self.options.os_use_keyring:
service = KEYRING_SERVICE
backend = self.init_keyring_backend()
if not self.options.os_password:
password = backend.get_password(service,
self.options.os_username)
self.options.os_password = password
def set_password_in_keyring(self):
"""Set password in keyring for this user"""
if self.options.os_use_keyring:
service = KEYRING_SERVICE
backend = self.init_keyring_backend()
if self.options.os_password:
password = backend.get_password(service,
self.options.os_username)
# either password is not set in keyring, or it is different
if password != self.options.os_password:
backend.set_password(service,
self.options.os_username,
self.options.os_password)
def initialize_app(self, argv):
"""Global app init bits:

View File

@ -1,7 +1,9 @@
cliff
argparse
httplib2
keyring
prettytable
pycrypto
python-keystoneclient>=0.1,<0.2
python-novaclient>=2,<3
simplejson