Skip to content

Commit 277e0ab

Browse files
committed
add create_question with tests and examples
1 parent 09b917c commit 277e0ab

File tree

7 files changed

+1268
-0
lines changed

7 files changed

+1268
-0
lines changed

docs/create_question_usage.md

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Create Question Method Documentation
2+
3+
## Overview
4+
5+
The `create_question` method allows you to programmatically create questions in your JupiterOne account. Questions are saved queries that can be run on-demand or on a schedule to monitor your infrastructure and security posture.
6+
7+
## Method Signature
8+
9+
```python
10+
def create_question(
11+
self,
12+
title: str,
13+
queries: List[Dict],
14+
resource_group_id: str = None,
15+
**kwargs
16+
)
17+
```
18+
19+
## Parameters
20+
21+
### Required Parameters
22+
23+
- **`title`** (str): The title of the question. This is required and cannot be empty.
24+
25+
- **`queries`** (List[Dict]): A list of query objects. At least one query is required. Each query object can contain:
26+
- **`query`** (str, required): The J1QL query string
27+
- **`name`** (str, optional): Name for the query. Defaults to "Query{index}"
28+
- **`version`** (str, optional): Query version (e.g., "v1")
29+
- **`resultsAre`** (str, optional): Query result type. Defaults to "INFORMATIVE". Options include:
30+
- "INFORMATIVE" - Neutral information
31+
- "GOOD" - Positive/expected results
32+
- "BAD" - Negative/unexpected results
33+
- "UNKNOWN" - Unknown state
34+
35+
### Optional Parameters
36+
37+
- **`resource_group_id`** (str): ID of the resource group to associate the question with
38+
39+
### Additional Keyword Arguments (**kwargs)
40+
41+
- **`description`** (str): Description of the question
42+
- **`tags`** (List[str]): List of tags to apply to the question
43+
- **`compliance`** (Dict): Compliance metadata containing:
44+
- `standard` (str): Compliance standard name
45+
- `requirements` (List[str]): List of requirement IDs
46+
- `controls` (List[str]): List of control names
47+
- **`variables`** (List[Dict]): Variable definitions for parameterized queries
48+
- **`showTrend`** (bool): Whether to show trend data for the question results
49+
- **`pollingInterval`** (str): How often to run the queries (e.g., "ONE_HOUR", "ONE_DAY")
50+
- **`integrationDefinitionId`** (str): Integration definition ID if the question is integration-specific
51+
52+
## Return Value
53+
54+
Returns a dictionary containing the created question object with fields like:
55+
- `id`: Unique identifier for the question
56+
- `title`: The question title
57+
- `description`: The question description
58+
- `queries`: List of query objects
59+
- `tags`: Applied tags
60+
- And other metadata fields
61+
62+
## Examples
63+
64+
### Basic Question
65+
66+
```python
67+
from jupiterone import JupiterOneClient
68+
69+
j1_client = JupiterOneClient(
70+
account="your-account-id",
71+
token="your-api-token"
72+
)
73+
74+
# Create a simple question
75+
question = j1_client.create_question(
76+
title="Find All Open Hosts",
77+
queries=[{
78+
"query": "FIND Host WITH open=true",
79+
"name": "OpenHosts"
80+
}]
81+
)
82+
```
83+
84+
### Question with Multiple Queries
85+
86+
```python
87+
# Create a question with multiple queries for comprehensive checks
88+
question = j1_client.create_question(
89+
title="Security Compliance Check",
90+
queries=[
91+
{
92+
"query": "FIND Host WITH open=true",
93+
"name": "OpenHosts",
94+
"resultsAre": "BAD"
95+
},
96+
{
97+
"query": "FIND User WITH mfaEnabled=false",
98+
"name": "UsersWithoutMFA",
99+
"resultsAre": "BAD"
100+
},
101+
{
102+
"query": "FIND DataStore WITH encrypted=false",
103+
"name": "UnencryptedDataStores",
104+
"resultsAre": "BAD"
105+
}
106+
],
107+
description="Comprehensive security compliance check",
108+
tags=["security", "compliance", "audit"]
109+
)
110+
```
111+
112+
### Advanced Question with All Options
113+
114+
```python
115+
# Create a question with all optional parameters
116+
question = j1_client.create_question(
117+
title="AWS Security Audit",
118+
queries=[{
119+
"query": "FIND aws_instance WITH publicIpAddress!=undefined",
120+
"name": "PublicInstances",
121+
"version": "v1",
122+
"resultsAre": "INFORMATIVE"
123+
}],
124+
resource_group_id="resource-group-123",
125+
description="Audit AWS instances with public IP addresses",
126+
tags=["aws", "security", "network"],
127+
showTrend=True,
128+
pollingInterval="ONE_DAY",
129+
compliance={
130+
"standard": "CIS",
131+
"requirements": ["2.1", "2.2"],
132+
"controls": ["Network Security"]
133+
},
134+
variables=[
135+
{
136+
"name": "environment",
137+
"required": False,
138+
"default": "production"
139+
}
140+
]
141+
)
142+
```
143+
144+
### Minimal Question
145+
146+
```python
147+
# Create a question with only required parameters
148+
# The query name will default to "Query0" and resultsAre to "INFORMATIVE"
149+
question = j1_client.create_question(
150+
title="Simple Query",
151+
queries=[{
152+
"query": "FIND User LIMIT 10"
153+
}]
154+
)
155+
```
156+
157+
## Error Handling
158+
159+
The method includes validation for required fields and will raise `ValueError` exceptions for:
160+
- Missing or empty `title`
161+
- Missing or empty `queries` list
162+
- Invalid query format (not a dictionary)
163+
- Missing required `query` field in query objects
164+
165+
```python
166+
try:
167+
question = j1_client.create_question(
168+
title="", # This will raise an error
169+
queries=[]
170+
)
171+
except ValueError as e:
172+
print(f"Error: {e}")
173+
```
174+
175+
## GraphQL Mutation
176+
177+
The method uses the following GraphQL mutation internally:
178+
179+
```graphql
180+
mutation CreateQuestion($question: CreateQuestionInput!) {
181+
createQuestion(question: $question) {
182+
id
183+
title
184+
description
185+
tags
186+
queries {
187+
name
188+
query
189+
version
190+
resultsAre
191+
}
192+
# ... other fields
193+
}
194+
}
195+
```
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python3
2+
"""
3+
JupiterOne Python SDK - Account Parameter (List Value) Example
4+
5+
This example demonstrates how to create or update an Account Parameter where the
6+
value is a list of strings.
7+
8+
Prerequisites (environment variables):
9+
- JUPITERONE_ACCOUNT_ID
10+
- JUPITERONE_API_TOKEN
11+
- (optional) JUPITERONE_URL
12+
- (optional) JUPITERONE_SYNC_URL
13+
14+
Usage:
15+
python 07_account_parameters_list_example.py
16+
"""
17+
18+
import os
19+
from jupiterone import JupiterOneClient
20+
21+
22+
def setup_client() -> JupiterOneClient:
23+
"""Instantiate the JupiterOne client using environment variables."""
24+
return JupiterOneClient(
25+
account=os.getenv("JUPITERONE_ACCOUNT_ID"),
26+
token=os.getenv("JUPITERONE_API_TOKEN"),
27+
url=os.getenv("JUPITERONE_URL", "https://graphql.us.jupiterone.io"),
28+
sync_url=os.getenv("JUPITERONE_SYNC_URL", "https://api.us.jupiterone.io"),
29+
)
30+
31+
32+
def main() -> None:
33+
print("JupiterOne - Create/Update Account Parameter (List Value)")
34+
print("=" * 70)
35+
36+
# Configure the parameter name and value
37+
# Name can be anything meaningful to your workflows
38+
parameter_name = os.getenv("J1_LIST_PARAM_NAME", "ENTITY_TYPES_TO_INCLUDE")
39+
40+
# Example list value requested: ["aws_account", "aws_security_group"]
41+
parameter_value = ["aws_account", "aws_security_group"]
42+
43+
try:
44+
j1 = setup_client()
45+
46+
print(f"Creating/Updating parameter '{parameter_name}' with value: {parameter_value}")
47+
result = j1.create_update_parameter(
48+
name=parameter_name,
49+
value=parameter_value,
50+
secret=False,
51+
)
52+
53+
# The mutation returns a success flag; fetch the parameter to verify
54+
if result and result.get("setParameter", {}).get("success") is True:
55+
print("✓ Parameter upsert reported success")
56+
else:
57+
print("! Parameter upsert did not report success (check details below)")
58+
print(result)
59+
60+
# Verify by reading it back (non-secret parameters will return the value)
61+
details = j1.get_parameter_details(name=parameter_name)
62+
print("\nFetched parameter details:")
63+
print(details)
64+
65+
print("\n✓ Completed creating/updating list-valued account parameter")
66+
67+
except Exception as exc:
68+
print(f"✗ Error: {exc}")
69+
print("\nMake sure you have set the following environment variables:")
70+
print("- JUPITERONE_ACCOUNT_ID")
71+
print("- JUPITERONE_API_TOKEN")
72+
print("- JUPITERONE_URL (optional)")
73+
print("- JUPITERONE_SYNC_URL (optional)")
74+
75+
76+
if __name__ == "__main__":
77+
main()
78+
79+

0 commit comments

Comments
 (0)