def __enter__(self): """ Context manager method that's called when someone creates a with Smartcheck(...) as session: block. We'll start the session when the block is entered. """ # Create the session with the credentials that were provided in # the constructor. response = self.post('/api/sessions', json=self.credentials) if not response.ok: raise CreateSessionException(response) # Parse the created session session = response.json() # Save the session href (needed for later refreshes (TODO) # or to terminate the session when we're done). self.session_href = session['href'] # Put the session token into the `Authorization` header so all # requests in this session get authenticated and authorized. self.headers.update({'Authorization': f'Bearer {session["token"]}'}) return self
def _list(self, url, exception_kind, key, **kwargs): """ Generic "list anything in Deep Security Smart Check" method. Is a generator that will yield the individual items being listed and retrieve additional pages of data as needed until there are no more. The way listing resources works in the Deep Security Smart Check API is as follows: 1. Perform `GET /api/things` to get the first page of things. 2. The response will have the structure `{ things: [...] }` and if there is more data there will be a header `Link: <...>;rel="next"` that will take you to the next page. If there is no more data, the `Link rel=next` header won't be there. This method is the generic implementation that all of the `list*` methods will call. """ # Get the first page of results response = self.get(url, **kwargs) while True: # If the request failed, bail out -- we've got a specific exception type # for each kind of thing we list, so raise the appropriate exception if not response.ok: raise exception_kind(response) # All of the `list*` responses have the same structure: # { [key]: [items], next: "cursor?" } # Use the key to extract the items and yield them one at a time. for item in response.json()[key]: yield item # We use the link in the `Link: rel='next'` header as it's easier # than building a URL based on the cursor in the body. If there is # no header then there's no more data. if not 'next' in response.links: break # Extract the URL from the `Link: rel='next'` header. url = response.links['next']['url'] # Get the next page of results, we'll see you again at the top of the loop response = self.get(url)