Remove all hard-coded passwords and require it
- Additionally, add password validation function. - Breaks Parser.py into more manageable functions. - Changes where defaults are set (Parser.py instead of class under /consts) The goal is to not have any reference to a password in the code itself, only in configuration files or README files, if strictly necessary. The new password validation function, besides failing fast at the argument parser, makes sure the password will be allowed by Debian later on the installation. This commit is not touching any Shell script because they will probably be removed or change in follow-up commits. Test Plan: PASS: Operating system password should be set to value passed via --password Failure Path: PASS: Script fails fast without the parameter --password PASS: Script fails fast if password requirements are not met Regression: PASS: AIO-SX install works Story: 2005051 Task: 47960 Task: 48230 Change-Id: Ibf42b792ef825cee61cc69d1b5afa807361037b7 Signed-off-by: Bruno Muniz <bruno.muniz@encora.com>
This commit is contained in:
parent
c93f1aa754
commit
07051a09aa
@ -7,23 +7,54 @@
|
||||
"""
|
||||
Parser to handle command line arguments
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from argparse import ArgumentParser, RawTextHelpFormatter
|
||||
import getpass
|
||||
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
def validate_password(pwd: str):
|
||||
"""
|
||||
Validation function that raises an argparse.ArgumentTypeError if
|
||||
requirements are not met.
|
||||
|
||||
Args:
|
||||
pwd: the password to validate against requirements
|
||||
|
||||
Returns: the password, if requirements are met
|
||||
"""
|
||||
errors = [
|
||||
None if len(pwd) >= 7 else "at least 7 characters long",
|
||||
None if re.search(r'[!@#$%^&*(),.?":{}|<>]', pwd) else "at least one special character",
|
||||
None if any(c.isupper() for c in pwd) else "at least one capital letter",
|
||||
None if any(c.isdigit() for c in pwd) else "at least one digit"
|
||||
]
|
||||
errors = list(filter(None, errors)) # Remove occurrences of None from errors list
|
||||
if errors:
|
||||
raise argparse.ArgumentTypeError(f'unmet requirements: {"; ".join(errors)}')
|
||||
return pwd
|
||||
|
||||
|
||||
def handle_args():
|
||||
"""
|
||||
Handle arguments supplied to the command line
|
||||
Handle arguments supplied via command line
|
||||
"""
|
||||
parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
|
||||
parse_setup_config(parser)
|
||||
parse_config_location(parser)
|
||||
parse_disk_info(parser)
|
||||
parse_networking(parser)
|
||||
parse_custom_scripts(parser)
|
||||
parse_other(parser)
|
||||
|
||||
#**************************************
|
||||
#* Setup type & install configuration *
|
||||
#**************************************
|
||||
return parser
|
||||
|
||||
|
||||
def parse_setup_config(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related to the setup type
|
||||
"""
|
||||
parser.add_argument("--setup-type", help=
|
||||
"""
|
||||
Type of setup:
|
||||
@ -83,11 +114,36 @@ def handle_args():
|
||||
""",
|
||||
type=str,
|
||||
default=None)
|
||||
parser.add_argument("--lowlatency", help=
|
||||
"""
|
||||
Whether to install an AIO system as low latency.
|
||||
""",
|
||||
action='store_true')
|
||||
parser.add_argument("--install-mode", help=
|
||||
"""
|
||||
Lab will be installed using the mode specified. Serial mode by default
|
||||
""",
|
||||
type=str, choices=['serial', 'graphical'],
|
||||
default='serial')
|
||||
parser.add_argument("--username", help=
|
||||
"""
|
||||
Username. default is 'sysadmin'
|
||||
""",
|
||||
type=str,
|
||||
default="sysadmin")
|
||||
parser.add_argument("--password", help=
|
||||
"""
|
||||
Password.
|
||||
""",
|
||||
type=validate_password,
|
||||
required=True)
|
||||
|
||||
#******************************************
|
||||
#* Config folders and files configuration *
|
||||
#******************************************
|
||||
|
||||
def parse_config_location(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related with the location of files and
|
||||
configuration
|
||||
"""
|
||||
parser.add_argument("--iso-location", help=
|
||||
"""
|
||||
Location of ISO including the filename:
|
||||
@ -143,10 +199,12 @@ def handle_args():
|
||||
""",
|
||||
action='append')
|
||||
|
||||
#**************************************
|
||||
#* Disk number and size configuration *
|
||||
#**************************************
|
||||
|
||||
def parse_disk_info(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related with VirtualBox disks
|
||||
arguments
|
||||
"""
|
||||
parser.add_argument("--controller-disks", help=
|
||||
"""
|
||||
Select the number of disks for a controller VM. default is 3
|
||||
@ -178,9 +236,11 @@ def handle_args():
|
||||
""",
|
||||
type=str)
|
||||
|
||||
#**************
|
||||
#* Networking *
|
||||
#**************
|
||||
|
||||
def parse_networking(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related with VirtualBox networking
|
||||
"""
|
||||
|
||||
parser.add_argument("--vboxnet-name", help=
|
||||
"""
|
||||
@ -203,7 +263,8 @@ def handle_args():
|
||||
"""
|
||||
OAM floating IP.
|
||||
""",
|
||||
type=str)
|
||||
type=str,
|
||||
default="10.10.10.5")
|
||||
parser.add_argument("--controller0-ip", help=
|
||||
"""
|
||||
OAM IP of controller-0. This is also used to
|
||||
@ -211,13 +272,15 @@ def handle_args():
|
||||
config_controller config file of an AIO SX setup.
|
||||
This should not be the floating IP.
|
||||
""",
|
||||
type=str)
|
||||
type=str,
|
||||
default="10.10.10.3")
|
||||
parser.add_argument("--controller1-ip", help=
|
||||
"""
|
||||
OAM IP of controller-1.
|
||||
This should not be the floating IP.
|
||||
""",
|
||||
type=str)
|
||||
type=str,
|
||||
default="10.10.10.4")
|
||||
parser.add_argument("--vboxnet-type", help=
|
||||
"""
|
||||
Type of vbox network, either hostonly on nat
|
||||
@ -277,10 +340,11 @@ def handle_args():
|
||||
""",
|
||||
type=str)
|
||||
|
||||
#******************
|
||||
#* Custom scripts *
|
||||
#******************
|
||||
|
||||
def parse_custom_scripts(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related to custom scripts
|
||||
"""
|
||||
parser.add_argument("--script1", help=
|
||||
"""
|
||||
Name of an executable script file plus options.
|
||||
@ -326,10 +390,11 @@ def handle_args():
|
||||
default=None,
|
||||
type=str)
|
||||
|
||||
#**************************************
|
||||
#* Other *
|
||||
#**************************************
|
||||
|
||||
def parse_other(parser: ArgumentParser):
|
||||
"""
|
||||
Mutate parser with CLI arguments related to overall flow control
|
||||
"""
|
||||
parser.add_argument("--list-stages", help=
|
||||
"""
|
||||
List stages that can be used by autoinstaller.
|
||||
@ -360,26 +425,6 @@ def handle_args():
|
||||
""",
|
||||
type=str, choices=['standard', 'extended'],
|
||||
default='standard')
|
||||
parser.add_argument("--lowlatency", help=
|
||||
"""
|
||||
Whether to install an AIO system as low latency.
|
||||
""",
|
||||
action='store_true')
|
||||
parser.add_argument("--install-mode", help=
|
||||
"""
|
||||
Lab will be installed using the mode specified. Serial mode by default
|
||||
""",
|
||||
type=str, choices=['serial', 'graphical'], default='serial')
|
||||
parser.add_argument("--username", help=
|
||||
"""
|
||||
Username. default is 'sysadmin'
|
||||
""",
|
||||
type=str)
|
||||
parser.add_argument("--password", help=
|
||||
"""
|
||||
Password. default is 'Li69nux*'
|
||||
""",
|
||||
type=str)
|
||||
parser.add_argument("--labname", help=
|
||||
"""
|
||||
The name of the lab to be created.
|
||||
@ -400,4 +445,3 @@ def handle_args():
|
||||
Turn on host i/o caching
|
||||
""",
|
||||
action='store_true')
|
||||
return parser
|
||||
|
@ -151,10 +151,16 @@ will be configured and used.
|
||||
```
|
||||
|
||||
5. Now you're ready to run the script. From the `/virtualbox/pybox`
|
||||
folder, do:
|
||||
folder, do (remember to change the password on the below command before
|
||||
running it):
|
||||
|
||||
```shell
|
||||
python3 ./install_vbox.py --setup-type AIO-SX \
|
||||
export STX_INSTALL_PASSWORD="Chang3*m3"
|
||||
```
|
||||
|
||||
```shell
|
||||
python3 ./install_vbox.py \
|
||||
--setup-type AIO-SX \
|
||||
--iso-location "$HOME/Downloads/stx-8.iso" \
|
||||
--labname StarlingX --install-mode serial \
|
||||
--config-files-dir ./configs/aio-sx/ \
|
||||
@ -165,6 +171,7 @@ folder, do:
|
||||
--nat-controller0-local-ssh-port 3122 \
|
||||
--controller0-ip 10.10.10.3 \
|
||||
--ini-oam-cidr '10.10.10.0/24' \
|
||||
--password $STX_INSTALL_PASSWORD \
|
||||
--snapshot
|
||||
```
|
||||
|
||||
@ -176,7 +183,8 @@ everything for you.
|
||||
|
||||
## Pybox folder structure
|
||||
.
|
||||
├── configs/aio-sx: Contains scripts and configs to set up a controller/worker
|
||||
├── consts: This folder contains modules for managing virtual lab environments, including classes for Lab, Subnets, NICs, OAM, Serial, nodes, and HostTimeout.
|
||||
├── helper: This folder contains modules for interacting with a StarlingX controller-0 server via a serial connection, configuring system settings, and managing virtual machines using VirtualBox.
|
||||
└── utils: This folder contains modules for initializing logging, tracking and reporting KPIs, connecting and communicating with remote hosts via local domain socket, and sending files and directories to remote servers using rsync and paramiko libraries.
|
||||
├── configs/aio-sx: contains scripts and configs to set up a controller/worker
|
||||
├── consts: contains modules for managing virtual lab environments, including classes for Lab, Subnets, NICs, OAM, Serial, nodes, and HostTimeout.
|
||||
├── helper: contains modules for interacting with a StarlingX controller-0 server via a serial connection, configuring system settings, and managing virtual machines using VirtualBox.
|
||||
└── utils: contains modules for initializing logging, tracking and reporting KPIs, connecting and communicating with remote hosts via local domain socket, and sending files and directories to remote servers using rsync and paramiko libraries.
|
||||
|
||||
|
@ -21,16 +21,3 @@ if platform in ("win32", "win64"):
|
||||
else:
|
||||
homedir = os.environ["HOME"]
|
||||
LOGPATH = f"{homedir}/vbox_installer_logs"
|
||||
|
||||
|
||||
class Lab: #pylint: disable=too-few-public-methods
|
||||
"""The `Lab` class represents a virtual lab and contains a dictionary attribute
|
||||
`VBOX` with information about the virtual machines in the lab."""
|
||||
|
||||
VBOX = {
|
||||
"floating_ip": "10.10.10.7",
|
||||
"controller-0_ip": "10.10.10.8",
|
||||
"controller-1_ip": "10.10.10.9",
|
||||
"username": "sysadmin",
|
||||
"password": "Li69nux*",
|
||||
}
|
||||
|
@ -114,14 +114,16 @@ def disable_logout(stream):
|
||||
serial.send_bytes(stream, "export TMOUT=0")
|
||||
|
||||
|
||||
def change_password(stream, username="sysadmin", password="Li69nux*"):
|
||||
def change_password(stream, username, password):
|
||||
"""
|
||||
changes the default password on initial login.
|
||||
changes the default password (username) on initial login.
|
||||
Args:
|
||||
stream(stream): stream to cont0
|
||||
username: the current username (which should also be the password)
|
||||
password: the new password
|
||||
"""
|
||||
|
||||
LOG.info('Changing password to Li69nux*')
|
||||
LOG.info('Changing password to %s', password)
|
||||
serial.send_bytes(stream, username, expect_prompt=False)
|
||||
serial.expect_bytes(stream, "Password:")
|
||||
serial.send_bytes(stream, username, expect_prompt=False)
|
||||
@ -133,40 +135,7 @@ def change_password(stream, username="sysadmin", password="Li69nux*"):
|
||||
serial.send_bytes(stream, password)
|
||||
|
||||
|
||||
def login(stream, timeout=600, username="sysadmin", password="Li69nux*"):
|
||||
"""
|
||||
Logs into controller-0.
|
||||
Args:
|
||||
stream(stream): stream to cont0
|
||||
timeout(int): Time before login fails in seconds.
|
||||
"""
|
||||
|
||||
serial.send_bytes(stream, "\n", expect_prompt=False)
|
||||
login_result = serial.expect_bytes(stream, "ogin:", fail_ok=True, timeout=timeout)
|
||||
if login_result != 0:
|
||||
serial.send_bytes(stream, "\n", expect_prompt=False)
|
||||
if serial.expect_bytes(stream, "~$", timeout=10, fail_ok=True) == -1:
|
||||
serial.send_bytes(stream, '\n', expect_prompt=False)
|
||||
serial.expect_bytes(stream, "keystone", timeout=10)
|
||||
else:
|
||||
serial.send_bytes(stream, username, expect_prompt=False)
|
||||
serial.expect_bytes(stream, "assword:")
|
||||
serial.send_bytes(stream, password)
|
||||
disable_logout(stream)
|
||||
|
||||
|
||||
def logout(stream):
|
||||
"""
|
||||
Logs out of controller-0.
|
||||
Args:
|
||||
stream(stream): stream to cont0
|
||||
"""
|
||||
|
||||
serial.send_bytes(stream, "exit", expect_prompt=False)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def check_password(stream, password="Li69nux*"):
|
||||
def check_password(stream, password):
|
||||
"""
|
||||
Checks the password.
|
||||
Args:
|
||||
|
@ -42,16 +42,11 @@ def set_dns(stream, dns_ip):
|
||||
)
|
||||
|
||||
|
||||
def config_controller(stream, config_file=None, password="Li69nux*"):
|
||||
def config_controller(stream, password):
|
||||
"""
|
||||
Configure controller-0 using optional arguments
|
||||
"""
|
||||
|
||||
args = ""
|
||||
if config_file:
|
||||
args += "--config-file " + config_file + " "
|
||||
|
||||
# serial.send_bytes(stream, f'sudo config_controller {args}', expect_prompt=False)
|
||||
serial.send_bytes(
|
||||
stream,
|
||||
"ansible-playbook /usr/share/ansible/stx-ansible/playbooks/bootstrap.yml",
|
||||
|
@ -29,7 +29,6 @@ from helper import vboxmanage
|
||||
from helper import install_lab
|
||||
from helper import host_helper
|
||||
|
||||
from consts import env
|
||||
from consts.node import Nodes
|
||||
from consts.networking import NICs, OAM, Serial
|
||||
from consts.timeout import HostTimeout
|
||||
@ -79,7 +78,7 @@ def menu_selector(stream, setup_type,
|
||||
time.sleep(4)
|
||||
|
||||
|
||||
def setup_networking(stream, ctrlr0_ip, gateway_ip, password='Li69nux*'):
|
||||
def setup_networking(stream, ctrlr0_ip, gateway_ip, password):
|
||||
"""
|
||||
Setup initial networking so we can transfer files.
|
||||
"""
|
||||
@ -128,7 +127,7 @@ def setup_networking(stream, ctrlr0_ip, gateway_ip, password='Li69nux*'):
|
||||
LOG.info("Ping succeeded!")
|
||||
|
||||
|
||||
def fix_networking(stream, release, password='Li69nux*'):
|
||||
def fix_networking(stream, release, password):
|
||||
"""
|
||||
Vbox/linux bug: Sometimes after resuming a VM networking fails to comes up.
|
||||
Setting VM interface down then up again fixes it.
|
||||
@ -171,8 +170,8 @@ def install_controller_0(cont0_stream, menu_select_dict, network_dict):
|
||||
network_dict (dict): A dictionary containing the following keys:
|
||||
- ctrlr0_ip (str): The IP address for controller-0.
|
||||
- gateway_ip (str): The IP address for the gateway.
|
||||
- username (str, optional): The username for the SSH connection. Defaults to "wrsroot".
|
||||
- password (str, optional): The password for the SSH connection. Defaults to "Li69nux*".
|
||||
- username (str, optional): The username for the SSH connection.
|
||||
- password (str, optional): The password for the SSH connection.
|
||||
|
||||
Raises:
|
||||
Exception: If there is a failure in the installation process.
|
||||
@ -181,8 +180,8 @@ def install_controller_0(cont0_stream, menu_select_dict, network_dict):
|
||||
The function waits for certain durations between each step.
|
||||
"""
|
||||
|
||||
username = network_dict.get("username", "wrsroot")
|
||||
password = network_dict.get("password", "Li69nux*")
|
||||
username = network_dict.get("username")
|
||||
password = network_dict.get("password")
|
||||
|
||||
LOG.info("Starting installation of controller-0")
|
||||
start_time = time.time()
|
||||
@ -966,8 +965,7 @@ def stage_config_controller(stream): # pylint: disable=too-many-locals
|
||||
|
||||
# Run config_controller
|
||||
LOG.info("#### Running config_controller")
|
||||
install_lab.config_controller(stream, config_file=destination,
|
||||
password=V_BOX_OPTIONS.password)
|
||||
install_lab.config_controller(stream, V_BOX_OPTIONS.password)
|
||||
|
||||
# Wait for services to stabilize
|
||||
time.sleep(120)
|
||||
@ -1745,22 +1743,12 @@ def load_config():
|
||||
global V_BOX_OPTIONS # pylint: disable=global-statement
|
||||
V_BOX_OPTIONS = handle_args().parse_args()
|
||||
|
||||
lab_config = [getattr(env.Lab, attr)
|
||||
for attr in dir(env.Lab) if not attr.startswith('__')]
|
||||
oam_config = [getattr(OAM, attr)
|
||||
for attr in dir(OAM) if not attr.startswith('__')]
|
||||
|
||||
if V_BOX_OPTIONS.controller0_ip is None:
|
||||
V_BOX_OPTIONS.controller0_ip = lab_config[0]['controller-0_ip']
|
||||
|
||||
if V_BOX_OPTIONS.vboxnet_ip is None:
|
||||
V_BOX_OPTIONS.vboxnet_ip = oam_config[0]['ip']
|
||||
|
||||
if V_BOX_OPTIONS.username is None:
|
||||
V_BOX_OPTIONS.username = lab_config[0]['username']
|
||||
|
||||
if V_BOX_OPTIONS.password is None:
|
||||
V_BOX_OPTIONS.password = lab_config[0]['password']
|
||||
if V_BOX_OPTIONS.hostiocache:
|
||||
V_BOX_OPTIONS.hostiocache = 'on'
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user