Incorporating new components into existing systems is such a pain, this process has been labeled “Integration Hell”. To ease tool integration, Ghostwriter v3.0.0 shipped with a GraphQL API. This API allows outside entities to easily query and manipulate Ghostwriter’s data. In this blogpost, we’ll use our Operation Log Generator to demonstrate the capabilities of this API.
Ghostwriter’s GraphQL API is driven by the Hasura GraphQL Engine. This engine provides three broad GraphQL operations:
Queries – Query operations fetch data from Ghostwriter
query domainQueryID {
domain(where: {name: {eq: "mydomain.com"}}) {
id
}
}
Mutations – Mutation operations manipulate Ghostwriter data
mutation createSampleClient {
insert_client_one(object: {name: "SpecterPops", codename: "SAMPLE CLIENT", timezone: "America/Los_Angeles"}) {
id
}
}
Subscriptions – Subscription operations allow applications to receive data in real-time
subscription domainHealthMonitoring {
domain(where: {healthStatus: {healthStatus: {_neq: "Healthy"}}}) {
id
name
}
}
Ghostwriter’s GraphQL schema can be explored in two different ways:
The GraphQL operations defined by the schema provide powerful methods for Ghostwriter data management and the API allows external tools to easily leverage these operations. For example, our Python Operation Log Generator script leverages GraphQL mutation operations to create and fill a Ghostwriter operation log with entries we commonly see on our operations.
The Operation Log Generator uses a serries of Ghostwriter GraphQL mutations to create and populate an operation log. These mutations include:
These five API calls are all it takes to link our operation log generator to Ghostwriter! Let’s take a closer look at how our script actually implements these calls.
The script first sets up token-based authentication with Ghostwriter. The steps to authenticate are outlined in Ghostwriter’s documentation, but at a high level, the program first use a username and password obtain a JWT with a login GraphQL API call.
def get_logon_token(credentials):
# Prepare our initial unauthenticated GraphQL client
transport = AIOHTTPTransport(credentials.url)
client = Client(transport=transport, fetch_schema_from_transport=True)# Define our gql query
get_logon_token_query = gql(
"""
mutation login_mutation($password: String!, $username: String!) {
login(password: $password, username: $username) {
token expires
}
}
"""
)
get_logon_token_query_params = {
"password": credentials.password,
"username": credentials.username
}# Login and get our token
login_result = client.execute(
get_logon_token_query,
variable_values=get_logon_token_query_params
)
return login_result["login"]["token"] # pylint: disable=unsubscriptable-object...
The script then creates a GQL Client object and uses the obtained JWT as the bearer token in an HTTP Authroization header.
...
from gql import Client, gql
...
# Use credential configs to get a Ghostwriter token
gw_auth_token = get_logon_token(credentials)# Set up token-based authentication
headers = {"Authorization": f"Bearer {gw_auth_token}"}
transport = AIOHTTPTransport(credentials.url, headers=headers)
authenticated_client = Client(transport=transport, fetch_schema_from_transport=True)
...
This GQL Client object is then used to execute all other GQL operations.
Once a GQL Client object has been created, executing operations is a simple three step process.
def create_sample_client(gql_client):
CLIENT_NAME = "SpecterPops"
CLIENT_CODENAME = "SAMPLE CLIENT"
TIMEZONE = "America/Los_Angeles"# Define our GQL string
sample_client = gql(
"""
mutation create_sample_client(
$client_name: String!,
$code_name: String!,
$timezone: String!
) {
insert_client_one(
object: {
name: $client_name,
codename: $code_name,
timezone: $timezone
}
) {
id
}
}
"""
)create_sample_client_param = {
"client_name": CLIENT_NAME,
"code_name": CLIENT_CODENAME,
"timezone": TIMEZONE
}result = gql_client.execute(sample_client, variable_values=create_sample_client_param)
return result
Ghostwriter’s GraphQL API allowed us to quickly link our Operation Log Generator to Ghostwriter. Now, we can test procedurally-generated operation logs to our heart’s content.
Ghostwriter ❤ Tool Integration was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.
*** This is a Security Bloggers Network syndicated blog from Posts By SpecterOps Team Members - Medium authored by Alexander Sou. Read the original post at: https://posts.specterops.io/ghostwriter-tool-integration-2dfbb952eb8a?source=rss----f05f8696e3cc---4