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 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 get_install_params(events, context): """Retrieve necessary installation detail from CrowdStrike cloud.""" api_base_url, api_client_id, api_client_secret = get_ssm_params(events) try: auth = OAuth2(client_id=api_client_id, client_secret=api_client_secret, base_url=api_base_url ) except Exception as err: raise ValueError(f"Failure while interacting with CrowdStrike backend. Error: {err}") from err try: print('Requesting Customer ID from CrowdStrike backend.') sensor = SensorDownload(auth_object=auth) get_ccid = sensor.get_sensor_installer_ccid() if get_ccid["status_code"] != 200: error_detail = get_ccid['body']['errors'][0] code = error_detail["code"] msg = error_detail["message"] raise ValueError(f"Received non success response {code}. Error: {msg}") customer_ccid = get_ccid['body']['resources'][0] print('Successfully received Customer ID.') except Exception as err: raise ValueError(f"Failure while interacting with CrowdStrike backend. Error {err}") from err try: hosts = Hosts(auth_object=auth) id_to_retrieve = events["InstanceIds"][0] host_aid = hosts.query_devices_by_filter(filter=f"instance_id:'{id_to_retrieve}'") skip_install = "NO" if host_aid["status_code"] == 200: if host_aid["body"]["resources"]: skip_install = "YES" print('Checked for a skipped install') return { 'CCID': customer_ccid, 'SkipInstall': skip_install } except Exception as err: raise ValueError(f"Failure while interacting with CrowdStrike backend. Error {err}") from err
def hide_falcon_instance(events, context): """Hide the host from the Falcon Console.""" try: api_base_url, api_client_id, api_client_secret = get_ssm_params(events) print("Hiding terminated instance in Falcon") hosts = Hosts(client_id=api_client_id, client_secret=api_client_secret, base_url=api_base_url ) for id_to_retrieve in events["InstanceIds"]: host_aid = hosts.query_devices_by_filter(filter=f"instance_id:'{id_to_retrieve}'") if host_aid["status_code"] != 200: returned = f"AWS instance: {id_to_retrieve} was not found in your Falcon tenant" if host_aid["body"]["resources"]: falcon_host_id = host_aid["body"]["resources"][0] hide_result = hosts.perform_action(action_name="hide_host", ids=falcon_host_id) if hide_result["status_code"] == 202: returned = ( f"AWS Instance: {id_to_retrieve} | Falcon Resource ID: {falcon_host_id} was " "successfully hidden" ) elif hide_result["status_code"] == 404: returned = ( f"AWS Instance: {id_to_retrieve} does not have a sensor installed." ) else: err_detail = hide_result["body"]["errors"][0] code = err_detail["code"] msg = err_detail["message"] raise ValueError(f"Received non success response {code} while attempting to hide host. Error: {msg}") else: returned = f"AWS instance: {id_to_retrieve} was not found in your Falcon tenant" return returned except Exception as err: raise ValueError(f"Failure while interacting with CrowdStrike backend. Error {err}") from err
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
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)
parser.add_argument( # CrowdStrike API Client ID '-k', '--key', help='Your CrowdStrike API key ID\n' ' Required Scopes\n' ' Hosts: READ\n' ' RTR: WRITE\n' ' RTR Admin: WRITE', required=True) parser.add_argument( # CrowdStrike API Client secret '-s', '--secret', help='Your CrowdStrike API key secret', required=True) args = parser.parse_args() # Retrieve our provided command line arguments hostname = args.target # Grab the hostname of our target from the user falcon_auth = OAuth2( # Create an instance of our authentication class client_id=args.key, # and authenticate to the API client_secret=args.secret, ) falcon_hosts = Hosts( auth_object=falcon_auth) # Connect to the Hosts API using our auth object falcon_rtr = RealTimeResponse( auth_object=falcon_auth) # Connect to the RTR API using our auth object falcon_rtra = RealTimeResponseAdmin( auth_object=falcon_auth ) # Connect to the RTR Admin API using our auth object if __name__ == "__main__": main()
import platform # Authentication via the test_authorization.py from tests import test_authorization as Authorization # Import our sibling src folder into the path sys.path.append(os.path.abspath('src')) # Classes to test - manually imported from sibling folder # flake8: noqa: E402 from falconpy import RealTimeResponse from falconpy import Hosts auth = Authorization.TestAuthorization() config = auth.getConfigObject() falcon = RealTimeResponse(auth_object=config) # Testing direct credential specification here - jshcodes 08.14.21 falcon_hosts = Hosts(client_id=auth.config["falcon_client_id"], client_secret=auth.config["falcon_client_secret"], base_url=auth.config["falcon_base_url"]) AllowedResponses = [200, 204, 400, 404, 429] # Adding rate-limiting as an allowed response for now class TestRTR: def rtr_list_all_sessions(self): if falcon.RTR_ListAllSessions( parameters={"limit": 1})["status_code"] in AllowedResponses: return True else: return False def rtr_session_tester(self): returned = False
"updated_on", "hostname", "local_ip", "os_version", "service_provider", "remediation" ] sort_type = args.sort.strip().lower() if sort_type in sort_types: SORT = sort_type SORT_REVERSE = args.reverse PROGRESS = args.show_progress # Connect to the API and create instances of the SpotlightVulnerabilities and Hosts Service Classes auth = OAuth2(client_id=args.client_id, client_secret=args.client_secret, base_url=BASE) spotlight = SpotlightVulnerabilities(auth_object=auth) hosts = Hosts(auth_object=auth) # Headers used for our results display HEADERS = { "cve": "CVE", "score": "Score", "severity": "Severity", "cve_description": "Description", "created_on": "Created", "updated_on": "Updated", "hostname": "Host", "local_ip": "IP Address", "os_version": "Operating System", "service_provider": "Service Provider", "remediation": "Remediation" }
HOSTNAME = "HOSTNAME_HERE" mssp = FlightControl(client_id=args.client_id, client_secret=args.client_secret, base_url=BASE) children = mssp.query_children() if children["status_code"] == 200: if children["body"]["resources"]: CIDS = children["body"]["resources"] AUTH = [] for cid in CIDS: AUTH.append( OAuth2(client_id=args.client_id, client_secret=args.client_secret, base_url=BASE, member_cid=cid)) for auth in AUTH: hosts = Hosts(auth_object=auth) lookup = hosts.query_devices_by_filter( filter=f"hostname:'{HOSTNAME}'") if lookup["body"]["resources"]: for host in lookup["body"]["resources"]: detail = hosts.get_device_details(ids=host) host_cid = detail["body"]["resources"][0]["cid"] print(f"Host identified on CID: {host_cid}") else: print("No children identified.") else: print("No children identified, check permissions.")
args = parse_command_line() if args.base_url: BASE = args.base_url else: BASE = "us1" if args.reverse: SORT = "hostname.desc" else: SORT = "hostname.asc" falcon = Hosts(client_id=args.client_id, client_secret=args.client_secret, base_url=BASE) OFFSET = 0 # Start at the beginning DISPLAYED = 0 # This is just so we can show a running count TOTAL = 1 # Assume there is at least one LIMIT = 500 # Quick limit to prove pagination while OFFSET < TOTAL: OFFSET, TOTAL, devices = device_list(OFFSET, LIMIT, SORT) details = device_detail(devices) for detail in details: DISPLAYED += 1 print( f"{DISPLAYED}: {detail['hostname']} is on version {detail['agent_version']}" )
def connect_api(key: str, secret: str, base_url: str) -> Hosts: """ Connects to the API and returns an instance of the Hosts Service Class. """ return Hosts(client_id=key, client_secret=secret, base_url=base_url)
""" import platform import os import sys import pytest # Authentication via the test_authorization.py from tests import test_authorization as Authorization # Import our sibling src folder into the path sys.path.append(os.path.abspath('src')) # Classes to test - manually imported from sibling folder from falconpy import Hosts auth = Authorization.TestAuthorization() config = auth.getConfigObject() falcon = Hosts(auth_object=config) AllowedResponses = [200, 202, 400, 404, 429] # Adding rate-limiting as an allowed response for now class TestHosts: """ Hosts Service Class test harness """ def hosts_add_tag(self): """ Tests tagging functionality """ id_list = "1234567890" id_lookup = falcon.QueryDevicesByFilter(parameters={"limit": 1}) if id_lookup["status_code"] != 429:
else: # Set the value of offset to be the offset returned offset = offset_value # This will be the same every time, # overrides our init value of 1 total = result["meta"]["pagination"]["total"] # Retrieve the list of IDs returned id_list = result["resources"] # Append this list to our running list of all IDs returning.extend(id_list) return returning # Connect to the Hosts API falcon = Hosts(client_id=os.environ["FALCON_CLIENT_ID"], client_secret=os.environ["FALCON_CLIENT_SECRET"]) # Dictionary to hold our results compare = {} # Number of records to return per call, max is 5000 LIMIT = 100 # Standard offset handling using QueryDevicesByFilter indicator = Indicator(msg="Offset method )( ") indicator.display() compare["offset_style"] = get_query_results("offset_style", LIMIT) # "After" style offset handling using QueryDevicesByFilterScroll indicator = ind_message(indicator, "Token method") indicator.display() compare["token_style"] = get_query_results("token_style", LIMIT)