rewrite
This commit is contained in:
parent
c5ee561bbd
commit
40128c57b5
4
setup.py
4
setup.py
|
|
@ -7,8 +7,8 @@ setup(
|
|||
packages=find_packages(),
|
||||
install_requires=[],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'tenant=tenant.main:main',
|
||||
"console_scripts": [
|
||||
"tenant=tenant.main:main",
|
||||
],
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,40 +1,32 @@
|
|||
# tenant/commands/init.py
|
||||
import os
|
||||
from tenant.utils.common import get_secure_password
|
||||
from tenant.utils.common import get_secure_password, generate_key, generate_csr
|
||||
from tenant.utils.terraform import create_tfvars_file
|
||||
import tenant.utils.generatecsr
|
||||
import tenant.utils.generate_secrets_file
|
||||
|
||||
|
||||
def add_subparser(subparsers):
|
||||
init_parser = subparsers.add_parser("init", help="Initialize a new tenant")
|
||||
default_tenant_name = os.getenv("TENANT_NAME", None)
|
||||
init_parser.add_argument(
|
||||
"tenant_name", help="Name of the tenant", default=default_tenant_name, nargs="?"
|
||||
)
|
||||
init_parser.add_argument(
|
||||
"--target", default=".", help="Target directory (default: current directory)"
|
||||
)
|
||||
|
||||
|
||||
def execute(args):
|
||||
if args.tenant_name is not None:
|
||||
tenant_name = args.tenant_name
|
||||
# If tenant_name is not provided and TENANT_NAME is not set, prompt the user
|
||||
if args.tenant_name is None and os.getenv("TENANT_NAME") is None:
|
||||
tenant_name = input("Please enter the tenant name: ")
|
||||
|
||||
# Ask the user to confirm the tenant name if the environment variable is set
|
||||
if os.getenv("TENANT_NAME") == args.tenant_name:
|
||||
tenant_name = os.environ.get("TENANT_NAME")
|
||||
if not tenant_name:
|
||||
tenant_name = input("Please enter the desired tenant name: ")
|
||||
else:
|
||||
user_confirmation = input(
|
||||
f"Use '{os.getenv('TENANT_NAME')}' as the tenant name? (yes/no): "
|
||||
).lower()
|
||||
if user_confirmation not in ("yes", "y"):
|
||||
tenant_name = input("Please enter the desired tenant name: ")
|
||||
f"Current tenant name is {tenant_name}. Is this correct? (y/n): "
|
||||
)
|
||||
if user_confirmation != "y":
|
||||
tenant_name = input("Please enter the tenant name: ")
|
||||
|
||||
if os.getenv("TENANT_NAME") and args.tenant_name != os.getenv("TENANT_NAME"):
|
||||
user_confirmation = input(
|
||||
f"Both env var TENANT_NAME and tenant_name argument are set. Use '{os.getenv('TENANT_NAME')}' as the tenant name? (If no, '{tenant_name}' will be used) (yes/no): "
|
||||
).lower()
|
||||
if user_confirmation in ("yes", "y"):
|
||||
tenant_name = os.getenv("TENANT_NAME")
|
||||
ingress = input(
|
||||
"Please enter the FQDN of the Kibana ingress, without the 'kibana' prefix: "
|
||||
)
|
||||
|
||||
target_directory = args.target
|
||||
|
||||
|
|
@ -42,25 +34,42 @@ def execute(args):
|
|||
|
||||
# Check if the tenant directory already exists
|
||||
if os.path.exists(tenant_directory):
|
||||
print(f"Error: Tenant directory '{tenant_directory}' already exists.")
|
||||
print(
|
||||
f"Error: Tenant directory '{tenant_directory}' already exists. Init aborted."
|
||||
)
|
||||
return
|
||||
|
||||
# Prompt the user for the GitSync password securely
|
||||
git_sync_password = get_secure_password(
|
||||
prompt="Please insert known password for GitSync: "
|
||||
prompt="Please insert predefined password for GitSync: "
|
||||
)
|
||||
|
||||
terraform_directory = os.path.join(tenant_directory, "terraform")
|
||||
kubernetes_directory = os.path.join(tenant_directory, "kubernetes")
|
||||
certificates_directory = os.path.join(tenant_directory, "certificates")
|
||||
# define and create necessary folder structure
|
||||
terraform_directory = os.path.join(tenant_directory, "00-terraform")
|
||||
certificates_directory = os.path.join(tenant_directory, "01-certificates")
|
||||
kubernetes_directory = os.path.join(tenant_directory, "02-kubernetes")
|
||||
helm_directory = os.path.join(tenant_directory, "03-helm")
|
||||
|
||||
os.makedirs(certificates_directory)
|
||||
os.makedirs(terraform_directory)
|
||||
os.makedirs(kubernetes_directory)
|
||||
os.makedirs(certificates_directory)
|
||||
os.makedirs(helm_directory)
|
||||
|
||||
# Create symbolic links for *.tf files
|
||||
# generate key and csr if not exist
|
||||
keyfile = os.path.join(certificates_directory, ingress + ".key")
|
||||
csrfile = os.path.join(certificates_directory, ingress + ".csr")
|
||||
|
||||
if os.path.exists(keyfile):
|
||||
print("Keyfile file already exists")
|
||||
print(keyfile)
|
||||
exit(1)
|
||||
else:
|
||||
generate_key(keyfile)
|
||||
generate_csr(csrfile, ingress)
|
||||
|
||||
# Create symbolic links for *.tf files in tenant directory
|
||||
source_tf_dir = os.path.join(target_directory, "terraform")
|
||||
target_tf_dir = os.path.join(tenant_directory, "terraform")
|
||||
target_tf_dir = terraform_directory
|
||||
|
||||
for filename in os.listdir(source_tf_dir):
|
||||
if filename.endswith(".tf"):
|
||||
|
|
@ -74,6 +83,22 @@ def execute(args):
|
|||
print(
|
||||
f"Warning: Source file '{filename}' not found in '{source_tf_dir}'."
|
||||
)
|
||||
print(
|
||||
f"Tenant '{tenant_name}' initialized in '{tenant_directory}' with GitSync password provided."
|
||||
)
|
||||
|
||||
variables = {
|
||||
"tenant_name": tenant_name,
|
||||
}
|
||||
|
||||
tfvars_filepath = os.path.join(terraform_directory, tenant_name + ".tfvars")
|
||||
create_tfvars_file(variables, tfvars_filepath)
|
||||
|
||||
# generate secrets file if not already exist, not yet encrypted on the fly
|
||||
secrets_file = os.path.join(helm_directory, tenant_name + ".secrets.yaml")
|
||||
if os.path.exists(secrets_file):
|
||||
print("Secrets file already exists")
|
||||
print(secrets_file)
|
||||
else:
|
||||
tenant.utils.generate_secrets_file.generate_secrets_file(
|
||||
secrets_file, git_sync_password
|
||||
)
|
||||
|
||||
print(f"Tenant '{tenant_name}' initialized in '{tenant_directory}'.")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,62 @@
|
|||
# tenant/utils/common.py
|
||||
import getpass
|
||||
from OpenSSL import crypto
|
||||
|
||||
TYPE_RSA = crypto.TYPE_RSA
|
||||
TYPE_DSA = crypto.TYPE_DSA
|
||||
key = crypto.PKey()
|
||||
|
||||
|
||||
def get_secure_password(prompt="Enter password: "):
|
||||
# Use getpass to securely input a password without displaying it
|
||||
return getpass.getpass(prompt=prompt)
|
||||
|
||||
|
||||
def generate_key(keyfile):
|
||||
print("Generating Key: ")
|
||||
key.generate_key(TYPE_RSA, 4096)
|
||||
f = open(keyfile, "wb")
|
||||
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
|
||||
|
||||
|
||||
def generate_csr(csrfile, ingress):
|
||||
req = crypto.X509Req()
|
||||
req.get_subject().CN = ingress
|
||||
req.get_subject().C = "DE"
|
||||
req.get_subject().ST = "Nordrhein-Westfalen"
|
||||
req.get_subject().L = "Bonn"
|
||||
req.get_subject().O = "Informationstechnikzentrum Bund (ITZBund)"
|
||||
req.get_subject().OU = "Laas/DaaS"
|
||||
req.get_subject().emailAddress = "logging@itzbund.de"
|
||||
req.set_pubkey(key)
|
||||
req.sign(key, "sha256")
|
||||
f = open(csrfile, "wb")
|
||||
f.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, req))
|
||||
f.close()
|
||||
print("CSR file generated")
|
||||
|
||||
|
||||
def calculate_java_settings(memory_limit):
|
||||
# Use regex to extract the value and unit
|
||||
match = re.match(r"(\d*\.?\d+)([GgMm])i?", memory_limit)
|
||||
|
||||
if match:
|
||||
value, unit = match.groups()
|
||||
|
||||
# Convert the value to an integer
|
||||
value = float(value)
|
||||
|
||||
if unit.lower() == "g":
|
||||
# Convert GiB to MiB
|
||||
value *= 1024
|
||||
|
||||
# Calculate Xmx value
|
||||
xmx_value = value * 0.75
|
||||
|
||||
# Build the Java Xmx settings string without decimal part if it's ".0"
|
||||
value = f"{int(xmx_value) if xmx_value.is_integer() else xmx_value}m"
|
||||
java_settings = "-Xmx" + value + " " + "-Xms" + value
|
||||
return java_settings
|
||||
else:
|
||||
# If the unit is neither "Gi" nor "m", return an error message or handle accordingly
|
||||
return "Unsupported memory unit"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
import random
|
||||
import os
|
||||
import ruamel.yaml
|
||||
import string
|
||||
|
||||
yaml = ruamel.yaml.YAML()
|
||||
|
||||
|
||||
def generate_random_string(length):
|
||||
characters = string.ascii_letters + string.digits
|
||||
return "".join(random.choice(characters) for i in range(length))
|
||||
|
||||
|
||||
def generate_secrets_file(secrets_file, git_sync_password):
|
||||
with open(secrets_file, "w", encoding="utf-8") as file:
|
||||
yaml.dump(
|
||||
{
|
||||
"elasticsearch": {
|
||||
"config": {
|
||||
"rbac": {
|
||||
"builtinUsers": {
|
||||
"apm_system": generate_random_string(8),
|
||||
"beats_system": generate_random_string(8),
|
||||
"elastic": generate_random_string(8),
|
||||
"kibana_system": generate_random_string(8),
|
||||
"logstash_system": generate_random_string(8),
|
||||
"remote_monitoring_user": generate_random_string(8),
|
||||
},
|
||||
"customUsers": {
|
||||
"logstash_internal": {
|
||||
"password": generate_random_string(8)
|
||||
},
|
||||
"logstash_writer": {
|
||||
"password": generate_random_string(8)
|
||||
},
|
||||
"prometheus": {"password": "monitor"},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"kibana": {
|
||||
"config": {
|
||||
"encryption": {
|
||||
"common": generate_random_string(32),
|
||||
"reporting": generate_random_string(32),
|
||||
"savedObjects": generate_random_string(32),
|
||||
}
|
||||
}
|
||||
},
|
||||
"logstash": {
|
||||
"gitSync": {"password": git_sync_password},
|
||||
"password": generate_random_string(32),
|
||||
},
|
||||
"oauthProxy": {
|
||||
"clientSecret": generate_random_string(20),
|
||||
"cookie_secret": generate_random_string(32),
|
||||
},
|
||||
"tls": {
|
||||
"externalCertificates": {
|
||||
"kibana": {"tls_key": "ImportMeFromSopsFile"}
|
||||
},
|
||||
"keystorePassword": generate_random_string(8),
|
||||
"truststorePassword": generate_random_string(8),
|
||||
},
|
||||
},
|
||||
file,
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
def create_tfvars_file(variables, filepath):
|
||||
with open(filepath, "w") as tfvars_file:
|
||||
for key, value in variables.items():
|
||||
# Writing variable assignments to the file
|
||||
tfvars_file.write(f'{key} = "{value}"\n')
|
||||
|
|
@ -5,6 +5,7 @@ from unittest.mock import patch
|
|||
from argparse import Namespace # Import Namespace for creating args object
|
||||
from tenant.commands import init
|
||||
|
||||
|
||||
class TestInitCommand(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Set up any necessary configurations or resources
|
||||
|
|
@ -25,7 +26,9 @@ class TestInitCommand(unittest.TestCase):
|
|||
os.rmdir(tenant_directory)
|
||||
|
||||
# Create an args object
|
||||
args = Namespace(command="init", tenant_name=tenant_name, target=target_directory)
|
||||
args = Namespace(
|
||||
command="init", tenant_name=tenant_name, target=target_directory
|
||||
)
|
||||
|
||||
# Call the init command with the args object
|
||||
init.execute(args)
|
||||
|
|
@ -42,5 +45,6 @@ class TestInitCommand(unittest.TestCase):
|
|||
os.rmdir(os.path.join(tenant_directory, "certificates"))
|
||||
os.rmdir(tenant_directory)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue