diff --git a/.gitbook.yaml b/.gitbook.yaml new file mode 100644 index 00000000..1d0768ac --- /dev/null +++ b/.gitbook.yaml @@ -0,0 +1,3 @@ +structure: + readme: ./README.md + summary: ./docs/SUMMARY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..e1be2776 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report to help FalconPy improve. +title: "[ BUG ] ..." +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Environment (please complete the following information):** + - OS: [e.g. Red Hat Enterprise Linux 8.3] + - Python [e.g. 3.9] + +**Additional context** +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..a8116196 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + - package-ecosystem: pip + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..31880fd4 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,26 @@ +documentation: +- docs/* +- '*.md' +- src/falconpy/*.md +- samples/*.md + +package: +- src/*.py +- src/falconpy/*.py +- setup.py + +pipeline: +- .github/* +- .github/workflows/* +- .github/ISSUE_TEMPLATE/* + +unit testing: +- tests/* +- util/* + +code samples: +- samples/*.py +- samples/discover_aws/*.py +- samples/real_time_response/*.py +- samples/sample_uploads/*.py +- samples/quick_scan/*.py diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..5b0de148 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,45 @@ +> Please review our [Code of Conduct](https://github.com/CrowdStrike/falconpy/CODE_OF_CONDUCT.md) +> and our [Contribution Guidelines](https://github.com/CrowdStrike/falconpy/CONTRIBUTING.md) before submitting a Pull Request. + +> REMOVE ALL PULL REQUEST HINTS BEFORE SUBMITTING + +## PULL REQUEST TITLE +Pull Request general description should go here. +> Please fill out all values and then remove any help text before submitting your PR. +> Refer to [this PR](https://github.com/CrowdStrike/falconpy/pull/67) as a reference example! + +- [ ] Enhancement +- [ ] Major Feature update +- [ ] Bug fixes +- [ ] Breaking Change +- [ ] Updated unit tests +- [ ] Documentation + +> Check the values above that match your PR and remove the remaining. + +#### Unit test coverage +```shell +COVERAGE RESULTS SHOULD BE POSTED HERE +PLEASE REVIEW CONTRIBUTING.md FOR MORE +DETAILS ON GENERATING COVERAGE RESULTS +``` + +#### Bandit analysis +```shell +BANDIT ANALYSIS RESULTS SHOULD BE POSTED +HERE. PLEASE REVIEW CONTRIBUTING.md FOR +MORE DETAILS ON GENERATING BANDIT RESULTS +``` +## Added features and functionality ++ If your PR adds features or functionality, what should be included in the next release notes? + +## Issues resolved ++ Bug fix: Please list related bugs individually. Identifying the ticket or bug report in the PR description auto-updates the affected ticket and helps the community with ticket triage. For example: + +* Fixes https://github.com/CrowdStrike/falconpy/issues/1234 by doing foo +* Mitigates https://github.com/CrowdStrike/falconpy/issues/5678 by updating bar. ++ BE EXPLICIT in what you are resolving + +## Other ++ List any other details here ++ Documentation regarding your changes can also be listed here diff --git a/.github/wordlist.txt b/.github/wordlist.txt new file mode 100644 index 00000000..4248580a --- /dev/null +++ b/.github/wordlist.txt @@ -0,0 +1,395 @@ +APIs +CrowdScore +CrowdStrike +CrowdStrike's +Overwatch +APIHarness +deauthentication +detections +initialisation +SDK +gofalcon +ip +oauth +OAuth +OAuth2 +oauth2 +pre +falconpy +FalconPy +urllib +autogenerated +pytest +ipython +dev +config +cov +FalconDebug +Uber +UUID +USERUUID +SHA +sha +MacOS +DeleteSampleV +upfile +formData +executables +cURL +boto +serverless +boolean +Shockwave +Scalable +Powershell +MalQuery +Javascript +APK +json +JSON +UploadSampleV +GetSampleV +desc +FQL +querySensorVisibilityExclusionsV +updateSensorVisibilityExclusionsV +deleteSensorVisibilityExclusionsV +createSVExclusionsV +getSensorVisibilityExclusionsV +ruletype +rulesMixin +groupsMixin +platformsMixin +groupMixin +severities +IOA +IOAs +IOC +ioa +ioc +queryIOAExclusionsV +updateIOAExclusionsV +deleteIOAExclusionsV +createIOAExclusionsV +getIOAExclusionsV +UpdateCSPMScanSchedule +GetCSPMScanSchedule +UpdateCSPMPolicySettings +GetCSPMPolicySettings +GetCSPMPolicy +GetCSPMAzureUserScriptsAttachment +ClientID +UpdateCSPMAzureAccountClientID +DeleteCSPMAzureAccount +CreateCSPMAzureAccount +GetCSPMAzureAccount +SubscriptionID +SubscriptionIDs +GetCSPMAwsAccountScriptsAttachment +GetCSPMAwsConsoleSetupURLs +DeleteCSPMAwsAccount +CreateCSPMAwsAccount +CreateCSPMAwsAccount +CreateCSPMAzureAccount +DeleteCSPMAwsAccount +DeleteCSPMAzureAccount +GetCSPMAwsAccount +GetCSPMAwsAccountScriptsAttachment +GetCSPMAwsConsoleSetupURLs +GetCSPMAzureAccount +GetCSPMAzureUserScriptsAttachment +GetCSPMPolicy +GetCSPMPolicySettings +GetCSPMScanSchedule +UpdateCSPMAzureAccountClientID +UpdateCSPMPolicySettings +UpdateCSPMScanSchedule +CSPM +ScanSamples +GetScans +GetScansAggregates +QuerySubmissionsMixin +CreateCSPMAzureAccount +CreateCSPMGCPAccount +GCP +GetCSPMAzureAccount +GetCSPMAzureUserScripts +GetCSPMAzureUserScriptsAttachment +GetCSPMCGPAccount +GetCSPMGCPUserScripts +GetCSPMGCPUserScriptsAttachment +UpdateCSPMAzureAccountClientID +GetMalQueryDownloadV +GetMalQueryEntitiesSamplesFetchV +GetMalQueryMetadataV +GetMalQueryQuotasV +GetMalQueryRequestV +PostMalQueryEntitiesSamplesMultidownloadV +PostMalQueryExactSearchV +PostMalQueryFuzzySearchV +PostMalQueryHuntV +YARA +multidownload +createMLExclusionsV +deleteMLExclusionsV +getMLExclusionsV +queryMLExclusionsV +updateMLExclusionsV +CID +CCID +DownloadSensorInstallerById +GetCombinedSensorInstallersByQuery +GetSensorInstallersByQuery +GetSensorInstallersCCIDByQuery +GetSensorInstallersEntities +asc +desc +hostname +AIDs +GetDeviceDetails +PerformActionV +QueryDevicesByFilter +QueryDevicesByFilterScroll +QueryHiddenDevices +IPs +UI +AID +agentIDs +RTR +AggregateSessions +BatchActiveResponderCmd +BatchCmd +BatchGetCmd +BatchGetCmdStatus +BatchInitSessions +BatchRefreshSessions +CheckActiveResponderCommandStatus +CheckCommandStatus +DeleteFile +DeleteQueuedSession +DeleteSession +ExecuteActiveResponderCommand +ExecuteCommand +GetExtractedFileContents +InitSession +ListAllSessions +ListFiles +ListQueuedSessions +ListSessions +PulseSession +responder +Responder +cmd +req +af +cd +ced +efa +fc +FH +IPv +ipv +md +gzip +yara +TODO +IOCs +powershell +responders +url +py +Trainings +linux +ndetect +notificationsnnnone +CreateIOC +DeleteIOC +DevicesCount +DevicesRanOn +GetIOC +ProcessID +ProcessesRanOn +QueryIOCs +UpdateIOC +GetAggregateDetects +GetDetectSummaries +QueryDetects +UpdateDetectsByIdsV +CreateOrUpdateAWSSettings +DeleteAWSAccounts +GetAWSAccounts +GetAWSSettings +ProvisionAWSAccounts +QueryAWSAccounts +QueryAWSAccountsForIDs +UpdateAWSAccounts +VerifyAWSAccountAccess +APK +Javascript +formData +upfile +Runtime +runtime +DeleteReport +DeleteSampleV +GetArtifacts +GetReports +GetSampleV +GetSubmissions +GetSummaryReports +PCAP +QueryReports +QuerySampleV +QuerySubmissions +UploadSampleV +Falconx +FalconX +getVulnerabilities +queryVulnerabilities +createSensorUpdatePolicies +createSensorUpdatePoliciesV +deleteSensorUpdatePolicies +getSensorUpdatePolicies +getSensorUpdatePoliciesV +performSensorUpdatePoliciesAction +queryCombinedSensorUpdateBuilds +queryCombinedSensorUpdatePolicies +queryCombinedSensorUpdatePoliciesV +queryCombinedSensorUpdatePolicyMembers +querySensorUpdatePolicies +querySensorUpdatePolicyMembers +revealUninstallToken +setSensorUpdatePoliciesPrecedence +updateSensorUpdatePolicies +updateSensorUpdatePoliciesV +createHostGroups +deleteHostGroups +getHostGroups +performGroupAction +queryCombinedGroupMembers +queryCombinedHostGroups +queryGroupMembers +queryHostGroups +updateHostGroups +GetBehaviors +GetIncidents +PerformIncidentAction +QueryBehaviors +QueryIncidents +Substring +changelog +netwitness +substring +suricata +GetIntelActorEntities +GetIntelIndicatorEntities +GetIntelReportEntities +GetIntelReportPDF +GetIntelRuleEntities +GetIntelRuleFile +GetLatestIntelRuleFile +QueryIntelActorEntities +QueryIntelActorIds +QueryIntelIndicatorEntities +QueryIntelIndicatorIds +QueryIntelReportEntities +QueryIntelReportIds +QueryIntelRuleIds +BatchAdminCmd +CheckAdminCommandStatus +CreatePut +CreateScripts +DeletePut +DeleteScripts +ExecuteAdminCommand +GetPut +GetScripts +ListPut +ListScripts +UpdateScripts +createDeviceControlPolicies +deleteDeviceControlPolicies +getDeviceControlPolicies +performDeviceControlPoliciesAction +queryCombinedDeviceControlPolicies +queryCombinedDeviceControlPolicyMembers +queryDeviceControlPolicies +queryDeviceControlPolicyMembers +setDeviceControlPoliciesPrecedence +updateDeviceControlPolicies +CIDs +MSSP +cid +ccid +AccessToken +RevokeToken +auth +urlencoded +www +uid +uuid +CreateUser +DeleteUser +GetAvailableRoleIds +GetRoles +GetUserRoleIds +GrantUserRoleIds +RetrieveEmailsByCID +RetrieveUser +RetrieveUserUUID +RetrieveUserUUIDsByCID +RevokeUserRoleIds +UpdateUser +createPreventionPolicies +deletePreventionPolicies +getPreventionPolicies +performPreventionPoliciesAction +queryCombinedPreventionPolicies +queryCombinedPreventionPolicyMembers +queryPreventionPolicies +queryPreventionPolicyMembers +setPreventionPoliciesPrecedence +updatePreventionPolicies +flatjson +appId +datafeed +listAvailableStreamsOAuth +refreshActiveStreamSession +Realtime +codebase +PyPI +https +github +intel +Auth +duplicative +CodeQL +faq +sexualized +socio +crowdstrike +api +falconx +html +cspm +aws +malquery +iocs +ioas +SemVer +ver +src +backend +util +PyTest +FalconShell +Unlicense +errored +XZY +toc +performFirewallPoliciesAction +mssp +CalebSchwartz +rewgord +validator +UpdateDeviceTags \ No newline at end of file diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml new file mode 100644 index 00000000..32fefd88 --- /dev/null +++ b/.github/workflows/bandit.yml @@ -0,0 +1,35 @@ +name: Bandit +on: + push: + paths: + - '**.py' + branches: + - main + - 'ver_*' + pull_request: + paths: + - '**.py' + branches: + - main + - 'ver_*' + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install bandit + pip install -r requirements.txt + - name: Analyze package with bandit + run: | + bandit -r src + - name: Analyze samples with bandit + run: | + bandit -r samples diff --git a/.github/workflows/check_spelling.yml b/.github/workflows/check_spelling.yml new file mode 100644 index 00000000..399de052 --- /dev/null +++ b/.github/workflows/check_spelling.yml @@ -0,0 +1,13 @@ +name: Check Spelling +on: + pull_request: + paths: + - '**.txt' + - '**.md' +jobs: + spelling: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Check Spelling + uses: SFLScientific/spellcheck-github-actions@master diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..67524dba --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + paths: + - '**.py' + branches: [ main ] + pull_request: + paths: + - '**.py' + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + - cron: '26 4 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/dev-deploy.yml b/.github/workflows/dev-deploy.yml new file mode 100644 index 00000000..095f8877 --- /dev/null +++ b/.github/workflows/dev-deploy.yml @@ -0,0 +1,35 @@ +name: Publish Test Python Package + +on: + push: + paths: + - '**.py' + branches: + - main + +jobs: + deploy-package: + + runs-on: ubuntu-latest + if: "startsWith(github.event.head_commit.message, '[DEPLOY]')" + + steps: + + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + + - name: Build and publish to test index + env: + TWINE_USERNAME: ${{ secrets.DEV_PACKAGE_ID }} + TWINE_PASSWORD: ${{ secrets.DEV_PACKAGE_SECRET }} + run: | + python setup.py sdist bdist_wheel + twine upload --repository testpypi dist/* diff --git a/.github/workflows/label_request.yml b/.github/workflows/label_request.yml new file mode 100644 index 00000000..0d6f448a --- /dev/null +++ b/.github/workflows/label_request.yml @@ -0,0 +1,13 @@ +name: "Label Request" +on: + pull_request: + branches: + - main + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@main + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index d5c94b35..95d28095 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -1,22 +1,21 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: Python package - +name: Flake8 on: push: - branches: [ main ] + paths: + - '**.py' + branches: + - main + - 'ver_*' pull_request: - branches: [ main ] + paths: + - '**.py' + branches: + - main + - 'ver_*' jobs: - build: - + analyze: runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.5', '3.6', '3.7', '3.8', '3.9'] - steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -26,14 +25,18 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: Lint with flake8 + python -m pip install flake8 + pip install -r requirements.txt + - name: Lint package source with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 src/falconpy --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + # Stop the build on all linting errors - 04.02.21 / jshcodes@CrowdStrike + flake8 src/falconpy --count --max-complexity=15 --max-line-length=127 --statistics + - name: Lint samples with flake8 run: | # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 samples --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics -# - name: Test with pytest -# run: | -# pytest + flake8 samples --exit-zero --count --max-complexity=15 --max-line-length=127 --statistics diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 00000000..3d939745 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,31 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +name: Publish Python Package + +on: + release: + types: [created] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PACKAGE_API_ID }} + TWINE_PASSWORD: ${{ secrets.PACKAGE_API_SECRET }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/.github/workflows/unit_testing_macos.yml b/.github/workflows/unit_testing_macos.yml new file mode 100644 index 00000000..73cc2430 --- /dev/null +++ b/.github/workflows/unit_testing_macos.yml @@ -0,0 +1,41 @@ +name: Python package (MacOS) +on: + push: + paths: + - '**.py' + branches: + - main + - 'ver_*' + pull_request: + paths: + - '**.py' + branches: + - main + - 'ver_*' + +jobs: + build: + strategy: + matrix: + # os: [macos-latest, windows-latest, ubuntu-latest] + python-version: ['3.6', '3.7', '3.8', '3.9'] + # runs-on: ${{ matrix.os }} + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pytest coverage + pip install -r requirements.txt + - name: Test with pytest + env: + DEBUG_API_ID: ${{ secrets.DEBUG_API_ID }} + DEBUG_API_SECRET: ${{ secrets.DEBUG_API_SECRET }} + run: | + coverage run --source=src --omit=src/falconpy/debug.py -m pytest -s + coverage report diff --git a/.github/workflows/unit_testing_ubuntu.yml b/.github/workflows/unit_testing_ubuntu.yml new file mode 100644 index 00000000..c92a1a3a --- /dev/null +++ b/.github/workflows/unit_testing_ubuntu.yml @@ -0,0 +1,41 @@ +name: Python package (Ubuntu) +on: + push: + paths: + - '**.py' + branches: + - main + - 'ver_*' + pull_request: + paths: + - '**.py' + branches: + - main + - 'ver_*' + +jobs: + build: + strategy: + matrix: + # os: [macos-latest, windows-latest, ubuntu-latest] + python-version: ['3.6', '3.7', '3.8', '3.9'] + # runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pytest coverage + pip install -r requirements.txt + - name: Test with pytest + env: + DEBUG_API_ID: ${{ secrets.DEBUG_API_ID }} + DEBUG_API_SECRET: ${{ secrets.DEBUG_API_SECRET }} + run: | + coverage run --source=src --omit=src/falconpy/debug.py -m pytest -s + coverage report diff --git a/.github/workflows/unit_testing_windows.yml b/.github/workflows/unit_testing_windows.yml new file mode 100644 index 00000000..b8a26ee8 --- /dev/null +++ b/.github/workflows/unit_testing_windows.yml @@ -0,0 +1,41 @@ +name: Python package (Windows) +on: + push: + paths: + - '**.py' + branches: + - main + - 'ver_*' + pull_request: + paths: + - '**.py' + branches: + - main + - 'ver_*' + +jobs: + build: + strategy: + matrix: + # os: [macos-latest, windows-latest, ubuntu-latest] + python-version: ['3.6', '3.7', '3.8', '3.9'] + # runs-on: ${{ matrix.os }} + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pytest coverage + pip install -r requirements.txt + - name: Test with pytest + env: + DEBUG_API_ID: ${{ secrets.DEBUG_API_ID }} + DEBUG_API_SECRET: ${{ secrets.DEBUG_API_SECRET }} + run: | + coverage run --source=src --omit=src/falconpy/debug.py -m pytest -s + coverage report diff --git a/.gitignore b/.gitignore index 0bf3bed8..6c573822 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,8 @@ env/ .vscode/ build/ dist -falconpy.egg-info/ -__pycache__/ \ No newline at end of file +*.egg-info/ +sensor_downloads/ +__pycache__/ +.env +.coverage \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..2a4745b3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,169 @@ +# Version 0.4.5 +## Added features and functionality ++ Added: Custom Indicators of Attack (IOA) API Service Class (`custom_ioa.py`) + * get_patterns + * get_platformsMixin0 + * get_rule_groupsMixin0 + * create_rule_groupMixin0 + * delete_rule_groupsMixin0 + * update_rule_groupMixin0 + * get_rule_types + * get_rules_get + * get_rulesMixin0 + * create_rule + * delete_rules + * update_rules + * validate + * query_patterns + * query_platformsMixin0 + * query_rule_groups_full + * query_rule_groupsMixin0 + * query_rule_types + * query_rulesMixin0 + - Added unit tests (`test_custom_ioa.py`) + ++ Added: Falcon X Quick Scan API Service Class (`quick_scan.py`) + * GetScansAggregates + * GetScans + * ScanSamples + * QuerySubmissionsMixin0 + - Added unit tests (`test_quick_scan.py`) + ++ Added: Uber class endpoints (`_endpoints.py`) + * Falcon Complete Dashboard API + * Falcon Overwatch Dashboard API + * Falcon Flight Control API +## Issues resolved ++ Fixed unidiomatic type check in `_util.py` (_parse_id_list_) ++ Fixed potentially problematic default payload lists and dictionaries (Service Classes and Uber Class) +## Other ++ Added CHANGELOG.md ++ Documentation updates to reflect new service class and upcoming API additions ++ Minor comment updates ++ Adjusted GitHub actions to test operating systems as separate workflows ++ Minor GitHub workflow adjustments ++ Unit test updates + - Cloud Connect AWS + - CSPM Registration + - Sensor Download + +# Version 0.4.4 +## Added features and functionality ++ Added: Sensor Download API Service Class (Contributor: @CalebSchwartz) + * GetCombinedSensorInstallersByQuery + * DownloadSensorInstallerById + * GetSensorInstallersEntities + * GetSensorInstallersCCIDByQuery + * GetSensorInstallersByQuery + - Added unit tests +## Issues resolved ++ Fixed: action_name parameter default bug. Resolved by setting a default value and overriding this value if action_name is present in the parameters dictionary, Closes #114. +## Other ++ Documentation updated to reflect the new Sensor Download Service Class + + +# Version 0.4.3 +## Added features and functionality ++ Added: Sample_Uploads service class (`sample_uploads.py`) + * UploadSampleV3 + * GetSampleV3 + * DeleteSampleV3 + - Added: Sample_Uploads unit tests (`test_sample_uploads.py`) ++ Added: FalconDebug - Interactive Python3 debugger that provides a pre-defined API token. +## Issues resolved ++ Fixed: Issue with Uber class command method using the action_name variable instead of file_name variable for actions passing the file_name parameter. ++ Fixed: Issue with `setup.py` passing GitHub emoji text to the package description. ++ Fixed: Issue with Uber class unit testing not deleting uploaded files from Sample_Uploads API. (`test_uber_api_complete.py`) + + +# Version 0.4.2 +## Added features and functionality ++ Added missing method: `hosts.py` - Added UpdateDeviceTags method to Hosts service class. (Contributor: @rewgord) + - Unit test added to `test_hosts.py` to test device tagging functionality. ++ API Operation summaries added to the Uber class: `_endpoint.py` - This provides for upcoming functionality that will be announced in future updates. ++ New endpoints added to the Uber class: `_endpoint.py` + +> Deprecation Warning: Legacy API operation IDs that made use of the Python reserved characters "." and "-" have been deprecated. +> New operation IDs have been generated for each that now aligns to the method names defined in the equivalent service class. + +## Issues resolved ++ Added method validation to Uber class calls to the requests library. (HTTP 418 is sent when an invalid method is specified.) +## Other ++ Cleaned up `event_streams.py` class file to match new patterns. ++ Updated return type decorators for service_request and perform_request. (`_util.py`) ++ Updated return type decorators for GetArtifacts, GetReports and GetSampleV2. (`falconx_sandbox.py`) ++ Abstracted all remaining common error output code paths to a stand-alone generic method. (`_util.py`) + + +# Version 0.4.1 +## Added features and functionality ++ New service class: cspm_registration.py - Provides the *CSPM_Registration* service class for handling Horizon registration in Azure and AWS. + - Unit test added ++ Added methods: falconx_sandbox.py - Support for the following operations have been added to the *FalconX_Sandbox* service class. + * QuerySampleV1 + * DeleteSampleV2 + * GetSampleV2 + * DeleteReport + * GetReports + - Unit test added +## Issues resolved ++ Bug fix: Resolved malformed validator in detects.py - UpdateDetectsByIdsV2 ++ Bug fix: Added action_name parameter to operations that require the parameter. Closes #53. + This issue impacted 6 service classes in total: + - device_control_policies.py - *Device_Control_Policies* - performDeviceControlPoliciesAction + - firewall_policies.py - *Firewall_Policies* - performFirewallPoliciesAction + - host_group.py - *Host_Group* - performGroupAction + - hosts.py - *Host* - PerformActionV2 + - prevention_policy.py - *Prevention_Policy* - performPreventionPoliciesAction + - sensor_update_policy.py - *Sensor_Update_Policy* - performSensorUpdatePoliciesAction + + - This issue also impacted the Uber class, resulting in updates to the command method within the APIHarness class. + + - Unit tests modified + +> Breaking Change: The action_name parameter does not currently accept unspecified values. This is resolved in the 0.4.4 version of the package. + +## Other ++ Minor updates to `_endpoints.py` to reflect operation ID corrections for the CSPM registration API. ++ Abstracted common error output code paths to a stand-alone method within `_util.py`. + + +# Version 0.4.0 +## Added features and functionality ++ Added additional HTTP status codes ++ Added parameter input validation handling + - Additional validations are planned for all service classes. Currently only enabled in `cloud_connect_aws.py`. ++ Added body payload input validation handling + - Additional validations are planned for all service classes. Currently only enabled in `cloud_connect_aws.py`. ++ Added allowed HTTP method restrictions ++ Added ID list handling to API operations that require ID lists + - Developers may now pass in a list of IDs or a comma-delimited string. ++ Added status code response checks to authentication events ++ Instantiate Service classes without having to manage tokens + - Pass in credentials (Now referred to as "credential authentication") + - Pass in the entire auth object (Now referred to as "object authentication") + > Please note: Passing a token into Service classes is still fully supported. This is now referred to as "legacy authentication". ++ Added automatic token refresh functionality to Service Class calls + - Developers must make use of either credential or object authentication in order to leverage this functionality. +## Issues resolved ++ Added dynamic package metadata updates (Closes #14) + - Generalized version control + - New constant file: `_version.py` ++ Added user-agent string to HTTP headers. (Closes #57) ++ Resolved a bug with token deauthentication (Uber and Service classes) ++ Resolved a bug in Firewall_Management.update_rule_group +## Other ++ Abstracted calls to the requests library from all classes, reducing code segment size + - New library: _util.py + - New class: _service_class.py + - New class: _result.py + - All Service Classes refactored ++ Abstracted endpoint list from the Uber class to a standalone source file + - New constant file: _endpoint.py ++ Linting / code cleanup + - Added function input parameter datatype specifications (where possible) + - Added function output datatype decorators + - In order to reduce confusion, references to the `json` requests attribute are now always referred to as "body". + - References to the `data` requests attribute are still referred to as "data". ++ 100% unit test coverage ++ Internal documentation updates \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..2b17acda --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# FalconPy Community Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +falconpy@crowdstrike.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..aced3b1e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,182 @@ +# Contributing to this repository + +## Getting started +_Welcome!_ We're excited you want to take part in the FalconPy community! + +Please review this document for details regarding getting started with your first contribution, packages you'll need to install as a developer, and our Pull Request process. If you have any questions, please let us know by +posting your question in the [discussion board](https://github.com/CrowdStrike/falconpy/discussions). + +### Before you begin +- Have you read the [Code of Conduct](CODE_OF_CONDUCT.md)? The Code of Conduct helps us establish community norms and how they'll be enforced. + +### Table of Contents +- [How you can contribute](#how-you-can-contribute) + + [Bug reporting](#bug-reporting-is-handled-using-githubs-issues) + + [All other discussions](#githubs-discussion-board-is-used-for-questions-suggestions-and-feedback) +- [Pull Requests](#pull-requests) + + [Contributor dependencies](#additional-contributor-package-requirements) + + [Unit testing](#unit-testing--code-coverage) + + [Linting](#linting) + + [Breaking changes](#breaking-changes) + + [Branch targeting](#branch-targeting) +- [Suggestions](#suggestions) + +## How you can contribute +- See something? Say something! Submit a [bug report](https://github.com/CrowdStrike/falconpy/issues) to let the community know what you've experienced or found. Bonus points if you suggest possible fixes or what you feel may resolve the issue. For example: "_Attempted to use the XZY API class but it errored out. Could a more descriptive error code be returned?_" +- Join the [discussion board](https://github.com/CrowdStrike/falconpy/discussions) where you can: + - [Interact](https://github.com/CrowdStrike/falconpy/discussions/categories/general) with other members of the community + - Suggest [new functionality](https://github.com/CrowdStrike/falconpy/discussions/categories/ideas) + - Provide [feedback](https://github.com/CrowdStrike/falconpy/discussions/categories/q-a) + - [Show others](https://github.com/CrowdStrike/falconpy/discussions/categories/show-and-tell) how you are using FalconPy today +- Submit a [Pull Request](#pull-requests) + +### Bug reporting is handled using GitHub's issues +We use GitHub issues to track bugs. Report a bug by opening a [new issue](https://github.com/CrowdStrike/falconpy/issues). + +### GitHub's discussion board is used for questions, suggestions and feedback. +We use GitHub's discussion board functionality to handling community discussions related to +[questions](https://github.com/CrowdStrike/falconpy/discussions/categories/q-a), +[feedback](https://github.com/CrowdStrike/falconpy/discussions/categories/general) +or [functionality enhancements](https://github.com/CrowdStrike/falconpy/discussions/categories/ideas). + +## Pull Requests + +### All contributions will be submitted under the Unlicense license +When you submit code changes, your submissions are understood to be under the same Unlicense [license](LICENSE) that covers the project. +If this is a concern, contact the maintainers before contributing. + +### Additional contributor package requirements +`requirements-dev.txt` contains Python modules required for unit test development and for accessing the integrated debugger within FalconShell. Review this file's contents and install missing requirements as needed. + +### Unit testing & Code coverage ++ All submitted code must also have an associated unit test that tests __all__ code paths within this new segment. (:100: percent coverage) + - If the code submission is already covered by an existing unit test, additional unit tests are not required. + - Please include coverage testing results in your Pull Request. (Example: [PR #67](https://github.com/CrowdStrike/falconpy/pull/67)) ++ Unit testing is intended to prove out code formatting and functionality, not necessarily API functionality. Unit testing does not need to communicate with the API in order to provide the necessary coverage. ++ We use bandit for static code analysis. + - Please include bandit analysis results in the section provided in your Pull Request. + - Pull Requests that produce alerts in bandit may be closed without merging. ++ All new contributions __must__ pass unit testing before they will be merged. + - For scenarios where unit testing passes in the PR and fails post-merge, a maintainer will address the issue. If the problem is programmatic and related to code within the pull request, the merge may be reverted. ++ The util folder contains a BASH script, `run-tests.sh`, that contains the parameters used that match unit testing performed as part of our GitHub workflows. +> You can run all unit tests and perform a bandit analysis by executing the command `util/run-tests.sh` from the root of the project directory. + +#### Posting coverage results to Pull Requests +Our Pull Request template provides an area for you to post the coverage results from your local unit tests. This table is generated by the command `coverage report` and is executed when you use the "run-tests.sh" BASH script found in the util folder. This table is output only when all unit tests have passed successfully, and is a required element for Pull Request approval. + +##### Example coverage results +```shell +Name Stmts Miss Cover +--------------------------------------------------------------- +src/falconpy/__init__.py 10 0 100% +src/falconpy/_endpoint.py 1 0 100% +src/falconpy/_result.py 8 0 100% +src/falconpy/_service_class.py 31 0 100% +src/falconpy/_util.py 80 0 100% +src/falconpy/_version.py 8 0 100% +src/falconpy/api_complete.py 77 0 100% +src/falconpy/cloud_connect_aws.py 66 0 100% +src/falconpy/cspm_registration.py 114 0 100% +src/falconpy/detects.py 34 0 100% +src/falconpy/device_control_policies.py 67 0 100% +src/falconpy/event_streams.py 15 0 100% +src/falconpy/falconx_sandbox.py 78 0 100% +src/falconpy/firewall_management.py 130 0 100% +src/falconpy/firewall_policies.py 68 0 100% +src/falconpy/host_group.py 61 0 100% +src/falconpy/hosts.py 37 0 100% +src/falconpy/incidents.py 39 0 100% +src/falconpy/intel.py 89 0 100% +src/falconpy/iocs.py 58 0 100% +src/falconpy/oauth2.py 30 0 100% +src/falconpy/prevention_policy.py 67 0 100% +src/falconpy/real_time_response.py 135 0 100% +src/falconpy/real_time_response_admin.py 82 0 100% +src/falconpy/sensor_update_policy.py 103 0 100% +src/falconpy/spotlight_vulnerabilities.py 15 0 100% +src/falconpy/user_management.py 75 0 100% +--------------------------------------------------------------- +TOTAL 1578 0 100% +``` + +#### Posting bandit results to Pull Requests +Our Pull Request template provides an area for you to post the bandit analysis results from your local unit tests. This detail is generated by the command `bandit ...` and is executed when you run the "run-tests.sh" BASH script found in the util folder. These results are produced only when all unit tests have passed successfully, and are required for Pull Request approval. + +##### Example bandit analysis results +```shell +[main] INFO profile include tests: None +[main] INFO profile exclude tests: None +[main] INFO cli include tests: None +[main] INFO cli exclude tests: None +[main] INFO running on Python 3.9.2 +Run started:2021-03-26 21:13:00.083912 + +Test results: + No issues identified. + +Code scanned: + Total lines of code: 6415 + Total lines skipped (#nosec): 0 + +Run metrics: + Total issues (by severity): + Undefined: 0.0 + Low: 0.0 + Medium: 0.0 + High: 0.0 + Total issues (by confidence): + Undefined: 0.0 + Low: 0.0 + Medium: 0.0 + High: 0.0 +Files skipped (0): +``` + +#### More details regarding PyTest, Coverage and Bandit +For more information regarding PyTest, and how we leverage it to perform unit testing, refer to the [PyTest documentation](https://docs.pytest.org/en/stable/contents.html#toc). + +To find out more above Coverage, review their [website](https://coverage.readthedocs.io/en/coverage-5.5/). + +To read more about bandit, you can visit [their documentation website](https://bandit.readthedocs.io/en/latest/). + +### Linting +All submitted code must meet minimum linting requirements. ++ We use `flake8` for linting. ++ All code that is included within the installation package must pass linting when the Pull Request checks have completed. + - You will be asked to correct linting errors before your Pull Request will be approved. ++ Unit tests do not need to meet this requirement, but try to keep linting errors to a minimum. ++ Refer to the `lint.sh` script within the util folder to review our standard linting parameters. +> You can quickly check the linting for all code within the src folder by executing the command `util/lint.sh` from the root of the project directory. + +More information about flake8 can be found [here](https://flake8.pycqa.org/en/latest/). + +### Breaking changes +In an effort to maintain backwards compatibility, we thoroughly unit test every Pull Request for all versions of Python we support. These unit tests are intended to catch general programmatic errors, possible vulnerabilities (via bandit) and _potential breaking changes_. + +> If you have to adjust a unit test locally in order to produce passing results, there is a possibility you are working with a potential breaking change. + +Please fully document changes to unit tests within your Pull Request. If you did not specify "Breaking Change" on the punch list in the description, and the change is identified as possibly breaking, this may delay or prevent approval of your PR. + +### Branch targeting +_Please do not target the `main` branch with your Pull Request unless directed to do so by a maintainer_. Instead, target your PR at the most recent development branch. + +We use [SemVer](https://semver.org/) as our versioning scheme. (Example branch name: _ver_0.4.3_) + +If you are unable to identify the current development branch, please reach out to the maintainers or post a message to the general discussion board. + +### Pull Request template +Please use the pull request template provided, making sure the following details are included in your request: ++ Is this a breaking change? ++ Are all new or changed code paths covered by unit testing? ++ A complete listing of issues addressed or closed with this change. ++ A complete listing of any enhancements provided by this change. ++ Any usage details developers may need to make use of this new functionality. + - Does additional documentation need to be developed beyond what is listed in your Pull Request? ++ Any other salient points of interest. + +### Approval / Merging +All Pull Requests must be approved by at least one maintainer. Once approved, a maintainer will perform the merge and execute any backend +processes related to package deployment. At this time, contributors _do not_ have the ability to merge to the `main` branch. + +## Suggestions +If you have suggestions on how this process could be improved, please let us know by [starting a new discussion](https://github.com/CrowdStrike/falconpy/discussions). diff --git a/LICENSE b/LICENSE index 48334c4d..fdddb29a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,27 +1,24 @@ -Copyright CrowdStrike 2020 +This is free and unencumbered software released into the public domain. -By accessing or using this script, sample code, application programming interface, tools, -and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -warrant that You are entering into this Agreement on behalf of a company, organization -or another legal entity (“Entity”) that is currently a customer or partner of -CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -such Entity agrees to be bound by this Agreement. +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. -CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -free and limited license to access and use the Tools solely for Entity’s internal business -purposes and in accordance with its obligations under any agreement(s) it may have with -CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -right, title and interest in and to the Tools, and all intellectual property rights -embodied therein, and that Entity has no right, title or interest therein except for the -express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -confidential information. +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. -THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/README.md b/README.md index 63511db7..6ca56bbb 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,113 @@ -![PyPI - Status](https://img.shields.io/pypi/status/crowdstrike-falconpy) -![PyPI](https://img.shields.io/pypi/v/crowdstrike-falconpy) +![CrowdStrike Falcon](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/cs-logo.png) [![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20%40CrowdStrike&style=social&url=https%3A%2F%2Ftwitter.com%2FCrowdStrike)](https://twitter.com/CrowdStrike)
+ +# FalconPy - The CrowdStrike Falcon SDK for Python 3 ![PyPI - Implementation](https://img.shields.io/pypi/implementation/crowdstrike-falconpy) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/crowdstrike-falconpy) -![PyPI - Wheel](https://img.shields.io/pypi/wheel/crowdstrike-falconpy) +[![CodeQL](https://github.com/CrowdStrike/falconpy/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/CrowdStrike/falconpy/actions/workflows/codeql-analysis.yml) +![CI Test Coverage](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/tests/coverage.svg) +![Maintained](https://img.shields.io/maintenance/yes/2021)
+The FalconPy SDK contains a collection of Python classes that abstract CrowdStrike Falcon OAuth2 API interaction, removing duplicative code and allowing developers to focus on just the logic of their solution requirements. + +This SDK provides two distinct methods for interacting with CrowdStrike's Falcon OAuth2 APIs: + * ***Service classes***, representing a single service collection, with methods defined for every available operation. + * ***The Uber class***, which provides a single harness for interacting with the entire API, covering every available operation within every service collection. + +## Installation & Removal +![PyPI - Status](https://img.shields.io/pypi/status/crowdstrike-falconpy) +![PyPI](https://img.shields.io/pypi/v/crowdstrike-falconpy) +![PyPI - Wheel](https://img.shields.io/pypi/wheel/crowdstrike-falconpy) ![PyPI - Downloads](https://img.shields.io/pypi/dm/crowdstrike-falconpy) -![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20%40CrowdStrike&style=social&url=https%3A%2F%2Ftwitter.com%2FCrowdStrike) - -# FalconPy -FalconPy provides a Python native harness for interacting with the CrowdStrike Falcon OAuth2 API. - -## Why FalconPy -This project contains a collection of Python classes that abstract CrowdStrike Falcon API interaction, removing duplicative code and allowing developers to focus on just the logic of their solution requirements. - -## Contents -Currently the solution defines a class for each service (_ex: cloud_connect_aws_), with endpoint methods defined as class methods. There is also a single _uber_-class that provides an interface to the entire API with a single handler. - -### Available classes -+ [cloud_connect_aws.py](services/cloud_connect_aws.py) - AWS Cloud -+ [detects.py](services/detects.py) - Detections -+ [device_control_policies.py](services/device_control_policies.py) - Device Control -+ [event_streams.py](services/event_streams.py) - Event Streams -+ [falconx_sandbox.py](services/falconx_sandbox.py) - The Falcon Sandbox -+ [firewall_management.py](services/firewall_management.py) - Firewall administration -+ [firewall_policies.py](services/firewall_policies.py) - Firewall policy management -+ [host_group.py](services/host_group.py) - Host groups -+ [hosts.py](services/hosts.py) - Hosts -+ [incidents.py](services/incidents.py) - Incidents -+ [intel.py](services/intel.py) - Threat Intel -+ [iocs.py](services/iocs.py) - Indicators of Compromise -+ [oauth2.py](services/oauth2.py) - OAuth2 authentication -+ [prevention_policy.py](services/prevention_policy.py) - Prevention policies -+ [real_time_response_admin.py](services/real_time_response_admin.py) - Real time response administration -+ [real_time_response.py](services/real_time_response.py) - Real time response -+ [sensor_update_policy.py](services/sensor_update_policy.py) - Sensor policy management -+ [spotlight_vulnerabilities.py](services/spotlight_vulnerabilities.py) - Vulnerabilities -+ [user_management.py](services/user_management.py) - User administration - -### Uber-class -+ [api_complete.py](api_complete.py) - CrowdStrike Falcon API full interface harness - -## Installation -FalconPy is available on PyPI: -```bash -$ python -m pip install falconpy +![CI Tests](https://github.com/CrowdStrike/falconpy/workflows/Python%20package/badge.svg)
+Stable releases of FalconPy are available on the Python Package Index: +```shell +$ python3 -m pip install crowdstrike-falconpy ``` -## Documentation -Documentation can be found in the [GitHub Wiki](https://github.com/CrowdStrike/falconpy/wiki). - -## License -Copyright CrowdStrike 2020 - -By accessing or using this script, sample code, application programming interface, tools, -and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -warrant that You are entering into this Agreement on behalf of a company, organization -or another legal entity (“Entity”) that is currently a customer or partner of -CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -such Entity agrees to be bound by this Agreement. - -CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -free and limited license to access and use the Tools solely for Entity’s internal business -purposes and in accordance with its obligations under any agreement(s) it may have with -CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -right, title and interest in and to the Tools, and all intellectual property rights -embodied therein, and that Entity has no right, title or interest therein except for the -express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -confidential information. - -THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +If you'd like to try the *absolute bleeding edge*, an automated GitHub action releases a test package with every merged pull request containing the string +`[DEPLOY]` in the head of the commit. + +To install this testing version of the package, use the command: +```shell +$ python3 -m pip install -i https://test.pypi.org/simple crowdstrike-falconpy +``` + +To uninstall and remove FalconPy: +```shell +$ python3 -m pip uninstall crowdstrike-falconpy +``` + +# Service classes +| OAuth2-Based API
*(CrowdStrike documentation, requires CrowdStrike customer login)* | Code Location | +|:-|:-| +| CrowdStrike Device Control API | [device_control_policies.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/device_control_policies.py) | +| CrowdStrike Falcon Sandbox API | [falconx_sandbox.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/falconx_sandbox.py) | +| CrowdStrike Sensor Policy Management API | [sensor_update_policy.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/sensor_update_policy.py) | +| CrowdStrike Custom Indicators of Attack (IOAs) APIs | [custom_ioa.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/custom_ioa.py) | +| [CrowdStrike Custom Indicators of Compromise (IOCs) APIs](https://falcon.crowdstrike.com/support/documentation/88/custom-ioc-apis) | [iocs.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/iocs.py) | +| [CrowdStrike Detections APIs](https://falcon.crowdstrike.com/support/documentation/85/detection-and-prevention-policies-apis) | [detects.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/detects.py) | +| [CrowdStrike Event Streams API](https://falcon.crowdstrike.com/support/documentation/89/event-streams-apis)| [event_streams.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/event_streams.py) | +| [CrowdStrike Falcon Horizon APIs](https://falcon.crowdstrike.com/support/documentation/137/falcon-horizon-apis) | [cspm_registration.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/cspm_registration.py) | +| [CrowdStrike Falcon X APIs](https://falcon.crowdstrike.com/support/documentation/92/falcon-x-apis) | [sample_uploads.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/sample_uploads.py)
[quick_scan.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/quick_scan.py)| +| [CrowdStrike Firewall Management API](https://falcon.crowdstrike.com/support/documentation/107/falcon-firewall-management-apis) | [firewall_management.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/firewall_management.py) | +| [CrowdStrike Firewall Policy Management](https://falcon.crowdstrike.com/support/documentation/107/falcon-firewall-management-apis) | [firewall_policies.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/firewall_policies.py) | +| [CrowdStrike Falcon Flight Control APIs](https://falcon.crowdstrike.com/support/documentation/154/flight-control-apis) | *Coming Soon* | +| [CrowdStrike Host Groups API](https://falcon.crowdstrike.com/support/documentation/84/host-and-host-group-management-apis) | [host_group.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/host_group.py) | +| [CrowdStrike Hosts API](https://falcon.crowdstrike.com/support/documentation/84/host-and-host-group-management-apis) | [hosts.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/hosts.py) | +| [CrowdStrike Incident and Detection Monitoring APIs](https://falcon.crowdstrike.com/support/documentation/86/detections-monitoring-apis) | [incidents.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/incidents.py) | +| [CrowdStrike Installation Token APIs](https://falcon.crowdstrike.com/support/documentation/120/Installation-token-APIs) | *Coming Soon* | +| [CrowdStrike Intel API](https://falcon.crowdstrike.com/support/documentation/72/intel-apis) | [intel.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/intel.py) | +| [CrowdStrike MalQuery API](https://falcon.crowdstrike.com/support/documentation/113/malquery-apis) | *Coming Soon* | +| [CrowdStrike OAuth2 Auth Token APIs](https://falcon.crowdstrike.com/support/documentation/93/oauth2-auth-token-apis) | [oauth2.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/oauth2.py) | +| [CrowdStrike Prevention Policy APIs](https://falcon.crowdstrike.com/support/documentation/85/detection-and-prevention-policies-apis) | [prevention_policy.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/prevention_policy.py) | +| [CrowdStrike Real Time Response (RTR) APIs](https://falcon.crowdstrike.com/support/documentation/90/real-time-response-apis) | [real_time_response.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/real_time_response.py) | +| [CrowdStrike Realtime Response (RTR) Administration API](https://falcon.crowdstrike.com/support/documentation/90/real-time-response-apis) | [real_time_response_admin.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/real_time_response_admin.py) | +| [CrowdStrike Sensor Download APIs](https://falcon.crowdstrike.com/support/documentation/109/sensor-download-apis) | [sensor_download.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/sensor_download.py) | +| [CrowdStrike Spotlight APIs](https://falcon.crowdstrike.com/support/documentation/98/spotlight-apis) | [spotlight_vulnerabilities.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/spotlight_vulnerabilities.py) | +| [CrowdStrike User and Roles API](https://falcon.crowdstrike.com/support/documentation/87/users-and-roles-apis) | [user_management.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/user_management.py) | +| [Falcon Discover for Cloud and Containers - AWS Accounts APIs](https://falcon.crowdstrike.com/support/documentation/91/discover-for-aws-apis) | [cloud_connect_aws.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/cloud_connect_aws.py) | +| [Falcon Discover for Cloud and Containers - Azure Subscriptions APIs](https://falcon.crowdstrike.com/support/documentation/118/falcon-discover-for-cloud-and-containers-azure-subscription-apis) | *Coming Soon* | +| [Falcon Discover for Cloud and Containers - GCP Projects APIs](https://falcon.crowdstrike.com/support/documentation/117/falcon-discover-for-cloud-and-containers-gcp-projects-apis) | *Coming Soon* | +| [CrowdStrike Falcon Zero Trust Assessment APIs](https://falcon.crowdstrike.com/support/documentation/156/zero-trust-assessment-apis) | *Coming Soon* | + +# The Uber class ++ [api_complete.py](./src/falconpy/api_complete.py) - The Uber class provides an interface to all CrowdStrike APIs with a single handler. +This solution supports communicating with API endpoints that do not have an available Service Class or are recently released. + +# Contributing +There are *many* ways you can contribute to the FalconPy project! + * ***Providing feedback*** by opening a GitHub ticket. Even a fly-by "Hey, this worked!" is appreciated and helps validate approaches. Ideas on improving the project are most welcome. + * ***Documenting, blogging, or creating videos***, of how you've used FalconPy! This type of content is *invaluable* and helps communities grow. Open a pull request for inclusion in the [Documentation and Collateral](https://github.com/CrowdStrike/falconpy#documentation-and-collateral) section. + * ***Fix a bug or implement a new feature***. Check out our [open issues on GitHub](https://github.com/CrowdStrike/falconpy/issues) for inspiration. + * ***Review pull requests*** by going through the queue of [open pull requests on GitHub](https://github.com/CrowdStrike/falconpy/pulls) and giving feedback to the authors + + > Review [CONTRIBUTING.md](https://github.com/CrowdStrike/falconpy/CONTRIBUTING.md) for more details regarding contributing to the FalconPy project. + +Open to do something else but not sure where to start? Try [opening an issue](https://github.com/CrowdStrike/falconpy/issues/new), or posting a topic in our [discussion board](https://github.com/CrowdStrike/falconpy/discussions), to introduce yourself and your interests. We look forward to chatting with you! + +# Support & Community Forums +FalconPy is an open source project, not a formal CrowdStrike product, to assist developers implement CrowdStrike's APIs within their applications. As such it carries no formal support, express or implied. + +:fire: Is something going wrong? :fire:
+GitHub Issues are used to report bugs. Submit a ticket here:
+[https://github.com/CrowdStrike/falconpy/issues/new/choose](https://github.com/CrowdStrike/falconpy/issues/new/choose) + +GitHub Discussions provide the community with means to communicate. There are four discussion categories: + * :speech_balloon: [**General**](https://github.com/CrowdStrike/falconpy/discussions?discussions_q=category%3AGeneral) : Catch all for general discussions. + * :bulb: [**Ideas**](https://github.com/CrowdStrike/falconpy/discussions?discussions_q=category%3AIdeas): Have a suggestion for a feature request? Is there something the community or project could improve upon? Let us know here. + * :pray: [**Q&A**](https://github.com/CrowdStrike/falconpy/discussions?discussions_q=category%3AQ%26A): Have a question about how to accomplish something? A usability question? Submit them here! + * :raised_hands: [**Show and Tell**](https://github.com/CrowdStrike/falconpy/discussions?discussions_q=category%3A%22Show+and+tell%22): Share with the community what you're up to! Perhaps this is letting everyone know about your upcoming conference talk, share a project that has embedded FalconPy, or your recent blog. + + +# Documentation and Collateral + +## Official Project Documentation +See the wiki for extended documentation: [https://github.com/CrowdStrike/falconpy/wiki](https://github.com/CrowdStrike/falconpy/wiki). + +## Videos (Tutorials, Trainings, Overviews) +*Coming soon*. + +## Conference Presentations +[![API Office Hour 03.23.21](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/api_office_hour_preso_thumbnail.png)](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/falconpy-api-office-hour_customer_presentation.pdf?raw=true) + +## Blogs/Articles/Prose +*Coming soon*. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..be5a90b1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,51 @@ +# Security Policy +This document outlines security policy and procedures for the CrowdStrike `falconpy` project. ++ [Supported Python versions](#supported-python-versions) ++ [Supported FalconPy versions](#supported-falconpy-versions) ++ [Reporting a potential security vulnerability](#reporting-a-potential-security-vulnerability) ++ [Disclosure and Mitigation Process](#disclosure-and-mitigation-process) + +## Supported Python versions + +FalconPy functionality is unit tested to run under the following versions of Python. + +| Version | Supported | +| :------- | :--------- | +| 3.9.x | :white_check_mark: | +| 3.8.x | :white_check_mark: | +| 3.7.x | :white_check_mark: | +| 3.6.x | :white_check_mark: | +| <= 3.5 | :x: | +| <= 2.x.x | :x: | + +This unit testing is performed using Windows, MacOS, and Ubuntu Linux. + +## Supported FalconPy versions + +When discovered, we release security vulnerability patches for the most recent release at an accelerated cadence. + +## Reporting a potential security vulnerability + +We have multiple avenues to receive security-related vulnerability reports. + +Please report suspected security vulnerabilities by: ++ Submitting a [bug](https://github.com/CrowdStrike/falconpy/issues) ++ Starting a new [discussion](https://github.com/CrowdStrike/falconpy/discussions) ++ Submitting a [pull request](https://github.com/CrowdStrike/falconpy/pulls) to potentially resolve the issue ++ Sending an email to __falconpy@crowdstrike.com__. + +## Disclosure and mitigation process + +Upon receiving a security bug report, the issue will be assigned to one of the project maintainers. This person will coordinate the related fix and release +process, involving the following steps: ++ Communicate with you to confirm we have received the report and provide you with a status update. + - You should receive this message within 48 - 72 business hours. ++ Confirmation of the issue and a determination of affected versions. ++ An audit of the codebase to find any potentially similar problems. ++ Preparation of patches for all releases still under maintenance. + - These patches will be submitted as a separate pull request and contain a version update. + - This pull request will be flagged as a security fix. + - Once merged, and after post-merge unit testing has been completed, the patch will be immediately published to both PyPI repositories. + +## Comments +If you have suggestions on how this process could be improved, please let us know by [starting a new discussion](https://github.com/CrowdStrike/falconpy/discussions). diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 00000000..952940bf --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,33 @@ +## Available Classes +- Service Classes + - [Cloud Connect AWS](service-class/cloud-connect-aws.md) + - [Detects](service-class/detects.md) + - [Device Control Policies](service-class/device-control-policies.md) + - [Event Streams](service-class/event-streams.md) + - [FalconX Sandbox](service-class/falconx-sandbox.md) + - [Firewall Management](service-class/firewall-management.md) + - [Host Group](service-class/host-group.md) + - [Hosts](service-class/hosts.md) + - [Incidents](service-class/incidents.md) + - [Intel](service-class/intel.md) + - [IOCs](service-class/iocs.md) + - [OAuth2](service-class/oauth2.md) + - [Prevention Policies](service-class/prevention-policies.md) + - [Realtime Response Admin](service-class/real-time-response-admin.md) + - [Realtime Response](service-class/real-time-response.md) + - [Sensor Update Policies](service-class/sensor-update-policies.md) + - [Spotlight Vulnerabilities](service-class/spotlight-vulnerabilities.md) + - [User Management](service-class/user-management.md) + +- Uber Class + - [CSPM Registration](uber-class/cspm-registration.md) + - [Custom IOA](uber-class/custom-ioa.md) + - [D4C Registration](uber-class/d4c-registration.md) + - [Installation Tokens](uber-class/installation-tokens.md) + - [IOA Exclusions](uber-class/ioa-exclusions.md) + - [MalQuery](uber-class/malquery.md) + - [ML Exclusions](uber-class/ml-exclusions.md) + - [Quick Scan](uber-class/quick-scan.md) + - [Sample Uploads](uber-class/sample-uploads.md) + - [Sensor Download](uber-class/sensor-download.md) + - [Sensor Visibility Exclusions](uber-class/sensor-visibility-exclusions.md) diff --git a/docs/asset/api_office_hour_preso_thumbnail.png b/docs/asset/api_office_hour_preso_thumbnail.png new file mode 100644 index 00000000..007cb7b1 Binary files /dev/null and b/docs/asset/api_office_hour_preso_thumbnail.png differ diff --git a/docs/asset/cs-logo.png b/docs/asset/cs-logo.png new file mode 100644 index 00000000..ada2fc61 Binary files /dev/null and b/docs/asset/cs-logo.png differ diff --git a/docs/asset/csfalcon.png b/docs/asset/csfalcon.png new file mode 100644 index 00000000..3495bd51 Binary files /dev/null and b/docs/asset/csfalcon.png differ diff --git a/docs/asset/falconpy-api-office-hour_customer_presentation.pdf b/docs/asset/falconpy-api-office-hour_customer_presentation.pdf new file mode 100644 index 00000000..c7dcc77e Binary files /dev/null and b/docs/asset/falconpy-api-office-hour_customer_presentation.pdf differ diff --git a/docs/service-class/cloud-connect-aws.md b/docs/service-class/cloud-connect-aws.md new file mode 100644 index 00000000..112204e8 --- /dev/null +++ b/docs/service-class/cloud-connect-aws.md @@ -0,0 +1,523 @@ +# Using the Cloud Connect AWS service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [QueryAWSAccounts](#queryawsaccounts) | Search for provisioned AWS Accounts by providing an FQL filter and paging details. Returns a set of AWS accounts which match the filter criteria | +| [GetAWSSettings](#getawssettings) | Retrieve a set of Global Settings which are applicable to all provisioned AWS accounts | +| [GetAWSAccounts](#getawsaccounts) | Retrieve a set of AWS Accounts by specifying their IDs | +| [ProvisionAWSAccounts](#provisionawsaccounts) | Provision AWS Accounts by specifying details about the accounts to provision | +| [DeleteAWSAccounts](#deleteawsaccounts) | Delete a set of AWS Accounts by specifying their IDs | +| [UpdateAWSAccounts](#updateawsaccounts) | Update AWS Accounts by specifying the ID of the account and details to update | +| [CreateOrUpdateAWSSettings](#createorupdateawssettings) | Create or update Global Settings which are applicable to all provisioned AWS accounts | +| [VerifyAWSAccountAccess](#verifyawsaccountaccess) | Performs an Access Verification check on the specified AWS Account IDs | +| [QueryAWSAccountsForIDs](#queryawsaccountsforids) | Search for provisioned AWS Accounts by providing an FQL filter and paging details. Returns a set of AWS account IDs which match the filter criteria | +### QueryAWSAccounts +Search for provisioned AWS Accounts by providing an FQL filter and paging details. Returns a set of AWS accounts which match the filter criteria + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500]. Defaults to 100. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __sort__ | query | _string_ | The property to sort by (e.g. alias.desc or state.asc) | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + PARAMS = { + 'limit': integer, + 'offset': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.QueryAWSAccounts(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'limit': integer, + 'offset': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('QueryAWSAccounts', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetAWSSettings +Retrieve a set of Global Settings which are applicable to all provisioned AWS accounts + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + response = falcon.GetAWSSettings() + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetAWSSettings') +print(response) +falcon.deauthenticate() +``` +### GetAWSAccounts +Retrieve a set of AWS Accounts by specifying their IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | IDs of accounts to retrieve details | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetAWSAccounts(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetAWSAccounts', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### ProvisionAWSAccounts +Provision AWS Accounts by specifying details about the accounts to provision + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __mode__ | query | _string_ | Mode for provisioning. Allowed values are `manual` or `cloudformation`. Defaults to manual if not defined. | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + PARAMS = { + 'mode': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.ProvisionAWSAccounts(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'mode': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('ProvisionAWSAccounts', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### DeleteAWSAccounts +Delete a set of AWS Accounts by specifying their IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | IDs of accounts to remove | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.DeleteAWSAccounts(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteAWSAccounts', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### UpdateAWSAccounts +Update AWS Accounts by specifying the ID of the account and details to update + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.UpdateAWSAccounts(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateAWSAccounts', body=BODY) +print(response) +falcon.deauthenticate() +``` +### CreateOrUpdateAWSSettings +Create or update Global Settings which are applicable to all provisioned AWS accounts + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.CreateOrUpdateAWSSettings(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateOrUpdateAWSSettings', body=BODY) +print(response) +falcon.deauthenticate() +``` +### VerifyAWSAccountAccess +Performs an Access Verification check on the specified AWS Account IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | IDs of accounts to verify access on | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.VerifyAWSAccountAccess(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('VerifyAWSAccountAccess', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### QueryAWSAccountsForIDs +Search for provisioned AWS Accounts by providing an FQL filter and paging details. Returns a set of AWS account IDs which match the filter criteria + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500]. Defaults to 100. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __sort__ | query | _string_ | The property to sort by (e.g. alias.desc or state.asc) | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import cloud_connect_aws as FalconAWS + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAWS.Cloud_Connect_AWS(access_token=token) + + PARAMS = { + 'limit': integer, + 'offset': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.QueryAWSAccountsForIDs(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'limit': integer, + 'offset': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('QueryAWSAccountsForIDs', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/detects.md b/docs/service-class/detects.md new file mode 100644 index 00000000..f15e4813 --- /dev/null +++ b/docs/service-class/detects.md @@ -0,0 +1,244 @@ +# Using the Detects service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetAggregateDetects](#getaggregatedetects) | Get detect aggregates as specified via json in request body. | +| [UpdateDetectsByIdsV2](#updatedetectsbyidsv2) | Modify the state, assignee, and visibility of detections | +| [GetDetectSummaries](#getdetectsummaries) | View information about detections | +| [QueryDetects](#querydetects) | Search for detection IDs that match a given query | +### GetAggregateDetects +Get detect aggregates as specified via json in request body. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Query criteria and settings | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import detects as FalconDetects + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDetects.Detects(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GetAggregateDetects(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetAggregateDetects', body=BODY) +print(response) +falcon.deauthenticate() +``` +### UpdateDetectsByIdsV2 +Modify the state, assignee, and visibility of detections + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | This endpoint modifies attributes (state and assignee) of detections. This endpoint accepts a query formatted as a JSON array of key-value pairs. You can update one or more attributes one or more detections with a single request. **`assigned_to_uuid` values** A user ID, such as `1234567891234567891` **`ids` values** One or more detection IDs, which you can find with the `/detects/queries/detects/v1` endpoint, the Falcon console, or the Streaming API. **`show_in_ui` values** - `true`: This detection is displayed in Falcon - `false`: This detection is not displayed in Falcon. Most commonly used together with the `status` key's `false_positive` value. **`status` values** - `new` - `in_progress` - `true_positive` - `false_positive` - `ignored` **`comment` values** Optional comment to add to the detection. Comments are displayed with the detection in Falcon and usually used to provide context or notes for other Falcon users. A detection can have multiple comments over time. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import detects as FalconDetects + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDetects.Detects(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.UpdateDetectsByIdsV2(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateDetectsByIdsV2', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetDetectSummaries +View information about detections + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | View key attributes of detections, including the associated host, [disposition](https://falcon.crowdstrike.com/support/documentation/2/query-api-reference#patterndispositionvalue), objective/tactic/technique, adversary, and more. Specify one or more detection IDs (max 1000 per request). Find detection IDs with the `/detects/queries/detects/v1` endpoint, the Falcon console, or the Streaming API. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import detects as FalconDetects + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDetects.Detects(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GetDetectSummaries(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetDetectSummaries', body=BODY) +print(response) +falcon.deauthenticate() +``` +### QueryDetects +Search for detection IDs that match a given query + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The first detection to return, where `0` is the latest detection. Use with the `limit` parameter to manage pagination of results. | +| | __limit__ | query | _integer_ | The maximum number of detections to return in this response (default: 9999; max: 9999). Use with the `offset` parameter to manage pagination of results. | +| | __sort__ | query | _string_ | Sort detections using these options: - `first_behavior`: Timestamp of the first behavior associated with this detection - `last_behavior`: Timestamp of the last behavior associated with this detection - `max_severity`: Highest severity of the behaviors associated with this detection - `max_confidence`: Highest confidence of the behaviors associated with this detection - `adversary_id`: ID of the adversary associated with this detection, if any - `devices.hostname`: Hostname of the host where this detection was detected Sort either `asc` (ascending) or `desc` (descending). For example: `last_behavior|asc` | +| | __filter__ | query | _string_ | Filter detections using a query in Falcon Query Language (FQL) An asterisk wildcard `*` includes all results. Common filter options include: - `status` - `device.device_id` - `max_severity` The full list of valid filter options is extensive. Review it in our [documentation inside the Falcon console](https://falcon.crowdstrike.com/support/documentation/2/query-api-reference#detections_fql). | +| | __q__ | query | _string_ | Search all detection metadata for the provided string | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import detects as FalconDetects + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDetects.Detects(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' + } + + response = falcon.QueryDetects(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' +} + +response = falcon.command('QueryDetects', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/device-control-policies.md b/docs/service-class/device-control-policies.md new file mode 100644 index 00000000..47813e98 --- /dev/null +++ b/docs/service-class/device-control-policies.md @@ -0,0 +1,608 @@ +# Using the Device Control Policies service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [queryCombinedDeviceControlPolicyMembers](#querycombineddevicecontrolpolicymembers) | Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria | +| [queryCombinedDeviceControlPolicies](#querycombineddevicecontrolpolicies) | Search for Device Control Policies in your environment by providing an FQL filter and paging details. Returns a set of Device Control Policies which match the filter criteria | +| [performDeviceControlPoliciesAction](#performdevicecontrolpoliciesaction) | Perform the specified action on the Device Control Policies specified in the request | +| [setDeviceControlPoliciesPrecedence](#setdevicecontrolpoliciesprecedence) | Sets the precedence of Device Control Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence | +| [getDeviceControlPolicies](#getdevicecontrolpolicies) | Retrieve a set of Device Control Policies by specifying their IDs | +| [createDeviceControlPolicies](#createdevicecontrolpolicies) | Create Device Control Policies by specifying details about the policy to create | +| [deleteDeviceControlPolicies](#deletedevicecontrolpolicies) | Delete a set of Device Control Policies by specifying their IDs | +| [updateDeviceControlPolicies](#updatedevicecontrolpolicies) | Update Device Control Policies by specifying the ID of the policy and details to update | +| [queryDeviceControlPolicyMembers](#querydevicecontrolpolicymembers) | Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria | +| [queryDeviceControlPolicies](#querydevicecontrolpolicies) | Search for Device Control Policies in your environment by providing an FQL filter and paging details. Returns a set of Device Control Policy IDs which match the filter criteria | +### queryCombinedDeviceControlPolicyMembers +Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Device Control Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryCombinedDeviceControlPolicyMembers(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedDeviceControlPolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedDeviceControlPolicies +Search for Device Control Policies in your environment by providing an FQL filter and paging details. Returns a set of Device Control Policies which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryCombinedDeviceControlPolicies(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedDeviceControlPolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### performDeviceControlPoliciesAction +Perform the specified action on the Device Control Policies specified in the request + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | The action to perform | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + PARAMS = { + 'action_name': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.performDeviceControlPoliciesAction(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('performDeviceControlPoliciesAction', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### setDeviceControlPoliciesPrecedence +Sets the precedence of Device Control Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.setDeviceControlPoliciesPrecedence(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('setDeviceControlPoliciesPrecedence', body=BODY) +print(response) +falcon.deauthenticate() +``` +### getDeviceControlPolicies +Retrieve a set of Device Control Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Device Control Policies to return | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.getDeviceControlPolicies(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getDeviceControlPolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createDeviceControlPolicies +Create Device Control Policies by specifying details about the policy to create + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.createDeviceControlPolicies(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createDeviceControlPolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteDeviceControlPolicies +Delete a set of Device Control Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Device Control Policies to delete | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.deleteDeviceControlPolicies(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteDeviceControlPolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateDeviceControlPolicies +Update Device Control Policies by specifying the ID of the policy and details to update + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.updateDeviceControlPolicies(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateDeviceControlPolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryDeviceControlPolicyMembers +Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Device Control Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryDeviceControlPolicyMembers(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryDeviceControlPolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryDeviceControlPolicies +Search for Device Control Policies in your environment by providing an FQL filter and paging details. Returns a set of Device Control Policy IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import device_control_policies as FalconDCP + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconDCP.Device_Control_Policies(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryDeviceControlPolicies(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryDeviceControlPolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/event-streams.md b/docs/service-class/event-streams.md new file mode 100644 index 00000000..d3d3823c --- /dev/null +++ b/docs/service-class/event-streams.md @@ -0,0 +1,130 @@ +# Using the Event Streams service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [refreshActiveStreamSession](#refreshactivestreamsession) | Refresh an active event stream. Use the URL shown in a GET /sensors/entities/datafeed/v2 response. | +| [listAvailableStreamsOAuth2](#listavailablestreamsoauth2) | Discover all event streams in your environment | +### refreshActiveStreamSession +Refresh an active event stream. Use the URL shown in a GET /sensors/entities/datafeed/v2 response. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | Action name. Allowed value is refresh_active_stream_session. | +| :white_check_mark: | __appId__ | query | _string_ | Label that identifies your connection. Max: 32 alphanumeric characters (a-z, A-Z, 0-9). | +| :white_check_mark: | __partition__ | path | _integer_ | Partition to request data for. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import event_streams as FalconES + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconES.Event_Streams(access_token=token) + + PARAMS = { + 'action_name': 'string', + 'appId': 'string' + } + + PARTITION = 0 #Refresh the partition we are working with + + response = falcon.refreshActiveStreamSession(parameters=PARAMS, partition=PARTITION) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string', + 'appId': 'string' +} + +PARTITION = 0 #Refresh the partition we are working with + +response = falcon.command('refreshActiveStreamSession', parameters=PARAMS, partition=PARTITION) +print(response) +falcon.deauthenticate() +``` +### listAvailableStreamsOAuth2 +Discover all event streams in your environment + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __appId__ | query | _string_ | Label that identifies your connection. Max: 32 alphanumeric characters (a-z, A-Z, 0-9). | +| | __format__ | query | _string_ | Format for streaming events. Valid values: json, flatjson | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import event_streams as FalconES + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconES.Event_Streams(access_token=token) + + PARAMS = { + 'appId': 'string', + 'format': 'string' + } + + response = falcon.listAvailableStreamsOAuth2(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'appId': 'string', + 'format': 'string' +} + +response = falcon.command('listAvailableStreamsOAuth2', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/falconx-sandbox.md b/docs/service-class/falconx-sandbox.md new file mode 100644 index 00000000..9876faec --- /dev/null +++ b/docs/service-class/falconx-sandbox.md @@ -0,0 +1,750 @@ +# Using the Falconx Sandbox service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetArtifacts](#getartifacts) | Download IOC packs, PCAP files, and other analysis artifacts. | +| [GetSummaryReports](#getsummaryreports) | Get a short summary version of a sandbox report. | +| [GetReports](#getreports) | Get a full sandbox report. | +| [DeleteReport](#deletereport) | Delete report based on the report ID. Operation can be checked for success by polling for the report ID on the report-summaries endpoint. | +| [GetSubmissions](#getsubmissions) | Check the status of a sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. | +| [Submit](#submit) | Submit an uploaded file or a URL for sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. | +| [QueryReports](#queryreports) | Find sandbox reports by providing an FQL filter and paging details. Returns a set of report IDs that match your criteria. | +| [QuerySubmissions](#querysubmissions) | Find submission IDs for uploaded files by providing an FQL filter and paging details. Returns a set of submission IDs that match your criteria. | +| [GetSampleV2](#getsamplev2) | Retrieves the file associated with the given ID (SHA256) | +| [UploadSampleV2](#uploadsamplev2) | Upload a file for sandbox analysis. After uploading, use `/falconx/entities/submissions/v1` to start analyzing the file. | +| [DeleteSampleV2](#deletesamplev2) | Removes a sample, including file, meta and submissions from the collection | +| [QuerySampleV1](#querysamplev1) | Retrieves a list with sha256 of samples that exist and customer has rights to access them, maximum number of accepted items is 200 | +### GetArtifacts +Download IOC packs, PCAP files, and other analysis artifacts. + +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | query | _string_ | ID of an artifact, such as an IOC pack, PCAP file, or actor image. Find an artifact ID in a report or summary. | +| | __name__ | query | _string_ | The name given to your downloaded file. | +| | __Accept-Encoding__ | header | _string_ | Format used to compress your downloaded file. Currently, you must provide the value `gzip`, the only valid format. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + PARAMS = { + 'id': 'string', + 'name': 'string' + } + + HEADERS = { + 'Accept-Encoding': 'string' + } + + response = falcon.GetArtifacts(parameters=PARAMS, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'name': 'string' +} + +HEADERS = { + 'Accept-Encoding': 'string' +} + +response = falcon.command('GetArtifacts', parameters=PARAMS, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### GetSummaryReports +Get a short summary version of a sandbox report. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a summary. Find a summary ID from the response when submitting a malware sample or search with `/falconx/queries/reports/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetSummaryReports(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetSummaryReports', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetReports +Get a full sandbox report. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a report. Find a report ID from the response when submitting a malware sample or search with `/falconx/queries/reports/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetReports(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetReports', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### DeleteReport +Delete report based on the report ID. Operation can be checked for success by polling for the report ID on the report-summaries endpoint. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | ID of a report. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.DeleteReport(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteReport', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetSubmissions +Check the status of a sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a submitted malware sample. Find a submission ID from the response when submitting a malware sample or search with `/falconx/queries/submissions/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetSubmissions(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetSubmissions', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### Submit +Submit an uploaded file or a URL for sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Submit either a URL or a sample SHA256 for sandbox analysis. The sample file must have been previously uploaded through `/samples/entities/samples/v2`. You must specify a JSON object that includes the `falconx.SubmissionParametersV1` key/value pairs shown below. **`environment_id`**: Specifies the sandbox environment used for analysis. Values: - `300`: Linux Ubuntu 16.04, 64-bit - `200`: Android (static analysis) - `160`: Windows 10, 64-bit - `110`: Windows 7, 64-bit - `100`: Windows 7, 32-bit **`sha256`** ID of the sample, which is a SHA256 hash value. Find a sample ID from the response when uploading a malware sample or search with `/falconx/queries/submissions/v1`.The `url` parameter must be unset if `sha256` is used. **`url`** A web page or file URL. It can be HTTP(S) or FTP. The `sha256` parameter must be unset if `url` is used. **`action_script`** (optional): Runtime script for sandbox analysis. Values: - `default` - `default_maxantievasion` - `default_randomfiles` - `default_randomtheme` - `default_openie` **`command_line`** (optional): Command line script passed to the submitted file at runtime. Max length: 2048 characters **`document_password`** (optional): Auto-filled for Adobe or Office files that prompt for a password. Max length: 32 characters **`enable_tor`** (optional): If `true`, sandbox analysis routes network traffic via TOR. Default: `false`. **`submit_name`** (optional): Name of the malware sample that's used for file type detection and analysis **`system_date`** (optional): Set a custom date in the format `yyyy-MM-dd` for the sandbox environment **`system_time`** (optional): Set a custom time in the format `HH:mm` for the sandbox environment. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.Submit(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('Submit', body=BODY) +print(response) +falcon.deauthenticate() +``` +### QueryReports +Find sandbox reports by providing an FQL filter and paging details. Returns a set of report IDs that match your criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | The offset to start retrieving reports from. | +| | __limit__ | query | _integer_ | Maximum number of report IDs to return. Max: 5000. | +| | __sort__ | query | _string_ | Sort order: `asc` or `desc`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.QueryReports(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('QueryReports', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QuerySubmissions +Find submission IDs for uploaded files by providing an FQL filter and paging details. Returns a set of submission IDs that match your criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | The offset to start retrieving submissions from. | +| | __limit__ | query | _integer_ | Maximum number of submission IDs to return. Max: 5000. | +| | __sort__ | query | _string_ | Sort order: `asc` or `desc`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.QuerySubmissions(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('QuerySubmissions', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetSampleV2 +Retrieves the file associated with the given ID (SHA256) + +#### Content-Type +- Produces: _application/octet-stream_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __ids__ | query | _string_ | The file SHA256. | +| | __password_protected__ | query | _string_ | Flag whether the sample should be zipped and password protected with pass='infected' | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + PARAMS = { + 'password_protected': 'string' + } + + HEADERS = { + 'X-CS-USERUUID': 'string' + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetSampleV2(parameters=PARAMS, headers=HEADERS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'password_protected': 'string' +} + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetSampleV2', parameters=PARAMS, headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### UploadSampleV2 +Upload a file for sandbox analysis. After uploading, use `/falconx/entities/submissions/v1` to start analyzing the file. + +#### Content-Type +- Consumes: _application/octet-stream_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __body__ | body | _string_ | Content of the uploaded sample in binary format. For example, use `--data-binary @$FILE_PATH` when using cURL. Max file size: 100 MB. Accepted file formats: - Portable executables: `.exe`, `.scr`, `.pif`, `.dll`, `.com`, `.cpl`, etc. - Office documents: `.doc`, `.docx`, `.ppt`, `.pps`, `.pptx`, `.ppsx`, `.xls`, `.xlsx`, `.rtf`, `.pub` - PDF - APK - Executable JAR - Windows script component: `.sct` - Windows shortcut: `.lnk` - Windows help: `.chm` - HTML application: `.hta` - Windows script file: `.wsf` - Javascript: `.js` - Visual Basic: `.vbs`, `.vbe` - Shockwave Flash: `.swf` - Perl: `.pl` - Powershell: `.ps1`, `.psd1`, `.psm1` - Scalable vector graphics: `.svg` - Python: `.py` - Linux ELF executables - Email files: MIME RFC 822 `.eml`, Outlook `.msg`. | +| :white_check_mark: | __upfile__ | formData | _file_ | The binary file. | +| :white_check_mark: | __file_name__ | query | _string_ | Name of the file. | +| | __comment__ | query | _string_ | A descriptive comment to identify the file for other users. | +| | __is_confidential__ | query | _boolean_ | Defines visibility of this file in Falcon MalQuery, either via the API or the Falcon console. - `true`: File is only shown to users within your customer account - `false`: File can be seen by other CrowdStrike customers Default: `true`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + PARAMS = { + 'file_name': 'string', + 'comment': 'string', + 'is_confidential': boolean + } + + BODY = { + 'Body Payload': 'See body description above' + } + + FILENAME = 'testfile.jpg' + PAYLOAD = open(FILENAME, 'rb').read() + + HEADERS = { + 'X-CS-USERUUID': 'string' + } + + response = falcon.UploadSampleV2(parameters=PARAMS, body=BODY, data=PAYLOAD, file_name=FILENAME, content_type='application/octet-stream', headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'file_name': 'string', + 'comment': 'string', + 'is_confidential': boolean +} + +BODY = { + 'Body Payload': 'See body description above' +} + +FILENAME = 'testfile.jpg' +PAYLOAD = open(FILENAME, 'rb').read() + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +response = falcon.command('UploadSampleV2', parameters=PARAMS, body=BODY, data=PAYLOAD, file_name=FILENAME, content_type='application/octet-stream', headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### DeleteSampleV2 +Removes a sample, including file, meta and submissions from the collection + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __ids__ | query | _string_ | The file SHA256. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + HEADERS = { + 'X-CS-USERUUID': 'string' + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.DeleteSampleV2(headers=HEADERS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteSampleV2', headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### QuerySampleV1 +Retrieves a list with sha256 of samples that exist and customer has rights to access them, maximum number of accepted items is 200 + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __body__ | body | _string_ | Pass a list of sha256s to check if the exist. It will be returned the list of existing hashes. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import falconx_sandbox as FalconX + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconX.FalconX_Sandbox(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + HEADERS = { + 'X-CS-USERUUID': 'string' + } + + response = falcon.QuerySampleV1(body=BODY, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +response = falcon.command('QuerySampleV1', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/firewall-management.md b/docs/service-class/firewall-management.md new file mode 100644 index 00000000..0b961efb --- /dev/null +++ b/docs/service-class/firewall-management.md @@ -0,0 +1,1238 @@ +# Using the Firewall Management service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [aggregate_events](#aggregate-events) | Aggregate events for customer | +| [aggregate_policy_rules](#aggregate-policy-rules) | Aggregate rules within a policy for customer | +| [aggregate_rule_groups](#aggregate-rule-groups) | Aggregate rule groups for customer | +| [aggregate_rules](#aggregate-rules) | Aggregate rules for customer | +| [get_events](#get-events) | Get events entities by ID and optionally version | +| [get_firewall_fields](#get-firewall-fields) | Get the firewall field specifications by ID | +| [get_platforms](#get-platforms) | Get platforms by ID, e.g., windows or mac or droid | +| [get_policy_containers](#get-policy-containers) | Get policy container entities by policy ID | +| [update_policy_container](#update-policy-container) | Update an identified policy container | +| [get_rule_groups](#get-rule-groups) | Get rule group entities by ID. These groups do not contain their rule entities, just the rule IDs in precedence order. | +| [create_rule_group](#create-rule-group) | Create new rule group on a platform for a customer with a name and description, and return the ID | +| [delete_rule_groups](#delete-rule-groups) | Delete rule group entities by ID | +| [update_rule_group](#update-rule-group) | Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules | +| [get_rules](#get-rules) | Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string) | +| [query_events](#query-events) | Find all event IDs matching the query with filter | +| [query_firewall_fields](#query-firewall-fields) | Get the firewall field specification IDs for the provided platform | +| [query_platforms](#query-platforms) | Get the list of platform names | +| [query_policy_rules](#query-policy-rules) | Find all firewall rule IDs matching the query with filter, and return them in precedence order | +| [query_rule_groups](#query-rule-groups) | Find all rule group IDs matching the query with filter | +| [query_rules](#query-rules) | Find all rule IDs matching the query with filter | +### aggregate_events +Aggregate events for customer + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Query criteria and settings | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.aggregate-events(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('aggregate-events', body=BODY) +print(response) +falcon.deauthenticate() +``` +### aggregate_policy_rules +Aggregate rules within a policy for customer + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Query criteria and settings | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.aggregate-policy-rules(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('aggregate-policy-rules', body=BODY) +print(response) +falcon.deauthenticate() +``` +### aggregate_rule_groups +Aggregate rule groups for customer + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Query criteria and settings | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.aggregate-rule-groups(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('aggregate-rule-groups', body=BODY) +print(response) +falcon.deauthenticate() +``` +### aggregate_rules +Aggregate rules for customer + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Query criteria and settings | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.aggregate-rules(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('aggregate-rules', body=BODY) +print(response) +falcon.deauthenticate() +``` +### get_events +Get events entities by ID and optionally version + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The events to retrieve, identified by ID | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-events(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-events', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_firewall_fields +Get the firewall field specifications by ID + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the rule types to retrieve | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-firewall-fields(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-firewall-fields', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_platforms +Get platforms by ID, e.g., windows or mac or droid + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the platforms to retrieve | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-platforms(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-platforms', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_policy_containers +Get policy container entities by policy ID + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The policy container(s) to retrieve, identified by policy ID | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-policy-containers(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-policy-containers', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### update_policy_container +Update an identified policy container + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user id | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + HEADERS = { + 'X-CS-USERNAME': 'string' + } + + response = falcon.update-policy-container(body=BODY, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('update-policy-container', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### get_rule_groups +Get rule group entities by ID. These groups do not contain their rule entities, just the rule IDs in precedence order. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the rule groups to retrieve | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-rule-groups(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-rule-groups', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### create_rule_group +Create new rule group on a platform for a customer with a name and description, and return the ID + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user id | +| | __clone_id__ | query | _string_ | A rule group ID from which to copy rules. If this is provided then the 'rules' property of the body is ignored. | +| | __library__ | query | _string_ | If this flag is set to true then the rules will be cloned from the clone_id from the CrowdStrike Firewall Rule Groups Library. | +| | __comment__ | query | _string_ | Audit log comment for this action | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'clone_id': 'string', + 'library': 'string', + 'comment': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + HEADERS = { + 'X-CS-USERNAME': 'string' + } + + response = falcon.create-rule-group(parameters=PARAMS, body=BODY, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'clone_id': 'string', + 'library': 'string', + 'comment': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('create-rule-group', parameters=PARAMS, body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### delete_rule_groups +Delete rule group entities by ID + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user id | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the rule groups to be deleted | +| | __comment__ | query | _string_ | Audit log comment for this action | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'comment': 'string' + } + + HEADERS = { + 'X-CS-USERNAME': 'string' + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.delete-rule-groups(parameters=PARAMS, headers=HEADERS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('delete-rule-groups', parameters=PARAMS, headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### update_rule_group +Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user id | +| | __comment__ | query | _string_ | Audit log comment for this action | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'comment': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + HEADERS = { + 'X-CS-USERNAME': 'string' + } + + response = falcon.update-rule-group(parameters=PARAMS, body=BODY, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('update-rule-group', parameters=PARAMS, body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### get_rules +Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string) + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The rules to retrieve, identified by ID | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.get-rules(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-rules', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### query_events +Find all event IDs matching the query with filter + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: enabled, platform, name, description, etc TODO. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields, plus TODO | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __after__ | query | _string_ | A pagination token used with the `limit` parameter to manage pagination of results. On your first request, don't provide an `after` token. On subsequent requests, provide the `after` token from the previous response to continue from that place in the results. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer + } + + response = falcon.query-events(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer +} + +response = falcon.command('query-events', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_firewall_fields +Get the firewall field specification IDs for the provided platform + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __platform_id__ | query | _string_ | Get fields configuration for this platform | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'platform_id': 'string', + 'offset': 'string', + 'limit': integer + } + + response = falcon.query-firewall-fields(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'platform_id': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-firewall-fields', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_platforms +Get the list of platform names + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'offset': 'string', + 'limit': integer + } + + response = falcon.query-platforms(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-platforms', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_policy_rules +Find all firewall rule IDs matching the query with filter, and return them in precedence order + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the policy container within which to query | +| | __sort__ | query | _string_ | Possible order by fields: | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: enabled, platform, name, description, etc TODO. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields, plus TODO | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'id': 'string', + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'limit': integer + } + + response = falcon.query-policy-rules(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-policy-rules', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rule_groups +Find all rule group IDs matching the query with filter + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: enabled, platform, name, description, etc TODO. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields, plus TODO | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __after__ | query | _string_ | A pagination token used with the `limit` parameter to manage pagination of results. On your first request, don't provide an `after` token. On subsequent requests, provide the `after` token from the previous response to continue from that place in the results. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer + } + + response = falcon.query-rule-groups(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer +} + +response = falcon.command('query-rule-groups', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rules +Find all rule IDs matching the query with filter + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: enabled, platform, name, description, etc TODO. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields, plus TODO | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __after__ | query | _string_ | A pagination token used with the `limit` parameter to manage pagination of results. On your first request, don't provide an `after` token. On subsequent requests, provide the `after` token from the previous response to continue from that place in the results. | +| | __limit__ | query | _integer_ | Number of ids to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import firewall_management as FalconFM + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconFM.Firewall_Management(access_token=token) + + PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer + } + + response = falcon.query-rules(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'after': 'string', + 'limit': integer +} + +response = falcon.command('query-rules', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/host-group.md b/docs/service-class/host-group.md new file mode 100644 index 00000000..bc782a72 --- /dev/null +++ b/docs/service-class/host-group.md @@ -0,0 +1,552 @@ +# Using the Host Group service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [queryCombinedGroupMembers](#querycombinedgroupmembers) | Search for members of a Host Group in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria | +| [queryCombinedHostGroups](#querycombinedhostgroups) | Search for Host Groups in your environment by providing an FQL filter and paging details. Returns a set of Host Groups which match the filter criteria | +| [performGroupAction](#performgroupaction) | Perform the specified action on the Host Groups specified in the request | +| [getHostGroups](#gethostgroups) | Retrieve a set of Host Groups by specifying their IDs | +| [createHostGroups](#createhostgroups) | Create Host Groups by specifying details about the group to create | +| [deleteHostGroups](#deletehostgroups) | Delete a set of Host Groups by specifying their IDs | +| [updateHostGroups](#updatehostgroups) | Update Host Groups by specifying the ID of the group and details to update | +| [queryGroupMembers](#querygroupmembers) | Search for members of a Host Group in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria | +| [queryHostGroups](#queryhostgroups) | Search for Host Groups in your environment by providing an FQL filter and paging details. Returns a set of Host Group IDs which match the filter criteria | +### queryCombinedGroupMembers +Search for members of a Host Group in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Host Group to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryCombinedGroupMembers(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedGroupMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedHostGroups +Search for Host Groups in your environment by providing an FQL filter and paging details. Returns a set of Host Groups which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryCombinedHostGroups(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedHostGroups', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### performGroupAction +Perform the specified action on the Host Groups specified in the request + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | The action to perform | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + PARAMS = { + 'action_name': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.performGroupAction(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('performGroupAction', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### getHostGroups +Retrieve a set of Host Groups by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Host Groups to return | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.getHostGroups(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getHostGroups', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createHostGroups +Create Host Groups by specifying details about the group to create + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.createHostGroups(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createHostGroups', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteHostGroups +Delete a set of Host Groups by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Host Groups to delete | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.deleteHostGroups(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteHostGroups', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateHostGroups +Update Host Groups by specifying the ID of the group and details to update + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.updateHostGroups(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateHostGroups', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryGroupMembers +Search for members of a Host Group in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Host Group to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryGroupMembers(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryGroupMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryHostGroups +Search for Host Groups in your environment by providing an FQL filter and paging details. Returns a set of Host Group IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import host_group as FalconHG + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHG.Host_Group(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' + } + + response = falcon.queryHostGroups(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryHostGroups', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/hosts.md b/docs/service-class/hosts.md new file mode 100644 index 00000000..a7148596 --- /dev/null +++ b/docs/service-class/hosts.md @@ -0,0 +1,318 @@ +# Using the Hosts service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [PerformActionV2](#performactionv2) | Take various actions on the hosts in your environment. Contain or lift containment on a host. Delete or restore a host. | +| [GetDeviceDetails](#getdevicedetails) | Get details on one or more hosts by providing agent IDs (AID). You can get a host's agent IDs (AIDs) from the /devices/queries/devices/v1 endpoint, the Falcon console or the Streaming API | +| [QueryHiddenDevices](#queryhiddendevices) | Retrieve hidden hosts that match the provided filter criteria. | +| [QueryDevicesByFilterScroll](#querydevicesbyfilterscroll) | Search for hosts in your environment by platform, hostname, IP, and other criteria with continuous pagination capability (based on offset pointer which expires after 2 minutes with no maximum limit) | +| [QueryDevicesByFilter](#querydevicesbyfilter) | Search for hosts in your environment by platform, hostname, IP, and other criteria. | +### PerformActionV2 +Take various actions on the hosts in your environment. Contain or lift containment on a host. Delete or restore a host. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | Specify one of these actions: - `contain` - This action contains the host, which stops any network communications to locations other than the CrowdStrike cloud and IPs specified in your [containment policy](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#containmentpolicy) - `lift_containment`: This action lifts containment on the host, which returns its network communications to normal - `hide_host`: This action will delete a host. After the host is deleted, no new detections for that host will be reported via UI or APIs - `unhide_host`: This action will restore a host. Detection reporting will resume after the host is restored | +| :white_check_mark: | __body__ | body | _string_ | The host agent ID (AID) of the host you want to contain. Get an agent ID from a detection, the Falcon console, or the Streaming API. Provide the ID in JSON format with the key `ids` and the value in square brackets, such as: `"ids": ["123456789"]` | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHosts.Hosts(access_token=token) + + PARAMS = { + 'action_name': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.PerformActionV2(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PerformActionV2', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetDeviceDetails +Get details on one or more hosts by providing agent IDs (AID). You can get a host's agent IDs (AIDs) from the /devices/queries/devices/v1 endpoint, the Falcon console or the Streaming API + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The host agentIDs used to get details on | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHosts.Hosts(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetDeviceDetails(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetDeviceDetails', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### QueryHiddenDevices +Retrieve hidden hosts that match the provided filter criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by (e.g. status.desc or hostname.asc) | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHosts.Hosts(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.QueryHiddenDevices(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('QueryHiddenDevices', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryDevicesByFilterScroll +Search for hosts in your environment by platform, hostname, IP, and other criteria with continuous pagination capability (based on offset pointer which expires after 2 minutes with no maximum limit) + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | The offset to page from, for the next result set | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by (e.g. status.desc or hostname.asc) | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHosts.Hosts(access_token=token) + + PARAMS = { + 'offset': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.QueryDevicesByFilterScroll(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('QueryDevicesByFilterScroll', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryDevicesByFilter +Search for hosts in your environment by platform, hostname, IP, and other criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by (e.g. status.desc or hostname.asc) | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconHosts.Hosts(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.QueryDevicesByFilter(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('QueryDevicesByFilter', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/incidents.md b/docs/service-class/incidents.md new file mode 100644 index 00000000..8f54cd16 --- /dev/null +++ b/docs/service-class/incidents.md @@ -0,0 +1,374 @@ +# Using the Incidents service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [CrowdScore](#crowdscore) | Query environment wide CrowdScore and return the entity data | +| [GetBehaviors](#getbehaviors) | Get details on behaviors by providing behavior IDs | +| [PerformIncidentAction](#performincidentaction) | Perform a set of actions on one or more incidents, such as adding tags or comments or updating the incident name or description | +| [GetIncidents](#getincidents) | Get details on incidents by providing incident IDs | +| [QueryBehaviors](#querybehaviors) | Search for behaviors by providing an FQL filter, sorting, and paging details | +| [QueryIncidents](#queryincidents) | Search for incidents by providing an FQL filter, sorting, and paging details | +### CrowdScore +Query environment wide CrowdScore and return the entity data + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | The maximum records to return. [1-2500] | +| | __sort__ | query | _string_ | The property to sort on, followed by a dot (.), followed by the sort direction, either "asc" or "desc". | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.CrowdScore(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('CrowdScore', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetBehaviors +Get details on behaviors by providing behavior IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GetBehaviors(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetBehaviors', body=BODY) +print(response) +falcon.deauthenticate() +``` +### PerformIncidentAction +Perform a set of actions on one or more incidents, such as adding tags or comments or updating the incident name or description + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.PerformIncidentAction(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PerformIncidentAction', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetIncidents +Get details on incidents by providing incident IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GetIncidents(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetIncidents', body=BODY) +print(response) +falcon.deauthenticate() +``` +### QueryBehaviors +Search for behaviors by providing an FQL filter, sorting, and paging details + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500] | +| | __sort__ | query | _string_ | The property to sort on, followed by a dot (.), followed by the sort direction, either "asc" or "desc". | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.QueryBehaviors(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('QueryBehaviors', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIncidents +Search for incidents by providing an FQL filter, sorting, and paging details + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | The property to sort on, followed by a dot (.), followed by the sort direction, either "asc" or "desc". | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500] | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import incidents as FalconIncidents + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIncidents.Incidents(access_token=token) + + PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'offset': 'string', + 'limit': integer + } + + response = falcon.QueryIncidents(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('QueryIncidents', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/intel.md b/docs/service-class/intel.md new file mode 100644 index 00000000..a678890c --- /dev/null +++ b/docs/service-class/intel.md @@ -0,0 +1,973 @@ +# Using the Intel service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [QueryIntelActorEntities](#queryintelactorentities) | Get info about actors that match provided FQL filters. | +| [QueryIntelIndicatorEntities](#queryintelindicatorentities) | Get info about indicators that match provided FQL filters. | +| [QueryIntelReportEntities](#queryintelreportentities) | Get info about reports that match provided FQL filters. | +| [GetIntelActorEntities](#getintelactorentities) | Retrieve specific actors using their actor IDs. | +| [GetIntelIndicatorEntities](#getintelindicatorentities) | Retrieve specific indicators using their indicator IDs. | +| [GetIntelReportPDF](#getintelreportpdf) | Return a Report PDF attachment | +| [GetIntelReportEntities](#getintelreportentities) | Retrieve specific reports using their report IDs. | +| [GetIntelRuleFile](#getintelrulefile) | Download earlier rule sets. | +| [GetLatestIntelRuleFile](#getlatestintelrulefile) | Download the latest rule set. | +| [GetIntelRuleEntities](#getintelruleentities) | Retrieve details for rule sets for the specified ids. | +| [QueryIntelActorIds](#queryintelactorids) | Get actor IDs that match provided FQL filters. | +| [QueryIntelIndicatorIds](#queryintelindicatorids) | Get indicators IDs that match provided FQL filters. | +| [QueryIntelReportIds](#queryintelreportids) | Get report IDs that match provided FQL filters. | +| [QueryIntelRuleIds](#queryintelruleids) | Search for rule IDs that match provided filter criteria. | +### QueryIntelActorEntities +Get info about actors that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return actors from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of actors to return. The value must be between 1 and 5000. | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: created_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: actors, actors.id, actors.name, actors.slug, actors.url, created_date, description, id, last_modified_date, motivations, motivations.id, motivations.slug, motivations.value, name, name.raw, short_description, slug, sub_type, sub_type.id, sub_type.name, sub_type.slug, tags, tags.id, tags.slug, tags.value, target_countries, target_countries.id, target_countries.slug, target_countries.value, target_industries, target_industries.id, target_industries.slug, target_industries.value, type, type.id, type.name, type.slug, url. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +| | __fields__ | query | array (_string_) | The fields to return, or a predefined set of fields in the form of the collection name surrounded by two underscores like: ____. Ex: slug __full__. Defaults to __basic__. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'fields': [ + 'string', + 'string' + ] + } + + response = falcon.QueryIntelActorEntities(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'fields': [ + 'string', + 'string' + ] +} + +response = falcon.command('QueryIntelActorEntities', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelIndicatorEntities +Get info about indicators that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return indicators from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of indicators to return. The number must be between 1 and 50000 | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: published_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: _marker, actors, deleted, domain_types, id, indicator, ip_address_types, kill_chains, labels, labels.created_on, labels.last_valid_on, labels.name, last_updated, malicious_confidence, malware_families, published_date, reports, targets, threat_types, type, vulnerabilities. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +| | __include_deleted__ | query | _boolean_ | If true, include both published and deleted indicators in the response. Defaults to false. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'include_deleted': boolean + } + + response = falcon.QueryIntelIndicatorEntities(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'include_deleted': boolean +} + +response = falcon.command('QueryIntelIndicatorEntities', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelReportEntities +Get info about reports that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return reports from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of reports to return. The value must be between 1 and 5000. | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: created_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: actors, actors.id, actors.name, actors.slug, actors.url, created_date, description, id, last_modified_date, motivations, motivations.id, motivations.slug, motivations.value, name, name.raw, short_description, slug, sub_type, sub_type.id, sub_type.name, sub_type.slug, tags, tags.id, tags.slug, tags.value, target_countries, target_countries.id, target_countries.slug, target_countries.value, target_industries, target_industries.id, target_industries.slug, target_industries.value, type, type.id, type.name, type.slug, url. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +| | __fields__ | query | array (_string_) | The fields to return, or a predefined set of fields in the form of the collection name surrounded by two underscores like: ____. Ex: slug __full__. Defaults to __basic__. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'fields': [ + 'string', + 'string' + ] + } + + response = falcon.QueryIntelReportEntities(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'fields': [ + 'string', + 'string' + ] +} + +response = falcon.command('QueryIntelReportEntities', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetIntelActorEntities +Retrieve specific actors using their actor IDs. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the actors you want to retrieve. | +| | __fields__ | query | array (_string_) | The fields to return, or a predefined set of fields in the form of the collection name surrounded by two underscores like: ____. Ex: slug __full__. Defaults to __basic__. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'fields': [ + 'string', + 'string' + ] + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetIntelActorEntities(parameters=PARAMS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'fields': [ + 'string', + 'string' + ] +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetIntelActorEntities', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetIntelIndicatorEntities +Retrieve specific indicators using their indicator IDs. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GetIntelIndicatorEntities(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetIntelIndicatorEntities', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetIntelReportPDF +Return a Report PDF attachment + +#### Content-Type +- Produces: _application/octet-stream_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | query | _string_ | The ID of the report you want to download as a PDF. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'id': 'string' + } + + response = falcon.GetIntelReportPDF(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string' +} + +response = falcon.command('GetIntelReportPDF', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetIntelReportEntities +Retrieve specific reports using their report IDs. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the reports you want to retrieve. | +| | __fields__ | query | array (_string_) | The fields to return, or a predefined set of fields in the form of the collection name surrounded by two underscores like: ____. Ex: slug __full__. Defaults to __basic__. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'fields': [ + 'string', + 'string' + ] + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetIntelReportEntities(parameters=PARAMS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'fields': [ + 'string', + 'string' + ] +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetIntelReportEntities', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetIntelRuleFile +Download earlier rule sets. + +#### Content-Type +- Produces: _application/zip_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __Accept__ | header | _string_ | Choose the format you want the rule set in. | +| :white_check_mark: | __id__ | query | _integer_ | The ID of the rule set. | +| | __format__ | query | _string_ | Choose the format you want the rule set in. Valid formats are zip and gzip. Defaults to zip. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'id': integer, + 'format': 'string' + } + + HEADERS = { + 'Accept': 'string' + } + + response = falcon.GetIntelRuleFile(parameters=PARAMS, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': integer, + 'format': 'string' +} + +HEADERS = { + 'Accept': 'string' +} + +response = falcon.command('GetIntelRuleFile', parameters=PARAMS, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### GetLatestIntelRuleFile +Download the latest rule set. + +#### Content-Type +- Produces: _application/zip_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __Accept__ | header | _string_ | Choose the format you want the rule set in. | +| :white_check_mark: | __type__ | query | _string_ | The rule news report type. Accepted values: snort-suricata-master snort-suricata-update snort-suricata-changelog yara-master yara-update yara-changelog common-event-format netwitness | +| | __format__ | query | _string_ | Choose the format you want the rule set in. Valid formats are zip and gzip. Defaults to zip. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'type': 'string', + 'format': 'string' + } + + HEADERS = { + 'Accept': 'string' + } + + response = falcon.GetLatestIntelRuleFile(parameters=PARAMS, headers=HEADERS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'format': 'string' +} + +HEADERS = { + 'Accept': 'string' +} + +response = falcon.command('GetLatestIntelRuleFile', parameters=PARAMS, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### GetIntelRuleEntities +Retrieve details for rule sets for the specified ids. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of rules to return. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetIntelRuleEntities(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetIntelRuleEntities', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelActorIds +Get actor IDs that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return actors IDs from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of actor IDs to return. The value must be between 1 and 5000. | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: created_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: actors, actors.id, actors.name, actors.slug, actors.url, created_date, description, id, last_modified_date, motivations, motivations.id, motivations.slug, motivations.value, name, name.raw, short_description, slug, sub_type, sub_type.id, sub_type.name, sub_type.slug, tags, tags.id, tags.slug, tags.value, target_countries, target_countries.id, target_countries.slug, target_countries.value, target_industries, target_industries.id, target_industries.slug, target_industries.value, type, type.id, type.name, type.slug, url. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' + } + + response = falcon.QueryIntelActorIds(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' +} + +response = falcon.command('QueryIntelActorIds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelIndicatorIds +Get indicators IDs that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return indicator IDs from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of indicator IDs to return. The number must be between 1 and 50000 | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: published_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: _marker, actors, deleted, domain_types, id, indicator, ip_address_types, kill_chains, labels, labels.created_on, labels.last_valid_on, labels.name, last_updated, malicious_confidence, malware_families, published_date, reports, targets, threat_types, type, vulnerabilities. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +| | __include_deleted__ | query | _boolean_ | If true, include both published and deleted indicators in the response. Defaults to false. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'include_deleted': boolean + } + + response = falcon.QueryIntelIndicatorIds(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'include_deleted': boolean +} + +response = falcon.command('QueryIntelIndicatorIds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelReportIds +Get report IDs that match provided FQL filters. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return report IDs from. Defaults to 0. | +| | __limit__ | query | _integer_ | Set the number of report IDs to return. The value must be between 1 and 5000. | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: created_date|asc. | +| | __filter__ | query | _string_ | Filter your query by specifying FQL filter parameters. Filter parameters include: actors, actors.id, actors.name, actors.slug, actors.url, created_date, description, id, last_modified_date, motivations, motivations.id, motivations.slug, motivations.value, name, name.raw, short_description, slug, sub_type, sub_type.id, sub_type.name, sub_type.slug, tags, tags.id, tags.slug, tags.value, target_countries, target_countries.id, target_countries.slug, target_countries.value, target_industries, target_industries.id, target_industries.slug, target_industries.value, type, type.id, type.name, type.slug, url. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' + } + + response = falcon.QueryIntelReportIds(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string', + 'q': 'string' +} + +response = falcon.command('QueryIntelReportIds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIntelRuleIds +Search for rule IDs that match provided filter criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | Set the starting row number to return reports from. Defaults to 0. | +| | __limit__ | query | _integer_ | The number of rule IDs to return. Defaults to 10. | +| | __sort__ | query | _string_ | Order fields in ascending or descending order. Ex: created_date|asc. | +| | __name__ | query | array (_string_) | Search by rule title. | +| :white_check_mark: | __type__ | query | _string_ | The rule news report type. Accepted values: snort-suricata-master snort-suricata-update snort-suricata-changelog yara-master yara-update yara-changelog common-event-format netwitness | +| | __description__ | query | array (_string_) | Substring match on description field. | +| | __tags__ | query | array (_string_) | Search for rule tags. | +| | __min_created_date__ | query | _integer_ | Filter results to those created on or after a certain date. | +| | __max_created_date__ | query | _string_ | Filter results to those created on or before a certain date. | +| | __q__ | query | _string_ | Perform a generic substring search across all fields. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import intel as FalconIntel + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIntel.Intel(access_token=token) + + PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'name': [ + 'string', + 'string' + ], + 'type': 'string', + 'description': [ + 'string', + 'string' + ], + 'tags': [ + 'string', + 'string' + ], + 'min_created_date': integer, + 'max_created_date': 'string', + 'q': 'string' + } + + response = falcon.QueryIntelRuleIds(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'name': [ + 'string', + 'string' + ], + 'type': 'string', + 'description': [ + 'string', + 'string' + ], + 'tags': [ + 'string', + 'string' + ], + 'min_created_date': integer, + 'max_created_date': 'string', + 'q': 'string' +} + +response = falcon.command('QueryIntelRuleIds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/iocs.md b/docs/service-class/iocs.md new file mode 100644 index 00000000..d9c28fcf --- /dev/null +++ b/docs/service-class/iocs.md @@ -0,0 +1,582 @@ +# Using the IOCs service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [DevicesCount](#devicescount) | Number of hosts in your customer account that have observed a given custom IOC | +| [GetIOC](#getioc) | Get an IOC by providing a type and value | +| [CreateIOC](#createioc) | Create a new IOC | +| [DeleteIOC](#deleteioc) | Delete an IOC by providing a type and value | +| [UpdateIOC](#updateioc) | Update an IOC by providing a type and value | +| [DevicesRanOn](#devicesranon) | Find hosts that have observed a given custom IOC. For details about those hosts, use GET /devices/entities/devices/v1 | +| [QueryIOCs](#queryiocs) | Search the custom IOCs in your customer account | +| [ProcessesRanOn](#processesranon) | Search for processes associated with a custom IOC | +| [entities_processes](#entities.processes) | For the provided ProcessID retrieve the process details | +### DevicesCount +Number of hosts in your customer account that have observed a given custom IOC + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string' + } + + response = falcon.DevicesCount(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string' +} + +response = falcon.command('DevicesCount', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetIOC +Get an IOC by providing a type and value + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string' + } + + response = falcon.GetIOC(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string' +} + +response = falcon.command('GetIOC', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### CreateIOC +Create a new IOC + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Create a new IOC by providing a JSON object that includes these key/value pairs: **type** (required): The type of the indicator. Valid values: - sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. - md5: A hex-encoded md5 hash string. Length - min 32, max: 32. - domain: A domain name. Length - min: 1, max: 200. - ipv4: An IPv4 address. Must be a valid IP address. - ipv6: An IPv6 address. Must be a valid IP address. **value** (required): The string representation of the indicator. **policy** (required): Action to take when a host observes the custom IOC. Values: - detect: Enable detections for this custom IOC - none: Disable detections for this custom IOC **share_level** (optional): Visibility of this custom IOC. All custom IOCs are visible only within your customer account, so only one value is valid: - red **expiration_days** (optional): Number of days this custom IOC is active. Only applies for the types `domain`, `ipv4`, and `ipv6`. **source** (optional): The source where this indicator originated. This can be used for tracking where this indicator was defined. Limit 200 characters. **description** (optional): Descriptive label for this custom IOC | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.CreateIOC(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateIOC', body=BODY) +print(response) +falcon.deauthenticate() +``` +### DeleteIOC +Delete an IOC by providing a type and value + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string' + } + + response = falcon.DeleteIOC(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string' +} + +response = falcon.command('DeleteIOC', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### UpdateIOC +Update an IOC by providing a type and value + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.UpdateIOC(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateIOC', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### DevicesRanOn +Find hosts that have observed a given custom IOC. For details about those hosts, use GET /devices/entities/devices/v1 + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +| | __limit__ | query | _string_ | The first process to return, where 0 is the latest offset. Use with the offset parameter to manage pagination of results. | +| | __offset__ | query | _string_ | The first process to return, where 0 is the latest offset. Use with the limit parameter to manage pagination of results. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string', + 'limit': 'string', + 'offset': 'string' + } + + response = falcon.DevicesRanOn(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string', + 'limit': 'string', + 'offset': 'string' +} + +response = falcon.command('DevicesRanOn', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### QueryIOCs +Search the custom IOCs in your customer account + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __types__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| | __values__ | query | _string_ | The string representation of the indicator | +| | __from.expiration_timestamp__ | query | _string_ | Find custom IOCs created after this time (RFC-3339 timestamp) | +| | __to.expiration_timestamp__ | query | _string_ | Find custom IOCs created before this time (RFC-3339 timestamp) | +| | __policies__ | query | _string_ | ndetect: Find custom IOCs that produce notificationsnnnone: Find custom IOCs the particular indicator has been detected on a host. This is equivalent to turning the indicator off. | +| | __sources__ | query | _string_ | The source where this indicator originated. This can be used for tracking where this indicator was defined. Limit 200 characters. | +| | __share_levels__ | query | _string_ | The level at which the indicator will be shared. Currently only red share level (not shared) is supported, indicating that the IOC isn't shared with other FH customers. | +| | __created_by__ | query | _string_ | created_by | +| | __deleted_by__ | query | _string_ | The user or API client who deleted the custom IOC | +| | __include_deleted__ | query | _string_ | true: Include deleted IOCs false: Don't include deleted IOCs (default) | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'types': 'string', + 'values': 'string', + 'from.expiration_timestamp': 'string', + 'to.expiration_timestamp': 'string', + 'policies': 'string', + 'sources': 'string', + 'share_levels': 'string', + 'created_by': 'string', + 'deleted_by': 'string', + 'include_deleted': 'string' + } + + response = falcon.QueryIOCs(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'types': 'string', + 'values': 'string', + 'from.expiration_timestamp': 'string', + 'to.expiration_timestamp': 'string', + 'policies': 'string', + 'sources': 'string', + 'share_levels': 'string', + 'created_by': 'string', + 'deleted_by': 'string', + 'include_deleted': 'string' +} + +response = falcon.command('QueryIOCs', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### ProcessesRanOn +Search for processes associated with a custom IOC + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __type__ | query | _string_ | The type of the indicator. Valid types include: sha256: A hex-encoded sha256 hash string. Length - min: 64, max: 64. md5: A hex-encoded md5 hash string. Length - min 32, max: 32. domain: A domain name. Length - min: 1, max: 200. ipv4: An IPv4 address. Must be a valid IP address. ipv6: An IPv6 address. Must be a valid IP address. | +| :white_check_mark: | __value__ | query | _string_ | The string representation of the indicator | +| :white_check_mark: | __device_id__ | query | _string_ | Specify a host's ID to return only processes from that host. Get a host's ID from GET /devices/queries/devices/v1, the Falcon console, or the Streaming API. | +| | __limit__ | query | _string_ | The first process to return, where 0 is the latest offset. Use with the offset parameter to manage pagination of results. | +| | __offset__ | query | _string_ | The first process to return, where 0 is the latest offset. Use with the limit parameter to manage pagination of results. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + PARAMS = { + 'type': 'string', + 'value': 'string', + 'device_id': 'string', + 'limit': 'string', + 'offset': 'string' + } + + response = falcon.ProcessesRanOn(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'type': 'string', + 'value': 'string', + 'device_id': 'string', + 'limit': 'string', + 'offset': 'string' +} + +response = falcon.command('ProcessesRanOn', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### entities_processes +For the provided ProcessID retrieve the process details + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ProcessID for the running process you want to lookup | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import iocs as FalconIOCs + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconIOCs.Iocs(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.entities.processes(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('entities.processes', ids=IDS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/oauth2.md b/docs/service-class/oauth2.md new file mode 100644 index 00000000..3f5442c8 --- /dev/null +++ b/docs/service-class/oauth2.md @@ -0,0 +1,123 @@ +# Using the OAuth2 service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [oauth2RevokeToken](#oauth2revoketoken) | Revoke a previously issued OAuth2 access token before the end of its standard 30-minute lifespan. | +| [oauth2AccessToken](#oauth2accesstoken) | Generate an OAuth2 access token | +### oauth2RevokeToken +Revoke a previously issued OAuth2 access token before the end of its standard 30-minute lifespan. + +#### Content-Type +- Consumes: _application/x-www-form-urlencoded_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __token__ | formData | _string_ | The OAuth2 access token you want to revoke. Include your API client ID and secret in basic auth format (`Authorization: basic `) in your request header. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAuth.OAuth2(access_token=token) + + PAYLOAD = { + 'token': 'string' + } + + response = falcon.oauth2RevokeToken(data=PAYLOAD) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PAYLOAD = { + 'token': 'string' +} + +response = falcon.command('oauth2RevokeToken', data=PAYLOAD) +print(response) +falcon.deauthenticate() +``` +### oauth2AccessToken +Generate an OAuth2 access token + +#### Content-Type +- Consumes: _application/x-www-form-urlencoded_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __client_id__ | formData | _string_ | The API client ID to authenticate your API requests. For information on generating API clients, see [API documentation inside Falcon](https://falcon.crowdstrike.com/support/documentation/1/crowdstrike-api-introduction-for-developers). | +| :white_check_mark: | __client_secret__ | formData | _string_ | The API client secret to authenticate your API requests. For information on generating API clients, see [API documentation inside Falcon](https://falcon.crowdstrike.com/support/documentation/1/crowdstrike-api-introduction-for-developers). | +| | __member_cid__ | formData | _string_ | For MSSP Master CIDs, optionally lock the token to act on behalf of this member CID | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconAuth.OAuth2(access_token=token) + + PAYLOAD = { + 'client_id': 'string', + 'client_secret': 'string', + 'member_cid': 'string' + } + + response = falcon.oauth2AccessToken(data=PAYLOAD) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PAYLOAD = { + 'client_id': 'string', + 'client_secret': 'string', + 'member_cid': 'string' +} + +response = falcon.command('oauth2AccessToken', data=PAYLOAD) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/prevention-policies.md b/docs/service-class/prevention-policies.md new file mode 100644 index 00000000..8f961330 --- /dev/null +++ b/docs/service-class/prevention-policies.md @@ -0,0 +1,324 @@ +# Using the Prevention Policies service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [queryCombinedPreventionPolicyMembers](#querycombinedpreventionpolicymembers) | Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria | +| [queryCombinedPreventionPolicies](#querycombinedpreventionpolicies) | Search for Prevention Policies in your environment by providing an FQL filter and paging details. Returns a set of Prevention Policies which match the filter criteria | +| [performPreventionPoliciesAction](#performpreventionpoliciesaction) | Perform the specified action on the Prevention Policies specified in the request | +| [setPreventionPoliciesPrecedence](#setpreventionpoliciesprecedence) | Sets the precedence of Prevention Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence | +| [getPreventionPolicies](#getpreventionpolicies) | Retrieve a set of Prevention Policies by specifying their IDs | +| [createPreventionPolicies](#createpreventionpolicies) | Create Prevention Policies by specifying details about the policy to create | +| [deletePreventionPolicies](#deletepreventionpolicies) | Delete a set of Prevention Policies by specifying their IDs | +| [updatePreventionPolicies](#updatepreventionpolicies) | Update Prevention Policies by specifying the ID of the policy and details to update | +| [queryPreventionPolicyMembers](#querypreventionpolicymembers) | Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria | +| [queryPreventionPolicies](#querypreventionpolicies) | Search for Prevention Policies in your environment by providing an FQL filter and paging details. Returns a set of Prevention Policy IDs which match the filter criteria | +### queryCombinedPreventionPolicyMembers +Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Prevention Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedPreventionPolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedPreventionPolicies +Search for Prevention Policies in your environment by providing an FQL filter and paging details. Returns a set of Prevention Policies which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedPreventionPolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### performPreventionPoliciesAction +Perform the specified action on the Prevention Policies specified in the request + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | The action to perform | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('performPreventionPoliciesAction', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### setPreventionPoliciesPrecedence +Sets the precedence of Prevention Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('setPreventionPoliciesPrecedence', body=BODY) +print(response) +falcon.deauthenticate() +``` +### getPreventionPolicies +Retrieve a set of Prevention Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Prevention Policies to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getPreventionPolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createPreventionPolicies +Create Prevention Policies by specifying details about the policy to create + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createPreventionPolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deletePreventionPolicies +Delete a set of Prevention Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Prevention Policies to delete | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deletePreventionPolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updatePreventionPolicies +Update Prevention Policies by specifying the ID of the policy and details to update + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updatePreventionPolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryPreventionPolicyMembers +Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Prevention Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryPreventionPolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryPreventionPolicies +Search for Prevention Policies in your environment by providing an FQL filter and paging details. Returns a set of Prevention Policy IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryPreventionPolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/real-time-response-admin.md b/docs/service-class/real-time-response-admin.md new file mode 100644 index 00000000..b7322755 --- /dev/null +++ b/docs/service-class/real-time-response-admin.md @@ -0,0 +1,751 @@ +# Using the Real Time Response Admin service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [BatchAdminCmd](#batchadmincmd) | Batch executes a RTR administrator command across the hosts mapped to the given batch ID. | +| [RTR_CheckAdminCommandStatus](#rtr-checkadmincommandstatus) | Get status of an executed RTR administrator command on a single host. | +| [RTR_ExecuteAdminCommand](#rtr-executeadmincommand) | Execute a RTR administrator command on a single host. | +| [RTR_GetPut_Files](#rtr-getput-files) | Get put-files based on the ID's given. These are used for the RTR `put` command. | +| [RTR_CreatePut_Files](#rtr-createput-files) | Upload a new put-file to use for the RTR `put` command. | +| [RTR_DeletePut_Files](#rtr-deleteput-files) | Delete a put-file based on the ID given. Can only delete one file at a time. | +| [RTR_GetScripts](#rtr-getscripts) | Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command. | +| [RTR_CreateScripts](#rtr-createscripts) | Upload a new custom-script to use for the RTR `runscript` command. | +| [RTR_DeleteScripts](#rtr-deletescripts) | Delete a custom-script based on the ID given. Can only delete one script at a time. | +| [RTR_UpdateScripts](#rtr-updatescripts) | Upload a new scripts to replace an existing one. | +| [RTR_ListPut_Files](#rtr-listput-files) | Get a list of put-file ID's that are available to the user for the `put` command. | +| [RTR_ListScripts](#rtr-listscripts) | Get a list of custom-script ID's that are available to the user for the `runscript` command. | +### BatchAdminCmd +Batch executes a RTR administrator command across the hosts mapped to the given batch ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `cp` - `encrypt` - `env` - `eventlog` - `filehash` - `get` - `getsid` - `help` - `history` - `ipconfig` - `kill` - `ls` - `map` - `memdump` - `mkdir` - `mount` - `mv` - `netstat` - `ps` - `put` - `reg query` - `reg set` - `reg delete` - `reg load` - `reg unload` - `restart` - `rm` - `run` - `runscript` - `shutdown` - `unmap` - `update history` - `update install` - `update list` - `update query` - `xmemdump` - `zip` **`base_command`** Active-Responder command type we are going to execute, for example: `get` or `cp`. Refer to the RTR documentation for the full list of commands. **`batch_id`** Batch ID to execute the command on. Received from `/real-time-response/combined/init-sessions/v1`. **`command_string`** Full command string for the command. For example `get some_file.txt` **`optional_hosts`** List of a subset of hosts we want to run the command on. If this list is supplied, only these hosts will receive the command. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchAdminCmd(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchAdminCmd', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_CheckAdminCommandStatus +Get status of an executed RTR administrator command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __cloud_request_id__ | query | _string_ | Cloud Request ID of the executed command to query | +| :white_check_mark: | __sequence_id__ | query | _integer_ | Sequence ID that we want to retrieve. Command responses are chunked across sequences | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer + } + + response = falcon.RTR-CheckAdminCommandStatus(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer +} + +response = falcon.command('RTR-CheckAdminCommandStatus', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ExecuteAdminCommand +Execute a RTR administrator command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `cp` - `encrypt` - `env` - `eventlog` - `filehash` - `get` - `getsid` - `help` - `history` - `ipconfig` - `kill` - `ls` - `map` - `memdump` - `mkdir` - `mount` - `mv` - `netstat` - `ps` - `put` - `reg query` - `reg set` - `reg delete` - `reg load` - `reg unload` - `restart` - `rm` - `run` - `runscript` - `shutdown` - `unmap` - `update history` - `update install` - `update list` - `update query` - `xmemdump` - `zip` Required values. The rest of the fields are unused. **`base_command`** Active-Responder command type we are going to execute, for example: `get` or `cp`. Refer to the RTR documentation for the full list of commands. **`command_string`** Full command string for the command. For example `get some_file.txt` **`session_id`** RTR session ID to run the command on | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-ExecuteAdminCommand(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-ExecuteAdminCommand', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_GetPut_Files +Get put-files based on the ID's given. These are used for the RTR `put` command. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | File IDs | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.RTR-GetPut-Files(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RTR-GetPut-Files', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### RTR_CreatePut_Files +Upload a new put-file to use for the RTR `put` command. + +#### Content-Type +- Consumes: _multipart/form-data_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __file__ | formData | _file_ | put-file to upload | +| :white_check_mark: | __description__ | formData | _string_ | File description | +| | __name__ | formData | _string_ | File name (if different than actual file name) | +| | __comments_for_audit_log__ | formData | _string_ | The audit log comment | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PAYLOAD = { + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string' + } + + response = falcon.RTR-CreatePut-Files(data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PAYLOAD = { + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string' +} + +response = falcon.command('RTR-CreatePut-Files', data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) +print(response) +falcon.deauthenticate() +``` +### RTR_DeletePut_Files +Delete a put-file based on the ID given. Can only delete one file at a time. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | File id | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.RTR-DeletePut-Files(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RTR-DeletePut-Files', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### RTR_GetScripts +Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | File IDs | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.RTR-GetScripts(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RTR-GetScripts', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### RTR_CreateScripts +Upload a new custom-script to use for the RTR `runscript` command. + +#### Content-Type +- Consumes: _multipart/form-data_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __file__ | formData | _file_ | custom-script file to upload. These should be powershell scripts. | +| :white_check_mark: | __description__ | formData | _string_ | File description | +| | __name__ | formData | _string_ | File name (if different than actual file name) | +| | __comments_for_audit_log__ | formData | _string_ | The audit log comment | +| :white_check_mark: | __permission_type__ | formData | _string_ | Permission for the custom-script. Valid permission values: - `private`, usable by only the user who uploaded it - `group`, usable by all RTR Admins - `public`, usable by all active-responders and RTR admins | +| | __content__ | formData | _string_ | The script text that you want to use to upload | +| | __platform__ | formData | array (_string_) | Platforms for the file. Currently supports: windows, mac, linux, . If no platform is provided, it will default to 'windows' | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PAYLOAD = { + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string', + 'permission_type': 'string', + 'content': 'string', + 'platform': [ + 'string', + 'string' + ] + } + + response = falcon.RTR-CreateScripts(data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PAYLOAD = { + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string', + 'permission_type': 'string', + 'content': 'string', + 'platform': [ + 'string', + 'string' + ] +} + +response = falcon.command('RTR-CreateScripts', data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) +print(response) +falcon.deauthenticate() +``` +### RTR_DeleteScripts +Delete a custom-script based on the ID given. Can only delete one script at a time. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | File id | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.RTR-DeleteScripts(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RTR-DeleteScripts', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### RTR_UpdateScripts +Upload a new scripts to replace an existing one. + +#### Content-Type +- Consumes: _multipart/form-data_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | formData | _string_ | ID to update | +| | __file__ | formData | _file_ | custom-script file to upload. These should be powershell scripts. | +| | __description__ | formData | _string_ | File description | +| | __name__ | formData | _string_ | File name (if different than actual file name) | +| | __comments_for_audit_log__ | formData | _string_ | The audit log comment | +| | __permission_type__ | formData | _string_ | Permission for the custom-script. Valid permission values: - `private`, usable by only the user who uploaded it - `group`, usable by all RTR Admins - `public`, usable by all active-responders and RTR admins | +| | __content__ | formData | _string_ | The script text that you want to use to upload | +| | __platform__ | formData | array (_string_) | Platforms for the file. Currently supports: windows, mac, | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PAYLOAD = { + 'id': 'string', + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string', + 'permission_type': 'string', + 'content': 'string', + 'platform': [ + 'string', + 'string' + ] + } + + response = falcon.RTR-UpdateScripts(data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PAYLOAD = { + 'id': 'string', + 'description': 'string', + 'name': 'string', + 'comments_for_audit_log': 'string', + 'permission_type': 'string', + 'content': 'string', + 'platform': [ + 'string', + 'string' + ] +} + +response = falcon.command('RTR-UpdateScripts', data=PAYLOAD, files=[('file', ('testfile.jpg', open('testfile.jpg','rb').read(), 'image/jpg'))]) +print(response) +falcon.deauthenticate() +``` +### RTR_ListPut_Files +Get a list of put-file ID's that are available to the user for the `put` command. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter criteria in the form of an FQL query. For more information about FQL queries, see our [FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +| | __sort__ | query | _string_ | Sort by spec. Ex: 'created_at|asc'. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.RTR-ListPut-Files(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('RTR-ListPut-Files', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ListScripts +Get a list of custom-script ID's that are available to the user for the `runscript` command. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter criteria in the form of an FQL query. For more information about FQL queries, see our [FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +| | __sort__ | query | _string_ | Sort by spec. Ex: 'created_at|asc'. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response_admin as FalconRTRAdmin + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTRAdmin.Real_Time_Response_Admin(access_token=token) + + PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' + } + + response = falcon.RTR-ListScripts(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('RTR-ListScripts', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/real-time-response.md b/docs/service-class/real-time-response.md new file mode 100644 index 00000000..7f81fee0 --- /dev/null +++ b/docs/service-class/real-time-response.md @@ -0,0 +1,1276 @@ +# Using the Real Time Response service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [RTR_AggregateSessions](#rtr-aggregatesessions) | Get aggregates on session data. | +| [BatchActiveResponderCmd](#batchactiverespondercmd) | Batch executes a RTR active-responder command across the hosts mapped to the given batch ID. | +| [BatchCmd](#batchcmd) | Batch executes a RTR read-only command across the hosts mapped to the given batch ID. | +| [BatchGetCmdStatus](#batchgetcmdstatus) | Retrieves the status of the specified batch get command. Will return successful files when they are finished processing. | +| [BatchGetCmd](#batchgetcmd) | Batch executes `get` command across hosts to retrieve files. After this call is made `GET /real-time-response/combined/batch-get-command/v1` is used to query for the results. | +| [BatchInitSessions](#batchinitsessions) | Batch initialize a RTR session on multiple hosts. Before any RTR commands can be used, an active session is needed on the host. | +| [BatchRefreshSessions](#batchrefreshsessions) | Batch refresh a RTR session on multiple hosts. RTR sessions will expire after 10 minutes unless refreshed. | +| [RTR_CheckActiveResponderCommandStatus](#rtr-checkactiverespondercommandstatus) | Get status of an executed active-responder command on a single host. | +| [RTR_ExecuteActiveResponderCommand](#rtr-executeactiverespondercommand) | Execute an active responder command on a single host. | +| [RTR_CheckCommandStatus](#rtr-checkcommandstatus) | Get status of an executed command on a single host. | +| [RTR_ExecuteCommand](#rtr-executecommand) | Execute a command on a single host. | +| [RTR_GetExtractedFileContents](#rtr-getextractedfilecontents) | Get RTR extracted file contents for specified session and sha256. | +| [RTR_ListFiles](#rtr-listfiles) | Get a list of files for the specified RTR session. | +| [RTR_DeleteFile](#rtr-deletefile) | Delete a RTR session file. | +| [RTR_ListQueuedSessions](#rtr-listqueuedsessions) | Get queued session metadata by session ID. | +| [RTR_DeleteQueuedSession](#rtr-deletequeuedsession) | Delete a queued session command | +| [RTR_PulseSession](#rtr-pulsesession) | Refresh a session timeout on a single host. | +| [RTR_ListSessions](#rtr-listsessions) | Get session metadata by session id. | +| [RTR_InitSession](#rtr-initsession) | Initialize a new session with the RTR cloud. | +| [RTR_DeleteSession](#rtr-deletesession) | Delete a session. | +| [RTR_ListAllSessions](#rtr-listallsessions) | Get a list of session_ids. | +### RTR_AggregateSessions +Get aggregates on session data. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Supported aggregations: - `term` - `date_range` Supported aggregation members: **`date_ranges`** If performing a date range query specify the **`from`** and **`to`** date ranges. These can be in common date formats like `2019-07-18` or `now` **`field`** Term you want to aggregate on. If doing a `date_range` query, this is the date field you want to apply the date ranges to **`filter`** Optional filter criteria in the form of an FQL query. For more information about FQL queries, see our [FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). **`name`** Name of the aggregation **`size`** Size limit to apply to the queries. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-AggregateSessions(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-AggregateSessions', body=BODY) +print(response) +falcon.deauthenticate() +``` +### BatchActiveResponderCmd +Batch executes a RTR active-responder command across the hosts mapped to the given batch ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `cp` - `encrypt` - `env` - `eventlog` - `filehash` - `get` - `getsid` - `help` - `history` - `ipconfig` - `kill` - `ls` - `map` - `memdump` - `mkdir` - `mount` - `mv` - `netstat` - `ps` - `reg query` - `reg set` - `reg delete` - `reg load` - `reg unload` - `restart` - `rm` - `runscript` - `shutdown` - `unmap` - `update history` - `update install` - `update list` - `update query` - `xmemdump` - `zip` **`base_command`** Active-Responder command type we are going to execute, for example: `get` or `cp`. Refer to the RTR documentation for the full list of commands. **`batch_id`** Batch ID to execute the command on. Received from `/real-time-response/combined/init-sessions/v1`. **`command_string`** Full command string for the command. For example `get some_file.txt` **`optional_hosts`** List of a subset of hosts we want to run the command on. If this list is supplied, only these hosts will receive the command. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchActiveResponderCmd(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchActiveResponderCmd', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### BatchCmd +Batch executes a RTR read-only command across the hosts mapped to the given batch ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `env` - `eventlog` - `filehash` - `getsid` - `help` - `history` - `ipconfig` - `ls` - `mount` - `netstat` - `ps` - `reg query` **`base_command`** read-only command type we are going to execute, for example: `ls` or `cd`. Refer to the RTR documentation for the full list of commands. **`batch_id`** Batch ID to execute the command on. Received from `/real-time-response/combined/init-sessions/v1`. **`command_string`** Full command string for the command. For example `cd C:some_directory` **`optional_hosts`** List of a subset of hosts we want to run the command on. If this list is supplied, only these hosts will receive the command. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchCmd(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchCmd', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### BatchGetCmdStatus +Retrieves the status of the specified batch get command. Will return successful files when they are finished processing. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __batch_get_cmd_req_id__ | query | _string_ | Batch Get Command Request ID received from `/real-time-response/combined/get-command/v1` | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string', + 'batch_get_cmd_req_id': 'string' + } + + response = falcon.BatchGetCmdStatus(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string', + 'batch_get_cmd_req_id': 'string' +} + +response = falcon.command('BatchGetCmdStatus', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### BatchGetCmd +Batch executes `get` command across hosts to retrieve files. After this call is made `GET /real-time-response/combined/batch-get-command/v1` is used to query for the results. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | **`batch_id`** Batch ID to execute the command on. Received from `/real-time-response/combined/init-sessions/v1`. **`file_path`** Full path to the file that is to be retrieved from each host in the batch. **`optional_hosts`** List of a subset of hosts we want to run the command on. If this list is supplied, only these hosts will receive the command. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchGetCmd(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchGetCmd', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### BatchInitSessions +Batch initialize a RTR session on multiple hosts. Before any RTR commands can be used, an active session is needed on the host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | **`host_ids`** List of host agent ID's to initialize a RTR session on **`existing_batch_id`** Optional batch ID. Use an existing batch ID if you want to initialize new hosts and add them to the existing batch | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchInitSessions(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchInitSessions', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### BatchRefreshSessions +Batch refresh a RTR session on multiple hosts. RTR sessions will expire after 10 minutes unless refreshed. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __timeout__ | query | _integer_ | Timeout for how long to wait for the request in seconds, default timeout is 30 seconds. Maximum is 10 minutes. | +| | __timeout_duration__ | query | _string_ | Timeout duration for for how long to wait for the request in duration syntax. Example, `10s`. Valid units: `ns, us, ms, s, m, h`. Maximum is 10 minutes. | +| :white_check_mark: | __body__ | body | _string_ | **`batch_id`** Batch ID to execute the command on. Received from `/real-time-response/combined/init-sessions/v1`. **`hosts_to_remove`** Hosts to remove from the batch session. Heartbeats will no longer happen on these hosts and the sessions will expire. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.BatchRefreshSessions(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'timeout': integer, + 'timeout_duration': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('BatchRefreshSessions', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_CheckActiveResponderCommandStatus +Get status of an executed active-responder command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __cloud_request_id__ | query | _string_ | Cloud Request ID of the executed command to query | +| :white_check_mark: | __sequence_id__ | query | _integer_ | Sequence ID that we want to retrieve. Command responses are chunked across sequences | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer + } + + response = falcon.RTR-CheckActiveResponderCommandStatus(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer +} + +response = falcon.command('RTR-CheckActiveResponderCommandStatus', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ExecuteActiveResponderCommand +Execute an active responder command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `cp` - `encrypt` - `env` - `eventlog` - `filehash` - `get` - `getsid` - `help` - `history` - `ipconfig` - `kill` - `ls` - `map` - `memdump` - `mkdir` - `mount` - `mv` - `netstat` - `ps` - `reg query` - `reg set` - `reg delete` - `reg load` - `reg unload` - `restart` - `rm` - `runscript` - `shutdown` - `unmap` - `update history` - `update install` - `update list` - `update query` - `xmemdump` - `zip` Required values. The rest of the fields are unused. **`base_command`** Active-Responder command type we are going to execute, for example: `get` or `cp`. Refer to the RTR documentation for the full list of commands. **`command_string`** Full command string for the command. For example `get some_file.txt` **`session_id`** RTR session ID to run the command on | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-ExecuteActiveResponderCommand(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-ExecuteActiveResponderCommand', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_CheckCommandStatus +Get status of an executed command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __cloud_request_id__ | query | _string_ | Cloud Request ID of the executed command to query | +| :white_check_mark: | __sequence_id__ | query | _integer_ | Sequence ID that we want to retrieve. Command responses are chunked across sequences | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer + } + + response = falcon.RTR-CheckCommandStatus(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'cloud_request_id': 'string', + 'sequence_id': integer +} + +response = falcon.command('RTR-CheckCommandStatus', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ExecuteCommand +Execute a command on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Use this endpoint to run these [real time response commands](https://falcon.crowdstrike.com/support/documentation/11/getting-started-guide#rtr_commands): - `cat` - `cd` - `clear` - `env` - `eventlog` - `filehash` - `getsid` - `help` - `history` - `ipconfig` - `ls` - `mount` - `netstat` - `ps` - `reg query` Required values. The rest of the fields are unused. **`base_command`** read-only command type we are going to execute, for example: `ls` or `cd`. Refer to the RTR documentation for the full list of commands. **`command_string`** Full command string for the command. For example `cd C:some_directory` **`session_id`** RTR session ID to run the command on | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-ExecuteCommand(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-ExecuteCommand', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_GetExtractedFileContents +Get RTR extracted file contents for specified session and sha256. + +#### Content-Type +- Produces: _application/x-7z-compressed_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __session_id__ | query | _string_ | RTR Session id | +| :white_check_mark: | __sha256__ | query | _string_ | Extracted SHA256 (e.g. 'efa256a96af3b556cd3fc9d8b1cf587d72807d7805ced441e8149fc279db422b') | +| | __filename__ | query | _string_ | Filename to use for the archive name and the file within the archive. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'session_id': 'string', + 'sha256': 'string', + 'filename': 'string' + } + + response = falcon.RTR-GetExtractedFileContents(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'session_id': 'string', + 'sha256': 'string', + 'filename': 'string' +} + +response = falcon.command('RTR-GetExtractedFileContents', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ListFiles +Get a list of files for the specified RTR session. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __session_id__ | query | _string_ | RTR Session id | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'session_id': 'string' + } + + response = falcon.RTR-ListFiles(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'session_id': 'string' +} + +response = falcon.command('RTR-ListFiles', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_DeleteFile +Delete a RTR session file. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | RTR Session file id | +| :white_check_mark: | __session_id__ | query | _string_ | RTR Session id | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'session_id': 'string' + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.RTR-DeleteFile(parameters=PARAMS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'session_id': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RTR-DeleteFile', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### RTR_ListQueuedSessions +Get queued session metadata by session ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | **`ids`** List of RTR sessions to retrieve. RTR will only return the sessions that were created by the calling user | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-ListQueuedSessions(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-ListQueuedSessions', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_DeleteQueuedSession +Delete a queued session command + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __session_id__ | query | _string_ | RTR Session id | +| :white_check_mark: | __cloud_request_id__ | query | _string_ | Cloud Request ID of the executed command to query | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'session_id': 'string', + 'cloud_request_id': 'string' + } + + response = falcon.RTR-DeleteQueuedSession(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'session_id': 'string', + 'cloud_request_id': 'string' +} + +response = falcon.command('RTR-DeleteQueuedSession', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_PulseSession +Refresh a session timeout on a single host. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | **`device_id`** The host agent ID to refresh the RTR session on. RTR will retrieve an existing session for the calling user on this host | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-PulseSession(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-PulseSession', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_ListSessions +Get session metadata by session id. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | **`ids`** List of RTR sessions to retrieve. RTR will only return the sessions that were created by the calling user | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-ListSessions(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-ListSessions', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_InitSession +Initialize a new session with the RTR cloud. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | **`device_id`** The host agent ID to initialize the RTR session on. RTR will retrieve an existing session for the calling user on this host | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.RTR-InitSession(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('RTR-InitSession', body=BODY) +print(response) +falcon.deauthenticate() +``` +### RTR_DeleteSession +Delete a session. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __session_id__ | query | _string_ | RTR Session id | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'session_id': 'string' + } + + response = falcon.RTR-DeleteSession(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'session_id': 'string' +} + +response = falcon.command('RTR-DeleteSession', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RTR_ListAllSessions +Get a list of session_ids. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return ids. | +| | __limit__ | query | _integer_ | Number of ids to return. | +| | __sort__ | query | _string_ | Sort by spec. Ex: 'date_created|asc'. | +| | __filter__ | query | _string_ | Optional filter criteria in the form of an FQL query. For more information about FQL queries, see our [FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). “user_id” can accept a special value ‘@me’ which will restrict results to records with current user’s ID. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import real_time_response as FalconRTR + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconRTR.Real_Time_Response(access_token=token) + + PARAMS = { + 'offset': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.RTR-ListAllSessions(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('RTR-ListAllSessions', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/sensor-update-policies.md b/docs/service-class/sensor-update-policies.md new file mode 100644 index 00000000..aa33ba84 --- /dev/null +++ b/docs/service-class/sensor-update-policies.md @@ -0,0 +1,502 @@ +# Using the Sensor Update Policies service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [revealUninstallToken](#revealuninstalltoken) | Reveals an uninstall token for a specific device. To retrieve the bulk maintenance token pass the value 'MAINTENANCE' as the value for 'device_id' | +| [queryCombinedSensorUpdateBuilds](#querycombinedsensorupdatebuilds) | Retrieve available builds for use with Sensor Update Policies | +| [queryCombinedSensorUpdatePolicyMembers](#querycombinedsensorupdatepolicymembers) | Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria | +| [queryCombinedSensorUpdatePolicies](#querycombinedsensorupdatepolicies) | Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria | +| [queryCombinedSensorUpdatePoliciesV2](#querycombinedsensorupdatepoliciesv2) | Search for Sensor Update Policies with additional support for uninstall protection in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria | +| [performSensorUpdatePoliciesAction](#performsensorupdatepoliciesaction) | Perform the specified action on the Sensor Update Policies specified in the request | +| [setSensorUpdatePoliciesPrecedence](#setsensorupdatepoliciesprecedence) | Sets the precedence of Sensor Update Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence | +| [getSensorUpdatePolicies](#getsensorupdatepolicies) | Retrieve a set of Sensor Update Policies by specifying their IDs | +| [createSensorUpdatePolicies](#createsensorupdatepolicies) | Create Sensor Update Policies by specifying details about the policy to create | +| [deleteSensorUpdatePolicies](#deletesensorupdatepolicies) | Delete a set of Sensor Update Policies by specifying their IDs | +| [updateSensorUpdatePolicies](#updatesensorupdatepolicies) | Update Sensor Update Policies by specifying the ID of the policy and details to update | +| [getSensorUpdatePoliciesV2](#getsensorupdatepoliciesv2) | Retrieve a set of Sensor Update Policies with additional support for uninstall protection by specifying their IDs | +| [createSensorUpdatePoliciesV2](#createsensorupdatepoliciesv2) | Create Sensor Update Policies by specifying details about the policy to create with additional support for uninstall protection | +| [updateSensorUpdatePoliciesV2](#updatesensorupdatepoliciesv2) | Update Sensor Update Policies by specifying the ID of the policy and details to update with additional support for uninstall protection | +| [querySensorUpdatePolicyMembers](#querysensorupdatepolicymembers) | Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria | +| [querySensorUpdatePolicies](#querysensorupdatepolicies) | Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policy IDs which match the filter criteria | +### revealUninstallToken +Reveals an uninstall token for a specific device. To retrieve the bulk maintenance token pass the value 'MAINTENANCE' as the value for 'device_id' + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('revealUninstallToken', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryCombinedSensorUpdateBuilds +Retrieve available builds for use with Sensor Update Policies + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __platform__ | query | _string_ | The platform to return builds for | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'platform': 'string' +} + +response = falcon.command('queryCombinedSensorUpdateBuilds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedSensorUpdatePolicyMembers +Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. Returns a set of host details which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Sensor Update Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedSensorUpdatePolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedSensorUpdatePolicies +Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedSensorUpdatePolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### queryCombinedSensorUpdatePoliciesV2 +Search for Sensor Update Policies with additional support for uninstall protection in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryCombinedSensorUpdatePoliciesV2', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### performSensorUpdatePoliciesAction +Perform the specified action on the Sensor Update Policies specified in the request + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __action_name__ | query | _string_ | The action to perform | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'action_name': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('performSensorUpdatePoliciesAction', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### setSensorUpdatePoliciesPrecedence +Sets the precedence of Sensor Update Policies based on the order of IDs specified in the request. The first ID specified will have the highest precedence and the last ID specified will have the lowest. You must specify all non-Default Policies for a platform when updating precedence + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('setSensorUpdatePoliciesPrecedence', body=BODY) +print(response) +falcon.deauthenticate() +``` +### getSensorUpdatePolicies +Retrieve a set of Sensor Update Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Sensor Update Policies to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getSensorUpdatePolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createSensorUpdatePolicies +Create Sensor Update Policies by specifying details about the policy to create + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createSensorUpdatePolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteSensorUpdatePolicies +Delete a set of Sensor Update Policies by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Sensor Update Policies to delete | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteSensorUpdatePolicies', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateSensorUpdatePolicies +Update Sensor Update Policies by specifying the ID of the policy and details to update + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateSensorUpdatePolicies', body=BODY) +print(response) +falcon.deauthenticate() +``` +### getSensorUpdatePoliciesV2 +Retrieve a set of Sensor Update Policies with additional support for uninstall protection by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the Sensor Update Policies to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getSensorUpdatePoliciesV2', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createSensorUpdatePoliciesV2 +Create Sensor Update Policies by specifying details about the policy to create with additional support for uninstall protection + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createSensorUpdatePoliciesV2', body=BODY) +print(response) +falcon.deauthenticate() +``` +### updateSensorUpdatePoliciesV2 +Update Sensor Update Policies by specifying the ID of the policy and details to update with additional support for uninstall protection + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateSensorUpdatePoliciesV2', body=BODY) +print(response) +falcon.deauthenticate() +``` +### querySensorUpdatePolicyMembers +Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. Returns a set of Agent IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __id__ | query | _string_ | The ID of the Sensor Update Policy to search for members of | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('querySensorUpdatePolicyMembers', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### querySensorUpdatePolicies +Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. Returns a set of Sensor Update Policy IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-5000] | +| | __sort__ | query | _string_ | The property to sort by | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('querySensorUpdatePolicies', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/spotlight-vulnerabilities.md b/docs/service-class/spotlight-vulnerabilities.md new file mode 100644 index 00000000..6edb7750 --- /dev/null +++ b/docs/service-class/spotlight-vulnerabilities.md @@ -0,0 +1,122 @@ +# Using the Spotlight Vulnerabilities service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [getVulnerabilities](#getvulnerabilities) | Get details on vulnerabilities by providing one or more IDs | +| [queryVulnerabilities](#queryvulnerabilities) | Search for Vulnerabilities in your environment by providing an FQL filter and paging details. Returns a set of Vulnerability IDs which match the filter criteria | +### getVulnerabilities +Get details on vulnerabilities by providing one or more IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | One or more vulnerability IDs (max: 400). Find vulnerability IDs with GET /spotlight/queries/vulnerabilities/v1 | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import spotlight_vulnerabilities as FalconSV + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconSV.Sensor_Vulnerabilities(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.getVulnerabilities(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getVulnerabilities', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### queryVulnerabilities +Search for Vulnerabilities in your environment by providing an FQL filter and paging details. Returns a set of Vulnerability IDs which match the filter criteria + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __after__ | query | _string_ | A pagination token used with the `limit` parameter to manage pagination of results. On your first request, don't provide an `after` token. On subsequent requests, provide the `after` token from the previous response to continue from that place in the results. | +| | __limit__ | query | _integer_ | The number of items to return in this response (default: 100, max: 400). Use with the after parameter to manage pagination of results. | +| | __sort__ | query | _string_ | Sort vulnerabilities by their properties. Common sort options include:
  • created_timestamp|desc
  • closed_timestamp|asc
| +| :white_check_mark: | __filter__ | query | _string_ | Filter items using a query in Falcon Query Language (FQL). Wildcards * are unsupported. Common filter options include:
  • created_timestamp:>'2019-11-25T22:36:12Z'
  • closed_timestamp:>'2019-11-25T22:36:12Z'
  • aid:'8e7656b27d8c49a34a1af416424d6231'
| +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import spotlight_vulnerabilities as FalconSV + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconSV.Sensor_Vulnerabilities(access_token=token) + + PARAMS = { + 'after': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' + } + + response = falcon.queryVulnerabilities(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'after': 'string', + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('queryVulnerabilities', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/service-class/user-management.md b/docs/service-class/user-management.md new file mode 100644 index 00000000..37f1610d --- /dev/null +++ b/docs/service-class/user-management.md @@ -0,0 +1,680 @@ +# Using the User Management service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-%E2%9C%93%20Yes-green.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetRoles](#getroles) | Get info about a role | +| [GrantUserRoleIds](#grantuserroleids) | Assign one or more roles to a user | +| [RevokeUserRoleIds](#revokeuserroleids) | Revoke one or more roles from a user | +| [GetAvailableRoleIds](#getavailableroleids) | Show role IDs for all roles available in your customer account. For more information on each role, provide the role ID to `/customer/entities/roles/v1`. | +| [GetUserRoleIds](#getuserroleids) | Show role IDs of roles assigned to a user. For more information on each role, provide the role ID to `/customer/entities/roles/v1`. | +| [RetrieveUser](#retrieveuser) | Get info about a user | +| [CreateUser](#createuser) | Create a new user. After creating a user, assign one or more roles with POST /user-roles/entities/user-roles/v1 | +| [DeleteUser](#deleteuser) | Delete a user permanently | +| [UpdateUser](#updateuser) | Modify an existing user's first or last name | +| [RetrieveEmailsByCID](#retrieveemailsbycid) | List the usernames (usually an email address) for all users in your customer account | +| [RetrieveUserUUIDsByCID](#retrieveuseruuidsbycid) | List user IDs for all users in your customer account. For more information on each user, provide the user ID to `/users/entities/user/v1`. | +| [RetrieveUserUUID](#retrieveuseruuid) | Get a user's ID by providing a username (usually an email address) | +### GetRoles +Get info about a role + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a role. Find a role ID from `/customer/queries/roles/v1` or `/users/queries/roles/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.GetRoles(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetRoles', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GrantUserRoleIds +Assign one or more roles to a user + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __user_uuid__ | query | _string_ | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +| :white_check_mark: | __body__ | body | _string_ | Role ID(s) of the role you want to assign | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'user_uuid': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.GrantUserRoleIds(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'user_uuid': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GrantUserRoleIds', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### RevokeUserRoleIds +Revoke one or more roles from a user + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __user_uuid__ | query | _string_ | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +| :white_check_mark: | __ids__ | query | array (_string_) | One or more role IDs to revoke. Find a role's ID from `/users/queries/roles/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'user_uuid': 'string' + } + + IDS = 'ID1,ID2,ID3' + + response = falcon.RevokeUserRoleIds(parameters=PARAMS, ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'user_uuid': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RevokeUserRoleIds', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetAvailableRoleIds +Show role IDs for all roles available in your customer account. For more information on each role, provide the role ID to `/customer/entities/roles/v1`. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + response = falcon.GetAvailableRoleIds() + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetAvailableRoleIds') +print(response) +falcon.deauthenticate() +``` +### GetUserRoleIds +Show role IDs of roles assigned to a user. For more information on each role, provide the role ID to `/customer/entities/roles/v1`. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __user_uuid__ | query | _string_ | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'user_uuid': 'string' + } + + response = falcon.GetUserRoleIds(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'user_uuid': 'string' +} + +response = falcon.command('GetUserRoleIds', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### RetrieveUser +Get info about a user + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + IDS = 'ID1,ID2,ID3' + + response = falcon.RetrieveUser(ids=IDS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('RetrieveUser', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### CreateUser +Create a new user. After creating a user, assign one or more roles with POST /user-roles/entities/user-roles/v1 + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Attributes for this user. `uid` (required) is the user's email address, which is their username in Falcon. Optional attributes:
  • `firstName`
  • `lastName`
  • `password`
As a best practice, we recommend omitting `password`. If single sign-on is enabled for your customer account, the `password` attribute is ignored. If single sign-on is not enabled, we send a user activation request to their email address when you create the user with no `password`. The user should use the activation email to set their own password. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.CreateUser(body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateUser', body=BODY) +print(response) +falcon.deauthenticate() +``` +### DeleteUser +Delete a user permanently + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __user_uuid__ | query | _string_ | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'user_uuid': 'string' + } + + response = falcon.DeleteUser(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'user_uuid': 'string' +} + +response = falcon.command('DeleteUser', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### UpdateUser +Modify an existing user's first or last name + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __user_uuid__ | query | _string_ | ID of a user. Find a user's ID from `/users/entities/user/v1`. | +| :white_check_mark: | __body__ | body | _string_ | Attributes for this user. All attributes (shown below) are optional. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'user_uuid': 'string' + } + + BODY = { + 'Body Payload': 'See body description above' + } + + response = falcon.UpdateUser(parameters=PARAMS, body=BODY) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'user_uuid': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateUser', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### RetrieveEmailsByCID +List the usernames (usually an email address) for all users in your customer account + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + response = falcon.RetrieveEmailsByCID() + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('RetrieveEmailsByCID') +print(response) +falcon.deauthenticate() +``` +### RetrieveUserUUIDsByCID +List user IDs for all users in your customer account. For more information on each user, provide the user ID to `/users/entities/user/v1`. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + response = falcon.RetrieveUserUUIDsByCID() + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('RetrieveUserUUIDsByCID') +print(response) +falcon.deauthenticate() +``` +### RetrieveUserUUID +Get a user's ID by providing a username (usually an email address) + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __uid__ | query | array (_string_) | A username. This is usually the user's email address, but may vary based on your configuration. | +#### Usage +##### Service class example +```python +from falconpy import oauth2 as FalconAuth +from falconpy import user_management as FalconUsers + +authorization = FalconAuth.OAuth2(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret +}) + +try: + token = authorization.token()['body']['access_token'] +except: + token = False + +if token: + falcon = FalconUsers.User_Management(access_token=token) + + PARAMS = { + 'uid': [ + 'string', + 'string' + ] + } + + response = falcon.RetrieveUserUUID(parameters=PARAMS) + print(response) + + authorization.revoke(token=token) +``` +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'uid': [ + 'string', + 'string' + ] +} + +response = falcon.command('RetrieveUserUUID', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/cspm-registration.md b/docs/uber-class/cspm-registration.md new file mode 100644 index 00000000..60c21fb3 --- /dev/null +++ b/docs/uber-class/cspm-registration.md @@ -0,0 +1,478 @@ +# Using the CSPM Registration service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetCSPMAwsAccount](#getcspmawsaccount) | Returns information about the current status of an AWS account. | +| [CreateCSPMAwsAccount](#createcspmawsaccount) | Creates a new account in our system for a customer and generates a script for them to run in their AWS cloud environment to grant us access. | +| [DeleteCSPMAwsAccount](#deletecspmawsaccount) | Deletes an existing AWS account or organization in our system. | +| [GetCSPMAwsConsoleSetupURLs](#getcspmawsconsolesetupurls) | Return a URL for customer to visit in their cloud environment to grant us access to their AWS environment. | +| [GetCSPMAwsAccountScriptsAttachment](#getcspmawsaccountscriptsattachment) | Return a script for customer to run in their cloud environment to grant us access to their AWS environment as a downloadable attachment. | +| [GetCSPMAzureAccount](#getcspmazureaccount) | Return information about Azure account registration | +| [CreateCSPMAzureAccount](#createcspmazureaccount) | Creates a new account in our system for a customer and generates a script for them to run in their cloud environment to grant us access. | +| [DeleteCSPMAzureAccount](#deletecspmazureaccount) | Deletes an Azure subscription from the system. | +| [UpdateCSPMAzureAccountClientID](#updatecspmazureaccountclientid) | Update an Azure service account in our system by with the user-created client_id created with the public key we've provided | +| [GetCSPMAzureUserScriptsAttachment](#getcspmazureuserscriptsattachment) | Return a script for customer to run in their cloud environment to grant us access to their Azure environment as a downloadable attachment | +| [GetCSPMPolicy](#getcspmpolicy) | Given a policy ID, returns detailed policy information. | +| [GetCSPMPolicySettings](#getcspmpolicysettings) | Returns information about current policy settings. | +| [UpdateCSPMPolicySettings](#updatecspmpolicysettings) | Updates a policy setting - can be used to override policy severity or to disable a policy entirely. | +| [GetCSPMScanSchedule](#getcspmscanschedule) | Returns scan schedule configuration for one or more cloud platforms. | +| [UpdateCSPMScanSchedule](#updatecspmscanschedule) | Updates scan schedule configuration for one or more cloud platforms. | +### GetCSPMAwsAccount +Returns information about the current status of an AWS account. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __scan-type__ | query | _string_ | Type of scan, dry or full, to perform on selected accounts | +| | __ids__ | query | array (_string_) | AWS account IDs | +| | __organization-ids__ | query | array (_string_) | AWS organization IDs | +| | __status__ | query | _string_ | Account status to filter results by. | +| | __limit__ | query | _integer_ | The maximum records to return. Defaults to 100. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'scan-type': 'string', + 'organization-ids': [ + 'string', + 'string' + ], + 'status': 'string', + 'limit': integer, + 'offset': integer +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetCSPMAwsAccount', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### CreateCSPMAwsAccount +Creates a new account in our system for a customer and generates a script for them to run in their AWS cloud environment to grant us access. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateCSPMAwsAccount', body=BODY) +print(response) +falcon.deauthenticate() +``` +### DeleteCSPMAwsAccount +Deletes an existing AWS account or organization in our system. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __ids__ | query | array (_string_) | AWS account IDs to remove | +| | __organization-ids__ | query | array (_string_) | AWS organization IDs to remove | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'organization-ids': [ + 'string', + 'string' + ] +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteCSPMAwsAccount', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetCSPMAwsConsoleSetupURLs +Return a URL for customer to visit in their cloud environment to grant us access to their AWS environment. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMAwsConsoleSetupURLs') +print(response) +falcon.deauthenticate() +``` +### GetCSPMAwsAccountScriptsAttachment +Return a script for customer to run in their cloud environment to grant us access to their AWS environment as a downloadable attachment. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMAwsAccountScriptsAttachment') +print(response) +falcon.deauthenticate() +``` +### GetCSPMAzureAccount +Return information about Azure account registration + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __ids__ | query | array (_string_) | SubscriptionIDs of accounts to select for this status operation. If this is empty then all accounts are returned. | +| | __scan-type__ | query | _string_ | Type of scan, dry or full, to perform on selected accounts | +| | __status__ | query | _string_ | Account status to filter results by. | +| | __limit__ | query | _integer_ | The maximum records to return. Defaults to 100. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'scan-type': 'string', + 'status': 'string', + 'limit': integer, + 'offset': integer +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetCSPMAzureAccount', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### CreateCSPMAzureAccount +Creates a new account in our system for a customer and generates a script for them to run in their cloud environment to grant us access. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateCSPMAzureAccount', body=BODY) +print(response) +falcon.deauthenticate() +``` +### DeleteCSPMAzureAccount +Deletes an Azure subscription from the system. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | Azure subscription IDs to remove | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteCSPMAzureAccount', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### UpdateCSPMAzureAccountClientID +Update an Azure service account in our system by with the user-created client_id created with the public key we've provided + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | query | _string_ | ClientID to use for the Service Principal associated with the customer's Azure account | +| | __tenant-id__ | query | _string_ | Tenant ID to update client ID for. Required if multiple tenants are registered. | +| :white_check_mark: | __body__ | body | _string_ | This is a placeholder only. Please ignore this field. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string', + 'tenant-id': 'string' +} + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateCSPMAzureAccountClientID', parameters=PARAMS, body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetCSPMAzureUserScriptsAttachment +Return a script for customer to run in their cloud environment to grant us access to their Azure environment as a downloadable attachment + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __tenant-id__ | query | _string_ | Tenant ID to generate script for. Defaults to most recently registered tenant. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'tenant-id': 'string' +} + +response = falcon.command('GetCSPMAzureUserScriptsAttachment', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetCSPMPolicy +Given a policy ID, returns detailed policy information. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | Policy ID | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetCSPMPolicy', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetCSPMPolicySettings +Returns information about current policy settings. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __service__ | query | _string_ | Service type to filter policy settings by. | +| | __policy-id__ | query | _string_ | Policy ID | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'service': 'string', + 'policy-id': 'string' +} + +response = falcon.command('GetCSPMPolicySettings', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### UpdateCSPMPolicySettings +Updates a policy setting - can be used to override policy severity or to disable a policy entirely. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateCSPMPolicySettings', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetCSPMScanSchedule +Returns scan schedule configuration for one or more cloud platforms. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __cloud-platform__ | query | array (_string_) | Cloud Platform | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'cloud-platform': [ + 'string', + 'string' + ] +} + +response = falcon.command('GetCSPMScanSchedule', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### UpdateCSPMScanSchedule +Updates scan schedule configuration for one or more cloud platforms. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('UpdateCSPMScanSchedule', body=BODY) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/custom-ioa.md b/docs/uber-class/custom-ioa.md new file mode 100644 index 00000000..60793bea --- /dev/null +++ b/docs/uber-class/custom-ioa.md @@ -0,0 +1,620 @@ +# Using the Custom IOA service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [get_patterns](#get-patterns) | Get pattern severities by ID. | +| [get_platformsMixin0](#get-platformsmixin0) | Get platforms by ID. | +| [get_rule_groupsMixin0](#get-rule-groupsmixin0) | Get rule groups by ID. | +| [create_rule_groupMixin0](#create-rule-groupmixin0) | Create a rule group for a platform with a name and an optional description. Returns the rule group. | +| [delete_rule_groupsMixin0](#delete-rule-groupsmixin0) | Delete rule groups by ID. | +| [update_rule_groupMixin0](#update-rule-groupmixin0) | Update a rule group. The following properties can be modified: name, description, enabled. | +| [get_rule_types](#get-rule-types) | Get rule types by ID. | +| [get_rules_get](#get-rules-get) | Get rules by ID and optionally version in the following format: `ID[:version]`. | +| [get_rulesMixin0](#get-rulesmixin0) | Get rules by ID and optionally version in the following format: `ID[:version]`. The max number of IDs is constrained by URL size. | +| [create_rule](#create-rule) | Create a rule within a rule group. Returns the rule. | +| [delete_rules](#delete-rules) | Delete rules from a rule group by ID. | +| [update_rules](#update-rules) | Update rules within a rule group. Return the updated rules. | +| [validate](#validate) | Validates field values and checks for matches if a test string is provided. | +| [query_patterns](#query-patterns) | Get all pattern severity IDs. | +| [query_platformsMixin0](#query-platformsmixin0) | Get all platform IDs. | +| [query_rule_groups_full](#query-rule-groups-full) | Find all rule groups matching the query with optional filter. | +| [query_rule_groupsMixin0](#query-rule-groupsmixin0) | Finds all rule group IDs matching the query with optional filter. | +| [query_rule_types](#query-rule-types) | Get all rule type IDs. | +| [query_rulesMixin0](#query-rulesmixin0) | Finds all rule IDs matching the query with optional filter. | +### get_patterns +Get pattern severities by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-patterns', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_platformsMixin0 +Get platforms by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-platformsMixin0', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_rule_groupsMixin0 +Get rule groups by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-rule-groupsMixin0', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### create_rule_groupMixin0 +Create a rule group for a platform with a name and an optional description. Returns the rule group. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('create-rule-groupMixin0', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### delete_rule_groupsMixin0 +Delete rule groups by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| | __comment__ | query | _string_ | Explains why the entity is being deleted | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('delete-rule-groupsMixin0', parameters=PARAMS, headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### update_rule_groupMixin0 +Update a rule group. The following properties can be modified: name, description, enabled. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('update-rule-groupMixin0', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### get_rule_types +Get rule types by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-rule-types', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### get_rules_get +Get rules by ID and optionally version in the following format: `ID[:version]`. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | The "ids" field contains a list of the rules to retrieve. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('get-rules-get', body=BODY) +print(response) +falcon.deauthenticate() +``` +### get_rulesMixin0 +Get rules by ID and optionally version in the following format: `ID[:version]`. The max number of IDs is constrained by URL size. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('get-rulesMixin0', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### create_rule +Create a rule within a rule group. Returns the rule. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('create-rule', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### delete_rules +Delete rules from a rule group by ID. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| :white_check_mark: | __rule_group_id__ | query | _string_ | The parent rule group | +| | __comment__ | query | _string_ | Explains why the entity is being deleted | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the entities | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'rule_group_id': 'string', + 'comment': 'string' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('delete-rules', parameters=PARAMS, headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### update_rules +Update rules within a rule group. Return the updated rules. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __X-CS-USERNAME__ | header | _string_ | The user ID | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +HEADERS = { + 'X-CS-USERNAME': 'string' +} + +response = falcon.command('update-rules', body=BODY, headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### validate +Validates field values and checks for matches if a test string is provided. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('validate', body=BODY) +print(response) +falcon.deauthenticate() +``` +### query_patterns +Get all pattern severity IDs. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-patterns', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_platformsMixin0 +Get all platform IDs. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-platformsMixin0', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rule_groups_full +Find all rule groups matching the query with optional filter. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: {created_by, created_on, modified_by, modified_on, enabled, name, description} | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: [enabled platform name description rules.action_label rules.name rules.description rules.pattern_severity rules.ruletype_name rules.enabled]. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-rule-groups-full', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rule_groupsMixin0 +Finds all rule group IDs matching the query with optional filter. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: {created_by, created_on, modified_by, modified_on, enabled, name, description} | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: [enabled platform name description rules.action_label rules.name rules.description rules.pattern_severity rules.ruletype_name rules.enabled]. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-rule-groupsMixin0', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rule_types +Get all rule type IDs. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-rule-types', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### query_rulesMixin0 +Finds all rule IDs matching the query with optional filter. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __sort__ | query | _string_ | Possible order by fields: {rules.ruletype_name, rules.enabled, rules.created_by, rules.current_version.name, rules.current_version.modified_by, rules.created_on, rules.current_version.description, rules.current_version.pattern_severity, rules.current_version.action_label, rules.current_version.modified_on} | +| | __filter__ | query | _string_ | FQL query specifying the filter parameters. Filter term criteria: [enabled platform name description rules.action_label rules.name rules.description rules.pattern_severity rules.ruletype_name rules.enabled]. Filter range criteria: created_on, modified_on; use any common date format, such as '2010-05-15T14:55:21.892315096Z'. | +| | __q__ | query | _string_ | Match query criteria, which includes all the filter string fields | +| | __offset__ | query | _string_ | Starting index of overall result set from which to return IDs | +| | __limit__ | query | _integer_ | Number of IDs to return | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'sort': 'string', + 'filter': 'string', + 'q': 'string', + 'offset': 'string', + 'limit': integer +} + +response = falcon.command('query-rulesMixin0', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/d4c-registration.md b/docs/uber-class/d4c-registration.md new file mode 100644 index 00000000..2fa7e73e --- /dev/null +++ b/docs/uber-class/d4c-registration.md @@ -0,0 +1,255 @@ +# Using the D4C Registration service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetCSPMAzureAccount](#getcspmazureaccount) | Return information about Azure account registration | +| [CreateCSPMAzureAccount](#createcspmazureaccount) | Creates a new account in our system for a customer and generates a script for them to run in their cloud environment to grant us access. | +| [UpdateCSPMAzureAccountClientID](#updatecspmazureaccountclientid) | Update an Azure service account in our system by with the user-created client_id created with the public key we've provided | +| [GetCSPMAzureUserScriptsAttachment](#getcspmazureuserscriptsattachment) | Return a script for customer to run in their cloud environment to grant us access to their Azure environment as a downloadable attachment | +| [GetCSPMAzureUserScripts](#getcspmazureuserscripts) | Return a script for customer to run in their cloud environment to grant us access to their Azure environment | +| [GetCSPMCGPAccount](#getcspmcgpaccount) | Returns information about the current status of an GCP account. | +| [CreateCSPMGCPAccount](#createcspmgcpaccount) | Creates a new account in our system for a customer and generates a new service account for them to add access to in their GCP environment to grant us access. | +| [GetCSPMGCPUserScriptsAttachment](#getcspmgcpuserscriptsattachment) | Return a script for customer to run in their cloud environment to grant us access to their GCP environment as a downloadable attachment | +| [GetCSPMGCPUserScripts](#getcspmgcpuserscripts) | Return a script for customer to run in their cloud environment to grant us access to their GCP environment | +### GetCSPMAzureAccount +Return information about Azure account registration + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __ids__ | query | array (_string_) | SubscriptionIDs of accounts to select for this status operation. If this is empty then all accounts are returned. | +| | __scan-type__ | query | _string_ | Type of scan, dry or full, to perform on selected accounts | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'scan-type': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetCSPMAzureAccount', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### CreateCSPMAzureAccount +Creates a new account in our system for a customer and generates a script for them to run in their cloud environment to grant us access. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateCSPMAzureAccount', body=BODY) +print(response) +falcon.deauthenticate() +``` +### UpdateCSPMAzureAccountClientID +Update an Azure service account in our system by with the user-created client_id created with the public key we've provided + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | query | _string_ | ClientID to use for the Service Principal associated with the customer's Azure account | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string' +} + +response = falcon.command('UpdateCSPMAzureAccountClientID', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetCSPMAzureUserScriptsAttachment +Return a script for customer to run in their cloud environment to grant us access to their Azure environment as a downloadable attachment + +#### Content-Type +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMAzureUserScriptsAttachment') +print(response) +falcon.deauthenticate() +``` +### GetCSPMAzureUserScripts +Return a script for customer to run in their cloud environment to grant us access to their Azure environment + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMAzureUserScripts') +print(response) +falcon.deauthenticate() +``` +### GetCSPMCGPAccount +Returns information about the current status of an GCP account. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __scan-type__ | query | _string_ | Type of scan, dry or full, to perform on selected accounts | +| | __ids__ | query | array (_string_) | Parent IDs of accounts | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'scan-type': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetCSPMCGPAccount', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### CreateCSPMGCPAccount +Creates a new account in our system for a customer and generates a new service account for them to add access to in their GCP environment to grant us access. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('CreateCSPMGCPAccount', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetCSPMGCPUserScriptsAttachment +Return a script for customer to run in their cloud environment to grant us access to their GCP environment as a downloadable attachment + +#### Content-Type +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMGCPUserScriptsAttachment') +print(response) +falcon.deauthenticate() +``` +### GetCSPMGCPUserScripts +Return a script for customer to run in their cloud environment to grant us access to their GCP environment + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetCSPMGCPUserScripts') +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/installation-tokens.md b/docs/uber-class/installation-tokens.md new file mode 100644 index 00000000..03330b9f --- /dev/null +++ b/docs/uber-class/installation-tokens.md @@ -0,0 +1,247 @@ +# Using the Installation Tokens service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [audit_events_read](#audit-events-read) | Gets the details of one or more audit events by id. | +| [customer_settings_read](#customer-settings-read) | Check current installation token settings. | +| [tokens_read](#tokens-read) | Gets the details of one or more tokens by id. | +| [tokens_create](#tokens-create) | Creates a token. | +| [tokens_delete](#tokens-delete) | Deletes a token immediately. To revoke a token, use PATCH /installation-tokens/entities/tokens/v1 instead. | +| [tokens_update](#tokens-update) | Updates one or more tokens. Use this endpoint to edit labels, change expiration, revoke, or restore. | +| [audit_events_query](#audit-events-query) | Search for audit events by providing an FQL filter and paging details. | +| [tokens_query](#tokens-query) | Search for tokens by providing an FQL filter and paging details. | +### audit_events_read +Gets the details of one or more audit events by id. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __ids__ | query | array (_string_) | IDs of audit events to retrieve details for | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('audit-events-read', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### customer_settings_read +Check current installation token settings. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('customer-settings-read') +print(response) +falcon.deauthenticate() +``` +### tokens_read +Gets the details of one or more tokens by id. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __ids__ | query | array (_string_) | IDs of tokens to retrieve details for | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('tokens-read', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### tokens_create +Creates a token. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('tokens-create', body=BODY) +print(response) +falcon.deauthenticate() +``` +### tokens_delete +Deletes a token immediately. To revoke a token, use PATCH /installation-tokens/entities/tokens/v1 instead. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The token ids to delete. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('tokens-delete', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### tokens_update +Updates one or more tokens. Use this endpoint to edit labels, change expiration, revoke, or restore. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The token ids to update. | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('tokens-update', body=BODY, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### audit_events_query +Search for audit events by providing an FQL filter and paging details. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The offset to start retrieving records from. | +| | __limit__ | query | _integer_ | The maximum records to return. [1-1000]. Defaults to 50. | +| | __sort__ | query | _string_ | The property to sort by (e.g. timestamp.desc). | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results (e.g., `action:'token_create'`). | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('audit-events-query', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### tokens_query +Search for tokens by providing an FQL filter and paging details. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The offset to start retrieving records from. | +| | __limit__ | query | _integer_ | The maximum records to return. [1-1000]. Defaults to 50. | +| | __sort__ | query | _string_ | The property to sort by (e.g. created_timestamp.desc). | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results (e.g., `status:'valid'`). | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('tokens-query', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/ioa-exclusions.md b/docs/uber-class/ioa-exclusions.md new file mode 100644 index 00000000..6d45ec4d --- /dev/null +++ b/docs/uber-class/ioa-exclusions.md @@ -0,0 +1,157 @@ +# Using the IOA Exclusions service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [getIOAExclusionsV1](#getioaexclusionsv1) | Get a set of IOA Exclusions by specifying their IDs | +| [createIOAExclusionsV1](#createioaexclusionsv1) | Create the IOA exclusions | +| [deleteIOAExclusionsV1](#deleteioaexclusionsv1) | Delete the IOA exclusions by id | +| [updateIOAExclusionsV1](#updateioaexclusionsv1) | Update the IOA exclusions | +| [queryIOAExclusionsV1](#queryioaexclusionsv1) | Search for IOA exclusions. | +### getIOAExclusionsV1 +Get a set of IOA Exclusions by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to retrieve | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getIOAExclusionsV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createIOAExclusionsV1 +Create the IOA exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createIOAExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteIOAExclusionsV1 +Delete the IOA exclusions by id + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to delete | +| | __comment__ | query | _string_ | Explains why this exclusions was deleted | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteIOAExclusionsV1', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateIOAExclusionsV1 +Update the IOA exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateIOAExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryIOAExclusionsV1 +Search for IOA exclusions. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500] | +| | __sort__ | query | _string_ | The sort expression that should be used to sort the results. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryIOAExclusionsV1', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/malquery.md b/docs/uber-class/malquery.md new file mode 100644 index 00000000..4fba84d7 --- /dev/null +++ b/docs/uber-class/malquery.md @@ -0,0 +1,256 @@ +# Using the Malquery service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetMalQueryQuotasV1](#getmalqueryquotasv1) | Get information about search and download quotas in your environment | +| [PostMalQueryFuzzySearchV1](#postmalqueryfuzzysearchv1) | Search Falcon MalQuery quickly, but with more potential for false positives. Search for a combination of hex patterns and strings in order to identify samples based upon file content at byte level granularity. | +| [GetMalQueryDownloadV1](#getmalquerydownloadv1) | Download a file indexed by MalQuery. Specify the file using its SHA256. Only one file is supported at this time | +| [GetMalQueryMetadataV1](#getmalquerymetadatav1) | Retrieve indexed files metadata by their hash | +| [GetMalQueryRequestV1](#getmalqueryrequestv1) | Check the status and results of an asynchronous request, such as hunt or exact-search. Supports a single request id at this time. | +| [GetMalQueryEntitiesSamplesFetchV1](#getmalqueryentitiessamplesfetchv1) | Fetch a zip archive with password 'infected' containing the samples. Call this once the /entities/samples-multidownload request has finished processing | +| [PostMalQueryEntitiesSamplesMultidownloadV1](#postmalqueryentitiessamplesmultidownloadv1) | Schedule samples for download. Use the result id with the /request endpoint to check if the download is ready after which you can call the /entities/samples-fetch to get the zip | +| [PostMalQueryExactSearchV1](#postmalqueryexactsearchv1) | Search Falcon MalQuery for a combination of hex patterns and strings in order to identify samples based upon file content at byte level granularity. You can filter results on criteria such as file type, file size and first seen date. Returns a request id which can be used with the /request endpoint | +| [PostMalQueryHuntV1](#postmalqueryhuntv1) | Schedule a YARA-based search for execution. Returns a request id which can be used with the /request endpoint | +### GetMalQueryQuotasV1 +Get information about search and download quotas in your environment + +#### Content-Type +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetMalQueryQuotasV1') +print(response) +falcon.deauthenticate() +``` +### PostMalQueryFuzzySearchV1 +Search Falcon MalQuery quickly, but with more potential for false positives. Search for a combination of hex patterns and strings in order to identify samples based upon file content at byte level granularity. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Fuzzy search parameters. See model for more details. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PostMalQueryFuzzySearchV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetMalQueryDownloadV1 +Download a file indexed by MalQuery. Specify the file using its SHA256. Only one file is supported at this time + +#### Content-Type +- Produces: _application/octet-stream_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The file SHA256. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetMalQueryDownloadV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetMalQueryMetadataV1 +Retrieve indexed files metadata by their hash + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The file SHA256. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetMalQueryMetadataV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetMalQueryRequestV1 +Check the status and results of an asynchronous request, such as hunt or exact-search. Supports a single request id at this time. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | Identifier of a MalQuery request | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetMalQueryRequestV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetMalQueryEntitiesSamplesFetchV1 +Fetch a zip archive with password 'infected' containing the samples. Call this once the /entities/samples-multidownload request has finished processing + +#### Content-Type +- Produces: _application/zip_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | _string_ | Multidownload job id | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetMalQueryEntitiesSamplesFetchV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### PostMalQueryEntitiesSamplesMultidownloadV1 +Schedule samples for download. Use the result id with the /request endpoint to check if the download is ready after which you can call the /entities/samples-fetch to get the zip + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Download request. See model for more details. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PostMalQueryEntitiesSamplesMultidownloadV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### PostMalQueryExactSearchV1 +Search Falcon MalQuery for a combination of hex patterns and strings in order to identify samples based upon file content at byte level granularity. You can filter results on criteria such as file type, file size and first seen date. Returns a request id which can be used with the /request endpoint + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Exact search parameters. See model for more details. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PostMalQueryExactSearchV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### PostMalQueryHuntV1 +Schedule a YARA-based search for execution. Returns a request id which can be used with the /request endpoint + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Hunt parameters. See model for more details. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('PostMalQueryHuntV1', body=BODY) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/ml-exclusions.md b/docs/uber-class/ml-exclusions.md new file mode 100644 index 00000000..ea829116 --- /dev/null +++ b/docs/uber-class/ml-exclusions.md @@ -0,0 +1,157 @@ +# Using the ML Exclusions service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [getMLExclusionsV1](#getmlexclusionsv1) | Get a set of ML Exclusions by specifying their IDs | +| [createMLExclusionsV1](#createmlexclusionsv1) | Create the ML exclusions | +| [deleteMLExclusionsV1](#deletemlexclusionsv1) | Delete the ML exclusions by id | +| [updateMLExclusionsV1](#updatemlexclusionsv1) | Update the ML exclusions | +| [queryMLExclusionsV1](#querymlexclusionsv1) | Search for ML exclusions. | +### getMLExclusionsV1 +Get a set of ML Exclusions by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to retrieve | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getMLExclusionsV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createMLExclusionsV1 +Create the ML exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createMLExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteMLExclusionsV1 +Delete the ML exclusions by id + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to delete | +| | __comment__ | query | _string_ | Explains why this exclusions was deleted | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteMLExclusionsV1', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateMLExclusionsV1 +Update the ML exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateMLExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### queryMLExclusionsV1 +Search for ML exclusions. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500] | +| | __sort__ | query | _string_ | The sort expression that should be used to sort the results. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('queryMLExclusionsV1', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/quick-scan.md b/docs/uber-class/quick-scan.md new file mode 100644 index 00000000..5dc5ae13 --- /dev/null +++ b/docs/uber-class/quick-scan.md @@ -0,0 +1,126 @@ +# Using the Quick Scan service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetScansAggregates](#getscansaggregates) | Get scans aggregations as specified via json in request body. | +| [GetScans](#getscans) | Check the status of a volume scan. Time required for analysis increases with the number of samples in a volume but usually it should take less than 1 minute | +| [ScanSamples](#scansamples) | Submit a volume of files for ml scanning. Time required for analysis increases with the number of samples in a volume but usually it should take less than 1 minute | +| [QuerySubmissionsMixin0](#querysubmissionsmixin0) | Find IDs for submitted scans by providing an FQL filter and paging details. Returns a set of volume IDs that match your criteria. | +### GetScansAggregates +Get scans aggregations as specified via json in request body. + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('GetScansAggregates', body=BODY) +print(response) +falcon.deauthenticate() +``` +### GetScans +Check the status of a volume scan. Time required for analysis increases with the number of samples in a volume but usually it should take less than 1 minute + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | ID of a submitted scan | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetScans', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### ScanSamples +Submit a volume of files for ml scanning. Time required for analysis increases with the number of samples in a volume but usually it should take less than 1 minute + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ | Submit a batch of SHA256s for ml scanning. The samples must have been previously uploaded through `/samples/entities/samples/v3` | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('ScanSamples', body=BODY) +print(response) +falcon.deauthenticate() +``` +### QuerySubmissionsMixin0 +Find IDs for submitted scans by providing an FQL filter and paging details. Returns a set of volume IDs that match your criteria. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | Optional filter and sort criteria in the form of an FQL query. For more information about FQL queries, see [our FQL documentation in Falcon](https://falcon.crowdstrike.com/support/documentation/45/falcon-query-language-feature-guide). | +| | __offset__ | query | _string_ | The offset to start retrieving submissions from. | +| | __limit__ | query | _integer_ | Maximum number of volume IDs to return. Max: 5000. | +| | __sort__ | query | _string_ | Sort order: `asc` or `desc`. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': 'string', + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('QuerySubmissionsMixin0', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/sample-uploads.md b/docs/uber-class/sample-uploads.md new file mode 100644 index 00000000..627eca68 --- /dev/null +++ b/docs/uber-class/sample-uploads.md @@ -0,0 +1,122 @@ +# Using the Sample Uploads service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetSampleV3](#getsamplev3) | Retrieves the file associated with the given ID (SHA256) | +| [UploadSampleV3](#uploadsamplev3) | Upload a file for further cloud analysis. After uploading, call the specific analysis API endpoint. | +| [DeleteSampleV3](#deletesamplev3) | Removes a sample, including file, meta and submissions from the collection | +### GetSampleV3 +Retrieves the file associated with the given ID (SHA256) + +#### Content-Type +- Produces: _application/octet-stream_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __ids__ | query | _string_ | The file SHA256. | +| | __password_protected__ | query | _string_ | Flag whether the sample should be zipped and password protected with pass='infected' | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'password_protected': 'string' +} + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetSampleV3', parameters=PARAMS, headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### UploadSampleV3 +Upload a file for further cloud analysis. After uploading, call the specific analysis API endpoint. + +#### Content-Type +- Consumes: _application/octet-stream_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __body__ | body | _string_ | Content of the uploaded sample in binary format. For example, use `--data-binary @$FILE_PATH` when using cURL. Max file size: 100 MB. Accepted file formats: - Portable executables: `.exe`, `.scr`, `.pif`, `.dll`, `.com`, `.cpl`, etc. - Office documents: `.doc`, `.docx`, `.ppt`, `.pps`, `.pptx`, `.ppsx`, `.xls`, `.xlsx`, `.rtf`, `.pub` - PDF - APK - Executable JAR - Windows script component: `.sct` - Windows shortcut: `.lnk` - Windows help: `.chm` - HTML application: `.hta` - Windows script file: `.wsf` - Javascript: `.js` - Visual Basic: `.vbs`, `.vbe` - Shockwave Flash: `.swf` - Perl: `.pl` - Powershell: `.ps1`, `.psd1`, `.psm1` - Scalable vector graphics: `.svg` - Python: `.py` - Linux ELF executables - Email files: MIME RFC 822 `.eml`, Outlook `.msg`. | +| :white_check_mark: | __upfile__ | formData | _file_ | The binary file. | +| :white_check_mark: | __file_name__ | query | _string_ | Name of the file. | +| | __comment__ | query | _string_ | A descriptive comment to identify the file for other users. | +| | __is_confidential__ | query | _boolean_ | Defines visibility of this file in Falcon MalQuery, either via the API or the Falcon console. - `true`: File is only shown to users within your customer account - `false`: File can be seen by other CrowdStrike customers Default: `true`. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'file_name': 'string', + 'comment': 'string', + 'is_confidential': boolean +} + +BODY = { + 'Body Payload': 'See body description above' +} + +FILENAME = 'testfile.jpg' +PAYLOAD = open(FILENAME, 'rb').read() + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +response = falcon.command('UploadSampleV3', parameters=PARAMS, body=BODY, data=PAYLOAD, file_name=FILENAME, content_type='application/octet-stream', headers=HEADERS) +print(response) +falcon.deauthenticate() +``` +### DeleteSampleV3 +Removes a sample, including file, meta and submissions from the collection + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __X-CS-USERUUID__ | header | _string_ | User UUID | +| :white_check_mark: | __ids__ | query | _string_ | The file SHA256. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +HEADERS = { + 'X-CS-USERUUID': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('DeleteSampleV3', headers=HEADERS, ids=IDS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/sensor-download.md b/docs/uber-class/sensor-download.md new file mode 100644 index 00000000..eddcb489 --- /dev/null +++ b/docs/uber-class/sensor-download.md @@ -0,0 +1,159 @@ +# Using the Sensor Download service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [GetCombinedSensorInstallersByQuery](#getcombinedsensorinstallersbyquery) | Get sensor installer details by provided query | +| [DownloadSensorInstallerById](#downloadsensorinstallerbyid) | Download sensor installer by SHA256 ID | +| [GetSensorInstallersEntities](#getsensorinstallersentities) | Get sensor installer details by provided SHA256 IDs | +| [GetSensorInstallersCCIDByQuery](#getsensorinstallersccidbyquery) | Get CCID to use with sensor installers | +| [GetSensorInstallersByQuery](#getsensorinstallersbyquery) | Get sensor installer IDs by provided query | +### GetCombinedSensorInstallersByQuery +Get sensor installer details by provided query + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The first item to return, where 0 is the latest item. Use with the limit parameter to manage pagination of results. | +| | __limit__ | query | _integer_ | The number of items to return in this response (default: 100, max: 500). Use with the offset parameter to manage pagination of results. | +| | __sort__ | query | _string_ | Sort items using their properties. Common sort options include:
  • version|asc
  • release_date|desc
| +| | __filter__ | query | _string_ | Filter items using a query in Falcon Query Language (FQL). An asterisk wildcard * includes all results. Common filter options include:
  • platform:"windows"
  • version:>"5.2"
| +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('GetCombinedSensorInstallersByQuery', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### DownloadSensorInstallerById +Download sensor installer by SHA256 ID + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __id__ | query | _string_ | SHA256 of the installer to download | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'id': 'string' +} + +response = falcon.command('DownloadSensorInstallerById', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` +### GetSensorInstallersEntities +Get sensor installer details by provided SHA256 IDs + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The IDs of the installers | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('GetSensorInstallersEntities', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### GetSensorInstallersCCIDByQuery +Get CCID to use with sensor installers + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +No parameters +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +response = falcon.command('GetSensorInstallersCCIDByQuery') +print(response) +falcon.deauthenticate() +``` +### GetSensorInstallersByQuery +Get sensor installer IDs by provided query + +#### Content-Type +- Consumes: _application/json_ +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __offset__ | query | _integer_ | The first item to return, where 0 is the latest item. Use with the limit parameter to manage pagination of results. | +| | __limit__ | query | _integer_ | The number of items to return in this response (default: 100, max: 500). Use with the offset parameter to manage pagination of results. | +| | __sort__ | query | _string_ | Sort items using their properties. Common sort options include:
  • version|asc
  • release_date|desc
| +| | __filter__ | query | _string_ | Filter items using a query in Falcon Query Language (FQL). An asterisk wildcard * includes all results. Common filter options include:
  • platform:"windows"
  • version:>"5.2"
| +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'offset': integer, + 'limit': integer, + 'sort': 'string', + 'filter': 'string' +} + +response = falcon.command('GetSensorInstallersByQuery', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/docs/uber-class/sensor-visibility-exclusions.md b/docs/uber-class/sensor-visibility-exclusions.md new file mode 100644 index 00000000..488e8f94 --- /dev/null +++ b/docs/uber-class/sensor-visibility-exclusions.md @@ -0,0 +1,157 @@ +# Using the Sensor Visibility Exclusions service collection +![Uber class support](https://img.shields.io/badge/Uber%20class%20support-%E2%9C%93%20Yes-green.svg) ![Uber class support](https://img.shields.io/badge/Service%20class%20support-X%20No-red.svg) +## Table of Contents +| API Function | Description | +| :--- | :--- | +| [getSensorVisibilityExclusionsV1](#getsensorvisibilityexclusionsv1) | Get a set of Sensor Visibility Exclusions by specifying their IDs | +| [createSVExclusionsV1](#createsvexclusionsv1) | Create the sensor visibility exclusions | +| [deleteSensorVisibilityExclusionsV1](#deletesensorvisibilityexclusionsv1) | Delete the sensor visibility exclusions by id | +| [updateSensorVisibilityExclusionsV1](#updatesensorvisibilityexclusionsv1) | Update the sensor visibility exclusions | +| [querySensorVisibilityExclusionsV1](#querysensorvisibilityexclusionsv1) | Search for sensor visibility exclusions. | +### getSensorVisibilityExclusionsV1 +Get a set of Sensor Visibility Exclusions by specifying their IDs + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to retrieve | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('getSensorVisibilityExclusionsV1', ids=IDS) +print(response) +falcon.deauthenticate() +``` +### createSVExclusionsV1 +Create the sensor visibility exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('createSVExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### deleteSensorVisibilityExclusionsV1 +Delete the sensor visibility exclusions by id + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __ids__ | query | array (_string_) | The ids of the exclusions to delete | +| | __comment__ | query | _string_ | Explains why this exclusions was deleted | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'comment': 'string' +} + +IDS = 'ID1,ID2,ID3' + +response = falcon.command('deleteSensorVisibilityExclusionsV1', parameters=PARAMS, ids=IDS) +print(response) +falcon.deauthenticate() +``` +### updateSensorVisibilityExclusionsV1 +Update the sensor visibility exclusions + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| :white_check_mark: | __body__ | body | _string_ +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +BODY = { + 'Body Payload': 'See body description above' +} + +response = falcon.command('updateSensorVisibilityExclusionsV1', body=BODY) +print(response) +falcon.deauthenticate() +``` +### querySensorVisibilityExclusionsV1 +Search for sensor visibility exclusions. + +#### Content-Type +- Produces: _application/json_ +#### Parameters +| Required | Name | Type | Datatype | Description | +| :---: | :---- | :---- | :-------- | :---------- | +| | __filter__ | query | _string_ | The filter expression that should be used to limit the results. | +| | __offset__ | query | _integer_ | The offset to start retrieving records from | +| | __limit__ | query | _integer_ | The maximum records to return. [1-500] | +| | __sort__ | query | _string_ | The sort expression that should be used to sort the results. | +#### Usage +##### Uber class example +```python +from falconpy import api_complete as FalconSDK + +falcon = FalconSDK.APIHarness(creds={ + 'client_id': falcon_client_id, + 'client_secret': falcon_client_secret + } +) + +PARAMS = { + 'filter': 'string', + 'offset': integer, + 'limit': integer, + 'sort': 'string' +} + +response = falcon.command('querySensorVisibilityExclusionsV1', parameters=PARAMS) +print(response) +falcon.deauthenticate() +``` diff --git a/falconpy/__init__.py b/falconpy/__init__.py deleted file mode 100644 index 6faf7061..00000000 --- a/falconpy/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -falconpy - -The CrowdStrike Falcon API SDK -""" - -__version__ = '0.1.7' -__maintainer__ = 'Joshua Hiller' -__author__ = 'CrowdStrike' -__credits__ = 'CrowdStrike' \ No newline at end of file diff --git a/falconpy/api_complete.py b/falconpy/api_complete.py deleted file mode 100644 index 03e44bb0..00000000 --- a/falconpy/api_complete.py +++ /dev/null @@ -1,418 +0,0 @@ -##################################################################################################### -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# api_complete.py - All-in-one CrowdStrike Falcon OAuth2 API harness # -##################################################################################################### -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import time -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class APIHarness: - """ This one does it all. It's like the One Ring with significantly fewer orcs. """ - - def __init__(self, creds, base_url="https://api.crowdstrike.com"): - """ Instantiates an instance of the base class, ingests credentials and the base URL and initializes global variables. """ - - self.creds = creds - self.base_url = base_url - self.token = False - self.token_expiration = 0 - self.token_renew_window = 20 - self.token_time = time.time() - self.token_expired = lambda: True if (time.time() - self.token_time) >= (self.token_expiration - self.token_renew_window) else False - self.authenticated = False - self.valid_cred_format = lambda: True if "client_id" in self.creds and "client_secret" in self.creds else False - self.headers = lambda: { 'Authorization': 'Bearer {}'.format(self.token) } if self.token else {} - # This is a list of available commands, additional endpoints (commands) can be added ad-hoc - # [Command Name, HTTP Method, Endpoint] - self.commands = [ - ["QueryAWSAccounts", "GET", "/cloud-connect-aws/combined/accounts/v1"], - ["GetAWSSettings", "GET", "/cloud-connect-aws/combined/settings/v1"], - ["GetAWSAccounts", "GET", "/cloud-connect-aws/entities/accounts/v1?ids={}"], - ["ProvisionAWSAccounts", "POST", "/cloud-connect-aws/entities/accounts/v1"], - ["UpdateAWSAccounts", "PATCH", "/cloud-connect-aws/entities/accounts/v1"], - ["DeleteAWSAccounts", "DELETE", "/cloud-connect-aws/entities/accounts/v1?ids={}"], - ["CreateOrUpdateAWSSettings", "POST", "/cloud-connect-aws/entities/settings/v1"], - ["VerifyAWSAccountAccess", "POST", "/cloud-connect-aws/entities/verify-account-access/v1?ids={}"], - ["QueryAWSAccountsForIDs", "GET", "/cloud-connect-aws/queries/accounts/v1"], - ["GetCSPMAzureAccount", "GET", "/cloud-connect-azure/entities/account/v1?ids={}"], - ["CreateCSPMAzureAccount", "POST", "/cloud-connect-azure/entities/account/v1"], - ["UpdateCSPMAzureAccountClientID", "PATCH", "/cloud-connect-azure/entities/client-id/v1"], - ["GetCSPMAzureUserScriptsAttachment", "GET", "/cloud-connect-azure/entities/user-scripts-download/v1"], - ["GetCSPMAzureUserScripts", "GET", "/cloud-connect-azure/entities/user-scripts/v1"], - ["GetCSPMAwsAccount", "GET", "/cloud-connect-cspm-aws/entities/account/v1?ids={}"], - ["CreateCSPMAwsAccount", "POST", "/cloud-connect-cspm-aws/entities/account/v1"], - ["DeleteCSPMAwsAccount", "DELETE", "/cloud-connect-cspm-aws/entities/account/v1?ids={}"], - ["GetCSPMAwsConsoleSetupURLs", "GET", "/cloud-connect-cspm-aws/entities/console-setup-urls/v1"], - ["GetCSPMAwsAccountScriptsAttachment", "GET", "/cloud-connect-cspm-aws/entities/user-scripts-download/v1"], - ["GetCSPMAzureAccount", "GET", "/cloud-connect-cspm-azure/entities/account/v1?ids={}"], - ["CreateCSPMAzureAccount", "POST", "/cloud-connect-cspm-azure/entities/account/v1"], - ["DeleteCSPMAzureAccount", "DELETE", "/cloud-connect-cspm-azure/entities/account/v1?ids={}"], - ["UpdateCSPMAzureAccountClientID", "PATCH", "/cloud-connect-cspm-azure/entities/client-id/v1"], - ["GetCSPMAzureUserScriptsAttachment", "GET", "/cloud-connect-cspm-azure/entities/user-scripts-download/v1"], - ["GetCSPMCGPAccount", "GET", "/cloud-connect-gcp/entities/account/v1?ids={}"], - ["CreateCSPMGCPAccount", "POST", "/cloud-connect-gcp/entities/account/v1"], - ["GetCSPMGCPUserScriptsAttachment", "GET", "/cloud-connect-gcp/entities/user-scripts-download/v1"], - ["GetCSPMGCPUserScripts", "GET", "/cloud-connect-gcp/entities/user-scripts/v1"], - ["GetAggregateDetects", "POST", "/detects/aggregates/detects/GET/v1"], - ["UpdateDetectsByIdsV2", "PATCH", "/detects/entities/detects/v2"], - ["GetDetectSummaries", "POST", "/detects/entities/summaries/GET/v1"], - ["QueryDetects", "GET", "/detects/queries/detects/v1"], - ["queryCombinedGroupMembers", "GET", "/devices/combined/host-group-members/v1"], - ["queryCombinedHostGroups", "GET", "/devices/combined/host-groups/v1"], - ["PerformActionV2", "POST", "/devices/entities/devices-actions/v2"], - ["GetDeviceDetails", "GET", "/devices/entities/devices/v1?ids={}"], - ["performGroupAction", "POST", "/devices/entities/host-group-actions/v1"], - ["getHostGroups", "GET", "/devices/entities/host-groups/v1?ids={}"], - ["createHostGroups", "POST", "/devices/entities/host-groups/v1"], - ["updateHostGroups", "PATCH", "/devices/entities/host-groups/v1"], - ["deleteHostGroups", "DELETE", "/devices/entities/host-groups/v1?ids={}"], - ["QueryHiddenDevices", "GET", "/devices/queries/devices-hidden/v1"], - ["QueryDevicesByFilterScroll", "GET", "/devices/queries/devices-scroll/v1"], - ["QueryDevicesByFilter", "GET", "/devices/queries/devices/v1"], - ["queryGroupMembers", "GET", "/devices/queries/host-group-members/v1"], - ["queryHostGroups", "GET", "/devices/queries/host-groups/v1"], - ["GetArtifacts", "GET", "/falconx/entities/artifacts/v1"], - ["GetSummaryReports", "GET", "/falconx/entities/report-summaries/v1?ids={}"], - ["GetReports", "GET", "/falconx/entities/reports/v1?ids={}"], - ["DeleteReport", "DELETE", "/falconx/entities/reports/v1?ids={}"], - ["GetSubmissions", "GET", "/falconx/entities/submissions/v1?ids={}"], - ["Submit", "POST", "/falconx/entities/submissions/v1"], - ["QueryReports", "GET", "/falconx/queries/reports/v1"], - ["QuerySubmissions", "GET", "/falconx/queries/submissions/v1"], - ["aggregate-events", "POST", "/fwmgr/aggregates/events/GET/v1"], - ["aggregate-policy-rules", "POST", "/fwmgr/aggregates/policy-rules/GET/v1"], - ["aggregate-rule-groups", "POST", "/fwmgr/aggregates/rule-groups/GET/v1"], - ["aggregate-rules", "POST", "/fwmgr/aggregates/rules/GET/v1"], - ["get-events", "GET", "/fwmgr/entities/events/v1?ids={}"], - ["get-firewall-fields", "GET", "/fwmgr/entities/firewall-fields/v1?ids={}"], - ["get-platforms", "GET", "/fwmgr/entities/platforms/v1?ids={}"], - ["get-policy-containers", "GET", "/fwmgr/entities/policies/v1?ids={}"], - ["get-rule-groups", "GET", "/fwmgr/entities/rule-groups/v1?ids={}"], - ["create-rule-group", "POST", "/fwmgr/entities/rule-groups/v1"], - ["update-rule-group", "PATCH", "/fwmgr/entities/rule-groups/v1"], - ["delete-rule-groups", "DELETE", "/fwmgr/entities/rule-groups/v1?ids={}"], - ["get-rules", "GET", "/fwmgr/entities/rules/v1?ids={}"], - ["query-events", "GET", "/fwmgr/queries/events/v1"], - ["query-firewall-fields", "GET", "/fwmgr/queries/firewall-fields/v1"], - ["query-platforms", "GET", "/fwmgr/queries/platforms/v1"], - ["query-policy-rules", "GET", "/fwmgr/queries/policy-rules/v1"], - ["query-rule-groups", "GET", "/fwmgr/queries/rule-groups/v1"], - ["query-rules", "GET", "/fwmgr/queries/rules/v1"], - ["CrowdScore", "GET", "/incidents/combined/crowdscores/v1"], - ["GetBehaviors", "POST", "/incidents/entities/behaviors/GET/v1"], - ["PerformIncidentAction", "POST", "/incidents/entities/incident-actions/v1"], - ["GetIncidents", "POST", "/incidents/entities/incidents/GET/v1"], - ["QueryBehaviors", "GET", "/incidents/queries/behaviors/v1"], - ["QueryIncidents", "GET", "/incidents/queries/incidents/v1"], - ["DevicesCount", "GET", "/indicators/aggregates/devices-count/v1"], - ["GetIOC", "GET", "/indicators/entities/iocs/v1"], - ["CreateIOC", "POST", "/indicators/entities/iocs/v1"], - ["UpdateIOC", "PATCH", "/indicators/entities/iocs/v1"], - ["DeleteIOC", "DELETE", "/indicators/entities/iocs/v1"], - ["DevicesRanOn", "GET", "/indicators/queries/devices/v1"], - ["QueryIOCs", "GET", "/indicators/queries/iocs/v1"], - ["ProcessesRanOn", "GET", "/indicators/queries/processes/v1"], - ["audit-events-read", "GET", "/installation-tokens/entities/audit-events/v1?ids={}"], - ["customer-settings-read", "GET", "/installation-tokens/entities/customer-settings/v1"], - ["tokens-read", "GET", "/installation-tokens/entities/tokens/v1?ids={}"], - ["tokens-create", "POST", "/installation-tokens/entities/tokens/v1"], - ["tokens-update", "PATCH", "/installation-tokens/entities/tokens/v1?ids={}"], - ["tokens-delete", "DELETE", "/installation-tokens/entities/tokens/v1?ids={}"], - ["audit-events-query", "GET", "/installation-tokens/queries/audit-events/v1"], - ["tokens-query", "GET", "/installation-tokens/queries/tokens/v1"], - ["QueryIntelActorEntities", "GET", "/intel/combined/actors/v1"], - ["QueryIntelIndicatorEntities", "GET", "/intel/combined/indicators/v1"], - ["QueryIntelReportEntities", "GET", "/intel/combined/reports/v1"], - ["GetIntelActorEntities", "GET", "/intel/entities/actors/v1?ids={}"], - ["GetIntelIndicatorEntities", "POST", "/intel/entities/indicators/GET/v1"], - ["GetIntelReportPDF", "GET", "/intel/entities/report-files/v1"], - ["GetIntelReportEntities", "GET", "/intel/entities/reports/v1?ids={}"], - ["GetIntelRuleFile", "GET", "/intel/entities/rules-files/v1"], - ["GetLatestIntelRuleFile", "GET", "/intel/entities/rules-latest-files/v1"], - ["GetIntelRuleEntities", "GET", "/intel/entities/rules/v1?ids={}"], - ["QueryIntelActorIds", "GET", "/intel/queries/actors/v1"], - ["QueryIntelIndicatorIds", "GET", "/intel/queries/indicators/v1"], - ["QueryIntelReportIds", "GET", "/intel/queries/reports/v1"], - ["QueryIntelRuleIds", "GET", "/intel/queries/rules/v1"], - ["get-patterns", "GET", "/ioarules/entities/pattern-severities/v1?ids={}"], - ["get-platformsMixin0", "GET", "/ioarules/entities/platforms/v1?ids={}"], - ["get-rule-groupsMixin0", "GET", "/ioarules/entities/rule-groups/v1?ids={}"], - ["create-rule-groupMixin0", "POST", "/ioarules/entities/rule-groups/v1"], - ["update-rule-groupMixin0", "PATCH", "/ioarules/entities/rule-groups/v1"], - ["delete-rule-groupsMixin0", "DELETE", "/ioarules/entities/rule-groups/v1?ids={}"], - ["get-rule-types", "GET", "/ioarules/entities/rule-types/v1?ids={}"], - ["get-rules-get", "POST", "/ioarules/entities/rules/GET/v1"], - ["get-rulesMixin0", "GET", "/ioarules/entities/rules/v1?ids={}"], - ["create-rule", "POST", "/ioarules/entities/rules/v1"], - ["update-rules", "PATCH", "/ioarules/entities/rules/v1"], - ["delete-rules", "DELETE", "/ioarules/entities/rules/v1?ids={}"], - ["validate", "POST", "/ioarules/entities/rules/validate/v1"], - ["query-patterns", "GET", "/ioarules/queries/pattern-severities/v1"], - ["query-platformsMixin0", "GET", "/ioarules/queries/platforms/v1"], - ["query-rule-groups-full", "GET", "/ioarules/queries/rule-groups-full/v1"], - ["query-rule-groupsMixin0", "GET", "/ioarules/queries/rule-groups/v1"], - ["query-rule-types", "GET", "/ioarules/queries/rule-types/v1"], - ["query-rulesMixin0", "GET", "/ioarules/queries/rules/v1"], - ["GetMalQueryQuotasV1", "GET", "/malquery/aggregates/quotas/v1"], - ["PostMalQueryFuzzySearchV1", "POST", "/malquery/combined/fuzzy-search/v1"], - ["GetMalQueryDownloadV1", "GET", "/malquery/entities/download-files/v1?ids={}"], - ["GetMalQueryMetadataV1", "GET", "/malquery/entities/metadata/v1?ids={}"], - ["GetMalQueryRequestV1", "GET", "/malquery/entities/requests/v1?ids={}"], - ["GetMalQueryEntitiesSamplesFetchV1", "GET", "/malquery/entities/samples-fetch/v1?ids={}"], - ["PostMalQueryEntitiesSamplesMultidownloadV1", "POST", "/malquery/entities/samples-multidownload/v1"], - ["PostMalQueryExactSearchV1", "POST", "/malquery/queries/exact-search/v1"], - ["PostMalQueryHuntV1", "POST", "/malquery/queries/hunt/v1"], - ["oauth2RevokeToken", "POST", "/oauth2/revoke"], - ["oauth2AccessToken", "POST", "/oauth2/token"], - ["queryCombinedDeviceControlPolicyMembers", "GET", "/policy/combined/device-control-members/v1"], - ["queryCombinedDeviceControlPolicies", "GET", "/policy/combined/device-control/v1"], - ["queryCombinedFirewallPolicyMembers", "GET", "/policy/combined/firewall-members/v1"], - ["queryCombinedFirewallPolicies", "GET", "/policy/combined/firewall/v1"], - ["queryCombinedPreventionPolicyMembers", "GET", "/policy/combined/prevention-members/v1"], - ["queryCombinedPreventionPolicies", "GET", "/policy/combined/prevention/v1"], - ["revealUninstallToken", "POST", "/policy/combined/reveal-uninstall-token/v1"], - ["queryCombinedSensorUpdateBuilds", "GET", "/policy/combined/sensor-update-builds/v1"], - ["queryCombinedSensorUpdatePolicyMembers", "GET", "/policy/combined/sensor-update-members/v1"], - ["queryCombinedSensorUpdatePolicies", "GET", "/policy/combined/sensor-update/v1"], - ["queryCombinedSensorUpdatePoliciesV2", "GET", "/policy/combined/sensor-update/v2"], - ["performDeviceControlPoliciesAction", "POST", "/policy/entities/device-control-actions/v1"], - ["setDeviceControlPoliciesPrecedence", "POST", "/policy/entities/device-control-precedence/v1"], - ["getDeviceControlPolicies", "GET", "/policy/entities/device-control/v1?ids={}"], - ["createDeviceControlPolicies", "POST", "/policy/entities/device-control/v1"], - ["updateDeviceControlPolicies", "PATCH", "/policy/entities/device-control/v1"], - ["deleteDeviceControlPolicies", "DELETE", "/policy/entities/device-control/v1?ids={}"], - ["performFirewallPoliciesAction", "POST", "/policy/entities/firewall-actions/v1"], - ["setFirewallPoliciesPrecedence", "POST", "/policy/entities/firewall-precedence/v1"], - ["getFirewallPolicies", "GET", "/policy/entities/firewall/v1?ids={}"], - ["createFirewallPolicies", "POST", "/policy/entities/firewall/v1"], - ["updateFirewallPolicies", "PATCH", "/policy/entities/firewall/v1"], - ["deleteFirewallPolicies", "DELETE", "/policy/entities/firewall/v1?ids={}"], - ["getIOAExclusionsV1", "GET", "/policy/entities/ioa-exclusions/v1?ids={}"], - ["createIOAExclusionsV1", "POST", "/policy/entities/ioa-exclusions/v1"], - ["updateIOAExclusionsV1", "PATCH", "/policy/entities/ioa-exclusions/v1"], - ["deleteIOAExclusionsV1", "DELETE", "/policy/entities/ioa-exclusions/v1?ids={}"], - ["getMLExclusionsV1", "GET", "/policy/entities/ml-exclusions/v1?ids={}"], - ["createMLExclusionsV1", "POST", "/policy/entities/ml-exclusions/v1"], - ["updateMLExclusionsV1", "PATCH", "/policy/entities/ml-exclusions/v1"], - ["deleteMLExclusionsV1", "DELETE", "/policy/entities/ml-exclusions/v1?ids={}"], - ["performPreventionPoliciesAction", "POST", "/policy/entities/prevention-actions/v1"], - ["setPreventionPoliciesPrecedence", "POST", "/policy/entities/prevention-precedence/v1"], - ["getPreventionPolicies", "GET", "/policy/entities/prevention/v1?ids={}"], - ["createPreventionPolicies", "POST", "/policy/entities/prevention/v1"], - ["updatePreventionPolicies", "PATCH", "/policy/entities/prevention/v1"], - ["deletePreventionPolicies", "DELETE", "/policy/entities/prevention/v1?ids={}"], - ["performSensorUpdatePoliciesAction", "POST", "/policy/entities/sensor-update-actions/v1"], - ["setSensorUpdatePoliciesPrecedence", "POST", "/policy/entities/sensor-update-precedence/v1"], - ["getSensorUpdatePolicies", "GET", "/policy/entities/sensor-update/v1?ids={}"], - ["createSensorUpdatePolicies", "POST", "/policy/entities/sensor-update/v1"], - ["updateSensorUpdatePolicies", "PATCH", "/policy/entities/sensor-update/v1"], - ["deleteSensorUpdatePolicies", "DELETE", "/policy/entities/sensor-update/v1?ids={}"], - ["getSensorUpdatePoliciesV2", "GET", "/policy/entities/sensor-update/v2?ids={}"], - ["createSensorUpdatePoliciesV2", "POST", "/policy/entities/sensor-update/v2"], - ["updateSensorUpdatePoliciesV2", "PATCH", "/policy/entities/sensor-update/v2"], - ["getSensorVisibilityExclusionsV1", "GET", "/policy/entities/sv-exclusions/v1?ids={}"], - ["createSVExclusionsV1", "POST", "/policy/entities/sv-exclusions/v1"], - ["updateSensorVisibilityExclusionsV1", "PATCH", "/policy/entities/sv-exclusions/v1"], - ["deleteSensorVisibilityExclusionsV1", "DELETE", "/policy/entities/sv-exclusions/v1?ids={}"], - ["queryDeviceControlPolicyMembers", "GET", "/policy/queries/device-control-members/v1"], - ["queryDeviceControlPolicies", "GET", "/policy/queries/device-control/v1"], - ["queryFirewallPolicyMembers", "GET", "/policy/queries/firewall-members/v1"], - ["queryFirewallPolicies", "GET", "/policy/queries/firewall/v1"], - ["queryIOAExclusionsV1", "GET", "/policy/queries/ioa-exclusions/v1"], - ["queryMLExclusionsV1", "GET", "/policy/queries/ml-exclusions/v1"], - ["queryPreventionPolicyMembers", "GET", "/policy/queries/prevention-members/v1"], - ["queryPreventionPolicies", "GET", "/policy/queries/prevention/v1"], - ["querySensorUpdatePolicyMembers", "GET", "/policy/queries/sensor-update-members/v1"], - ["querySensorUpdatePolicies", "GET", "/policy/queries/sensor-update/v1"], - ["querySensorVisibilityExclusionsV1", "GET", "/policy/queries/sv-exclusions/v1"], - ["entities.processes", "GET", "/processes/entities/processes/v1?ids={}"], - ["RTR-AggregateSessions", "POST", "/real-time-response/aggregates/sessions/GET/v1"], - ["BatchActiveResponderCmd", "POST", "/real-time-response/combined/batch-active-responder-command/v1"], - ["BatchAdminCmd", "POST", "/real-time-response/combined/batch-admin-command/v1"], - ["BatchCmd", "POST", "/real-time-response/combined/batch-command/v1"], - ["BatchGetCmdStatus", "GET", "/real-time-response/combined/batch-get-command/v1"], - ["BatchGetCmd", "POST", "/real-time-response/combined/batch-get-command/v1"], - ["BatchInitSessions", "POST", "/real-time-response/combined/batch-init-session/v1"], - ["BatchRefreshSessions", "POST", "/real-time-response/combined/batch-refresh-session/v1"], - ["RTR-CheckActiveResponderCommandStatus", "GET", "/real-time-response/entities/active-responder-command/v1"], - ["RTR-ExecuteActiveResponderCommand", "POST", "/real-time-response/entities/active-responder-command/v1"], - ["RTR-CheckAdminCommandStatus", "GET", "/real-time-response/entities/admin-command/v1"], - ["RTR-ExecuteAdminCommand", "POST", "/real-time-response/entities/admin-command/v1"], - ["RTR-CheckCommandStatus", "GET", "/real-time-response/entities/command/v1"], - ["RTR-ExecuteCommand", "POST", "/real-time-response/entities/command/v1"], - ["RTR-GetExtractedFileContents", "GET", "/real-time-response/entities/extracted-file-contents/v1"], - ["RTR-ListFiles", "GET", "/real-time-response/entities/file/v1"], - ["RTR-DeleteFile", "DELETE", "/real-time-response/entities/file/v1?ids={}"], - ["RTR-GetPut-Files", "GET", "/real-time-response/entities/put-files/v1?ids={}"], - ["RTR-CreatePut-Files", "POST", "/real-time-response/entities/put-files/v1"], - ["RTR-DeletePut-Files", "DELETE", "/real-time-response/entities/put-files/v1?ids={}"], - ["RTR-ListQueuedSessions", "POST", "/real-time-response/entities/queued-sessions/GET/v1"], - ["RTR-DeleteQueuedSession", "DELETE", "/real-time-response/entities/queued-sessions/command/v1"], - ["RTR-PulseSession", "POST", "/real-time-response/entities/refresh-session/v1"], - ["RTR-GetScripts", "GET", "/real-time-response/entities/scripts/v1?ids={}"], - ["RTR-CreateScripts", "POST", "/real-time-response/entities/scripts/v1"], - ["RTR-UpdateScripts", "PATCH", "/real-time-response/entities/scripts/v1"], - ["RTR-DeleteScripts", "DELETE", "/real-time-response/entities/scripts/v1?ids={}"], - ["RTR-ListSessions", "POST", "/real-time-response/entities/sessions/GET/v1"], - ["RTR-InitSession", "POST", "/real-time-response/entities/sessions/v1"], - ["RTR-DeleteSession", "DELETE", "/real-time-response/entities/sessions/v1"], - ["RTR-ListPut-Files", "GET", "/real-time-response/queries/put-files/v1"], - ["RTR-ListScripts", "GET", "/real-time-response/queries/scripts/v1"], - ["RTR-ListAllSessions", "GET", "/real-time-response/queries/sessions/v1"], - ["GetSampleV2", "GET", "/samples/entities/samples/v2?ids={}"], - ["UploadSampleV2", "POST", "/samples/entities/samples/v2"], - ["DeleteSampleV2", "DELETE", "/samples/entities/samples/v2?ids={}"], - ["GetSampleV3", "GET", "/samples/entities/samples/v3?ids={}"], - ["UploadSampleV3", "POST", "/samples/entities/samples/v3"], - ["DeleteSampleV3", "DELETE", "/samples/entities/samples/v3?ids={}"], - ["QuerySampleV1", "POST", "/samples/queries/samples/GET/v1"], - ["GetScansAggregates", "POST", "/scanner/aggregates/scans/GET/v1"], - ["GetScans", "GET", "/scanner/entities/scans/v1?ids={}"], - ["ScanSamples", "POST", "/scanner/entities/scans/v1"], - ["QuerySubmissionsMixin0", "GET", "/scanner/queries/scans/v1"], - ["GetCombinedSensorInstallersByQuery", "GET", "/sensors/combined/installers/v1"], - ["refreshActiveStreamSession", "POST", "/sensors/entities/datafeed-actions/v1/{}"], - ["listAvailableStreamsOAuth2", "GET", "/sensors/entities/datafeed/v2"], - ["DownloadSensorInstallerById", "GET", "/sensors/entities/download-installer/v1"], - ["GetSensorInstallersEntities", "GET", "/sensors/entities/installers/v1?ids={}"], - ["GetSensorInstallersCCIDByQuery", "GET", "/sensors/queries/installers/ccid/v1"], - ["GetSensorInstallersByQuery", "GET", "/sensors/queries/installers/v1"], - ["GetCSPMPolicy", "GET", "/settings/entities/policy-details/v1?ids={}"], - ["GetCSPMPolicySettings", "GET", "/settings/entities/policy/v1"], - ["UpdateCSPMPolicySettings", "PATCH", "/settings/entities/policy/v1"], - ["GetCSPMScanSchedule", "GET", "/settings/scan-schedule/v1"], - ["UpdateCSPMScanSchedule", "POST", "/settings/scan-schedule/v1"], - ["getVulnerabilities", "GET", "/spotlight/entities/vulnerabilities/v2?ids={}"], - ["queryVulnerabilities", "GET", "/spotlight/queries/vulnerabilities/v1"], - ["GetRoles", "GET", "/user-roles/entities/user-roles/v1?ids={}"], - ["GrantUserRoleIds", "POST", "/user-roles/entities/user-roles/v1"], - ["RevokeUserRoleIds", "DELETE", "/user-roles/entities/user-roles/v1?ids={}"], - ["GetAvailableRoleIds", "GET", "/user-roles/queries/user-role-ids-by-cid/v1"], - ["GetUserRoleIds", "GET", "/user-roles/queries/user-role-ids-by-user-uuid/v1"], - ["RetrieveUser", "GET", "/users/entities/users/v1?ids={}"], - ["CreateUser", "POST", "/users/entities/users/v1"], - ["UpdateUser", "PATCH", "/users/entities/users/v1"], - ["DeleteUser", "DELETE", "/users/entities/users/v1"], - ["RetrieveEmailsByCID", "GET", "/users/queries/emails-by-cid/v1"], - ["RetrieveUserUUIDsByCID", "GET", "/users/queries/user-uuids-by-cid/v1"], - ["RetrieveUserUUID", "GET", "/users/queries/user-uuids-by-email/v1"] - ] - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def authenticate(self): - """ Generates an authorization token. """ - FULL_URL = self.base_url+'/oauth2/token' - DATA = {} - if self.valid_cred_format(): - DATA = { - 'client_id': self.creds['client_id'], - 'client_secret': self.creds['client_secret'] - } - try: - response = requests.request("POST", FULL_URL, data=DATA, headers={}, verify=False) - result = self.Result()(status_code=response.status_code,headers={},body=response.json())["body"] - self.token = result["access_token"] - self.token_expiration = result["expires_in"] - self.token_time = time.time() - self.authenticated = True - except Exception: - self.authenticated = False - - return self.authenticated - - def deauthenticate(self): - """ Revokes the specified authorization token. """ - FULL_URL = self.base_url+'/oauth2/revoke' - HEADERS = { 'Authorization': 'basic {}'.format(self.token) } - DATA = { 'token': '{}'.format(self.token) } - revoked = False - try: - requests.request("POST", FULL_URL, data=DATA, headers=HEADERS, verify=False) - self.authenticated = False - self.token = False - revoked = True - except Exception: - revoked = False - - return revoked - - def command(self, action="", parameters={}, body={}, data={}, ids=False, partition=False, override=False, files=[], content_type=False): - """ Checks token expiration, renewing when necessary, then performs the request. """ - if self.token_expired(): - self.authenticate() - if override: - CMD = [["Manual"] + override.split(",")] - else: - CMD = [a for a in self.commands if a[0] == action] - if CMD: - FULL_URL = self.base_url+"{}".format(CMD[0][2]) - if ids: - ID_LIST = str(ids).replace(",","&ids=") - FULL_URL = FULL_URL.format(ID_LIST) - if partition: - FULL_URL = FULL_URL.format(str(partition)) - HEADERS = self.headers() - if content_type: - HEADERS["Content-Type"] = str(content_type) - DATA = data - BODY = body - PARAMS = parameters - FILES = files - if self.authenticated: - try: - response = requests.request(CMD[0][1].upper(), FULL_URL, json=BODY, data=DATA, params=PARAMS, headers=HEADERS, files=FILES, verify=False) - returned = self.Result()(status_code=response.status_code, headers=response.headers, body=response.json()) - except Exception as e: - returned = self.Result()(status_code=500, headers={}, body=str(e)) - else: - returned = self.Result()(status_code=500, headers={}, body={"errors":[{"message":"Failed to issue token."}],"resources":""}) - else: - returned = self.Result()(status_code=500, headers={}, body={"errors":[{"message":"Invalid API service method."}],"resources":""}) - - return returned diff --git a/falconpy/services/cloud_connect_aws.py b/falconpy/services/cloud_connect_aws.py deleted file mode 100644 index 7207a060..00000000 --- a/falconpy/services/cloud_connect_aws.py +++ /dev/null @@ -1,205 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# cloud_connect_aws - Falcon X Discover API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Cloud_Connect_AWS: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url="https://api.crowdstrike.com"): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = {'Authorization': 'Bearer {}'.format(access_token)} - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def QueryAWSAccounts(self, parameters): - """ Search for provisioned AWS Accounts by providing an FQL filter and paging details. - Returns a set of AWS accounts which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/QueryAWSAccounts - FULL_URL = self.base_url+'/cloud-connect-aws/combined/accounts/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetAWSSettings(self): - """ Retrieve a set of Global Settings which are applicable to all provisioned AWS accounts. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/GetAWSSettings - FULL_URL = self.base_url+'/cloud-connect-aws/combined/settings/v1' - HEADERS = self.headers - result = self.Result() - try: - response = requests.request("GET", FULL_URL, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetAWSAccounts(self, parameters, ids): - """ Retrieve a set of AWS Accounts by specifying their IDs.""" - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/GetAWSAccounts - ID_LIST = str(ids).replace(",","&ids=") - FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1?ids={}'.format(ID_LIST) - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def ProvisionAWSAccounts(self, parameters, body): - """ Provision AWS Accounts by specifying details about the accounts to provision. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/ProvisionAWSAccounts - FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1' - PARAMS=parameters - BODY=body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=self.headers, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def DeleteAWSAccounts(self, parameters, ids): - """ Delete a set of AWS Accounts by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/DeleteAWSAccounts - ID_LIST = str(ids).replace(",","&ids=") - FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1?ids={}'.format(ID_LIST) - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=self.headers, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def UpdateAWSAccounts(self, body): - """ Update AWS Accounts by specifying the ID of the account and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/UpdateAWSAccounts - FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1' - BODY=body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=self.headers, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def CreateOrUpdateAWSSettings(self, body): - """ Create or update Global Settings which are applicable to all provisioned AWS accounts. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/CreateOrUpdateAWSSettings - FULL_URL = self.base_url+'/cloud-connect-aws/entities/settings/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def VerifyAWSAccountAccess(self, parameters, body, ids): - """ Performs an Access Verification check on the specified AWS Account IDs. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/VerifyAWSAccountAccess - ID_LIST = str(ids).replace(",","&ids=") - FULL_URL = self.base_url+'/cloud-connect-aws/entities/verify-account-access/v1?ids={}'.format(ID_LIST) - HEADERS = self.headers - PARAMS = parameters - BODY = body #payload does not appear to be required - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryAWSAccountsForIDs(self, parameters): - """ Search for provisioned AWS Accounts by providing an FQL filter and paging details. - Returns a set of AWS account IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/QueryAWSAccountsForIDs - FULL_URL = self.base_url+'/cloud-connect-aws/queries/accounts/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/detects.py b/falconpy/services/detects.py deleted file mode 100644 index 9925fc76..00000000 --- a/falconpy/services/detects.py +++ /dev/null @@ -1,127 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# detects - Falcon X Detections API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Detects: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def GetAggregateDetects(self, body, parameters): - """ Get detect aggregates as specified via json in request body. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/GetAggregateDetects - FULL_URL = self.base_url+'/detects/aggregates/detects/GET/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def UpdateDetectsByIdsV2(self, body): - """ Modify the state, assignee, and visibility of detections. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/UpdateDetectsByIdsV2 - FULL_URL = self.base_url+'/detects/entities/detects/v2' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetDetectSummaries(self, body, parameters): - """ View information about detections. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/GetDetectSummaries - FULL_URL = self.base_url+'/detects/entities/summaries/GET/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryDetects(self, parameters): - """ Search for detection IDs that match a given query. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/QueryDetects - FULL_URL = self.base_url+'/detects/queries/detects/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/device_control_policies.py b/falconpy/services/device_control_policies.py deleted file mode 100644 index b3632e84..00000000 --- a/falconpy/services/device_control_policies.py +++ /dev/null @@ -1,229 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# device_control_policies - Falcon X Device Control Policies API Interface Class. # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Device_Control_Policies: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def queryCombinedDeviceControlPolicyMembers(self, parameters): - """ Search for members of a Device Control Policy in your environment by providing an FQL filter - and paging details. Returns a set of host details which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/queryCombinedDeviceControlPolicyMembers - FULL_URL = self.base_url+'/policy/combined/device-control-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedDeviceControlPolicies(self, parameters): - """ Search for Device Control Policies in your environment by providing an FQL filter and - paging details. Returns a set of Device Control Policies which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/queryCombinedDeviceControlPolicies - FULL_URL = self.base_url+'/policy/combined/device-control/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def performDeviceControlPoliciesAction(self, parameters, body): - """ Search for Device Control Policies in your environment by providing an FQL filter - and paging details. Returns a set of Device Control Policies which match the filter criteria. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/performDeviceControlPoliciesAction - FULL_URL = self.base_url+'/policy/combined/device-control/v1' - HEADERS = self.headers - BODY = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def setDeviceControlPoliciesPrecedence(self, body): - """ Sets the precedence of Device Control Policies based on the order of IDs specified in the request. - The first ID specified will have the highest precedence and the last ID specified will have the lowest. - You must specify all non-Default Policies for a platform when updating precedence. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/performDeviceControlPoliciesAction - FULL_URL = self.base_url+'/policy/entities/device-control-precedence/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getDeviceControlPolicies(self, parameters): - """ Retrieve a set of Device Control Policies by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/getDeviceControlPolicies - FULL_URL = self.base_url+'/policy/entities/device-control/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createDeviceControlPolicies(self, body): - """ Create Device Control Policies by specifying details about the policy to create. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/createDeviceControlPolicies - FULL_URL = self.base_url+'/policy/entities/device-control/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def deleteDeviceControlPolicies(self, parameters): - """ Delete a set of Device Control Policies by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/createDeviceControlPolicies - FULL_URL = self.base_url+'/policy/entities/device-control/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def updateDeviceControlPolicies(self, body): - """ Update Device Control Policies by specifying the ID of the policy and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/updateDeviceControlPolicies - FULL_URL = self.base_url+'/policy/entities/device-control/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryDeviceControlPolicyMembers(self, parameters): - """ Search for members of a Device Control Policy in your environment by providing an FQL filter - and paging details. Returns a set of Agent IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/queryDeviceControlPolicyMembers - FULL_URL = self.base_url+'/policy/queries/device-control-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryDeviceControlPolicies(self, parameters): - """ Search for Device Control Policies in your environment by providing an FQL filter and paging details. - Returns a set of Device Control Policy IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies/queryDeviceControlPolicyMembers - FULL_URL = self.base_url+'/policy/queries/device-control/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/event_streams.py b/falconpy/services/event_streams.py deleted file mode 100644 index 3e28b19f..00000000 --- a/falconpy/services/event_streams.py +++ /dev/null @@ -1,97 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# event_streams - Falcon X Horizon Event Stream API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Event_Streams: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url="https://api.crowdstrike.com"): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def refreshActiveStreamSession(self, parameters): - """ Refresh an active event stream. Use the URL shown in a GET /sensors/entities/datafeed/v2 response. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/event-streams/refreshActiveStreamSession - FULL_URL = self.base_url+'/sensors/entities/datafeed-actions/v1/{}'.format(parameters['partition']) - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def listAvailableStreamsOAuth2(self, parameters): - """ Discover all event streams in your environment. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/event-streams/listAvailableStreamsOAuth2 - FULL_URL = self.base_url+'/sensors/entities/datafeed/v2' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - - except Exception as e: - returned = result(500, {}, str(e)) - - return returned \ No newline at end of file diff --git a/falconpy/services/falconx_sandbox.py b/falconpy/services/falconx_sandbox.py deleted file mode 100644 index aca5cee6..00000000 --- a/falconpy/services/falconx_sandbox.py +++ /dev/null @@ -1,174 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# falconx_sandbox - Falcon X Sandbox API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class FalconX_Sandbox: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def GetArtifacts(self, parameters):#This function will probably need to not do a result.json() if used... See Swagger - """ Download IOC packs, PCAP files, and other analysis artifacts. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetArtifacts - FULL_URL = self.base_url+'/falconx/entities/artifacts/v1' - HEADERS = self.headers - HEADERS['Accept-Encoding'] = 'gzip' - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetSummaryReports(self, parameters): - """ Get a short summary version of a sandbox report. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetSummaryReports - FULL_URL = self.base_url+'/falconx/entities/report-summaries/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetSubmissions(self, parameters): - """ Check the status of a sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetSubmissions - FULL_URL = self.base_url+'/falconx/entities/submissions/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def Submit(self, body): - """ Submit an uploaded file or a URL for sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/Submit - FULL_URL = self.base_url+'/falconx/entities/submissions/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryReports(self, parameters): - """ Find sandbox reports by providing an FQL filter and paging details. Returns a set of report IDs that match your criteria. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QueryReports - FULL_URL = self.base_url+'/falconx/queries/reports/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QuerySubmissions(self, parameters): - """ Find submission IDs for uploaded files by providing an FQL filter and paging details. - Returns a set of submission IDs that match your criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QuerySubmissions - FULL_URL = self.base_url+'/falconx/queries/submissions/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def UploadSampleV2(self, parameters, body): - """ Upload a file for sandbox analysis. After uploading, use `/falconx/entities/submissions/v1` to start analyzing the file. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/UploadSampleV2 - FULL_URL = self.base_url+'/samples/entities/samples/v2' - HEADERS = self.headers - BODY = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, data=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/firewall_management.py b/falconpy/services/firewall_management.py deleted file mode 100644 index 25b4a10f..00000000 --- a/falconpy/services/firewall_management.py +++ /dev/null @@ -1,370 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# firewall_management - Falcon X Firewall Management API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Firewall_Management: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def aggregate_events(self, body): - """ Aggregate events for customer. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_events - FULL_URL = self.base_url+'/fwmgr/aggregates/events/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def aggregate_policy_rules(self, body): - """ Aggregate rules within a policy for customer. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_policy_rules - FULL_URL = self.base_url+'/fwmgr/aggregates/policy-rules/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def aggregate_rule_groups(self, body): - """ Aggregate rule groups for customer. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_rule_groups - FULL_URL = self.base_url+'/fwmgr/aggregates/rule-groups/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def aggregate_rules(self, body): - """ Aggregate rules for customer. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_rules - FULL_URL = self.base_url+'/fwmgr/aggregates/rules/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_events(self, parameters): - """ Get events entities by ID and optionally version. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_events - FULL_URL = self.base_url+'/fwmgr/entities/events/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_firewall_fields(self, parameters): - """ Get the firewall field specifications by ID. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_firewall_fields - FULL_URL = self.base_url+'/fwmgr/entities/firewall-fields/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_platforms(self, parameters): - """ Get platforms by ID, e.g., windows or mac or droid. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_platforms - FULL_URL = self.base_url+'/fwmgr/entities/platforms/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_policy_containers(self, parameters): - """ Get policy container entities by policy ID. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_policy_containers - FULL_URL = self.base_url+'/fwmgr/entities/policies/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def update_policy_container(self, body, cs_username): - """ Update an identified policy container. """ - # [PUT] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/update_policy_container - FULL_URL = self.base_url+'/fwmgr/entities/policies/v1' - HEADERS = self.headers - HEADERS['X-CS-USERNAME'] = cs_username - BODY = body - result = self.Result() - try: - response = requests.request("PUT", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_rule_groups(self, parameters): - """ Get rule group entities by ID. These groups do not contain their rule entites, just the rule IDs in precedence order. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_rule_groups - FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def create_rule_group(self, parameters, body, cs_username): - """ Create new rule group on a platform for a customer with a name and description, and return the ID. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/create_rule_group - FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' - HEADERS = self.headers - HEADERS['X-CS-USERNAME'] = cs_username - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def delete_rule_groups(self, parameters, cs_username): - """ Delete rule group entities by ID. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QueryReports - FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' - HEADERS = self.headers - HEADERS['X-CS-USERNAME'] = cs_username - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def update_rule_group(self, parameters, cs_username): - """ Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/update_rule_group - FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' - HEADERS = self.headers - HEADERS['X-CS-USERNAME'] = cs_username - PARAMS = parameters - result = self.Result() - try: - response = requests.request("PTACH", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def get_rules(self, parameters): - """ Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string). """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_rules - FULL_URL = self.base_url+'/fwmgr/entities/rules/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_events(self, parameters): - """ Find all event IDs matching the query with filter. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_events - FULL_URL = self.base_url+'/fwmgr/queries/events/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_firewall_fields(self, parameters): - """ Get the firewall field specification IDs for the provided platform. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_firewall_fields - FULL_URL = self.base_url+'/fwmgr/queries/firewall-fields/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_platforms(self, parameters): - """ Get the list of platform names. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_platforms - FULL_URL = self.base_url+'/fwmgr/queries/platforms/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_policy_rules(self, parameters): - """ Find all firewall rule IDs matching the query with filter, and return them in precedence order. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_policy_rules - FULL_URL = self.base_url+'/fwmgr/queries/policy-rules/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_rule_groups(self, parameters): - """ Find all rule group IDs matching the query with filter. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_rule_groups - FULL_URL = self.base_url+'/fwmgr/queries/rule-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def query_rules(self, parameters): - """ Find all rule IDs matching the query with filter. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_rule_groups - FULL_URL = self.base_url+'/fwmgr/queries/rules/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/firewall_policies.py b/falconpy/services/firewall_policies.py deleted file mode 100644 index 12d8d36f..00000000 --- a/falconpy/services/firewall_policies.py +++ /dev/null @@ -1,228 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# firewall_policies - Falcon X Firewall Policies API Interface Class. # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Firewall_Policies: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def queryCombinedFirewallPolicyMembers(self, parameters): - """ Search for members of a Firewall Policy in your environment by providing an FQL filter - and paging details. Returns a set of host details which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryCombinedFirewallPolicyMembers - FULL_URL = self.base_url+'/policy/combined/firewall-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedFirewallPolicies(self, parameters): - """ Search for Firewall Policies in your environment by providing an FQL filter and paging details. - Returns a set of Firewall Policies which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryCombinedFirewallPolicies - FULL_URL = self.base_url+'/policy/combined/firewall/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def performFirewallPoliciesAction(self, parameters, body): - """ Perform the specified action on the Firewall Policies specified in the request. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/performFirewallPoliciesAction - FULL_URL = self.base_url+'/policy/entities/firewall-actions/v1' - HEADERS = self.headers - BODY = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def setFirewallPoliciesPrecedence(self, body): - """ Sets the precedence of Firewall Policies based on the order of IDs specified in the request. - The first ID specified will have the highest precedence and the last ID specified will have the lowest. - You must specify all non-Default Policies for a platform when updating precedence. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/setFirewallPoliciesPrecedence - FULL_URL = self.base_url+'/policy/entities/firewall-precedence/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getFirewallPolicies(self, parameters): - """ Retrieve a set of Firewall Policies by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/getFirewallPolicies - FULL_URL = self.base_url+'/policy/entities/firewall/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createFirewallPolicies(self, parameters, body): - """ Create Firewall Policies by specifying details about the policy to create. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/createFirewallPolicies - FULL_URL = self.base_url+'/policy/entities/firewall/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def deleteFirewallPolicies(self, parameters): - """ Delete a set of Firewall Policies by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/deleteFirewallPolicies - FULL_URL = self.base_url+'/policy/entities/firewall/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def updateFirewallPolicies(self, body): - """ Update Firewall Policies by specifying the ID of the policy and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/updateFirewallPolicies - FULL_URL = self.base_url+'/policy/entities/firewall/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryFirewallPolicyMembers(self, parameters): - """ Search for members of a Firewall Policy in your environment by providing an FQL filter and - paging details. Returns a set of Agent IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryFirewallPolicyMembers - FULL_URL = self.base_url+'/policy/queries/firewall-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryFirewallPolicies(self, parameters): - """ Search for Firewall Policies in your environment by providing an FQL filter and paging details. - Returns a set of Firewall Policy IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryFirewallPolicies - FULL_URL = self.base_url+'/policy/queries/firewall/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/host_group.py b/falconpy/services/host_group.py deleted file mode 100644 index 8174fa26..00000000 --- a/falconpy/services/host_group.py +++ /dev/null @@ -1,208 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# host_groups - Falcon X Host Groups API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Host_Group: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def queryCombinedGroupMembers(self, parameters): - """ Search for members of a Host Group in your environment by providing an FQL filter - and paging details. Returns a set of host details which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryCombinedGroupMembers - FULL_URL = self.base_url+'/devices/combined/host-group-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedHostGroups(self, parameters): - """ Search for Host Groups in your environment by providing an FQL filter and - paging details. Returns a set of Host Groups which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryCombinedHostGroups - FULL_URL = self.base_url+'/devices/combined/host-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def performGroupAction(self, parameters, body): - """ Perform the specified action on the Host Groups specified in the request. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/performGroupAction - FULL_URL = self.base_url+'/devices/entities/host-group-actions/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getHostGroups(self, parameters): - """ Retrieve a set of Host Groups by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/getHostGroups - FULL_URL = self.base_url+'/devices/entities/host-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createHostGroups(self, body): - """ Create Host Groups by specifying details about the group to create. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/createHostGroups - FULL_URL = self.base_url+'/devices/entities/host-groups/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def deleteHostGroups(self, parameters): - """ Delete a set of Host Groups by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/deleteHostGroups - FULL_URL = self.base_url+'/devices/entities/host-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - return returned - - def updateHostGroups(self, body): - """ Update Host Groups by specifying the ID of the group and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/updateHostGroups - FULL_URL = self.base_url+'/devices/entities/host-groups/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryGroupMembers(self, parameters): - """ Search for members of a Host Group in your environment by providing an FQL filter - and paging details. Returns a set of Agent IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryGroupMembers - FULL_URL = self.base_url+'/devices/queries/host-group-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryHostGroups(self, parameters): - """ Search for Host Groups in your environment by providing an FQL filter and - paging details. Returns a set of Host Group IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryHostGroups - FULL_URL = self.base_url+'/devices/queries/host-groups/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned \ No newline at end of file diff --git a/falconpy/services/hosts.py b/falconpy/services/hosts.py deleted file mode 100644 index bd877975..00000000 --- a/falconpy/services/hosts.py +++ /dev/null @@ -1,128 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# hosts - Falcon X Hosts API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Hosts: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def PerformActionV2(self, parameters, body): - """ Take various actions on the hosts in your environment. Contain or lift containment on a host. Delete or restore a host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/PerformActionV2 - FULL_URL = self.base_url+'/devices/entities/devices-actions/v2' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetDeviceDetails(self, parameters): - """ Get details on one or more hosts by providing agent IDs (AID). - You can get a host's agent IDs (AIDs) from the /devices/queries/devices/v1 endpoint, the Falcon console or the Streaming API. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/GetDeviceDetails - FULL_URL = self.base_url+'/devices/entities/devices/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryDevicesByFilterScroll(self, parameters): - """ Perform the specified action on the Prevention Policies specified in the request. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/QueryDevicesByFilterScroll - FULL_URL = self.base_url+'/devices/queries/devices-scroll/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryDevicesByFilter(self, parameters, body): - """ Search for hosts in your environment by platform, hostname, IP, and other criteria. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/QueryDevicesByFilter - FULL_URL = self.base_url+'/devices/queries/devices/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/incidents.py b/falconpy/services/incidents.py deleted file mode 100644 index 41936790..00000000 --- a/falconpy/services/incidents.py +++ /dev/null @@ -1,157 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# incidents - Falcon X Incidents API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Incidents: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def CrowdScore(self, parameters): - """ Query environment wide CrowdScore and return the entity data. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/CrowdScore - FULL_URL = self.base_url+'/incidents/combined/crowdscores/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetBehaviors(self, body): - """ Get details on behaviors by providing behavior IDs. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/GetBehaviors - FULL_URL = self.base_url+'/incidents/entities/behaviors/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def PerformIncidentAction(self, body): - """ Perform a set of actions on one or more incidents, such as - adding tags or comments or updating the incident name or description. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/PerformIncidentAction - FULL_URL = self.base_url+'/incidents/entities/incident-actions/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIncidents(self, body): - """ Get details on incidents by providing incident IDs. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/GetIncidents - FULL_URL = self.base_url+'/incidents/entities/incidents/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryBehaviors(self, parameters): - """ Search for behaviors by providing an FQL filter, sorting, and paging details. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/QueryBehaviors - FULL_URL = self.base_url+'/incidents/queries/behaviors/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIncidents(self, parameters): - """ Search for incidents by providing an FQL filter, sorting, and paging details. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/QueryIncidents - FULL_URL = self.base_url+'/incidents/queries/incidents/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/intel.py b/falconpy/services/intel.py deleted file mode 100644 index 30bbcdcf..00000000 --- a/falconpy/services/intel.py +++ /dev/null @@ -1,275 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# intel - Falcon X Threat Intelligence API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Intel: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def QueryIntelActorEntities(self, parameters): - """ Get info about actors that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelActorEntities - FULL_URL = self.base_url+'/intel/combined/actors/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelIndicatorEntities(self, parameters): - """ Get info about indicators that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelIndicatorEntities - FULL_URL = self.base_url+'/intel/combined/indicators/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelReportEntities(self, parameters): - """ Get info about reports that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportEntities - FULL_URL = self.base_url+'/intel/combined/reports/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelActorEntities(self, parameters): - """ Retrieve specific actors using their actor IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelActorEntities - FULL_URL = self.base_url+'/intel/entities/actors/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelIndicatorEntities(self, body): - """ Retrieve specific indicators using their indicator IDs. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelIndicatorEntities - FULL_URL = self.base_url+'/intel/entities/indicators/GET/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelReportPDF(self, parameters):#Probably need to not do result.json() here. Check the swagger - """ Return a Report PDF attachment. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelReportPDF - FULL_URL = self.base_url+'/intel/entities/report-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelReportEntities(self, parameters): - """ Retrieve specific reports using their report IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelReportEntities - FULL_URL = self.base_url+'/intel/entities/reports/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelRuleFile(self, parameters):#There is an optional header you can see Accept to choose the result format. See Swagger. - """ Download earlier rule sets. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelRuleFile - FULL_URL = self.base_url+'/intel/entities/rules-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetLatestIntelRuleFile(self, parameters):#There is an optional header you can see Accept to choose the result format. See Swagger. - """ Download the latest rule set. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetLatestIntelRuleFile - FULL_URL = self.base_url+'/intel/entities/rules-latest-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIntelRuleEntities(self, parameters): - """ Retrieve details for rule sets for the specified ids. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelRuleEntities - FULL_URL = self.base_url+'/intel/entities/rules/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelActorIds(self, parameters): - """ Get actor IDs that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelActorIds - FULL_URL = self.base_url+'/intel/queries/actors/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelIndicatorIds(self, parameters): - """ Get indicators IDs that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelIndicatorIds - FULL_URL = self.base_url+'/intel/queries/indicators/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelReportIds(self, parameters): - """ Get report IDs that match provided FQL filters. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportIds - FULL_URL = self.base_url+'/intel/queries/reports/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIntelRuleIds(self, parameters): - """ Search for rule IDs that match provided filter criteria. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportIds - FULL_URL = self.base_url+'/intel/queries/rules/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/iocs.py b/falconpy/services/iocs.py deleted file mode 100644 index dd0d6df6..00000000 --- a/falconpy/services/iocs.py +++ /dev/null @@ -1,201 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# iocs - Falcon X Indicators of Compromise API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Iocs: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def DevicesCount(self, parameters): - """ Number of hosts in your customer account that have observed a given custom IOC. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DevicesCount - FULL_URL = self.base_url+'/indicators/aggregates/devices-count/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetIOC(self, parameters): - """ Get an IOC by providing a type and value. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/GetIOC - FULL_URL = self.base_url+'/indicators/entities/iocs/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def CreateIOC(self, body): - """ Create a new IOC. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/CreateIOC - FULL_URL = self.base_url+'/indicators/entities/iocs/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def DeleteIOC(self, parameters): - """ Delete an IOC by providing a type and value. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DeleteIOC - FULL_URL = self.base_url+'/indicators/entities/iocs/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def UpdateIOC(self, parameters, body): - """ Update an IOC by providing a type and value. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/UpdateIOC - FULL_URL = self.base_url+'/indicators/entities/iocs/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def DevicesRanOn(self, parameters): - """ Find hosts that have observed a given custom IOC. For details about those hosts, use the hosts API interface. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DevicesRanOn - FULL_URL = self.base_url+'/indicators/queries/devices/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def QueryIOCs(self, parameters): - """ Search the custom IOCs in your customer account. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/QueryIOCs - FULL_URL = self.base_url+'/indicators/queries/iocs/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def ProcessesRanOn(self, parameters): - """ Search for processes associated with a custom IOC. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/QueryIOCs - FULL_URL = self.base_url+'/indicators/queries/processes/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def entities_processes(self, parameters): - """ For the provided ProcessID retrieve the process details. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/entities_processes - FULL_URL = self.base_url+'/processes/entities/processes/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/oauth2.py b/falconpy/services/oauth2.py deleted file mode 100644 index 18d5f446..00000000 --- a/falconpy/services/oauth2.py +++ /dev/null @@ -1,100 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# oauth2 - Falcon X oAuth API Authentication Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class OAuth2: - """ To create an instance of this class, you must pass a - properly formatted JSON object containing your falcon - client_id and falcon client_secret for the key you - wish to use to connect to the API. - - { - "client_id": FALCON_CLIENT_ID, - "client_secret": FALCON_CLIENT_SECRET - } - """ - - def __init__(self, creds, base_url="https://api.crowdstrike.com"): - """ Initializes the base class, ingesting credentials and the base URL. """ - self.creds = creds - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['body'] = body - - return self.result_obj - - def token(self): - """ Generates an authorization token. """ - FULL_URL = self.base_url+'/oauth2/token' - HEADERS = {} - DATA = { - 'client_id': self.creds['client_id'], - 'client_secret': self.creds['client_secret'] - } - result = self.Result() - try: - response = requests.request("POST", FULL_URL, data=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code,response.json()) - except Exception as e: - returned = result(500, str(e)) - - return returned - - def revoke(self, token): - """ Revokes the specified authorization token. """ - FULL_URL = self.base_url+'/oauth2/revoke' - HEADERS = { 'Authorization': 'basic {}'.format(token) } - DATA = { 'token': '{}'.format(token) } - result = self.Result() - try: - response = requests.request("POST", FULL_URL, data=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.json()) - except Exception as e: - returned = result(500, str(e)) - - return returned diff --git a/falconpy/services/prevention_policy.py b/falconpy/services/prevention_policy.py deleted file mode 100644 index d74506bb..00000000 --- a/falconpy/services/prevention_policy.py +++ /dev/null @@ -1,227 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# prevention_policy - Falcon X Prevention Policy API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Prevention_Policy: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def queryCombinedPreventionPolicyMembers(self, parameters): - """ Search for members of a Prevention Policy in your environment by providing an FQL filter - and paging details. Returns a set of host details which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/queryCombinedPreventionPolicyMembers - FULL_URL = self.base_url+'/policy/combined/prevention-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedPreventionPolicies(self, parameters): - """ Search for Prevention Policies in your environment by providing an FQL filter and - paging details. Returns a set of Prevention Policies which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/queryCombinedPreventionPolicies - FULL_URL = self.base_url+'/policy/combined/prevention/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def performPreventionPoliciesAction(self, parameters, body): - """ Perform the specified action on the Prevention Policies specified in the request. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/performPreventionPoliciesAction - FULL_URL = self.base_url+'/policy/entities/prevention-actions/v1' - HEADERS = self.headers - PARAMS = parameters - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def setPreventionPoliciesPrecedence(self, body): - """ Sets the precedence of Prevention Policies based on the order of IDs specified in the request. - The first ID specified will have the highest precedence and the last ID specified will have the lowest. - You must specify all non-Default Policies for a platform when updating precedence. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/setPreventionPoliciesPrecedence - FULL_URL = self.base_url+'/policy/entities/prevention-precedence/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getPreventionPolicies(self, parameters): - """ Retrieve a set of Prevention Policies by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/getPreventionPolicies - FULL_URL = self.base_url+'/policy/entities/prevention/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createPreventionPolicies(self, body): - """ Create Prevention Policies by specifying details about the policy to create. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/createPreventionPolicies - FULL_URL = self.base_url+'/policy/entities/prevention/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def deletePreventionPolicies(self, parameters): - """ Delete a set of Prevention Policies by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/deletePreventionPolicies - FULL_URL = self.base_url+'/policy/entities/prevention/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def updatePreventionPolicies(self, body): - """ Update Prevention Policies by specifying the ID of the policy and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/updatePreventionPolicies - FULL_URL = self.base_url+'/policy/entities/prevention/v1' - HEADERS = self.headers - BODY = body - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, json=BODY, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryPreventionPolicyMembers(self, parameters): - """ Search for members of a Prevention Policy in your environment by providing an FQL filter - and paging details. Returns a set of Agent IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/queryPreventionPolicyMembers - FULL_URL = self.base_url+'/policy/queries/prevention-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryPreventionPolicies(self, parameters): - """ Search for Prevention Policies in your environment by providing an FQL filter - and paging details. Returns a set of Prevention Policy IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/queryPreventionPolicies - FULL_URL = self.base_url+'/policy/queries/prevention/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/real_time_response.py b/falconpy/services/real_time_response.py deleted file mode 100644 index f6d493f4..00000000 --- a/falconpy/services/real_time_response.py +++ /dev/null @@ -1,357 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# real_time_response - Falcon X Real Time Response API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Real_Time_Response: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def RTR_AggregateSessions(self, body): - """ Get aggregates on session data. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_AggregateSessions - FULL_URL = self.base_url+'/real-time-response/aggregates/sessions/GET/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchActiveResponderCmd(self, parameters, body): - """ Batch executes a RTR active-responder command across the hosts mapped to the given batch ID. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd - FULL_URL = self.base_url+'/real-time-response/combined/batch-active-responder-command/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchCmd(self, parameters, body): - """ Batch executes a RTR read-only command across the hosts mapped to the given batch ID. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd - FULL_URL = self.base_url+'/real-time-response/combined/batch-command/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchGetCmdStatus(self, parameters): - """ Retrieves the status of the specified batch get command. Will return successful files when they are finished processing. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchGetCmdStatus - FULL_URL = self.base_url+'/real-time-response/combined/batch-get-command/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchGetCmd(self, parameters, body): - """ Batch executes `get` command across hosts to retrieve files. - After this call is made `/real-time-response/combined/get-command-status/v1` is used to query for the results. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd - FULL_URL = self.base_url+'/real-time-response/combined/batch-get-command/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchInitSessions(self, parameters, body): - """ Batch initialize a RTR session on multiple hosts. Before any RTR commands can be used, an active session is needed on the host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchInitSessions - FULL_URL = self.base_url+'/real-time-response/combined/batch-init-session/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def BatchRefreshSessions(self, parameters, body): - """ Batch refresh a RTR session on multiple hosts. RTR sessions will expire after 10 minutes unless refreshed. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchRefreshSessions - FULL_URL = self.base_url+'/real-time-response/combined/batch-refresh-session/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_CheckActiveResponderCommandStatus(self, parameters): - """ Get status of an executed active-responder command on a single host. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_CheckActiveResponderCommandStatus - FULL_URL = self.base_url+'/real-time-response/entities/active-responder-command/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ExecuteActiveResponderCommand(self, body): - """ Execute an active responder command on a single host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchRefreshSessions - FULL_URL = self.base_url+'/real-time-response/entities/active-responder-command/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_CheckCommandStatus(self, parameters): - """ Get status of an executed command on a single host. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_CheckCommandStatus - FULL_URL = self.base_url+'/real-time-response/entities/command/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ExecuteCommand(self, body): - """ Execute a command on a single host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ExecuteCommand - FULL_URL = self.base_url+'/real-time-response/entities/command/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_GetExtractedFileContents(self, parameters): - """ Get RTR extracted file contents for specified session and sha256. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_GetExtractedFileContents - FULL_URL = self.base_url+'/real-time-response/entities/extracted-file-contents/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ListFiles(self, parameters): - """ Get a list of files for the specified RTR session. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListFiles - FULL_URL = self.base_url+'/real-time-response/entities/file/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_DeleteFile(self, parameters): - """ Delete a RTR session file. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_DeleteFile - FULL_URL = self.base_url+'/real-time-response/entities/file/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_PulseSession(self, body): - """ Refresh a session timeout on a single host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_PulseSession - FULL_URL = self.base_url+'/real-time-response/entities/refresh-session/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ListSessions(self, body): - """ Get session metadata by session id. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListSessions - FULL_URL = self.base_url+'/real-time-response/entities/sessions/GET/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def InitSessionMixin0(self, body): - """ Initialize a new session with the RTR cloud. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/InitSessionMixin0 - FULL_URL = self.base_url+'/real-time-response/entities/sessions/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_DeleteSession(self, parameters): - """ Delete a session. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_DeleteSession - FULL_URL = self.base_url+'/real-time-response/entities/sessions/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ListAllSessions(self, parameters): - """ Get a list of session_ids. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListAllSessions - FULL_URL = self.base_url+'/real-time-response/queries/sessions/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/real_time_response_admin.py b/falconpy/services/real_time_response_admin.py deleted file mode 100644 index 06086cd0..00000000 --- a/falconpy/services/real_time_response_admin.py +++ /dev/null @@ -1,249 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# real_time_response_admin - Falcon X Real Time Response Administration API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Real_Time_Response_Admin: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def BatchAdminCmd(self, parameters, body): - """ Batch executes a RTR administrator command across the hosts mapped to the given batch ID. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/BatchAdminCmd - FULL_URL = self.base_url+'/real-time-response/combined/batch-admin-command/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_CheckAdminCommandStatus(self, parameters): - """ Get status of an executed RTR administrator command on a single host. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_CheckAdminCommandStatus - FULL_URL = self.base_url+'/real-time-response/entities/admin-command/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ExecuteAdminCommand(self, body): - """ Execute a RTR administrator command on a single host. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_ExecuteAdminCommand - FULL_URL = self.base_url+'/real-time-response/entities/admin-command/v1' - HEADERS = self.headers - DATA = body - result = self.Result() - try: - response = requests.request("POST", FULL_URL, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_GetPut_Files(self, parameters): - """ Get put-files based on the ID's given. These are used for the RTR `put` command. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_GetPut_Files - FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_CreatePut_Files(self, data, files): - """ Upload a new put-file to use for the RTR `put` command. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_CreatePut_Files - FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1' - HEADERS = self.headers - DATA = data - FILES = files - result = self.Result() - try: - response = requests.request("POST", FULL_URL, data=DATA, files=FILES, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_DeletePut_Files(self, parameters): - """ Delete a put-file based on the ID given. Can only delete one file at a time. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_DeletePut_Files - FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_GetScripts(self, parameters): - """ Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_GetScripts - FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_CreateScripts(self, data, files): - """ Upload a new custom-script to use for the RTR `runscript` command. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_CreateScripts - FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' - HEADERS = self.headers - DATA = data - FILES = files - result = self.Result() - try: - response = requests.request("POST", FULL_URL, data=DATA, files=FILES, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_DeleteScripts(self, parameters): - """ Delete a custom-script based on the ID given. Can only delete one script at a time. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_DeleteScripts - FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_UpdateScripts(self, data, files): - """ Upload a new scripts to replace an existing one. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_UpdateScripts - FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' - HEADERS = self.headers - DATA = data - FILES = files - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, data=DATA, files=FILES, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ListPut_Files(self, parameters): - """ Get a list of put-file ID's that are available to the user for the `put` command. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_ListPut_Files - FULL_URL = self.base_url+'/real-time-response/queries/put-files/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RTR_ListScripts(self, parameters): - """ Get a list of custom-script ID's that are available to the user for the `runscript` command. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_ListScripts - FULL_URL = self.base_url+'/real-time-response/queries/scripts/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/sensor_update_policy.py b/falconpy/services/sensor_update_policy.py deleted file mode 100644 index 7345a8ca..00000000 --- a/falconpy/services/sensor_update_policy.py +++ /dev/null @@ -1,327 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# sensor_update_policy - Falcon X Sensor Policy Management API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Sensor_Update_Policy: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def revealUninstallToken(self, parameters, body): - """ Reveals an uninstall token for a specific device. To retrieve the bulk maintenance token pass the value 'MAINTENANCE' as the value for 'device_id'. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/revealUninstallToken - FULL_URL = self.base_url+'/policy/combined/reveal-uninstall-token/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - - - def queryCombinedSensorUpdateBuilds(self, parameters): - """ Retrieve available builds for use with Sensor Update Policies. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/queryCombinedSensorUpdateBuilds - FULL_URL = self.base_url+'/policy/combined/sensor-update-builds/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedSensorUpdatePolicyMembers(self, parameters): - """ Search for members of a Sensor Update Policy in your environment by providing an FQL - filter and paging details. Returns a set of host details which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/queryCombinedSensorUpdatePolicyMembers - FULL_URL = self.base_url+'/policy/combined/sensor-update-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedSensorUpdatePolicies(self, parameters): - """ Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. - Returns a set of Sensor Update Policies which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/queryCombinedSensorUpdatePolicies - FULL_URL = self.base_url+'/policy/combined/sensor-update/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryCombinedSensorUpdatePoliciesV2(self, parameters): - """ Search for Sensor Update Policies with additional support for uninstall protection in your environment - by providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/queryCombinedSensorUpdatePoliciesV2 - FULL_URL = self.base_url+'/policy/combined/sensor-update/v2' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def performSensorUpdatePoliciesAction(self, parameters, body): - """ Perform the specified action on the Sensor Update Policies specified in the request. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/performSensorUpdatePoliciesAction - FULL_URL = self.base_url+'/policy/entities/sensor-update-actions/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def setSensorUpdatePoliciesPrecedence(self, parameters, body): - """ Sets the precedence of Sensor Update Policies based on the order of IDs specified in the request. - The first ID specified will have the highest precedence and the last ID specified will have the lowest. - You must specify all non-Default Policies for a platform when updating precedence. - """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/setSensorUpdatePoliciesPrecedence - FULL_URL = self.base_url+'/policy/entities/sensor-update-precedence/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getSensorUpdatePolicies(self, parameters): - """ Retrieve a set of Sensor Update Policies by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/getSensorUpdatePolicies - FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createSensorUpdatePolicies(self, parameters, body): - """ Create Sensor Update Policies by specifying details about the policy to create. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/createSensorUpdatePolicies - FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def deleteSensorUpdatePolicies(self, parameters): - """ Delete a set of Sensor Update Policies by specifying their IDs. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/deleteSensorUpdatePolicies - FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def updateSensorUpdatePolicies(self, parameters, body): - """ Update Sensor Update Policies by specifying the ID of the policy and details to update. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/updateSensorUpdatePolicies - FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def getSensorUpdatePoliciesV2(self, parameters): - """ Retrieve a set of Sensor Update Policies with additional support for uninstall protection by specifying their IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/getSensorUpdatePoliciesV2 - FULL_URL = self.base_url+'/policy/entities/sensor-update/v2' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def createSensorUpdatePoliciesV2(self, parameters, body): - """ Create Sensor Update Policies by specifying details about the policy to create with additional support for uninstall protection. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/createSensorUpdatePoliciesV2 - FULL_URL = self.base_url+'/policy/entities/sensor-update/v2' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def updateSensorUpdatePoliciesV2(self, parameters, body): - """ Update Sensor Update Policies by specifying the ID of the policy and details to update with additional support for uninstall protection. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/updateSensorUpdatePoliciesV2 - FULL_URL = self.base_url+'/users/entities/users/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def querySensorUpdatePolicyMembers(self, parameters): - """ Search for members of a Sensor Update Policy in your environment by providing an FQL - filter and paging details. Returns a set of Agent IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/querySensorUpdatePolicyMembers - FULL_URL = self.base_url+'/policy/queries/sensor-update-members/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def querySensorUpdatePolicies(self, parameters): - """ Search for Sensor Update Policies in your environment by providing an FQL filter and - paging details. Returns a set of Sensor Update Policy IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/querySensorUpdatePolicies - FULL_URL = self.base_url+'/policy/queries/sensor-update/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/spotlight_vulnerabilities.py b/falconpy/services/spotlight_vulnerabilities.py deleted file mode 100644 index 24c03968..00000000 --- a/falconpy/services/spotlight_vulnerabilities.py +++ /dev/null @@ -1,97 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# spotlight_vulnerabilities - Falcon X Spotlight Vulnerabilities API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class Spotlight_Vulnerabilities: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def getVulnerabilities(self, parameters): - """ Get details on vulnerabilities by providing one or more IDs. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/spotlight-vulnerabilities/getVulnerabilities - FULL_URL = self.base_url+'/spotlight/entities/vulnerabilities/v2' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def queryVulnerabilities(self, parameters): - """ Search for Vulnerabilities in your environment by providing an FQL filter - and paging details. Returns a set of Vulnerability IDs which match the filter criteria. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/spotlight-vulnerabilities/queryVulnerabilities - FULL_URL = self.base_url+'/spotlight/queries/vulnerabilities/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/falconpy/services/user_management.py b/falconpy/services/user_management.py deleted file mode 100644 index 55997df2..00000000 --- a/falconpy/services/user_management.py +++ /dev/null @@ -1,247 +0,0 @@ -################################################################################################################ -# CROWDSTRIKE FALCON # -# OAuth2 API - Customer SDK # -# # -# user_management - Falcon X User Management API Interface Class # -################################################################################################################ -# Copyright CrowdStrike 2020 - -# By accessing or using this script, sample code, application programming interface, tools, -# and/or associated documentation (if any) (collectively, “Tools”), You (i) represent and -# warrant that You are entering into this Agreement on behalf of a company, organization -# or another legal entity (“Entity”) that is currently a customer or partner of -# CrowdStrike, Inc. (“CrowdStrike”), and (ii) have the authority to bind such Entity and -# such Entity agrees to be bound by this Agreement. - -# CrowdStrike grants Entity a non-exclusive, non-transferable, non-sublicensable, royalty -# free and limited license to access and use the Tools solely for Entity’s internal business -# purposes and in accordance with its obligations under any agreement(s) it may have with -# CrowdStrike. Entity acknowledges and agrees that CrowdStrike and its licensors retain all -# right, title and interest in and to the Tools, and all intellectual property rights -# embodied therein, and that Entity has no right, title or interest therein except for the -# express licenses granted hereunder and that Entity will treat such Tools as CrowdStrike’s -# confidential information. - -# THE TOOLS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED OR -# STATUTORY OR OTHERWISE. CROWDSTRIKE SPECIFICALLY DISCLAIMS ALL SUPPORT OBLIGATIONS AND -# ALL WARRANTIES, INCLUDING WITHOUT LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL CROWDSTRIKE -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THE TOOLS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json -import urllib3 -from urllib3.exceptions import InsecureRequestWarning -urllib3.disable_warnings(InsecureRequestWarning) - -class User_Management: - """ The only requirement to instantiate an instance of this class - is a valid token provided by the Falcon API SDK OAuth2 class. - """ - - def __init__(self, access_token, base_url='https://api.crowdstrike.com'): - """ Instantiates the base class, ingests the authorization token, - and initializes the headers and base_url global variables. - """ - self.headers = { 'Authorization': 'Bearer {}'.format(access_token) } - self.base_url = base_url - - class Result: - """ Subclass to handle parsing of result client output. """ - def __init__(self): - """ Instantiates the subclass and initializes the result object. """ - self.result_obj = {} - - def __call__(self, status_code, headers, body): - """ Formats values into a properly formatted result object. """ - self.result_obj['status_code'] = status_code - self.result_obj['headers'] = dict(headers) - self.result_obj['body'] = body - - return self.result_obj - - def GetRoles(self, parameters): - """ Get info about a role. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetRoles - FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GrantUserRoleIds(self, parameters, body): - """ Assign one or more roles to a user. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GrantUserRoleIds - FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RevokeUserRoleIds(self, parameters): - """ Revoke one or more roles from a user. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RevokeUserRoleIds - FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetAvailableRoleIds(self): - """ Show role IDs for all roles available in your customer account. - For more information on each role, provide the role ID to `/customer/entities/roles/v1`. - """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetAvailableRoleIds - FULL_URL = self.base_url+'/user-roles/queries/user-role-ids-by-cid/v1' - HEADERS = self.headers - result = self.Result() - try: - response = requests.request("GET", FULL_URL, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def GetUserRoleIds(self, parameters): - """ Show role IDs of roles assigned to a user. For more information on each role, provide the role ID to `/customer/entities/roles/v1`. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetUserRoleIds - FULL_URL = self.base_url+'/user-roles/queries/user-role-ids-by-user-uuid/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RetrieveUser(self, parameters): - """ Get info about a user. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUser - FULL_URL = self.base_url+'/users/entities/users/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def CreateUser(self, parameters, body): - """ Create a new user. After creating a user, assign one or more roles with POST /user-roles/entities/user-roles/v1. """ - # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/CreateUser - FULL_URL = self.base_url+'/users/entities/users/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("POST", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def DeleteUser(self, parameters): - """ Delete a user permanently. """ - # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/DeleteUser - FULL_URL = self.base_url+'/users/entities/users/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("DELETE", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def UpdateUser(self, parameters, body): - """ Modify an existing user. """ - # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/UpdateUser - FULL_URL = self.base_url+'/users/entities/users/v1' - HEADERS = self.headers - DATA = body - PARAMS = parameters - result = self.Result() - try: - response = requests.request("PATCH", FULL_URL, params=PARAMS, json=DATA, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RetrieveEmailsByCID(self): - """ List the usernames (usually an email address) for all users in your customer account. """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveEmailsByCID - FULL_URL = self.base_url+'/users/queries/emails-by-cid/v1' - HEADERS = self.headers - result = self.Result() - try: - response = requests.request("GET", FULL_URL, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RetrieveUserUUIDsByCID(self): - """ List user IDs for all users in your customer account. For more information on each user, provide the user ID to `/users/entities/user/v1`.""" - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUserUUIDsByCID - FULL_URL = self.base_url+'/users/queries/user-uuids-by-cid/v1' - HEADERS = self.headers - result = self.Result() - try: - response = requests.request("GET", FULL_URL, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned - - def RetrieveUserUUID(self, parameters): - """ Get a user's ID by providing a username (usually an email address). """ - # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUserUUID - FULL_URL = self.base_url+'/users/queries/user-uuids-by-email/v1' - HEADERS = self.headers - PARAMS = parameters - result = self.Result() - try: - response = requests.request("GET", FULL_URL, params=PARAMS, headers=HEADERS, verify=False) - returned = result(response.status_code, response.headers, response.json()) - except Exception as e: - returned = result(500, {}, str(e)) - - return returned diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..39d15652 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3531 @@ +{ + "name": "coursebook", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@11ty/dependency-tree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree/-/dependency-tree-1.0.0.tgz", + "integrity": "sha512-2FWYlkphQ/83MG7b9qqBJfJJ0K9zupNz/6n4EdDuNLw6hQHGp4Sp4UMDRyBvA/xCTYDBaPSuSjHuu45tSujegg==", + "dev": true + }, + "@11ty/eleventy": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@11ty/eleventy/-/eleventy-0.11.0.tgz", + "integrity": "sha512-ozkfpmSlhodVoGCNFhBFsNbFxJbaiPYiVGKCeVdsFBTfDLhGyWS8cieNWjsvKyEHWT8OLNSIBvJYv4JxuxTivg==", + "dev": true, + "requires": { + "@11ty/dependency-tree": "^1.0.0", + "browser-sync": "^2.26.7", + "chalk": "^3.0.0", + "chokidar": "^3.4.0", + "debug": "^4.1.1", + "dependency-graph": "^0.9.0", + "ejs": "^2.7.4", + "fast-glob": "^3.2.2", + "fs-extra": "^8.1.0", + "gray-matter": "^4.0.2", + "hamljs": "^0.6.2", + "handlebars": "^4.7.6", + "javascript-stringify": "^2.0.1", + "liquidjs": "^6.4.3", + "lodash": "^4.17.15", + "luxon": "^1.24.1", + "markdown-it": "^10.0.0", + "minimist": "^1.2.5", + "moo": "^0.5.1", + "multimatch": "^4.0.0", + "mustache": "^2.3.2", + "normalize-path": "^3.0.0", + "nunjucks": "^3.2.1", + "parse-filepath": "^1.0.2", + "please-upgrade-node": "^3.2.0", + "pretty": "^2.0.0", + "pug": "^2.0.4", + "recursive-copy": "^2.0.10", + "semver": "^7.3.2", + "slugify": "^1.4.0", + "time-require": "^0.1.2", + "valid-url": "^1.0.9" + }, + "dependencies": { + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@sindresorhus/slugify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.0.tgz", + "integrity": "sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw==", + "dev": true, + "requires": { + "@sindresorhus/transliterate": "^0.1.1", + "escape-string-regexp": "^4.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + } + } + }, + "@sindresorhus/transliterate": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-0.1.1.tgz", + "integrity": "sha512-QSdIQ5keUFAZ3KLbfbsntW39ox0Ym8183RqTwBq/ZEFoN3NQAtGV+qWaNdzKpIDHgj9J2CQ2iNDRVU11Zyr7MQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0", + "lodash.deburr": "^4.1.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "@types/babel-types": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.8.tgz", + "integrity": "sha512-jvu8g4LR7+p6ao30RhTREnEhHxmP4/R9D9/rOR/Kq14FztORty9SKgtOZUNZNMB9CXLxZ54EWu4dArUE8WdTsw==", + "dev": true + }, + "@types/babylon": { + "version": "6.16.5", + "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", + "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", + "dev": true, + "requires": { + "@types/babel-types": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "acorn-globals": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "dev": true, + "requires": { + "acorn": "^4.0.4" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each-series": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", + "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-sync": { + "version": "2.26.12", + "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.12.tgz", + "integrity": "sha512-1GjAe+EpZQJgtKhWsxklEjpaMV0DrRylpHRvZWgOphDQt+bfLZjfynl/j1WjSFIx8ozj9j78g6Yk4TqD3gKaMA==", + "dev": true, + "requires": { + "browser-sync-client": "^2.26.12", + "browser-sync-ui": "^2.26.12", + "bs-recipes": "1.3.4", + "bs-snippet-injector": "^2.0.1", + "chokidar": "^3.4.1", + "connect": "3.6.6", + "connect-history-api-fallback": "^1", + "dev-ip": "^1.0.1", + "easy-extender": "^2.3.4", + "eazy-logger": "^3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "fs-extra": "3.0.1", + "http-proxy": "^1.18.1", + "immutable": "^3", + "localtunnel": "^2.0.0", + "micromatch": "^4.0.2", + "opn": "5.3.0", + "portscanner": "2.1.1", + "qs": "6.2.3", + "raw-body": "^2.3.2", + "resp-modifier": "6.0.2", + "rx": "4.1.0", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.13.2", + "server-destroy": "1.0.1", + "socket.io": "2.1.1", + "ua-parser-js": "^0.7.18", + "yargs": "^15.4.1" + }, + "dependencies": { + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "browser-sync-client": { + "version": "2.26.12", + "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.12.tgz", + "integrity": "sha512-bEBDRkufKxrIfjOsIB1FN9itUEXr2oLtz1AySgSSr80K2AWzmtoYnxtVASx/i40qFrSdeI31pNvdCjHivihLVA==", + "dev": true, + "requires": { + "etag": "1.8.1", + "fresh": "0.5.2", + "mitt": "^1.1.3", + "rxjs": "^5.5.6" + } + }, + "browser-sync-ui": { + "version": "2.26.12", + "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.12.tgz", + "integrity": "sha512-PkAJNf/TfCFTCkQUfXplR2Kp/+/lbCWFO9lrgLZsmxIhvMLx2pYZFBbTBIaem8qjXhld9ZcESUC8EdU5VWFJgQ==", + "dev": true, + "requires": { + "async-each-series": "0.1.1", + "connect-history-api-fallback": "^1", + "immutable": "^3", + "server-destroy": "1.0.1", + "socket.io-client": "^2.0.4", + "stream-throttle": "^0.1.3" + } + }, + "bs-recipes": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", + "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", + "dev": true + }, + "bs-snippet-injector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", + "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "dev": true, + "requires": { + "is-regex": "^1.0.3" + } + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "condense-newlines": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz", + "integrity": "sha1-PemFVTE5R10yUCyDsC9gaE0kxV8=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-whitespace": "^0.3.0", + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "constantinople": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", + "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", + "dev": true, + "requires": { + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "date-time": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-0.1.1.tgz", + "integrity": "sha1-7S9tk9l5DOL9ZtW1/z7dW7y/Owc=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "dependency-graph": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.9.0.tgz", + "integrity": "sha512-9YLIBURXj4DJMFALxXw9K3Y3rwb5Fk0X5/8ipCzaN84+gKxoHK43tVKRNakCQbiEx07E8Uwhuq21BpUagFhZ8w==", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "dev-ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", + "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", + "dev": true + }, + "doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=", + "dev": true + }, + "easy-extender": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", + "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "eazy-logger": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz", + "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=", + "dev": true, + "requires": { + "tfunk": "^3.0.1" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", + "dev": true + }, + "emitter-mixin": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/emitter-mixin/-/emitter-mixin-0.0.3.tgz", + "integrity": "sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "engine.io-client": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.3.tgz", + "integrity": "sha512-0NGY+9hioejTEJCaSJZfWZLk4FPI9dN+1H1C4+wj2iuFba47UgZbJzfWs4aNFajnX/qAaYKbe2lLTfEEWzCmcw==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + } + } + }, + "engine.io-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", + "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fastq": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "gray-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", + "integrity": "sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==", + "dev": true, + "requires": { + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, + "hamljs": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/hamljs/-/hamljs-0.6.2.tgz", + "integrity": "sha1-e3EWz22+cnjkKz9u+HJaM+F3yOM=", + "dev": true + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", + "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", + "dev": true, + "requires": { + "acorn": "~4.0.2", + "object-assign": "^4.0.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dev": true, + "requires": { + "lodash.isfinite": "^3.3.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-whitespace": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz", + "integrity": "sha1-Fjnssb4DauxppUy7QBz77XEUq38=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "javascript-stringify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.0.1.tgz", + "integrity": "sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow==", + "dev": true + }, + "js-beautify": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.12.0.tgz", + "integrity": "sha512-hZCm93+sWHqrsB2ac38cPX4A9t6mfReq13ZUr/0dk6rCXNLIq0R4lu0EiuJc0Ip6RiWNtE0vECjXOhcy/jMt9Q==", + "dev": true, + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "^1.0.4", + "nopt": "^4.0.3" + } + }, + "js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "dev": true, + "requires": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", + "dev": true + }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "liquidjs": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-6.4.3.tgz", + "integrity": "sha512-m1xSB10Ncu22NR3X0xdaqu/GvP1xadDCFYGqGgd6me8DAWjyA68BKE5DHJmSxw1CGsWPsX+Hj2v/87J2w/LvMQ==", + "dev": true + }, + "localtunnel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.0.tgz", + "integrity": "sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg==", + "dev": true, + "requires": { + "axios": "0.19.0", + "debug": "4.1.1", + "openurl": "1.1.1", + "yargs": "13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.deburr": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", + "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=", + "dev": true + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "luxon": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.24.1.tgz", + "integrity": "sha512-CgnIMKAWT0ghcuWFfCWBnWGOddM0zu6c4wZAWmD0NN7MZTnro0+833DF6tJep+xlxRPg4KtsYEHYLfTMBQKwYg==", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "markdown-it": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.0.tgz", + "integrity": "sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==", + "dev": true + }, + "markdown-it-title": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-title/-/markdown-it-title-3.0.0.tgz", + "integrity": "sha512-iHZptfptAXGJlcboqWxUSWNkJLUyxZ452CobBzkQ7MtwfVhTI77W1LTAy+miQTqo3U+wkDUOFhhXj2XUD0dVWQ==", + "dev": true + }, + "maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + }, + "dependencies": { + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + } + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mitt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "mustache": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", + "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "nunjucks": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", + "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", + "dev": true, + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "chokidar": "^3.3.0", + "commander": "^5.1.0" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-path": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz", + "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", + "dev": true + }, + "opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-ms": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-0.1.2.tgz", + "integrity": "sha1-3T+iXtbC78e93hKtm0bBY6opIk4=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "portscanner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", + "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", + "dev": true, + "requires": { + "async": "1.5.2", + "is-number-like": "^1.0.3" + } + }, + "pretty": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz", + "integrity": "sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU=", + "dev": true, + "requires": { + "condense-newlines": "^0.2.1", + "extend-shallow": "^2.0.1", + "js-beautify": "^1.6.12" + } + }, + "pretty-ms": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-0.2.2.tgz", + "integrity": "sha1-2oeaaC/zOjcBEEbxPWJ/Z8c7hPY=", + "dev": true, + "requires": { + "parse-ms": "^0.1.0" + } + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pug": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz", + "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==", + "dev": true, + "requires": { + "pug-code-gen": "^2.0.2", + "pug-filters": "^3.1.1", + "pug-lexer": "^4.1.0", + "pug-linker": "^3.0.6", + "pug-load": "^2.0.12", + "pug-parser": "^5.0.1", + "pug-runtime": "^2.0.5", + "pug-strip-comments": "^1.0.4" + } + }, + "pug-attrs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", + "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", + "dev": true, + "requires": { + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.5" + } + }, + "pug-code-gen": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", + "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", + "dev": true, + "requires": { + "constantinople": "^3.1.2", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.4", + "pug-error": "^1.3.3", + "pug-runtime": "^2.0.5", + "void-elements": "^2.0.1", + "with": "^5.0.0" + } + }, + "pug-error": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", + "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==", + "dev": true + }, + "pug-filters": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz", + "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==", + "dev": true, + "requires": { + "clean-css": "^4.1.11", + "constantinople": "^3.0.1", + "jstransformer": "1.0.0", + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "pug-lexer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz", + "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==", + "dev": true, + "requires": { + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.3" + } + }, + "pug-linker": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz", + "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==", + "dev": true, + "requires": { + "pug-error": "^1.3.3", + "pug-walk": "^1.1.8" + } + }, + "pug-load": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz", + "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "pug-walk": "^1.1.8" + } + }, + "pug-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz", + "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==", + "dev": true, + "requires": { + "pug-error": "^1.3.3", + "token-stream": "0.0.1" + } + }, + "pug-runtime": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", + "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==", + "dev": true + }, + "pug-strip-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz", + "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==", + "dev": true, + "requires": { + "pug-error": "^1.3.3" + } + }, + "pug-walk": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz", + "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==", + "dev": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "recursive-copy": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.10.tgz", + "integrity": "sha512-S9J9XJUnfZ2NUS3lK6lx6HWLl2nWui+f7AKuu+qoFs4ikEPYgZ3qKk1T6tmBnr7PzhtKnawE+6TREy9XQKmxCA==", + "dev": true, + "requires": { + "del": "^2.2.0", + "emitter-mixin": "0.0.3", + "errno": "^0.1.2", + "graceful-fs": "^4.1.4", + "junk": "^1.0.1", + "maximatch": "^0.1.0", + "mkdirp": "^0.5.1", + "pify": "^2.3.0", + "promise": "^7.0.1", + "slash": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resp-modifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", + "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", + "dev": true, + "requires": { + "debug": "^2.2.0", + "minimatch": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", + "dev": true + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slugify": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.5.tgz", + "integrity": "sha512-WpECLAgYaxHoEAJ8Q1Lo8HOs1ngn7LN7QjXgOLbmmfkcWvosyk4ZTXkTzKyhngK640USTZUlgoQJfED1kz5fnQ==", + "dev": true + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stream-throttle": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", + "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", + "dev": true, + "requires": { + "commander": "^2.2.0", + "limiter": "^1.0.5" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "tfunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-3.1.0.tgz", + "integrity": "sha1-OORBT8ZJd9h6/apy+sttKfgve1s=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "object-path": "^0.9.0" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + } + } + }, + "time-require": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/time-require/-/time-require-0.1.2.tgz", + "integrity": "sha1-+eEss3D8JgXhFARYK6VO9corLZg=", + "dev": true, + "requires": { + "chalk": "^0.4.0", + "date-time": "^0.1.1", + "pretty-ms": "^0.2.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + } + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "token-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", + "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", + "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.1.tgz", + "integrity": "sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q==", + "dev": true, + "optional": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "with": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", + "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", + "dev": true, + "requires": { + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..57119dfe --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "coursebook", + "version": "1.0.0", + "description": "Our open source web development curriculum", + "main": "index.js", + "scripts": { + "dev": "eleventy --serve --quiet", + "build": "ELEVENTY_ENV=production eleventy" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/crowdstrike/falconpy.git" + }, + "keywords": [], + "author": "Oliver Phillips (https://oliverjam.es)", + "license": "MIT", + "bugs": { + "url": "https://github.com/crowdstrike/falconpy/issues" + }, + "homepage": "https://github.com/crowdstrike/falconpy#readme", + "devDependencies": { + "@11ty/eleventy": "^0.11.0", + "@sindresorhus/slugify": "^1.1.0", + "markdown-it": "^11.0.0", + "markdown-it-anchor": "^5.3.0", + "markdown-it-task-lists": "^2.1.1", + "markdown-it-title": "^3.0.0" + } + } + \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..57e98bfe --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,18 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements-dev.in +# +# These packages are not necessary in order to +# communicate with the CrowdStrike Falcon OAuth2 API. +# +# These packages are only required if you are a contributor, +# or wish to use FalconDebug. +# +bandit>=1.7.0 # via -r requirements-dev.in +coverage>=5.5 # via -r requirements-dev.in +flake8>=3.9.0 # via -r requirements-dev.in +pytest-cov>=2.11.1 # via -r requirements-dev.in +pytest>=6.2.2 # via -r requirements-dev.in +ipython>=7.21.0 # via -r requirements-dev.in diff --git a/requirements.txt b/requirements.txt index 6f727908..a684efa4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,8 +4,6 @@ # # pip-compile requirements.in # -certifi==2020.11.8 # via requests -chardet==3.0.4 # via requests -idna==2.10 # via requests -requests==2.25.0 # via -r requirements.in -urllib3==1.26.2 # via -r requirements.in, requests +requests==2.25.1 # via -r requirements.in +urllib3==1.26.4 # via -r requirements.in, requests + diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 00000000..61c391ae --- /dev/null +++ b/samples/README.md @@ -0,0 +1,64 @@ +![CrowdStrike Falcon](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/cs-logo.png) + +[![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20%40CrowdStrike&style=social&url=https%3A%2F%2Ftwitter.com%2FCrowdStrike)](https://twitter.com/CrowdStrike) + +# FalconPy usage examples +These examples are provided as a quick start for your project. + ++ [Authentication for Examples](#authentication-for-these-examples) ++ [Samples by API service collection](#samples-by-api-service-collection) + - [Detections](#detections) + - [Event Streams](#event-streams) + - [Falcon Discover](#falcon-discover) + - [Hosts](#hosts) + - [Quick Scan / Sample Uploads](#quick-scan) + - [Real Time Response](#real-time-response) + - [Sample Uploads](#sample-uploads) ++ [Suggestions](#suggestions) + +## Authentication for these Examples +In order to expedite sample delivery, we will be following a standard pattern for defining and providing credentials to the API. +This is not the only method of providing these values, and not recommended for production deployments as the config.json file is +**not encrypted**. + +In order to test these samples locally in your development environment, rename the file `config_sample.json` to `config.json` and then +update this file to reflect your current development API credentials. + +## Samples by API service collection +These samples are categorized by API service collection. The list below will grow as more samples are planned. + +### Detections +_Coming Soon_ + +### Event Streams +_Coming Soon_ + +### Falcon Discover +| Service Class | Uber Class | +| :--- | :--- | +| [Register, delete, update and check accounts](discover_aws/manage_discover_accounts_service.py) | [Register, delete, update and check accounts](discover_aws/manage_discover_accounts_uber.py) | + + +### Hosts +_Coming Soon_ + +### Quick Scan / Sample Uploads +| Service Class | Uber Class | +| :--- | :--- | +| [Scan a target folder or bucket](quick_scan/scan_target.py) | | + + +### Real Time Response +| Service Class | Uber Class | +| :--- | :--- | +| [Quarantine a host](real_time_response/quarantine_hosts.py) | | + +### Sample Uploads +| Service Class | Uber Class | +| :--- | :--- | +| [Upload, Retrieve and then Delete a file](sample_uploads/sample_uploads_service.py) | [Upload, Retrieve and then Delete a file](sample_uploads/sample_uploads_uber.py) | + +## Suggestions +Got a suggestion for an example you'd like to see? Let us know by posting a message to our [discussion board](https://github.com/CrowdStrike/falconpy/discussions). + +Have an example you've developed yourself that you'd like to share? **_Excellent!_** Please review our [contributing guidelines](/CONTRIBUTING.md) and then submit a pull request. \ No newline at end of file diff --git a/samples/config_sample.json b/samples/config_sample.json new file mode 100644 index 00000000..51d83b29 --- /dev/null +++ b/samples/config_sample.json @@ -0,0 +1,4 @@ +{ + "falcon_client_id": "API ID GOES HERE", + "falcon_client_secret": "API SECRET GOES HERE" +} diff --git a/samples/discover_aws/manage_discover_accounts_service.py b/samples/discover_aws/manage_discover_accounts_service.py new file mode 100644 index 00000000..49a76b32 --- /dev/null +++ b/samples/discover_aws/manage_discover_accounts_service.py @@ -0,0 +1,260 @@ +# ____ _ _ ____ _ ___ ______ +# / ___| | ___ _ _ __| | / ___|___ _ __ _ __ ___ ___| |_ / \ \ / / ___| +# | | | |/ _ \| | | |/ _` | | | / _ \| '_ \| '_ \ / _ \/ __| __| / _ \ \ /\ / /\___ \ +# | |___| | (_) | |_| | (_| | | |__| (_) | | | | | | | __/ (__| |_ / ___ \ V V / ___) | +# \____|_|\___/ \__,_|\__,_| \____\___/|_| |_|_| |_|\___|\___|\__| /_/ \_\_/\_/ |____/ +# +# This is a modified version of the script falcon_discover_accounts, a troubleshooting script +# posted to our Cloud-AWS repository at https://github.com/CrowdStrike/Cloud-AWS. +# +# This solution demonstrates accepting user input to query the CrowdStrike Falcon Discover API +# to register, update and delete AWS accounts. An additional check function loops through all +# accounts registered, and returns configuration detail to assist with troubleshooting setup. +# +# This example leverages the Cloud Connect AWS Service Class and legacy authentication. +# +import argparse +import json +import sys +# Falcon SDK - Cloud_Connect_AWS and OAuth2 API service classes +from falconpy import cloud_connect_aws as FalconAWS +from falconpy import oauth2 as FalconAuth + + +# =============== FORMAT API PAYLOAD +def format_api_payload(rate_limit_reqs=0, rate_limit_time=0): + # Generates a properly formatted JSON payload for POST and PATCH requests + data = { + "resources": [ + { + "cloudtrail_bucket_owner_id": cloudtrail_bucket_owner_id, + "cloudtrail_bucket_region": cloudtrail_bucket_region, + "external_id": external_id, + "iam_role_arn": iam_role_arn, + "id": local_account, + "rate_limit_reqs": rate_limit_reqs, + "rate_limit_time": rate_limit_time + } + ] + } + return data + + +# =============== ACCOUNT VALUE +def account_value(id, val, accts): + # Returns the specified value for a specific account id within account_list + returned = False + for item in accts: + if item["id"] == id: + returned = item[val] + return returned + + +# =============== CHECK ACCOUNTS +def check_account(): + + # Retrieve the account list + account_list = falcon_discover.QueryAWSAccounts(parameters={"limit": int(query_limit)})["body"]["resources"] + # Log the results of the account query to a file if logging is enabled + if log_enabled: + with open('falcon-discover-accounts.json', 'w+') as f: + json.dump(account_list, f) + # Create a list of our account IDs out of account_list + id_items = [] + for z in account_list: + id_items.append(z["id"]) + q_max = 10 # VerifyAWSAccountAccess has a ID max count of 10 + for index in range(0, len(id_items), q_max): + sub_acct_list = id_items[index:index + q_max] + temp_list = ",".join([a for a in sub_acct_list]) + access_response = falcon_discover.VerifyAWSAccountAccess(ids=temp_list) + if access_response['status_code'] == 200: + # Loop through each ID we verified + for result in access_response["body"]["resources"]: + if result["successful"]: + # This account is correctly configured + print(f'Account {result["id"]} is ok!') + else: + # This account is incorrectly configured. We'll use our account_value function to + # retrieve configuration values from the account list we've already ingested. + account_values_to_check = { + 'id': result["id"], + 'iam_role_arn': account_value(result["id"], "iam_role_arn", account_list), + 'external_id': account_value(result["id"], "external_id", account_list), + 'cloudtrail_bucket_owner_id': account_value(result["id"], "cloudtrail_bucket_owner_id", account_list), + 'cloudtrail_bucket_region': account_value(result["id"], "cloudtrail_bucket_region", account_list), + } + # Use the account_value function to retrieve the access_health branch, + # which contains our api failure reason. + try: + print('Account {} has a problem: {}'.format(result["id"], + account_value(result["id"], + "access_health", + account_list + )["api"]["reason"] + )) + except Exception: + # The above call will produce an error if we're running + # check immediately after registering an account as + # the access_health branch hasn't been populated yet. + # Requery the API for the account_list when this happens. + account_list = falcon_discover.QueryAWSAccounts( + parameters={"limit": f"{str(query_limit)}"} + )["body"]["resources"] + print('Account {} has a problem: {}'.format(result["id"], + account_value(result["id"], + "access_health", + account_list + )["api"]["reason"] + )) + # Output the account details to the user to assist with troubleshooting the account + print(f'Current settings {json.dumps(account_values_to_check, indent=4)}\n') + else: + try: + # An error has occurred + print("Got response error code {} message {}".format(access_response["status_code"], + access_response["body"]["errors"][0]["message"] + )) + except Exception: + # Handle any egregious errors that break our return error payload + print("Got response error code {} message {}".format(access_response["status_code"], access_response["body"])) + return + + +# =============== REGISTER ACCOUNT +def register_account(): + # Call the API to update the requested account. + register_response = falcon_discover.ProvisionAWSAccounts(parameters={}, body=format_api_payload()) + if register_response["status_code"] == 201: + print("Successfully registered account.") + else: + print("Registration failed with response: {} {}".format(register_response["status_code"], + register_response["body"]["errors"][0]["message"] + )) + + return + + +# =============== UPDATE ACCOUNT +def update_account(): + # Call the API to update the requested account. + update_response = falcon_discover.UpdateAWSAccounts(body=format_api_payload()) + if update_response["status_code"] == 200: + print("Successfully updated account.") + else: + print("Update failed with response: {} {}".format(update_response["status_code"], + update_response["body"]["errors"][0]["message"] + )) + + return + + +# =============== DELETE ACCOUNT +def delete_account(): + # Call the API to delete the requested account, multiple IDs can be deleted by passing in a comma-delimited list + delete_response = falcon_discover.DeleteAWSAccounts(ids=local_account) + if delete_response["status_code"] == 200: + print("Successfully deleted account.") + else: + print("Delete failed with response: {} {}".format(delete_response["status_code"], + delete_response["body"]["errors"][0]["message"] + )) + + return + + +# =============== MAIN + +# Configure argument parsing +parser = argparse.ArgumentParser(description="Get Params to send notification to CRWD topic") +# Fully optional +parser.add_argument('-q', '--query_limit', help='The query limit used for check account commands', required=False) +parser.add_argument('-l', '--log_enabled', help='Save results to a file?', required=False, action="store_true") +# Optionally required +parser.add_argument('-r', '--cloudtrail_bucket_region', help='AWS Region where the S3 bucket is hosted', + required=False) +parser.add_argument('-o', '--cloudtrail_bucket_owner_id', help='Account where the S3 bucket is hosted', + required=False) +parser.add_argument('-a', '--local_account', help='This AWS Account', required=False) +parser.add_argument('-e', '--external_id', help='External ID used to assume role in account', required=False) +parser.add_argument('-i', '--iam_role_arn', + help='IAM AWS IAM Role ARN that grants access to resources for Crowdstrike', required=False) +# Always required +parser.add_argument('-c', '--command', help='Troubleshooting action to perform', required=True) +parser.add_argument("-f", "--falcon_client_id", help="Falcon Client ID", required=True) +parser.add_argument("-s", "--falcon_client_secret", help="Falcon Client Secret", required=True) +args = parser.parse_args() + +# =============== SET GLOBALS +command = args.command +# Only execute our defined commands +if command.lower() in "check,update,register,delete": + if command.lower() in "update,register": + # All fields required for update and register + if (args.cloudtrail_bucket_owner_id is None or + args.cloudtrail_bucket_region is None or + args.local_account is None or + args.external_id is None or + args.iam_role_arn is None): + parser.error("The {} command requires the -r, -o, -a, -e, -i arguments to also be specified.".format(command)) + else: + cloudtrail_bucket_region = args.cloudtrail_bucket_region + cloudtrail_bucket_owner_id = args.cloudtrail_bucket_owner_id + local_account = args.local_account + external_id = args.external_id + iam_role_arn = args.iam_role_arn + elif command.lower() in "delete": + # Delete only requires the local account ID + if args.local_account is None: + parser.error("The {} command requires the -l argument to also be specified.".format(command)) + else: + local_account = args.local_account +else: + parser.error("The {} command is not recognized.".format(command)) +# These globals exist for all requests +falcon_client_id = args.falcon_client_id +falcon_client_secret = args.falcon_client_secret +log_enabled = args.log_enabled +if args.query_limit is None: + query_limit = 100 +else: + query_limit = args.query_limit + +# =============== MAIN ROUTINE +# Authenticate using our provided falcon client_id and client_secret +try: + authorized = FalconAuth.OAuth2(creds={'client_id': falcon_client_id, 'client_secret': falcon_client_secret}) +except Exception: + # We can't communicate with the endpoint, return a false token + authorized.token = lambda: False +# Try to retrieve a token from our authentication, returning false on failure +try: + token = authorized.token()["body"]["access_token"] +except Exception: + token = False + +# Confirm the token was successfully retrieved +if token: + # Connect using our token and return an instance of the API gateway object + falcon_discover = FalconAWS.Cloud_Connect_AWS(access_token=token) + try: + # Execute the requested command + if command.lower() == "delete": + delete_account() + elif command.lower() == "register": + register_account() + elif command.lower() == "update": + update_account() + else: + check_account() + except Exception as e: + # Handle any previously unhandled errors + print("Command failed with error: {}.".format(str(e))) + # Discard our token before we exit + authorized.revoke(token) +else: + # Report that authentication failed and stop processing + print("Failed to retrieve authentication token.") + +# Force clean exit +sys.exit(0) diff --git a/samples/discover_aws/manage_discover_accounts_uber.py b/samples/discover_aws/manage_discover_accounts_uber.py new file mode 100644 index 00000000..d19e729b --- /dev/null +++ b/samples/discover_aws/manage_discover_accounts_uber.py @@ -0,0 +1,255 @@ +# ____ _ _ ____ _ ___ ______ +# / ___| | ___ _ _ __| | / ___|___ _ __ _ __ ___ ___| |_ / \ \ / / ___| +# | | | |/ _ \| | | |/ _` | | | / _ \| '_ \| '_ \ / _ \/ __| __| / _ \ \ /\ / /\___ \ +# | |___| | (_) | |_| | (_| | | |__| (_) | | | | | | | __/ (__| |_ / ___ \ V V / ___) | +# \____|_|\___/ \__,_|\__,_| \____\___/|_| |_|_| |_|\___|\___|\__| /_/ \_\_/\_/ |____/ +# +# This is a modified version of the script falcon_discover_accounts, a troubleshooting script +# posted to our Cloud-AWS repository at https://github.com/CrowdStrike/Cloud-AWS. +# +# This solution demonstrates accepting user input to query the CrowdStrike Falcon Discover API +# to register, update and delete AWS accounts. An additional check function loops through all +# accounts registered, and returns configuration detail to assist with troubleshooting setup. +# +# This example leverages the Uber Class. +# +import argparse +import json +import sys +# Falcon SDK - All in one uber-class +from falconpy import api_complete as FalconSDK + + +# =================== FORMAT API PAYLOAD +def format_api_payload(rate_limit_reqs=0, rate_limit_time=0): + # Generates a properly formatted JSON payload for POST and PATCH requests + data = { + "resources": [ + { + "cloudtrail_bucket_owner_id": cloudtrail_bucket_owner_id, + "cloudtrail_bucket_region": cloudtrail_bucket_region, + "external_id": external_id, + "iam_role_arn": iam_role_arn, + "id": local_account, + "rate_limit_reqs": rate_limit_reqs, + "rate_limit_time": rate_limit_time + } + ] + } + return data + + +# =============== ACCOUNT VALUE +def account_value(id, val, accts): + # Returns the specified value for a specific account id within account_list + returned = False + for item in accts: + if item["id"] == id: + returned = item[val] + return returned + + +# =================== CHECK ACCOUNTS +def check_account(): + # Retrieve the account list + account_list = falcon.command(action="QueryAWSAccounts", + parameters={"limit": "{}".format(str(query_limit))} + )["body"]["resources"] + # Log the results of the account query to a file if logging is enabled + if log_enabled: + with open('falcon-discover-accounts.json', 'w+') as f: + json.dump(account_list, f) + # Create a list of our account IDs out of account_list + id_items = [] + for z in account_list: + id_items.append(z["id"]) + + q_max = 10 # VerifyAWSAccountAccess has a ID max count of 10 + for index in range(0, len(id_items), q_max): + sub_acct_list = id_items[index:index + q_max] + temp_list = ",".join([a for a in sub_acct_list]) + # Check our AWS account access against the list of accounts returned in our query + access_response = falcon.command(action="VerifyAWSAccountAccess", ids=temp_list) + if access_response['status_code'] == 200: + # Loop through each ID we verified + for result in access_response["body"]["resources"]: + if result["successful"]: + # This account is correctly configured + print(f'Account {result["id"]} is ok!') + else: + # This account is incorrectly configured. We'll use our account_value function to + # retrieve configuration values from the account list we've already ingested. + account_values_to_check = { + 'id': result["id"], + 'iam_role_arn': account_value(result["id"], "iam_role_arn", account_list), + 'external_id': account_value(result["id"], "external_id", account_list), + 'cloudtrail_bucket_owner_id': account_value(result["id"], "cloudtrail_bucket_owner_id", account_list), + 'cloudtrail_bucket_region': account_value(result["id"], "cloudtrail_bucket_region", account_list), + } + # Use the account_value function to retrieve the access_health branch, + # which contains our api failure reason + try: + print('Account {} has a problem: {}'.format(result["id"], + account_value(result["id"], + "access_health", + account_list + )["api"]["reason"] + )) + except Exception: + # The above call will produce an error if we're running + # check immediately after registering an account as + # the access_health branch hasn't been populated yet. + # Requery the API for the account_list when this happens. + account_list = falcon.command(action="QueryAWSAccounts", + parameters={"limit": "{}".format(str(query_limit))} + )["body"]["resources"] + print('Account {} has a problem: {}'.format(result["id"], + account_value(result["id"], + "access_health", + account_list + )["api"]["reason"] + )) + # Output the account details to the user to assist with troubleshooting the account + print(f'Current settings {json.dumps(account_values_to_check, indent=4)}\n') + else: + try: + # An error has occurred + print("Got response error code {} message {}".format(access_response["status_code"], + access_response["body"]["errors"][0]["message"] + )) + except Exception: + # Handle any egregious errors that break our return error payload + print("Got response error code {} message {}".format(access_response["status_code"], access_response["body"])) + + return + + +# =================== REGISTER ACCOUNT +def register_account(): + # Call the API to update the requested account. + register_response = falcon.command(action="ProvisionAWSAccounts", parameters={}, body=format_api_payload()) + if register_response["status_code"] == 201: + print("Successfully registered account.") + else: + print("Registration failed with response: {} {}".format(register_response["status_code"], + register_response["body"]["errors"][0]["message"] + )) + + return + + +# =================== UPDATE ACCOUNT +def update_account(): + # Call the API to update the requested account. + update_response = falcon.command(action="UpdateAWSAccounts", body=format_api_payload()) + if update_response["status_code"] == 200: + print("Successfully updated account.") + else: + print("Update failed with response: {} {}".format(update_response["status_code"], + update_response["body"]["errors"][0]["message"] + )) + + return + + +# =================== DELETE ACCOUNT +def delete_account(): + # Call the API to delete the requested account, multiple IDs can be deleted by passing in a comma-delimited list + delete_response = falcon.command(action="DeleteAWSAccounts", parameters={}, ids=local_account) + if delete_response["status_code"] == 200: + print("Successfully deleted account.") + else: + print("Delete failed with response: {} {}".format(delete_response["status_code"], + delete_response["body"]["errors"][0]["message"] + )) + + return + + +# =================== MAIN + +# Configure argument parsing +parser = argparse.ArgumentParser(description="Get Params to send notification to CRWD topic") +# Fully optional +parser.add_argument('-q', '--query_limit', help='The query limit used for check account commands', required=False) +parser.add_argument('-l', '--log_enabled', help='Save results to a file?', required=False, action="store_true") +# Optionally required +parser.add_argument('-r', '--cloudtrail_bucket_region', help='AWS Region where the S3 bucket is hosted', + required=False) +parser.add_argument('-o', '--cloudtrail_bucket_owner_id', help='Account where the S3 bucket is hosted', + required=False) +parser.add_argument('-a', '--local_account', help='This AWS Account', required=False) +parser.add_argument('-e', '--external_id', help='External ID used to assume role in account', required=False) +parser.add_argument('-i', '--iam_role_arn', + help='IAM AWS IAM Role ARN that grants access to resources for Crowdstrike', required=False) +# Always required +parser.add_argument('-c', '--command', help='Troubleshooting action to perform', required=True) +parser.add_argument("-f", "--falcon_client_id", help="Falcon Client ID", required=True) +parser.add_argument("-s", "--falcon_client_secret", help="Falcon Client Secret", required=True) +args = parser.parse_args() + +# =================== SET GLOBALS +command = args.command +# Only execute our defined commands +if command.lower() in "check,update,register,delete": + if command.lower() in "update,register": + # All fields required for update and register + if (args.cloudtrail_bucket_owner_id is None or + args.cloudtrail_bucket_region is None or + args.local_account is None or + args.external_id is None or + args.iam_role_arn is None): + parser.error("The {} command requires the -r, -o, -a, -e, -i arguments to also be specified.".format(command)) + else: + cloudtrail_bucket_region = args.cloudtrail_bucket_region + cloudtrail_bucket_owner_id = args.cloudtrail_bucket_owner_id + local_account = args.local_account + external_id = args.external_id + iam_role_arn = args.iam_role_arn + elif command.lower() in "delete": + # Delete only requires the local account ID + if args.local_account is None: + parser.error("The {} command requires the -l argument to also be specified.".format(command)) + else: + local_account = args.local_account +else: + parser.error("The {} command is not recognized.".format(command)) +# These globals exist for all requests +falcon_client_id = args.falcon_client_id +falcon_client_secret = args.falcon_client_secret +log_enabled = args.log_enabled +if args.query_limit is None: + 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 = FalconSDK.APIHarness(creds={'client_id': falcon_client_id, 'client_secret': falcon_client_secret}) +except Exception: + # We can't communicate with the endpoint + print("Unable to communicate with API") +# Authenticate +if falcon.authenticate(): + try: + # Execute the requested command + if command.lower() == "delete": + delete_account() + elif command.lower() == "register": + register_account() + elif command.lower() == "update": + update_account() + else: + check_account() + except Exception as e: + # Handle any previously unhandled errors + print("Command failed with error: {}.".format(str(e))) + # Discard our token before we exit + falcon.deauthenticate() +else: + # Report that authentication failed and stop processing + print("Authentication Failure.") + +# Force clean exit +sys.exit(0) diff --git a/samples/quick_scan/README.md b/samples/quick_scan/README.md new file mode 100644 index 00000000..5c9829ff --- /dev/null +++ b/samples/quick_scan/README.md @@ -0,0 +1,43 @@ +![CrowdStrike Falcon](https://raw.githubusercontent.com/CrowdStrike/falconpy/main/docs/asset/cs-logo.png) + +[![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20%40CrowdStrike&style=social&url=https%3A%2F%2Ftwitter.com%2FCrowdStrike)](https://twitter.com/CrowdStrike) + +# Sandbox / Quick Scan sample +This is a proof of concept. Extensive performance testing has not been performed at this time. + +## Notes ++ A **VOLUME** is a collection of files that are uploaded and then scanned as a singular batch. ++ The log file rotates to prevent file system bloat. + +## Local Directory scanning ++ The folder is inventoried and then files are uploaded to the API in a linear fashion. ++ This method is impacted by data transfer speeds from the source file system location to CrowdStrike's cloud. ++ Supports pattern matching to filter objects scanned using the "--pattern" or "-p" command line parameter. + +## S3 Bucket scanning ++ The bucket contents are inventoried, and then the contents are downloaded to local memory and +uploaded to the Sandbox API in a linear fashion. ++ This method does NOT store the files on the local file system. ++ Due to the nature of this solution, the method is heavily impacted by data transfer speeds. + - Recommended deployment pattern involves running in AWS within a container, an EC2 instance or as a serverless lambda. ++ Currently scans the entire bucket only. ++ You must specify a target that includes the string "s3://" in order to scan a bucket. + +## Dependencies ++ boto3 ++ crowdstrike-falconpy 0.4.5+ + +```shell +python3 -m pip install boto3 crowdstrike-falconpy +``` + +## Example config.json file: +```json +{ + "falcon_client_id": "API ID GOES HERE", + "falcon_client_secret": "API SECRET GOES HERE" +} +``` + +## Alpha testing +This solution has been tested on Python 3.7 / 3.9 running under Amazon Linux 2 and MacOS 10.15. diff --git a/samples/quick_scan/scan_target.py b/samples/quick_scan/scan_target.py new file mode 100644 index 00000000..41c26c24 --- /dev/null +++ b/samples/quick_scan/scan_target.py @@ -0,0 +1,364 @@ +"""Quick Scan a folder or a bucket""" +# _______ ___ ___ ___ _______ ___ ___ _______ _______ _______ ______ _______ _______ ___ +# | _ | Y | | _ | Y ) | _ | _ | _ | _ \ | _ | _ | | +# |. | |. | |. |. 1___|. 1 / | 1___|. 1___|. 1 |. | | |. 1 |. 1 |. | +# |. | |. | |. |. |___|. _ \ |____ |. |___|. _ |. | | |. _ |. ____|. | +# |: 1 |: 1 |: |: 1 |: | \ |: 1 |: 1 |: | |: | | |: | |: | |: | +# |::.. |::.. . |::.|::.. . |::.| . ) |::.. . |::.. . |::.|:. |::.| | |::.|:. |::.| |::.| +# `----|:.`-------`---`-------`--- ---' `-------`-------`--- ---`--- ---' `--- ---`---' `---' +# `--' Josh's Quick Scan experiment +# +# Scans either a folder or a S3 bucket using the CrowdStrike Falcon X Quick Scan and Sandbox APIs. +# +# Created // 04.12.21: jshcodes@CrowdStrike - In order to proceed, please insert 16oz of coffee. +# +# ===== NOTES REGARDING THIS SOLUTION ============================================================ +# +# This is a proof of concept. Extensive performance testing has not been performed at this time. +# +# A VOLUME is a collection of files that are uploaded and then scanned as a singular batch. +# +# LOCAL DIRECTORY scanning: the folder is inventoried and then files are uploaded to the API in a +# linear fashion. This method is only impacted by data transfer speeds from the source file system +# location to CrowdStrike's cloud. Supports pattern matching to filter objects scanned using the +# "--pattern" or "-p" command line parameter. +# +# S3 BUCKET scanning: the bucket contents are inventoried, and then the contents are downloaded +# to local memory and uploaded to the Sandbox API in a linear fashion. This method does NOT store +# the files on the local file system. Due to the nature of this solution, the method is heavily +# impacted by data transfer speeds. Recommended deployment pattern involves running in AWS within +# a container, an EC2 instance or as a serverless lambda. Scans the entire bucket whether you like +# it or not. You must specify a target that includes the string "s3://" in order to scan a bucket. +# +# The log file rotates because cool kids don't leave messes on other people's file systems. +# +# This solution is dependant upon Amazon's boto3 library, and CrowdStrike FalconPy >= v0.4.5. +# python3 -m pip install boto3 crowdstrike-falconpy +# +# Example config.json file: +# +# { +# "falcon_client_id": "API ID GOES HERE", +# "falcon_client_secret": "API SECRET GOES HERE" +# } +# +# +# This solution has been tested on Python 3.7 / 3.9 running under Amazon Linux 2 and MacOS 10.15. +# +# ================================================================================================ +# +import io +import os +import json +import time +import argparse +import logging +from logging.handlers import RotatingFileHandler +from pathlib import Path +# AWS Boto library +import boto3 # pylint: disable=E0401 +# !!! Requires FalconPy v0.4.5+ !!! +# Authorization +from falconpy import oauth2 as FalconAuth # pylint: disable=E0401 +# Sandbox Uploads +from falconpy import sample_uploads as FalconUploads # pylint: disable=E0401 +# Quick Scan +from falconpy import quick_scan as FalconScan # pylint: disable=E0401 + + +class Analysis: # pylint: disable=R0903 + """Class to hold our analysis and status""" + def __init__(self): + self.uploaded = [] + self.files = [] + self.scanning = True + # Dynamically create our payload using the contents of our uploaded list + self.payload = lambda: {"samples": self.uploaded} + + +class Configuration: # pylint: disable=R0903 + """Class to hold our running configuration""" + def __init__(self, args): + self.config_file = "../config.json" + if args.config_file: + self.config_file = args.config_file + self.log_level = logging.INFO + if args.log_level: + if args.log_level.upper() in "DEBUG,WARN,ERROR".split(","): + if args.log_level.upper() == "DEBUG": + self.log_level = logging.DEBUG + elif args.log_level.upper() == "WARN": + self.log_level = logging.WARN + elif args.log_level.upper() == "ERROR": + self.log_level = logging.ERROR + + self.target_pattern = "**/*.*" + if args.pattern: + self.target_pattern = args.pattern + self.scan_delay = 3 + if args.check_delay: + try: + self.scan_delay = int(args.check_delay) + except ValueError: + # They gave us garbage, ignore it + pass + # Will stop processing if you give us a bucket and no region + self.region = None + if args.region: + self.region = args.region + # Target directory or bucket to be scanned + if "s3://" in args.target: + self.target_dir = args.target.replace("s3://", "") + self.bucket = True + else: + self.target_dir = args.target + self.bucket = False + + +def upload_samples(): + """Uploads the samples identified within the target to the Sandbox API""" + # Retrieve a list of all files and paths within the target + paths = Path(Config.target_dir).glob(Config.target_pattern) + # Inform the user as to what we're doing + logger.info("Assembling %s volume for submission", Config.target_dir) + # Loop through each identified file and upload it to the sandbox for analysis + for path in paths: + # Convert the path to a string + filepath = str(path) + # Grab the file name + filename = os.path.basename(filepath) + # Open the file for binary read, this will be our payload + payload = open(filepath, 'rb').read() + # Upload the file using the Sandbox + response = Samples.UploadSampleV3(file_name=filename, file_data=payload) + # Grab the SHA256 unique identifier for the file we just uploaded + sha = response["body"]["resources"][0]["sha256"] + # Add this SHA256 to the volume payload element + Analyzer.uploaded.append(sha) + # Track the upload so we can remove the file when we're done + Analyzer.files.append([filename, filepath, sha]) + # Inform the user of our progress + logger.debug("Uploaded %s to %s", filename, sha) + + +def upload_bucket_samples(): + """Retrieves keys from a bucket and then uploads them to the Sandbox API""" + if not Config.region: + logger.error("You must specify a region in order to scan a bucket target") + raise SystemExit("Target region not specified. Use -r or --region to specify the target region.") + # Connect to S3 in our target region + s_3 = boto3.resource("s3", region_name=Config.region) + # Connect to our target bucket + bucket = s_3.Bucket(Config.target_dir) + # Retrieve a list of all objects in the bucket + summaries = bucket.objects.all() + # Inform the user as this may take a minute + logger.info("Assembling volume from target bucket (%s) for submission", Config.target_dir) + # Loop through our list of files, downloading each to memory then upload them to the Sandbox + for item in summaries: + # Grab the file name from the path + filename = os.path.basename(item.key) + # Teensy bit of witch-doctor magic to download the file + # straight into the payload used for our upload to the Sandbox + response = Samples.UploadSampleV3(file_name=filename, + file_data=io.BytesIO(bucket.Object(key=item.key).get()["Body"].read()) + ) + # Retrieve our uploaded file SHA256 identifier + sha = response["body"]["resources"][0]["sha256"] + # Add this SHA256 to the upload payload element + Analyzer.uploaded.append(sha) + # Track the upload so we recognize the file when we're done + Analyzer.files.append([filename, item.key, sha]) + # Inform the user of our progress + logger.debug("Uploaded %s to %s", filename, sha) + + +def scan_samples() -> dict: + """Retrieves a scan using the ID of the scan provided by the scan submission""" + while Analyzer.scanning: + # Retrieve the scan results + scan_results = Scanner.GetScans(ids=scan_id) + try: + if scan_results["body"]["resources"][0]["status"] == "done": + # Scan is complete, retrieve our results + results = scan_results["body"]["resources"][0]["samples"] + # and break out of the loop + Analyzer.scanning = False + else: + # Not done yet, sleep for a bit + time.sleep(Config.scan_delay) + except IndexError: + # Results aren't populated yet, skip + pass + + return results + + +def report_results(results: dict): + """Retrieves the scan results for the submitted scan""" + # Loop thru our results, compare to our upload and return the verdict + for result in results: + for item in Analyzer.files: + if result["sha256"] == item[2]: + if "no specific threat" in result["verdict"]: + # File is clean + logger.info("Verdict for %s: %s", item[1], result["verdict"]) + else: + # Mitigation would trigger from here + logger.warning("Verdict for %s: %s", item[1], result["verdict"]) + + +def clean_up_artifacts(): + """Removes uploaded files from the Sandbox""" + logger.info("Removing artifacts from Sandbox") + for item in Analyzer.uploaded: + # Perform the delete + response = Samples.DeleteSampleV3(ids=item) + if response["status_code"] > 201: + # File was not removed, log the failure + logger.warning("Failed to delete %s", item) + else: + logger.debug("Deleted %s", item) + logger.info("Artifact cleanup complete") + + +def parse_command_line(): + """Parse any inbound command line arguments and set defaults""" + parser = argparse.ArgumentParser("Falcon Quick Scan") + parser.add_argument("-f", "--config", dest="config_file", help="Path to the configuration file", required=False) + parser.add_argument("-l", "--log-level", dest="log_level", help="Default log level (DEBUG, WARN, INFO, ERROR)", + required=False) + parser.add_argument("-d", "--check-delay", dest="check_delay", help="Delay between checks for scan results", + required=False) + parser.add_argument("-p", "--pattern", dest="pattern", help="Target file patterns to scan (defaults to *.*)", + required=False) + parser.add_argument("-r", "--region", dest="region", help="Region the target bucket resides in", required=False) + parser.add_argument("-t", "--target", dest="target", + help="Target folder or bucket to scan. Bucket must have 's3://' prefix.", required=True) + + return parser.parse_args() + + +def load_api_config(): + """Grab our config parameters from our provided config file (JSON format)""" + with open(Config.config_file, 'r') as file_config: + conf = json.loads(file_config.read()) + + return FalconAuth.OAuth2(creds={ + "client_id": conf["falcon_client_id"], + "client_secret": conf["falcon_client_secret"] + } + ) + + +def enable_logging(): + """Configure logging""" + logging.basicConfig(level=Config.log_level, format="%(asctime)s %(name)s %(levelname)s %(message)s") + # Create our logger + log = logging.getLogger("Quick Scan") + # Rotate log file handler + rfh = RotatingFileHandler("falcon_quick_scan.log", maxBytes=20971520, backupCount=5) + # Log file output format + f_format = logging.Formatter('%(asctime)s %(name)s %(levelname)s %(message)s') + # Set the log file output level to INFO + rfh.setLevel(Config.log_level) + # Add our log file formatter to the log file handler + rfh.setFormatter(f_format) + # Add our log file handler to our logger + log.addHandler(rfh) + + return log + + +if __name__ == '__main__': + # Parse the inbound command line parameters and setup our running Config object + Config = Configuration(parse_command_line()) + # Activate logging + logger = enable_logging() + # Grab our authentication object + auth = load_api_config() + # Connect to the Samples Sandbox API + Samples = FalconUploads.Sample_Uploads(auth_object=auth) + # Connect to the Quick Scan API + Scanner = FalconScan.Quick_Scan(auth_object=auth) + # Create our analysis object + Analyzer = Analysis() + # Log that startup is done + logger.info("Process startup complete, preparing to run scan") + # Upload our samples to the Sandbox + if Config.bucket: + # S3 bucket + upload_bucket_samples() + else: + # Local folder + upload_samples() + # Submit our volume for analysis and grab the id of our scan submission + scan_id = Scanner.ScanSamples(body=Analyzer.payload())["body"]["resources"][0] + # Inform the user of our progress + logger.info("Scan %s submitted for analysis", scan_id) + # Retrieve our scan results from the API and report them + report_results(scan_samples()) + # Clean up our uploaded files from out of the API + clean_up_artifacts() + # We're done, let everyone know + logger.info("Scan completed") + +# __ ____ ___ __ __ ___ _____ ______ ____ ____ __ _ ___ +# / ]| \ / \ | T__T T| \ / ___/| T| \ l j| l/ ] / _] +# / / | D )Y Y| | | || \( \_ | || D ) | T | ' / / [_ +# / / | / | O || | | || D Y\__ Tl_j l_j| / | | | \ Y _] +# / \_ | \ | |l ` ' !| |/ \ | | | | \ | | | Y| [_ +# \ || . Yl ! \ / | |\ | | | | . Y j l | . || T +# \____jl__j\_j \___/ \_/\_/ l_____j \___j l__j l__j\_j|____jl__j\_jl_____j +# +# ████ +# ████░░ ████▒▒████ +# ██▒▒▒▒████████▒▒▒▒▒▒████ +# ██▒▒▒▒▒▒▒▒████▒▒▒▒▒▒▒▒▒▒██ +# ██▒▒▒▒▒▒▒▒▒▒▒▒████▒▒▒▒▒▒▒▒▒▒██ +# ██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒▒▒██████ +# ██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▒▒▒▒▒▒▒▒▒▒████ +# ░░ ████▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▒▒▒▒▒▒▒▒██▒▒ +# ████ ██████▒▒▒▒▒▒▒▒▒▒▒▒▒▒██░░██▒▒▒▒██ +# ████▒▒████████████▒▒▒▒▒▒▒▒▒▒▓▓██░░██▓▓██ Yup! That's a file... +# ██░░▒▒██████ ░░████████▒▒▒▒▒▒▒▒██░░░░██ +# ▒▒██░░░░██▓▓ ██░░██████████▒▒▒▒▒▒▒▒██░░██ +# ██▒▒░░░░██▒▒░░ ████░░ ████▒▒▒▒▒▒██▒▒██ +# ████░░░░░░░░████▒▒░░██░░░░██░░░░██▒▒▒▒▒▒████ +# ██▒▒░░░░░░░░██▒▒░░░░██░░▒▒██████ ████▒▒▒▒██ +# ██░░░░░░░░░░▓▓██░░░░██░░ ██ ██▒▒██▓▓▒▒██ +# ████████▒▒░░░░░░░░██░░░░░░░░░░██ ████▒▒██▒▒██ +# ░░████▒▒░░░░▓▓██▓▓░░░░░░▓▓░░░░░░░░░░ ██ ░░░░██ ██▓▓▓▓ +# ▒▒████░░░░░░░░░░████░░░░░░░░▒▒░░░░░░░░░░░░████████▒▒ ████ ██████ +# ▒▒██░░░░░░░░░░░░░░░░████░░░░░░██░░░░░░░░░░░░░░ ░░░░██░░ ▒▒ ████▒▒██████ +# ████░░░░░░░░░░░░░░░░░░░░██░░░░░░██░░░░░░████████░░░░░░░░██ ██░░████████ ██ +# ████████░░░░░░░░░░░░░░░░░░░░░░░░██░░░░██ ░░██████████░░░░░░░░░░██ ██▒▒████░░░░ ██ +# ██░░████░░░░░░░░░░░░░░░░░░░░░░██████░░░░░░██░░ ████████░░░░░░░░░░██ ██████░░ ░░██ ██ +# ██░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░██▓▓░░░░██░░░░░░████████░░░░░░ ██ ░░██░░██░░ ██ ██ +# ████████ ██░░░░██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████░░██▒▒██████▒▒████████░░██ ▒▒██░░░░░░ ██ ██ +# ████░░░░░░████▒▒░░████░░░░░░░░░░░░░░░░▒▒░░░░░░░░░░░░▓▓██████ ██ ░░ ██ ░░██ ░░████░░░░██ +# ░░██░░░░░░░░░░██░░░░████░░░░░░░░░░░░░░██░░░░░░░░░░░░░░████ ██ ██░░ ▒▒▒▒░░░░░░██ +# ██████▒▒░░░░████░░██░░░░░░██░░░░░░░░██░░░░░░░░░░░░░░░░██ ██ ██▒▒ ░░████░░░░██ +# ████▒▒░░░░░░██████░░░░██░░░░░░████████░░░░░░░░░░░░░░░░██ ██ ████░░░░██████████ +# ████░░░░░░░░░░░░██░░░░██████░░░░░░░░░░████░░░░░░░░░░░░░░░░████ ██ ██░░░░██ ▒▒████ +# ██░░░░░░░░░░░░░░░░██░░░░░░████░░░░░░░░██▒▒░░░░░░░░░░░░░░▒▒████ ▒▒████████████░░████ +# ▒▒██░░░░░░░░░░░░░░██▓▓░░░░░░░░████████████░░░░░░░░░░░░░░░░██████ ▓▓▒▒██████ ▒▒██████ +# ████░░░░░░░░░░░░░░██▒▒░░░░░░████░░████▒▒██░░░░░░░░░░░░▓▓██░░██████▒▒██ ▒▒██████████ +# ████░░░░░░░░░░████████▒▒██░░░░▒▒██ ██▒▒██░░░░░░░░░░██░░ ██░░░░░░██████████████ +# ▒▒██░░░░░░░░░░░░░░██████░░░░██▒▒▒▒▒▒░░██░░░░░░░░██░░ ██░░░░░░▒▒████████ +# ▒▒████░░░░░░░░░░░░░░████████ ▒▒▒▒ ████░░░░██ ░░██░░░░▒▒████████ +# ████████▒▒░░░░░░░░░░░░▒▒████████████████████ ██▒▒░░░░░░████████ +# ██████████████████▒▒░░░░░░░░██ ████████░░░░░░░░░░░░░░██████ +# ████████████████████████▒▒██ ▒▒ ██▒▒▓▓░░░░░░░░ ░░░░████ +# ████████████████████████████ ██░░░░░░░░██▒▒ ██ +# ████████ ████████████████▒▒ ██ ░░░░░░░░██████ +# ██████████████████ ██████████████ ████░░░░██░░░░██ +# ██████████████████ ████████████ ██████░░░░██████ +# ██████████████████ ████████████ ████████████ +# ▓▓██████████████████▒▒ ░░████████████ ▓▓ +# ████████████████▒▒ ████████████▓▓ +# ░░░░████████████▒▒░░░░░░ ▒▒██████████████ +# ░░░░░░░░░░██████░░░░░░░░░░░░░░██████████████ +# ░░░░░░░░░░████████████░░░░░░░░██████████████ +# ░░░░░░░░░░████████████░░░░░░░░████████████████████ +# ░░░░░░░░░░░░▒▒░░░░░░░░░░░░░░░░████████████████████████ diff --git a/samples/real_time_response/quarantine_hosts.py b/samples/real_time_response/quarantine_hosts.py new file mode 100644 index 00000000..edebbf7b --- /dev/null +++ b/samples/real_time_response/quarantine_hosts.py @@ -0,0 +1,88 @@ +# ____ _ _____ _ ____ +# | _ \ ___ __ _| | |_ _(_)_ __ ___ ___ | _ \ ___ ___ _ __ ___ _ __ ___ ___ +# | |_) / _ \/ _` | | | | | | '_ ` _ \ / _ \ | |_) / _ \/ __| '_ \ / _ \| '_ \/ __|/ _ \ +# | _ < __/ (_| | | | | | | | | | | | __/ | _ < __/\__ \ |_) | (_) | | | \__ \ __/ +# |_| \_\___|\__,_|_| |_| |_|_| |_| |_|\___| |_| \_\___||___/ .__/ \___/|_| |_|___/\___| +# |_| +# +# This example demonstrates how to apply or lift containment on a host using its hostname. +# This solution makes use of Service Class legacy authentication. +# +import json +import argparse +# Import necessary FalconPy classes +from falconpy import oauth2 as FalconAuth +from falconpy import hosts as FalconHosts + +# Setup our argument parser +parser = argparse.ArgumentParser("Script that leverages Falcon API to (un)contain hosts") +parser.add_argument('-c', '--creds_file', dest='creds_file', help='Path to creds json file', required=True) +parser.add_argument('-H', '--hostname', dest='hostname', help='Hostname to quarantine', required=True) +parser.add_argument('-l', '--lift', dest='lift_containment', action="store_true", help='Lift containment', default=False) +# Parse our ingested arguments +args = parser.parse_args() +# Hostname of the machine to contain / release +hostname = args.hostname +# Default action is to quarantine +if args.lift_containment: + action = "lift_containment" +else: + action = "contain" +# Use the credentials file provided +creds_file = args.creds_file +# Load the contents of the creds file into the creds dictionary +with open(creds_file) as f: + creds = json.load(f) +# Create an instance of our OAuth2 authorization class using our ingested creds +authorization = FalconAuth.OAuth2(creds={ + "client_id": creds['falcon_client_id'], + "client_secret": creds['falcon_client_secret'] + }) +# Try to generate a token +try: + token = authorization.token()['body']['access_token'] +except Exception as e: + # Exit out on authentication errors + print("Failed to authenticate") + print(e) + exit(-1) +# If we have a token, proceed to the next step +if token: + # Create an instance of the Hosts class + falcon = FalconHosts.Hosts(access_token=token) + # Create our parameter payload, using our ingested hostname as a filter + PARAMS = { + 'offset': 0, + 'limit': 10, + 'filter': f"hostname:'{hostname}'" + } + # Query the Hosts API for hosts that match our filter pattern + response = falcon.QueryDevicesByFilter(parameters=PARAMS) + # Retrieve the list of IDs returned + contain_ids = response['body']['resources'] + # Output the result + print(json.dumps(response, indent=4)) + + if not contain_ids: + # No hosts were found, exit out + print(f"[-] Could not find hostname: {hostname} - Please verify proper case") + exit(-2) + + # Create our next payload based upon the action requested + PARAMS = { + 'action_name': action + } + # Our body payload will contain our list of IDs + BODY = { + 'ids': contain_ids + } + # Provide a status update to the terminal + if action == "contain": + print(f"\n[+] Containing: {hostname}\n") + else: + print(f"\n[+] Lifting Containment: {hostname}\n") + + # Perform the requested action + response = falcon.PerformActionV2(parameters=PARAMS, body=BODY) + # Output the result + print(json.dumps(response, indent=4)) diff --git a/samples/sample_uploads/sample_uploads_service.py b/samples/sample_uploads/sample_uploads_service.py new file mode 100644 index 00000000..134d38fe --- /dev/null +++ b/samples/sample_uploads/sample_uploads_service.py @@ -0,0 +1,48 @@ +# ____ _ _ _ _ _ +# / ___| __ _ _ __ ___ _ __ | | ___ | | | |_ __ | | ___ __ _ __| |___ +# \___ \ / _` | '_ ` _ \| '_ \| |/ _ \ | | | | '_ \| |/ _ \ / _` |/ _` / __| +# ___) | (_| | | | | | | |_) | | __/ | |_| | |_) | | (_) | (_| | (_| \__ \ +# |____/ \__,_|_| |_| |_| .__/|_|\___| \___/| .__/|_|\___/ \__,_|\__,_|___/ +# |_| |_| +# +# ____ _ ____ _ +# / ___| ___ _ ____ _(_) ___ ___ / ___| | __ _ ___ ___ +# \___ \ / _ \ '__\ \ / / |/ __/ _ \ | | | |/ _` / __/ __| +# ___) | __/ | \ V /| | (_| __/ | |___| | (_| \__ \__ \ +# |____/ \___|_| \_/ |_|\___\___| \____|_|\__,_|___/___/ +# +# +# These examples show how to interact with the Sample Uploads API using the Service Class +# This example uses Credential authentication and supports token refresh / authentication free usage. +# +import json +# Import the Sample Uploads service class +from falconpy import sample_uploads as FalconUploads + +# #Grab our config parameters +with open('config.json', 'r') as file_config: + config = json.loads(file_config.read()) + +falcon = FalconUploads.Sample_Uploads(creds={ + "client_id": config["falcon_client_id"], + "client_secret": config["falcon_client_secret"] + } +) + +# Define our file +FILENAME = "testfile.jpg" +# Open the file for binary read, this will be our payload +PAYLOAD = open(FILENAME, 'rb').read() +# Upload the file using the Sample Uploads API, name this file "newfile.jpg" in the API +# Since we are using the Service Class, we do not need to specify the content type +response = falcon.UploadSampleV3(file_name="newfile.jpg", file_data=PAYLOAD) +# Grab the SHA256 unique identifier for the file we just uploaded +sha = response["body"]["resources"][0]["sha256"] +# Download a copy of this file, use the SHA256 ID to retrieve it +response = falcon.GetSampleV3(ids=sha) +# Save the result to a new file +open('serviceclass.jpg', 'wb').write(response) +# Delete the file from the API +response = falcon.DeleteSampleV3(ids=sha) +# Print the results of our delete command +print(json.dumps(response, indent=4)) diff --git a/samples/sample_uploads/sample_uploads_uber.py b/samples/sample_uploads/sample_uploads_uber.py new file mode 100644 index 00000000..794c7008 --- /dev/null +++ b/samples/sample_uploads/sample_uploads_uber.py @@ -0,0 +1,47 @@ +# ____ _ _ _ _ _ +# / ___| __ _ _ __ ___ _ __ | | ___ | | | |_ __ | | ___ __ _ __| |___ +# \___ \ / _` | '_ ` _ \| '_ \| |/ _ \ | | | | '_ \| |/ _ \ / _` |/ _` / __| +# ___) | (_| | | | | | | |_) | | __/ | |_| | |_) | | (_) | (_| | (_| \__ \ +# |____/ \__,_|_| |_| |_| .__/|_|\___| \___/| .__/|_|\___/ \__,_|\__,_|___/ +# |_| |_| +# +# +# _ _ _ ____ _ +# | | | | |__ ___ _ __ / ___| | __ _ ___ ___ +# | | | | '_ \ / _ \ '__| | | | |/ _` / __/ __| +# | |_| | |_) | __/ | | |___| | (_| \__ \__ \ +# \___/|_.__/ \___|_| \____|_|\__,_|___/___/ +# +# These examples show how to interact with the Sample Uploads API using the Uber class. +# +import json +# Import the Uber Class +from falconpy import api_complete as FalconSDK + +# Grab our config parameters +with open('../config.json', 'r') as file_config: + config = json.loads(file_config.read()) + +# Create an instance of the Uber class +falcon = FalconSDK.APIHarness(creds={ + "client_id": config["falcon_client_id"], + "client_secret": config["falcon_client_secret"] + } +) + +# Define our file +FILENAME = "testfile.jpg" +# Open the file for binary read, this will be our payload +PAYLOAD = open(FILENAME, 'rb').read() +# Upload the file using the Sample Uploads API, name this file "newfile.jpg" in the API +response = falcon.command('UploadSampleV3', file_name="newfile.jpg", data=PAYLOAD, content_type="application/octet-stream") +# Grab the SHA256 unique identifier for the file we just uploaded +sha = response["body"]["resources"][0]["sha256"] +# Download a copy of this file, use the SHA256 ID to retrieve it +response = falcon.command("GetSampleV3", ids=sha) +# Save the result to a new file +open('uberclass.jpg', 'wb').write(response) +# Delete the file from the API +response = falcon.command("DeleteSampleV3", ids=sha) +# Print the results of our delete command +print(json.dumps(response, indent=4)) diff --git a/setup.py b/setup.py index 7b79b841..c4c68803 100644 --- a/setup.py +++ b/setup.py @@ -1,30 +1,98 @@ -import setuptools +""" + + .---. .----------- + / \ __ / ------ + / / \( )/ ----- + ////// ' \/ ` --- + //// / // : : --- CrowdStrike + // / / /` '-- FalconPy + // //..\\ + _.UU8888UU8lkoz.,_ + d888888888888888888888b, + j88P""V8888888888888888888 + 888 8888888888888888888 + 888baed8888888888888888888 + 88888888888888888888888888 + 8888888888888 + ,ad8888888888888888888888888888888888 888888be, + d8888888888888888888888888888888888888 888888888b, + d88888888888888888888888888888888888888 8888888888b, + j888888888888888888888888888888888888888 88888888888p, +j888888888888888888888888888888888888888' 8888888888888 +8888888888888888888888888888888888888^" ,8888888888888 +88888888888888^' .d88888888888888 +8888888888888" .a8888888888888888888888888888888888888 +8888888888888 ,888888888888888888888888888888888888888^ +^888888888888 888888888888888888888888888888888888888^ + V88888888888 88888888888888888888888888888888888888Y + V8888888888 8888888888888888888888888888888888888Y + `"^8888888 8888888888888888888888888888888888^"' + 8888888888888 + 88888888888888888888888888 + 8888888888888888888P""V888 + 8888888888888888888 888 + 8888888888888888888baed88V + `^888888888888888888888^ + `'"^^V888888888V^^' + +setup.py - PyPI packaging utility for CrowdStrike FalconPy +""" + +from setuptools import find_packages +from setuptools import setup +from glob import glob +from os.path import basename +from os.path import splitext +from src.falconpy import _version, _maintainer, _title, _description, _author, _author_email, _project_url with open("README.md", "r") as fh: long_description = fh.read() -setuptools.setup( - name="crowdstrike-falconpy", - version="0.1.7", - author="CrowdStrike", - maintainer="Joshua Hiller", - description="The CrowdStrike Falcon API SDK for Python 3", +# Remove GitHub's emoji +emojis = [":speech_balloon: ", ":bulb: ", ":pray: ", ":raised_hands: ", " :fire:", ":fire: "] +for emoji in emojis: + long_description = long_description.replace(emoji, "") + +setup( + name=_title, + version=_version, + author=_author, + author_email=_author_email, + maintainer=_maintainer, + description=_description, long_description=long_description, long_description_content_type="text/markdown", - url="https://github.com/CrowdStrike/falconpy", - packages=["falconpy"], - package_dir={'': 'falconpy'}, + url=_project_url, + packages=find_packages("src"), + package_dir={"": "src"}, + py_modules=[splitext(basename(path))[0] for path in glob("src/*.py")], + include_package_data=True, install_requires=[ - "requests", - "urllib3" + "requests", + "urllib3" ], + extras_require={ + "dev": [ + "flake8", + "coverage", + "pytest-cov", + "pytest", + "bandit", + ], + }, classifiers=[ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Operating System :: Unix", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", - "License :: Other/Proprietary License", + "License :: OSI Approved :: The Unlicense (Unlicense)", "Operating System :: OS Independent", ], python_requires='>=3.6', diff --git a/falconpy/services/README.MD b/src/falconpy/README.md similarity index 70% rename from falconpy/services/README.MD rename to src/falconpy/README.md index 2e1e7a74..456fe0d1 100644 --- a/falconpy/services/README.MD +++ b/src/falconpy/README.md @@ -1,8 +1,12 @@ -# falconpy - Falcon Complete API Service classes -These classes are part of the falconpy project, a python interface handler to the CrowdStrike Falcon Complete OAuth2 API. +![CrowdStrike Falcon](../../docs/asset/cs-logo.png) +# FalconPy - The CrowdStrike Falcon SDK for Python 3 +This folder contains the FalconPy project, a Python 3 interface handler for the CrowdStrike Falcon OAuth2 API. +## Service Classes ### Currently implemented: + `cloud_connect_aws.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws ++ `cspm-registration.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration ++ `custom_ioa.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa + `detects.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects + `device_control_policies.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/device-control-policies + `event_streams.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/event-streams @@ -16,22 +20,24 @@ These classes are part of the falconpy project, a python interface handler to th + `iocs.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs + `oauth2.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/oauth2 + `prevention_policy.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies ++ `quick_scan.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan + `real_time_response_admin.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin + `real_time_response.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response ++ `sample_uploads.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sample-uploads ++ `sensor_download.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-download + `sensor_update_policy.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies + `spotlight_vulnerabilities.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/spotlight-vulnerabilities + `user_management.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management ### Planned -+ `d4c-registration.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration -+ `cspm-registration.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration -+ `installation-tokens.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/installation-tokens -+ `custom-ioa.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa ++ `d4c_registration.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration ++ `installation_tokens.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/installation-tokens ++ `mssp.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/mssp + `malquery.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/malquery -+ `ioa-exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/ioa-exclusions -+ `ml-exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/ml-exclusions -+ `sensor-visibility-exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-visibility-exclusions -+ `sample-uploads.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sample-uploads -+ `quick-scan.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan -+ `sensor-download.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-download ++ `ioa_exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/ioa-exclusions ++ `ml_exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/ml-exclusions ++ `sensor_visibility_exclusions.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-visibility-exclusions +## The Uber Class +### A single class to interface with the entire API ++ `api_complete.py` https://assets.falcon.crowdstrike.com/support/api/swagger.html diff --git a/src/falconpy/__init__.py b/src/falconpy/__init__.py new file mode 100644 index 00000000..e06c4e1c --- /dev/null +++ b/src/falconpy/__init__.py @@ -0,0 +1,87 @@ +""" + @@@@@@@ @@@@@@@ @@@@@@ @@@ @@@ @@@ @@@@@@@ @@@@@@ @@@@@@@ @@@@@@@ @@@ @@@ @@@ @@@@@@@@ +@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@ @@@@@@@ @@@@@@@@ @@@ @@@ @@@ @@@@@@@@ +!@@ @@! @@@ @@! @@@ @@! @@! @@! @@! @@@ !@@ @@! @@! @@@ @@! @@! !@@ @@! +!@! !@! @!@ !@! @!@ !@! !@! !@! !@! @!@ !@! !@! !@! @!@ !@! !@! @!! !@! +!@! @!@!!@! @!@ !@! @!! !!@ @!@ @!@ !@! !!@@!! @!! @!@!!@! !!@ @!@@!@! @!!!:! +!!! !!@!@! !@! !!! !@! !!! !@! !@! !!! !!@!!! !!! !!@!@! !!! !!@!!! !!!!!: +:!! !!: :!! !!: !!! !!: !!: !!: !!: !!! !:! !!: !!: :!! !!: !!: :!! !!: +:!: :!: !:! :!: !:! :!: :!: :!: :!: !:! !:! :!: :!: !:! :!: :!: !:! :!: + ::: ::: :: ::: ::::: :: :::: :: ::: :::: :: :::: :: :: :: ::: :: :: ::: :: :::: + :: :: : : : : : : : :: : : : :: : : :: : : : : : : : : ::: : :: :: + + _______ __ _______ + | _ .---.-| .----.-----.-----| _ .--.--. + |. 1___| _ | | __| _ | |. 1 | | | + |. __) |___._|__|____|_____|__|__|. ____|___ | + |: | |: | |_____| + |::.| CrowdStrike Falcon |::.| + `---' OAuth2 API SDK for Python 3 `---' +""" +from ._version import _version, _maintainer, _author, _author_email, _credits, _description, _title, _project_url + +__version__ = _version +__maintainer__ = _maintainer +__author__ = _author +__author_email__ = _author_email +__credits__ = _credits +__description__ = _description +__title__ = _title +__project_url__ = _project_url + +""" +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + +⢻⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀ +⠀⠹⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠈⣿⣿⣶⡀⠀⠀⠀⠀⠀⠀⠈⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠙⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠹⣿⣶ +⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣶⣀⠀⠀⠀⠀⠀⠻⣿⣿⣤ +⠀⠀⠀⠹⣄⠀⠀⠀⠈⠻⣿⣿⣿⣶⡀⠀⠀⠀⠀⠙⢿⣿⣿⣤ +⠀⠀⠀⠀⠙⣿⣦⠀⠀⠀⠀⠙⢿⣿⣿⣿⣶⣀⠀⠀⠀⠈⠛⣿⣿⣿⣶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠛⣿⣷⣤⠀⠀⠀⠀⠙⢿⣿⣿⣿⣷⣤⠀⠀⠀⠈⠛⣿⣿⣿⣿⣶⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣷⣤⠀⠀⠀⠀⠉⠻⣿⣿⣿⣿⣦⡀⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣶⣤⣀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣶⡀⠀⠀⠀⠈⠙⢿⣿⣿⣿⣶⡀⠀⠀⠉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣿⣿⣷⣤⡀⠀⠀⠀⠉⠛⢿⣿⣿⣄⠀⠀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣤⡀⠀⠀⠀⠙⢿⣿⣦⠀⠀⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣶⣄⠀⠀⠀⠙⣿⡀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⣿⣷⣄⠀⠀⠙⡄⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣦⠀⠀⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣆⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠲⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣷⣤⣀⠀⠀⠀⠀⠛⢶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣶⣶⣶⣼⣿⣿⣷⣦⡀⠀⠀⠀⣀⠀⠀⠀⠉⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠈⢶⣤⠀⠀⠀⠉⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠿⣿⣿⣿⣦⠀⠀⠻⣿⣷⣶⣤⣀⣀⣀⠀⣀⣀⣀⣤⣤⣴⣶⣶⣶⣶⣶⣶⣮⣭⣉⠛⠿⣿⣿⣿⣿⣦⠙⣷⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠶⡀⠀⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣍⠻⣿⣿⣿⣷⡀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠿⠷⠌⠻⣿⣿⣦ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⣶⣀⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀WE STOP ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣶⣤⣤⣤⠀ +⠀⠀⠀⠀⠀BREACHES⠀⠀⠀⠀⠀⠀ ⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠛⠿⠛⠉⣿⣿⣿⠋⠀⠀⠀⠀⠀⢿⡇⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⢻⣿⣄⠀ ⠀⠀⠈⠈⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠈⠉⠀FalconPy +""" diff --git a/src/falconpy/_endpoint.py b/src/falconpy/_endpoint.py new file mode 100644 index 00000000..7e40b912 --- /dev/null +++ b/src/falconpy/_endpoint.py @@ -0,0 +1,2470 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +_endpoint - Internal API endpoint constant library + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" + +api_endpoints = [ + [ + "QueryAWSAccounts", + "GET", + "/cloud-connect-aws/combined/accounts/v1", + "Search for provisioned AWS Accounts by providing an FQL filter and paging details. " + "Returns a set of AWS accounts which match the filter criteria" + ], + [ + "GetAWSSettings", + "GET", + "/cloud-connect-aws/combined/settings/v1", + "Retrieve a set of Global Settings which are applicable to all provisioned AWS accounts" + ], + [ + "GetAWSAccounts", + "GET", + "/cloud-connect-aws/entities/accounts/v1?ids={}", + "Retrieve a set of AWS Accounts by specifying their IDs" + ], + [ + "ProvisionAWSAccounts", + "POST", + "/cloud-connect-aws/entities/accounts/v1", + "Provision AWS Accounts by specifying details about the accounts to provision" + ], + [ + "UpdateAWSAccounts", + "PATCH", + "/cloud-connect-aws/entities/accounts/v1", + "Update AWS Accounts by specifying the ID of the account and details to update" + ], + [ + "DeleteAWSAccounts", + "DELETE", + "/cloud-connect-aws/entities/accounts/v1?ids={}", + "Delete a set of AWS Accounts by specifying their IDs" + ], + [ + "CreateOrUpdateAWSSettings", + "POST", + "/cloud-connect-aws/entities/settings/v1", + "Create or update Global Settings which are applicable to all provisioned AWS accounts" + ], + [ + "VerifyAWSAccountAccess", + "POST", + "/cloud-connect-aws/entities/verify-account-access/v1?ids={}", + "Performs an Access Verification check on the specified AWS Account IDs" + ], + [ + "QueryAWSAccountsForIDs", + "GET", + "/cloud-connect-aws/queries/accounts/v1", + "Search for provisioned AWS Accounts by providing an FQL filter and paging details. " + "Returns a set of AWS account IDs which match the filter criteria" + ], + [ + "GetCSPMAzureAccount", + "GET", + "/cloud-connect-azure/entities/account/v1?ids={}", + "Return information about Azure account registration" + ], + [ + "CreateCSPMAzureAccount", + "POST", + "/cloud-connect-azure/entities/account/v1", + "Creates a new account in our system for a customer and generates a script for them to run in " + "their cloud environment to grant us access." + ], + [ + "UpdateCSPMAzureAccountClientID", + "PATCH", + "/cloud-connect-azure/entities/client-id/v1", + "Update an Azure service account in our system by with the user-created client_id created with " + "the public key we've provided" + ], + [ + "GetCSPMAzureUserScriptsAttachment", + "GET", + "/cloud-connect-azure/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their " + "Azure environment as a downloadable attachment" + ], + [ + "GetCSPMAzureUserScripts", + "GET", + "/cloud-connect-azure/entities/user-scripts/v1", + "Return a script for customer to run in their cloud environment to grant us access to their Azure environment" + ], + [ + "GetCSPMAwsAccount", + "GET", + "/cloud-connect-cspm-aws/entities/account/v1?ids={}", + "Returns information about the current status of an AWS account." + ], + [ + "CreateCSPMAwsAccount", + "POST", + "/cloud-connect-cspm-aws/entities/account/v1", + "Creates a new account in our system for a customer and generates a script for them to run in " + "their AWS cloud environment to grant us access." + ], + [ + "DeleteCSPMAwsAccount", + "DELETE", + "/cloud-connect-cspm-aws/entities/account/v1?ids={}", + "Deletes an existing AWS account or organization in our system." + ], + [ + "GetCSPMAwsConsoleSetupURLs", + "GET", + "/cloud-connect-cspm-aws/entities/console-setup-urls/v1", + "Return a URL for customer to visit in their cloud environment to grant us access to their AWS environment." + ], + [ + "GetCSPMAwsAccountScriptsAttachment", + "GET", + "/cloud-connect-cspm-aws/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their AWS " + "environment as a downloadable attachment." + ], + [ + "GetCSPMAzureAccount", + "GET", + "/cloud-connect-cspm-azure/entities/account/v1?ids={}", + "Return information about Azure account registration" + ], + [ + "CreateCSPMAzureAccount", + "POST", + "/cloud-connect-cspm-azure/entities/account/v1", + "Creates a new account in our system for a customer and generates a script for them to run in their " + "cloud environment to grant us access." + ], + [ + "DeleteCSPMAzureAccount", + "DELETE", + "/cloud-connect-cspm-azure/entities/account/v1?ids={}", + "Deletes an Azure subscription from the system." + ], + [ + "UpdateCSPMAzureAccountClientID", + "PATCH", + "/cloud-connect-cspm-azure/entities/client-id/v1", + "Update an Azure service account in our system by with the user-created client_id created with the " + "public key we've provided" + ], + [ + "GetCSPMAzureUserScriptsAttachment", + "GET", + "/cloud-connect-cspm-azure/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their Azure " + "environment as a downloadable attachment" + ], + [ + "GetCSPMCGPAccount", + "GET", + "/cloud-connect-gcp/entities/account/v1?ids={}", + "Returns information about the current status of an GCP account." + ], + [ + "CreateCSPMGCPAccount", + "POST", + "/cloud-connect-gcp/entities/account/v1", + "Creates a new account in our system for a customer and generates a new service account for them to add " + "access to in their GCP environment to grant us access." + ], + [ + "GetCSPMGCPUserScriptsAttachment", + "GET", + "/cloud-connect-gcp/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their GCP environment " + "as a downloadable attachment" + ], + [ + "GetCSPMGCPUserScripts", + "GET", + "/cloud-connect-gcp/entities/user-scripts/v1", + "Return a script for customer to run in their cloud environment to grant us access to their GCP environment" + ], + [ + "GetAggregateDetects", + "POST", + "/detects/aggregates/detects/GET/v1", + "Get detect aggregates as specified via json in request body." + ], + [ + "UpdateDetectsByIdsV2", + "PATCH", + "/detects/entities/detects/v2", + "Modify the state, assignee, and visibility of detections" + ], + [ + "GetDetectSummaries", + "POST", + "/detects/entities/summaries/GET/v1", + "View information about detections" + ], + [ + "QueryDetects", + "GET", + "/detects/queries/detects/v1", + "Search for detection IDs that match a given query" + ], + [ + "queryCombinedGroupMembers", + "GET", + "/devices/combined/host-group-members/v1", + "Search for members of a Host Group in your environment by providing an FQL filter and paging details. " + "Returns a set of host details which match the filter criteria" + ], + [ + "queryCombinedHostGroups", + "GET", + "/devices/combined/host-groups/v1", + "Search for Host Groups in your environment by providing an FQL filter and paging details. " + "Returns a set of Host Groups which match the filter criteria" + ], + [ + "PerformActionV2", + "POST", + "/devices/entities/devices-actions/v2", + "Take various actions on the hosts in your environment. Contain or lift containment on a host. Delete or restore a host." + ], + [ + "UpdateDeviceTags", + "PATCH", + "/devices/entities/devices/tags/v1", + "Append or remove one or more Falcon Grouping Tags on one or more hosts." + ], + [ + "GetDeviceDetails", + "GET", + "/devices/entities/devices/v1?ids={}", + "Get details on one or more hosts by providing agent IDs (AID). You can get a host's agent IDs (AIDs) " + "from the /devices/queries/devices/v1 endpoint, the Falcon console or the Streaming API" + ], + [ + "performGroupAction", + "POST", + "/devices/entities/host-group-actions/v1", + "Perform the specified action on the Host Groups specified in the request" + ], + [ + "getHostGroups", + "GET", + "/devices/entities/host-groups/v1?ids={}", + "Retrieve a set of Host Groups by specifying their IDs" + ], + [ + "createHostGroups", + "POST", + "/devices/entities/host-groups/v1", + "Create Host Groups by specifying details about the group to create" + ], + [ + "updateHostGroups", + "PATCH", + "/devices/entities/host-groups/v1", + "Update Host Groups by specifying the ID of the group and details to update" + ], + [ + "deleteHostGroups", + "DELETE", + "/devices/entities/host-groups/v1?ids={}", + "Delete a set of Host Groups by specifying their IDs" + ], + [ + "QueryHiddenDevices", + "GET", + "/devices/queries/devices-hidden/v1", + "Retrieve hidden hosts that match the provided filter criteria." + ], + [ + "QueryDevicesByFilterScroll", + "GET", + "/devices/queries/devices-scroll/v1", + "Search for hosts in your environment by platform, hostname, IP, and other criteria with continuous " + "pagination capability (based on offset pointer which expires after 2 minutes with no maximum limit)" + ], + [ + "QueryDevicesByFilter", + "GET", + "/devices/queries/devices/v1", + "Search for hosts in your environment by platform, hostname, IP, and other criteria." + ], + [ + "queryGroupMembers", + "GET", + "/devices/queries/host-group-members/v1", + "Search for members of a Host Group in your environment by providing an FQL filter and paging details. " + "Returns a set of Agent IDs which match the filter criteria" + ], + [ + "queryHostGroups", + "GET", + "/devices/queries/host-groups/v1", + "Search for Host Groups in your environment by providing an FQL filter and paging details. " + "Returns a set of Host Group IDs which match the filter criteria" + ], + [ + "AggregateAllowList", + "POST", + "/falcon-complete-dashboards/aggregates/allowlist/GET/v1", + "Retrieve aggregate allowlist ticket values based on the matched filter" + ], + [ + "AggregateBlockList", + "POST", + "/falcon-complete-dashboards/aggregates/blocklist/GET/v1", + "Retrieve aggregate blocklist ticket values based on the matched filter" + ], + [ + "AggregateDetections", + "POST", + "/falcon-complete-dashboards/aggregates/detects/GET/v1", + "Retrieve aggregate detection values based on the matched filter" + ], + [ + "AggregateDeviceCountCollection", + "POST", + "/falcon-complete-dashboards/aggregates/devicecount-collections/GET/v1", + "Retrieve aggregate host/devices count based on the matched filter" + ], + [ + "AggregateEscalations", + "POST", + "/falcon-complete-dashboards/aggregates/escalations/GET/v1", + "Retrieve aggregate escalation ticket values based on the matched filter" + ], + [ + "AggregateFCIncidents", + "POST", + "/falcon-complete-dashboards/aggregates/incidents/GET/v1", + "Retrieve aggregate incident values based on the matched filter" + ], + [ + "AggregateRemediations", + "POST", + "/falcon-complete-dashboards/aggregates/remediations/GET/v1", + "Retrieve aggregate remediation ticket values based on the matched filter" + ], + [ + "QueryAllowListFilter", + "GET", + "/falcon-complete-dashboards/queries/allowlist/v1", + "Retrieve allowlist tickets that match the provided filter criteria with scrolling enabled" + ], + [ + "QueryBlockListFilter", + "GET", + "/falcon-complete-dashboards/queries/blocklist/v1", + "Retrieve block listtickets that match the provided filter criteria with scrolling enabled" + ], + [ + "QueryDetectionIdsByFilter", + "GET", + "/falcon-complete-dashboards/queries/detects/v1", + "Retrieve DetectionsIds that match the provided FQL filter, criteria with scrolling enabled" + ], + [ + "GetDeviceCountCollectionQueriesByFilter", + "GET", + "/falcon-complete-dashboards/queries/devicecount-collections/v1", + "Retrieve device count collection Ids that match the provided FQL filter, criteria with scrolling enabled" + ], + [ + "QueryEscalationsFilter", + "GET", + "/falcon-complete-dashboards/queries/escalations/v1", + "Retrieve escalation tickets that match the provided filter criteria with scrolling enabled" + ], + [ + "QueryIncidentIdsByFilter", + "GET", + "/falcon-complete-dashboards/queries/incidents/v1", + "Retrieve incidents that match the provided filter criteria with scrolling enabled" + ], + [ + "QueryRemediationsFilter", + "GET", + "/falcon-complete-dashboards/queries/remediations/v1", + "Retrieve remediation tickets that match the provided filter criteria with scrolling enabled" + ], + [ + "GetArtifacts", + "GET", + "/falconx/entities/artifacts/v1", + "Download IOC packs, PCAP files, and other analysis artifacts." + ], + [ + "GetSummaryReports", + "GET", + "/falconx/entities/report-summaries/v1?ids={}", + "Get a short summary version of a sandbox report." + ], + [ + "GetReports", + "GET", + "/falconx/entities/reports/v1?ids={}", + "Get a full sandbox report." + ], + [ + "DeleteReport", + "DELETE", + "/falconx/entities/reports/v1?ids={}", + "Delete report based on the report ID. " + "Operation can be checked for success by polling for the report ID on the report-summaries endpoint." + ], + [ + "GetSubmissions", + "GET", + "/falconx/entities/submissions/v1?ids={}", + "Check the status of a sandbox analysis. Time required for analysis varies but is usually less than 15 minutes." + ], + [ + "Submit", + "POST", + "/falconx/entities/submissions/v1", + "Submit an uploaded file or a URL for sandbox analysis. " + "Time required for analysis varies but is usually less than 15 minutes." + ], + [ + "QueryReports", + "GET", + "/falconx/queries/reports/v1", + "Find sandbox reports by providing an FQL filter and paging details. Returns a set of report IDs that match your criteria." + ], + [ + "QuerySubmissions", + "GET", + "/falconx/queries/submissions/v1", + "Find submission IDs for uploaded files by providing an FQL filter and paging details. " + "Returns a set of submission IDs that match your criteria." + ], + [ + "aggregate_events", + "POST", + "/fwmgr/aggregates/events/GET/v1", + "Aggregate events for customer" + ], + [ + "aggregate_policy_rules", + "POST", + "/fwmgr/aggregates/policy-rules/GET/v1", + "Aggregate rules within a policy for customer" + ], + [ + "aggregate_rule_groups", + "POST", + "/fwmgr/aggregates/rule-groups/GET/v1", + "Aggregate rule groups for customer" + ], + [ + "aggregate_rules", + "POST", + "/fwmgr/aggregates/rules/GET/v1", + "Aggregate rules for customer" + ], + [ + "get_events", + "GET", + "/fwmgr/entities/events/v1?ids={}", + "Get events entities by ID and optionally version" + ], + [ + "get_firewall_fields", + "GET", + "/fwmgr/entities/firewall-fields/v1?ids={}", + "Get the firewall field specifications by ID" + ], + [ + "get_platforms", + "GET", + "/fwmgr/entities/platforms/v1?ids={}", + "Get platforms by ID, e.g., windows or mac or droid" + ], + [ + "get_policy_containers", + "GET", + "/fwmgr/entities/policies/v1?ids={}", + "Get policy container entities by policy ID" + ], + [ + "update_policy_container", + "PUT", + "/fwmgr/entities/policies/v1", + "Update an identified policy container" + ], + [ + "get_rule_groups", + "GET", + "/fwmgr/entities/rule-groups/v1?ids={}", + "Get rule group entities by ID. These groups do not contain their rule entites, just the rule IDs in precedence order." + ], + [ + "create_rule_group", + "POST", + "/fwmgr/entities/rule-groups/v1", + "Create new rule group on a platform for a customer with a name and description, and return the ID" + ], + [ + "update_rule_group", + "PATCH", + "/fwmgr/entities/rule-groups/v1", + "Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules" + ], + [ + "delete_rule_groups", + "DELETE", + "/fwmgr/entities/rule-groups/v1?ids={}", + "Delete rule group entities by ID" + ], + [ + "get_rules", + "GET", + "/fwmgr/entities/rules/v1?ids={}", + "Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string)" + ], + [ + "query_events", + "GET", + "/fwmgr/queries/events/v1", + "Find all event IDs matching the query with filter" + ], + [ + "query_firewall_fields", + "GET", + "/fwmgr/queries/firewall-fields/v1", + "Get the firewall field specification IDs for the provided platform" + ], + [ + "query_platforms", + "GET", + "/fwmgr/queries/platforms/v1", + "Get the list of platform names" + ], + [ + "query_policy_rules", + "GET", + "/fwmgr/queries/policy-rules/v1", + "Find all firewall rule IDs matching the query with filter, and return them in precedence order" + ], + [ + "query_rule_groups", + "GET", + "/fwmgr/queries/rule-groups/v1", + "Find all rule group IDs matching the query with filter" + ], + [ + "query_rules", + "GET", + "/fwmgr/queries/rules/v1", + "Find all rule IDs matching the query with filter" + ], + [ + "CrowdScore", + "GET", + "/incidents/combined/crowdscores/v1", + "Query environment wide CrowdScore and return the entity data" + ], + [ + "GetBehaviors", + "POST", + "/incidents/entities/behaviors/GET/v1", + "Get details on behaviors by providing behavior IDs" + ], + [ + "PerformIncidentAction", + "POST", + "/incidents/entities/incident-actions/v1", + "Perform a set of actions on one or more incidents, " + "such as adding tags or comments or updating the incident name or description" + ], + [ + "GetIncidents", + "POST", + "/incidents/entities/incidents/GET/v1", + "Get details on incidents by providing incident IDs" + ], + [ + "QueryBehaviors", + "GET", + "/incidents/queries/behaviors/v1", + "Search for behaviors by providing an FQL filter, sorting, and paging details" + ], + [ + "QueryIncidents", + "GET", + "/incidents/queries/incidents/v1", + "Search for incidents by providing an FQL filter, sorting, and paging details" + ], + [ + "DevicesCount", + "GET", + "/indicators/aggregates/devices-count/v1", + "Number of hosts in your customer account that have observed a given custom IOC" + ], + [ + "GetIOC", + "GET", + "/indicators/entities/iocs/v1", + "Get an IOC by providing a type and value" + ], + [ + "CreateIOC", + "POST", + "/indicators/entities/iocs/v1", + "Create a new IOC" + ], + [ + "UpdateIOC", + "PATCH", + "/indicators/entities/iocs/v1", + "Update an IOC by providing a type and value" + ], + [ + "DeleteIOC", + "DELETE", + "/indicators/entities/iocs/v1", + "Delete an IOC by providing a type and value" + ], + [ + "DevicesRanOn", + "GET", + "/indicators/queries/devices/v1", + "Find hosts that have observed a given custom IOC. For details about those hosts, use GET /devices/entities/devices/v1" + ], + [ + "QueryIOCs", + "GET", + "/indicators/queries/iocs/v1", + "Search the custom IOCs in your customer account" + ], + [ + "ProcessesRanOn", + "GET", + "/indicators/queries/processes/v1", + "Search for processes associated with a custom IOC" + ], + [ + "audit_events_read", + "GET", + "/installation-tokens/entities/audit-events/v1?ids={}", + "Gets the details of one or more audit events by id." + ], + [ + "customer_settings_read", + "GET", + "/installation-tokens/entities/customer-settings/v1", + "Check current installation token settings." + ], + [ + "tokens_read", + "GET", + "/installation-tokens/entities/tokens/v1?ids={}", + "Gets the details of one or more tokens by id." + ], + [ + "tokens_create", + "POST", + "/installation-tokens/entities/tokens/v1", + "Creates a token." + ], + [ + "tokens_update", + "PATCH", + "/installation-tokens/entities/tokens/v1?ids={}", + "Updates one or more tokens. Use this endpoint to edit labels, change expiration, revoke, or restore." + ], + [ + "tokens_delete", + "DELETE", + "/installation-tokens/entities/tokens/v1?ids={}", + "Deletes a token immediately. To revoke a token, use PATCH /installation-tokens/entities/tokens/v1 instead." + ], + [ + "audit_events_query", + "GET", + "/installation-tokens/queries/audit-events/v1", + "Search for audit events by providing an FQL filter and paging details." + ], + [ + "tokens_query", + "GET", + "/installation-tokens/queries/tokens/v1", + "Search for tokens by providing an FQL filter and paging details." + ], + [ + "QueryIntelActorEntities", + "GET", + "/intel/combined/actors/v1", + "Get info about actors that match provided FQL filters." + ], + [ + "QueryIntelIndicatorEntities", + "GET", + "/intel/combined/indicators/v1", + "Get info about indicators that match provided FQL filters." + ], + [ + "QueryIntelReportEntities", + "GET", + "/intel/combined/reports/v1", + "Get info about reports that match provided FQL filters." + ], + [ + "GetIntelActorEntities", + "GET", + "/intel/entities/actors/v1?ids={}", + "Retrieve specific actors using their actor IDs." + ], + [ + "GetIntelIndicatorEntities", + "POST", + "/intel/entities/indicators/GET/v1", + "Retrieve specific indicators using their indicator IDs." + ], + [ + "GetIntelReportPDF", + "GET", + "/intel/entities/report-files/v1", + "Return a Report PDF attachment" + ], + [ + "GetIntelReportEntities", + "GET", + "/intel/entities/reports/v1?ids={}", + "Retrieve specific reports using their report IDs." + ], + [ + "GetIntelRuleFile", + "GET", + "/intel/entities/rules-files/v1", + "Download earlier rule sets." + ], + [ + "GetLatestIntelRuleFile", + "GET", + "/intel/entities/rules-latest-files/v1", + "Download the latest rule set." + ], + [ + "GetIntelRuleEntities", + "GET", + "/intel/entities/rules/v1?ids={}", + "Retrieve details for rule sets for the specified ids." + ], + [ + "QueryIntelActorIds", + "GET", + "/intel/queries/actors/v1", + "Get actor IDs that match provided FQL filters." + ], + [ + "QueryIntelIndicatorIds", + "GET", + "/intel/queries/indicators/v1", + "Get indicators IDs that match provided FQL filters." + ], + [ + "QueryIntelReportIds", + "GET", + "/intel/queries/reports/v1", + "Get report IDs that match provided FQL filters." + ], + [ + "QueryIntelRuleIds", + "GET", + "/intel/queries/rules/v1", + "Search for rule IDs that match provided filter criteria." + ], + [ + "get_patterns", + "GET", + "/ioarules/entities/pattern-severities/v1?ids={}", + "Get pattern severities by ID." + ], + [ + "get_platformsMixin0", + "GET", + "/ioarules/entities/platforms/v1?ids={}", + "Get platforms by ID." + ], + [ + "get_rule_groupsMixin0", + "GET", + "/ioarules/entities/rule-groups/v1?ids={}", + "Get rule groups by ID." + ], + [ + "create_rule_groupMixin0", + "POST", + "/ioarules/entities/rule-groups/v1", + "Create a rule group for a platform with a name and an optional description. Returns the rule group." + ], + [ + "update_rule_groupMixin0", + "PATCH", + "/ioarules/entities/rule-groups/v1", + "Update a rule group. The following properties can be modified: name, description, enabled." + ], + [ + "delete_rule_groupsMixin0", + "DELETE", + "/ioarules/entities/rule-groups/v1?ids={}", + "Delete rule groups by ID." + ], + [ + "get_rule_types", + "GET", + "/ioarules/entities/rule-types/v1?ids={}", + "Get rule types by ID." + ], + [ + "get_rules_get", + "POST", + "/ioarules/entities/rules/GET/v1", + "Get rules by ID and optionally version in the following format: `ID[:version]`." + ], + [ + "get_rulesMixin0", + "GET", + "/ioarules/entities/rules/v1?ids={}", + "Get rules by ID and optionally version in the following format: `ID[:version]`. " + "The max number of IDs is constrained by URL size." + ], + [ + "create_rule", + "POST", + "/ioarules/entities/rules/v1", + "Create a rule within a rule group. Returns the rule." + ], + [ + "update_rules", + "PATCH", + "/ioarules/entities/rules/v1", + "Update rules within a rule group. Return the updated rules." + ], + [ + "delete_rules", + "DELETE", + "/ioarules/entities/rules/v1?ids={}", + "Delete rules from a rule group by ID." + ], + [ + "validate", + "POST", + "/ioarules/entities/rules/validate/v1", + "Validates field values and checks for matches if a test string is provided." + ], + [ + "query_patterns", + "GET", + "/ioarules/queries/pattern-severities/v1", + "Get all pattern severity IDs." + ], + [ + "query_platformsMixin0", + "GET", + "/ioarules/queries/platforms/v1", + "Get all platform IDs." + ], + [ + "query_rule_groups_full", + "GET", + "/ioarules/queries/rule-groups-full/v1", + "Find all rule groups matching the query with optional filter." + ], + [ + "query_rule_groupsMixin0", + "GET", + "/ioarules/queries/rule-groups/v1", + "Finds all rule group IDs matching the query with optional filter." + ], + [ + "query_rule_types", + "GET", + "/ioarules/queries/rule-types/v1", + "Get all rule type IDs." + ], + [ + "query_rulesMixin0", + "GET", + "/ioarules/queries/rules/v1", + "Finds all rule IDs matching the query with optional filter." + ], + [ + "GetMalQueryQuotasV1", + "GET", + "/malquery/aggregates/quotas/v1", + "Get information about search and download quotas in your environment" + ], + [ + "PostMalQueryFuzzySearchV1", + "POST", + "/malquery/combined/fuzzy-search/v1", + "Search Falcon MalQuery quickly, but with more potential for false positives. " + "Search for a combination of hex patterns and strings in order to identify samples " + "based upon file content at byte level granularity." + ], + [ + "GetMalQueryDownloadV1", + "GET", + "/malquery/entities/download-files/v1?ids={}", + "Download a file indexed by MalQuery. Specify the file using its SHA256. Only one file is supported at this time" + ], + [ + "GetMalQueryMetadataV1", + "GET", + "/malquery/entities/metadata/v1?ids={}", + "Retrieve indexed files metadata by their hash" + ], + [ + "GetMalQueryRequestV1", + "GET", + "/malquery/entities/requests/v1?ids={}", + "Check the status and results of an asynchronous request, such as hunt or exact-search. " + "Supports a single request id at this time." + ], + [ + "GetMalQueryEntitiesSamplesFetchV1", + "GET", + "/malquery/entities/samples-fetch/v1?ids={}", + "Fetch a zip archive with password 'infected' containing the samples. " + "Call this once the /entities/samples-multidownload request has finished processing" + ], + [ + "PostMalQueryEntitiesSamplesMultidownloadV1", + "POST", + "/malquery/entities/samples-multidownload/v1", + "Schedule samples for download. Use the result id with the /request endpoint to check if the " + "download is ready after which you can call the /entities/samples-fetch to get the zip" + ], + [ + "PostMalQueryExactSearchV1", + "POST", + "/malquery/queries/exact-search/v1", + "Search Falcon MalQuery for a combination of hex patterns and strings in order to identify samples " + "based upon file content at byte level granularity. You can filter results on criteria such as file type, " + "file size and first seen date. Returns a request id which can be used with the /request endpoint" + ], + [ + "PostMalQueryHuntV1", + "POST", + "/malquery/queries/hunt/v1", + "Schedule a YARA-based search for execution. Returns a request id which can be used with the /request endpoint" + ], + [ + "getChildren", + "GET", + "/mssp/entities/children/v1?ids={}", + "Get link to child customer by child CID(s)" + ], + [ + "getCIDGroupMembersBy", + "GET", + "/mssp/entities/cid-group-members/v1", + "Get CID Group members by CID Group IDs." + ], + [ + "addCIDGroupMembers", + "POST", + "/mssp/entities/cid-group-members/v1", + "Add new CID Group member." + ], + [ + "deleteCIDGroupMembers", + "DELETE", + "/mssp/entities/cid-group-members/v1", + "Delete CID Group members entry." + ], + [ + "getCIDGroupById", + "GET", + "/mssp/entities/cid-groups/v1", + "Get CID Group(s) by ID(s)." + ], + [ + "createCIDGroups", + "POST", + "/mssp/entities/cid-groups/v1", + "Create new CID Group(s). Maximum 500 CID Group(s) allowed." + ], + [ + "updateCIDGroups", + "PATCH", + "/mssp/entities/cid-groups/v1", + "Update existing CID Group(s). CID Group ID is expected for each CID Group definition provided in request body. " + "CID Group member(s) remain unaffected." + ], + [ + "deleteCIDGroups", + "DELETE", + "/mssp/entities/cid-groups/v1", + "Delete CID Group(s) by ID(s)." + ], + [ + "getRolesByID", + "GET", + "/mssp/entities/mssp-roles/v1?ids={}", + "Get MSSP Role assignment(s). MSSP Role assignment is of the format :." + ], + [ + "addRole", + "POST", + "/mssp/entities/mssp-roles/v1", + "Assign new MSSP Role(s) between User Group and CID Group. " + "It does not revoke existing role(s) between User Group and CID Group. " + "User Group ID and CID Group ID have to be specified in request. " + ], + [ + "deletedRoles", + "DELETE", + "/mssp/entities/mssp-roles/v1", + "Delete MSSP Role assignment(s) between User Group and CID Group. " + "User Group ID and CID Group ID have to be specified in request. " + "Only specified roles are removed if specified in request payload, " + "else association between User Group and CID Group is dissolved completely (if no roles specified)." + ], + [ + "getUserGroupMembersByID", + "GET", + "/mssp/entities/user-group-members/v1", + "Get User Group members by User Group ID(s)." + ], + [ + "addUserGroupMembers", + "POST", + "/mssp/entities/user-group-members/v1", + "Add new User Group member. Maximum 500 members allowed per User Group." + ], + [ + "deleteUserGroupMembers", + "DELETE", + "/mssp/entities/user-group-members/v1", + "Delete User Group members entry." + ], + [ + "getUserGroupsByID", + "GET", + "/mssp/entities/user-groups/v1", + "Get User Group by ID(s)." + ], + [ + "createUserGroups", + "POST", + "/mssp/entities/user-groups/v1", + "Create new User Group(s). Maximum 500 User Group(s) allowed per customer." + ], + [ + "updateUserGroups", + "PATCH", + "/mssp/entities/user-groups/v1", + "Update existing User Group(s). User Group ID is expected for each User Group definition " + "provided in request body. User Group member(s) remain unaffected." + ], + [ + "deleteUserGroups", + "DELETE", + "/mssp/entities/user-groups/v1", + "Delete User Group(s) by ID(s)." + ], + [ + "queryChildren", + "GET", + "/mssp/queries/children/v1", + "Query for customers linked as children" + ], + [ + "queryCIDGroupMembers", + "GET", + "/mssp/queries/cid-group-members/v1", + "Query a CID Groups members by associated CID." + ], + [ + "queryCIDGroups", + "GET", + "/mssp/queries/cid-groups/v1", + "Query CID Groups." + ], + [ + "queryRoles", + "GET", + "/mssp/queries/mssp-roles/v1", + "Query MSSP Role assignment. At least one of CID Group ID or User Group ID should also be provided. Role ID is optional." + ], + [ + "queryUserGroupMembers", + "GET", + "/mssp/queries/user-group-members/v1", + "Query User Group member by User UUID." + ], + [ + "queryUserGroups", + "GET", + "/mssp/queries/user-groups/v1", + "Query User Groups." + ], + [ + "oauth2RevokeToken", + "POST", + "/oauth2/revoke", + "Revoke a previously issued OAuth2 access token before the end of its standard 30-minute lifespan." + ], + [ + "oauth2AccessToken", + "POST", + "/oauth2/token", + "Generate an OAuth2 access token" + ], + [ + "AggregatesDetectionsGlobalCounts", + "GET", + "/overwatch-dashboards/aggregates/detections-global-counts/v1", + "Get the total number of detections pushed across all customers" + ], + [ + "AggregatesEventsCollections", + "POST", + "/overwatch-dashboards/aggregates/events-collections/GET/v1", + "Get OverWatch detection event collection info by providing an aggregate query" + ], + [ + "AggregatesEvents", + "POST", + "/overwatch-dashboards/aggregates/events/GET/v1", + "Get aggregate OverWatch detection event info by providing an aggregate query" + ], + [ + "AggregatesIncidentsGlobalCounts", + "GET", + "/overwatch-dashboards/aggregates/incidents-global-counts/v1", + "Get the total number of incidents pushed across all customers" + ], + [ + "AggregatesOWEventsGlobalCounts", + "GET", + "/overwatch-dashboards/aggregates/ow-events-global-counts/v1", + "Get the total number of OverWatch events across all customers" + ], + [ + "queryCombinedDeviceControlPolicyMembers", + "GET", + "/policy/combined/device-control-members/v1", + "Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of host details which match the filter criteria" + ], + [ + "queryCombinedDeviceControlPolicies", + "GET", + "/policy/combined/device-control/v1", + "Search for Device Control Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Device Control Policies which match the filter criteria" + ], + [ + "queryCombinedFirewallPolicyMembers", + "GET", + "/policy/combined/firewall-members/v1", + "Search for members of a Firewall Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of host details which match the filter criteria" + ], + [ + "queryCombinedFirewallPolicies", + "GET", + "/policy/combined/firewall/v1", + "Search for Firewall Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Firewall Policies which match the filter criteria" + ], + [ + "queryCombinedPreventionPolicyMembers", + "GET", + "/policy/combined/prevention-members/v1", + "Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of host details which match the filter criteria" + ], + [ + "queryCombinedPreventionPolicies", + "GET", + "/policy/combined/prevention/v1", + "Search for Prevention Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Prevention Policies which match the filter criteria" + ], + [ + "revealUninstallToken", + "POST", + "/policy/combined/reveal-uninstall-token/v1", + "Reveals an uninstall token for a specific device. To retrieve the bulk maintenance token pass " + "the value 'MAINTENANCE' as the value for 'device_id'" + ], + [ + "queryCombinedSensorUpdateBuilds", + "GET", + "/policy/combined/sensor-update-builds/v1", + "Retrieve available builds for use with Sensor Update Policies" + ], + [ + "queryCombinedSensorUpdatePolicyMembers", + "GET", + "/policy/combined/sensor-update-members/v1", + "Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of host details which match the filter criteria" + ], + [ + "queryCombinedSensorUpdatePolicies", + "GET", + "/policy/combined/sensor-update/v1", + "Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Sensor Update Policies which match the filter criteria" + ], + [ + "queryCombinedSensorUpdatePoliciesV2", + "GET", + "/policy/combined/sensor-update/v2", + "Search for Sensor Update Policies with additional support for uninstall protection in your environment by " + "providing an FQL filter and paging details. Returns a set of Sensor Update Policies which match the filter criteria" + ], + [ + "performDeviceControlPoliciesAction", + "POST", + "/policy/entities/device-control-actions/v1", + "Perform the specified action on the Device Control Policies specified in the request" + ], + [ + "setDeviceControlPoliciesPrecedence", + "POST", + "/policy/entities/device-control-precedence/v1", + "Sets the precedence of Device Control Policies based on the order of IDs specified in the request. " + "The first ID specified will have the highest precedence and the last ID specified will have the lowest. " + "You must specify all non-Default Policies for a platform when updating precedence" + ], + [ + "getDeviceControlPolicies", + "GET", + "/policy/entities/device-control/v1?ids={}", + "Retrieve a set of Device Control Policies by specifying their IDs" + ], + [ + "createDeviceControlPolicies", + "POST", + "/policy/entities/device-control/v1", + "Create Device Control Policies by specifying details about the policy to create" + ], + [ + "updateDeviceControlPolicies", + "PATCH", + "/policy/entities/device-control/v1", + "Update Device Control Policies by specifying the ID of the policy and details to update" + ], + [ + "deleteDeviceControlPolicies", + "DELETE", + "/policy/entities/device-control/v1?ids={}", + "Delete a set of Device Control Policies by specifying their IDs" + ], + [ + "performFirewallPoliciesAction", + "POST", + "/policy/entities/firewall-actions/v1", + "Perform the specified action on the Firewall Policies specified in the request" + ], + [ + "setFirewallPoliciesPrecedence", + "POST", + "/policy/entities/firewall-precedence/v1", + "Sets the precedence of Firewall Policies based on the order of IDs specified in the request. " + "The first ID specified will have the highest precedence and the last ID specified will have the lowest. " + "You must specify all non-Default Policies for a platform when updating precedence" + ], + [ + "getFirewallPolicies", + "GET", + "/policy/entities/firewall/v1?ids={}", + "Retrieve a set of Firewall Policies by specifying their IDs" + ], + [ + "createFirewallPolicies", + "POST", + "/policy/entities/firewall/v1", + "Create Firewall Policies by specifying details about the policy to create" + ], + [ + "updateFirewallPolicies", + "PATCH", + "/policy/entities/firewall/v1", + "Update Firewall Policies by specifying the ID of the policy and details to update" + ], + [ + "deleteFirewallPolicies", + "DELETE", + "/policy/entities/firewall/v1?ids={}", + "Delete a set of Firewall Policies by specifying their IDs" + ], + [ + "getIOAExclusionsV1", + "GET", + "/policy/entities/ioa-exclusions/v1?ids={}", + "Get a set of IOA Exclusions by specifying their IDs" + ], + [ + "createIOAExclusionsV1", + "POST", + "/policy/entities/ioa-exclusions/v1", + "Create the IOA exclusions" + ], + [ + "updateIOAExclusionsV1", + "PATCH", + "/policy/entities/ioa-exclusions/v1", + "Update the IOA exclusions" + ], + [ + "deleteIOAExclusionsV1", + "DELETE", + "/policy/entities/ioa-exclusions/v1?ids={}", + "Delete the IOA exclusions by id" + ], + [ + "getMLExclusionsV1", + "GET", + "/policy/entities/ml-exclusions/v1?ids={}", + "Get a set of ML Exclusions by specifying their IDs" + ], + [ + "createMLExclusionsV1", + "POST", + "/policy/entities/ml-exclusions/v1", + "Create the ML exclusions" + ], + [ + "updateMLExclusionsV1", + "PATCH", + "/policy/entities/ml-exclusions/v1", + "Update the ML exclusions" + ], + [ + "deleteMLExclusionsV1", + "DELETE", + "/policy/entities/ml-exclusions/v1?ids={}", + "Delete the ML exclusions by id" + ], + [ + "performPreventionPoliciesAction", + "POST", + "/policy/entities/prevention-actions/v1", + "Perform the specified action on the Prevention Policies specified in the request" + ], + [ + "setPreventionPoliciesPrecedence", + "POST", + "/policy/entities/prevention-precedence/v1", + "Sets the precedence of Prevention Policies based on the order of IDs specified in the request. " + "The first ID specified will have the highest precedence and the last ID specified will have the lowest. " + "You must specify all non-Default Policies for a platform when updating precedence" + ], + [ + "getPreventionPolicies", + "GET", + "/policy/entities/prevention/v1?ids={}", + "Retrieve a set of Prevention Policies by specifying their IDs" + ], + [ + "createPreventionPolicies", + "POST", + "/policy/entities/prevention/v1", + "Create Prevention Policies by specifying details about the policy to create" + ], + [ + "updatePreventionPolicies", + "PATCH", + "/policy/entities/prevention/v1", + "Update Prevention Policies by specifying the ID of the policy and details to update" + ], + [ + "deletePreventionPolicies", + "DELETE", + "/policy/entities/prevention/v1?ids={}", + "Delete a set of Prevention Policies by specifying their IDs" + ], + [ + "performSensorUpdatePoliciesAction", + "POST", + "/policy/entities/sensor-update-actions/v1", + "Perform the specified action on the Sensor Update Policies specified in the request" + ], + [ + "setSensorUpdatePoliciesPrecedence", + "POST", + "/policy/entities/sensor-update-precedence/v1", + "Sets the precedence of Sensor Update Policies based on the order of IDs specified in the request. " + "The first ID specified will have the highest precedence and the last ID specified will have the lowest. " + "You must specify all non-Default Policies for a platform when updating precedence" + ], + [ + "getSensorUpdatePolicies", + "GET", + "/policy/entities/sensor-update/v1?ids={}", + "Retrieve a set of Sensor Update Policies by specifying their IDs" + ], + [ + "createSensorUpdatePolicies", + "POST", + "/policy/entities/sensor-update/v1", + "Create Sensor Update Policies by specifying details about the policy to create" + ], + [ + "updateSensorUpdatePolicies", + "PATCH", + "/policy/entities/sensor-update/v1", + "Update Sensor Update Policies by specifying the ID of the policy and details to update" + ], + [ + "deleteSensorUpdatePolicies", + "DELETE", + "/policy/entities/sensor-update/v1?ids={}", + "Delete a set of Sensor Update Policies by specifying their IDs" + ], + [ + "getSensorUpdatePoliciesV2", + "GET", + "/policy/entities/sensor-update/v2?ids={}", + "Retrieve a set of Sensor Update Policies with additional support for uninstall " + "protection by specifying their IDs" + ], + [ + "createSensorUpdatePoliciesV2", + "POST", + "/policy/entities/sensor-update/v2", + "Create Sensor Update Policies by specifying details about the policy to create " + "with additional support for uninstall protection" + ], + [ + "updateSensorUpdatePoliciesV2", + "PATCH", + "/policy/entities/sensor-update/v2", + "Update Sensor Update Policies by specifying the ID of the policy and details to " + "update with additional support for uninstall protection" + ], + [ + "getSensorVisibilityExclusionsV1", + "GET", + "/policy/entities/sv-exclusions/v1?ids={}", + "Get a set of Sensor Visibility Exclusions by specifying their IDs" + ], + [ + "createSVExclusionsV1", + "POST", + "/policy/entities/sv-exclusions/v1", + "Create the sensor visibility exclusions" + ], + [ + "updateSensorVisibilityExclusionsV1", + "PATCH", + "/policy/entities/sv-exclusions/v1", + "Update the sensor visibility exclusions" + ], + [ + "deleteSensorVisibilityExclusionsV1", + "DELETE", + "/policy/entities/sv-exclusions/v1?ids={}", + "Delete the sensor visibility exclusions by id" + ], + [ + "queryDeviceControlPolicyMembers", + "GET", + "/policy/queries/device-control-members/v1", + "Search for members of a Device Control Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of Agent IDs which match the filter criteria" + ], + [ + "queryDeviceControlPolicies", + "GET", + "/policy/queries/device-control/v1", + "Search for Device Control Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Device Control Policy IDs which match the filter criteria" + ], + [ + "queryFirewallPolicyMembers", + "GET", + "/policy/queries/firewall-members/v1", + "Search for members of a Firewall Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of Agent IDs which match the filter criteria" + ], + [ + "queryFirewallPolicies", + "GET", + "/policy/queries/firewall/v1", + "Search for Firewall Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Firewall Policy IDs which match the filter criteria" + ], + [ + "queryIOAExclusionsV1", + "GET", + "/policy/queries/ioa-exclusions/v1", + "Search for IOA exclusions." + ], + [ + "queryMLExclusionsV1", + "GET", + "/policy/queries/ml-exclusions/v1", + "Search for ML exclusions." + ], + [ + "queryPreventionPolicyMembers", + "GET", + "/policy/queries/prevention-members/v1", + "Search for members of a Prevention Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of Agent IDs which match the filter criteria" + ], + [ + "queryPreventionPolicies", + "GET", + "/policy/queries/prevention/v1", + "Search for Prevention Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Prevention Policy IDs which match the filter criteria" + ], + [ + "querySensorUpdatePolicyMembers", + "GET", + "/policy/queries/sensor-update-members/v1", + "Search for members of a Sensor Update Policy in your environment by providing an FQL filter and paging details. " + "Returns a set of Agent IDs which match the filter criteria" + ], + [ + "querySensorUpdatePolicies", + "GET", + "/policy/queries/sensor-update/v1", + "Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. " + "Returns a set of Sensor Update Policy IDs which match the filter criteria" + ], + [ + "querySensorVisibilityExclusionsV1", + "GET", + "/policy/queries/sv-exclusions/v1", + "Search for sensor visibility exclusions." + ], + [ + "entities_processes", + "GET", + "/processes/entities/processes/v1?ids={}", + "For the provided ProcessID retrieve the process details" + ], + [ + "RTR_AggregateSessions", + "POST", + "/real-time-response/aggregates/sessions/GET/v1", + "Get aggregates on session data." + ], + [ + "BatchActiveResponderCmd", + "POST", + "/real-time-response/combined/batch-active-responder-command/v1", + "Batch executes a RTR active-responder command across the hosts mapped to the given batch ID." + ], + [ + "BatchAdminCmd", + "POST", + "/real-time-response/combined/batch-admin-command/v1", + "Batch executes a RTR administrator command across the hosts mapped to the given batch ID." + ], + [ + "BatchCmd", + "POST", + "/real-time-response/combined/batch-command/v1", + "Batch executes a RTR read-only command across the hosts mapped to the given batch ID." + ], + [ + "BatchGetCmdStatus", + "GET", + "/real-time-response/combined/batch-get-command/v1", + "Retrieves the status of the specified batch get command. Will return successful files when they are finished processing." + ], + [ + "BatchGetCmd", + "POST", + "/real-time-response/combined/batch-get-command/v1", + "Batch executes `get` command across hosts to retrieve files. " + "After this call is made `GET /real-time-response/combined/batch-get-command/v1` is used to query for the results." + ], + [ + "BatchInitSessions", + "POST", + "/real-time-response/combined/batch-init-session/v1", + "Batch initialize a RTR session on multiple hosts. " + "Before any RTR commands can be used, an active session is needed on the host." + ], + [ + "BatchRefreshSessions", + "POST", + "/real-time-response/combined/batch-refresh-session/v1", + "Batch refresh a RTR session on multiple hosts. RTR sessions will expire after 10 minutes unless refreshed." + ], + [ + "RTR_CheckActiveResponderCommandStatus", + "GET", + "/real-time-response/entities/active-responder-command/v1", + "Get status of an executed active-responder command on a single host." + ], + [ + "RTR_ExecuteActiveResponderCommand", + "POST", + "/real-time-response/entities/active-responder-command/v1", + "Execute an active responder command on a single host." + ], + [ + "RTR_CheckAdminCommandStatus", + "GET", + "/real-time-response/entities/admin-command/v1", + "Get status of an executed RTR administrator command on a single host." + ], + [ + "RTR_ExecuteAdminCommand", + "POST", + "/real-time-response/entities/admin-command/v1", + "Execute a RTR administrator command on a single host." + ], + [ + "RTR_CheckCommandStatus", + "GET", + "/real-time-response/entities/command/v1", + "Get status of an executed command on a single host." + ], + [ + "RTR_ExecuteCommand", + "POST", + "/real-time-response/entities/command/v1", + "Execute a command on a single host." + ], + [ + "RTR_GetExtractedFileContents", + "GET", + "/real-time-response/entities/extracted-file-contents/v1", + "Get RTR extracted file contents for specified session and sha256." + ], + [ + "RTR_ListFiles", + "GET", + "/real-time-response/entities/file/v1", + "Get a list of files for the specified RTR session." + ], + [ + "RTR_DeleteFile", + "DELETE", + "/real-time-response/entities/file/v1?ids={}", + "Delete a RTR session file." + ], + [ + "RTR_GetPut_Files", + "GET", + "/real-time-response/entities/put-files/v1?ids={}", + "Get put-files based on the ID's given. These are used for the RTR `put` command." + ], + [ + "RTR_CreatePut_Files", + "POST", + "/real-time-response/entities/put-files/v1", + "Upload a new put-file to use for the RTR `put` command." + ], + [ + "RTR_DeletePut_Files", + "DELETE", + "/real-time-response/entities/put-files/v1?ids={}", + "Delete a put-file based on the ID given. Can only delete one file at a time." + ], + [ + "RTR_ListQueuedSessions", + "POST", + "/real-time-response/entities/queued-sessions/GET/v1", + "Get queued session metadata by session ID." + ], + [ + "RTR_DeleteQueuedSession", + "DELETE", + "/real-time-response/entities/queued-sessions/command/v1", + "Delete a queued session command" + ], + [ + "RTR_PulseSession", + "POST", + "/real-time-response/entities/refresh-session/v1", + "Refresh a session timeout on a single host." + ], + [ + "RTR_GetScripts", + "GET", + "/real-time-response/entities/scripts/v1?ids={}", + "Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command." + ], + [ + "RTR_CreateScripts", + "POST", + "/real-time-response/entities/scripts/v1", + "Upload a new custom-script to use for the RTR `runscript` command." + ], + [ + "RTR_UpdateScripts", + "PATCH", + "/real-time-response/entities/scripts/v1", + "Upload a new scripts to replace an existing one." + ], + [ + "RTR_DeleteScripts", + "DELETE", + "/real-time-response/entities/scripts/v1?ids={}", + "Delete a custom-script based on the ID given. Can only delete one script at a time." + ], + [ + "RTR_ListSessions", + "POST", + "/real-time-response/entities/sessions/GET/v1", + "Get session metadata by session id." + ], + [ + "RTR_InitSession", + "POST", + "/real-time-response/entities/sessions/v1", + "Initialize a new session with the RTR cloud." + ], + [ + "RTR_DeleteSession", + "DELETE", + "/real-time-response/entities/sessions/v1", + "Delete a session." + ], + [ + "RTR_ListPut_Files", + "GET", + "/real-time-response/queries/put-files/v1", + "Get a list of put-file ID's that are available to the user for the `put` command." + ], + [ + "RTR_ListScripts", + "GET", + "/real-time-response/queries/scripts/v1", + "Get a list of custom-script ID's that are available to the user for the `runscript` command." + ], + [ + "RTR_ListAllSessions", + "GET", + "/real-time-response/queries/sessions/v1", + "Get a list of session_ids." + ], + [ + "GetSampleV2", + "GET", + "/samples/entities/samples/v2?ids={}", + "Retrieves the file associated with the given ID (SHA256)" + ], + [ + "UploadSampleV2", + "POST", + "/samples/entities/samples/v2", + "Upload a file for sandbox analysis. After uploading, use `/falconx/entities/submissions/v1` to start analyzing the file." + ], + [ + "DeleteSampleV2", + "DELETE", + "/samples/entities/samples/v2?ids={}", + "Removes a sample, including file, meta and submissions from the collection" + ], + [ + "GetSampleV3", + "GET", + "/samples/entities/samples/v3?ids={}", + "Retrieves the file associated with the given ID (SHA256)" + ], + [ + "UploadSampleV3", + "POST", + "/samples/entities/samples/v3", + "Upload a file for further cloud analysis. After uploading, call the specific analysis API endpoint." + ], + [ + "DeleteSampleV3", + "DELETE", + "/samples/entities/samples/v3?ids={}", + "Removes a sample, including file, meta and submissions from the collection" + ], + [ + "QuerySampleV1", + "POST", + "/samples/queries/samples/GET/v1", + "Retrieves a list with sha256 of samples that exist and customer has rights to access them, " + "maximum number of accepted items is 200" + ], + [ + "GetScansAggregates", + "POST", + "/scanner/aggregates/scans/GET/v1", + "Get scans aggregations as specified via json in request body." + ], + [ + "GetScans", + "GET", + "/scanner/entities/scans/v1?ids={}", + "Check the status of a volume scan. Time required for analysis increases with the number of " + "samples in a volume but usually it should take less than 1 minute" + ], + [ + "ScanSamples", + "POST", + "/scanner/entities/scans/v1", + "Submit a volume of files for ml scanning. Time required for analysis increases with the number of " + "samples in a volume but usually it should take less than 1 minute" + ], + [ + "QuerySubmissionsMixin0", + "GET", + "/scanner/queries/scans/v1", + "Find IDs for submitted scans by providing an FQL filter and paging details. " + "Returns a set of volume IDs that match your criteria." + ], + [ + "GetCombinedSensorInstallersByQuery", + "GET", + "/sensors/combined/installers/v1", + "Get sensor installer details by provided query" + ], + [ + "refreshActiveStreamSession", + "POST", + "/sensors/entities/datafeed-actions/v1/{}", + "Refresh an active event stream. Use the URL shown in a GET /sensors/entities/datafeed/v2 response." + ], + [ + "listAvailableStreamsOAuth2", + "GET", + "/sensors/entities/datafeed/v2", + "Discover all event streams in your environment" + ], + [ + "DownloadSensorInstallerById", + "GET", + "/sensors/entities/download-installer/v1", + "Download sensor installer by SHA256 ID" + ], + [ + "GetSensorInstallersEntities", + "GET", + "/sensors/entities/installers/v1?ids={}", + "Get sensor installer details by provided SHA256 IDs" + ], + [ + "GetSensorInstallersCCIDByQuery", + "GET", + "/sensors/queries/installers/ccid/v1", + "Get CCID to use with sensor installers" + ], + [ + "GetSensorInstallersByQuery", + "GET", + "/sensors/queries/installers/v1", + "Get sensor installer IDs by provided query" + ], + [ + "GetCSPMPolicy", + "GET", + "/settings/entities/policy-details/v1?ids={}", + "Given a policy ID, returns detailed policy information." + ], + [ + "GetCSPMPolicySettings", + "GET", + "/settings/entities/policy/v1", + "Returns information about current policy settings." + ], + [ + "UpdateCSPMPolicySettings", + "PATCH", + "/settings/entities/policy/v1", + "Updates a policy setting - can be used to override policy severity or to disable a policy entirely." + ], + [ + "GetCSPMScanSchedule", + "GET", + "/settings/scan-schedule/v1", + "Returns scan schedule configuration for one or more cloud platforms." + ], + [ + "UpdateCSPMScanSchedule", + "POST", + "/settings/scan-schedule/v1", + "Updates scan schedule configuration for one or more cloud platforms." + ], + [ + "getVulnerabilities", + "GET", + "/spotlight/entities/vulnerabilities/v2?ids={}", + "Get details on vulnerabilities by providing one or more IDs" + ], + [ + "queryVulnerabilities", + "GET", + "/spotlight/queries/vulnerabilities/v1", + "Search for Vulnerabilities in your environment by providing an FQL filter and paging details. " + "Returns a set of Vulnerability IDs which match the filter criteria" + ], + [ + "GetRoles", + "GET", + "/user-roles/entities/user-roles/v1?ids={}", + "Get info about a role" + ], + [ + "GrantUserRoleIds", + "POST", + "/user-roles/entities/user-roles/v1", + "Assign one or more roles to a user" + ], + [ + "RevokeUserRoleIds", + "DELETE", + "/user-roles/entities/user-roles/v1?ids={}", + "Revoke one or more roles from a user" + ], + [ + "GetAvailableRoleIds", + "GET", + "/user-roles/queries/user-role-ids-by-cid/v1", + "Show role IDs for all roles available in your customer account. " + "For more information on each role, provide the role ID to `/customer/entities/roles/v1`." + ], + [ + "GetUserRoleIds", + "GET", + "/user-roles/queries/user-role-ids-by-user-uuid/v1", + "Show role IDs of roles assigned to a user. " + "For more information on each role, provide the role ID to `/customer/entities/roles/v1`." + ], + [ + "RetrieveUser", + "GET", + "/users/entities/users/v1?ids={}", + "Get info about a user" + ], + [ + "CreateUser", + "POST", + "/users/entities/users/v1", + "Create a new user. After creating a user, assign one or more roles with POST /user-roles/entities/user-roles/v1" + ], + [ + "UpdateUser", + "PATCH", + "/users/entities/users/v1", + "Modify an existing user's first or last name" + ], + [ + "DeleteUser", + "DELETE", + "/users/entities/users/v1", + "Delete a user permanently" + ], + [ + "RetrieveEmailsByCID", + "GET", + "/users/queries/emails-by-cid/v1", + "List the usernames (usually an email address) for all users in your customer account" + ], + [ + "RetrieveUserUUIDsByCID", + "GET", + "/users/queries/user-uuids-by-cid/v1", + "List user IDs for all users in your customer account. " + "For more information on each user, provide the user ID to `/users/entities/user/v1`." + ], + [ + "RetrieveUserUUID", + "GET", + "/users/queries/user-uuids-by-email/v1", + "Get a user's ID by providing a username (usually an email address)" + ], + [ + "getAssessmentV1", + "GET", + "/zero-trust-assessment/entities/assessments/v1?ids={}", + "Get Zero Trust Assessment data for one or more hosts by providing agent IDs (AID) and a customer ID (CID)." + ], + # .---. .----------- + # / \ __ / ------ + # / / \(..)/ ----- + # _____ __ __ ////// ' \/ ` --- + # | \.-----.-----.----.-----.----.---.-.| |_.-----.--| | //// / // : : --- + # | -- | -__| _ | _| -__| __| _ || _| -__| _ | // / / /` '-- + # |_____/|_____| __|__| |_____|____|___._||____|_____|_____| // //..\\ + # |__| UU UU + # The following operations reference legacy naming convention and are considered deprecated. + # These operation IDs are maintained for backwards compatibility purposes only, Move all code + # references to use the new operations IDs defined above that align with the IDs defined in + # the service classes. + [ + "aggregate-events", + "POST", + "/fwmgr/aggregates/events/GET/v1", + "Aggregate events for customer" + ], + [ + "aggregate-policy-rules", + "POST", + "/fwmgr/aggregates/policy-rules/GET/v1", + "Aggregate rules within a policy for customer" + ], + [ + "aggregate-rule-groups", + "POST", + "/fwmgr/aggregates/rule-groups/GET/v1", + "Aggregate rule groups for customer" + ], + [ + "aggregate-rules", + "POST", + "/fwmgr/aggregates/rules/GET/v1", + "Aggregate rules for customer" + ], + [ + "get-events", + "GET", + "/fwmgr/entities/events/v1?ids={}", + "Get events entities by ID and optionally version" + ], + [ + "get-firewall-fields", + "GET", + "/fwmgr/entities/firewall-fields/v1?ids={}", + "Get the firewall field specifications by ID" + ], + [ + "get-platforms", + "GET", + "/fwmgr/entities/platforms/v1?ids={}", + "Get platforms by ID, e.g., windows or mac or droid" + ], + [ + "get-policy-containers", + "GET", + "/fwmgr/entities/policies/v1?ids={}", + "Get policy container entities by policy ID" + ], + [ + "update-policy-container", + "PUT", + "/fwmgr/entities/policies/v1", + "Update an identified policy container" + ], + [ + "get-rule-groups", + "GET", + "/fwmgr/entities/rule-groups/v1?ids={}", + "Get rule group entities by ID. These groups do not contain their rule entites, just the rule IDs in precedence order." + ], + [ + "create-rule-group", + "POST", + "/fwmgr/entities/rule-groups/v1", + "Create new rule group on a platform for a customer with a name and description, and return the ID" + ], + [ + "update-rule-group", + "PATCH", + "/fwmgr/entities/rule-groups/v1", + "Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules" + ], + [ + "delete-rule-groups", + "DELETE", + "/fwmgr/entities/rule-groups/v1?ids={}", + "Delete rule group entities by ID" + ], + [ + "get-rules", + "GET", + "/fwmgr/entities/rules/v1?ids={}", + "Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string)" + ], + [ + "query-events", + "GET", + "/fwmgr/queries/events/v1", + "Find all event IDs matching the query with filter" + ], + [ + "query-firewall-fields", + "GET", + "/fwmgr/queries/firewall-fields/v1", + "Get the firewall field specification IDs for the provided platform" + ], + [ + "query-platforms", + "GET", + "/fwmgr/queries/platforms/v1", + "Get the list of platform names" + ], + [ + "query-policy-rules", + "GET", + "/fwmgr/queries/policy-rules/v1", + "Find all firewall rule IDs matching the query with filter, and return them in precedence order" + ], + [ + "query-rule-groups", + "GET", + "/fwmgr/queries/rule-groups/v1", + "Find all rule group IDs matching the query with filter" + ], + [ + "query-rules", + "GET", + "/fwmgr/queries/rules/v1", + "Find all rule IDs matching the query with filter" + ], + [ + "audit-events-read", + "GET", + "/installation-tokens/entities/audit-events/v1?ids={}", + "Gets the details of one or more audit events by id." + ], + [ + "customer-settings-read", + "GET", + "/installation-tokens/entities/customer-settings/v1", + "Check current installation token settings." + ], + [ + "tokens-read", + "GET", + "/installation-tokens/entities/tokens/v1?ids={}", + "Gets the details of one or more tokens by id." + ], + [ + "tokens-create", + "POST", + "/installation-tokens/entities/tokens/v1", + "Creates a token." + ], + [ + "tokens-update", + "PATCH", + "/installation-tokens/entities/tokens/v1?ids={}", + "Updates one or more tokens. Use this endpoint to edit labels, change expiration, revoke, or restore." + ], + [ + "tokens-delete", + "DELETE", + "/installation-tokens/entities/tokens/v1?ids={}", + "Deletes a token immediately. To revoke a token, use PATCH /installation-tokens/entities/tokens/v1 instead." + ], + [ + "audit-events-query", + "GET", + "/installation-tokens/queries/audit-events/v1", + "Search for audit events by providing an FQL filter and paging details." + ], + [ + "tokens-query", + "GET", + "/installation-tokens/queries/tokens/v1", + "Search for tokens by providing an FQL filter and paging details." + ], + [ + "get-patterns", + "GET", + "/ioarules/entities/pattern-severities/v1?ids={}", + "Get pattern severities by ID." + ], + [ + "get-platformsMixin0", + "GET", + "/ioarules/entities/platforms/v1?ids={}", + "Get platforms by ID." + ], + [ + "get-rule-groupsMixin0", + "GET", + "/ioarules/entities/rule-groups/v1?ids={}", + "Get rule groups by ID." + ], + [ + "create-rule-groupMixin0", + "POST", + "/ioarules/entities/rule-groups/v1", + "Create a rule group for a platform with a name and an optional description. Returns the rule group." + ], + [ + "update-rule-groupMixin0", + "PATCH", + "/ioarules/entities/rule-groups/v1", + "Update a rule group. The following properties can be modified: name, description, enabled." + ], + [ + "delete-rule-groupsMixin0", + "DELETE", + "/ioarules/entities/rule-groups/v1?ids={}", + "Delete rule groups by ID." + ], + [ + "get-rule-types", + "GET", + "/ioarules/entities/rule-types/v1?ids={}", + "Get rule types by ID." + ], + [ + "get-rules-get", + "POST", + "/ioarules/entities/rules/GET/v1", + "Get rules by ID and optionally version in the following format: `ID[:version]`." + ], + [ + "get-rulesMixin0", + "GET", + "/ioarules/entities/rules/v1?ids={}", + "Get rules by ID and optionally version in the following format: `ID[:version]`." + "The max number of IDs is constrained by URL size." + ], + [ + "create-rule", + "POST", + "/ioarules/entities/rules/v1", + "Create a rule within a rule group. Returns the rule." + ], + [ + "update-rules", + "PATCH", + "/ioarules/entities/rules/v1", + "Update rules within a rule group. Return the updated rules." + ], + [ + "delete-rules", + "DELETE", + "/ioarules/entities/rules/v1?ids={}", + "Delete rules from a rule group by ID." + ], + [ + "query-patterns", + "GET", + "/ioarules/queries/pattern-severities/v1", + "Get all pattern severity IDs." + ], + [ + "query-platformsMixin0", + "GET", + "/ioarules/queries/platforms/v1", + "Get all platform IDs." + ], + [ + "query-rule-groups-full", + "GET", + "/ioarules/queries/rule-groups-full/v1", + "Find all rule groups matching the query with optional filter." + ], + [ + "query-rule-groupsMixin0", + "GET", + "/ioarules/queries/rule-groups/v1", + "Finds all rule group IDs matching the query with optional filter." + ], + [ + "query-rule-types", + "GET", + "/ioarules/queries/rule-types/v1", + "Get all rule type IDs." + ], + [ + "query-rulesMixin0", + "GET", + "/ioarules/queries/rules/v1", + "Finds all rule IDs matching the query with optional filter." + ], + [ + "entities.processes", + "GET", + "/processes/entities/processes/v1?ids={}", + "For the provided ProcessID retrieve the process details" + ], + [ + "RTR-AggregateSessions", + "POST", + "/real-time-response/aggregates/sessions/GET/v1", + "Get aggregates on session data." + ], + [ + "RTR-CheckActiveResponderCommandStatus", + "GET", + "/real-time-response/entities/active-responder-command/v1", + "Get status of an executed active-responder command on a single host." + ], + [ + "RTR-ExecuteActiveResponderCommand", + "POST", + "/real-time-response/entities/active-responder-command/v1", + "Execute an active responder command on a single host." + ], + [ + "RTR-CheckAdminCommandStatus", + "GET", + "/real-time-response/entities/admin-command/v1", + "Get status of an executed RTR administrator command on a single host." + ], + [ + "RTR-ExecuteAdminCommand", + "POST", + "/real-time-response/entities/admin-command/v1", + "Execute a RTR administrator command on a single host." + ], + [ + "RTR-CheckCommandStatus", + "GET", + "/real-time-response/entities/command/v1", + "Get status of an executed command on a single host." + ], + [ + "RTR-ExecuteCommand", + "POST", + "/real-time-response/entities/command/v1", + "Execute a command on a single host." + ], + [ + "RTR-GetExtractedFileContents", + "GET", + "/real-time-response/entities/extracted-file-contents/v1", + "Get RTR extracted file contents for specified session and sha256." + ], + [ + "RTR-ListFiles", + "GET", + "/real-time-response/entities/file/v1", + "Get a list of files for the specified RTR session." + ], + [ + "RTR-DeleteFile", + "DELETE", + "/real-time-response/entities/file/v1?ids={}", + "Delete a RTR session file." + ], + [ + "RTR-GetPut-Files", + "GET", + "/real-time-response/entities/put-files/v1?ids={}", + "Get put-files based on the ID's given. These are used for the RTR `put` command." + ], + [ + "RTR-CreatePut-Files", + "POST", + "/real-time-response/entities/put-files/v1", + "Upload a new put-file to use for the RTR `put` command." + ], + [ + "RTR-DeletePut-Files", + "DELETE", + "/real-time-response/entities/put-files/v1?ids={}", + "Delete a put-file based on the ID given. Can only delete one file at a time." + ], + [ + "RTR-ListQueuedSessions", + "POST", + "/real-time-response/entities/queued-sessions/GET/v1", + "Get queued session metadata by session ID." + ], + [ + "RTR-DeleteQueuedSession", + "DELETE", + "/real-time-response/entities/queued-sessions/command/v1", + "Delete a queued session command" + ], + [ + "RTR-PulseSession", + "POST", + "/real-time-response/entities/refresh-session/v1", + "Refresh a session timeout on a single host." + ], + [ + "RTR-GetScripts", + "GET", + "/real-time-response/entities/scripts/v1?ids={}", + "Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command." + ], + [ + "RTR-CreateScripts", + "POST", + "/real-time-response/entities/scripts/v1", + "Upload a new custom-script to use for the RTR `runscript` command." + ], + [ + "RTR-UpdateScripts", + "PATCH", + "/real-time-response/entities/scripts/v1", + "Upload a new scripts to replace an existing one." + ], + [ + "RTR-DeleteScripts", + "DELETE", + "/real-time-response/entities/scripts/v1?ids={}", + "Delete a custom-script based on the ID given. Can only delete one script at a time." + ], + [ + "RTR-ListSessions", + "POST", + "/real-time-response/entities/sessions/GET/v1", + "Get session metadata by session id." + ], + [ + "RTR-InitSession", + "POST", + "/real-time-response/entities/sessions/v1", + "Initialize a new session with the RTR cloud." + ], + [ + "RTR-DeleteSession", + "DELETE", + "/real-time-response/entities/sessions/v1", + "Delete a session." + ], + [ + "RTR-ListPut-Files", + "GET", + "/real-time-response/queries/put-files/v1", + "Get a list of put-file ID's that are available to the user for the `put` command." + ], + [ + "RTR-ListScripts", + "GET", + "/real-time-response/queries/scripts/v1", + "Get a list of custom-script ID's that are available to the user for the `runscript` command." + ], + [ + "RTR-ListAllSessions", + "GET", + "/real-time-response/queries/sessions/v1", + "Get a list of session_ids." + ] +] diff --git a/src/falconpy/_result.py b/src/falconpy/_result.py new file mode 100644 index 00000000..514ea48c --- /dev/null +++ b/src/falconpy/_result.py @@ -0,0 +1,53 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +_result - API Response formatting class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" + + +class Result: + """ Callable subclass to handle parsing of result client output. """ + def __init__(self: object) -> dict: + """ Instantiates the subclass and initializes the result object. """ + self.result_obj = {} + + def __call__(self: object, status_code: int, headers, body: dict) -> dict: + """ Formats values into a properly formatted result object. """ + self.result_obj['status_code'] = status_code + self.result_obj['headers'] = dict(headers) # force standard dictionary to prevent json issues + self.result_obj['body'] = body + + return self.result_obj diff --git a/src/falconpy/_service_class.py b/src/falconpy/_service_class.py new file mode 100644 index 00000000..7be94370 --- /dev/null +++ b/src/falconpy/_service_class.py @@ -0,0 +1,82 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +_service_class - ServiceClass base class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from .oauth2 import OAuth2 as FalconAuth + + +class ServiceClass: + """ Base class of all service classes. Contains the default __init__ method. """ + def __init__(self: object, access_token: str = None, auth_object: object = None, creds: dict = None, + base_url: str = "https://api.crowdstrike.com", ssl_verify: bool = True) -> object: + """ Instantiates the base class, ingests the authorization token, + and initializes the headers and base_url global variables. + """ + self.refreshable = False + if auth_object: + self.auth_object = auth_object + self.headers = {'Authorization': 'Bearer {}'.format(auth_object.token()['body']['access_token'])} + self.base_url = auth_object.base_url + self.ssl_verify = auth_object.ssl_verify + self.refreshable = True + else: + if creds: + auth_object = FalconAuth(creds=creds) + self.auth_object = auth_object + self.headers = {'Authorization': 'Bearer {}'.format(auth_object.token()['body']['access_token'])} + self.base_url = base_url + self.ssl_verify = ssl_verify + self.refreshable = True + else: + self.auth_object = None + self.headers = {'Authorization': 'Bearer {}'.format(access_token)} + self.base_url = base_url + self.ssl_verify = ssl_verify + + def authenticated(self): + result = None + if self.auth_object: + result = self.auth_object.authenticated() + + return result + + def token_expired(self): + result = None + if self.auth_object: + result = self.auth_object.token_expired() + + return result diff --git a/src/falconpy/_util.py b/src/falconpy/_util.py new file mode 100644 index 00000000..6a923988 --- /dev/null +++ b/src/falconpy/_util.py @@ -0,0 +1,198 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +_util - Internal utilities library + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +import requests +import base64 +import urllib3 +from ._version import _title, _version +from ._result import Result +from urllib3.exceptions import InsecureRequestWarning +urllib3.disable_warnings(InsecureRequestWarning) + +# Restrict requests to only allowed HTTP methods +_ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'UPDATE'] +# Default user-agent string +_USER_AGENT = f"{_title}/{str(_version)}" + + +def validate_payload(validator: dict, params: dict, required: list = None) -> bool: + """ Validates parameters and body payloads sent to the API """ + # Repurposed with permission from https://github.com/yaleman/crowdstrike_api + # __ + # ( (\ + # \ =\ + # __\_ `--\ + # (____))( \---- + # (____)) _ Thanks + # (____)) James! + # (____))____/---- + for key in params: + if key not in validator: + raise ValueError(f"{key} is not a valid argument.") + if not isinstance(params[key], validator[key]): + raise TypeError(f"{key} is not the valid type. Should be: {validator[key]}, was {type(params[key])}") + if required: + for key in required: + if key not in params: + raise ValueError(f"Argument {key} must be specified.") + return True + + +def parse_id_list(id_list) -> str: + """ Converts a list of IDs to a comma-delimited string """ + if isinstance(id_list, list): + returned = "" + for s in id_list: + if len(returned) > 1: + returned += "," + returned += str(s) + return returned + else: + return id_list + + +def generate_b64cred(client_id: str, client_secret: str) -> str: + """ base64 encodes passed client_id and client_secret for authorization headers. """ + cr = "{}:{}".format(client_id, client_secret) + b64_byt = base64.b64encode(cr.encode("ascii")) + encoded = b64_byt.decode("ascii") + + return encoded + + +def service_request(caller: object = None, **kwargs) -> object: # May return dict or object datatypes + """ Checks for token expiration, refreshing if possible and then performs the request. """ + if caller: + try: + if caller.auth_object: + if caller.auth_object.token_expired(): + caller.auth_object.token() + caller.headers['Authorization'] = 'Bearer {}'.format(caller.auth_object.token()['body']['access_token']) + except AttributeError: + pass + + returned = perform_request(**kwargs) + + return returned + + +def perform_request(method: str = "", endpoint: str = "", headers: dict = None, + params: dict = None, body: dict = None, verify: bool = True, + data=None, files: list = None, + params_validator: dict = None, params_required: dict = None, + body_validator: dict = None, body_required: dict = None) -> object: # May return dict or object datatypes + """ + Leverages the requests library to perform the requested CrowdStrike OAuth2 API operation. + + method: str - HTTP method to use when communicating with the API + - Example: GET, POST, PATCH, DELETE or UPDATE + endpoint: str - API endpoint, do not include the URL base + - Example: /oauth2/revoke + headers: dict - HTTP headers to send to the API + - Example: {"AdditionalHeader": "AdditionalValue"} + params: dict - HTTP query string parameters to send to the API + - Example: {"limit": 1, "sort": "state.asc"} + body: dict - HTTP body payload to send to the API + - Example: {"ids": "123456789abcdefg,987654321zyxwvutsr"} + verify: bool - Enable / Disable SSL certificate checks + - Example: True + data - Encoded data to send to the API + - Example: PAYLOAD = open(FILENAME, 'rb').read() + files: list - List of files to upload + - Example: [('file',('testfile2.jpg',open('testfile2.jpg','rb'),'image/jpeg'))] + params_validator: dict - Dictionary containing parameters to be validated for the requested operation (key / datatype) + - Example: { "limit": int, "offset": int, "filter": str} + params_required: list - List of parameters required by the requested operation + - Example: ["ids"] + body_validator: dict - Dictionary containing payload to be validated for the requested operation (key / datatype) + - Example: { "limit": int, "offset": int, "filter": str} + body_required: list - List of payload parameters required by the requested operation + - Example: ["ids"] + """ + if files is None: + files = [] + PERFORM = True + METHOD = method.upper() + if METHOD in _ALLOWED_METHODS: + # Validate parameters + if params_validator: + try: + validate_payload(params_validator, params, params_required) + except ValueError as e: + returned = generate_error_result(message=f"{str(e)}") + PERFORM = False + except TypeError as e: + returned = generate_error_result(message=f"{str(e)}") + PERFORM = False + + # Validate body payload + if body_validator: + try: + validate_payload(body_validator, body, body_required) + except ValueError as e: + returned = generate_error_result(message=f"{str(e)}") + PERFORM = False + except TypeError as e: + returned = generate_error_result(message=f"{str(e)}") + PERFORM = False + + # Perform the request + if PERFORM: + headers["User-Agent"] = _USER_AGENT # Force all requests to pass the User-Agent identifier + try: + response = requests.request(METHOD, endpoint, params=params, headers=headers, + json=body, data=data, files=files, verify=verify) + if response.headers.get('content-type') == "application/json": + returned = Result()(response.status_code, response.headers, response.json()) + else: + returned = response.content + except Exception as e: + returned = generate_error_result(message=f"{str(e)}") + else: + returned = generate_error_result(message="Invalid API operation specified.", code=405) + + return returned + + +def generate_error_result(message: str = "An error has occurred. Check your payloads and try again.", code: int = 500) -> dict: + """ Normalized error messaging handler. """ + return Result()(status_code=code, headers={}, body={"errors": [{"message": f"{message}"}], "resources": []}) + + +def generate_ok_result(message: str = "Request returned with success", code: int = 200) -> dict: + return Result()(status_code=code, headers={}, body={"message": message, "resources": []}) diff --git a/src/falconpy/_version.py b/src/falconpy/_version.py new file mode 100644 index 00000000..533da351 --- /dev/null +++ b/src/falconpy/_version.py @@ -0,0 +1,46 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +_version - Internal version control constants + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +_version = '0.4.5' +_maintainer = 'Joshua Hiller' +_author = 'CrowdStrike' +_author_email = 'falconpy@crowdstrike.com' +_credits = 'CrowdStrike' +_description = "The CrowdStrike Falcon OAuth2 API SDK for Python 3" +_title = "crowdstrike-falconpy" +_project_url = "https://github.com/CrowdStrike/falconpy" diff --git a/src/falconpy/api_complete.py b/src/falconpy/api_complete.py new file mode 100644 index 00000000..9eeffd46 --- /dev/null +++ b/src/falconpy/api_complete.py @@ -0,0 +1,164 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +api_complete.py - All-in-one CrowdStrike Falcon OAuth2 API harness + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +import time +from ._util import perform_request, parse_id_list, generate_b64cred, _ALLOWED_METHODS, generate_error_result +from ._endpoint import api_endpoints + + +class APIHarness: + """ This one does it all. It's like the One Ring with significantly fewer orcs. """ + + def __init__(self: object, creds: dict, base_url: str = "https://api.crowdstrike.com", + ssl_verify: bool = True) -> object: + """ Instantiates an instance of the base class, ingests credentials and the base URL and initializes global variables. + """ + + self.creds = creds + self.base_url = base_url + self.ssl_verify = ssl_verify + self.token = False + self.token_expiration = 0 + self.token_renew_window = 20 + self.token_time = time.time() + self.token_expired = lambda: True if ( + time.time() - self.token_time + ) >= ( + self.token_expiration - self.token_renew_window + ) else False + self.authenticated = False + self.valid_cred_format = lambda: True if "client_id" in self.creds and "client_secret" in self.creds else False + self.headers = lambda: {'Authorization': 'Bearer {}'.format(self.token)} if self.token else {} + self.commands = api_endpoints + + def authenticate(self: object) -> bool: + """ Generates an authorization token. """ + FULL_URL = self.base_url+'/oauth2/token' + DATA = {} + if self.valid_cred_format(): + DATA = { + 'client_id': self.creds['client_id'], + 'client_secret': self.creds['client_secret'] + } + if "member_cid" in self.creds: + DATA["member_cid"] = self.creds["member_cid"] + + result = perform_request(method="POST", endpoint=FULL_URL, data=DATA, headers={}, verify=self.ssl_verify) + if result["status_code"] == 201: + self.token = result["body"]["access_token"] + self.token_expiration = result["body"]["expires_in"] + self.token_time = time.time() + self.authenticated = True + else: + self.authenticated = False + + return self.authenticated + + def deauthenticate(self: object) -> bool: + """ Revokes the specified authorization token. """ + FULL_URL = str(self.base_url)+'/oauth2/revoke' + HEADERS = {'Authorization': 'basic {}'.format(generate_b64cred(self.creds["client_id"], self.creds["client_secret"]))} + DATA = {'token': '{}'.format(self.token)} + revoked = False + if perform_request(method="POST", endpoint=FULL_URL, data=DATA, + headers=HEADERS, verify=self.ssl_verify)["status_code"] == 200: + self.authenticated = False + self.token = False + revoked = True + else: + revoked = False + + return revoked + + # NOTE: Not specifying datatypes for "ids" and "partition" parameters + # to allow developers to pass str / lists / integers as necessary + def command(self: object, action: str = "", parameters: dict = None, body: dict = None, data: dict = None, # noqa: C901 + headers: dict = None, ids=None, partition=None, override: str = None, action_name: str = None, + files: list = None, file_name: str = None, content_type: str = None): + """ Checks token expiration, renewing when necessary, then performs the request. """ + if self.token_expired(): + self.authenticate() + if override: + CMD = [["Manual"] + override.split(",")] + else: + CMD = [a for a in self.commands if a[0] == action] + if CMD: + FULL_URL = self.base_url+"{}".format(CMD[0][2]) + if ids: + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = FULL_URL.format(ID_LIST) + if action_name: + delim = "&" if "?" in FULL_URL else "?" + FULL_URL = f"{FULL_URL}{delim}action_name={str(action_name)}" # TODO: Additional action_name restrictions? + if partition: + FULL_URL = FULL_URL.format(str(partition)) + if file_name: + delim = "&" if "?" in FULL_URL else "?" + FULL_URL = f"{FULL_URL}{delim}file_name={str(file_name)}" + HEADERS = self.headers() + if headers is None: + headers = [] + for item in headers: + HEADERS[item] = headers[item] + if content_type: + HEADERS["Content-Type"] = str(content_type) + if data is None: + data = {} + DATA = data + if body is None: + body = {} + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + if files is None: + files = [] + FILES = files + if self.authenticated: + METHOD = CMD[0][1].upper() + if METHOD in _ALLOWED_METHODS: + returned = perform_request(method=METHOD, endpoint=FULL_URL, body=BODY, data=DATA, + params=PARAMS, headers=HEADERS, files=FILES, verify=self.ssl_verify) + else: + returned = generate_error_result(message="Invalid HTTP method specified.", code=405) + else: + returned = generate_error_result(message="Failed to issue token.", code=401) + else: + returned = generate_error_result(message="Invalid API operation specified.", code=418) + + return returned diff --git a/src/falconpy/cloud_connect_aws.py b/src/falconpy/cloud_connect_aws.py new file mode 100644 index 00000000..55f65f8a --- /dev/null +++ b/src/falconpy/cloud_connect_aws.py @@ -0,0 +1,205 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +cloud_connect_aws - Falcon Discover for AWS API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list +from ._service_class import ServiceClass + + +class Cloud_Connect_AWS(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def QueryAWSAccounts(self: object, parameters: dict = None) -> dict: + """ Search for provisioned AWS Accounts by providing an FQL filter and paging details. + Returns a set of AWS accounts which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/QueryAWSAccounts + FULL_URL = self.base_url+'/cloud-connect-aws/combined/accounts/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + VALIDATOR = { + "limit": int, + "offset": int, + "sort": str, + "filter": str + } + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify, + params_validator=VALIDATOR + ) + return returned + + def GetAWSSettings(self: object) -> dict: + """ Retrieve a set of Global Settings which are applicable to all provisioned AWS accounts. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/GetAWSSettings + FULL_URL = self.base_url+'/cloud-connect-aws/combined/settings/v1' + HEADERS = self.headers + returned = service_request(caller=self, method="GET", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def GetAWSAccounts(self: object, ids) -> dict: + """ Retrieve a set of AWS Accounts by specifying their IDs.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/GetAWSAccounts + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, method="GET", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def ProvisionAWSAccounts(self: object, body: dict, parameters: dict = None) -> dict: + """ Provision AWS Accounts by specifying details about the accounts to provision. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/ProvisionAWSAccounts + FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1' + if parameters is None: + parameters = {} + PARAMS = parameters + BODY = body + HEADERS = self.headers + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + body=BODY, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def DeleteAWSAccounts(self: object, ids) -> dict: + """ Delete a set of AWS Accounts by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/DeleteAWSAccounts + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, method="DELETE", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def UpdateAWSAccounts(self: object, body: dict) -> dict: + """ Update AWS Accounts by specifying the ID of the account and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/UpdateAWSAccounts + FULL_URL = self.base_url+'/cloud-connect-aws/entities/accounts/v1' + BODY = body + HEADERS = self.headers + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def CreateOrUpdateAWSSettings(self: object, body: dict) -> dict: + """ Create or update Global Settings which are applicable to all provisioned AWS accounts. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/CreateOrUpdateAWSSettings + FULL_URL = self.base_url+'/cloud-connect-aws/entities/settings/v1' + HEADERS = self.headers + BODY = body + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def VerifyAWSAccountAccess(self: object, ids, body: dict = None) -> dict: + """ Performs an Access Verification check on the specified AWS Account IDs. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/VerifyAWSAccountAccess + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/cloud-connect-aws/entities/verify-account-access/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + if body is None: + body = {} + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryAWSAccountsForIDs(self: object, parameters: dict = None) -> dict: + """ Search for provisioned AWS Accounts by providing an FQL filter and paging details. + Returns a set of AWS account IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cloud-connect-aws/QueryAWSAccountsForIDs + FULL_URL = self.base_url+'/cloud-connect-aws/queries/accounts/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + VALIDATOR = { + "limit": int, + "offset": int, + "sort": str, + "filter": str + } + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + params_validator=VALIDATOR, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/cspm_registration.py b/src/falconpy/cspm_registration.py new file mode 100644 index 00000000..b534016a --- /dev/null +++ b/src/falconpy/cspm_registration.py @@ -0,0 +1,317 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +cspm_registration - Falcon Horizon for AWS API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list +from ._service_class import ServiceClass + + +class CSPM_Registration(ServiceClass): + """The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetCSPMAwsAccount(self: object, ids, org_ids=None, parameters: dict = None) -> dict: + """Returns information about the current status of an AWS account. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMAwsAccount + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/cloud-connect-cspm-aws/entities/account/v1?ids={}".format(ID_LIST) + if org_ids: + ORG_ID_LIST = str(parse_id_list(org_ids)).replace(",", "&organization-ids=") + FULL_URL = FULL_URL + "&organization-id={}".format(ORG_ID_LIST) + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def CreateCSPMAwsAccount(self: object, body: dict) -> dict: + """Creates a new account in our system for a customer and generates a script + to run in their AWS cloud environment to grant CrowdStrike Horizon access. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/CreateCSPMAwsAccount + FULL_URL = self.base_url+"/cloud-connect-cspm-aws/entities/account/v1" + HEADERS = self.headers + BODY = body + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def DeleteCSPMAwsAccount(self: object, ids=None, org_ids=None) -> dict: + """Delete an existing AWS Account or Organization by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/DeleteCSPMAwsAccount + ep_base = "/cloud-connect-cspm-aws/entities/account/v1" + if ids: + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'{}?ids={}'.format(ep_base, ID_LIST) + else: + FULL_URL = self.base_url+ep_base + if org_ids: + ORG_ID_LIST = str(parse_id_list(org_ids)).replace(",", "&organization-ids=") + if "?" in FULL_URL: + stem = "&organization-ids=" + else: + stem = "?organization-ids=" + FULL_URL = FULL_URL + stem + '{}'.format(ORG_ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, method="DELETE", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def GetCSPMAwsConsoleSetupURLs(self: object) -> dict: + """Returns a URL for customers to visit in their cloud environment to grant access to CrowdStrike""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMAwsConsoleSetupURLs + FULL_URL = self.base_url+"/cloud-connect-cspm-aws/entities/console-setup-urls/v1" + HEADERS = self.headers + returned = service_request(caller=self, method="GET", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def GetCSPMAwsAccountScriptsAttachment(self: object) -> bytes: + """Return a script for customers to run in their cloud environment + to grant access to CrowdStrike for their AWS environment. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /cspm-registration/GetCSPMAwsAccountScriptsAttachment + FULL_URL = self.base_url+"/cloud-connect-cspm-aws/entities/user-scripts-download/v1" + HEADERS = self.headers + returned = service_request(caller=self, method="GET", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + def GetCSPMAzureAccount(self: object, ids, parameters: dict = None) -> dict: + """Return information about Azure account registration.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMAzureAccount2 + # This shows up as GetCSPMAzureAccount2 in the Uber class. + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/cloud-connect-cspm-azure/entities/account/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def CreateCSPMAzureAccount(self: object, body: dict) -> dict: + """Creates a new account in our system for a customer and generates a script + to run in their cloud environment to grant CrowdStrike Horizon access. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/CreateCSPMAzureAccount2 + # This shows up as CreateCSPMAzureAccount2 in the Uber class + FULL_URL = self.base_url+"/cloud-connect-cspm-azure/entities/account/v1" + HEADERS = self.headers + BODY = body + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def DeleteCSPMAzureAccount(self: object, ids) -> dict: + """Delete an existing Azure Subscription by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/DeleteCSPMAzureAccount + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/cloud-connect-cspm-azure/entities/account/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, method="DELETE", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned + + # TODO: Confirm payload formats for IDs not passed via an array + def UpdateCSPMAzureAccountClientID(self: object, body: dict = None, parameters: dict = None) -> dict: + """Update an Azure service account in our system with the + user-created client_id created with the public key we've provided. + """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /cspm-registration/UpdateCSPMAzureAccountClientID2 + # This shows up as UpdateCSPMAzureAccountClientID2 in the Uber class + FULL_URL = self.base_url+'/cloud-connect-cspm-azure/entities/client-id/v1' + if parameters is None: + parameters = {} + PARAMS = parameters + HEADERS = self.headers + if body is None: + body = {} + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetCSPMAzureUserScriptsAttachment(self: object, parameters: dict = None) -> bytes: + """Return a script for customers to run in their cloud environment + to grant access to CrowdStrike for their Azure environment. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /cspm-registration/GetCSPMAzureUserScriptsAttachment2 + FULL_URL = self.base_url+"/cloud-connect-cspm-azure/entities/user-scripts-download/v1" + if parameters is None: + parameters = {} + PARAMS = parameters + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def GetCSPMPolicy(self: object, ids) -> dict: + """Given a policy ID, returns detailed policy information.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMPolicy + FULL_URL = self.base_url+"/settings/entities/policy-details/v1" + if ids: + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = FULL_URL + "&ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def GetCSPMPolicySettings(self: object, parameters: dict = None) -> dict: + """Returns information about current policy settings.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMPolicySettings + FULL_URL = self.base_url+"/settings/entities/policy/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def UpdateCSPMPolicySettings(self: object, body: dict) -> dict: + """Updates a policy setting - can be used to override policy severity or to disable a policy entirely.""" + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /cspm-registration/UpdateCSPMPolicySettings + FULL_URL = self.base_url+'/settings/entities/policy/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetCSPMScanSchedule(self: object, parameters: dict = None) -> dict: + """Returns scan schedule configuration for one or more cloud platforms.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMScanSchedule + FULL_URL = self.base_url+"/settings/scan-schedule/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + + return returned + + def UpdateCSPMScanSchedule(self: object, body: dict) -> dict: + """Updates scan schedule configuration for one or more cloud platforms.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/UpdateCSPMScanSchedule + FULL_URL = self.base_url+"/settings/scan-schedule/v1" + HEADERS = self.headers + BODY = body + VALIDATOR = {"resources": list} + REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/custom_ioa.py b/src/falconpy/custom_ioa.py new file mode 100644 index 00000000..2ab78c33 --- /dev/null +++ b/src/falconpy/custom_ioa.py @@ -0,0 +1,352 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +custom_ioa - Falcon Custom Indicators of Attack API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list +from ._service_class import ServiceClass + + +class Custom_IOA(ServiceClass): + """The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def get_patterns(self: object, ids) -> dict: + """Get pattern severities by ID""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-patterns + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/ioarules/entities/pattern-severities/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_platformsMixin0(self: object, ids) -> dict: + """Get platforms by ID""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-platformsMixin0 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/ioarules/entities/platforms/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rule_groupsMixin0(self: object, ids) -> dict: + """Get rule groups by ID""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-rule-groupsMixin0 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/ioarules/entities/rule-groups/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def create_rule_groupMixin0(self: object, body: dict, cs_username: str) -> dict: + """Create a rule group for a platform with a name and an optional description. Returns the rule group.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/create-rule-groupMixin0 + FULL_URL = self.base_url+'/ioarules/entities/rule-groups/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def delete_rule_groupMixin0(self: object, ids, cs_username: str, parameters: dict = None) -> dict: + """Delete rule groups by ID.""" + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/delete-rule-groupsMixin0 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/ioarules/entities/rule-groups/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def update_rule_groupMixin0(self: object, body: dict, cs_username: str) -> dict: + """Update a rule group. The following properties can be modified: name, description, enabled.""" + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/update-rule-groupMixin0 + FULL_URL = self.base_url+'/ioarules/entities/rule-groups/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rule_types(self: object, ids) -> dict: + """Get rule types by ID""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-rule-types + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/ioarules/entities/rule-types/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rules_get(self: object, ids) -> dict: + """Get rules by ID and optionally version in the following format: ID[:version]""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-rules-get + FULL_URL = self.base_url+"/ioarules/entities/rules/GET/v1" + HEADERS = self.headers + BODY = {} + BODY["ids"] = parse_id_list(ids).split(",") # We need a list in this scenario + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rulesMixin0(self: object, ids) -> dict: + """Get rules by ID and optionally version in the following format: ID[:version]. + The max number of IDs is constrained by URL size. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/get-rulesMixin0 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/ioarules/entities/rules/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def create_rule(self: object, body: dict, cs_username: str) -> dict: + """Create a rule within a rule group. Returns the rule.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/create-rule + FULL_URL = self.base_url+'/ioarules/entities/rules/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def delete_rules(self: object, ids, cs_username: str, parameters: dict = None) -> dict: + """Delete rules from a rule group by ID.""" + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/delete-rules + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/ioarules/entities/rules/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def update_rules(self: object, body: dict, cs_username: str) -> dict: + """Update rules within a rule group. Return the updated rules.""" + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/update-rules + FULL_URL = self.base_url+'/ioarules/entities/rules/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def validate(self: object, body: dict) -> dict: + """Validates field values and checks for matches if a test string is provided.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/validate + FULL_URL = self.base_url+'/ioarules/entities/rules/validate/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_patterns(self: object, parameters: dict = None) -> dict: + """Get all pattern severity IDs""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-patterns + FULL_URL = self.base_url+"/ioarules/queries/pattern-severities/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def query_platformsMixin0(self: object, parameters: dict = None) -> dict: + """Get all platform IDs.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-platformsMixin0 + FULL_URL = self.base_url+"/ioarules/queries/platforms/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def query_rule_groups_full(self: object, parameters: dict = None) -> dict: + """Find all rule groups matching the query with optional filter.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-rule-groups-full + FULL_URL = self.base_url+"/ioarules/queries/rule-groups-full/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def query_rule_groupsMixin0(self: object, parameters: dict = None) -> dict: + """Finds all rule group IDs matching the query with optional filter.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-rule-groupsMixin0 + FULL_URL = self.base_url+"/ioarules/queries/rule-groups/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def query_rule_types(self: object, parameters: dict = None) -> dict: + """Get all rule type IDs.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-rule-types + FULL_URL = self.base_url+"/ioarules/queries/rule-types/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def query_rulesMixin0(self: object, parameters: dict = None) -> dict: + """Finds all rule IDs matching the query with optional filter.""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/custom-ioa/query-rulesMixin0 + FULL_URL = self.base_url+"/ioarules/queries/rules/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/debug.py b/src/falconpy/debug.py new file mode 100644 index 00000000..38c057a6 --- /dev/null +++ b/src/falconpy/debug.py @@ -0,0 +1,73 @@ +from . import oauth2 as FalconAuth + +banner = """ +,---. | ,--. | +|__. ,---.| ,---.,---.,---.| |,---.|---.. .,---. +| ,---|| | | || || ||---'| || || | +` `---^`---'`---'`---'` '`--' `---'`---'`---'`---| + `---' + CrowdStrike Python 3 Debug Interface + +This shell-like interface allows for quick learning, +demoing, and prototyping of API operations using +the CrowdStrike FalconPy SDK and Python 3. + +Please type help() to learn more. + | + _____________ __ -+- _____________ + \\_____ / /_ \\ | \\ _____/ + \\_____ \\____/ \\____/ _____/ + \\_____ FalconPy _____/ + \\___________ ___________/ + /____\\ +""" + +python_help = help + + +def help(item=None): + text = """ + This is interactive Python shell. Python help is available under python_help() + If you have FALCON_CLIENT_ID FALCON_CLIENT_SECRET environment variable set. This + shell will authenticate at the start up and the 'debug_token' variable will be + filled in with your OAuth2 token. + """ + if item is None: + print(text) + elif callable(getattr(item, 'help', None)): + item.help() + else: + print(item.__doc__) + + +def embed(): + from IPython.terminal.embed import InteractiveShellEmbed + ipshell = InteractiveShellEmbed(banner1=banner) + ipshell.confirm_exit = False + ipshell() + + +def startup(dbg_falcon_client_id: str, dbg_falcon_client_secret: str): + dbg_authorization = FalconAuth.OAuth2(creds={ + 'client_id': dbg_falcon_client_id, + 'client_secret': dbg_falcon_client_secret + }) + + try: + debug_token = dbg_authorization.token()["body"]["access_token"] + except Exception: + debug_token = False + + return debug_token + + +def init(dbg_falcon_client_id: str = None, dbg_falcon_client_secret: str = None, creds: dict = None): + if creds: + dbg_falcon_client_id = creds["falcon_client_id"] + dbg_falcon_client_secret = creds["falcon_client_secret"] + global debug_token + debug_token = startup(dbg_falcon_client_id, dbg_falcon_client_secret) + embed() + + +debug_token = False diff --git a/src/falconpy/detects.py b/src/falconpy/detects.py new file mode 100644 index 00000000..b22cfb40 --- /dev/null +++ b/src/falconpy/detects.py @@ -0,0 +1,133 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +detects - CrowdStrike Falcon Detections API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request +from ._service_class import ServiceClass + + +class Detects(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetAggregateDetects(self: object, body: dict) -> dict: + """ Get detect aggregates as specified via json in request body. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/GetAggregateDetects + FULL_URL = self.base_url+'/detects/aggregates/detects/GET/v1' + HEADERS = self.headers + BODY = body + # VALIDATOR = {"resources": list} # TODO: Confirm body payload format + # REQUIRED = ["resources"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + headers=HEADERS, + body=BODY, + # body_validator=VALIDATOR, + # body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def UpdateDetectsByIdsV2(self: object, body: dict) -> dict: + """ Modify the state, assignee, and visibility of detections. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/UpdateDetectsByIdsV2 + FULL_URL = self.base_url+'/detects/entities/detects/v2' + HEADERS = self.headers + BODY = body + VALIDATOR = { + "assigned_to_uuid": str, + "ids": list, + "show_in_ui": bool, + "status": str, + "comment": str + } + REQUIRED = ["ids"] + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + headers=HEADERS, + body=BODY, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def GetDetectSummaries(self: object, body: dict) -> dict: + """ View information about detections. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/GetDetectSummaries + FULL_URL = self.base_url+'/detects/entities/summaries/GET/v1' + HEADERS = self.headers + BODY = body + VALIDATOR = {"ids": list} # TODO: Confirm list datatype for ingested IDs via the body payload + REQUIRED = ["ids"] + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + headers=HEADERS, + body=BODY, + body_validator=VALIDATOR, + body_required=REQUIRED, + verify=self.ssl_verify + ) + return returned + + def QueryDetects(self: object, parameters: dict = None) -> dict: + """ Search for detection IDs that match a given query. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/detects/QueryDetects + FULL_URL = self.base_url+'/detects/queries/detects/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + VALIDATOR = { + "limit": int, + "offset": int, + "sort": str, + "filter": str, + "q": str + } + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + params_validator=VALIDATOR, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/device_control_policies.py b/src/falconpy/device_control_policies.py new file mode 100644 index 00000000..b3bc12b2 --- /dev/null +++ b/src/falconpy/device_control_policies.py @@ -0,0 +1,233 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +device_control_policies - CrowdStrike Falcon Device Control Policies API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list, generate_error_result +from ._service_class import ServiceClass + + +class Device_Control_Policies(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def queryCombinedDeviceControlPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Device Control Policy in your environment by providing an FQL filter + and paging details. Returns a set of host details which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/queryCombinedDeviceControlPolicyMembers + FULL_URL = self.base_url+'/policy/combined/device-control-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedDeviceControlPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Device Control Policies in your environment by providing an FQL filter and + paging details. Returns a set of Device Control Policies which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/queryCombinedDeviceControlPolicies + FULL_URL = self.base_url+'/policy/combined/device-control/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def performDeviceControlPoliciesAction(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Search for Device Control Policies in your environment by providing an FQL filter + and paging details. Returns a set of Device Control Policies which match the filter criteria. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/performDeviceControlPoliciesAction + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + ALLOWED_ACTIONS = ['add-host-group', 'disable', 'enable', 'remove-host-group'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/policy/combined/device-control/v1' + HEADERS = self.headers + BODY = body + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def setDeviceControlPoliciesPrecedence(self: object, body: dict) -> dict: + """ Sets the precedence of Device Control Policies based on the order of IDs specified in the request. + The first ID specified will have the highest precedence and the last ID specified will have the lowest. + You must specify all non-Default Policies for a platform when updating precedence. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/performDeviceControlPoliciesAction + FULL_URL = self.base_url+'/policy/entities/device-control-precedence/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def getDeviceControlPolicies(self: object, ids) -> dict: + """ Retrieve a set of Device Control Policies by specifying their IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/getDeviceControlPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/device-control/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createDeviceControlPolicies(self: object, body: dict) -> dict: + """ Create Device Control Policies by specifying details about the policy to create. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/createDeviceControlPolicies + FULL_URL = self.base_url+'/policy/entities/device-control/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def deleteDeviceControlPolicies(self: object, ids) -> dict: + """ Delete a set of Device Control Policies by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/createDeviceControlPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/device-control/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updateDeviceControlPolicies(self: object, body: dict) -> dict: + """ Update Device Control Policies by specifying the ID of the policy and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/updateDeviceControlPolicies + FULL_URL = self.base_url+'/policy/entities/device-control/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryDeviceControlPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Device Control Policy in your environment by providing an FQL filter + and paging details. Returns a set of Agent IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/queryDeviceControlPolicyMembers + FULL_URL = self.base_url+'/policy/queries/device-control-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryDeviceControlPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Device Control Policies in your environment by providing an FQL filter and paging details. + Returns a set of Device Control Policy IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /device-control-policies/queryDeviceControlPolicyMembers + FULL_URL = self.base_url+'/policy/queries/device-control/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/event_streams.py b/src/falconpy/event_streams.py new file mode 100644 index 00000000..d708e6f7 --- /dev/null +++ b/src/falconpy/event_streams.py @@ -0,0 +1,76 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +event_streams - CrowdStrike Falcon Event Stream API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request +from ._service_class import ServiceClass + + +class Event_Streams(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def refreshActiveStreamSession(self: object, parameters: dict, partition: int = 0) -> dict: + """ Refresh an active event stream. Use the URL shown in a GET /sensors/entities/datafeed/v2 response. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/event-streams/refreshActiveStreamSession + FULL_URL = self.base_url+'/sensors/entities/datafeed-actions/v1/{}'.format(str(partition)) + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body={}, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def listAvailableStreamsOAuth2(self: object, parameters: dict) -> dict: + """ Discover all event streams in your environment. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/event-streams/listAvailableStreamsOAuth2 + FULL_URL = self.base_url+'/sensors/entities/datafeed/v2' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/falconx_sandbox.py b/src/falconpy/falconx_sandbox.py new file mode 100644 index 00000000..53f2cece --- /dev/null +++ b/src/falconpy/falconx_sandbox.py @@ -0,0 +1,241 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +incidents - CrowdStrike Falcon X Sanbox API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class FalconX_Sandbox(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetArtifacts(self: object, parameters: dict) -> object: + """ Download IOC packs, PCAP files, and other analysis artifacts. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetArtifacts + FULL_URL = self.base_url+'/falconx/entities/artifacts/v1' + HEADERS = self.headers + HEADERS['Accept-Encoding'] = 'gzip' # Force gzip compression + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetSummaryReports(self: object, ids) -> dict: + """ Get a short summary version of a sandbox report. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetSummaryReports + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/falconx/entities/report-summaries/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetSubmissions(self: object, ids) -> dict: + """ Check the status of a sandbox analysis. Time required for analysis varies but is usually less than 15 minutes. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetSubmissions + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/falconx/entities/submissions/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def Submit(self: object, body: dict) -> dict: + """ Submit an uploaded file or a URL for sandbox analysis. + Time required for analysis varies but is usually less than 15 minutes. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/Submit + FULL_URL = self.base_url+'/falconx/entities/submissions/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryReports(self: object, parameters: dict = None) -> dict: + """ Find sandbox reports by providing an FQL filter and paging details. + Returns a set of report IDs that match your criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QueryReports + FULL_URL = self.base_url+'/falconx/queries/reports/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QuerySubmissions(self: object, parameters: dict = None) -> dict: + """ Find submission IDs for uploaded files by providing an FQL filter and paging details. + Returns a set of submission IDs that match your criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QuerySubmissions + FULL_URL = self.base_url+'/falconx/queries/submissions/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def UploadSampleV2(self: object, parameters: dict, body: dict) -> dict: + """ Upload a file for sandbox analysis. After uploading, + use `/falconx/entities/submissions/v1` to start analyzing the file. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/UploadSampleV2 + FULL_URL = self.base_url+'/samples/entities/samples/v2' + HEADERS = self.headers + HEADERS['Content-Type'] = 'application/octet-stream' + BODY = body # TODO: Confirm this is a data element and update calling code to reflect the correct reference + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + data=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetReports(self: object, ids) -> object: + """ Retrieves a full sandbox report. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetReports + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/falconx/entities/reports/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DeleteReport(self: object, ids) -> dict: + """ Delete report based on the report ID. Operation can be checked for success + by polling for the report ID on the report-summaries endpoint. + """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/DeleteReport + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/falconx/entities/reports/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetSampleV2(self: object, ids, password_protect: bool = False) -> object: + """ Retrieves the file associated with the given ID (SHA256). """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/GetSampleV2 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/samples/entities/samples/v2?ids={}&password_protected={}'.format( + ID_LIST, + str(password_protect) + ) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DeleteSampleV2(self: object, ids) -> dict: + """ Removes a sample, including file, meta and submissions from the collection. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/DeleteSampleV2 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/samples/entities/samples/v2?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QuerySampleV1(self: object, ids) -> dict: + """ Retrieves a list with sha256 of samples that exist and customer has rights to access them, + maximum number of accepted items is 200. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/DeleteSampleV2 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/samples/queries/samples/GET/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/firewall_management.py b/src/falconpy/firewall_management.py new file mode 100644 index 00000000..eca5ce47 --- /dev/null +++ b/src/falconpy/firewall_management.py @@ -0,0 +1,369 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +firewall_management - CrowdStrike Falcon Firewall Management API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Firewall_Management(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def aggregate_events(self: object, body: dict) -> dict: + """ Aggregate events for customer. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_events + FULL_URL = self.base_url+'/fwmgr/aggregates/events/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def aggregate_policy_rules(self: object, body: dict) -> dict: + """ Aggregate rules within a policy for customer. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_policy_rules + FULL_URL = self.base_url+'/fwmgr/aggregates/policy-rules/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def aggregate_rule_groups(self: object, body: dict) -> dict: + """ Aggregate rule groups for customer. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_rule_groups + FULL_URL = self.base_url+'/fwmgr/aggregates/rule-groups/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def aggregate_rules(self: object, body: dict) -> dict: + """ Aggregate rules for customer. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/aggregate_rules + FULL_URL = self.base_url+'/fwmgr/aggregates/rules/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_events(self: object, ids) -> dict: + """ Get events entities by ID and optionally version. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_events + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/events/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_firewall_fields(self: object, ids) -> dict: + """ Get the firewall field specifications by ID. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_firewall_fields + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/firewall-fields/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_platforms(self: object, ids) -> dict: + """ Get platforms by ID, e.g., windows or mac or droid. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_platforms + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/platforms/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_policy_containers(self: object, ids) -> dict: + """ Get policy container entities by policy ID. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_policy_containers + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/policies/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + # TODO: Update dynamic documentation to handle the cs_username parameter + def update_policy_container(self: object, body: dict, cs_username: str) -> dict: + """ Update an identified policy container. """ + # [PUT] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/update_policy_container + FULL_URL = self.base_url+'/fwmgr/entities/policies/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + BODY = body + returned = service_request(caller=self, + method="PUT", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rule_groups(self: object, ids) -> dict: + """ Get rule group entities by ID. These groups do not contain their rule entites, + just the rule IDs in precedence order. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_rule_groups + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def create_rule_group(self: object, body: dict, cs_username: str, parameters: dict = None) -> dict: + """ Create new rule group on a platform for a customer with a name and description, and return the ID. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/create_rule_group + FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + if parameters is None: + parameters = {} + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def delete_rule_groups(self: object, ids, cs_username: str, parameters: dict = None) -> dict: + """ Delete rule group entities by ID. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox/QueryReports + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def update_rule_group(self: object, body: dict, cs_username: str, parameters: dict = None) -> dict: + """ Update name, description, or enabled status of a rule group, or create, edit, delete, or reorder rules. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/update_rule_group + FULL_URL = self.base_url+'/fwmgr/entities/rule-groups/v1' + HEADERS = self.headers + HEADERS['X-CS-USERNAME'] = cs_username + if parameters is None: + parameters = {} + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def get_rules(self: object, ids) -> dict: + """ Get rule entities by ID (64-bit unsigned int as decimal string) or Family ID (32-character hexadecimal string). """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/get_rules + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/fwmgr/entities/rules/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_events(self: object, parameters: dict = None) -> dict: + """ Find all event IDs matching the query with filter. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_events + FULL_URL = self.base_url+'/fwmgr/queries/events/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_firewall_fields(self: object, parameters: dict = None) -> dict: + """ Get the firewall field specification IDs for the provided platform. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_firewall_fields + FULL_URL = self.base_url+'/fwmgr/queries/firewall-fields/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_platforms(self: object, parameters: dict = None) -> dict: + """ Get the list of platform names. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_platforms + FULL_URL = self.base_url+'/fwmgr/queries/platforms/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_policy_rules(self: object, parameters: dict = None) -> dict: + """ Find all firewall rule IDs matching the query with filter, and return them in precedence order. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_policy_rules + FULL_URL = self.base_url+'/fwmgr/queries/policy-rules/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_rule_groups(self: object, parameters: dict = None) -> dict: + """ Find all rule group IDs matching the query with filter. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_rule_groups + FULL_URL = self.base_url+'/fwmgr/queries/rule-groups/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def query_rules(self: object, parameters: dict = None) -> dict: + """ Find all rule IDs matching the query with filter. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management/query_rule_groups + FULL_URL = self.base_url+'/fwmgr/queries/rules/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/firewall_policies.py b/src/falconpy/firewall_policies.py new file mode 100644 index 00000000..9d74ce60 --- /dev/null +++ b/src/falconpy/firewall_policies.py @@ -0,0 +1,228 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +firewall_policies - CrowdStrike Falcon Firewall Policy API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request, generate_error_result +from ._service_class import ServiceClass + + +class Firewall_Policies(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def queryCombinedFirewallPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Firewall Policy in your environment by providing an FQL filter + and paging details. Returns a set of host details which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /firewall-policies/queryCombinedFirewallPolicyMembers + FULL_URL = self.base_url+'/policy/combined/firewall-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedFirewallPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Firewall Policies in your environment by providing an FQL filter and paging details. + Returns a set of Firewall Policies which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryCombinedFirewallPolicies + FULL_URL = self.base_url+'/policy/combined/firewall/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def performFirewallPoliciesAction(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Perform the specified action on the Firewall Policies specified in the request. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /firewall-policies/performFirewallPoliciesAction + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + ALLOWED_ACTIONS = ['add-host-group', 'disable', 'enable', 'remove-host-group'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/policy/entities/firewall-actions/v1' + HEADERS = self.headers + BODY = body + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def setFirewallPoliciesPrecedence(self: object, body: dict) -> dict: + """ Sets the precedence of Firewall Policies based on the order of IDs specified in the request. + The first ID specified will have the highest precedence and the last ID specified will have the lowest. + You must specify all non-Default Policies for a platform when updating precedence. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /firewall-policies/setFirewallPoliciesPrecedence + FULL_URL = self.base_url+'/policy/entities/firewall-precedence/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def getFirewallPolicies(self: object, ids) -> dict: + """ Retrieve a set of Firewall Policies by specifying their IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/getFirewallPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/firewall/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createFirewallPolicies(self: object, body: dict, parameters: dict = None) -> dict: + """ Create Firewall Policies by specifying details about the policy to create. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/createFirewallPolicies + FULL_URL = self.base_url+'/policy/entities/firewall/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def deleteFirewallPolicies(self: object, ids) -> dict: + """ Delete a set of Firewall Policies by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/deleteFirewallPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/firewall/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updateFirewallPolicies(self: object, body: dict) -> dict: + """ Update Firewall Policies by specifying the ID of the policy and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/updateFirewallPolicies + FULL_URL = self.base_url+'/policy/entities/firewall/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryFirewallPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Firewall Policy in your environment by providing an FQL filter and + paging details. Returns a set of Agent IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryFirewallPolicyMembers + FULL_URL = self.base_url+'/policy/queries/firewall-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryFirewallPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Firewall Policies in your environment by providing an FQL filter and paging details. + Returns a set of Firewall Policy IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies/queryFirewallPolicies + FULL_URL = self.base_url+'/policy/queries/firewall/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/host_group.py b/src/falconpy/host_group.py new file mode 100644 index 00000000..7575de05 --- /dev/null +++ b/src/falconpy/host_group.py @@ -0,0 +1,203 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +host_groups - CrowdStrike Falcon Host Groups API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request, generate_error_result +from ._service_class import ServiceClass + + +class Host_Group(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def queryCombinedGroupMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Host Group in your environment by providing an FQL filter + and paging details. Returns a set of host details which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryCombinedGroupMembers + FULL_URL = self.base_url+'/devices/combined/host-group-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedHostGroups(self: object, parameters: dict = None) -> dict: + """ Search for Host Groups in your environment by providing an FQL filter and + paging details. Returns a set of Host Groups which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryCombinedHostGroups + FULL_URL = self.base_url+'/devices/combined/host-groups/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def performGroupAction(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Perform the specified action on the Host Groups specified in the request. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/performGroupAction + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + ALLOWED_ACTIONS = ['add-hosts', 'remove-hosts'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/devices/entities/host-group-actions/v1' + HEADERS = self.headers + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def getHostGroups(self: object, ids) -> dict: + """ Retrieve a set of Host Groups by specifying their IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/getHostGroups + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/devices/entities/host-groups/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createHostGroups(self: object, body: dict) -> dict: + """ Create Host Groups by specifying details about the group to create. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/createHostGroups + FULL_URL = self.base_url+'/devices/entities/host-groups/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def deleteHostGroups(self: object, ids) -> dict: + """ Delete a set of Host Groups by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/deleteHostGroups + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/devices/entities/host-groups/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updateHostGroups(self: object, body: dict) -> dict: + """ Update Host Groups by specifying the ID of the group and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/updateHostGroups + FULL_URL = self.base_url+'/devices/entities/host-groups/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryGroupMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Host Group in your environment by providing an FQL filter + and paging details. Returns a set of Agent IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryGroupMembers + FULL_URL = self.base_url+'/devices/queries/host-group-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryHostGroups(self: object, parameters: dict = None) -> dict: + """ Search for Host Groups in your environment by providing an FQL filter and + paging details. Returns a set of Host Group IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group/queryHostGroups + FULL_URL = self.base_url+'/devices/queries/host-groups/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/hosts.py b/src/falconpy/hosts.py new file mode 100644 index 00000000..1ff369cf --- /dev/null +++ b/src/falconpy/hosts.py @@ -0,0 +1,177 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +hosts - CrowdStrike Falcon Hosts API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list, generate_error_result +from ._service_class import ServiceClass + + +class Hosts(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def PerformActionV2(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Take various actions on the hosts in your environment. + Contain or lift containment on a host. Delete or restore a host. + """ + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/PerformActionV2 + ALLOWED_ACTIONS = ['contain', 'lift_containment', 'hide_host', 'unhide_host'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/devices/entities/devices-actions/v2' + HEADERS = self.headers + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def UpdateDeviceTags(self: object, action_name: str, ids: list or str, tags: list or str) -> dict: + """ + allows for tagging hosts. If the tags are empty + """ + ALLOWED_ACTIONS = ["add", "remove"] + # validate action is allowed AND tags is "something" + if action_name.lower() in ALLOWED_ACTIONS and tags is not None: + FULL_URL = self.base_url + '/devices/entities/devices/tags/v1' + HEADERS = self.headers + # convert ids/tags to be a list object if not already + if isinstance(ids, str): + ids = ids.split(",") + if isinstance(tags, str): + tags = tags.split(",") + # tags must start with FalconGroupingTags, users probably won't know this so add it for them + patch_tag = [] + for tag in tags: + if tag.startswith("FalconGroupingTags/"): + patch_tag.append(tag) + else: + tag_name = "FalconGroupingTags/" + tag + patch_tag.append(tag_name) + BODY = { + "action": action_name, + "device_ids": ids, + "tags": patch_tag + } + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + return returned + + def GetDeviceDetails(self: object, ids) -> dict: + """ Get details on one or more hosts by providing agent IDs (AID). + You can get a host's agent IDs (AIDs) from the /devices/queries/devices/v1 endpoint, + the Falcon console or the Streaming API. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/GetDeviceDetails + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/devices/entities/devices/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryHiddenDevices(self: object, parameters: dict = None) -> dict: + """ Perform the specified action on the Prevention Policies specified in the request. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/QueryHiddenDevices + FULL_URL = self.base_url+'/devices/queries/devices-hidden/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryDevicesByFilterScroll(self: object, parameters: dict = None) -> dict: + """ Perform the specified action on the Prevention Policies specified in the request. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/QueryDevicesByFilterScroll + FULL_URL = self.base_url+'/devices/queries/devices-scroll/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryDevicesByFilter(self: object, parameters: dict = None) -> dict: + """ Search for hosts in your environment by platform, hostname, IP, and other criteria. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/hosts/QueryDevicesByFilter + FULL_URL = self.base_url+'/devices/queries/devices/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/incidents.py b/src/falconpy/incidents.py new file mode 100644 index 00000000..a7be5a91 --- /dev/null +++ b/src/falconpy/incidents.py @@ -0,0 +1,143 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +incidents - CrowdStrike Falcon Incidents API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request +from ._service_class import ServiceClass + + +class Incidents(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def CrowdScore(self: object, parameters: dict = None) -> dict: + """ Query environment wide CrowdScore and return the entity data. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/CrowdScore + FULL_URL = self.base_url+'/incidents/combined/crowdscores/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetBehaviors(self: object, body: dict) -> dict: + """ Get details on behaviors by providing behavior IDs. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/GetBehaviors + FULL_URL = self.base_url+'/incidents/entities/behaviors/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def PerformIncidentAction(self: object, body: dict) -> dict: + """ Perform a set of actions on one or more incidents, such as + adding tags or comments or updating the incident name or description. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/PerformIncidentAction + FULL_URL = self.base_url+'/incidents/entities/incident-actions/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIncidents(self: object, body: dict) -> dict: + """ Get details on incidents by providing incident IDs. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/GetIncidents + FULL_URL = self.base_url+'/incidents/entities/incidents/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryBehaviors(self: object, parameters: dict = None) -> dict: + """ Search for behaviors by providing an FQL filter, sorting, and paging details. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/QueryBehaviors + FULL_URL = self.base_url+'/incidents/queries/behaviors/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIncidents(self: object, parameters: dict = None) -> dict: + """ Search for incidents by providing an FQL filter, sorting, and paging details. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/incidents/QueryIncidents + FULL_URL = self.base_url+'/incidents/queries/incidents/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/intel.py b/src/falconpy/intel.py new file mode 100644 index 00000000..5be22e40 --- /dev/null +++ b/src/falconpy/intel.py @@ -0,0 +1,274 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +host_groups - CrowdStrike Falcon Threat Intelligence API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Intel(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def QueryIntelActorEntities(self: object, parameters: dict = None) -> dict: + """ Get info about actors that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelActorEntities + FULL_URL = self.base_url+'/intel/combined/actors/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelIndicatorEntities(self: object, parameters: dict = None) -> dict: + """ Get info about indicators that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelIndicatorEntities + FULL_URL = self.base_url+'/intel/combined/indicators/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelReportEntities(self: object, parameters: dict = None) -> dict: + """ Get info about reports that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportEntities + FULL_URL = self.base_url+'/intel/combined/reports/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelActorEntities(self: object, ids, parameters: dict = None) -> dict: + """ Retrieve specific actors using their actor IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelActorEntities + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/intel/entities/actors/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelIndicatorEntities(self: object, body: dict) -> dict: + """ Retrieve specific indicators using their indicator IDs. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelIndicatorEntities + FULL_URL = self.base_url+'/intel/entities/indicators/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelReportPDF(self: object, parameters: dict) -> dict: + """ Return a Report PDF attachment. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelReportPDF + FULL_URL = self.base_url+'/intel/entities/report-files/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelReportEntities(self: object, ids, parameters: dict = None) -> dict: + """ Retrieve specific reports using their report IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelReportEntities + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/intel/entities/reports/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelRuleFile(self: object, parameters: dict) -> dict: + # There is an optional header you can see Accept to choose the result format. See Swagger. + """ Download earlier rule sets. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelRuleFile + FULL_URL = self.base_url+'/intel/entities/rules-files/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetLatestIntelRuleFile(self: object, parameters: dict) -> dict: + # There is an optional header you can see Accept to choose the result format. See Swagger. + """ Download the latest rule set. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetLatestIntelRuleFile + FULL_URL = self.base_url+'/intel/entities/rules-latest-files/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIntelRuleEntities(self: object, ids) -> dict: + """ Retrieve details for rule sets for the specified ids. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/GetIntelRuleEntities + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/intel/entities/rules/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelActorIds(self: object, parameters: dict = None) -> dict: + """ Get actor IDs that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelActorIds + FULL_URL = self.base_url+'/intel/queries/actors/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelIndicatorIds(self: object, parameters: dict = None) -> dict: + """ Get indicators IDs that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelIndicatorIds + FULL_URL = self.base_url+'/intel/queries/indicators/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelReportIds(self: object, parameters: dict = None) -> dict: + """ Get report IDs that match provided FQL filters. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportIds + FULL_URL = self.base_url+'/intel/queries/reports/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIntelRuleIds(self: object, parameters: dict) -> dict: + """ Search for rule IDs that match provided filter criteria. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/intel/QueryIntelReportIds + FULL_URL = self.base_url+'/intel/queries/rules/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/iocs.py b/src/falconpy/iocs.py new file mode 100644 index 00000000..9ab40139 --- /dev/null +++ b/src/falconpy/iocs.py @@ -0,0 +1,185 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Indicators of Compromise API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Iocs(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def DevicesCount(self: object, parameters: dict) -> dict: + """ Number of hosts in your customer account that have observed a given custom IOC. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DevicesCount + FULL_URL = self.base_url+'/indicators/aggregates/devices-count/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetIOC(self: object, parameters: dict) -> dict: + """ Get an IOC by providing a type and value. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/GetIOC + FULL_URL = self.base_url+'/indicators/entities/iocs/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def CreateIOC(self: object, body: dict) -> dict: + """ Create a new IOC. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/CreateIOC + FULL_URL = self.base_url+'/indicators/entities/iocs/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DeleteIOC(self: object, parameters: dict) -> dict: + """ Delete an IOC by providing a type and value. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DeleteIOC + FULL_URL = self.base_url+'/indicators/entities/iocs/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def UpdateIOC(self: object, parameters: dict, body: dict) -> dict: + """ Update an IOC by providing a type and value. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/UpdateIOC + FULL_URL = self.base_url+'/indicators/entities/iocs/v1' + HEADERS = self.headers + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DevicesRanOn(self: object, parameters: dict) -> dict: + """ Find hosts that have observed a given custom IOC. + For details about those hosts, use the hosts API interface. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/DevicesRanOn + FULL_URL = self.base_url+'/indicators/queries/devices/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QueryIOCs(self: object, parameters: dict = None) -> dict: + """ Search the custom IOCs in your customer account. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/QueryIOCs + FULL_URL = self.base_url+'/indicators/queries/iocs/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def ProcessesRanOn(self: object, parameters: dict) -> dict: + """ Search for processes associated with a custom IOC. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/QueryIOCs + FULL_URL = self.base_url+'/indicators/queries/processes/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def entities_processes(self: object, ids) -> dict: + """ For the provided ProcessID retrieve the process details. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/iocs/entities_processes + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/processes/entities/processes/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/oauth2.py b/src/falconpy/oauth2.py new file mode 100644 index 00000000..4529978c --- /dev/null +++ b/src/falconpy/oauth2.py @@ -0,0 +1,95 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +oauth2 - Falcon OAuth2 Authentication API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +import time +from ._util import perform_request, generate_b64cred + + +class OAuth2: + """ To create an instance of this class, you must pass a properly formatted JSON object containing your falcon + client_id and falcon client_secret for the key you wish to use to connect to the API. + + Example: + { + "client_id": FALCON_CLIENT_ID, + "client_secret": FALCON_CLIENT_SECRET + } + """ + + def __init__(self: object, creds: dict, base_url: str = "https://api.crowdstrike.com", ssl_verify: bool = True): + """ Initializes the base class by ingesting credentials, the base URL, and SSL verification options. """ + self.creds = creds + self.base_url = base_url + self.ssl_verify = ssl_verify + self.token_expiration = 0 + self.token_renew_window = 20 + self.token_time = time.time() + self.token_expired = lambda: True if ( + time.time() - self.token_time + ) >= ( + self.token_expiration - self.token_renew_window + ) else False + + self.authenticated = lambda: False if self.token_expired() else True + + def token(self: object) -> dict: + """ Generates an authorization token. """ + FULL_URL = self.base_url+'/oauth2/token' + HEADERS = {} + DATA = { + 'client_id': self.creds['client_id'], + 'client_secret': self.creds['client_secret'] + } + if "member_cid" in self.creds: + DATA["member_cid"] = self.creds["member_cid"] + returned = perform_request(method="POST", endpoint=FULL_URL, data=DATA, headers=HEADERS, verify=self.ssl_verify) + if returned["status_code"] == 201: + self.token_expiration = returned["body"]["expires_in"] + self.token_time = time.time() + + return returned + + def revoke(self: object, token: str) -> dict: + """ Revokes the specified authorization token. """ + FULL_URL = self.base_url+'/oauth2/revoke' + HEADERS = {'Authorization': 'basic {}'.format(generate_b64cred(self.creds["client_id"], self.creds["client_secret"]))} + DATA = {'token': '{}'.format(token)} + returned = perform_request(method="POST", endpoint=FULL_URL, data=DATA, headers=HEADERS, verify=self.ssl_verify) + self.token_expiration = 0 + + return returned diff --git a/src/falconpy/prevention_policy.py b/src/falconpy/prevention_policy.py new file mode 100644 index 00000000..38cc1107 --- /dev/null +++ b/src/falconpy/prevention_policy.py @@ -0,0 +1,226 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Prevention Policy API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request, generate_error_result +from ._service_class import ServiceClass + + +class Prevention_Policy(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def queryCombinedPreventionPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Prevention Policy in your environment by providing an FQL filter + and paging details. Returns a set of host details which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /prevention-policies/queryCombinedPreventionPolicyMembers + FULL_URL = self.base_url+'/policy/combined/prevention-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedPreventionPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Prevention Policies in your environment by providing an FQL filter and + paging details. Returns a set of Prevention Policies which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /prevention-policies/queryCombinedPreventionPolicies + FULL_URL = self.base_url+'/policy/combined/prevention/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def performPreventionPoliciesAction(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Perform the specified action on the Prevention Policies specified in the request. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /prevention-policies/performPreventionPoliciesAction + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + ALLOWED_ACTIONS = ['add-host-group', 'disable', 'enable', 'remove-host-group'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/policy/entities/prevention-actions/v1' + HEADERS = self.headers + PARAMS = parameters + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def setPreventionPoliciesPrecedence(self: object, body: dict) -> dict: + """ Sets the precedence of Prevention Policies based on the order of IDs specified in the request. + The first ID specified will have the highest precedence and the last ID specified will have the lowest. + You must specify all non-Default Policies for a platform when updating precedence. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /prevention-policies/setPreventionPoliciesPrecedence + FULL_URL = self.base_url+'/policy/entities/prevention-precedence/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def getPreventionPolicies(self: object, ids) -> dict: + """ Retrieve a set of Prevention Policies by specifying their IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/getPreventionPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/prevention/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createPreventionPolicies(self: object, body: dict) -> dict: + """ Create Prevention Policies by specifying details about the policy to create. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/createPreventionPolicies + FULL_URL = self.base_url+'/policy/entities/prevention/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def deletePreventionPolicies(self: object, ids) -> dict: + """ Delete a set of Prevention Policies by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/deletePreventionPolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/prevention/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updatePreventionPolicies(self: object, body: dict) -> dict: + """ Update Prevention Policies by specifying the ID of the policy and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/updatePreventionPolicies + FULL_URL = self.base_url+'/policy/entities/prevention/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryPreventionPolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Prevention Policy in your environment by providing an FQL filter + and paging details. Returns a set of Agent IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /prevention-policies/queryPreventionPolicyMembers + FULL_URL = self.base_url+'/policy/queries/prevention-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryPreventionPolicies(self: object, parameters: dict = None) -> dict: + """ Search for Prevention Policies in your environment by providing an FQL filter + and paging details. Returns a set of Prevention Policy IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/prevention-policies/queryPreventionPolicies + FULL_URL = self.base_url+'/policy/queries/prevention/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/quick_scan.py b/src/falconpy/quick_scan.py new file mode 100644 index 00000000..5cd056df --- /dev/null +++ b/src/falconpy/quick_scan.py @@ -0,0 +1,110 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +quick_scan - Falcon Quick Scan API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list +from ._service_class import ServiceClass + + +class Quick_Scan(ServiceClass): + """The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetScansAggregates(self: object, body: dict) -> dict: + """Get scans aggregations as specified via json in request body.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan/GetScansAggregates + FULL_URL = self.base_url+"/scanner/aggregates/scans/GET/v1" + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetScans(self: object, ids) -> dict: + """Check the status of a volume scan. Time required for analysis increases with the number + of samples in a volume but usually it should take less than 1 minute + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan/GetScans + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+"/scanner/entities/scans/v1?ids={}".format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def ScanSamples(self: object, body: dict) -> dict: + """Get scans aggregations as specified via json in request body.""" + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan/ScanSamples + FULL_URL = self.base_url+"/scanner/entities/scans/v1" + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def QuerySubmissionsMixin0(self: object, parameters: dict = None) -> dict: + """Find IDs for submitted scans by providing an FQL filter and paging details. + Returns a set of volume IDs that match your criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/quick-scan/QuerySubmissionsMixin0 + FULL_URL = self.base_url+"/scanner/queries/scans/v1" + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/real_time_response.py b/src/falconpy/real_time_response.py new file mode 100644 index 00000000..79e7b7c9 --- /dev/null +++ b/src/falconpy/real_time_response.py @@ -0,0 +1,390 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Real Time Response API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Real_Time_Response(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def RTR_AggregateSessions(self: object, body: dict) -> dict: + """ Get aggregates on session data. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_AggregateSessions + FULL_URL = self.base_url+'/real-time-response/aggregates/sessions/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchActiveResponderCmd(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch executes a RTR active-responder command across the hosts mapped to the given batch ID. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd + FULL_URL = self.base_url+'/real-time-response/combined/batch-active-responder-command/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchCmd(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch executes a RTR read-only command across the hosts mapped to the given batch ID. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd + FULL_URL = self.base_url+'/real-time-response/combined/batch-command/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchGetCmdStatus(self: object, parameters: dict) -> dict: + """ Retrieves the status of the specified batch get command. + Will return successful files when they are finished processing. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchGetCmdStatus + FULL_URL = self.base_url+'/real-time-response/combined/batch-get-command/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchGetCmd(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch executes `get` command across hosts to retrieve files. + After this call is made `/real-time-response/combined/get-command-status/v1` is used to query for the results. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchActiveResponderCmd + FULL_URL = self.base_url+'/real-time-response/combined/batch-get-command/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchInitSessions(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch initialize a RTR session on multiple hosts. + Before any RTR commands can be used, an active session is needed on the host. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchInitSessions + FULL_URL = self.base_url+'/real-time-response/combined/batch-init-session/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def BatchRefreshSessions(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch refresh a RTR session on multiple hosts. RTR sessions will expire after 10 minutes unless refreshed. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchRefreshSessions + FULL_URL = self.base_url+'/real-time-response/combined/batch-refresh-session/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_CheckActiveResponderCommandStatus(self: object, parameters: dict) -> dict: + """ Get status of an executed active-responder command on a single host. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /real-time-response/RTR_CheckActiveResponderCommandStatus + FULL_URL = self.base_url+'/real-time-response/entities/active-responder-command/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ExecuteActiveResponderCommand(self: object, body: dict) -> dict: + """ Execute an active responder command on a single host. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/BatchRefreshSessions + FULL_URL = self.base_url+'/real-time-response/entities/active-responder-command/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_CheckCommandStatus(self: object, parameters: dict) -> dict: + """ Get status of an executed command on a single host. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_CheckCommandStatus + FULL_URL = self.base_url+'/real-time-response/entities/command/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ExecuteCommand(self: object, body: dict) -> dict: + """ Execute a command on a single host. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ExecuteCommand + FULL_URL = self.base_url+'/real-time-response/entities/command/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_GetExtractedFileContents(self: object, parameters: dict) -> dict: + """ Get RTR extracted file contents for specified session and sha256. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_GetExtractedFileContents + FULL_URL = self.base_url+'/real-time-response/entities/extracted-file-contents/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListFiles(self: object, parameters: dict) -> dict: + """ Get a list of files for the specified RTR session. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListFiles + FULL_URL = self.base_url+'/real-time-response/entities/file/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_DeleteFile(self: object, ids, parameters: dict) -> dict: + """ Delete a RTR session file. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_DeleteFile + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/real-time-response/entities/file/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_PulseSession(self: object, body: dict) -> dict: + """ Refresh a session timeout on a single host. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_PulseSession + FULL_URL = self.base_url+'/real-time-response/entities/refresh-session/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListSessions(self: object, body: dict) -> dict: + """ Get session metadata by session id. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListSessions + FULL_URL = self.base_url+'/real-time-response/entities/sessions/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListQueuedSessions(self: object, body: dict) -> dict: + """ Get session metadata by session id. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListSessions + FULL_URL = self.base_url+'/real-time-response/entities/queued-sessions/GET/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_InitSession(self: object, body: dict) -> dict: + """ Initialize a new session with the RTR cloud. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/InitSessionMixin0 + FULL_URL = self.base_url+'/real-time-response/entities/sessions/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_DeleteSession(self: object, parameters: dict) -> dict: + """ Delete a session. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_DeleteSession + FULL_URL = self.base_url+'/real-time-response/entities/sessions/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_DeleteQueuedSession(self: object, parameters: dict) -> dict: + """ Delete a queued session. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_DeleteSession + FULL_URL = self.base_url+'/real-time-response/entities/queued-sessions/command/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListAllSessions(self: object, parameters: dict = None) -> dict: + """ Get a list of session_ids. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response/RTR_ListAllSessions + FULL_URL = self.base_url+'/real-time-response/queries/sessions/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/real_time_response_admin.py b/src/falconpy/real_time_response_admin.py new file mode 100644 index 00000000..bc79e600 --- /dev/null +++ b/src/falconpy/real_time_response_admin.py @@ -0,0 +1,240 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Real Time Response Administration API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Real_Time_Response_Admin(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def BatchAdminCmd(self: object, body: dict, parameters: dict = None) -> dict: + """ Batch executes a RTR administrator command across the hosts mapped to the given batch ID. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/BatchAdminCmd + FULL_URL = self.base_url+'/real-time-response/combined/batch-admin-command/v1' + HEADERS = self.headers + BODY = body + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_CheckAdminCommandStatus(self: object, parameters: dict) -> dict: + """ Get status of an executed RTR administrator command on a single host. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /real-time-response-admin/RTR_CheckAdminCommandStatus + FULL_URL = self.base_url+'/real-time-response/entities/admin-command/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ExecuteAdminCommand(self: object, body: dict) -> dict: + """ Execute a RTR administrator command on a single host. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /real-time-response-admin/RTR_ExecuteAdminCommand + FULL_URL = self.base_url+'/real-time-response/entities/admin-command/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_GetPut_Files(self: object, ids) -> dict: + """ Get put-files based on the ID's given. These are used for the RTR `put` command. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_GetPut_Files + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_CreatePut_Files(self: object, data, files) -> dict: + """ Upload a new put-file to use for the RTR `put` command. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_CreatePut_Files + FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1' + HEADERS = self.headers + HEADERS['Content-Type'] = 'multipart/form-data' + DATA = data + FILES = files + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + data=DATA, + files=FILES, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_DeletePut_Files(self: object, ids) -> dict: + """ Delete a put-file based on the ID given. Can only delete one file at a time. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_DeletePut_Files + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/real-time-response/entities/put-files/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_GetScripts(self: object, ids) -> dict: + """ Get custom-scripts based on the ID's given. These are used for the RTR `runscript` command. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_GetScripts + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_CreateScripts(self: object, data, files) -> dict: + """ Upload a new custom-script to use for the RTR `runscript` command. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_CreateScripts + FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' + HEADERS = self.headers + HEADERS['Content-Type'] = 'multipart/form-data' + DATA = data + FILES = files + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + data=DATA, + files=FILES, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_DeleteScripts(self: object, ids) -> dict: + """ Delete a custom-script based on the ID given. Can only delete one script at a time. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_DeleteScripts + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_UpdateScripts(self: object, data, files) -> dict: + """ Upload a new scripts to replace an existing one. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_UpdateScripts + FULL_URL = self.base_url+'/real-time-response/entities/scripts/v1' + HEADERS = self.headers + HEADERS['Content-Type'] = 'multipart/form-data' + DATA = data + FILES = files + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + data=DATA, + files=FILES, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListPut_Files(self: object, parameters: dict = None) -> dict: + """ Get a list of put-file ID's that are available to the user for the `put` command. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_ListPut_Files + FULL_URL = self.base_url+'/real-time-response/queries/put-files/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RTR_ListScripts(self: object, parameters: dict = None) -> dict: + """ Get a list of custom-script ID's that are available to the user for the `runscript` command. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/real-time-response-admin/RTR_ListScripts + FULL_URL = self.base_url+'/real-time-response/queries/scripts/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/sample_uploads.py b/src/falconpy/sample_uploads.py new file mode 100644 index 00000000..fa2880fb --- /dev/null +++ b/src/falconpy/sample_uploads.py @@ -0,0 +1,101 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +sample_uploads - CrowdStrike Falcon Sample Upload API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import service_request, parse_id_list +from ._service_class import ServiceClass + + +class Sample_Uploads(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetSampleV3(self: object, ids: list or str, parameters: dict = None) -> object: + """ Retrieves the file associated with the given ID (SHA256)""" + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sample-uploads/GetSampleV3 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/samples/entities/samples/v3?ids={}'.format(ID_LIST) + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + return returned + + def UploadSampleV3(self: object, + file_data: object, + body: dict = None, + file_name: str = "", + parameters: dict = None) -> dict: + """ Upload a file for further cloud analysis. After uploading, call the specific analysis API endpoint. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sample-uploads/UploadSampleV3 + FULL_URL = self.base_url+f"/samples/entities/samples/v3?file_name={str(file_name)}" + HEADERS = self.headers + HEADERS["Content-Type"] = "application/octet-stream" + if parameters is None: + parameters = {} + PARAMS = parameters + DATA = file_data + if body is None: + body = {} + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + data=DATA, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DeleteSampleV3(self: object, ids: str or list) -> dict: + """ Removes a sample, including file, meta and submissions from the collection. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sample-uploads/DeleteSampleV3 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/samples/entities/samples/v3?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, method="DELETE", endpoint=FULL_URL, headers=HEADERS, verify=self.ssl_verify) + + return returned diff --git a/src/falconpy/sensor_download.py b/src/falconpy/sensor_download.py new file mode 100644 index 00000000..1f9d05d4 --- /dev/null +++ b/src/falconpy/sensor_download.py @@ -0,0 +1,139 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +sensor_download - Falcon Sensor Download API Interface Class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +import os +from ._util import service_request, parse_id_list, generate_ok_result +from ._service_class import ServiceClass + + +class Sensor_Download(ServiceClass): + """The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetCombinedSensorInstallersByQuery(self: object, parameters: dict = None) -> dict: + """ + Retrieve all metadata for installers from provided query + """ + FULL_URL = self.base_url+'/sensors/combined/installers/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DownloadSensorInstallerById(self: object, + parameters: dict, + file_name: str = None, + download_path: str = None + ) -> object: + """ + Download the sensor by the sha256 id, into the specified directory. + The path will be created for the user if it does not already exist + """ + FULL_URL = self.base_url+"/sensors/entities/download-installer/v1" + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + params=PARAMS, + verify=self.ssl_verify + ) + if file_name and download_path and isinstance(returned, bytes): + os.makedirs(download_path, exist_ok=True) + # write the newly downloaded sensor into the aforementioned directory with provided file name + with open(os.path.join(download_path, file_name), "wb") as sensor: + sensor.write(returned) + returned = generate_ok_result(message="Download successful") + return returned + + def GetSensorInstallersEntities(self: object, ids: list or str) -> object: + """ + For a given list of SHA256's, retrieve the metadata for each installer + such as the release_date and version among other fields + """ + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/sensors/entities/installers/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetSensorInstallersCCIDByQuery(self: object) -> dict: + """ + Retrieve the CID for the current oauth environment + """ + FULL_URL = self.base_url+'/sensors/queries/installers/ccid/v1' + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetSensorInstallersByQuery(self: object, parameters: dict = None) -> dict: + """ + Retrieve a list of SHA256 for installers based on the filter + """ + FULL_URL = self.base_url+'/sensors/queries/installers/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/sensor_update_policy.py b/src/falconpy/sensor_update_policy.py new file mode 100644 index 00000000..26fa9f08 --- /dev/null +++ b/src/falconpy/sensor_update_policy.py @@ -0,0 +1,339 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Sensor Policy Management API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request, generate_error_result +from ._service_class import ServiceClass + + +class Sensor_Update_Policy(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def revealUninstallToken(self: object, body: dict) -> dict: + """ Reveals an uninstall token for a specific device. + To retrieve the bulk maintenance token pass the value 'MAINTENANCE' as the value for 'device_id'. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/revealUninstallToken + FULL_URL = self.base_url+'/policy/combined/reveal-uninstall-token/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedSensorUpdateBuilds(self: object, parameters: dict = None) -> dict: + """ Retrieve available builds for use with Sensor Update Policies. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/queryCombinedSensorUpdateBuilds + FULL_URL = self.base_url+'/policy/combined/sensor-update-builds/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedSensorUpdatePolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Sensor Update Policy in your environment by providing an FQL + filter and paging details. Returns a set of host details which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/queryCombinedSensorUpdatePolicyMembers + FULL_URL = self.base_url+'/policy/combined/sensor-update-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedSensorUpdatePolicies(self: object, parameters: dict = None) -> dict: + """ Search for Sensor Update Policies in your environment by providing an FQL filter and paging details. + Returns a set of Sensor Update Policies which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/queryCombinedSensorUpdatePolicies + FULL_URL = self.base_url+'/policy/combined/sensor-update/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryCombinedSensorUpdatePoliciesV2(self: object, parameters: dict = None) -> dict: + """ Search for Sensor Update Policies with additional support for uninstall protection in your environment + by providing an FQL filter and paging details. + Returns a set of Sensor Update Policies which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/queryCombinedSensorUpdatePoliciesV2 + FULL_URL = self.base_url+'/policy/combined/sensor-update/v2' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def performSensorUpdatePoliciesAction(self: object, parameters: dict, body: dict, action_name: str = None) -> dict: + """ Perform the specified action on the Sensor Update Policies specified in the request. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/performSensorUpdatePoliciesAction + if "action_name" in parameters: + action_name = parameters["action_name"].lower() + ALLOWED_ACTIONS = ['add-host-group', 'disable', 'enable', 'remove-host-group'] + if action_name.lower() in ALLOWED_ACTIONS: + FULL_URL = self.base_url+'/policy/entities/sensor-update-actions/v1' + HEADERS = self.headers + BODY = body + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + else: + returned = generate_error_result("Invalid value specified for action_name parameter.") + + return returned + + def setSensorUpdatePoliciesPrecedence(self: object, body: dict) -> dict: + """ Sets the precedence of Sensor Update Policies based on the order of IDs specified in the request. + The first ID specified will have the highest precedence and the last ID specified will have the lowest. + You must specify all non-Default Policies for a platform when updating precedence. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/setSensorUpdatePoliciesPrecedence + FULL_URL = self.base_url+'/policy/entities/sensor-update-precedence/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def getSensorUpdatePolicies(self: object, ids) -> dict: + """ Retrieve a set of Sensor Update Policies by specifying their IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-update-policies/getSensorUpdatePolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/sensor-update/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createSensorUpdatePolicies(self: object, body: dict) -> dict: + """ Create Sensor Update Policies by specifying details about the policy to create. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/createSensorUpdatePolicies + FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def deleteSensorUpdatePolicies(self: object, ids) -> dict: + """ Delete a set of Sensor Update Policies by specifying their IDs. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/deleteSensorUpdatePolicies + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/sensor-update/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updateSensorUpdatePolicies(self: object, body: dict) -> dict: + """ Update Sensor Update Policies by specifying the ID of the policy and details to update. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/updateSensorUpdatePolicies + FULL_URL = self.base_url+'/policy/entities/sensor-update/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def getSensorUpdatePoliciesV2(self: object, ids) -> dict: + """ Retrieve a set of Sensor Update Policies with additional + support for uninstall protection by specifying their IDs. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/getSensorUpdatePoliciesV2 + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/policy/entities/sensor-update/v2?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def createSensorUpdatePoliciesV2(self: object, body: dict) -> dict: + """ Create Sensor Update Policies by specifying details about the + policy to create with additional support for uninstall protection. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/createSensorUpdatePoliciesV2 + FULL_URL = self.base_url+'/policy/entities/sensor-update/v2' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def updateSensorUpdatePoliciesV2(self: object, body: dict) -> dict: + """ Update Sensor Update Policies by specifying the ID of the policy + and details to update with additional support for uninstall protection. + """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/updateSensorUpdatePoliciesV2 + FULL_URL = self.base_url+'/users/entities/users/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def querySensorUpdatePolicyMembers(self: object, parameters: dict = None) -> dict: + """ Search for members of a Sensor Update Policy in your environment by providing an FQL + filter and paging details. Returns a set of Agent IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/querySensorUpdatePolicyMembers + FULL_URL = self.base_url+'/policy/queries/sensor-update-members/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def querySensorUpdatePolicies(self: object, parameters: dict = None) -> dict: + """ Search for Sensor Update Policies in your environment by providing an FQL filter and + paging details. Returns a set of Sensor Update Policy IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html# + # ... /sensor-update-policies/querySensorUpdatePolicies + FULL_URL = self.base_url+'/policy/queries/sensor-update/v1' + HEADERS = self.headers + if parameters is None: + parameters = {} + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/spotlight_vulnerabilities.py b/src/falconpy/spotlight_vulnerabilities.py new file mode 100644 index 00000000..51f14c87 --- /dev/null +++ b/src/falconpy/spotlight_vulnerabilities.py @@ -0,0 +1,76 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon Spotlight Vulnerability API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class Spotlight_Vulnerabilities(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def getVulnerabilities(self: object, ids) -> dict: + """ Get details on vulnerabilities by providing one or more IDs. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/spotlight-vulnerabilities/getVulnerabilities + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/spotlight/entities/vulnerabilities/v2?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def queryVulnerabilities(self: object, parameters: dict) -> dict: + """ Search for Vulnerabilities in your environment by providing an FQL filter + and paging details. Returns a set of Vulnerability IDs which match the filter criteria. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/spotlight-vulnerabilities/queryVulnerabilities + FULL_URL = self.base_url+'/spotlight/queries/vulnerabilities/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/src/falconpy/user_management.py b/src/falconpy/user_management.py new file mode 100644 index 00000000..fabf88b3 --- /dev/null +++ b/src/falconpy/user_management.py @@ -0,0 +1,230 @@ +""" + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +iocs - CrowdStrike Falcon User Management API interface class + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import parse_id_list, service_request +from ._service_class import ServiceClass + + +class User_Management(ServiceClass): + """ The only requirement to instantiate an instance of this class + is a valid token provided by the Falcon API SDK OAuth2 class. + """ + def GetRoles(self: object, ids) -> dict: + """ Get info about a role. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetRoles + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GrantUserRoleIds(self: object, parameters: dict, body: dict) -> dict: + """ Assign one or more roles to a user. """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GrantUserRoleIds + FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1' + HEADERS = self.headers + BODY = body + PARAMS = parameters + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RevokeUserRoleIds(self: object, ids, parameters: dict) -> dict: + """ Revoke one or more roles from a user. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RevokeUserRoleIds + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/user-roles/entities/user-roles/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetAvailableRoleIds(self: object) -> dict: + """ Show role IDs for all roles available in your customer account. + For more information on each role, provide the role ID to `/customer/entities/roles/v1`. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetAvailableRoleIds + FULL_URL = self.base_url+'/user-roles/queries/user-role-ids-by-cid/v1' + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def GetUserRoleIds(self: object, parameters: dict) -> dict: + """ Show role IDs of roles assigned to a user. For more information on each role, + provide the role ID to `/customer/entities/roles/v1`. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/GetUserRoleIds + FULL_URL = self.base_url+'/user-roles/queries/user-role-ids-by-user-uuid/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RetrieveUser(self: object, ids) -> dict: + """ Get info about a user. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUser + ID_LIST = str(parse_id_list(ids)).replace(",", "&ids=") + FULL_URL = self.base_url+'/users/entities/users/v1?ids={}'.format(ID_LIST) + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def CreateUser(self: object, body: dict) -> dict: + """ Create a new user. After creating a user, + assign one or more roles with POST /user-roles/entities/user-roles/v1. + """ + # [POST] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/CreateUser + FULL_URL = self.base_url+'/users/entities/users/v1' + HEADERS = self.headers + BODY = body + returned = service_request(caller=self, + method="POST", + endpoint=FULL_URL, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def DeleteUser(self: object, parameters: dict) -> dict: + """ Delete a user permanently. """ + # [DELETE] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/DeleteUser + FULL_URL = self.base_url+'/users/entities/users/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="DELETE", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def UpdateUser(self: object, parameters: dict, body: dict) -> dict: + """ Modify an existing user. """ + # [PATCH] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/UpdateUser + FULL_URL = self.base_url+'/users/entities/users/v1' + HEADERS = self.headers + BODY = body + PARAMS = parameters + returned = service_request(caller=self, + method="PATCH", + endpoint=FULL_URL, + params=PARAMS, + body=BODY, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RetrieveEmailsByCID(self: object) -> dict: + """ List the usernames (usually an email address) for all users in your customer account. """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveEmailsByCID + FULL_URL = self.base_url+'/users/queries/emails-by-cid/v1' + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RetrieveUserUUIDsByCID(self: object) -> dict: + """ List user IDs for all users in your customer account. + For more information on each user, provide the user ID to `/users/entities/user/v1`. + """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUserUUIDsByCID + FULL_URL = self.base_url+'/users/queries/user-uuids-by-cid/v1' + HEADERS = self.headers + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned + + def RetrieveUserUUID(self: object, parameters: dict) -> dict: + """ Get a user's ID by providing a username (usually an email address). """ + # [GET] https://assets.falcon.crowdstrike.com/support/api/swagger.html#/user-management/RetrieveUserUUID + FULL_URL = self.base_url+'/users/queries/user-uuids-by-email/v1' + HEADERS = self.headers + PARAMS = parameters + returned = service_request(caller=self, + method="GET", + endpoint=FULL_URL, + params=PARAMS, + headers=HEADERS, + verify=self.ssl_verify + ) + return returned diff --git a/falconpy/services/__init__.py b/tests/__init__.py similarity index 100% rename from falconpy/services/__init__.py rename to tests/__init__.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/coverage.svg b/tests/coverage.svg new file mode 100644 index 00000000..e5db27cd --- /dev/null +++ b/tests/coverage.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + coverage + coverage + 100% + 100% + + diff --git a/tests/test_authorization.py b/tests/test_authorization.py new file mode 100644 index 00000000..9397594c --- /dev/null +++ b/tests/test_authorization.py @@ -0,0 +1,154 @@ +# A valid CrowdStrike Falcon API key is required to run these tests. +# You can store these values in your environment (this is the preferred method). +# Example: +# export DEBUG_API_ID=CLIENT_ID_GOES_HERE +# export DEBUG_API_SECRET=CLIENT_SECRET_GOES_HERE +# +# You may also store these values locally in a configuration file. +# DO NOT SUBMIT A COMMIT OR A PR THAT INCLUDES YOUR CONFIGURATION FILE. +# API client ID & secret should be stored in tests/test.config in JSON format. +# { +# "falcon_client_id": "CLIENT_ID_GOES_HERE", +# "falcon_client_secret": "CLIENT_SECRET_GOES_HERE" +# } + +import json +import os +import sys +# Import our sibling src folder into the path +sys.path.append(os.path.abspath('src')) +# Classes to test - manually imported from our sibling folder +from falconpy import api_complete as FalconSDK +from falconpy import oauth2 as FalconAuth + + +# The TestAuthorization class tests authentication and deauthentication +# for both the Uber and Service classes. +class TestAuthorization(): + 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") + 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 = FalconSDK.APIHarness(creds={ + "client_id": self.config["falcon_client_id"], + "client_secret": self.config["falcon_client_secret"] + } + ) + self.falcon.authenticate() + if 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 = FalconAuth.OAuth2(creds={ + 'client_id': self.config["falcon_client_id"], + 'client_secret': self.config["falcon_client_secret"] + }) + + try: + self.token = self.authorization.token()['body']['access_token'] + except: + self.token = False + + if self.token: + return True + else: + return False + else: + return False + + def serviceMSSPAuth(self): + status = self.getConfig() + result = False + if status: + authorization = FalconAuth.OAuth2(creds={ + '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: + pass + + return result + + def failServiceAuth(self): + + self.authorization = FalconAuth.OAuth2(creds={ + 'client_id': "BadClientID", + 'client_secret': "BadClientSecret" + }) + self.authorization.base_url = "nowhere" + try: + self.token = self.authorization.token()['body']['access_token'] + except: + self.token = False + + self.authorization.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: + return False + + def test_uberAuth(self): + assert self.uberAuth() == True + self.uberRevoke() + + def test_uberRevoke(self): + self.uberAuth() + assert self.uberRevoke() == True + + def test_serviceAuth(self): + assert self.serviceAuth() == True + self.serviceRevoke() + + def test_serviceMSSPAuth(self): + assert self.serviceMSSPAuth() == True + + def test_serviceRevoke(self): + self.serviceAuth() + assert self.serviceRevoke() == True + + def test_failServiceAuth(self): + assert self.failServiceAuth() == True + + + diff --git a/tests/test_cloud_connect_aws.py b/tests/test_cloud_connect_aws.py new file mode 100644 index 00000000..8a79d04d --- /dev/null +++ b/tests/test_cloud_connect_aws.py @@ -0,0 +1,241 @@ +# test_cloud_connect_aws.py +# This class tests the cloud_connect_aws service class + +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 cloud_connect_aws as FalconAWS +from falconpy import oauth2 as FalconAuth +from falconpy._util import service_request + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconAWS.Cloud_Connect_AWS(access_token=auth.token) +AllowedResponses = [200, 201, 429] # Adding rate-limiting as an allowed response for now +accountPayload = { + "resources": [ + { + "rate_limit_reqs": 0, + "rate_limit_time": 0 + } + ] + } +falconWithCreds = None +falconWithObject = None + + +class TestCloudConnectAWS: + def serviceCCAWS_AuthWithCreds(self): + falconWithCreds = FalconAWS.Cloud_Connect_AWS(creds={ + 'client_id': auth.config["falcon_client_id"], + 'client_secret': auth.config["falcon_client_secret"] + }) + + return falconWithCreds.authenticated() + + def serviceCCAWS_AuthWithObject(self): + falconWithObject = FalconAWS.Cloud_Connect_AWS(auth_object=FalconAuth.OAuth2(creds={ + 'client_id': auth.config["falcon_client_id"], + 'client_secret': auth.config["falcon_client_secret"] + })) + + return falconWithObject.authenticated() + + def serviceCCAWS_RefreshToken(self): + falconWithObject = FalconAWS.Cloud_Connect_AWS(auth_object=FalconAuth.OAuth2(creds={ + 'client_id': auth.config["falcon_client_id"], + 'client_secret': auth.config["falcon_client_secret"] + })) + + if not falconWithObject.token_expired(): + falconWithObject.auth_object.token_expiration = 0 # Forcibly expire the current token + if falconWithObject.QueryAWSAccounts(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + else: + return False + + def serviceCCAWS_InvalidPayloads(self): + result = True + falconWithObject = FalconAWS.Cloud_Connect_AWS(auth_object=FalconAuth.OAuth2(creds={ + 'client_id': auth.config["falcon_client_id"], + 'client_secret': auth.config["falcon_client_secret"] + })) + if falconWithObject.QueryAWSAccounts(parameters={"limite": 1})["status_code"] != 500: + result = False + + if falconWithObject.QueryAWSAccounts(parameters={"limit": "1"})["status_code"] != 500: + result = False + + if falconWithObject.UpdateAWSAccounts(body={"resources": "I'm gonna go Boom!"})["status_code"] != 500: + result = False + + return result + + def serviceCCAWS_GetAWSSettings(self): + if falcon.GetAWSSettings()["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_QueryAWSAccounts(self): + if falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_GetAWSAccounts(self): + if falcon.GetAWSAccounts(ids=falcon.QueryAWSAccounts(parameters={"limit": 1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_GetAWSAccountsUsingList(self): + liste = [] + for thing in falcon.QueryAWSAccounts(parameters={"limit": 2})["body"]["resources"]: + liste.append(thing["id"]) + if falcon.GetAWSAccounts(ids=liste)["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_AccountUpdate(self): + account = falcon.QueryAWSAccounts(parameters={"limit": 1})["body"]["resources"][0] + accountPayload["resources"][0]["cloudtrail_bucket_owner_id"] = account["cloudtrail_bucket_owner_id"] + accountPayload["resources"][0]["cloudtrail_bucket_region"] = account["cloudtrail_bucket_region"] + orig_external_id = account["external_id"] + accountPayload["resources"][0]["external_id"] = "UnitTesting" + accountPayload["resources"][0]["iam_role_arn"] = account["iam_role_arn"] + accountPayload["resources"][0]["id"] = account["id"] + if falcon.UpdateAWSAccounts(body=accountPayload)["status_code"] in AllowedResponses: + accountPayload["resources"][0]["external_id"] = orig_external_id + return True + else: + accountPayload["resources"][0]["external_id"] = orig_external_id + return False + + def serviceCCAWS_AccountDelete(self): + if falcon.DeleteAWSAccounts(ids=accountPayload["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_AccountRegister(self): + if falcon.ProvisionAWSAccounts(body=accountPayload)["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_VerifyAWSAccountAccess(self): + if falcon.VerifyAWSAccountAccess(ids=falcon.QueryAWSAccounts(parameters={"limit":1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_QueryAWSAccountsForIDs(self): + if falcon.QueryAWSAccountsForIDs(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_ForceAttributeError(self): + FULL_URL = falcon.base_url+'/cloud-connect-aws/combined/accounts/v1' + if service_request(caller=self, + method="GET", + endpoint=FULL_URL, + headers=falcon.headers, + verify=falcon.ssl_verify + )["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCCAWS_GenerateErrors(self): + # Garf the base_url so we force 500s for each method to cover all remaining code paths + falcon.base_url = "nowhere" + errorChecks = True + if falcon.QueryAWSAccounts()["status_code"] != 500: + errorChecks = False + if falcon.QueryAWSAccountsForIDs()["status_code"] != 500: + errorChecks = False + if falcon.GetAWSSettings()["status_code"] != 500: + errorChecks = False + if falcon.GetAWSAccounts(ids="1234567890")["status_code"] != 500: + errorChecks = False + if falcon.UpdateAWSAccounts(body={})["status_code"] != 500: + errorChecks = False + if falcon.DeleteAWSAccounts(ids="1234567890")["status_code"] != 500: + errorChecks = False + if falcon.ProvisionAWSAccounts(body={})["status_code"] != 500: + errorChecks = False + if falcon.CreateOrUpdateAWSSettings(body={})["status_code"] != 500: + errorChecks = False + if falcon.VerifyAWSAccountAccess(ids="1234567890")["status_code"] != 500: + errorChecks = False + + return errorChecks + + def test_GetAWSSettings(self): + assert self.serviceCCAWS_GetAWSSettings() == True + + def test_QueryAWSAccounts(self): + assert self.serviceCCAWS_QueryAWSAccounts() == True + + @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_GetAWSAccounts(self): + assert self.serviceCCAWS_GetAWSAccounts() == True + + @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_GetAWSAccountsUsingList(self): + assert self.serviceCCAWS_GetAWSAccountsUsingList() == True + + # @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + # @pytest.mark.skipif(sys.version_info.minor < 9, reason="Frequency reduced due to potential race condition") + # def test_VerifyAWSAccountAccess(self): + # assert self.serviceCCAWS_VerifyAWSAccountAccess() == True + + @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + @pytest.mark.skipif(sys.version_info.minor < 9, reason="Frequency reduced due to potential race condition") + def test_AccountUpdate(self): + assert self.serviceCCAWS_AccountUpdate() == True + + @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + @pytest.mark.skipif(sys.version_info.minor < 9, reason="Frequency reduced due to potential race condition") + def test_AccountDelete(self): + assert self.serviceCCAWS_AccountDelete() == True + + def test_QueryAWSAccountsForIDs(self): + assert self.serviceCCAWS_QueryAWSAccountsForIDs() == True + + @pytest.mark.skipif(falcon.QueryAWSAccounts(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + @pytest.mark.skipif(sys.version_info.minor < 9, reason="Frequency reduced due to potential race condition") + def test_AccountRegister(self): + assert self.serviceCCAWS_AccountRegister() == True + + def test_AuthWithCreds(self): + assert self.serviceCCAWS_AuthWithCreds() == True + + def test_AuthWithObject(self): + assert self.serviceCCAWS_AuthWithObject() == True + + def test_RefreshToken(self): + assert self.serviceCCAWS_RefreshToken() == True + + def test_InvalidPayloads(self): + assert self.serviceCCAWS_InvalidPayloads() == True + + def test_ForceAttributeError(self): + assert self.serviceCCAWS_ForceAttributeError() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceCCAWS_GenerateErrors() == True diff --git a/tests/test_cspm_registration.py b/tests/test_cspm_registration.py new file mode 100644 index 00000000..141c695f --- /dev/null +++ b/tests/test_cspm_registration.py @@ -0,0 +1,87 @@ +# test_cspm_registration.py +# This class tests the cspm_registration service class + +import json +import os +import sys +import datetime +import requests +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 cspm_registration as FalconCSPM + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconCSPM.CSPM_Registration(access_token=auth.token) +AllowedResponses = [200, 201, 207, 429] #Adding rate-limiting as an allowed response for now +textchars = bytearray({7,8,9,10,12,13,27} | set(range(0x20, 0x100)) - {0x7f}) +is_binary_string = lambda bytes: bool(bytes.translate(None, textchars)) + +class TestCSPMRegistration: + + def serviceCSPM_GetCSPMAwsConsoleSetupURLs(self): + if falcon.GetCSPMAwsConsoleSetupURLs()["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceCSPM_GetCSPMAwsAccountScriptsAttachment(self): + if type(falcon.GetCSPMAwsAccountScriptsAttachment()) == bytes: + return True + else: + return False + + def serviceCSPM_GetCSPMAzureUserScriptsAttachment(self): + #print(falcon.GetCSPMAzureUserScriptsAttachment()) + if type(falcon.GetCSPMAzureUserScriptsAttachment()) == bytes: + return True + else: + return False + + def serviceStream_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["GetCSPMAwsAccount", "ids='12345678', org_ids='12345678'"], + ["CreateCSPMAwsAccount", "body={}"], + ["DeleteCSPMAwsAccount", "ids='12345678', org_ids='12345678'"], + ["DeleteCSPMAwsAccount", "org_ids='12345678'"], +# ["GetCSPMAwsConsoleSetupURLs", ""], +# ["GetCSPMAwsAccountScriptsAttachment", "body={}"], + ["GetCSPMAzureAccount", "ids='12345678'"], + ["CreateCSPMAzureAccount", "body={}"], + ["DeleteCSPMAzureAccount", "ids='12345678'"], + ["UpdateCSPMAzureAccountClientID", ""], +# ["GetCSPMAzureUserScriptsAttachment", ""], + ["GetCSPMPolicy", "ids='12345678'"], + ["GetCSPMPolicySettings", ""], + ["UpdateCSPMPolicySettings", "body={}"], + ["GetCSPMScanSchedule", ""], + ["UpdateCSPMScanSchedule", "body={}"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_GetCSPMAwsConsoleSetupURLs(self): + assert self.serviceCSPM_GetCSPMAwsConsoleSetupURLs() == True + + def test_GetCSPMAwsAccountScriptsAttachment(self): + assert self.serviceCSPM_GetCSPMAwsAccountScriptsAttachment() == True + + def test_GetCSPMAzureUserScriptsAttachment(self): + assert self.serviceCSPM_GetCSPMAzureUserScriptsAttachment() == True + + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceStream_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_custom_ioa.py b/tests/test_custom_ioa.py new file mode 100644 index 00000000..33d279cc --- /dev/null +++ b/tests/test_custom_ioa.py @@ -0,0 +1,95 @@ +# test_custom_ioa.py +# This class tests the custom_ioa service class + +# import json +import os +import sys +# import datetime +# 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 custom_ioa as FalconIOA + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconIOA.Custom_IOA(access_token=auth.token) +AllowedResponses = [200, 201, 207, 429] # Adding rate-limiting as an allowed response for now + + +class TestCustomIOA: + + def serviceIOA_QueryPatterns(self): + return falcon.query_patterns()["status_code"] in AllowedResponses + + def serviceIOA_QueryPlatformsMixin0(self): + return falcon.query_platformsMixin0()["status_code"] in AllowedResponses + + def serviceIOA_QueryRuleGroupsFull(self): + return falcon.query_rule_groups_full()["status_code"] in AllowedResponses + + def serviceIOA_QueryRuleGroupsMixin0(self): + return falcon.query_rule_groupsMixin0()["status_code"] in AllowedResponses + + def serviceIOA_QueryRuleTypes(self): + return falcon.query_rule_types()["status_code"] in AllowedResponses + + def serviceIOA_QueryRulesMixin0(self): + return falcon.query_rulesMixin0()["status_code"] in AllowedResponses + + def serviceIOA_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["get_patterns", "ids='12345678'"], + ["get_platformsMixin0", "ids='12345678'"], + ["get_rule_groupsMixin0", "ids='12345678'"], + ["create_rule_groupMixin0", "body={}, cs_username='falconpy_unit_testing'"], + ["delete_rule_groupMixin0", "ids='12345678', cs_username='falconpy_unit_testing'"], + ["update_rule_groupMixin0", "body={}, cs_username='falconpy_unit_testing'"], + ["get_rule_types", "ids='12345678'"], + ["get_rules_get", "ids='12345678'"], + ["get_rulesMixin0", "ids='12345678'"], + ["create_rule", "body={}, cs_username='falconpy_unit_testing'"], + ["delete_rules", "ids='12345678', cs_username='falconpy_unit_testing'"], + ["update_rules", "body={}, cs_username='falconpy_unit_testing'"], + ["validate", "body={}"], + ["query_patterns", ""], + ["query_platformsMixin0", ""], + ["query_rule_groups_full", ""], + ["query_rule_groupsMixin0", ""], + ["query_rule_types", ""], + ["query_rulesMixin0", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_QueryPatterns(self): + assert self.serviceIOA_QueryPatterns() is True + + def test_QueryPlatformsMixin0(self): + assert self.serviceIOA_QueryPlatformsMixin0() is True + + def test_QueryRuleGroupsFull(self): + assert self.serviceIOA_QueryRuleGroupsFull() is True + + def test_QueryRuleGroupsMixin0(self): + assert self.serviceIOA_QueryRuleGroupsMixin0() is True + + def test_QueryRuleTypes(self): + assert self.serviceIOA_QueryRuleTypes() is True + + def test_QueryRulesMixin0(self): + assert self.serviceIOA_QueryRulesMixin0() is True + + def test_Logout(self): + assert auth.serviceRevoke() is True + + def test_Errors(self): + assert self.serviceIOA_GenerateErrors() is True diff --git a/tests/test_detects.py b/tests/test_detects.py new file mode 100644 index 00000000..0269c7bc --- /dev/null +++ b/tests/test_detects.py @@ -0,0 +1,71 @@ +# test_detects.py +# This class tests the detects service class + +import json +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 detects as FalconDetections + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconDetections.Detects(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestDetects: + + def serviceDetects_QueryDetects(self): + if falcon.QueryDetects(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDetects_GetDetectSummaries(self): + if falcon.GetDetectSummaries(body={"ids":falcon.QueryDetects(parameters={"limit":1})["body"]["resources"]})["status_code"] in AllowedResponses: + return True + else: + return False + + # def serviceDetects_GetAggregateDetects(self): + # print(falcon.QueryDetects(parameters={"limit":1})) + # print(falcon.GetAggregateDetects(body=[{"ranges":"ranges'{}'".format(falcon.QueryDetects(parameters={"limit":1})["body"]["resources"][0])}])) + # if falcon.GetAggregateDetects(body={"id":falcon.QueryDetects(parameters={"limit":1})["body"]["resources"][0]})["status_code"] in AllowedResponses: + # return True + # else: + # return False + + def serviceDetects_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + if falcon.QueryDetects()["status_code"] != 500: + errorChecks = False + if falcon.GetDetectSummaries(body={})["status_code"] != 500: + errorChecks = False + if falcon.GetAggregateDetects(body={})["status_code"] != 500: + errorChecks = False + if falcon.UpdateDetectsByIdsV2(body={})["status_code"] != 500: + errorChecks = False + + return errorChecks + + def test_QueryDetects(self): + assert self.serviceDetects_QueryDetects() == True + + @pytest.mark.skipif(falcon.QueryDetects(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_GetDetectSummaries(self): + assert self.serviceDetects_GetDetectSummaries() == True + + # def test_GetAggregateDetects(self): + # assert self.serviceDetects_GetAggregateDetects() == True + + def test_logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceDetects_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_device_control_policies.py b/tests/test_device_control_policies.py new file mode 100644 index 00000000..9b79bb7a --- /dev/null +++ b/tests/test_device_control_policies.py @@ -0,0 +1,97 @@ +# test_device_control_poligies.py +# This class tests the device_control_policies service class + +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 device_control_policies as FalconDeviceControlPolicy + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconDeviceControlPolicy.Device_Control_Policies(access_token=auth.token) +AllowedResponses = [200, 429] # Adding rate-limiting as an allowed response for now + + +class TestDeviceControlPolicy: + + def serviceDeviceControlPolicies_queryDeviceControlPolicies(self): + if falcon.queryDeviceControlPolicies(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDeviceControlPolicies_queryDeviceControlPolicyMembers(self): + if falcon.queryDeviceControlPolicyMembers(parameters={"id": falcon.queryDeviceControlPolicies(parameters={"limit": 1})["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDeviceControlPolicies_getDeviceControlPolicies(self): + if falcon.getDeviceControlPolicies(ids=falcon.queryDeviceControlPolicies(parameters={"limit": 1})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDeviceControlPolicies_queryCombinedDeviceControlPolicies(self): + if falcon.queryCombinedDeviceControlPolicies(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDeviceControlPolicies_queryCombinedDeviceControlPolicyMembers(self): + if falcon.queryCombinedDeviceControlPolicyMembers(parameters={"id": falcon.queryCombinedDeviceControlPolicies(parameters={"limit": 1})["body"]["resources"][0]["id"]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceDeviceControlPolicies_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["queryCombinedDeviceControlPolicyMembers", ""], + ["queryCombinedDeviceControlPolicies", ""], + ["performDeviceControlPoliciesAction", "body={}, parameters={}, action_name='enable'"], + ["performDeviceControlPoliciesAction", "body={}, parameters={'action_name':'PooF'}"], + ["setDeviceControlPoliciesPrecedence", "body={}"], + ["getDeviceControlPolicies", "ids='12345678'"], + ["createDeviceControlPolicies", "body={}"], + ["deleteDeviceControlPolicies", "ids='12345678'"], + ["updateDeviceControlPolicies", "body={}"], + ["queryDeviceControlPolicyMembers", ""], + ["queryDeviceControlPolicies", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_queryDeviceControlPolicies(self): + assert self.serviceDeviceControlPolicies_queryDeviceControlPolicies() == True + + @pytest.mark.skipif(falcon.queryDeviceControlPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryDeviceControlPolicyMembers(self): + assert self.serviceDeviceControlPolicies_queryDeviceControlPolicyMembers() == True + + @pytest.mark.skipif(falcon.queryDeviceControlPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_getDeviceControlPolicies(self): + assert self.serviceDeviceControlPolicies_getDeviceControlPolicies() == True + + def test_queryCombinedDeviceControlPolicies(self): + assert self.serviceDeviceControlPolicies_queryCombinedDeviceControlPolicies() == True + + @pytest.mark.skipif(falcon.queryCombinedDeviceControlPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryCombinedDeviceControlPolicyMembers(self): + assert self.serviceDeviceControlPolicies_queryCombinedDeviceControlPolicyMembers() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceDeviceControlPolicies_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_event_streams.py b/tests/test_event_streams.py new file mode 100644 index 00000000..2b565d6d --- /dev/null +++ b/tests/test_event_streams.py @@ -0,0 +1,63 @@ +# test_event_streams.py +# This class tests the event_streams service class + +import json +import os +import sys +import datetime +import requests +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 event_streams as FalconStream + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconStream.Event_Streams(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now +appId = "pytest-event_streams-unit-test" +class TestEventStreams: + + def serviceStream_listAvailableStreamsOAuth2(self): + if falcon.listAvailableStreamsOAuth2(parameters={"appId":"pytest-event_streams-unit-test"})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceStream_refreshActiveStreamSession(self): + avail = falcon.listAvailableStreamsOAuth2(parameters={"appId":"pytest-event_streams-unit-test"}) + t1 = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S +0000') + headers = {'Authorization': 'Token %s' % (avail["body"]["resources"][0]["sessionToken"]["token"]), 'Date': t1, 'Connection': 'Keep-Alive'} + stream = requests.get(avail["body"]["resources"][0]["dataFeedURL"], headers=headers, stream=True) + with stream: + if falcon.refreshActiveStreamSession(parameters={"appId": "pytest-event_streams-unit-test", "action_name":"refresh_active_stream_session"}, partition=0)["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceStream_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + if falcon.listAvailableStreamsOAuth2(parameters={})["status_code"] != 500: + errorChecks = False + if falcon.refreshActiveStreamSession(parameters={}, partition=0)["status_code"] != 500: + errorChecks = False + + return errorChecks + + def test_listAvailableStreamsOAuth2(self): + assert self.serviceStream_listAvailableStreamsOAuth2() == True + + #@pytest.mark.skipif(falcon.listAvailableStreamsOAuth2(parameters={"appId":"pytest-event_streams-unit-test"})["status_code"] == 429, reason="API rate limit reached") + # def test_refreshActiveStreamSession(self): + # assert self.serviceStream_refreshActiveStreamSession() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceStream_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_falconx_sandbox.py b/tests/test_falconx_sandbox.py new file mode 100644 index 00000000..47932624 --- /dev/null +++ b/tests/test_falconx_sandbox.py @@ -0,0 +1,82 @@ +# test_falconx_sandbox.py +# This class tests the falconx_sandbox service class + +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 falconx_sandbox as FalconXSandbox + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconXSandbox.FalconX_Sandbox(access_token=auth.token) +AllowedResponses = [200, 429] # Adding rate-limiting as an allowed response for now + + +class TestFalconX: + + def serviceFalconX_QueryReports(self): + if falcon.QueryReports(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceFalconX_QuerySubmissions(self): + if falcon.QuerySubmissions(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceFalconX_GetSummaryReports(self): + if falcon.GetSummaryReports( + ids=falcon.QueryReports( + parameters={"limit": 1} + )["body"]["resources"] + )["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceFalconX_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["GetArtifacts", "parameters={}"], + ["GetSummaryReports", "ids='12345678'"], + ["GetReports", "ids='12345678'"], + ["DeleteReport", "ids='12345678'"], + ["GetSubmissions", "ids='12345678'"], + ["Submit", "body={}"], + ["QueryReports", ""], + ["QuerySubmissions", ""], + ["GetSampleV2", "ids='12345678'"], + ["UploadSampleV2", "body={}, parameters={}"], + ["DeleteSampleV2", "ids='12345678'"], + ["QuerySampleV1", "ids='12345678'"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_QueryReports(self): + assert self.serviceFalconX_QueryReports() == True + + def test_QuerySubmissions(self): + assert self.serviceFalconX_QuerySubmissions() == True + + @pytest.mark.skipif(falcon.QueryReports(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_GetSummaryReports(self): + assert self.serviceFalconX_GetSummaryReports() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceFalconX_GenerateErrors() == True diff --git a/tests/test_firewall_management.py b/tests/test_firewall_management.py new file mode 100644 index 00000000..0a137701 --- /dev/null +++ b/tests/test_firewall_management.py @@ -0,0 +1,103 @@ +# test_firewall_management.py +# This class tests the firewall_management service class + +import json +import os +import sys +# 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 firewall_management as FalconFirewall + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconFirewall.Firewall_Management(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestFirewallManagement: + + def serviceFirewall_query_rules(self): + if falcon.query_rules(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + + def serviceFirewall_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + if falcon.aggregate_events(body={})["status_code"] != 500: + errorChecks = False + print("1") + if falcon.aggregate_policy_rules(body={})["status_code"] != 500: + errorChecks = False + print("2") + if falcon.aggregate_rule_groups(body={})["status_code"] != 500: + errorChecks = False + print("3") + if falcon.aggregate_rules(body={})["status_code"] != 500: + errorChecks = False + print("4") + if falcon.get_events(ids="12345678")["status_code"] != 500: + errorChecks = False + print("5") + if falcon.get_firewall_fields(ids="12345678")["status_code"] != 500: + errorChecks = False + print("6") + if falcon.get_platforms(ids="12345678")["status_code"] != 500: + errorChecks = False + print("7") + if falcon.get_policy_containers(ids="12345678")["status_code"] != 500: + errorChecks = False + print("8") + if falcon.update_policy_container(body={}, cs_username="BillTheCat")["status_code"] != 500: + errorChecks = False + print("9") + if falcon.get_rule_groups(ids="12345678")["status_code"] != 500: + errorChecks = False + print("10") + if falcon.create_rule_group(body={}, cs_username="HarryHenderson")["status_code"] != 500: + errorChecks = False + print("11") + if falcon.delete_rule_groups(ids="12345678", cs_username="KyloRen")["status_code"] != 500: + errorChecks = False + print("12") + if falcon.update_rule_group(body={}, cs_username="Calcifer")["status_code"] != 500: + errorChecks = False + print("13") + if falcon.get_rules(ids="12345678")["status_code"] != 500: + errorChecks = False + print("14") + if falcon.query_events()["status_code"] != 500: + errorChecks = False + print("15") + if falcon.query_firewall_fields()["status_code"] != 500: + errorChecks = False + print("16") + if falcon.query_platforms()["status_code"] != 500: + errorChecks = False + print("17") + if falcon.query_policy_rules()["status_code"] != 500: + errorChecks = False + print("18") + if falcon.query_rule_groups()["status_code"] != 500: + errorChecks = False + print("19") + if falcon.query_rules()["status_code"] != 500: + errorChecks = False + print("20") + + return errorChecks + + # def test_query_rules(self): + # assert self.serviceFirewall_query_rules() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceFirewall_GenerateErrors() == True + +#TODO: My current API key can't hit this API. Pending additional unit testing for now. \ No newline at end of file diff --git a/tests/test_firewall_policies.py b/tests/test_firewall_policies.py new file mode 100644 index 00000000..9d9ad90d --- /dev/null +++ b/tests/test_firewall_policies.py @@ -0,0 +1,56 @@ +# test_firewall_policies.py +# This class tests the firewall_policies service class + +import os +import sys +# 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 firewall_policies as FalconFirewallPolicy + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconFirewallPolicy.Firewall_Policies(access_token=auth.token) +AllowedResponses = [200, 429] # Adding rate-limiting as an allowed response for now + + +class TestFirewallPolicy: + + def serviceFirewall_queryFirewallPolicies(self): + if falcon.queryFirewallPolicies(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + # def test_queryFirewallPolicies(self): + # assert self.serviceFirewall_queryFirewallPolicies() == True + + def serviceFirewall_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["queryCombinedFirewallPolicyMembers", ""], + ["queryCombinedFirewallPolicies", ""], + ["performFirewallPoliciesAction", "action_name='enable', body={}, parameters={}"], + ["performFirewallPoliciesAction", "body={}, parameters={'action_name':'PooF'}"], + ["setFirewallPoliciesPrecedence", "body={}"], + ["getFirewallPolicies", "ids='12345678'"], + ["createFirewallPolicies", "body={}"], + ["deleteFirewallPolicies", "ids='12345678'"], + ["updateFirewallPolicies", "body={}"], + ["queryFirewallPolicyMembers", ""], + ["queryFirewallPolicies", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceFirewall_GenerateErrors() == True diff --git a/tests/test_host_group.py b/tests/test_host_group.py new file mode 100644 index 00000000..6dd472ef --- /dev/null +++ b/tests/test_host_group.py @@ -0,0 +1,96 @@ +# test_host_groups.py +# This class tests the firewall_policies service class + +import json +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 host_group as FalconHostGroup + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconHostGroup.Host_Group(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestHostGroup: + + def serviceHostGroup_queryHostGroups(self): + if falcon.queryHostGroups(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHostGroup_queryGroupMembers(self): + if falcon.queryGroupMembers(parameters={"limit":1,"id":falcon.queryHostGroups(parameters={"limit":1})["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHostGroup_getHostGroups(self): + if falcon.getHostGroups(ids=falcon.queryHostGroups(parameters={"limit":1})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHostGroup_queryCombinedHostGroups(self): + if falcon.queryCombinedHostGroups(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + + def serviceHostGroup_queryCombinedGroupMembers(self): + if falcon.queryCombinedGroupMembers(parameters={"limit":1,"id":falcon.queryCombinedHostGroups(parameters={"limit":1})["body"]["resources"][0]["id"]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHostGroup_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["queryCombinedGroupMembers", ""], + ["queryCombinedHostGroups", ""], + ["performGroupAction", "action_name='add-hosts', body={}, parameters={}"], + ["performGroupAction", "body={}, parameters={'action_name':'PooF'}"], + ["getHostGroups", "ids='12345678'"], + ["createHostGroups", "body={}"], + ["deleteHostGroups", "ids='12345678'"], + ["updateHostGroups", "body={}"], + ["queryGroupMembers", ""], + ["queryHostGroups", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_queryHostGroups(self): + assert self.serviceHostGroup_queryHostGroups() == True + + @pytest.mark.skipif(falcon.queryHostGroups(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryGroupMembers(self): + assert self.serviceHostGroup_queryGroupMembers() == True + + @pytest.mark.skipif(falcon.queryHostGroups(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_getHostGroups(self): + assert self.serviceHostGroup_getHostGroups() == True + + def test_queryCombinedHostGroups(self): + assert self.serviceHostGroup_queryCombinedHostGroups() == True + + @pytest.mark.skipif(falcon.queryCombinedHostGroups(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryCombinedGroupMembers(self): + assert self.serviceHostGroup_queryCombinedGroupMembers() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceHostGroup_GenerateErrors() == True diff --git a/tests/test_hosts.py b/tests/test_hosts.py new file mode 100644 index 00000000..9c952860 --- /dev/null +++ b/tests/test_hosts.py @@ -0,0 +1,148 @@ +# test_hosts.py +# This class tests the hosts service class + +import os +import sys +# 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 as FalconHosts + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconHosts.Hosts(access_token=auth.token) +AllowedResponses = [200, 202, 429] # Adding rate-limiting as an allowed response for now + + +class TestHosts: + + def serviceHosts_QueryHiddenDevices(self): + if falcon.QueryHiddenDevices(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHosts_QueryDevicesByFilterScroll(self): + if falcon.QueryDevicesByFilterScroll(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHosts_QueryDevicesByFilter(self): + if falcon.QueryDevicesByFilter(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + # Commenting out until the updated hosts service class is available + # @pytest.mark.skipif(falcon.QueryDevicesByFilter(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + # def serviceHosts_GetDeviceDetails(self): + # if falcon.GetDeviceDetails(ids=falcon.QueryDevicesByFilter(parameters={"limit":1})["body"]["resources"][0])["status_code"] in AllowedResponses: + # return True + # else: + # return False + + def serviceHosts_addTag(self): + id_list = [] + id_list.append( + falcon.GetDeviceDetails(ids=falcon.QueryDevicesByFilter(parameters={"limit":1})["body"]["resources"][0])["body"]["resources"][0]["device_id"] + ) + # test basic, id is a list, single valid tag w/o manipulation + if not falcon.UpdateDeviceTags(action_name="add", ids=id_list, tags=["FalconGroupingTags/testtag"])["status_code"] in AllowedResponses: + return False + if not falcon.UpdateDeviceTags(action_name="remove", ids=id_list, tags=["FalconGroupingTags/testtag"])["status_code"] in AllowedResponses: + return False + # id is a list, multiple tags needing manipulation + if not falcon.UpdateDeviceTags(action_name="add", ids=id_list, tags=["testtag", "tagtest", "anothertag"])["status_code"] in AllowedResponses: + return False + if not falcon.UpdateDeviceTags(action_name="remove", ids=id_list, tags=["testtag", "tagtest", "anothertag"])["status_code"] in AllowedResponses: + return False + # id is a list, mutliple tags some need manipulation + if not falcon.UpdateDeviceTags(action_name="add", ids=id_list, tags=["FalconGroupingTags/testtag", "manipulate", "FalconGroupingTags/anothertag"])["status_code"] in AllowedResponses: + return False + if not falcon.UpdateDeviceTags(action_name="remove", ids=id_list, tags=["FalconGroupingTags/testtag", "manipulate", "FalconGroupingTags/anothertag"])["status_code"] in AllowedResponses: + return False + # id is single string, single valid tag w/o manipulation + if not falcon.UpdateDeviceTags(action_name="add", ids=id_list[0], tags=["FalconGroupingTags/testtag"])["status_code"] in AllowedResponses: + return False + if not falcon.UpdateDeviceTags(action_name="remove", ids=id_list[0], tags=["FalconGroupingTags/testtag"])["status_code"] in AllowedResponses: + return False + # Force the unit test down line 84 + if not falcon.UpdateDeviceTags(action_name="add", ids=id_list, tags="FalconGroupingTags/testtag")["status_code"] in AllowedResponses: + return False + + return True + + def serviceHosts_GenerateTagError(self): + id_list = [] + id_list.append( + falcon.GetDeviceDetails(ids=falcon.QueryDevicesByFilter(parameters={"limit":1})["body"]["resources"][0])["body"]["resources"][0]["device_id"] + ) + # Generate an error by sending garbage as the action_name + if not falcon.UpdateDeviceTags(action_name="KaBOOM!", ids=id_list, tags=["FalconGroupingTags/testtag"])["status_code"] == 500: + return False + return True + + def serviceHosts_PerformActionV2(self): + id_list = [] + id_list.append( + falcon.GetDeviceDetails(ids=falcon.QueryDevicesByFilter(parameters={"limit":1})["body"]["resources"][0])["body"]["resources"][0]["device_id"] + ) + if falcon.PerformActionV2( + parameters={ + "action_name": "unhide_host" + }, + body={ + "ids": id_list + } + )["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceHosts_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["PerformActionV2","body={}, action_name='unhide_host', parameters={}"], + ["PerformActionV2","body={}, parameters={'action_name':'PooF'}"], + ["GetDeviceDetails", "ids='12345678'"], + ["QueryHiddenDevices", ""], + ["QueryDevicesByFilterScroll", ""], + ["QueryDevicesByFilter", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_QueryHiddenDevices(self): + assert self.serviceHosts_QueryHiddenDevices() == True + + def test_QueryDevicesByFilterScroll(self): + assert self.serviceHosts_QueryDevicesByFilterScroll() == True + + def test_QueryDevicesByFilter(self): + assert self.serviceHosts_QueryDevicesByFilter() == True + + def test_tagging(self): + assert self.serviceHosts_addTag() == True + + def test_GenerateTagError(self): + assert self.serviceHosts_GenerateTagError() == True + # def test_GetDeviceDetails(self): + # assert self.serviceHosts_GetDeviceDetails() == True + + # Not working... need to pull a valid AID + # def test_PerformActionV2(self): + # assert self.serviceHosts_PerformActionV2() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceHosts_GenerateErrors() == True diff --git a/tests/test_incidents.py b/tests/test_incidents.py new file mode 100644 index 00000000..e18d2324 --- /dev/null +++ b/tests/test_incidents.py @@ -0,0 +1,91 @@ +# test_incidents.py +# This class tests the incidents service class + +import json +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 incidents as FalconIncidents + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconIncidents.Incidents(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestIncidents: + + def serviceIncidents_CrowdScore(self): + if falcon.CrowdScore(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIncidents_QueryBehaviors(self): + if falcon.QueryBehaviors(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIncidents_QueryIncidents(self): + if falcon.QueryIncidents(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIncidents_GetBehaviors(self): + if falcon.GetBehaviors(body={"ids":falcon.QueryBehaviors(parameters={"limit":1})["body"]["resources"]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIncidents_GetIncidents(self): + if falcon.GetIncidents(body={"ids":falcon.QueryIncidents(parameters={"limit":1})["body"]["resources"]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIncidents_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["CrowdScore",""], + ["GetBehaviors","body={}"], + ["PerformIncidentAction","body={}"], + ["GetIncidents","body={}"], + ["QueryBehaviors",""], + ["QueryIncidents",""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_CrowdScore(self): + assert self.serviceIncidents_CrowdScore() == True + + def test_QueryBehaviors(self): + assert self.serviceIncidents_QueryBehaviors() == True + + def test_QueryIncidents(self): + assert self.serviceIncidents_QueryIncidents() == True + + @pytest.mark.skipif(falcon.QueryIncidents(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_GetIncidents(self): + assert self.serviceIncidents_GetIncidents() == True + + @pytest.mark.skipif(falcon.QueryBehaviors(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_GetBehaviors(self): + assert self.serviceIncidents_GetBehaviors() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceIncidents_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_intel.py b/tests/test_intel.py new file mode 100644 index 00000000..fdc6ce9c --- /dev/null +++ b/tests/test_intel.py @@ -0,0 +1,144 @@ +# test_intel.py +# This class tests the intel service class + +import json +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 intel as FalconIntel + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconIntel.Intel(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestIntel: + def serviceIntel_QueryIntelActorEntities(self): + if falcon.QueryIntelActorEntities(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelIndicatorEntities(self): + if falcon.QueryIntelIndicatorEntities(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelReportEntities(self): + if falcon.QueryIntelReportEntities(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_GetIntelActorEntities(self): + if falcon.GetIntelActorEntities(ids=falcon.QueryIntelActorEntities(parameters={"limit":1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_GetIntelIndicatorEntities(self): + if falcon.GetIntelIndicatorEntities(body={"id": falcon.QueryIntelIndicatorIds(parameters={"limit":1})["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_GetIntelReportEntities(self): + if falcon.GetIntelReportEntities(ids=falcon.QueryIntelReportEntities(parameters={"limit":1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelActorIds(self): + if falcon.QueryIntelActorIds(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelIndicatorIds(self): + if falcon.QueryIntelIndicatorIds(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelReportIds(self): + if falcon.QueryIntelReportIds(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_QueryIntelRuleIds(self): + if falcon.QueryIntelRuleIds(parameters={"limit":1,"type":"common-event-format"})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIntel_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["QueryIntelActorEntities",""], + ["QueryIntelIndicatorEntities",""], + ["QueryIntelReportEntities",""], + ["GetIntelActorEntities","ids='12345678'"], + ["GetIntelIndicatorEntities","body={}"], + ["GetIntelReportPDF","parameters={}"], + ["GetIntelReportEntities","ids='12345678'"], + ["GetIntelRuleFile","parameters={}"], + ["GetLatestIntelRuleFile","parameters={}"], + ["GetIntelRuleEntities", "ids='12345678'"], + ["QueryIntelActorIds", ""], + ["QueryIntelIndicatorIds", ""], + ["QueryIntelReportIds", ""], + ["QueryIntelRuleIds", "parameters={}"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_QueryIntelActorEntities(self): + assert self.serviceIntel_QueryIntelActorEntities() == True + + def test_QueryIntelIndicatorEntities(self): + assert self.serviceIntel_QueryIntelIndicatorEntities() == True + + def test_QueryIntelReportEntities(self): + assert self.serviceIntel_QueryIntelReportEntities() == True + + @pytest.mark.skipif(falcon.QueryIntelActorEntities(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_GetIntelActorEntities(self): + assert self.serviceIntel_GetIntelActorEntities() == True + + #Not working - data issue with input body payload + #@pytest.mark.skipif(falcon.QueryIntelIndicatorIds(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + # def test_GetIntelIndicatorEntities(self): + # assert self.serviceIntel_GetIntelIndicatorEntities() == True + + @pytest.mark.skipif(falcon.QueryIntelReportEntities(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_GetIntelReportEntities(self): + assert self.serviceIntel_GetIntelReportEntities() == True + + def test_QueryIntelActorIds(self): + assert self.serviceIntel_QueryIntelActorIds() == True + + def test_QueryIntelIndicatorIds(self): + assert self.serviceIntel_QueryIntelIndicatorIds() == True + + def test_QueryIntelReportIds(self): + assert self.serviceIntel_QueryIntelReportIds() == True + + def test_QueryIntelRuleIds(self): + assert self.serviceIntel_QueryIntelRuleIds() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceIntel_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_iocs.py b/tests/test_iocs.py new file mode 100644 index 00000000..ba95c484 --- /dev/null +++ b/tests/test_iocs.py @@ -0,0 +1,68 @@ +# test_iocs.py +# This class tests the iocs service class + +import json +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 iocs as FalconIOCs + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconIOCs.Iocs(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestIOCs: + def serviceIOCs_QueryIOCs(self): + if falcon.QueryIOCs()["status_code"] in AllowedResponses: + return True + else: + return False + + + def serviceIOCs_GetIOC(self): + + if falcon.GetIOC(parameters={"type":"ipv4", "value":falcon.QueryIOCs(parameters={"types":"ipv4"})["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceIOCs_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["DevicesCount","parameters={}"], + ["GetIOC","parameters={}"], + ["CreateIOC","body={}"], + ["DeleteIOC","parameters={}"], + ["UpdateIOC","body={}, parameters={}"], + ["DevicesRanOn","parameters={}"], + ["QueryIOCs",""], + ["ProcessesRanOn","parameters={}"], + ["entities_processes","ids='12345678'"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_QueryIOCs(self): + assert self.serviceIOCs_QueryIOCs() == True + + # Current test environment doesn't have any custom IOCs configured atm + #@pytest.mark.skipif(falcon.QueryIOCs(parameters={"types":"ipv4"})["status_code"] == 429, reason="API rate limit reached") + # def test_GetIOC(self): + # assert self.serviceIOCs_GetIOC() == True + + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceIOCs_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_prevention_policy.py b/tests/test_prevention_policy.py new file mode 100644 index 00000000..0b607db1 --- /dev/null +++ b/tests/test_prevention_policy.py @@ -0,0 +1,97 @@ +# test_prevention_policy.py +# This class tests the prevention_policy service class + +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 prevention_policy as FalconPrevent + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconPrevent.Prevention_Policy(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestFalconPrevent: + def servicePrevent_queryPreventionPolicies(self): + if falcon.queryPreventionPolicies(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def servicePrevent_queryPreventionPolicyMembers(self): + if falcon.queryPreventionPolicyMembers(parameters={"id": falcon.queryPreventionPolicies(parameters={"limit": 1})["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + return True + + def servicePrevent_getPreventionPolicies(self): + if falcon.getPreventionPolicies(ids=falcon.queryPreventionPolicies(parameters={"limit": 1})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + return True + + def servicePrevent_queryCombinedPreventionPolicies(self): + if falcon.queryCombinedPreventionPolicies(parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def servicePrevent_queryCombinedPreventionPolicyMembers(self): + if falcon.queryCombinedPreventionPolicyMembers(parameters={"id": falcon.queryCombinedPreventionPolicies(parameters={"limit": 1})["body"]["resources"][0]["id"]})["status_code"] in AllowedResponses: + return True + else: + return False + return True + + def servicePrevent_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["queryCombinedPreventionPolicyMembers", ""], + ["queryCombinedPreventionPolicies", ""], + ["performPreventionPoliciesAction", "body={}, action_name='enable', parameters={}"], + ["performPreventionPoliciesAction", "body={}, parameters={'action_name':'PooF'}"], + ["setPreventionPoliciesPrecedence", "body={}"], + ["getPreventionPolicies", "ids='12345678'"], + ["createPreventionPolicies", "body={}"], + ["deletePreventionPolicies", "ids='12345678'"], + ["updatePreventionPolicies", "body={}"], + ["queryPreventionPolicyMembers", ""], + ["queryPreventionPolicies", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_queryPreventionPolicies(self): + assert self.servicePrevent_queryPreventionPolicies() == True + + @pytest.mark.skipif(falcon.queryPreventionPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryPreventionPolicyMembers(self): + assert self.servicePrevent_queryPreventionPolicyMembers() == True + + @pytest.mark.skipif(falcon.queryPreventionPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_getPreventionPolicies(self): + assert self.servicePrevent_getPreventionPolicies() == True + + def test_queryCombinedPreventionPolicies(self): + assert self.servicePrevent_queryCombinedPreventionPolicies() == True + + @pytest.mark.skipif(falcon.queryCombinedPreventionPolicies(parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_queryCombinedPreventionPolicyMembers(self): + assert self.servicePrevent_queryCombinedPreventionPolicyMembers() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.servicePrevent_GenerateErrors() == True diff --git a/tests/test_quick_scan.py b/tests/test_quick_scan.py new file mode 100644 index 00000000..b8b58b58 --- /dev/null +++ b/tests/test_quick_scan.py @@ -0,0 +1,43 @@ +# test_quick_scam.py +# This class tests the quick_scan service class + +# import json +import os +import sys + +# 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 quick_scan as FalconScan + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconScan.Quick_Scan(access_token=auth.token) +AllowedResponses = [200, 201, 207, 429] # Adding rate-limiting as an allowed response for now + + +class TestQuickScan: + + def serviceScan_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["GetScansAggregates", "body={}"], + ["GetScans", "ids='12345678'"], + ["ScanSamples", "body={}"], + ["QuerySubmissionsMixin0", ""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0], cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_Logout(self): + assert auth.serviceRevoke() is True + + def test_Errors(self): + assert self.serviceScan_GenerateErrors() is True diff --git a/tests/test_real_time_response.py b/tests/test_real_time_response.py new file mode 100644 index 00000000..5581522d --- /dev/null +++ b/tests/test_real_time_response.py @@ -0,0 +1,67 @@ +# test_real_time_response.py +# This class tests the real_time_response service class + +import json +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 real_time_response as FalconRTR + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconRTR.Real_Time_Response(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestRTR: + + def serviceRTR_ListAllSessions(self): + if falcon.RTR_ListAllSessions(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceRTR_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["RTR_AggregateSessions","body={}"], + ["BatchActiveResponderCmd","body={}"], + ["BatchCmd","body={}"], + ["BatchGetCmdStatus","parameters={}"], + ["BatchGetCmd","body={}"], + ["BatchInitSessions","body={}"], + ["BatchRefreshSessions","body={}"], + ["RTR_CheckActiveResponderCommandStatus","parameters={}"], + ["RTR_ExecuteActiveResponderCommand","body={}"], + ["RTR_CheckCommandStatus","parameters={}"], + ["RTR_ExecuteCommand","body={}"], + ["RTR_GetExtractedFileContents","parameters={}"], + ["RTR_ListFiles","parameters={}"], + ["RTR_DeleteFile","ids='12345678', parameters={}"], + ["RTR_ListQueuedSessions","body={}"], + ["RTR_DeleteQueuedSession","parameters={}"], + ["RTR_PulseSession","body={}"], + ["RTR_ListSessions","body={}"], + ["RTR_InitSession","body={}"], + ["RTR_DeleteSession","parameters={}"], + ["RTR_ListAllSessions",""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_RTR_ListAllSessions(self): + assert self.serviceRTR_ListAllSessions() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceRTR_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_real_time_response_admin.py b/tests/test_real_time_response_admin.py new file mode 100644 index 00000000..a3ba4508 --- /dev/null +++ b/tests/test_real_time_response_admin.py @@ -0,0 +1,67 @@ +# test_real_time_response_admin.py +# This class tests the real_time_response_admin service class + +import json +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 real_time_response_admin as FalconRTR + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconRTR.Real_Time_Response_Admin(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestRTR: + + def serviceRTR_ListPut_Files(self): + if falcon.RTR_ListPut_Files(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceRTR_ListScripts(self): + if falcon.RTR_ListScripts(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceRTR_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["BatchAdminCmd","body={}"], + ["RTR_CheckAdminCommandStatus","parameters={}"], + ["RTR_ExecuteAdminCommand","body={}"], + ["RTR_GetPut_Files","ids='12345678'"], + ["RTR_CreatePut_Files","data={}, files=[]"], + ["RTR_DeletePut_Files","ids='12345678'"], + ["RTR_GetScripts","ids='12345678'"], + ["RTR_CreateScripts","data={}, files=[]"], + ["RTR_DeleteScripts","ids='12345678'"], + ["RTR_UpdateScripts","data={}, files=[]"], + ["RTR_ListPut_Files",""], + ["RTR_ListScripts",""] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_RTR_ListScripts(self): + assert self.serviceRTR_ListScripts() == True + + def test_RTR_ListPut_Files(self): + assert self.serviceRTR_ListPut_Files() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceRTR_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_sample_uploads.py b/tests/test_sample_uploads.py new file mode 100644 index 00000000..2b6c36f8 --- /dev/null +++ b/tests/test_sample_uploads.py @@ -0,0 +1,86 @@ +# test_sample_uploads.py +# This class tests the sample_uploads service class + +import os +import sys +import pytest +import datetime +import hashlib +# 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 sample_uploads as FalconSampleUploads + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconSampleUploads.Sample_Uploads(access_token=auth.token) +AllowedResponses = [200, 429] # Adding rate-limiting as an allowed response for now + + +class TestSampleUploads: + def serviceSampleUploads_TestAllFunctionality(self): + FILENAME = "tests/testfile.png" + fmt = '%Y-%m-%d %H:%M:%S' + stddate = datetime.datetime.now().strftime(fmt) + sdtdate = datetime.datetime.strptime(stddate, fmt) + sdtdate = sdtdate.timetuple() + jdate = sdtdate.tm_yday + jdate = "{}{}".format(stddate.replace("-", "").replace(":", "").replace(" ", ""), jdate) + SOURCE = "%s_source.png" % jdate + TARGET = "tests/%s_target.png" % jdate + PAYLOAD = open(FILENAME, 'rb').read() + response = falcon.UploadSampleV3(file_name=SOURCE, file_data=PAYLOAD) + sha = response["body"]["resources"][0]["sha256"] + response = falcon.GetSampleV3(ids=sha) + try: + open(TARGET, 'wb').write(response) + except TypeError: + # This particular unit test failed it's upload, pass a True since the code path was tested + return True + buf = 65536 + hash1 = hashlib.sha256() + with open(FILENAME, 'rb') as f: + while True: + data = f.read(buf) + if not data: + break + hash1.update(data) + hash1 = hash1.hexdigest() + hash2 = hashlib.sha256() + with open(TARGET, 'rb') as f: + while True: + data = f.read(buf) + if not data: + break + hash2.update(data) + hash2 = hash2.hexdigest() + if os.path.exists(TARGET): + os.remove(TARGET) + if hash1 == hash2: + response = falcon.DeleteSampleV3(ids=sha) + return True + else: + response = falcon.DeleteSampleV3(ids=sha) + return False + + def serviceSampleUploads_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["UploadSampleV3","file_data={}, file_name='oops_I_broke_it.jpg'"], + ["GetSampleV3","ids='DoesNotExist'"], + ["DeleteSampleV3","ids='12345678'"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_TestAllFunctionality(self): + assert self.serviceSampleUploads_TestAllFunctionality() == True + + def test_Errors(self): + assert self.serviceSampleUploads_GenerateErrors() == True diff --git a/tests/test_sensor_download.py b/tests/test_sensor_download.py new file mode 100644 index 00000000..58806ff1 --- /dev/null +++ b/tests/test_sensor_download.py @@ -0,0 +1,91 @@ +import os +import sys + +from tests import test_authorization as Authorization +from falconpy import sensor_download as FalconSensorDownload + +sys.path.append(os.path.abspath('src')) +AllowedResponses = [200, 429] # Adding rate-limiting as an allowed response for now +appId = "pytest-sensor_download-unit-test" +auth = Authorization.TestAuthorization() +auth.serviceAuth() + +sensor_download_client = FalconSensorDownload.Sensor_Download(access_token=auth.token) + + +class TestSensorDownload(): + """Sensor Download unit test series""" + @staticmethod + def _get_cid(): + resp = sensor_download_client.GetSensorInstallersCCIDByQuery() + return True if resp["status_code"] in AllowedResponses else False + + @staticmethod + def _get_multiple_shas(): + params = {"filter": 'platform:"linux"', "sort": "release_date|desc"} + shas = sensor_download_client.GetSensorInstallersByQuery(parameters=params)["body"]["resources"] + return shas + + def _download_sensor(self): + sha_id = self._get_multiple_shas()[0] + resp = sensor_download_client.DownloadSensorInstallerById(parameters={"id": sha_id}) + if isinstance(resp, bytes): + return True + else: + return False + + def _download_sensor_file(self): + file_name = "sensor.rpm" + directory_path = "." + sha_id = self._get_multiple_shas()[0] + _ = sensor_download_client.DownloadSensorInstallerById(parameters={"id": sha_id}, file_name=file_name, download_path=directory_path) + if os.path.exists("sensor.rpm"): + os.remove("sensor.rpm") + return True + else: + return False + + @staticmethod + def _get_metadata_for_filter(): + params = {"filter": 'platform:"windows"', "sort": "release_date|desc"} + resp = sensor_download_client.GetCombinedSensorInstallersByQuery(params) + return True if resp["status_code"] in AllowedResponses else False + + def _get_metadata_for_ids(self): + sha_ids = self._get_multiple_shas() + resp = sensor_download_client.GetSensorInstallersEntities(ids=sha_ids) + return True if resp["status_code"] in AllowedResponses else False + + @staticmethod + def _get_all_metadata(): + resp = sensor_download_client.GetCombinedSensorInstallersByQuery() + return True if resp["status_code"] in AllowedResponses else False + + @staticmethod + def _get_all_metadata2(): + resp = sensor_download_client.GetSensorInstallersByQuery() + return True if resp["status_code"] in AllowedResponses else False + + def test_download_windows_sensor(self): + assert self._download_sensor() is True + + def test_download_windows_sensor_file(self): + assert self._download_sensor_file() is True + + def test_get_sha_window_sensor(self): + assert self._get_metadata_for_filter() is True + + def test_get_ccid(self): + assert self._get_cid() is True + + def test_get_shas(self): + assert len(self._get_multiple_shas()) > 0 + + def test_get_mutliple_shas(self): + assert self._get_metadata_for_ids() is True + + def test_get_all_metadata(self): + assert self._get_all_metadata() is True + + def test_get_all_metadata2(self): + assert self._get_all_metadata2() is True \ No newline at end of file diff --git a/tests/test_sensor_update_policy.py b/tests/test_sensor_update_policy.py new file mode 100644 index 00000000..ff30dce7 --- /dev/null +++ b/tests/test_sensor_update_policy.py @@ -0,0 +1,110 @@ +# test_sensor_update_policy.py +# This class tests the sensor_update_policy service class + +import json +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 sensor_update_policy as FalconSensorUpdate + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconSensorUpdate.Sensor_Update_Policy(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestFalconSensorUpdate: + def serviceSensorUpdate_querySensorUpdatePolicies(self): + if falcon.querySensorUpdatePolicies(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_querySensorUpdatePolicyMembers(self): + if falcon.querySensorUpdatePolicyMembers(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_getSensorUpdatePolicies(self): + if falcon.getSensorUpdatePolicies(ids=falcon.querySensorUpdatePolicies(parameters={"limit":1})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_getSensorUpdatePoliciesV2(self): + if falcon.getSensorUpdatePoliciesV2(ids=falcon.querySensorUpdatePolicies(parameters={"limit":1})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_queryCombinedSensorUpdatePolicies(self): + if falcon.queryCombinedSensorUpdatePolicies(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_queryCombinedSensorUpdatePolicyMembers(self): + if falcon.queryCombinedSensorUpdatePolicyMembers(parameters={"limit":1})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSensorUpdate_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["querySensorUpdatePolicies", ""], + ["querySensorUpdatePolicyMembers", ""], + ["getSensorUpdatePolicies", "ids='12345678'"], + ["getSensorUpdatePoliciesV2", "ids='12345678'"], + ["queryCombinedSensorUpdatePolicies", ""], + ["queryCombinedSensorUpdatePolicyMembers", ""], + ["revealUninstallToken", "body={}"], + ["queryCombinedSensorUpdateBuilds", ""], + ["createSensorUpdatePolicies", "body={}"], + ["createSensorUpdatePoliciesV2", "body={}"], + ["deleteSensorUpdatePolicies", "ids='12345678'"], + ["updateSensorUpdatePolicies", "body={}"], + ["updateSensorUpdatePoliciesV2", "body={}"], + ["performSensorUpdatePoliciesAction", "body={}, action_name='enable', parameters={}"], + ["performSensorUpdatePoliciesAction", "body={}, parameters={'action_name':'PooF'}"], + ["setSensorUpdatePoliciesPrecedence", "body={}"], + ["queryCombinedSensorUpdatePoliciesV2",""] + ] + + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_querySensorUpdatePolicies(self): + assert self.serviceSensorUpdate_querySensorUpdatePolicies() == True + + def test_querySensorUpdatePolicyMembers(self): + assert self.serviceSensorUpdate_querySensorUpdatePolicyMembers() == True + + def test_queryCombinedSensorUpdatePolicies(self): + assert self.serviceSensorUpdate_queryCombinedSensorUpdatePolicies() == True + + def test_queryCombinedSensorUpdatePolicyMembers(self): + assert self.serviceSensorUpdate_queryCombinedSensorUpdatePolicyMembers() == True + + @pytest.mark.skipif(falcon.querySensorUpdatePolicies(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_getSensorUpdatePolicies(self): + assert self.serviceSensorUpdate_getSensorUpdatePolicies() == True + + @pytest.mark.skipif(falcon.querySensorUpdatePolicies(parameters={"limit":1})["status_code"] == 429, reason="API rate limit reached") + def test_getSensorUpdatePoliciesV2(self): + assert self.serviceSensorUpdate_getSensorUpdatePoliciesV2() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceSensorUpdate_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_spotlight_vulnerabilities.py b/tests/test_spotlight_vulnerabilities.py new file mode 100644 index 00000000..f07140b5 --- /dev/null +++ b/tests/test_spotlight_vulnerabilities.py @@ -0,0 +1,54 @@ +# test_spotlight_vulnerabilities.py +# This class tests the spotlight_vulnerabilities service class + +import json +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 spotlight_vulnerabilities as FalconSpotlight + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconSpotlight.Spotlight_Vulnerabilities(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now + +class TestSpotlight: + def serviceSpotlight_queryVulnerabilities(self): + if falcon.queryVulnerabilities(parameters={"limit":1,"filter":"created_timestamp:>'2020-01-01T00:00:01Z'"})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSpotlight_getVulnerabilities(self): + if falcon.getVulnerabilities(ids=falcon.queryVulnerabilities(parameters={"limit":1,"filter":"created_timestamp:>'2020-01-01T00:00:01Z'"})["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceSpotlight_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + if falcon.queryVulnerabilities(parameters={})["status_code"] != 500: + errorChecks = False + if falcon.getVulnerabilities(ids="12345678")["status_code"] != 500: + errorChecks = False + + return errorChecks + + def test_queryVulnerabilities(self): + assert self.serviceSpotlight_queryVulnerabilities() == True + + @pytest.mark.skipif(falcon.queryVulnerabilities(parameters={"limit":1,"filter":"created_timestamp:>'2020-01-01T00:00:01Z'"})["status_code"] == 429, reason="API rate limit reached") + def test_getVulnerabilities(self): + assert self.serviceSpotlight_getVulnerabilities() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceSpotlight_GenerateErrors() == True \ No newline at end of file diff --git a/tests/test_uber_api_complete.py b/tests/test_uber_api_complete.py new file mode 100644 index 00000000..2f88347f --- /dev/null +++ b/tests/test_uber_api_complete.py @@ -0,0 +1,275 @@ +# test_uber_api_complete.py +# This class tests the uber class + +import json +import os +import sys +import pytest +import datetime +import hashlib +# Import our sibling src folder into the path +sys.path.append(os.path.abspath('src')) +# Classes to test - manually imported from our sibling folder +from falconpy import api_complete as FalconSDK +# Import perform_request from _util so we can test generating 405's directly +from falconpy._util import perform_request + +AllowedResponses = [200, 400, 415, 429, 500] + +if "DEBUG_API_ID" in os.environ and "DEBUG_API_SECRET" in os.environ: + config = {} + config["falcon_client_id"] = os.getenv("DEBUG_API_ID") + config["falcon_client_secret"] = os.getenv("DEBUG_API_SECRET") +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: + config = json.loads(file_config.read()) + else: + sys.exit(1) + +falcon = FalconSDK.APIHarness( + creds={ + "client_id": config["falcon_client_id"], + "client_secret": config["falcon_client_secret"] + } +) +falcon.authenticate() +if not falcon.authenticated: + sys.exit(1) + + +class TestUber: + def uberCCAWS_GetAWSSettings(self): + if falcon.command("GetAWSSettings")["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_QueryAWSAccounts(self): + if falcon.command("QueryAWSAccounts", parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_GetAWSAccounts(self): + if falcon.command("GetAWSAccounts", ids=falcon.command("QueryAWSAccounts", + parameters={"limit": 1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_VerifyAWSAccountAccess(self): + if falcon.command("VerifyAWSAccountAccess", ids=falcon.command("QueryAWSAccounts", + parameters={"limit": 1})["body"]["resources"][0]["id"])["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_QueryAWSAccountsForIDs(self): + if falcon.command("QueryAWSAccountsForIDs", parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_TestUploadDownload(self): + FILENAME = "tests/testfile.png" + fmt = '%Y-%m-%d %H:%M:%S' + stddate = datetime.datetime.now().strftime(fmt) + sdtdate = datetime.datetime.strptime(stddate, fmt) + sdtdate = sdtdate.timetuple() + jdate = sdtdate.tm_yday + jdate = "{}{}".format(stddate.replace("-", "").replace(":", "").replace(" ", ""), jdate) + SOURCE = "%s_source.png" % jdate + TARGET = "tests/%s_target.png" % jdate + PAYLOAD = open(FILENAME, 'rb').read() + response = falcon.command('UploadSampleV3', file_name=SOURCE, data=PAYLOAD, content_type="application/octet-stream") + sha = response["body"]["resources"][0]["sha256"] + response = falcon.command("GetSampleV3", parameters={}, ids=sha) + try: + open(TARGET, 'wb').write(response) + except TypeError: + return True + buf = 65536 + hash1 = hashlib.sha256() + with open(FILENAME, 'rb') as f: + while True: + data = f.read(buf) + if not data: + break + hash1.update(data) + hash1 = hash1.hexdigest() + hash2 = hashlib.sha256() + with open(TARGET, 'rb') as f: + while True: + data = f.read(buf) + if not data: + break + hash2.update(data) + hash2 = hash2.hexdigest() + if os.path.exists(TARGET): + os.remove(TARGET) + response = falcon.command("DeleteSampleV3", ids=sha) + if hash1 == hash2: + return True + else: + return False + + def uberCCAWS_GenerateError(self): + if falcon.command("QueryAWSAccounts", partition=0)["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_GenerateInvalidPayload(self): + if falcon.command("refreshActiveStreamSession", partition=9, + parameters={"action_name": "refresh_active_stream_session"})["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_OverrideAndHeader(self): + if falcon.command(action="", override="GET,/cloud-connect-aws/combined/accounts/v1", + headers={"Nothing": "Special"})["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_TestMSSP(self): + falcon.creds["member_cid"] = "1234567890ABCDEFG" + if not falcon.authenticate(): + falcon.creds.pop("member_cid") + return True + else: + falcon.creds.pop("member_cid") + return False + + def uberCCAWS_BadMethod(self): + if falcon.command(action="", override="BANANA,/cloud-connect-aws/combined/accounts/v1", + headers={"Nothing": "Special"})["status_code"] == 405: + return True + else: + return False + + def uberCCAWS_BadCommand(self): + if falcon.command(action="IWantTheImpossible", parameters={"limit": 1})["status_code"] == 418: + return True + else: + return False + + def uberCCAWS_GenerateServerError(self): + if falcon.command("GetAWSAccounts", ids="123", data=['Kerash!'])["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCHosts_GenerateActionNameError(self): + if falcon.command("PerformActionV2", parameters={}, body={}, action_name="Squish")["status_code"] in AllowedResponses: + return True + else: + return False + + def uberCCAWS_GenerateInvalidOperationIDError(self): + if perform_request(method="FETCH", endpoint="/somewhere/interesting")["status_code"] == 405: + return True + else: + return False + + def uberCCAWS_GenerateTokenError(self): + hold_token = falcon.token + falcon.token = "I am a bad token!" + if not falcon.deauthenticate(): + falcon.token = hold_token + return True + else: + falcon.token = hold_token + return False + + def uberCCAWS_BadAuthentication(self): + falcon = FalconSDK.APIHarness( + creds={ + "client_id": "BadClientID", + "client_secret": "BadClientSecret" + } + ) + if falcon.command("QueryAWSAccounts", parameters={"limit": 1})["status_code"] == 401: + return True + else: + return False + + def uberCCAWS_DisableSSLVerify(self): + falcon = FalconSDK.APIHarness( + creds={ + "client_id": config["falcon_client_id"], + "client_secret": config["falcon_client_secret"] + }, ssl_verify=False + ) + if falcon.command("QueryAWSAccounts", parameters={"limit": 1})["status_code"] in AllowedResponses: + return True + else: + return False + + def test_GetAWSSettings(self): + assert self.uberCCAWS_GetAWSSettings() == True + + def test_QueryAWSAccounts(self): + assert self.uberCCAWS_QueryAWSAccounts() == True + + @pytest.mark.skipif(falcon.command("QueryAWSAccounts", + parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + def test_GetAWSAccounts(self): + assert self.uberCCAWS_GetAWSAccounts() == True + + # @pytest.mark.skipif(falcon.command("QueryAWSAccounts", + # parameters={"limit": 1})["status_code"] == 429, reason="API rate limit reached") + # @pytest.mark.skipif(sys.version_info.minor < 9, reason="Frequency reduced due to potential race condition") + # def test_VerifyAWSAccountAccess(self): + # assert self.uberCCAWS_VerifyAWSAccountAccess() == True + + def test_QueryAWSAccountsForIDs(self): + assert self.uberCCAWS_QueryAWSAccountsForIDs() == True + + def test_UploadDownload(self): + assert self.uberCCAWS_TestUploadDownload() == True + + def test_GenerateError(self): + assert self.uberCCAWS_GenerateError() == True + + def test_GenerateInvalidPayload(self): + assert self.uberCCAWS_GenerateInvalidPayload() == True + + def test_BadCommand(self): + assert self.uberCCAWS_BadCommand() == True + + def test_OverrideAndHeader(self): + # Also check token auto-renewal + falcon.token_expiration = 0 + assert self.uberCCAWS_OverrideAndHeader() == True + + def test_GenerateActionNameError(self): + assert self.uberCCHosts_GenerateActionNameError() == True + + def test_GenerateInvalidOperationIDError(self): + assert self.uberCCAWS_GenerateInvalidOperationIDError() == True + + def test_BadMethod(self): + assert self.uberCCAWS_BadMethod() == True + + def test_GenerateServerError(self): + assert self.uberCCAWS_GenerateServerError() == True + + def test_TestMSSP(self): + assert self.uberCCAWS_TestMSSP() == True + + # def test_logout(self): + # assert falcon.deauthenticate() == True + + def test_GenerateTokenError(self): + assert self.uberCCAWS_GenerateTokenError() == True + + def test_BadAuthentication(self): + assert self.uberCCAWS_BadAuthentication() == True + + @pytest.mark.filterwarnings("ignore:Unverified HTTPS request is being made.*") + def test_DisableSSLVerify(self): + assert self.uberCCAWS_DisableSSLVerify() == True diff --git a/tests/test_user_management.py b/tests/test_user_management.py new file mode 100644 index 00000000..696a2a98 --- /dev/null +++ b/tests/test_user_management.py @@ -0,0 +1,114 @@ +# test_user_management.py +# This class tests the user_management service class + +import json +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 user_management as FalconUsers + +auth = Authorization.TestAuthorization() +auth.serviceAuth() +falcon = FalconUsers.User_Management(access_token=auth.token) +AllowedResponses = [200, 429] #Adding rate-limiting as an allowed response for now +class TestFalconUserManagement: + def serviceUserManagement_RetrieveEmailsByCID(self): + if falcon.RetrieveEmailsByCID()["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_RetrieveUserUUIDsByCID(self): + if falcon.RetrieveUserUUIDsByCID()["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_RetrieveUserUUID(self): + if falcon.RetrieveUserUUID(parameters={"uid": falcon.RetrieveEmailsByCID()["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_RetrieveUser(self): + if falcon.RetrieveUser(ids=falcon.RetrieveUserUUIDsByCID()["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_GetUserRoleIds(self): + if falcon.GetUserRoleIds(parameters={"user_uuid":falcon.RetrieveUserUUIDsByCID()["body"]["resources"][0]})["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_GetAvailableRoleIds(self): + if falcon.GetAvailableRoleIds()["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_GetRoles(self): + if falcon.GetRoles(ids=falcon.GetAvailableRoleIds()["body"]["resources"][0])["status_code"] in AllowedResponses: + return True + else: + return False + + def serviceUserManagement_GenerateErrors(self): + falcon.base_url = "nowhere" + errorChecks = True + commandList = [ + ["GetRoles","ids='12345678'"], + ["GrantUserRoleIds","body={}, parameters={}"], + ["RevokeUserRoleIds","ids='12345678', parameters={}"], + ["GetAvailableRoleIds",""], + ["GetUserRoleIds","parameters={}"], + ["RetrieveUser","ids='12345678'"], + ["CreateUser","body={}"], + ["DeleteUser","parameters={}"], + ["UpdateUser","body={}, parameters={}"], + ["RetrieveEmailsByCID",""], + ["RetrieveUserUUIDsByCID",""], + ["RetrieveUserUUID","parameters={}"] + ] + for cmd in commandList: + if eval("falcon.{}({})['status_code']".format(cmd[0],cmd[1])) != 500: + errorChecks = False + + return errorChecks + + def test_RetrieveEmailsByCID(self): + assert self.serviceUserManagement_RetrieveEmailsByCID() == True + + def test_RetrieveUserUUIDsByCID(self): + assert self.serviceUserManagement_RetrieveUserUUIDsByCID() == True + + @pytest.mark.skipif(falcon.RetrieveEmailsByCID()["status_code"] == 429, reason="API rate limit reached") + def test_RetrieveUserUUID(self): + assert self.serviceUserManagement_RetrieveUserUUID() == True + + @pytest.mark.skipif(falcon.RetrieveUserUUIDsByCID()["status_code"] == 429, reason="API rate limit reached") + def test_RetrieveUser(self): + assert self.serviceUserManagement_RetrieveUser() == True + + @pytest.mark.skipif(falcon.RetrieveUserUUIDsByCID()["status_code"] == 429, reason="API rate limit reached") + def test_GetUserRoleIds(self): + assert self.serviceUserManagement_GetUserRoleIds() == True + + def test_GetAvailableRoleIds(self): + assert self.serviceUserManagement_GetAvailableRoleIds() == True + + @pytest.mark.skipif(falcon.GetAvailableRoleIds()["status_code"] == 429, reason="API rate limit reached") + def test_GetRoles(self): + assert self.serviceUserManagement_GetRoles() == True + + def test_Logout(self): + assert auth.serviceRevoke() == True + + def test_Errors(self): + assert self.serviceUserManagement_GenerateErrors() == True \ No newline at end of file diff --git a/tests/testfile.png b/tests/testfile.png new file mode 100644 index 00000000..3495bd51 Binary files /dev/null and b/tests/testfile.png differ diff --git a/util/lint.sh b/util/lint.sh new file mode 100755 index 00000000..70c8b67e --- /dev/null +++ b/util/lint.sh @@ -0,0 +1,8 @@ +#!/bin/bash +if ! [[ -z "$1" ]] +then + TARGET=$1 +else + TARGET="." +fi +flake8 $TARGET --count --exit-zero --max-complexity=15 --max-line-length=127 --statistics \ No newline at end of file diff --git a/util/run-tests.sh b/util/run-tests.sh new file mode 100755 index 00000000..5c8de747 --- /dev/null +++ b/util/run-tests.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# At this point in time we are excluding FalconShell and FalconDebug from unit testing +# +coverage run --source=src/falconpy --omit=src/falconpy/debug.py -m pytest -s -v +coverage report +bandit -r src