Giter Club home page Giter Club logo

python-sdk's Introduction

Lacework Python SDK

Build Status Downloads

laceworksdk is a community developed Python library for interacting with the Lacework APIs.

The purpose of this library is to simplify the common tasks required for interacting with the Lacework API, and allow users write simple code to automate tasks related to their Lacework instance(s). From data retrieval to configuration, this library aims to expose all publicly available APIs. For example, the following code would authenticate, fetch events, fetch host vulnerabilities, and fetch container vulnerabilities. The latest version of the SDK supports expressive searches as enabled by v2 of the Lacework APIs.

For more information read the documentation

from laceworksdk import LaceworkClient

lw = LaceworkClient() # This would leverage your default Lacework CLI profile.
lw = LaceworkClient(account="ACCOUNT",
                    subaccount="SUBACCOUNT",
                    api_key="API KEY",
                    api_secret="API SECRET")

events = lw.events.search(json={
  "timeFilter": {
    "startTime": start_time,
    "endTime": end_time
  }
})

host_vulns = lw.vulnerabilities.hosts.search(json={
    "timeFilter": {
        "startTime": start_time,
        "endTime": end_time
    }
})

container_vulns = lw.vulnerabilities.containers.search(json={
    "timeFilter": {
        "startTime": start_time,
        "endTime": end_time
    },
    "filters": [
        {
            "field": "imageId",
            "expression": "eq",
            "value": "sha256:657922eb2d64b0a34fe7339f8b48afb9f2f44635d7d6eaa92af69591d29b3330"
        }
    ]
})

Requirements

  • Python 3.8 or higher
  • Lacework API Credentials
    • Account Name
    • API Key
    • API Secret

How-To

The following information is required to instantiate a LaceworkClient instance:

  • account: The Lacework account/organization domain. (xxxxx.lacework.net)
  • api_key: The API Key that was generated from the Lacework UI/API.
  • api_secret: The API Secret that was generated from the Lacework UI/API.

Optionally, you can also set a Lacework Sub-Account using the subaccount parameter.

To generate API credentials, you'll need to do the following in Lacework:

  1. In the Lacework web interface, go to Settings -> API Keys
  2. Create a new API Key and download information the credentials.

Environment Variables

If you wish to configure the LaceworkClient instance using environment variables, this module honors the same variables used by the Lacework CLI. The account, subaccount, api_key, api_secret, and profile parameters can all be configured as specified below.

Environment Variable Description Required
LW_PROFILE Lacework CLI profile to use (configured at ~/.lacework.toml) N
LW_ACCOUNT Lacework account/organization domain (i.e. <account>.lacework.net) Y
LW_SUBACCOUNT Lacework sub-account N
LW_API_KEY Lacework API Access Key Y
LW_API_SECRET Lacework API Access Secret Y

Installation

Installing and upgrading laceworksdk is easy:

Install via PIP

$ pip install laceworksdk

Upgrading to the latest Version

$ pip install laceworksdk --upgrade

Examples

Are you looking for some sample scripts? Check out the examples folder!

python-sdk's People

Contributors

afiune avatar alannix-lw avatar brianp9906 avatar credibleforce avatar droessmj avatar hazedav avatar iancrichardson avatar ipcrm avatar jon-stewart avatar kiddinn avatar lacework-releng avatar lw-chall avatar surajswaminathan avatar tmac1973 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-sdk's Issues

.agent_info.search() not including `Content-Type: application/json` header: 400 errors

using the .agent_info.search(json=...) call results in a 400 error. Reviewing output from the debug logs indicates that it is missing the Content-Type: application/json header which is likely the reason for the errors.

def collectagents(self):
    postpayload = { 'timeFilter': {}}
    postpayload['timeFilter']['startTime'] = datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=-1), "%Y-%m-%dT00:00:00Z")
    postpayload['timeFilter']['endTime'] = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%dT%H:%M:%SZ")
    agents = self.lw.agent_info.search(json=json.dumps(postpayload))
    for i in agents:
        print(i)
    print(agents)

Debug output:

Wed, 01 Mar 2023 09:32:21 - laceworksdk.http_session - INFO - POST request to URI: https://instructure.lacework.net/api/v2/AgentInfo/search
Wed, 01 Mar 2023 09:32:21 - laceworksdk.http_session - DEBUG - Request headers: 
{
  "User-Agent": "laceworksdk-python-client/1.9.0",
  "Accept-Encoding": "gzip, deflate",
  "Accept": "*/*",
  "Connection": "keep-alive",
  "Authorization": "Bearer REDACTED",
  "Org-Access": "false"
}
Wed, 01 Mar 2023 09:32:21 - laceworksdk.http_session - DEBUG - POST request data:
Data: None
JSON: {"timeFilter": {"startTime": "2023-02-28T00:00:00Z", "endTime": "2023-03-01T09:32:17Z"}}
Wed, 01 Mar 2023 09:32:21 - urllib3.connectionpool - DEBUG - https://instructure.lacework.net:443 "POST /api/v2/AgentInfo/search HTTP/1.1" 400 51

Error: Initializing a LaceworkClient object

Hi, we've stumbled upon an issue when initializing a LaceworkClient object.
The client does not seem to work properly when the obligatory parameter account == subdomain.lacework.net

To Reproduce

SDK v1.3.0
Python 3.7+

Intialize the client object with values derived from the downloadable .json key file:

