def decorated(*args, **kwargs): # First check that the source of the request is actually valid local_gw = ['127.0.0.1'] gw_names = [ gw for gw in config.config['gateways'] if isinstance(config.config['gateways'][gw], dict) ] gw_ips = [get_ip(gw_name) for gw_name in gw_names] + \ local_gw + settings.config.trusted_ip_list if request.remote_addr not in gw_ips: return jsonify(message="API access not available to " "{}".format(request.remote_addr)), 403 # check credentials supplied in the http request are valid auth = request.authorization if not auth: return jsonify(message="Missing credentials"), 401 if (auth.username != settings.config.api_user or auth.password != settings.config.api_password): return jsonify(message="username/password mismatch with the " "configuration file"), 401 return f(*args, **kwargs)
def is_cleanup_host(config): """ decide which gateway host should be responsible for any non-specific updates to the config object :param config: configuration dict from the rados pool :return: boolean indicating whether the addition cleanup should be performed by the running host """ cleanup = False if 'ip_list' in config.config["gateways"]: gw_1 = config.config["gateways"]["ip_list"][0] usable_ip = get_ip(gw_1) if usable_ip != '0.0.0.0': if usable_ip in ipv4_addresses(): cleanup = True return cleanup
def valid_gateway(gw_name, gw_ip, config): """ validate the request for a new gateway :param gw_name: (str) host (shortname) of the gateway :param gw_ip: (str) ipv4 address on the gw that will be used for iSCSI :param config: (dict) current config :return: (str) "ok" or error description """ http_mode = 'https' if settings.config.api_secure else "http" # if the gateway request already exists in the config, computer says "no" if gw_name in config['gateways']: return "Gateway name {} already defined".format(gw_name) if gw_ip in config['gateways'].get('ip_list', []): return "IP address already defined to the configuration" # validate the gateway name is resolvable if get_ip(gw_name) == '0.0.0.0': return ("Gateway '{}' is not resolvable to an ipv4" " address".format(gw_name)) # validate the ip_address is valid ipv4 if get_ip(gw_ip) == '0.0.0.0': return ("IP address provided is not usable (name doesn't" " resolve, or not a valid ipv4 address)") # At this point the request seems reasonable, so lets check a bit deeper gw_api = '{}://{}:{}/api'.format(http_mode, gw_name, settings.config.api_port) # check the intended host actually has the requested IP available api = APIRequest(gw_api + '/sysinfo/ipv4_addresses') api.get() if api.response.status_code != 200: return ("ipv4_addresses query to {} failed - check " "rbd-target-api log. Is the API server " "running and in the right mode (http/https)?".format(gw_name)) try: target_ips = api.response.json()['data'] except: return "Malformed REST API response" if gw_ip not in target_ips: return ("IP address of {} is not available on {}. Valid " "IPs are :{}".format(gw_ip, gw_name, ','.join(target_ips))) # check that config file on the new gateway matches the local machine api = APIRequest(gw_api + '/sysinfo/checkconf') api.get() if api.response.status_code != 200: return ("checkconf API call to {} failed with " "code".format(gw_name, api.response.status_code)) # compare the hash of the new gateways conf file with the local one local_hash = gen_file_hash('/etc/ceph/iscsi-gateway.cfg') try: remote_hash = str(api.response.json()['data']) except: remote_hash = None if local_hash != remote_hash: return ("/etc/ceph/iscsi-gateway.cfg on {} does " "not match the local version. Correct and " "retry request".format(gw_name)) # Check for package version dependencies api = APIRequest(gw_api + '/sysinfo/checkversions') api.get() if api.response.status_code != 200: try: errors = api.response.json()['data'] except: return "Malformed REST API response" return ("{} failed package validation checks - " "{}".format(gw_name, ','.join(errors))) # At this point the gateway seems valid return "ok"