def test_rmq_case_web_vc_with_agents(monkeypatch): with create_vcfg_vhome() as vhome: monkeypatch.setenv("VOLTTRON_HOME", vhome) monkeypatch.setenv("RABBITMQ_CONF_ENV_FILE", "") config_path = os.path.join(vhome, "config") message_bus = "rmq" instance_name = "test_rmq" vip_address = "tcp://127.0.0.15" vip_port = "22916" is_web_enabled = "Y" web_port = "8443" is_vc = "Y" is_vcp = "Y" install_historian = "Y" install_driver = "Y" install_fake_device = "Y" install_listener = "Y" agent_autostart = "N" create_rmq_volttron_setup(vhome=vhome, env=os.environ, ssl_auth=True, instance_name=instance_name) vcfg_args = "\n".join([ message_bus, vip_address, vip_port, instance_name, is_web_enabled, web_port, is_vc, agent_autostart, is_vcp, agent_autostart, install_historian, agent_autostart, install_driver, install_fake_device, agent_autostart, install_listener, agent_autostart ]) with subprocess.Popen(["vcfg", "--vhome", vhome], env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as vcfg: out, err = vcfg.communicate(vcfg_args) assert os.path.exists(config_path) config = ConfigParser() config.read(config_path) assert config.get('volttron', 'message-bus') == "rmq" assert config.get('volttron', 'vip-address') == "tcp://127.0.0.15:22916" assert config.get('volttron', 'instance-name').strip('"') == "test_rmq" assert config.get('volttron', 'volttron-central-address') == "{}{}{}".format( "https://", get_hostname(), ":8443") assert config.get('volttron', 'bind-web-address') == "{}{}{}".format( "https://", get_hostname(), ":8443") assert _is_agent_installed("listener") assert _is_agent_installed("platform_driver") assert _is_agent_installed("platform_historian") assert _is_agent_installed("vc ") assert _is_agent_installed("vcp") assert not is_volttron_running(vhome)
def test_zmq_case_web_no_agents(monkeypatch): with create_vcfg_vhome() as vhome: monkeypatch.setenv("VOLTTRON_HOME", vhome) config_path = os.path.join(vhome, "config") message_bus = "zmq" vip_address = "tcp://127.0.0.15" vip_port = "22916" instance_name = "test_zmq" is_web_enabled = "Y" web_protocol = "https" web_port = "8443" gen_web_cert = "Y" new_root_ca = "Y" ca_country = "US" ca_state = "test-state" ca_location = "test-location" ca_organization = "test-org" ca_org_unit = "test-org-unit" is_vc = "N" is_vcp = "N" install_historian = "N" install_driver = "N" install_listener = "N" vcfg_args = "\n".join([ message_bus, vip_address, vip_port, instance_name, is_web_enabled, web_protocol, web_port, gen_web_cert, new_root_ca, ca_country, ca_state, ca_location, ca_organization, ca_org_unit, is_vc, is_vcp, install_historian, install_driver, install_listener ]) with subprocess.Popen(["vcfg", "--vhome", vhome], env=os.environ, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as vcfg: out, err = vcfg.communicate(vcfg_args) assert os.path.exists(config_path) config = ConfigParser() config.read(config_path) assert config.get('volttron', 'message-bus') == "zmq" assert config.get('volttron', 'vip-address') == "tcp://127.0.0.15:22916" assert config.get('volttron', 'instance-name').strip('"') == "test_zmq" assert config.get('volttron', 'bind-web-address') == "{}{}{}".format( "https://", get_hostname().lower(), ":8443") assert config.get('volttron', 'web-ssl-cert') == os.path.join( vhome, "certificates", "certs", "platform_web-server.crt") assert config.get('volttron', 'web-ssl-key') == os.path.join( vhome, "certificates", "private", "platform_web-server.pem") assert not _is_agent_installed("listener") assert not _is_agent_installed("platform_driver") assert not _is_agent_installed("platform_historian") assert not _is_agent_installed("vc ") assert not _is_agent_installed("vcp") assert not is_volttron_running(vhome)
def _create_certs(cfg_path, platform_cfg): print("Creating CA Certificate...") crts = certs.Certs() data = { "C": "US", "ST": "WA", "L": "Richmond", "O": "PNNL", "OU": "Volttron", "CN": f"{platform_cfg.get('instance-name')}-root-ca", } crts.create_root_ca(overwrite=False, **data) copy(crts.cert_file(crts.root_ca_name), crts.cert_file(crts.trusted_ca_name)) print("Creating new web server certificate.") print( "Creating and signing new certificate using the newly created CA certificate." ) name = f"{platform_cfg.get('instance-name')}-{PLATFORM_WEB}" crts.create_signed_cert_files( name=name + "-server", cert_type="server", ca_name=crts.root_ca_name, fqdn=get_hostname(), ) master_web_cert = os.path.join(VOLTTRON_HOME, "certificates/certs/", name + "-server.crt") master_web_key = os.path.join(VOLTTRON_HOME, "certificates/private/", name + "-server.pem") print("Writing ssl cert and key paths to config.") with open(os.path.join(cfg_path), "a") as fout: fout.write(f"web-ssl-cert = {master_web_cert}\n") fout.write(f"web-ssl-key = {master_web_key}\n")
def _create_web_certs(): global config_opts """ Utility to create web server certificates Designed to be used in conjecture with get_cert_and_key As such, it assumes that the program has already checked for existing certs, and prompted the user to enter in certificates that they have generated separately. """ crts = certs.Certs() try: crts.ca_cert() except certs.CertError: print("WARNING! CA certificate does not exist.") prompt_str = "Create new root CA?" prompt = prompt_response(prompt_str, valid_answers=y_or_n, default='Y') if prompt in y: cert_data = {} print( "\nPlease enter the following details for web server certificate:" ) prompt = '\tCountry:' cert_data['country'] = prompt_response(prompt, default='US') prompt = '\tState:' cert_data['state'] = prompt_response(prompt, mandatory=True) prompt = '\tLocation:' cert_data['location'] = prompt_response(prompt, mandatory=True) prompt = '\tOrganization:' cert_data['organization'] = prompt_response(prompt, mandatory=True) prompt = '\tOrganization Unit:' cert_data['organization-unit'] = prompt_response(prompt, mandatory=True) cert_data['common-name'] = get_platform_instance_name( ) + '-root-ca' data = { 'C': cert_data.get('country'), 'ST': cert_data.get('state'), 'L': cert_data.get('location'), 'O': cert_data.get('organization'), 'OU': cert_data.get('organization-unit'), 'CN': cert_data.get('common-name') } crts.create_root_ca(overwrite=False, **data) copy(crts.cert_file(crts.root_ca_name), crts.cert_file(crts.trusted_ca_name)) else: return 1 print("Creating new web server certificate.") crts.create_signed_cert_files(name=PLATFORM_WEB + "-server", cert_type='server', ca_name=crts.root_ca_name, fqdn=get_hostname()) return 0
def do_web_enabled_zmq(vhome): global config_opts # Full implies that it will have a port on it as well. Though if it's # not in the address that means that we haven't set it up before. full_bind_web_address = config_opts.get('bind-web-address', 'https://' + get_hostname()) parsed = urlparse(full_bind_web_address) address_only = full_bind_web_address port_only = None if parsed.port is not None: address_only = parsed.scheme + '://' + parsed.hostname port_only = parsed.port else: port_only = 8443 valid_address = False external_ip = None while not valid_address: prompt = 'What is the protocol for this instance?' new_scheme = prompt_response(prompt, default=parsed.scheme) new_external_ip = new_scheme + '://' + parsed.hostname valid_address = is_valid_url(new_external_ip, ['http', 'https']) if valid_address: external_ip = new_external_ip print("Web address set to: {}".format(external_ip)) valid_port = False vc_port = None while not valid_port: prompt = 'What is the port for this instance?' if new_scheme == 'http' and port_only == 8443: port_only = 8080 new_vc_port = prompt_response(prompt, default=port_only) valid_port = is_valid_port(new_vc_port) if valid_port: vc_port = new_vc_port while external_ip.endswith("/"): external_ip = external_ip[:-1] parsed = urlparse(external_ip) config_opts['bind-web-address'] = '{}:{}'.format(external_ip, vc_port) if config_opts['message-bus'] == 'zmq' and parsed.scheme == "https": get_cert_and_key(vhome)
def do_vcp(): global config_opts is_vc = False vctl_list_process = Popen(['vctl', 'list'], env=os.environ, stdout=subprocess.PIPE, stderr=subprocess.PIPE) vctl_list = vctl_list_process.communicate() vctl_list_output = ''.join([v.decode('utf-8') for v in vctl_list]) try: vc_address = config_opts['volttron-central-address'] no_vc_address = False except KeyError: no_vc_address = True try: if no_vc_address: vc_address = config_opts['bind-web-address'] if VOLTTRON_CENTRAL in vctl_list_output: is_vc = True except KeyError: vc_address = config_opts.get( 'volttron-central-address', config_opts.get('bind-web-address', 'https://' + get_hostname())) if not is_vc: parsed = urlparse(vc_address) address_only = vc_address port_only = None if parsed.port is not None: address_only = parsed.scheme + '://' + parsed.hostname port_only = parsed.port else: port_only = 8443 valid_vc = False while not valid_vc: prompt = "What is the hostname for volttron central?" new_vc_address = prompt_response(prompt, default=address_only) valid_vc = is_valid_url(new_vc_address, ['http', 'https']) if valid_vc: vc_address = new_vc_address vc_port = None while True: prompt = 'What is the port for volttron central?' new_vc_port = prompt_response(prompt, default=port_only) if is_valid_port(new_vc_port): vc_port = new_vc_port break new_address = '{}:{}'.format(vc_address, vc_port) else: new_address = vc_address print('Volttron central address set to {}'.format(new_address)) config_opts['volttron-central-address'] = new_address return {}