lw = LaceworkClient(account=os.getenv("LW_ACCOUNT"), # subdomain.lacework.net
                    api_key=os.getenv("LW_API_KEY"),
                    api_secret=os.getenv("LW_API_SECRET"))

When run this should result in the following (shortened) error:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

In contrast when the account == subdomain then client works as expected.

Expected behaviour

In my opinion the account parameter parsing should be adjusted so that subdomain.lacework.net and subdomain would be handled gracefully.
Alternatively the documentation should state clearly that only the user-specific subdomain should be provided.

feat: resource inventory example

Feature Request

Describe the Feature Request
Integrating with the API. Would love to pull the resource inventory along with any associated issues tied to machines, IAM policies, etc - I know this partially appears in the inventory search and partially in reports? But I'd love an itterator.

Is your feature request related to a problem? Please describe
Programatically listing the surface for use with other tooling.

Describe Preferred Solution
Examples in the example folder of viewing associated resources and what lacework thinks about them (e.g., list of IAM users and whether they're a problem, or list of EC2s and whether they have SG problems)

Additional Context
Example code is one thing, good docs would probably help oto.

Exception Handling: local variable 'response' referenced before assignment

The exception handling appears to be routing generic exceptions (i.e. Exception) through custom exceptions (i.e. ApiError) however in doing so it is passing response which may have failed to assign.

Take the following example:

        try:
            response = self._session.post(uri, json=data, headers=headers)
    
            # Validate the response
            self._check_response_code(response, DEFAULT_SUCCESS_RESPONSE_CODES)
    
            self._print_debug_response(response)
    
        except Exception:
>           raise ApiError(response)
E           UnboundLocalError: local variable 'response' referenced before assignment

In this case if self._session.post excepts, then response will not be assigned and we do not get proper exception handling. There are a few different approaches that can be taken here (one of which would be to initialize response to None and then handle this accordingly).

Deprecated v1 API calls still supported

Various v1 endpoints will no longer be supported and should be pulled from the SDK at some point in the near future. We should probably update to emit WARNING messaging in the interim.

regression: v1.8.0 causes ApiErrors while instantiating a client instance

Simply instantiating the client causes an API error for me.

lwc = LaceworkClient(account=api_creds['account'], api_key=api_creds['keyId'], api_secret=api_creds['secret'])

That line works and allows me to query my lacework account using laceworksdk==1.7.0. After upgrading to the latest release (1.8.0 as of this writing) I get a server error:

ApiError                                  Traceback (most recent call last)
/tmp/ipykernel_43438/2254193892.py in <module>
----> 1 lwc = LaceworkClient(account=api_creds['account'],api_key=api_creds['keyId'], api_secret=api_creds['secret'])
      2 
      3 now = datetime.datetime.utcnow()
      4 then = now - datetime.timedelta(days=7)

~/.local/lib/python3.10/site-packages/laceworksdk/api/__init__.py in __init__(self, account, subaccount, api_key, api_secret, instance, base_domain, profile)
    133 
    134         # Create an HttpSession instance
--> 135         self._session = HttpSession(
    136             self._account,
    137             self._subaccount,

~/.local/lib/python3.10/site-packages/laceworksdk/http_session.py in __init__(self, account, subaccount, api_key, api_secret, base_domain)
     61 
     62         # Get an access token
---> 63         self._check_access_token()
     64 
     65     def _retry_session(self,

~/.local/lib/python3.10/site-packages/laceworksdk/http_session.py in _check_access_token(self)
    100         if self._access_token is None or self._access_token_expiry < datetime.now(timezone.utc):
    101 
--> 102             response = self._get_access_token()
    103 
    104             # Parse and restructure the returned date (necessary for Python 3.6)

~/.local/lib/python3.10/site-packages/laceworksdk/http_session.py in _get_access_token(self)
    169 
    170             # Validate the response
--> 171             self._check_response_code(response, DEFAULT_SUCCESS_RESPONSE_CODES)
    172 
    173             self._print_debug_response(response)

~/.local/lib/python3.10/site-packages/laceworksdk/http_session.py in _check_response_code(self, response, expected_response_codes)
    118             raise RateLimitError(response)
    119         else:
--> 120             raise ApiError(response)
    121 
    122     def _print_debug_response(self, response):

ApiError: [500] Internal Server Error - Internal Error

SDK Documentation?

Hi! Thanks for maintaining this; it's been really helpful for making my API scripting more readable/maintainable. I had some trouble getting started, though. Here are places where I got stuck and more information in the README (or in other SDK-specific docs) would have helped:

  • What methods are available on the client? Linking to the full API docs would be a good start, but I'd also need to know how to translate endpoints to method names. (Seems to be pascal -> snake case, but doesn't say that anywhere.)
  • When do I need to use a submethod like .get() or .search()? What methods like exist? How do I format the arguments? Which ones are required? (I was surprised that queries.execute() requires time bound arguments -- when I run queries through the Lacework CLI I don't need to supply that, and the API docs don't mention it. If it weren't for the test files I'd still be stumped.)
  • The how-to says I need to auth with arguments to the client, the environment variables section says I can use variables, and a comment in the example implies I can use my Lacework config file, but I wish all of that was summarized in one explanation of my auth options. (The terraform provider does a great job of this.)
  • What does this SDK do when a method call fails? What errors should I catch, and how do I get response codes and messages out of them?
  • How are responses formatted? When should I expect them to be paged and how do I unpage them?

I don't need immediate answers to any of these -- a combination of reading the source code and just trying stuff to see what breaks eventually got me there. But I'd love to see these things documented so the next person doesn't have to.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.