# Armis Python Library
<p align="center"><strong>armis</strong> <em>- A Python library for interacting with the Armis cloud.</em></p>
<p align="center">
<img src="https://img.shields.io/pypi/l/armis?style=flat-square">
<img src="https://img.shields.io/pypi/pyversions/armis?style=flat-square">
<img src="https://img.shields.io/librariesio/release/pypi/armis?style=flat-square">
<img src="https://img.shields.io/github/last-commit/mmlange/armis-python?style=flat-square">
<a href="https://github.com/mmlange/armis-python/actions"><img src="https://img.shields.io/github/actions/workflow/status/mmlange/armis-python/testsuite.yml?style=flat-square"></a>
<a href="https://www.pypi.com/projects/armis/"><img src="https://img.shields.io/pypi/v/armis?style=flat-square&logo=python"></a>
<a href="https://makeapullrequest.com"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square"></a>
</p>
**armis** is a Python client library for interacting with the Armis cloud. It connects using **HTTP/2** by default,
falling back to **HTTP/1.1** when necessary. Python 3.9 or later is supported.
---
Install **armis** using pip:
```console
$ pip install armis
```
# A Quick Demo of Features
## Getting Started
First, let's create an ArmisCloud object:
```python
from armis import ArmisCloud
a = ArmisCloud(
api_secret_key="your-api-secret-key-here",
tenant_hostname="your-tenant-hostname-here.armis.com"
)
```
## Device Operations
Let's get a list of all devices matching our ASQ and only retrieve a few fields:
```python
devices = a.get_devices(
asq='in:devices timeFrame:"10 Seconds"',
fields=["id", "ipAddress", "name", "firstSeen"]
)
print(devices)
[{"id": 15, "ipAddress": "10.1.2.3", "name": "super-pc", "firstSeen": "2019-05-15T13:00:00+00:00"}]
```
## Queries
If you need to execute ASQ beyond what `get_devices` gives you, use `get_search`:
```python
activities = armis_object.get_search(
asq='in:activity timeFrame:"1 Hours"',
fields_wanted=["activityUUID"],
)
print(activities)
[
{
"activityUUID": "abc12345678901234567"
},
{
"activityUUID": "def12345678901234567"
}
]
```
## Boundary Operations
Let's get all of the boundaries known to the system:
```python
boundaries = a.get_boundaries()
print(boundaries)
{1: {'affectedSites': '', 'id': 1, 'name': 'Corporate', 'ruleAql': {'or': ['ipAddress:10.0.0.0/8']}}, 2: {'affectedSites': '', 'id': 2, 'name': 'Guest', 'ruleAql': {'or': ['lastConnectedSsid:Guest']}}}
```
Let's get only one boundary by ID:
```python
boundaryone = a.get_boundary(boundary_id=1)
print(boundaryone)
{"data":{"affectedSites":"","id":1,"name":"Corporate","ruleAql":{"or":["ipAddress:10.0.0.0/8"]}},"success":true}
```
Deleting a boundary is easy:
```python
result = a.delete_boundary(boundary_id=3424234)
print(result)
{"success": True}
```
Creating a boundary is easy, though the syntax is not yet documented well here:
```python
result = a.create_boundary(
name="My New Boundary",
ruleaql={ "or": [
"ipAddress:10.0.0.0/24"
]
}
)
print(result)
{'data': {'id': 392309238}, 'success': True}
```
## Collector Operations
Get a list of collectors:
```python
collectors = a.get_collectors()
print(collectors)
{1234: {'clusterId': 0, 'collectorNumber': 1234, 'defaultGateway': '10.0.0.1', 'httpsProxyRedacted': '', 'ipAddress': '10.0.0.2', 'lastSeen': '2019-05-15T13:00:00+00:00', 'macAddress': '00:12:34:56:78:90', 'name': 'Collector 1234', 'status': 'Offline', 'subnet': '10.0.0.0/24', 'type': 'Physical'}}
```
Get the details for a specific collector:
```python
myimportantcollector = a.get_collector(collector_id=1234)
print(myimportantcollector)
{'clusterId': 0, 'collectorNumber': 1234, 'defaultGateway': '10.0.0.1', 'httpsProxyRedacted': '', 'ipAddress': '10.0.0.2', 'lastSeen': '2019-05-15T13:00:00+00:00', 'macAddress': '00:12:34:56:78:90', 'name': 'Collector 1234', 'status': 'Offline', 'subnet': '10.0.0.0/24', 'type': 'Physical'}
```
## Integration Operations
Get a list of integrations:
```python
integrations = a.get_integrations()
print(integrations)
[{"changeTime":1715778000000,"collectorId":1234,"creationTime":1715778000000,"currentState":null,"enforcementLists":[],"id":20,"instance":"SPAN eno5","integrationState":"ACTIVE","lastRunEnd":null,"name":"SPAN/TAP","params":{"sniff_interface":"eno5"}},{"changeTime":1715778000000,"collectorId":1234,"creationTime":1715778000000,"currentState":null,"enforcementLists":[],"id":21,"instance":"SPAN eno6","integrationState":"ACTIVE","lastRunEnd":null,"name":"SPAN/TAP","params":{"sniff_interface":"eno6"}}]
```
Get the details for a specific integration:
```python
integration = a.get_integration(20)
print(integration)
{"changeTime":1715778000000,"collectorId":1234,"creationTime":1715778000000,"currentState":null,"enforcementLists":[],"id":20,"instance":"SPAN eno5","integrationState":"ACTIVE","lastRunEnd":null,"name":"SPAN/TAP","params":{"sniff_interface":"eno5"},"statistics":null}
```
Create an integration:
```python
newintegration = a.create_integration(
collector_id=20,
integration_name="collector 20 capture on eno6",
integration_type="SWITCH",
integration_params={"sniff_interface": "eno5"}
)
print(newintegration)
{"data":{"changeTime":1715778000000,"collectorId":20,"creationTime":1715778000000,"currentState":null,"enforcementLists":[],"id":1234,"instance":"collector 20 capture on eno6","integrationState":"ACTIVE","lastRunEnd":null,"name":"SPAN/TAP","params":{"sniff_interface":"eno6"},"statistics":null},"success":true}
```
Delete an integration:
```python
result = a.delete_integration(20)
print(result)
{'success': True}
```
## User Operations
Get a list of users:
```python
users = a.get_users()
print(users)
{12: {'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}}
```
Get the details for a specific user, either by userid or email address:
```python
a_user = a.get_user(12)
{'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}
a_user = a.get_user('johndoe@example.com')
{'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}
```
Delete a user by user_id or email address:
```python
a.delete_user('12')
```
## Features
**armis** gives you:
* Easy connection to the Armis cloud using an API secret key.
* A quick way to fetch devices from the cloud.
* Retries in the event the cloud times out. This can happen with large queries that take more than 2 minutes. This is the default for CloudFlare, which front-ends the cloud infrastructure.
* Mostly type annotated.
* Nearly 100% test coverage.
## Installation
Install with pip:
```console
$ pip install armis
```
**armis** requires Python 3.9 or later.
## Dependencies
**armis** relies on these excellent libraries:
* [httpx](https://github.com/encode/httpx/) - The underlying transport implementation for making HTTP requests
* [msgspec](https://github.com/jcrist/msgspec) - for lightning fast decoding of JSON
* [pendulum](https://github.com/sdispater/pendulum) - for easy date/time management
* [tenacity](https://github.com/jd/tenacity) - retry management when things fail, with great retry/backoff options
## License
`armis` is distributed under the terms of the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) license.
Raw data
{
"_id": null,
"home_page": null,
"name": "armis",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "Matthew Lange <mmlange@gmail.com>",
"keywords": "api, armis, development",
"author": null,
"author_email": "Matthew Lange <mmlange@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/c0/bd/6d19c9ab8c42ec770208295ab413b7411e1d34909ed2c41e2c8971511446/armis-1.0.23.tar.gz",
"platform": null,
"description": "# Armis Python Library\n\n<p align=\"center\"><strong>armis</strong> <em>- A Python library for interacting with the Armis cloud.</em></p>\n\n<p align=\"center\">\n<img src=\"https://img.shields.io/pypi/l/armis?style=flat-square\">\n<img src=\"https://img.shields.io/pypi/pyversions/armis?style=flat-square\">\n<img src=\"https://img.shields.io/librariesio/release/pypi/armis?style=flat-square\">\n<img src=\"https://img.shields.io/github/last-commit/mmlange/armis-python?style=flat-square\">\n<a href=\"https://github.com/mmlange/armis-python/actions\"><img src=\"https://img.shields.io/github/actions/workflow/status/mmlange/armis-python/testsuite.yml?style=flat-square\"></a>\n<a href=\"https://www.pypi.com/projects/armis/\"><img src=\"https://img.shields.io/pypi/v/armis?style=flat-square&logo=python\"></a>\n<a href=\"https://makeapullrequest.com\"><img src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\"></a>\n</p>\n\n**armis** is a Python client library for interacting with the Armis cloud. It connects using **HTTP/2** by default,\nfalling back to **HTTP/1.1** when necessary. Python 3.9 or later is supported.\n\n---\n\nInstall **armis** using pip:\n\n```console\n$ pip install armis\n```\n\n# A Quick Demo of Features\n\n## Getting Started\nFirst, let's create an ArmisCloud object:\n```python\nfrom armis import ArmisCloud\n\na = ArmisCloud(\n api_secret_key=\"your-api-secret-key-here\",\n tenant_hostname=\"your-tenant-hostname-here.armis.com\"\n)\n```\n\n## Device Operations\nLet's get a list of all devices matching our ASQ and only retrieve a few fields:\n\n```python\ndevices = a.get_devices(\n asq='in:devices timeFrame:\"10 Seconds\"',\n fields=[\"id\", \"ipAddress\", \"name\", \"firstSeen\"]\n)\nprint(devices)\n\n[{\"id\": 15, \"ipAddress\": \"10.1.2.3\", \"name\": \"super-pc\", \"firstSeen\": \"2019-05-15T13:00:00+00:00\"}]\n```\n\n## Queries\nIf you need to execute ASQ beyond what `get_devices` gives you, use `get_search`:\n```python\nactivities = armis_object.get_search(\n asq='in:activity timeFrame:\"1 Hours\"',\n fields_wanted=[\"activityUUID\"],\n)\n\nprint(activities)\n[\n {\n \"activityUUID\": \"abc12345678901234567\"\n },\n {\n \"activityUUID\": \"def12345678901234567\"\n }\n]\n```\n\n## Boundary Operations\n\nLet's get all of the boundaries known to the system:\n```python\nboundaries = a.get_boundaries()\nprint(boundaries)\n\n{1: {'affectedSites': '', 'id': 1, 'name': 'Corporate', 'ruleAql': {'or': ['ipAddress:10.0.0.0/8']}}, 2: {'affectedSites': '', 'id': 2, 'name': 'Guest', 'ruleAql': {'or': ['lastConnectedSsid:Guest']}}}\n```\n\nLet's get only one boundary by ID:\n```python\nboundaryone = a.get_boundary(boundary_id=1)\nprint(boundaryone)\n\n{\"data\":{\"affectedSites\":\"\",\"id\":1,\"name\":\"Corporate\",\"ruleAql\":{\"or\":[\"ipAddress:10.0.0.0/8\"]}},\"success\":true}\n```\n\nDeleting a boundary is easy:\n\n```python\nresult = a.delete_boundary(boundary_id=3424234)\nprint(result)\n{\"success\": True}\n```\n\nCreating a boundary is easy, though the syntax is not yet documented well here:\n```python\nresult = a.create_boundary(\n name=\"My New Boundary\",\n ruleaql={ \"or\": [\n \"ipAddress:10.0.0.0/24\"\n ]\n }\n)\nprint(result)\n{'data': {'id': 392309238}, 'success': True}\n```\n\n## Collector Operations\nGet a list of collectors:\n\n```python\ncollectors = a.get_collectors()\nprint(collectors)\n\n{1234: {'clusterId': 0, 'collectorNumber': 1234, 'defaultGateway': '10.0.0.1', 'httpsProxyRedacted': '', 'ipAddress': '10.0.0.2', 'lastSeen': '2019-05-15T13:00:00+00:00', 'macAddress': '00:12:34:56:78:90', 'name': 'Collector 1234', 'status': 'Offline', 'subnet': '10.0.0.0/24', 'type': 'Physical'}}\n```\n\nGet the details for a specific collector:\n\n```python\nmyimportantcollector = a.get_collector(collector_id=1234)\nprint(myimportantcollector)\n\n{'clusterId': 0, 'collectorNumber': 1234, 'defaultGateway': '10.0.0.1', 'httpsProxyRedacted': '', 'ipAddress': '10.0.0.2', 'lastSeen': '2019-05-15T13:00:00+00:00', 'macAddress': '00:12:34:56:78:90', 'name': 'Collector 1234', 'status': 'Offline', 'subnet': '10.0.0.0/24', 'type': 'Physical'}\n```\n\n## Integration Operations\nGet a list of integrations:\n\n```python\nintegrations = a.get_integrations()\nprint(integrations)\n[{\"changeTime\":1715778000000,\"collectorId\":1234,\"creationTime\":1715778000000,\"currentState\":null,\"enforcementLists\":[],\"id\":20,\"instance\":\"SPAN eno5\",\"integrationState\":\"ACTIVE\",\"lastRunEnd\":null,\"name\":\"SPAN/TAP\",\"params\":{\"sniff_interface\":\"eno5\"}},{\"changeTime\":1715778000000,\"collectorId\":1234,\"creationTime\":1715778000000,\"currentState\":null,\"enforcementLists\":[],\"id\":21,\"instance\":\"SPAN eno6\",\"integrationState\":\"ACTIVE\",\"lastRunEnd\":null,\"name\":\"SPAN/TAP\",\"params\":{\"sniff_interface\":\"eno6\"}}]\n\n```\n\nGet the details for a specific integration:\n\n```python\nintegration = a.get_integration(20)\nprint(integration)\n\n{\"changeTime\":1715778000000,\"collectorId\":1234,\"creationTime\":1715778000000,\"currentState\":null,\"enforcementLists\":[],\"id\":20,\"instance\":\"SPAN eno5\",\"integrationState\":\"ACTIVE\",\"lastRunEnd\":null,\"name\":\"SPAN/TAP\",\"params\":{\"sniff_interface\":\"eno5\"},\"statistics\":null}\n\n```\n\nCreate an integration:\n\n```python\nnewintegration = a.create_integration(\n collector_id=20,\n integration_name=\"collector 20 capture on eno6\",\n integration_type=\"SWITCH\",\n integration_params={\"sniff_interface\": \"eno5\"}\n)\n\nprint(newintegration)\n{\"data\":{\"changeTime\":1715778000000,\"collectorId\":20,\"creationTime\":1715778000000,\"currentState\":null,\"enforcementLists\":[],\"id\":1234,\"instance\":\"collector 20 capture on eno6\",\"integrationState\":\"ACTIVE\",\"lastRunEnd\":null,\"name\":\"SPAN/TAP\",\"params\":{\"sniff_interface\":\"eno6\"},\"statistics\":null},\"success\":true}\n```\n\nDelete an integration:\n\n```python\nresult = a.delete_integration(20)\nprint(result)\n{'success': True}\n\n```\n\n\n## User Operations\nGet a list of users:\n```python\nusers = a.get_users()\nprint(users)\n\n{12: {'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}}\n```\n\nGet the details for a specific user, either by userid or email address:\n```python\na_user = a.get_user(12)\n{'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}\n\na_user = a.get_user('johndoe@example.com')\n{'email': 'johndoe@example.com', 'id': 12, 'isActive': True, 'lastLoginTime': '2019-05-15T13:01:23.456789', 'location': '', 'name': 'John Doe', 'phone': '', 'povEulaSigningDate': None, 'prodEulaSigningDate': None, 'reportPermissions': None, 'role': None, 'roleAssignment': [{'name': ['Admin']}], 'title': '', 'twoFactorAuthentication': False, 'username': 'johndoe'}\n```\n\nDelete a user by user_id or email address:\n```python\na.delete_user('12')\n```\n\n## Features\n\n**armis** gives you:\n\n* Easy connection to the Armis cloud using an API secret key.\n* A quick way to fetch devices from the cloud.\n* Retries in the event the cloud times out. This can happen with large queries that take more than 2 minutes. This is the default for CloudFlare, which front-ends the cloud infrastructure.\n* Mostly type annotated.\n* Nearly 100% test coverage.\n\n\n## Installation\n\nInstall with pip:\n\n```console\n$ pip install armis\n```\n\n**armis** requires Python 3.9 or later.\n\n## Dependencies\n**armis** relies on these excellent libraries:\n* [httpx](https://github.com/encode/httpx/) - The underlying transport implementation for making HTTP requests\n* [msgspec](https://github.com/jcrist/msgspec) - for lightning fast decoding of JSON\n* [pendulum](https://github.com/sdispater/pendulum) - for easy date/time management\n* [tenacity](https://github.com/jd/tenacity) - retry management when things fail, with great retry/backoff options\n\n## License\n`armis` is distributed under the terms of the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) license.\n",
"bugtrack_url": null,
"license": null,
"summary": "Connect and perform actions with the Armis cloud",
"version": "1.0.23",
"project_urls": {
"Homepage": "https://github.com/mmlange/armis-python/",
"Issues": "https://github.com/mmlange/armis-python/issues",
"Source": "https://github.com/mmlange/armis-python/"
},
"split_keywords": [
"api",
" armis",
" development"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d13fcd0c42fb1ecde14aeb224c7af1f2e5f9f6543780b6448f507a69fdbfab5a",
"md5": "77aff4c3c27799c213f73cf0d042395b",
"sha256": "45d0c4941c784a586c4bf91f390c8d446ee2a705312bf7235830c69f71d26c46"
},
"downloads": -1,
"filename": "armis-1.0.23-py3-none-any.whl",
"has_sig": false,
"md5_digest": "77aff4c3c27799c213f73cf0d042395b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 16240,
"upload_time": "2024-12-09T05:25:33",
"upload_time_iso_8601": "2024-12-09T05:25:33.411097Z",
"url": "https://files.pythonhosted.org/packages/d1/3f/cd0c42fb1ecde14aeb224c7af1f2e5f9f6543780b6448f507a69fdbfab5a/armis-1.0.23-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c0bd6d19c9ab8c42ec770208295ab413b7411e1d34909ed2c41e2c8971511446",
"md5": "eab144da0213dd1d94d180fcf07eaf65",
"sha256": "a112d3c2d45f13bf74f5a372bf4c131ee1db03f598576d422627710de443ede9"
},
"downloads": -1,
"filename": "armis-1.0.23.tar.gz",
"has_sig": false,
"md5_digest": "eab144da0213dd1d94d180fcf07eaf65",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 21414,
"upload_time": "2024-12-09T05:25:31",
"upload_time_iso_8601": "2024-12-09T05:25:31.755197Z",
"url": "https://files.pythonhosted.org/packages/c0/bd/6d19c9ab8c42ec770208295ab413b7411e1d34909ed2c41e2c8971511446/armis-1.0.23.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-09 05:25:31",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mmlange",
"github_project": "armis-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "httpx",
"specs": [
[
"==",
"0.28.1"
]
]
},
{
"name": "msgspec",
"specs": [
[
"==",
"0.18.6"
]
]
},
{
"name": "pendulum",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "tenacity",
"specs": [
[
"==",
"9.0.0"
]
]
},
{
"name": "loguru",
"specs": [
[
"==",
"0.7.3"
]
]
}
],
"lcname": "armis"
}