I'm somehow unable to came up with a solution after spending already few days on this. What I need to do:
Iterate trough a large list of hosts in a .txt file to perform a request to the
devices/queries/devices/v1
API endpoint for CrowdStrike to get a so called aid (agent id).Once I have the aid (there can be multiple aid's for a single host) I need to again iterate but this time over the aid's to the
devices/entities/devices/v1
API endpoint to retrieve information such as hostname, last seen plus need to make another call, this time to thepolicy/combined/reveal-uninstall-token/v1
API endpoint, to get the uninstall token for each of the aid's.
The problem is that the bearer token that I'm generating initially is only valid for 30 minutes, and it needs to by provided with each subsequent request. My idea was to use the try except
construct + I'm raising exceptions with Response raise for status as described in correct-way-to-try-except-using-python-requests-module. So I'm hoping that at any point I'm making a request, if it fails due to an HTTP error like 401 Client Error: Unauthorized for url:
it would indicate that the token has expired and would call the login()
function token = login()
within except
to make a call to request new a new token and assign it to the token
variable and that would allow my to proceed with my for loop since the new token
would be provided. The problem I now see, is that for the given host that I'm iterating over, when the token expires, it get's skipped right after the new token is generated (the loop basically continues for the next item within the list). How could I workaround this ?
PS. I know the code is far from perfect, but it's my first steps and would be really nice I someone could lead me here. Was looking and continue
and break
but continue
seams to actually be doing exactly what I'm seeing as behavior with my code and break
is not applicable for what I want to do.
for host in host_list:
try:
'''
1.Get agent id (aid) for each host (NOTE:can return multiple aid's for single host).
If the returned list is empty, that means the host is not in CS and skip the
processing of the remaining code.
'''
query_aid = requests.get(base_url+ 'devices/queries/devices/v1?limit=5000&filter=hostname:' + "'" + host + "'", headers = {"accept": "application/json", "authorization": "Bearer " + token} )
query_aid.raise_for_status()
aux = json.loads(query_aid.text)
aux2 = aux["resources"]
if len(aux2) == 0:
print(host + ' ; ' + 'not in CS')
else:
'''
for whatever count of aid's returned iterate through each and make a call to the
devices/entities/devices/v1 endpoint to pull hostname and last_seen information,
and make for each aid a call to the policy/combined/reveal-uninstall-token/v1
endpoint to pull the uninstall token for each
'''
for aid in aux2:
host_details_request = requests.get(base_url + 'devices/entities/devices/v1?ids=' + aid , headers = {"accept": "application/json", "authorization": "Bearer " + token})
host_details_request.raise_for_status()
aux = json.loads(host_details_request.text)
last_seen = re.search(r'\d{4}-\d{2}-\d{2}', aux["resources"][0]["last_seen"])
request_uninstall_token = requests.post(base_url + 'policy/combined/reveal-uninstall-token/v1', headers = {'Content-type': 'application/json', "authorization": "Bearer " + token }, json = { "audit_message": "test api ", "device_id": aid })
request_uninstall_token.raise_for_status()
aux3 = json.loads(request_uninstall_token.text)
print(aux["resources"][0]["hostname"] + 'uninstall token: ' + aux3["resources"][0]["uninstall_token"] + ';' + last_seen.group(0))
except requests.exceptions.HTTPError as err:
print(err)
token = login()