add set/clear/list passwords cli commands
- add set/clear/list password commands - update passwd_editor script to perform a password list - add new password unittest Still todo: - package script properly into rpm with appropriate restrictive permissions
This commit is contained in:
parent
15b2ab00b0
commit
3da95342ab
|
@ -0,0 +1,82 @@
|
|||
# Copyright(c) 2015, Oracle and/or its affiliates. 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.
|
||||
import os
|
||||
|
||||
from kollacli.exceptions import CommandError
|
||||
from kollacli import utils
|
||||
|
||||
PWDS_FILENAME = 'passwords.yml'
|
||||
PWD_EDITOR_FILENAME = 'passwd_editor.py'
|
||||
|
||||
|
||||
def set_password(pwd_key, pwd_value):
|
||||
"""set a password value
|
||||
|
||||
If the password name exists, it will be changed.
|
||||
If it doesn't exist, a new password will be added.
|
||||
"""
|
||||
editor_path = os.path.join(utils.get_kollacli_home(),
|
||||
'tools',
|
||||
PWD_EDITOR_FILENAME)
|
||||
|
||||
pwd_file_path = os.path.join(utils.get_kolla_etc(),
|
||||
PWDS_FILENAME)
|
||||
|
||||
cmd = 'sudo %s -p %s -k %s -v %s' % (editor_path, pwd_file_path,
|
||||
pwd_key, pwd_value)
|
||||
|
||||
err, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err:
|
||||
raise CommandError(output)
|
||||
|
||||
|
||||
def clear_password(pwd_key):
|
||||
"""clear a password
|
||||
|
||||
if the password exists, it will be removed from the passwords file
|
||||
"""
|
||||
editor_path = os.path.join(utils.get_kollacli_home(),
|
||||
'tools',
|
||||
PWD_EDITOR_FILENAME)
|
||||
|
||||
pwd_file_path = os.path.join(utils.get_kolla_etc(),
|
||||
PWDS_FILENAME)
|
||||
|
||||
cmd = 'sudo %s -p %s -k %s -c' % (editor_path, pwd_file_path,
|
||||
pwd_key)
|
||||
|
||||
err, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err:
|
||||
raise CommandError(output)
|
||||
|
||||
|
||||
def get_password_names():
|
||||
"""return a list of password names"""
|
||||
editor_path = os.path.join(utils.get_kollacli_home(),
|
||||
'tools',
|
||||
PWD_EDITOR_FILENAME)
|
||||
|
||||
pwd_file_path = os.path.join(utils.get_kolla_etc(),
|
||||
PWDS_FILENAME)
|
||||
|
||||
cmd = 'sudo %s -p %s -l' % (editor_path, pwd_file_path)
|
||||
|
||||
err, output = utils.run_cmd(cmd, print_output=False)
|
||||
if err:
|
||||
raise CommandError(output)
|
||||
|
||||
pwd_names = []
|
||||
if output and ',' in output[0]:
|
||||
pwd_names = output[0].split(',')
|
||||
return pwd_names
|
|
@ -15,9 +15,9 @@ import logging
|
|||
import os
|
||||
import yaml
|
||||
|
||||
from kollacli.utils import change_property
|
||||
from kollacli.utils import get_kolla_etc
|
||||
from kollacli.utils import get_kolla_home
|
||||
from kollacli.utils import change_property
|
||||
|
||||
ALLVARS_PATH = 'ansible/group_vars/all.yml'
|
||||
GLOBALS_FILENAME = 'globals.yml'
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# Copyright(c) 2015, Oracle and/or its affiliates. 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.
|
||||
import argparse
|
||||
import getpass
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from cliff.command import Command
|
||||
from cliff.lister import Lister
|
||||
|
||||
from kollacli.ansible.passwords import clear_password
|
||||
from kollacli.ansible.passwords import get_password_names
|
||||
from kollacli.ansible.passwords import set_password
|
||||
|
||||
|
||||
class PasswordSet(Command):
|
||||
"Password Set"
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(PasswordSet, self).get_parser(prog_name)
|
||||
parser.add_argument('passwordname', metavar='<passwordname>',
|
||||
help='passwordname')
|
||||
parser.add_argument('--insecure', nargs='?', help=argparse.SUPPRESS)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
password_name = parsed_args.passwordname.strip()
|
||||
if parsed_args.insecure:
|
||||
password = parsed_args.insecure.strip()
|
||||
else:
|
||||
password = getpass.getpass('Password: ').strip()
|
||||
|
||||
set_password(password_name, password)
|
||||
|
||||
except Exception:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
|
||||
class PasswordClear(Command):
|
||||
"Password Clear"
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(PasswordClear, self).get_parser(prog_name)
|
||||
parser.add_argument('passwordname', metavar='<passwordname>',
|
||||
help='passwordname')
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
try:
|
||||
password_name = parsed_args.passwordname.strip()
|
||||
clear_password(password_name)
|
||||
except Exception:
|
||||
raise Exception(traceback.format_exc())
|
||||
|
||||
|
||||
class PasswordList(Lister):
|
||||
"""List all password names"""
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
password_names = get_password_names()
|
||||
password_names = sorted(password_names)
|
||||
|
||||
data = []
|
||||
for password_name in password_names:
|
||||
data.append((password_name, '-'))
|
||||
|
||||
return (('Password Name', 'Password'), data)
|
|
@ -82,6 +82,15 @@ def convert_to_unicode(the_string):
|
|||
|
||||
|
||||
def run_cmd(cmd, print_output=True):
|
||||
"""run a system command
|
||||
|
||||
return:
|
||||
- err_flag: False=command succeeded
|
||||
True=command failed
|
||||
- output: [List of strings]
|
||||
if error, provides error information
|
||||
if success, provides command output
|
||||
"""
|
||||
log = logging.getLogger(__name__)
|
||||
err_flag = False
|
||||
output = []
|
||||
|
@ -111,9 +120,10 @@ def change_property(file_path, property_key, property_value, clear=False):
|
|||
property value: property value
|
||||
clear: flag to remove property
|
||||
|
||||
If clear and property doesn't exists, nothing is done.
|
||||
If clear, and property exists, remove it from the property file.
|
||||
If clear, and property doesn't exists, nothing is done.
|
||||
If not clear, and key is not found, the new property will be appended.
|
||||
If not clear, and key is found, edit property in place
|
||||
If not clear, and key is found, edit property in place.
|
||||
"""
|
||||
try:
|
||||
file_contents = []
|
||||
|
|
11
setup.cfg
11
setup.cfg
|
@ -31,6 +31,8 @@ console_scripts =
|
|||
kollacli = kollacli.shell:main
|
||||
|
||||
kolla.cli =
|
||||
deploy = kollacli.common:Deploy
|
||||
dump = kollacli.common:Dump
|
||||
group_add = kollacli.group:GroupAdd
|
||||
group_remove = kollacli.group:GroupRemove
|
||||
group_addhost = kollacli.group:GroupAddhost
|
||||
|
@ -44,14 +46,15 @@ kolla.cli =
|
|||
host_list = kollacli.host:HostList
|
||||
host_check = kollacli.host:HostCheck
|
||||
host_setup = kollacli.host:HostSetup
|
||||
service_list = kollacli.service:ServiceList
|
||||
list = kollacli.common:List
|
||||
password_set = kollacli.password:PasswordSet
|
||||
password_clear = kollacli.password:PasswordClear
|
||||
password_list = kollacli.password:PasswordList
|
||||
property_set = kollacli.property:PropertySet
|
||||
property_clear = kollacli.property:PropertyClear
|
||||
property_list = kollacli.property:PropertyList
|
||||
deploy = kollacli.common:Deploy
|
||||
list = kollacli.common:List
|
||||
service_list = kollacli.service:ServiceList
|
||||
setdeploy = kollacli.common:Setdeploy
|
||||
dump = kollacli.common:Dump
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# Copyright(c) 2015, Oracle and/or its affiliates. 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.
|
||||
#
|
||||
from common import KollaCliTest
|
||||
import unittest
|
||||
|
||||
|
||||
class TestFunctional(KollaCliTest):
|
||||
|
||||
def test_password_set_clear(self):
|
||||
# test list
|
||||
msg = self.run_client_cmd('password list')
|
||||
key = 'database_password'
|
||||
value = '-'
|
||||
ok = self._password_value_exists(key, value, msg)
|
||||
self.assertTrue(ok, 'list failed. Password (%s/%s) not in output: %s'
|
||||
% (key, value, msg))
|
||||
|
||||
# test append
|
||||
key = 'TeStKeY'
|
||||
value = '-'
|
||||
self.run_client_cmd('password set %s --insecure %s' % (key, value))
|
||||
msg = self.run_client_cmd('password list')
|
||||
ok = self._password_value_exists(key, value, msg)
|
||||
self.assertTrue(ok, 'set new password failed. Password ' +
|
||||
'(%s/%s) not in output: %s'
|
||||
% (key, value, msg))
|
||||
|
||||
# test modify existing
|
||||
key = 'TeStKeY'
|
||||
value = '-'
|
||||
self.run_client_cmd('password set %s --insecure %s' % (key, value))
|
||||
msg = self.run_client_cmd('password list')
|
||||
ok = self._password_value_exists(key, value, msg)
|
||||
self.assertTrue(ok, 'set modify password failed. Password ' +
|
||||
'(%s/%s) not in output: %s' %
|
||||
(key, value, msg))
|
||||
|
||||
# test clear
|
||||
key = 'TeStKeY'
|
||||
value = '-'
|
||||
self.run_client_cmd('password clear %s' % key)
|
||||
msg = self.run_client_cmd('password list')
|
||||
ok = self._password_value_exists(key, value, msg)
|
||||
self.assertFalse(ok, 'clear password failed. Password ' +
|
||||
'(%s/%s) not in output: %s' %
|
||||
(key, value, msg))
|
||||
|
||||
def _password_value_exists(self, key, value, cli_output):
|
||||
"""Verify cli data against model data"""
|
||||
# check for any host in cli output that shouldn't be there
|
||||
cli_lines = cli_output.split('\n')
|
||||
for cli_line in cli_lines:
|
||||
if key in cli_line and value in cli_line:
|
||||
return True
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -18,6 +18,22 @@ import sys
|
|||
from kollacli import utils
|
||||
|
||||
|
||||
def _print_pwd_keys(path):
|
||||
pwd_keys = ''
|
||||
prefix = ''
|
||||
with open(path, 'r') as pwd_file:
|
||||
for line in pwd_file:
|
||||
if line.startswith('#'):
|
||||
# skip commented lines
|
||||
continue
|
||||
if ':' in line:
|
||||
pwd_key = line.split(':')[0]
|
||||
pwd_keys = pwd_keys + prefix + pwd_key
|
||||
prefix = ','
|
||||
|
||||
print(pwd_keys)
|
||||
|
||||
|
||||
def main():
|
||||
"""edit password in passwords.yml file
|
||||
|
||||
|
@ -26,9 +42,9 @@ def main():
|
|||
-k key # key of password
|
||||
-v value # value of password
|
||||
-c # flag to clear the password
|
||||
-l # return a csv string of the existing keys
|
||||
-l # print to stdout a csv string of the existing keys
|
||||
"""
|
||||
opts, _ = getopt.getopt(sys.argv[1:], 'p:k:v:cal')
|
||||
opts, _ = getopt.getopt(sys.argv[1:], 'p:k:v:cl')
|
||||
path = ''
|
||||
pwd_key = ''
|
||||
pwd_value = ''
|
||||
|
@ -47,11 +63,11 @@ def main():
|
|||
list_flag = True
|
||||
|
||||
if list_flag:
|
||||
# return the password keys
|
||||
pass
|
||||
# print the password keys
|
||||
_print_pwd_keys(path)
|
||||
else:
|
||||
# edit a password
|
||||
utils.change_property(path, pwd_key, pwd_value, clear=clear_flag)
|
||||
utils.change_property(path, pwd_key, pwd_value, clear_flag)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue