Use correct default key file and normalize the usage

The provision command was defaulting to id_rsa.pub, however the deploy
command uses id_rsa_tripleo for initial setup.

When using the deploy command for provision as well, use the public
key, not the private id_rsa_tripleo.

This option was being processed in several different ways, this change
normalize it by creating a single function in the Command class, which
all inheriting methods will consume. Tests have been updated to
accomodate this change.

Related-Bug: #1863920
Change-Id: I221480f3cfc77545a8fcbef777829239c3bad0a0
Signed-off-by: Kevin Carter <kecarter@redhat.com>
This commit is contained in:
Kevin Carter 2020-02-19 20:15:22 -06:00
parent 475ace8f60
commit af749d1a6a
No known key found for this signature in database
GPG Key ID: CE94BD890A47B20A
14 changed files with 80 additions and 29 deletions

View File

@ -70,6 +70,29 @@ class Command(command.Command):
key = '.ssh/tripleo-admin-rsa' key = '.ssh/tripleo-admin-rsa'
return key, None return key, None
def get_key_pair(self, parsed_args):
"""Autodetect or return a user defined key file.
:param parsed_args: An argparse object.
:type parsed_args: Object
:returns: String
"""
if not parsed_args.overcloud_ssh_key:
key = utils.get_key(
stack=parsed_args.stack,
needs_pair=True
)
if not key:
raise oscexc.CommandError(
'No key pair found, set the ssh key using'
'the --overcloud-ssh-key switch.'
)
return key
else:
return parsed_args.overcloud_ssh_key
class Lister(Command, command.Lister): class Lister(Command, command.Lister):
pass pass

View File

@ -194,6 +194,10 @@ class FakePlaybookExecution(utils.TestCommand):
) )
self.config_action.start() self.config_action.start()
self.addCleanup(self.config_action.stop) self.addCleanup(self.config_action.stop)
get_key = mock.patch('tripleoclient.utils.get_key')
get_key.start()
get_key.return_value = 'keyfile-path'
self.addCleanup(get_key.stop)
if ansible_mock: if ansible_mock:
get_stack = mock.patch('tripleoclient.utils.get_stack') get_stack = mock.patch('tripleoclient.utils.get_stack')

View File

@ -1580,6 +1580,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
with open(ssh_key_path, 'w') as temp_file: with open(ssh_key_path, 'w') as temp_file:
temp_file.write('sekrit') temp_file.write('sekrit')
with open('{}.pub'.format(ssh_key_path), 'w') as f:
f.write('sekrit')
arglist = [ arglist = [
'--baremetal-deployment', bm_deploy_path, '--baremetal-deployment', bm_deploy_path,
'--overcloud-ssh-key', ssh_key_path '--overcloud-ssh-key', ssh_key_path

View File

@ -100,7 +100,7 @@ class TestFFWDUpgradePrepare(fakes.TestFFWDUpgradePrepare):
mock_stack, mock_stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, mock.ANY,
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )
mock_overcloud_deploy.assert_called_once_with(parsed_args) mock_overcloud_deploy.assert_called_once_with(parsed_args)

View File

@ -1290,6 +1290,8 @@ class TestProvisionNode(fakes.TestOvercloudNode):
inp.flush() inp.flush()
keyf.write(b'I am a key') keyf.write(b'I am a key')
keyf.flush() keyf.flush()
with open('{}.pub'.format(keyf.name), 'w') as f:
f.write('I am a key')
argslist = ['--output', outp.name, argslist = ['--output', outp.name,
'--overcloud-ssh-key', keyf.name, '--overcloud-ssh-key', keyf.name,

View File

@ -105,7 +105,7 @@ class TestOvercloudUpgradePrepare(fakes.TestOvercloudUpgradePrepare):
mock_stack, mock_stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, mock.ANY,
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )

View File

@ -37,6 +37,6 @@ class TestAdminAuthorize(test_plugin.TestPluginV1):
mock_stack, mock_stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, mock.ANY,
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )

View File

@ -13,6 +13,8 @@
# under the License. # under the License.
# #
import mock
from tripleoclient.tests import base from tripleoclient.tests import base
from tripleoclient.tests import fakes from tripleoclient.tests import fakes
@ -35,3 +37,7 @@ class TestPluginV1(base.TestCommand):
endpoint=fakes.AUTH_URL, endpoint=fakes.AUTH_URL,
token=fakes.AUTH_TOKEN, token=fakes.AUTH_TOKEN,
) )
get_key = mock.patch('tripleoclient.utils.get_key')
get_key.start()
get_key.return_value = 'keyfile-path'
self.addCleanup(get_key.stop)

View File

@ -1404,7 +1404,7 @@ def get_config(clients, container):
config_action.run(context=context) config_action.run(context=context)
def get_key(stack): def get_key(stack, needs_pair=False):
"""Returns the private key from the local file system. """Returns the private key from the local file system.
Searches for and returns the stack private key. If the key is inaccessible Searches for and returns the stack private key. If the key is inaccessible
@ -1414,18 +1414,26 @@ def get_key(stack):
:params stack: name of the stack to use :params stack: name of the stack to use
:type stack: String :type stack: String
:param needs_pair: Enable key pair search
:type needs_pair: Boolean
:returns: String || None :returns: String || None
""" """
key_files = list()
stack_dir = os.path.join(constants.DEFAULT_WORK_DIR, stack) stack_dir = os.path.join(constants.DEFAULT_WORK_DIR, stack)
stack_key_file = os.path.join(stack_dir, 'ssh_private_key') key_files.append(os.path.join(stack_dir, 'ssh_private_key'))
user_dir = os.path.join(os.path.expanduser("~"), '.ssh') user_dir = os.path.join(os.path.expanduser("~"), '.ssh')
user_key_file = os.path.join(user_dir, 'id_rsa_tripleo') key_files.append(os.path.join(user_dir, 'id_rsa_tripleo'))
key_files.append(os.path.join(user_dir, 'id_rsa'))
legacy_dir = os.path.join(constants.DEFAULT_WORK_DIR, '.ssh') legacy_dir = os.path.join(constants.DEFAULT_WORK_DIR, '.ssh')
legacy_key_file = os.path.join(legacy_dir, 'tripleo-admin-rsa') key_files.append(os.path.join(legacy_dir, 'tripleo-admin-rsa'))
for key_file in [stack_key_file, user_key_file, legacy_key_file]: for key_file in key_files:
try: try:
if os.path.exists(key_file): if os.path.exists(key_file):
if needs_pair:
if not os.path.exists('{}.pub'.format(key_file)):
continue
with open(key_file): with open(key_file):
return key_file return key_file
except IOError: except IOError:

