Merge "Remove keyring support from openstackclient"
This commit is contained in:
		@@ -79,7 +79,6 @@ The 'password flow' variation is most commonly used::
 | 
				
			|||||||
   export OS_PROJECT_NAME=<project-name>
 | 
					   export OS_PROJECT_NAME=<project-name>
 | 
				
			||||||
   export OS_USERNAME=<user-name>
 | 
					   export OS_USERNAME=<user-name>
 | 
				
			||||||
   export OS_PASSWORD=<password>  # (optional)
 | 
					   export OS_PASSWORD=<password>  # (optional)
 | 
				
			||||||
   export OS_USE_KEYRING=true  # (optional)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
The corresponding command-line options look very similar::
 | 
					The corresponding command-line options look very similar::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,12 +86,9 @@ The corresponding command-line options look very similar::
 | 
				
			|||||||
   --os-project-name <project-name>
 | 
					   --os-project-name <project-name>
 | 
				
			||||||
   --os-username <user-name>
 | 
					   --os-username <user-name>
 | 
				
			||||||
   [--os-password <password>]
 | 
					   [--os-password <password>]
 | 
				
			||||||
   [--os-use-keyring]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
If a password is not provided above (in plaintext), you will be interactively
 | 
					If a password is not provided above (in plaintext), you will be interactively
 | 
				
			||||||
prompted to provide one securely. If keyring is enabled, the password entered
 | 
					prompted to provide one securely.
 | 
				
			||||||
in the prompt is stored in keyring. From next time, the password is read from
 | 
					 | 
				
			||||||
keyring, if it is not provided above (in plaintext).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
The token flow variation for authentication uses an already-acquired token
 | 
					The token flow variation for authentication uses an already-acquired token
 | 
				
			||||||
and a URL pointing directly to the service API that presumably was acquired
 | 
					and a URL pointing directly to the service API that presumably was acquired
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,9 +68,6 @@ OPTIONS
 | 
				
			|||||||
:option:`--os-default-domain` <auth-domain>
 | 
					:option:`--os-default-domain` <auth-domain>
 | 
				
			||||||
    Default domain ID (Default: 'default')
 | 
					    Default domain ID (Default: 'default')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:option:`--os-use-keyring`
 | 
					 | 
				
			||||||
    Use keyring to store password (default: False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:option:`--os-cacert` <ca-bundle-file>
 | 
					:option:`--os-cacert` <ca-bundle-file>
 | 
				
			||||||
    CA certificate bundle file
 | 
					    CA certificate bundle file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,9 +174,6 @@ The following environment variables can be set to alter the behaviour of :progra
 | 
				
			|||||||
:envvar:`OS_DEFAULT_DOMAIN`
 | 
					:envvar:`OS_DEFAULT_DOMAIN`
 | 
				
			||||||
    Default domain ID (Default: ‘default’)
 | 
					    Default domain ID (Default: ‘default’)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:envvar:`OS_USE_KEYRING`
 | 
					 | 
				
			||||||
    Use keyring to store password (default: False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:envvar:`OS_CACERT`
 | 
					:envvar:`OS_CACERT`
 | 
				
			||||||
    CA certificate bundle file
 | 
					    CA certificate bundle file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,60 +0,0 @@
 | 
				
			|||||||
#   Copyright 2011-2013 OpenStack, LLC.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
#   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.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""Keyring backend for OpenStack, to store encrypted password in a file."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from Crypto.Cipher import AES
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import keyring
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
KEYRING_FILE = os.path.join(os.path.expanduser('~'), '.openstack-keyring.cfg')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class OpenStackKeyring(keyring.backends.file.BaseKeyring):
 | 
					 | 
				
			||||||
    """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, up to 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."""
 | 
					 | 
				
			||||||
    ring = 'openstackclient.common.openstackkeyring.OpenStackKeyring'
 | 
					 | 
				
			||||||
    return keyring.core.load_keyring(None, ring)
 | 
					 | 
				
			||||||
@@ -31,7 +31,6 @@ import openstackclient
 | 
				
			|||||||
from openstackclient.common import clientmanager
 | 
					from openstackclient.common import clientmanager
 | 
				
			||||||
from openstackclient.common import commandmanager
 | 
					from openstackclient.common import commandmanager
 | 
				
			||||||
from openstackclient.common import exceptions as exc
 | 
					from openstackclient.common import exceptions as exc
 | 
				
			||||||
from openstackclient.common import openstackkeyring
 | 
					 | 
				
			||||||
from openstackclient.common import restapi
 | 
					from openstackclient.common import restapi
 | 
				
			||||||
from openstackclient.common import utils
 | 
					from openstackclient.common import utils
 | 
				
			||||||
from openstackclient.identity import client as identity_client
 | 
					from openstackclient.identity import client as identity_client
 | 
				
			||||||
@@ -305,18 +304,6 @@ class OpenStackShell(app.App):
 | 
				
			|||||||
            default=env('OS_URL'),
 | 
					            default=env('OS_URL'),
 | 
				
			||||||
            help='Defaults to 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)')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        parser.add_argument(
 | 
					        parser.add_argument(
 | 
				
			||||||
            '--os-identity-api-version',
 | 
					            '--os-identity-api-version',
 | 
				
			||||||
            metavar='<identity-api-version>',
 | 
					            metavar='<identity-api-version>',
 | 
				
			||||||
@@ -359,14 +346,12 @@ class OpenStackShell(app.App):
 | 
				
			|||||||
                    "You must provide a username via"
 | 
					                    "You must provide a username via"
 | 
				
			||||||
                    " either --os-username or env[OS_USERNAME]")
 | 
					                    " either --os-username or env[OS_USERNAME]")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.get_password_from_keyring()
 | 
					 | 
				
			||||||
            if not self.options.os_password:
 | 
					            if not self.options.os_password:
 | 
				
			||||||
                # No password, if we've got a tty, try prompting for it
 | 
					                # No password, if we've got a tty, try prompting for it
 | 
				
			||||||
                if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
 | 
					                if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
 | 
				
			||||||
                    # Check for Ctl-D
 | 
					                    # Check for Ctl-D
 | 
				
			||||||
                    try:
 | 
					                    try:
 | 
				
			||||||
                        self.options.os_password = getpass.getpass()
 | 
					                        self.options.os_password = getpass.getpass()
 | 
				
			||||||
                        self.set_password_in_keyring()
 | 
					 | 
				
			||||||
                    except EOFError:
 | 
					                    except EOFError:
 | 
				
			||||||
                        pass
 | 
					                        pass
 | 
				
			||||||
                # No password because we did't have a tty or the
 | 
					                # No password because we did't have a tty or the
 | 
				
			||||||
@@ -430,34 +415,6 @@ class OpenStackShell(app.App):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        return
 | 
					        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):
 | 
					    def initialize_app(self, argv):
 | 
				
			||||||
        """Global app init bits:
 | 
					        """Global app init bits:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,5 @@
 | 
				
			|||||||
pbr>=0.6,!=0.7,<1.0
 | 
					pbr>=0.6,!=0.7,<1.0
 | 
				
			||||||
cliff>=1.6.0
 | 
					cliff>=1.6.0
 | 
				
			||||||
keyring>=2.1
 | 
					 | 
				
			||||||
pycrypto>=2.6
 | 
					 | 
				
			||||||
python-glanceclient>=0.13.1
 | 
					python-glanceclient>=0.13.1
 | 
				
			||||||
python-keystoneclient>=0.9.0
 | 
					python-keystoneclient>=0.9.0
 | 
				
			||||||
python-novaclient>=2.17.0
 | 
					python-novaclient>=2.17.0
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user