Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
277e0ab
add create_question with tests and examples
SeaBlooms Aug 14, 2025
72ee82f
Update 08_questions_management.py
SeaBlooms Aug 14, 2025
c9d201e
Potential fix for code scanning alert no. 115: Unused import
SeaBlooms Aug 14, 2025
24e9fde
Potential fix for code scanning alert no. 116: Unused import
SeaBlooms Aug 14, 2025
dc1dadf
Potential fix for code scanning alert no. 113: Unused local variable
SeaBlooms Aug 14, 2025
a8e952f
Potential fix for code scanning alert no. 117: Unused import
SeaBlooms Aug 15, 2025
9a93211
Update test_create_question.py
SeaBlooms Aug 15, 2025
7cdaf91
Merge branch 'KNO-606' of https://github.com/JupiterOne/jupiterone-ap…
SeaBlooms Aug 15, 2025
594241a
Update test_create_question.py
SeaBlooms Aug 15, 2025
4a097e8
add list_questions() documentation
SeaBlooms Aug 15, 2025
750e6e9
add keyword search and tag filtering to list_questions()
SeaBlooms Aug 15, 2025
84fe389
add get_question_details() method
SeaBlooms Aug 15, 2025
2b229be
add get_cft_upload_url() and update client to use deleteEntityV2
SeaBlooms Aug 19, 2025
014d97b
add new CFT methods and create usage example script
SeaBlooms Aug 19, 2025
35f2056
remove unused imports
SeaBlooms Aug 19, 2025
c913715
add update_question()
SeaBlooms Aug 19, 2025
14657ef
add delete_question()
SeaBlooms Aug 19, 2025
23fa34c
update to 1.6.0
SeaBlooms Aug 19, 2025
802dc6b
Delete create_question_usage.md
SeaBlooms Aug 19, 2025
711d42d
created tests
SeaBlooms Aug 19, 2025
61ddfb0
remove imports
SeaBlooms Aug 19, 2025
2b12fe8
remove resource_group from question methods
SeaBlooms Aug 20, 2025
e65f6ac
add input validation for 'queries' in 'update_question()' method
SeaBlooms Aug 20, 2025
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
195 changes: 195 additions & 0 deletions docs/create_question_usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Create Question Method Documentation

## Overview

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.

## Method Signature

```python
def create_question(
self,
title: str,
queries: List[Dict],
resource_group_id: str = None,
**kwargs
)
```

## Parameters

### Required Parameters

- **`title`** (str): The title of the question. This is required and cannot be empty.

- **`queries`** (List[Dict]): A list of query objects. At least one query is required. Each query object can contain:
- **`query`** (str, required): The J1QL query string
- **`name`** (str, optional): Name for the query. Defaults to "Query{index}"
- **`version`** (str, optional): Query version (e.g., "v1")
- **`resultsAre`** (str, optional): Query result type. Defaults to "INFORMATIVE". Options include:
- "INFORMATIVE" - Neutral information
- "GOOD" - Positive/expected results
- "BAD" - Negative/unexpected results
- "UNKNOWN" - Unknown state

### Optional Parameters

- **`resource_group_id`** (str): ID of the resource group to associate the question with

### Additional Keyword Arguments (**kwargs)

- **`description`** (str): Description of the question
- **`tags`** (List[str]): List of tags to apply to the question
- **`compliance`** (Dict): Compliance metadata containing:
- `standard` (str): Compliance standard name
- `requirements` (List[str]): List of requirement IDs
- `controls` (List[str]): List of control names
- **`variables`** (List[Dict]): Variable definitions for parameterized queries
- **`showTrend`** (bool): Whether to show trend data for the question results
- **`pollingInterval`** (str): How often to run the queries (e.g., "ONE_HOUR", "ONE_DAY")
- **`integrationDefinitionId`** (str): Integration definition ID if the question is integration-specific

## Return Value

Returns a dictionary containing the created question object with fields like:
- `id`: Unique identifier for the question
- `title`: The question title
- `description`: The question description
- `queries`: List of query objects
- `tags`: Applied tags
- And other metadata fields

## Examples

### Basic Question

```python
from jupiterone import JupiterOneClient

j1_client = JupiterOneClient(
account="your-account-id",
token="your-api-token"
)

# Create a simple question
question = j1_client.create_question(
title="Find All Open Hosts",
queries=[{
"query": "FIND Host WITH open=true",
"name": "OpenHosts"
}]
)
```

### Question with Multiple Queries

