QUERY_LIMIT = 100 else: QUERY_LIMIT = args.query_limit # ############## MAIN ROUTINE # Connect to the API using our provided falcon client_id and client_secret try: falcon = APIHarness(client_id=falcon_client_id, client_secret=falcon_client_secret, base_url=CLOUD_URL) except Exception as err: # noqa: E722 pylint: disable=W0703 # We can't communicate with the endpoint print(f'Unable to communicate with API {str(err)}') # Authenticate if falcon.authenticate(): try: # Execute the command by calling the named function if command.lower() == "check": check_account() if command.lower() == "update": update_account() if command.lower() == "register": register_account() if command.lower() == "delete": delete_account() if command.lower() == "get": get_account() except Exception as err: # pylint: disable=W0703 # Handle any previously unhandled errors print(f"Command failed with error: {str(err)}.")
class TestAuthorization(): def getConfigObject(self): status = self.getConfig() if status: os.environ["FALCONPY_DEBUG_CLIENT_ID"] = self.config[ "falcon_client_id"] os.environ["FALCONPY_DEBUG_CLIENT_SECRET"] = self.config[ "falcon_client_secret"] self.authorization = OAuth2( creds={ "client_id": self.config["falcon_client_id"], "client_secret": self.config["falcon_client_secret"] }, base_url=self.config["falcon_base_url"]) try: global shared_token if not shared_token: shared_token = self.authorization.token( )['body']['access_token'] except KeyError: shared_token = False return self.authorization def getConfigExtended(self): if "FALCONPY_DEBUG_TOKEN" in os.environ: self.token = os.getenv("FALCONPY_DEBUG_TOKEN") self.config = {} self.config["falcon_client_id"] = os.environ[ "FALCONPY_DEBUG_CLIENT_ID"] self.config["falcon_client_secret"] = os.environ[ "FALCONPY_DEBUG_CLIENT_SECRET"] if "DEBUG_API_BASE_URL" in os.environ: self.config["falcon_base_url"] = os.getenv( "DEBUG_API_BASE_URL") else: self.config["falcon_base_url"] = "https://api.crowdstrike.com" else: status = self.getConfig() if status: os.environ["FALCONPY_DEBUG_CLIENT_ID"] = self.config[ "falcon_client_id"] os.environ["FALCONPY_DEBUG_CLIENT_SECRET"] = self.config[ "falcon_client_secret"] self.authorization = OAuth2( creds={ "client_id": self.config["falcon_client_id"], "client_secret": self.config["falcon_client_secret"] }, base_url=self.config["falcon_base_url"]) try: self.token = self.authorization.token()['body']['access_token'] os.environ["FALCONPY_DEBUG_TOKEN"] = self.token except KeyError: self.token = False return self.token def clear_env_token(self): if "FALCONPY_DEBUG_TOKEN" in os.environ: os.environ["FALCONPY_DEBUG_TOKEN"] = "" os.environ["FALCONPY_DEBUG_CLIENT_ID"] = "" os.environ["FALCONPY_DEBUG_CLIENT_SECRET"] = "" return True def getConfig(self): # Grab our config parameters if "DEBUG_API_ID" in os.environ and "DEBUG_API_SECRET" in os.environ: self.config = {} self.config["falcon_client_id"] = os.getenv("DEBUG_API_ID") self.config["falcon_client_secret"] = os.getenv("DEBUG_API_SECRET") if "DEBUG_API_BASE_URL" in os.environ: self.config["falcon_base_url"] = os.getenv( "DEBUG_API_BASE_URL") else: self.config["falcon_base_url"] = "auto" return True else: cur_path = os.path.dirname(os.path.abspath(__file__)) if os.path.exists('%s/test.config' % cur_path): with open('%s/test.config' % cur_path, 'r') as file_config: self.config = json.loads(file_config.read()) return True else: return False def uberAuth(self): status = self.getConfig() if status: self.falcon = APIHarness(creds={ "client_id": self.config["falcon_client_id"], "client_secret": self.config["falcon_client_secret"], }, base_url=self.config["falcon_base_url"]) self.falcon.authenticate() if self.falcon.authenticated: return True else: if self.falcon.base_url == "https://api.laggar.gcw.crowdstrike.com": pytest.skip("GovCloud rate limit hit") else: return False else: return False def failUberMSSPAuth(self): status = self.getConfig() if status: self.falcon = APIHarness( client_id=self.config["falcon_client_id"], client_secret=self.config["falcon_client_secret"], member_cid="1234567890ABCDEFG") self.falcon.authenticate() if not self.falcon.authenticated: return True else: return False else: return False def uberRevoke(self): return self.falcon.deauthenticate() def serviceAuth(self): status = self.getConfig() if status: self.authorization = OAuth2( creds={ 'client_id': self.config["falcon_client_id"], 'client_secret': self.config["falcon_client_secret"] }, base_url=self.config["falcon_base_url"]) try: check = self.authorization.token() if check["status_code"] == 429: pytest.skip("Rate limit hit") self.token = check['body']['access_token'] # Force a token authentication _ = Hosts(access_token=self.token) except KeyError: self.token = False if self.token: return True else: return False else: return False def serviceAuthNoSSL(self): status = self.getConfig() if status: self.authorization = Hosts(creds={ 'client_id': self.config["falcon_client_id"], 'client_secret': self.config["falcon_client_secret"] }, ssl_verify=False, base_url=self.config["falcon_base_url"]) check = self.authorization.auth_object.token() if check["status_code"] == 429: pytest.skip("Rate limit hit") if check["body"]["access_token"]: self.authorization.auth_object.revoke( check["body"]["access_token"]) return True else: return False else: return False def serviceMSSPAuth(self): status = self.getConfig() result = False if status: authorization = OAuth2( client_id=self.config["falcon_client_id"], client_secret=self.config["falcon_client_secret"], member_cid='1234567890ABCDEFG') try: req = authorization.token() if req["status_code"] in [ 201, 403 ]: # Prolly an invalid MSSP cred, 403 is correct result = True except KeyError: pass return result def failServiceAuth(self): self.authorization = Hosts(client_id="BadClientID", client_secret="BadClientSecret", member_cid="123456789ABCDEFG", base_url="us3") # self.authorization.auth_object.base_url = "nowhere" try: self.token = self.authorization.auth_object.token( )['body']['access_token'] except KeyError: self.token = False self.authorization.auth_object.revoke(self.token) if self.token: return False else: return True def serviceRevoke(self): try: result = self.authorization.revoke(token=self.token)["status_code"] if result > 0: return True else: return False except KeyError: return False def credential_logout(self, api: object = None): if api: return bool( api.auth_object.revoke(api.auth_object.token( )["body"]["access_token"])["status_code"] in [200, 201]) else: return False def test_uberAuth(self): assert self.uberAuth() is True self.uberRevoke() def test_uberRevoke(self): self.uberAuth() assert self.uberRevoke() is True def test_serviceAuth(self): assert self.serviceAuth() is True self.serviceRevoke() # This test disables SSL and will generate a warning in pytest if we don't disable it @pytest.mark.filterwarnings( "ignore:Unverified HTTPS request is being made.*") def test_serviceAuthNoSSL(self): assert self.serviceAuthNoSSL() is True def test_serviceMSSPAuth(self): assert self.serviceMSSPAuth() is True def test_uberMSSPAuthFailure(self): assert self.failUberMSSPAuth() is True def test_serviceRevoke(self): self.serviceAuth() assert self.serviceRevoke() is True def test_failServiceAuth(self): assert self.failServiceAuth() is True @pytest.mark.skipif(os.getenv("DEBUG_API_BASE_URL", "us1").lower() in [ "https://api.laggar.gcw.crowdstrike.com", "usgov1" ], reason="Unit testing unavailable on US-GOV-1") def test_base_url_lookup(self): _ = self.getConfig() test_falcon = OAuth2(client_id=self.config["falcon_client_id"], client_secret=self.config["falcon_client_secret"], base_url="us1") assert bool(test_falcon.token()["status_code"] == 201) def test_fail_base_url_lookup(self): _ = self.getConfig() test_falcon = OAuth2(client_id=self.config["falcon_client_id"], client_secret=self.config["falcon_client_secret"], base_url="nowhere") assert bool(test_falcon.token()["status_code"] != 201)
try: VERIFY_SSL_CONNECTIONS = config["ssl_verify"] if VERIFY_SSL_CONNECTIONS == "": VERIFY_SSL_CONNECTIONS = True except KeyError: VERIFY_SSL_CONNECTIONS = True config["ssl_verify"] = VERIFY_SSL_CONNECTIONS # Connect to the API falcon = APIHarness(client_id=config["falcon_client_id"], client_secret=config["falcon_client_secret"], base_url=BASE_URL, ssl_verify=VERIFY_SSL_CONNECTIONS) # Authenticate to the API falcon.authenticate() # Cry about our bad keys if not falcon.authenticated: status.status_write( f"Failed to connect to the API on {BASE_URL}. Check base_url and ssl_verify configuration settings." ) raise SystemExit( f"Failed to connect to the API on {BASE_URL}. Check base_url and ssl_verify configuration settings." ) # Retrieve our current CID (MSSP functionality) or add it to config? # This method requires Sensor Install API, our fallback option uses the Hosts API but a device must exist try: current_cid = falcon.command( "GetSensorInstallersCCIDByQuery")["body"]["resources"][0][:-3] except KeyError: