Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions public/.github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Run formatter

on:
- push

permissions:
contents: read

jobs:
format:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: ./.github/workflows/install_deps

- name: Run formatter
run: poetry run black --check --diff .

- name: Run isort
run: poetry run isort --check-only --diff .

29 changes: 29 additions & 0 deletions public/.github/workflows/install_deps/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Based on https://github.com/marketplace/actions/python-poetry-action
name: Install deps

runs:
using: "composite"
steps:
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"

- name: Install poetry
uses: abatilo/actions-poetry@v4

- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
shell: bash

- uses: actions/cache@v3
name: Define a cache for the virtual environment based on the lock file
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}

- name: Install dependencies
run: poetry install
shell: bash
19 changes: 19 additions & 0 deletions public/.github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Run linter

on:
- push

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: ./.github/workflows/install_deps

- name: Run linter
run: poetry run pylint .
49 changes: 49 additions & 0 deletions public/.github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Based on https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/
name: Publish to PyPI

on:
release:
types:
- published
workflow_dispatch:
repository_dispatch:
types:
- trigger-publish

jobs:
build:
name: Build distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: ./.github/workflows/install_deps

- name: Build a binary wheel and a source tarball
run: poetry build

- name: Upload packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: Publish to PyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/armis_sdk
permissions:
id-token: write
steps:
- name: Download packages
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
53 changes: 53 additions & 0 deletions public/.github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Create release if needed

on:
push:
branches:
- master
workflow_dispatch:

jobs:
release:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"

- name: Install poetry
uses: abatilo/actions-poetry@v4

- name: Extract version
run: echo "VERSION=v$(poetry version -s)" >> $GITHUB_ENV

- name: Check if release exists
id: check-release-exists
uses: f2calv/gha-check-release-exists@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ReleaseName: ${{ env.VERSION }}

- name: Create release if needed
id: create-release
uses: actions/create-release@v1
if: steps.check-release-exists.outputs.ReleaseExists == 'false'
with:
tag_name: ${{ env.VERSION }}
release_name: ${{ env.VERSION }}
body: |
This is the release for version ${{ env.VERSION }}.
- Automatically created by GitHub Actions.
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Trigger publish to Pypi
uses: peter-evans/repository-dispatch@v3
if: steps.create-release.outcome == 'success'
with:
event-type: trigger-publish
30 changes: 30 additions & 0 deletions public/.github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Run tests

on:
- push

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: ./.github/workflows/install_deps

- name: Run tests
run: poetry run pytest -vv
mypy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: ./.github/workflows/install_deps

- name: Run mypy
run: poetry run mypy .

7 changes: 7 additions & 0 deletions public/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
.env
.idea
__pycache__
dist
local
site
13 changes: 13 additions & 0 deletions public/.readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 2

build:
os: ubuntu-lts-latest
tools:
python: "3.9"
jobs:
post_install:
- pip install poetry
- VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs

mkdocs:
configuration: mkdocs.yml
21 changes: 21 additions & 0 deletions public/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Armis, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

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 OR COPYRIGHT HOLDERS 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.
87 changes: 87 additions & 0 deletions public/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Armis SDK for Python 3.9+
[![Run tests](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/test.yml/badge.svg)](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/test.yml)
[![Run formatter](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/format.yml/badge.svg)](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/format.yml)
[![Run linter](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/lint.yml/badge.svg)](https://github.com/ArmisSecurity/armis-sdk-python/actions/workflows/lint.yml)

The Armis SDK is a package that encapsulates common use-cases for interacting with the [Armis platform](https://www.armis.com/).

## Installation
Use your favourite package manager to install the SDK, for example:
```shell
pip install armis_sdk
```

## Documentation
For full documentation, please visit our [dedicated](https://armis-python-sdk.readthedocs.io) site.

## Usage

All interaction with the SDK happens through the `ArmisSdk` class. You'll need five things:

1. **Audience**: The url of the tenant you want to interact with, including trailing slash (e.g. `https://acme.armis.com/`).
2. **Client ID**: The email address of the user account within the tenant that was used to generate the Client Secret.
3. **Client Secret**: The confidential credential generated by your customer within Armis, paired with the Client ID.
4. **Vendor ID**: An identifier unique to your developer account or integration, obtained when you register on our developer portal.
5. **Scopes**: The specific permissions required by your access token to interact with the desired API endpoints.

You can either provide these values using the environment variables `ARMIS_AUDIENCE`, `ARMIS_CLIENT_ID`, `ARMIS_CLIENT_SECRET`, `ARMIS_VENDOR_ID`, and `ARMIS_CLIENT_ID`:
```python
from armis_sdk import ArmisSdk

armis_sdk = ArmisSdk()
```

or by passing them explicitly:
```python
from armis_sdk import ArmisSdk
from armis_sdk import ClientCredentials

credentials = ClientCredentials(
audience="<audience>",
client_id="<client_id>",
client_secret="<client_secret>",
vendor_id="<vendor_id>",
scopes=["scope1", "scope2"],
)
armis_sdk = ArmisSdk(credentials=credentials)
```

> [!TIP]
> If you're building an application that interacts with multiple tenants, you can populate only the `ARMIS_VENDOR_ID` and `ARMIS_SCOPES` environment variable and pass the `audience`, `client_id` and `client_secret` explicitly:
> ```python
> from armis_sdk import ArmisSdk
> from armis_sdk import ClientCredentials
>
> credentials = ClientCredentials(
> audience="<audience>",
> client_id="<client_id>",
> client_secret="<client_secret>",
> )
> armis_sdk = ArmisSdk(credentials=credentials)
> ```

## Entity clients
Once you have an instance of `ArmisSdk`, you can start interacting with the various clients. Each handles use-cases of a specific entity.


> [!NOTE]
> Note that all functions in this SDK that eventually make HTTP requests are asynchronous.
>
> However, for convenience, all public asynchronous functions can also be executed in a synchronous way.

For example, if you want to update a site's location:
```python
import asyncio

from armis_sdk import ArmisSdk
from armis_sdk.entities.site import Site

armis_sdk = ArmisSdk()

async def main():
site = Site(id=1, location="new location")
await armis_sdk.sites.update(site)

asyncio.run(main())
```

2 changes: 2 additions & 0 deletions public/armis_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from armis_sdk.core.armis_sdk import ArmisSdk
from armis_sdk.core.client_credentials import ClientCredentials
Empty file.
Loading
Loading