class Create(ZatoCommand): """ Creates a new Zato cluster in the ODB """ opts = deepcopy(common_odb_opts) opts.append({'name':'lb_host', 'help':"Load-balancer host"}) opts.append({'name':'lb_port', 'help':'Load-balancer port'}) opts.append({'name':'lb_agent_port', 'help':'Load-balancer agent host'}) opts.append({'name':'broker_host', 'help':"Redis host"}) opts.append({'name':'broker_port', 'help':'Redis port'}) opts.append({'name':'cluster_name', 'help':'Name of the cluster to create'}) opts += get_tech_account_opts('for web admin instances to use') def execute(self, args, show_output=True): engine = self._get_engine(args) session = self._get_session(engine) cluster = Cluster() cluster.name = args.cluster_name cluster.description = 'Created by {} on {} (UTC)'.format(self._get_user_host(), datetime.utcnow().isoformat()) for name in('odb_type', 'odb_host', 'odb_port', 'odb_user', 'odb_db_name', 'broker_host', 'broker_port', 'lb_host', 'lb_port', 'lb_agent_port'): setattr(cluster, name, getattr(args, name)) session.add(cluster) admin_invoke_sec = HTTPBasicAuth(None, 'admin.invoke', True, 'admin.invoke', 'Zato admin invoke', args.admin_invoke_password, cluster) session.add(admin_invoke_sec) pubapi_sec = HTTPBasicAuth(None, 'pubapi', True, 'pubapi', 'Zato public API', uuid4().hex, cluster) session.add(pubapi_sec) self.add_soap_services(session, cluster, admin_invoke_sec, pubapi_sec) self.add_ping_services(session, cluster) try: session.commit() except IntegrityError, e: msg = 'Cluster name [{}] already exists'.format(cluster.name) if self.verbose: msg += '. Caught an exception:[{}]'.format(format_exc(e)) self.logger.error(msg) self.logger.error(msg) session.rollback() return self.SYS_ERROR.CLUSTER_NAME_ALREADY_EXISTS if show_output: if self.verbose: msg = 'Successfully created a new cluster [{}]'.format(args.cluster_name) self.logger.debug(msg) else: self.logger.info('OK')
class Create(ZatoCommand): """ Creates a new Zato cluster in the ODB """ opts = deepcopy(common_odb_opts) opts.append({'name': 'lb_host', 'help': "Load-balancer host"}) opts.append({'name': 'lb_port', 'help': 'Load-balancer port'}) opts.append({'name': 'lb_agent_port', 'help': 'Load-balancer agent host'}) opts.append({'name': 'broker_host', 'help': "Redis host"}) opts.append({'name': 'broker_port', 'help': 'Redis port'}) opts.append({ 'name': 'cluster_name', 'help': 'Name of the cluster to create' }) opts += get_tech_account_opts('for web admin instances to use') def execute(self, args, show_output=True): engine = self._get_engine(args) session = self._get_session(engine) cluster = Cluster() cluster.name = args.cluster_name cluster.description = 'Created by {} on {} (UTC)'.format( self._get_user_host(), datetime.utcnow().isoformat()) for name in ('odb_type', 'odb_host', 'odb_port', 'odb_user', 'odb_db_name', 'broker_host', 'broker_port', 'lb_host', 'lb_port', 'lb_agent_port'): setattr(cluster, name, getattr(args, name)) session.add(cluster) # TODO: getattrs below should be squared away - one of the attrs should win # and the other one should be get ridden of. admin_invoke_sec = HTTPBasicAuth( None, 'admin.invoke', True, 'admin.invoke', 'Zato admin invoke', getattr(args, 'admin_invoke_password', None) or getattr(args, 'tech_account_password'), cluster) session.add(admin_invoke_sec) pubapi_sec = HTTPBasicAuth(None, 'pubapi', True, 'pubapi', 'Zato public API', uuid4().hex, cluster) session.add(pubapi_sec) internal_invoke_sec = HTTPBasicAuth(None, 'zato.internal.invoke', True, 'zato.internal.invoke.user', 'Zato internal invoker', uuid4().hex, cluster) session.add(internal_invoke_sec) live_browser_sec = JWT(None, msg_browser_defaults.CHANNEL, True, msg_browser_defaults.USER, uuid4().hex, msg_browser_defaults.TOKEN_TTL, cluster) session.add(live_browser_sec) self.add_internal_services(session, cluster, admin_invoke_sec, pubapi_sec, internal_invoke_sec, live_browser_sec) self.add_ping_services(session, cluster) self.add_default_pubsub_accounts(session, cluster) self.add_default_rbac_permissions(session, cluster) self.add_default_rbac_roles(session, cluster) try: session.commit() except IntegrityError, e: msg = 'Cluster name [{}] already exists'.format(cluster.name) if self.verbose: msg += '. Caught an exception:[{}]'.format( format_exc(e).decode('utf-8')) self.logger.error(msg) self.logger.error(msg) session.rollback() return self.SYS_ERROR.CLUSTER_NAME_ALREADY_EXISTS if show_output: if self.verbose: msg = 'Successfully created a new cluster [{}]'.format( args.cluster_name) self.logger.debug(msg) else: self.logger.info('OK')
class Create(ZatoCommand): """ Creates a new web admin web console """ needs_empty_dir = True allow_empty_secrets = True opts = deepcopy(common_odb_opts) opts.append({ 'name': 'pub_key_path', 'help': "Path to the web admin's public key in PEM" }) opts.append({ 'name': 'priv_key_path', 'help': "Path to the web admin's private key in PEM" }) opts.append({ 'name': 'cert_path', 'help': "Path to the web admin's certificate in PEM" }) opts.append({ 'name': 'ca_certs_path', 'help': "Path to a bundle of CA certificates to be trusted" }) opts += get_tech_account_opts() def __init__(self, args): self.target_dir = os.path.abspath(args.path) super(Create, self).__init__(args) def execute(self, args, show_output=True, password=None, needs_admin_created_flag=False): os.chdir(self.target_dir) repo_dir = os.path.join(self.target_dir, 'config', 'repo') web_admin_conf_path = os.path.join(repo_dir, 'web-admin.conf') initial_data_json_path = os.path.join(repo_dir, 'initial-data.json') os.mkdir(os.path.join(self.target_dir, 'logs')) os.mkdir(os.path.join(self.target_dir, 'config')) os.mkdir(repo_dir) user_name = 'admin' password = password if password else generate_password() self.copy_web_admin_crypto(repo_dir, args) priv_key = open(os.path.join(repo_dir, 'web-admin-priv-key.pem')).read() config = { 'host': web_admin_host, 'port': web_admin_port, 'db_type': args.odb_type, 'log_config': 'logging.conf', 'DATABASE_NAME': args.odb_db_name or args.sqlite_path, 'DATABASE_USER': args.odb_user or '', 'DATABASE_PASSWORD': encrypt(args.odb_password, priv_key) if args.odb_password else '', 'DATABASE_HOST': args.odb_host or '', 'DATABASE_PORT': args.odb_port or '', 'SITE_ID': getrandbits(20), 'SECRET_KEY': encrypt(uuid.uuid4().hex, priv_key), 'ADMIN_INVOKE_NAME': 'admin.invoke', 'ADMIN_INVOKE_PASSWORD': encrypt( getattr(args, 'admin_invoke_password', None) or getattr(args, 'tech_account_password'), priv_key), } open(os.path.join(repo_dir, 'logging.conf'), 'w').write( common_logging_conf_contents.format( log_path='./logs/web-admin.log')) open(web_admin_conf_path, 'w').write(config_template.format(**config)) open(initial_data_json_path, 'w').write(initial_data_json.format(**config)) # Initial info self.store_initial_info(self.target_dir, self.COMPONENTS.WEB_ADMIN.code) config = json.loads( open(os.path.join(repo_dir, 'web-admin.conf')).read()) config['config_dir'] = self.target_dir update_globals(config, self.target_dir) os.environ['DJANGO_SETTINGS_MODULE'] = 'zato.admin.settings' import django django.setup() self.reset_logger(args, True) # Can't import these without DJANGO_SETTINGS_MODULE being set from django.contrib.auth.models import User from django.db import connection from django.db.utils import IntegrityError call_command('migrate', run_syncdb=True, interactive=False, verbosity=0) call_command('loaddata', initial_data_json_path, verbosity=0) try: call_command('createsuperuser', interactive=False, username=user_name, first_name='admin-first-name', last_name='admin-last-name', email='*****@*****.**') admin_created = True user = User.objects.get(username=user_name) user.set_password(password) user.save() except IntegrityError, e: admin_created = False connection._rollback() self.logger.info('Ignoring IntegrityError e:[%s]', format_exc(e).decode('utf-8')) # Needed because Django took over our logging config self.reset_logger(args, True) if show_output: if self.verbose: msg = """Successfully created a web admin instance. You can start it with the 'zato start {path}' command.""".format( path=os.path.abspath( os.path.join(os.getcwd(), self.target_dir))) self.logger.debug(msg) else: self.logger.info('OK') # We return it only when told to explicitly so when the command runs from CLI # it doesn't return a non-zero exit code. if needs_admin_created_flag: return admin_created
class Create(ZatoCommand): """ Creates a new web admin web console """ needs_empty_dir = True allow_empty_secrets = True opts = deepcopy(common_odb_opts) opts.append({'name':'--pub_key_path', 'help':"Path to the web admin's public key in PEM"}) opts.append({'name':'--priv_key_path', 'help':"Path to the web admin's private key in PEM"}) opts.append({'name':'--cert_path', 'help':"Path to the web admin's certificate in PEM"}) opts.append({'name':'--ca_certs_path', 'help':"Path to a bundle of CA certificates to be trusted"}) opts += get_tech_account_opts() def __init__(self, args): self.target_dir = os.path.abspath(args.path) super(Create, self).__init__(args) def execute(self, args, show_output=True, admin_password=None, needs_admin_created_flag=False): os.chdir(self.target_dir) repo_dir = os.path.join(self.target_dir, 'config', 'repo') web_admin_conf_path = os.path.join(repo_dir, 'web-admin.conf') initial_data_json_path = os.path.join(repo_dir, 'initial-data.json') os.mkdir(os.path.join(self.target_dir, 'logs')) os.mkdir(os.path.join(self.target_dir, 'config')) os.mkdir(repo_dir) user_name = 'admin' admin_password = admin_password if admin_password else WebAdminCryptoManager.generate_password() self.copy_web_admin_crypto(repo_dir, args) zato_secret_key = WebAdminCryptoManager.generate_key() cm = WebAdminCryptoManager.from_secret_key(zato_secret_key) django_secret_key = uuid4().hex.encode('utf8') django_site_id = getrandbits(20) admin_invoke_password = getattr(args, 'admin_invoke_password', None) or getattr(args, 'tech_account_password') admin_invoke_password = admin_invoke_password.encode('utf8') odb_password = args.odb_password or '' odb_password = odb_password.encode('utf8') # If we have a CA's certificate then it implicitly means that there is some CA # which tells us that we are to trust both the CA and the certificates that it issues, # and the only certificate we are interested in is the one to the load-balancer. # This is why, if we get ca_certs_path, it must be because we are to use TLS # in communication with the load-balancer's agent. lb_agent_use_tls = bool(args.get('ca_certs_path')) config = { 'host': web_admin_host, 'port': web_admin_port, 'db_type': args.odb_type, 'log_config': 'logging.conf', 'lb_agent_use_tls': 'true' if lb_agent_use_tls else 'false', 'zato_secret_key':zato_secret_key, 'well_known_data': cm.encrypt(well_known_data.encode('utf8')), 'DATABASE_NAME': args.odb_db_name or args.sqlite_path, 'DATABASE_USER': args.odb_user or '', 'DATABASE_PASSWORD': cm.encrypt(odb_password), 'DATABASE_HOST': args.odb_host or '', 'DATABASE_PORT': args.odb_port or '', 'SITE_ID': django_site_id, 'SECRET_KEY': cm.encrypt(django_secret_key), 'ADMIN_INVOKE_NAME':'admin.invoke', 'ADMIN_INVOKE_PASSWORD':cm.encrypt(admin_invoke_password), } for name in 'zato_secret_key', 'well_known_data', 'DATABASE_PASSWORD', 'SECRET_KEY', 'ADMIN_INVOKE_PASSWORD': config[name] = config[name].decode('utf8') open(os.path.join(repo_dir, 'logging.conf'), 'w').write( common_logging_conf_contents.format(log_path='./logs/web-admin.log')) open(web_admin_conf_path, 'w').write(config_template.format(**config)) open(initial_data_json_path, 'w').write(initial_data_json.format(**config)) # Initial info self.store_initial_info(self.target_dir, self.COMPONENTS.WEB_ADMIN.code) config = json.loads(open(os.path.join(repo_dir, 'web-admin.conf')).read()) config['config_dir'] = self.target_dir update_globals(config, self.target_dir) os.environ['DJANGO_SETTINGS_MODULE'] = 'zato.admin.settings' import django django.setup() self.reset_logger(args, True) # Can't import these without DJANGO_SETTINGS_MODULE being set from django.contrib.auth.models import User from django.db import connection from django.db.utils import IntegrityError call_command('migrate', run_syncdb=True, interactive=False, verbosity=0) call_command('loaddata', initial_data_json_path, verbosity=0) try: call_command( 'createsuperuser', interactive=False, username=user_name, first_name='admin-first-name', last_name='admin-last-name', email='*****@*****.**') admin_created = True user = User.objects.get(username=user_name) user.set_password(admin_password) user.save() except IntegrityError: # This will happen if user 'admin' already exists, e.g. if this is not the first cluster in this database admin_created = False connection._rollback() # Needed because Django took over our logging config self.reset_logger(args, True) if show_output: if self.verbose: msg = """Successfully created a web admin instance. You can start it with the 'zato start {path}' command.""".format(path=os.path.abspath(os.path.join(os.getcwd(), self.target_dir))) self.logger.debug(msg) else: self.logger.info('OK') # We return it only when told to explicitly so when the command runs from CLI # it doesn't return a non-zero exit code. if needs_admin_created_flag: return admin_created