View File

@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# #
import os
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
@ -51,9 +50,9 @@ class Authorize(command.Command):
) )
parser.add_argument( parser.add_argument(
'--overcloud-ssh-key', '--overcloud-ssh-key',
default=os.path.join( default=None,
os.path.expanduser('~'), '.ssh', 'id_rsa'), help=_('Key path for ssh access to overcloud nodes. When'
help=_('Key path for ssh access to overcloud nodes.') 'undefined the key will be autodetected.')
) )
parser.add_argument( parser.add_argument(
'--overcloud-ssh-network', '--overcloud-ssh-network',
@ -83,6 +82,6 @@ class Authorize(command.Command):
stack, stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )

View File

@ -608,14 +608,17 @@ class DeployOvercloud(command.Command):
with open(parsed_args.baremetal_deployment, 'r') as fp: with open(parsed_args.baremetal_deployment, 'r') as fp:
roles = yaml.safe_load(fp) roles = yaml.safe_load(fp)
with open(parsed_args.overcloud_ssh_key, 'rt') as fp: key = self.get_key_pair(parsed_args)
with open('{}.pub'.format(key), 'rt') as fp:
ssh_key = fp.read() ssh_key = fp.read()
parameter_defaults = baremetal.deploy_roles( parameter_defaults = baremetal.deploy_roles(
self.app.client_manager, self.app.client_manager,
plan=parsed_args.stack, plan=parsed_args.stack,
roles=roles, ssh_keys=[ssh_key], roles=roles,
ssh_user_name=parsed_args.overcloud_ssh_user) ssh_keys=[ssh_key],
ssh_user_name=parsed_args.overcloud_ssh_user
)
env_path, swift_path = self._write_user_environment( env_path, swift_path = self._write_user_environment(
parameter_defaults, parameter_defaults,
@ -674,9 +677,9 @@ class DeployOvercloud(command.Command):
) )
parser.add_argument( parser.add_argument(
'--overcloud-ssh-key', '--overcloud-ssh-key',
default=os.path.join( default=None,
os.path.expanduser('~'), '.ssh', 'id_rsa_tripleo'), help=_('Key path for ssh access to overcloud nodes. When'
help=_('Key path for ssh access to overcloud nodes.') 'undefined the key will be autodetected.')
) )
parser.add_argument( parser.add_argument(
'--overcloud-ssh-network', '--overcloud-ssh-network',
@ -956,7 +959,7 @@ class DeployOvercloud(command.Command):
stack, stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )

View File

@ -95,7 +95,7 @@ class FFWDUpgradePrepare(DeployOvercloud):
stack, stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )

View File

@ -617,10 +617,10 @@ class ProvisionNode(command.Command):
help=_('User for SSH access to newly deployed ' help=_('User for SSH access to newly deployed '
'nodes')) 'nodes'))
parser.add_argument('--overcloud-ssh-key', parser.add_argument('--overcloud-ssh-key',
default=os.path.join( default=None,
os.path.expanduser('~'), '.ssh', 'id_rsa.pub'), help=_('Key path for ssh access to'
help=_('Public key path for SSH access to newly ' 'overcloud nodes. When undefined the key'
'deployed nodes')) 'will be autodetected.'))
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
@ -629,14 +629,17 @@ class ProvisionNode(command.Command):
with open(parsed_args.input, 'r') as fp: with open(parsed_args.input, 'r') as fp:
roles = yaml.safe_load(fp) roles = yaml.safe_load(fp)
with open(parsed_args.overcloud_ssh_key, 'rt') as fp: key = self.get_key_pair(parsed_args)
with open('{}.pub'.format(key), 'rt') as fp:
ssh_key = fp.read() ssh_key = fp.read()
output = baremetal.deploy_roles( output = baremetal.deploy_roles(
self.app.client_manager, self.app.client_manager,
plan=parsed_args.stack, plan=parsed_args.stack,
roles=roles, ssh_keys=[ssh_key], roles=roles,
ssh_user_name=parsed_args.overcloud_ssh_user) ssh_keys=[ssh_key],
ssh_user_name=parsed_args.overcloud_ssh_user
)
with open(parsed_args.output, 'w') as fp: with open(parsed_args.output, 'w') as fp:
yaml.safe_dump(output['environment'], fp, default_flow_style=False) yaml.safe_dump(output['environment'], fp, default_flow_style=False)

View File

@ -85,7 +85,7 @@ class UpgradePrepare(DeployOvercloud):
stack, stack,
parsed_args.overcloud_ssh_network, parsed_args.overcloud_ssh_network,
parsed_args.overcloud_ssh_user, parsed_args.overcloud_ssh_user,
parsed_args.overcloud_ssh_key, self.get_key_pair(parsed_args),
parsed_args.overcloud_ssh_port_timeout parsed_args.overcloud_ssh_port_timeout
) )