```python
# Create a question with multiple queries for comprehensive checks
question = j1_client.create_question(
title="Security Compliance Check",
queries=[
{
"query": "FIND Host WITH open=true",
"name": "OpenHosts",
"resultsAre": "BAD"
},
{
"query": "FIND User WITH mfaEnabled=false",
"name": "UsersWithoutMFA",
"resultsAre": "BAD"
},
{
"query": "FIND DataStore WITH encrypted=false",
"name": "UnencryptedDataStores",
"resultsAre": "BAD"
}
],
description="Comprehensive security compliance check",
tags=["security", "compliance", "audit"]
)
```

### Advanced Question with All Options

```python
# Create a question with all optional parameters
question = j1_client.create_question(
title="AWS Security Audit",
queries=[{
"query": "FIND aws_instance WITH publicIpAddress!=undefined",
"name": "PublicInstances",
"version": "v1",
"resultsAre": "INFORMATIVE"
}],
resource_group_id="resource-group-123",
description="Audit AWS instances with public IP addresses",
tags=["aws", "security", "network"],
showTrend=True,
pollingInterval="ONE_DAY",
compliance={
"standard": "CIS",
"requirements": ["2.1", "2.2"],
"controls": ["Network Security"]
},
variables=[
{
"name": "environment",
"required": False,
"default": "production"
}
]
)
```

### Minimal Question

```python
# Create a question with only required parameters
# The query name will default to "Query0" and resultsAre to "INFORMATIVE"
question = j1_client.create_question(
title="Simple Query",
queries=[{
"query": "FIND User LIMIT 10"
}]
)
```

## Error Handling

The method includes validation for required fields and will raise `ValueError` exceptions for:
- Missing or empty `title`
- Missing or empty `queries` list
- Invalid query format (not a dictionary)
- Missing required `query` field in query objects

```python
try:
question = j1_client.create_question(
title="", # This will raise an error
queries=[]
)
except ValueError as e:
print(f"Error: {e}")
```

## GraphQL Mutation

The method uses the following GraphQL mutation internally:

```graphql
mutation CreateQuestion($question: CreateQuestionInput!) {
createQuestion(question: $question) {
id
title
description
tags
queries {
name
query
version
resultsAre
}
# ... other fields
}
}
```
79 changes: 79 additions & 0 deletions examples/07_account_parameters_list_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""
JupiterOne Python SDK - Account Parameter (List Value) Example

This example demonstrates how to create or update an Account Parameter where the
value is a list of strings.

Prerequisites (environment variables):
- JUPITERONE_ACCOUNT_ID
- JUPITERONE_API_TOKEN
- (optional) JUPITERONE_URL
- (optional) JUPITERONE_SYNC_URL

Usage:
python 07_account_parameters_list_example.py
"""

import os
from jupiterone import JupiterOneClient


def setup_client() -> JupiterOneClient:
"""Instantiate the JupiterOne client using environment variables."""
return JupiterOneClient(
account=os.getenv("JUPITERONE_ACCOUNT_ID"),
token=os.getenv("JUPITERONE_API_TOKEN"),
url=os.getenv("JUPITERONE_URL", "https://graphql.us.jupiterone.io"),
sync_url=os.getenv("JUPITERONE_SYNC_URL", "https://api.us.jupiterone.io"),
)


def main() -> None:
print("JupiterOne - Create/Update Account Parameter (List Value)")
print("=" * 70)

# Configure the parameter name and value
# Name can be anything meaningful to your workflows
parameter_name = os.getenv("J1_LIST_PARAM_NAME", "ENTITY_TYPES_TO_INCLUDE")

# Example list value requested: ["aws_account", "aws_security_group"]
parameter_value = ["aws_account", "aws_security_group"]

try:
j1 = setup_client()

print(f"Creating/Updating parameter '{parameter_name}' with value: {parameter_value}")
result = j1.create_update_parameter(
name=parameter_name,
value=parameter_value,
secret=False,
)

# The mutation returns a success flag; fetch the parameter to verify
if result and result.get("setParameter", {}).get("success") is True:
print("✓ Parameter upsert reported success")
else:
print("! Parameter upsert did not report success (check details below)")
print(result)

# Verify by reading it back (non-secret parameters will return the value)
details = j1.get_parameter_details(name=parameter_name)
print("\nFetched parameter details:")
print(details)

print("\n✓ Completed creating/updating list-valued account parameter")

except Exception as exc:
print(f"✗ Error: {exc}")
print("\nMake sure you have set the following environment variables:")
print("- JUPITERONE_ACCOUNT_ID")
print("- JUPITERONE_API_TOKEN")
print("- JUPITERONE_URL (optional)")
print("- JUPITERONE_SYNC_URL (optional)")


if __name__ == "__main__":
main()


Loading
Loading