Gremlin library for Python
Project description
gremlin-python
Project Status
This is an unoffical PythonSDK currently in alpha testing.
Installation
PyPi
pip3 install gremlinapi
Install from source
git clone git@github.com:gremlin/gremlin-python.git
cd gremlin-python
python3 setup.py install
Use Packaged Docker runtime
Build and run this project's self contained docker image with all the necessary dependencies
make docker-build && make docker-run-interactive
Usage
CLI
Coming soon
Authenticate to the API
The Gremlin API requires a form of authentication, either API Key or Bearer Token. API Keys are the least privileged form of authentication, are easy to manage and change, but do not allow for company wide actions see https://www.gremlin.com/docs/api-reference/overview/ for a list of which API endpoints support API Keys vs. Bearer Tokens.
A bearer token may be provided to the API instead of an API Key, and this allow the owner of the bearer token to use an escalated set of permissions and actions, pending the user has those roles in the RBAC schema. Because bearer tokens are short lived, the user may chose to use the login function instead of directly providing a bearer token. The downside to this is that user credentials are directly exposed, and may end up in logs. When using the login function, the Gremlin API will return a bearer token which will be used on the users behalf to execute API actions.
API User Keys
from gremlinapi.config import GremlinAPIConfig as config
config.api_key = 'Key MU3...ZiTk...Lo...4zO..c='
User Provided Bearer Token
from gremlinapi.config import GremlinAPIConfig as config
config.bearer_token = 'Bearer MU3...ZiTk...Lo...4zO..c='
User Login
import gremlinapi
gremlinapi.login(
email='user@gremlin.com',
password='looksL1keIshouldCh4ng3th1sagain!',
company_name="Gremlin Inc."
)
User Login with MFA
import gremlinapi
gremlinapi.login(
email='user@gremlin.com',
password='looksL1keIshouldCh4ng3th1sagain!',
company_name="Gremlin Inc.",
token="8675309"
)
Team IDs
When using a Gremlin RBAC enabled account, you must specify the teamId
to parameter for most requests. Additionally,
you may supply this globally via the GremlinAPIConfig
module:
from gremlinapi.config import GremlinAPIConfig as config
config.team_id = team_id
Proxy Support
This library supports system wide HTTP_PROXY
and HTTPS_PROXY
environment variables.
Additionally, proxy configuration may be directly configured inside the library, or the use of
GREMLIN_HTTP_PROXY
and GREMLIN_HTTPS_PROXY
can be utilized to isolate the communication stream.
Direct Proxy Configuration
from gremlinapi.config import GremlinAPIConfig as config
config.http_proxy = 'http://user:pass@myproxy:port'
config.https_proxy = 'https://user:pass@myproxy:port'
Examples
See Examples for more more functionality
Launching Attacks
Example 1
This will launch a 100ms latency attack, limited to ICMP traffic, against a single random container
with the ECS container-name swissknife
from gremlinapi.config import GremlinAPIConfig as config
from gremlinapi.attacks import GremlinAPIAttacks as attacks
config.bearer_token = 'Bearer MU....ziTk....40z...c='
config.team_id = 'e7352a6b-a9a0-513c-81e4-980f680a70c4'
body = {
'target': {
'type': 'Random',
'containers': {
'multiSelectLabels': {
"com.amazonaws.ecs.container-name": [
"swissknife"
]
}
},
'exact': 1
},
'command': {
'type': 'latency',
'commandType': 'Latency',
'args': [
'-l', '60',
'-h', '^api.gremlin.com',
'-m', '100',
'-P', 'ICMP'
],
'providers': []
}
}
attack_guid = attacks.create_attack(body=body, teamId=config.team_id)
Organization and Team management
List all teams
from gremlinapi.config import GremlinAPIConfig as config
from gremlinapi.orgs import GremlinAPIOrgs as orgs
config.bearer_token = 'Bearer MU3...ZiTk...Lo...4zO..c='
all_orgs = orgs.list_orgs()
import pprint
pprint.pprint(all_orgs)
[
{
'active': True,
'auto_add_users': False,
'certificate_expiration_imminent': False,
'certificate_expires_on': '2021-02-02T18:38:54.000Z',
'certificate_set_at': '2020-02-03T18:38:54.654Z',
'certificate_set_by': 'community@gremlin.com',
'company_id': '07814fbb-a9a0-81e4-b375-980f680a70c4',
'created_at': '2020-02-03T18:38:54.654Z',
'identifier': 'cb7ca0d3-4bac-542c-9059-3ee48df857fa',
'idle': False,
'name': 'testteam1',
'secret_set_at': '2020-02-03T18:38:54.654Z',
'secret_set_by': 'community@gremlin.com',
'updated_at': '2020-02-03T18:38:54.654Z'
},
{
'active': True,
'auto_add_users': False,
'certificate_expiration_imminent': False,
'certificate_expires_on': '2021-02-02T18:40:33.000Z',
'certificate_set_at': '2020-02-03T18:40:33.967Z',
'certificate_set_by': 'community@gremlin.com',
'company_id': '07814fbb-a9a0-81e4-b375-980f680a70c4',
'created_at': '2020-02-03T18:40:33.967Z',
'identifier': 'c049bf49-f236-5df7-9e2e-5c3858e32426',
'idle': False,
'name': 'testteam2',
'secret_set_at': '2020-02-03T18:40:33.967Z',
'secret_set_by': 'community@gremlin.com',
'updated_at': '2020-02-03T18:40:33.967Z'
},
{
'active': True,
'auto_add_users': False,
'certificate_expiration_imminent': False,
'certificate_expires_on': '2021-03-19T18:03:54.000Z',
'certificate_set_at': '2020-03-19T18:03:54.355Z',
'certificate_set_by': 'community@gremlin.com',
'company_id': '07814fbb-a9a0-81e4-b375-980f680a70c4',
'created_at': '2020-03-19T18:03:54.355Z',
'identifier': 'df51deb3-3fa6-5e9e-947f-9d5ef62418f1',
'idle': False,
'name': 'My New Awesome Team Name',
'updated_at': '2020-03-19T18:03:54.355Z'
}
]
Create a team
from gremlinapi.config import GremlinAPIConfig as config
from gremlinapi.orgs import GremlinAPIOrgs as orgs
config.bearer_token = 'Bearer MU3...ZiTk...Lo...4zO..c='
new_team_details = orgs.create_org(name='My New Awesome Team Name')
import pprint
pprint.pprint(new_team_details)
{
'has_secret': True,
'org_id': 'e7352a6b-a9a0-513c-81e4-980f680a70c4',
'pem_encoded_certificate': '-----BEGIN CERTIFICATE-----\nMIIBvDCCA ....=\n-----END CERTIFICATE-----\n',
'pem_encoded_private_key': '-----BEGIN EC PRIVATE KEY-----\nMHcCAQEE ....\n-----END EC PRIVATE KEY-----\n'
}
Scenarios
List all scenarios
from gremlinapi.config import GremlinAPIConfig as config
from gremlinapi.scenarios import GremlinAPIScenarios as scenarios
config.bearer_token = 'Bearer MU3...ZiTk...Lo...4zO..c='
team_id = 'e7352a6b-a9a0-513c-81e4-980f680a70c4'
scenarios_list = scenarios.list_scenarios(teamId=team_id)
import pprint
pprint.pprint(scenarios_list)
[
{
'create_source': 'WebApp',
'created_at': '2019-10-14T21:02:47.397Z',
'created_by': 'community@gremlin.com',
'description': 'Confidently adopt cloud auto-scaling services. Verify your '
'users have a positive experience and your application '
'behaves as expected while hosts come and go.',
'guid': 'ed49ebae-d45d-4412-89eb-aed45d841255',
'hypothesis': 'When CPU usage ramps up and hits a set threshold, active '
'instances will increase and decrease when CPU usage goes '
'down. User sessions will remain active without throwing any '
'errors.',
'last_run_at': '2019-10-14T21:02:47.865Z',
'name': 'Validate Auto-Scaling',
'org_id': 'e7352a6b-a9a0-513c-81e4-980f680a70c4',
'recommended_scenario_id': 'd543fb53-cbd8-4b92-83fb-53cbd8cb9250',
'state': 'PUBLISHED',
'steps': [{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'5',
'-a'
],
'length': 60,
'percent': 5
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'10',
'-a'
],
'length': 60,
'percent': 10
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'15',
'-a'
],
'length': 60,
'percent': 15
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'20',
'-a'
],
'length': 60,
'percent': 20
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
}
],
'tiers': ['Free', 'Enterprise'],
'updated_at': '2019-10-14T21:02:48.107Z'
},
{
'create_source': 'WebApp',
'created_at': '2019-10-14T20:36:59.952Z',
'created_by': 'community@gremlin.com',
'description': 'Confidently adopt cloud auto-scaling services. Verify your '
'users have a positive experience and your application '
'behaves as expected while hosts come and go.',
'guid': 'bdaeef1c-4dbd-47bd-aeef-1c4dbdf7bd3a',
'hypothesis': 'When CPU usage ramps up and hits a set threshold, active '
'instances will increase and decrease when CPU usage goes '
'down. User sessions will remain active without throwing any '
'errors.',
'last_run_at': '2019-10-14T20:37:00.128Z',
'name': 'Validate Auto-Scaling',
'org_id': 'e7352a6b-a9a0-513c-81e4-980f680a70c4',
'recommended_scenario_id': 'd543fb53-cbd8-4b92-83fb-53cbd8cb9250',
'state': 'PUBLISHED',
'steps': [{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'5',
'-a'
],
'length': 60,
'percent': 5
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'10',
'-a'
],
'length': 60,
'percent': 10
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'15',
'-a'
],
'length': 60,
'percent': 15
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
},
{
'attacks': [{
'attackType': 'ILFI',
'impactDefinition': {
'commandArgs': {
'allCores': True,
'cliArgs': ['cpu',
'-l',
'60',
'-p',
'20',
'-a'
],
'length': 60,
'percent': 20
},
'commandType': 'CPU'
},
'targetDefinition': {
'strategy': {
'percentage': 100
},
'strategyType': 'Random',
'targetType': 'Container'
}
}],
'delay': 5
}
],
'tiers': ['Free', 'Enterprise'],
'updated_at': '2019-10-14T20:37:00.314Z'
},
....
]
Create scenario
from gremlinapi.config import GremlinAPIConfig as config
from gremlinapi.attack_helpers import (
GremlinBlackholeAttack,
GremlinTargetContainers,
)
from gremlinapi.scenarios import GremlinAPIScenarios as scenarios
from gremlinapi.scenario_graph_helpers import (
GremlinScenarioGraphHelper,
GremlinScenarioILFINode,
GremlinScenarioDelayNode
)
# config.bearer_token = 'Bearer MU3...ZiTk...Lo...4zO..c='
config.api_key = "" #TODO: populate
config.team_id = "" #TODO: populate
blast_radius = 100
delay_time = 5
#create scenario
new_scenario = GremlinScenarioGraphHelper(
name="A Code-Created Scenario",
description="Python SDK created scenario",
hypothesis="No Hypothesis",
)
#create scenario nodes
black_hole_node_1 = GremlinScenarioILFINode(
command=GremlinBlackholeAttack(),
target=GremlinTargetContainers(
strategy_type="Random", labels={"owner": "kyle"}, percent=blast_radius
),
)
delay_node_1 = GremlinScenarioDelayNode(description="Add some delay", delay=delay_time)
black_hole_node_2 = GremlinScenarioILFINode(
command=GremlinBlackholeAttack(),
target=GremlinTargetContainers(
strategy_type="Random", labels={"owner": "kyle"}, percent=blast_radius
),
)
#add scenario nodes
new_scenario.add_node(black_hole_node_1)
new_scenario.add_node(black_hole_node_2)
new_scenario.add_node(delay_node_1)
#add node edges
new_scenario.add_edge(black_hole_node_1, delay_node_1)
new_scenario.add_edge(delay_node_1, black_hole_node_2)
#submit scenario to api
scenarios.create_scenario(body=new_scenario)
Support
Support for this library is provided by the Chaos Engineering community. Join us on slack!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file gremlinapi-0.12.2.tar.gz
.
File metadata
- Download URL: gremlinapi-0.12.2.tar.gz
- Upload date:
- Size: 50.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ffd822acec0360e5fe6621d3866539b2000b5648780eb8c3c6eb2d3dd5c0d42e |
|
MD5 | 071cbf0c4f40a54348ac2fb37ab4cea6 |
|
BLAKE2b-256 | bdfa5ed325720ee14242f522f578b1c1e20d1a3ddb765a4447fb3080da13c303 |
File details
Details for the file gremlinapi-0.12.2-py3-none-any.whl
.
File metadata
- Download URL: gremlinapi-0.12.2-py3-none-any.whl
- Upload date:
- Size: 76.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2e9c925f2b37001715da2cc587eb5873d1bde570ded5f5aabd99b3daed3acbe0 |
|
MD5 | 85797ad22eac5dcf6517841934a19572 |
|
BLAKE2b-256 | 19e45568f67a458cfc15bea62ee19a35aed1e7f27ceab877140d77ea9bd18ed7 |