def is_cluster_isolated(self, cluster_name): """.""" # check for the presence of the firewall section firewall_section_name = \ self._get_firewall_section_name_for_cluster(cluster_name) dfw_manager = DFWManager(self._nsxt_client) firewall_section = dfw_manager.get_firewall_section( name=firewall_section_name) if not firewall_section: return False rules = dfw_manager.get_all_rules_in_section( section_id=firewall_section['id']) # Check for presence of the isolation DFW rules. # The checks are overly rigid, because we don't want any tampering with # the network isolation rules created by CSE on NSX-T. If the number of # rules are changed in future, this piece of logic should be updated # accordingly. if len(rules) != 2: return False found_rule_names = {rules[0]['display_name'], rules[1]['display_name']} if self.RULE2_NAME not in found_rule_names or \ self.RULE3_NAME not in found_rule_names: return False return True
def _create_ncp_boundary_firewall_section( nsxt_client, anchor_id, firewall_section_name, tag_value): dfw_manager = DFWManager(nsxt_client) section = dfw_manager.get_firewall_section(name=firewall_section_name) if not section: tag = {} tag['scope'] = "ncp/fw_sect_marker" tag['tag'] = tag_value tags = [tag] nsxt_client.LOGGER.debug( f"Creating DFW section : {firewall_section_name}") section = dfw_manager.create_firewall_section( name=firewall_section_name, tags=tags, anchor_id=anchor_id, insert_policy=INSERT_POLICY.INSERT_BEFORE) else: nsxt_client.LOGGER.debug(f"DFW section : {firewall_section_name} " "already exists.") return section
def setup_nsxt_constructs(nsxt_client, nodes_ip_block_id, pods_ip_block_id, ncp_boundary_firewall_section_anchor_id): """Set up one time NSX-T construct which will aid in network isolation. :param list nodes_ip_block_id: list of strings, where each entry represents id of a non routable ip block from which ip of cluster nodes will be assigned. :param list pods_ip_block_id: list of strings, where each entry represents id of a non routable ip block from which ip of cluster pods will be assigned. :param str ncp_boundary_firewall_section_anchor_id: id of the firewal section which will act as anchor for the NCP fw_sector/top firewall section. """ _create_ipset_for_node_pod_ip_blocks(nsxt_client, nodes_ip_block_id, pods_ip_block_id) _create_all_nodes_pods_nsgroup(nsxt_client) dfw_manager = DFWManager(nsxt_client) dfw_manager.delete_firewall_section( name=NCP_BOUNDARY_FIREWALL_SECTION_NAME) _create_ncp_boundary_firewall_section( nsxt_client, ncp_boundary_firewall_section_anchor_id, NCP_BOUNDARY_TOP_FIREWALL_SECTION_NAME, "top") _create_ncp_boundary_firewall_section( nsxt_client, ncp_boundary_firewall_section_anchor_id, NCP_BOUNDARY_BOTTOM_FIREWALL_SECTION_NAME, "bottom")
def _create_firewall_rules_for_cluster(self, section_id, nodes_nsgroup_id, pods_nsgroup_id, nodes_pods_nsgroup_id, all_nodes_pods_nsgroup_id): """Create DFW Rules to isolate a cluster network. One rule to limit communication from pods to nodes. One rule to allow other form of communication between nodes and pods. One rule to isolate the nodes and pods of this cluster from other clusters. :param str section_id: id of the DFW Section where these rules will be added. :param str nodes_nsgroup_id: :param str pods_nsgroup_id: :param str nodes_pods_nsgroup_id: :param str all_nodes_pods_nsgroup_id: """ dfw_manager = DFWManager(self._nsxt_client) # self._nsxt_client.LOGGER.debug( # f"Creating DFW rule : {self.RULE1_NAME}") # rule1 = dfw_manager.create_dfw_rule( # section_id=section_id, # rule_name=self.RULE1_NAME, # source_nsgroup_id=pods_nsgroup_id, # dest_nsgroup_id=nodes_nsgroup_id, # action=FIREWALL_ACTION.DROP) self._nsxt_client.LOGGER.debug( f"Creating DFW rule : {self.RULE2_NAME}") rule2 = dfw_manager.create_dfw_rule( section_id=section_id, rule_name=self.RULE2_NAME, source_nsgroup_id=nodes_pods_nsgroup_id, dest_nsgroup_id=nodes_pods_nsgroup_id, action=FIREWALL_ACTION.ALLOW, # anchor_rule_id=rule1['id'], # insert_policy=INSERT_POLICY.INSERT_AFTER ) self._nsxt_client.LOGGER.debug( f"Creating DFW rule : {self.RULE3_NAME}") dfw_manager.create_dfw_rule(section_id=section_id, rule_name=self.RULE3_NAME, source_nsgroup_id=nodes_pods_nsgroup_id, dest_nsgroup_id=all_nodes_pods_nsgroup_id, action=FIREWALL_ACTION.DROP, anchor_rule_id=rule2['id'], insert_policy=INSERT_POLICY.INSERT_AFTER)
def remove_cluster_isolation(self, cluster_name): """Revert isolation of a PKS cluster's network. :param str cluster_name: name of the cluster whose network isolation needs to be reverted. """ firewall_section_name = \ self._get_firewall_section_name_for_cluster(cluster_name) nodes_nsgroup_name = self._get_nodes_nsgroup_name(cluster_name) pods_nsgroup_name = self._get_pods_nsgroup_name(cluster_name) nodes_pods_nsgroup_name = \ self._get_nodes_pods_nsgroup_name(cluster_name) dfw_manager = DFWManager(self._nsxt_client) nsgroup_manager = NSGroupManager(self._nsxt_client) dfw_manager.delete_firewall_section(firewall_section_name, cascade=True) nsgroup_manager.delete_nsgroup(nodes_pods_nsgroup_name, force=True) nsgroup_manager.delete_nsgroup(nodes_nsgroup_name, force=True) nsgroup_manager.delete_nsgroup(pods_nsgroup_name, force=True)
def _create_firewall_section_for_cluster(self, cluster_name, applied_to_nsgroup_id): """Create DFW Section for the cluster. If DFW Section already exists, delete it and re-create it. Since this section is based on cluster name, it possible that a previously deployed cluster on deletion failed to cleanup properly. We shouldn't re-use such a section rather create it afresh with new rules pointing to the correct NSGroups. :param str cluster_name: name of the cluster whose network is being isolated. :param str applied_to_nsgroup_id: id of the NSGroup on which the rules in this DFW Section will apply to. """ section_name = self._get_firewall_section_name_for_cluster( cluster_name) dfw_manager = DFWManager(self._nsxt_client) section = dfw_manager.get_firewall_section(section_name) if section: self._nsxt_client.LOGGER.debug(f"DFW section : {section_name} " "already exists.") dfw_manager.delete_firewall_section(section_name, cascade=True) self._nsxt_client.LOGGER.debug("Deleted DFW section : " f"{section_name} ") target = {} target['target_type'] = "NSGroup" target['target_id'] = applied_to_nsgroup_id anchor_section = dfw_manager.get_firewall_section( NCP_BOUNDARY_BOTTOM_FIREWALL_SECTION_NAME) self._nsxt_client.LOGGER.debug("Creating DFW section : " f"{section_name}") section = dfw_manager.create_firewall_section( name=section_name, applied_tos=[target], anchor_id=anchor_section['id'], insert_policy=INSERT_POLICY.INSERT_AFTER) return section
def _validate_pks_config_data_integrity( pks_config, msg_update_callback=NullPrinter(), logger_debug=NULL_LOGGER, logger_wire=NULL_LOGGER ): all_pks_servers = \ [entry['name'] for entry in pks_config[PKS_SERVERS_SECTION_KEY]] all_pks_accounts = \ [entry['name'] for entry in pks_config[PKS_ACCOUNTS_SECTION_KEY]] # Create a cache with pks_account to Credentials mapping pks_account_info_table = {} for pks_account in pks_config[PKS_ACCOUNTS_SECTION_KEY]: pks_account_name = pks_account['pks_api_server'] credentials = Credentials( pks_account['username'], pks_account['secret'] ) pks_account_info_table[pks_account_name] = credentials # Check for duplicate pks api server names duplicate_pks_server_names = get_duplicate_items_in_list(all_pks_servers) if len(duplicate_pks_server_names) != 0: raise ValueError( f"Duplicate PKS api server(s) : {duplicate_pks_server_names} found" f" in Section : {PKS_SERVERS_SECTION_KEY}" ) # Check for duplicate pks account names duplicate_pks_account_names = get_duplicate_items_in_list(all_pks_accounts) if len(duplicate_pks_account_names) != 0: raise ValueError( f"Duplicate PKS account(s) : {duplicate_pks_account_names} found" f" in Section : {PKS_ACCOUNTS_SECTION_KEY}" ) # Check validity of all PKS api servers referenced in PKS accounts section for pks_account in pks_config[PKS_ACCOUNTS_SECTION_KEY]: pks_server_name = pks_account.get('pks_api_server') if pks_server_name not in all_pks_servers: raise ValueError( f"Unknown PKS api server : {pks_server_name} referenced by " f"PKS account : {pks_account.get('name')} in Section : " f"{PKS_ACCOUNTS_SECTION_KEY}" ) # Check validity of all PKS accounts referenced in Orgs section if PKS_ORGS_SECTION_KEY in pks_config.keys(): for org in pks_config[PKS_ORGS_SECTION_KEY]: referenced_accounts = org.get('pks_accounts') if not referenced_accounts: continue for account in referenced_accounts: if account not in all_pks_accounts: raise ValueError( f"Unknown PKS account : {account} " f"referenced by Org : {org.get('name')} " f"in Section : {PKS_ORGS_SECTION_KEY}" ) # Check validity of all PKS api servers referenced in PVDC section for pvdc in pks_config[PKS_PVDCS_SECTION_KEY]: pks_server_name = pvdc.get('pks_api_server') if pks_server_name not in all_pks_servers: raise ValueError( f"Unknown PKS api server : {pks_server_name} " f"referenced by PVDC : {pvdc.get('name')} in " f"Section : {PKS_PVDCS_SECTION_KEY}" ) # Check validity of all PKS api servers referenced in the pks_api_servers # section for pks_server in pks_config[PKS_SERVERS_SECTION_KEY]: pks_account = pks_account_info_table.get(pks_server.get('name')) pks_configuration = Configuration() pks_configuration.proxy = f"http://{pks_server['proxy']}:80" \ if pks_server.get('proxy') else None pks_configuration.host = \ f"https://{pks_server['host']}:{pks_server['port']}/" \ f"{VERSION_V1}" pks_configuration.access_token = None pks_configuration.username = pks_account.username pks_configuration.verify_ssl = pks_server['verify'] pks_configuration.secret = pks_account.secret pks_configuration.uaac_uri = \ f"https://{pks_server['host']}:{pks_server['uaac_port']}" uaa_client = UaaClient( pks_configuration.uaac_uri, pks_configuration.username, pks_configuration.secret, proxy_uri=pks_configuration.proxy ) token = uaa_client.getToken() if not token: raise ValueError( "Unable to connect to PKS server : " f"{pks_server.get('name')} ({pks_server.get('host')})" ) pks_configuration.token = token client = ApiClient(configuration=pks_configuration) if client: msg_update_callback.general( "Connected to PKS server (" f"{pks_server.get('name')} : {pks_server.get('host')})" ) # Check validity of all PKS api servers referenced in NSX-T section for nsxt_server in pks_config[PKS_NSXT_SERVERS_SECTION_KEY]: pks_server_name = nsxt_server.get('pks_api_server') if pks_server_name not in all_pks_servers: raise ValueError( f"Unknown PKS api server : {pks_server_name} referenced by " f"NSX-T server : {nsxt_server.get('name')} in Section : " f"{PKS_NSXT_SERVERS_SECTION_KEY}" ) # Create a NSX-T client and verify connection # server nsxt_client = NSXTClient( host=nsxt_server.get('host'), username=nsxt_server.get('username'), password=nsxt_server.get('password'), logger_debug=logger_debug, logger_wire=logger_wire, http_proxy=nsxt_server.get('proxy'), https_proxy=nsxt_server.get('proxy'), verify_ssl=nsxt_server.get('verify') ) if not nsxt_client.test_connectivity(): raise ValueError( "Unable to connect to NSX-T server : " f"{nsxt_server.get('name')} ({nsxt_server.get('host')})" ) msg_update_callback.general( f"Connected to NSX-T server ({nsxt_server.get('host')})" ) ipset_manager = IPSetManager(nsxt_client) if nsxt_server.get('nodes_ip_block_ids'): block_not_found = False ip_block_id = '' try: for ip_block_id in nsxt_server.get('nodes_ip_block_ids'): if not ipset_manager.get_ip_block_by_id(ip_block_id): block_not_found = True except HTTPError: block_not_found = True if block_not_found: raise ValueError( f"Unknown Node IP Block : {ip_block_id} referenced by " f"NSX-T server : {nsxt_server.get('name')}.") if nsxt_server.get('pods_ip_block_ids'): block_not_found = False ip_block_id = '' try: for ip_block_id in nsxt_server.get('pods_ip_block_ids'): if not ipset_manager.get_ip_block_by_id(ip_block_id): block_not_found = True except HTTPError: block_not_found = True if block_not_found: raise ValueError( f"Unknown Pod IP Block : {ip_block_id} referenced by " f"NSX-T server : {nsxt_server.get('name')}.") dfw_manager = DFWManager(nsxt_client) fw_section_id = \ nsxt_server.get('distributed_firewall_section_anchor_id') section = dfw_manager.get_firewall_section(id=fw_section_id) if not section: raise ValueError( f"Unknown Firewall section : {fw_section_id} referenced by " f"NSX-T server : {nsxt_server.get('name')}.")