|
| 1 | +#!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +JupiterOne Python SDK - Client Setup and Query Examples |
| 4 | +
|
| 5 | +This file demonstrates how to: |
| 6 | +1. Set up the JupiterOne client |
| 7 | +2. Execute basic queries |
| 8 | +3. Use pagination methods |
| 9 | +4. Handle deferred responses for large datasets |
| 10 | +""" |
| 11 | + |
| 12 | +import os |
| 13 | +from jupiterone import JupiterOneClient |
| 14 | + |
| 15 | +def setup_client(): |
| 16 | + """Set up JupiterOne client with credentials.""" |
| 17 | + |
| 18 | + # Method 1: Using environment variables (recommended for production) |
| 19 | + j1 = JupiterOneClient( |
| 20 | + account=os.getenv('JUPITERONE_ACCOUNT_ID'), |
| 21 | + token=os.getenv('JUPITERONE_API_TOKEN'), |
| 22 | + url=os.getenv('JUPITERONE_URL', 'https://graphql.us.jupiterone.io'), |
| 23 | + sync_url=os.getenv('JUPITERONE_SYNC_URL', 'https://api.us.jupiterone.io') |
| 24 | + ) |
| 25 | + |
| 26 | + # Method 2: Direct configuration (for testing/development) |
| 27 | + # j1 = JupiterOneClient( |
| 28 | + # account='your-account-id', |
| 29 | + # token='your-api-token', |
| 30 | + # url='https://graphql.us.jupiterone.io', |
| 31 | + # sync_url='https://api.us.jupiterone.io' |
| 32 | + # ) |
| 33 | + |
| 34 | + return j1 |
| 35 | + |
| 36 | +def basic_query_examples(j1): |
| 37 | + """Demonstrate basic query operations.""" |
| 38 | + |
| 39 | + print("=== Basic Query Examples ===\n") |
| 40 | + |
| 41 | + # 1. Simple entity query |
| 42 | + print("1. Finding all hosts:") |
| 43 | + hosts = j1.query_v1(query='FIND Host LIMIT 10') |
| 44 | + print(f"Found {len(hosts)} hosts\n") |
| 45 | + |
| 46 | + # 2. Query with property filtering |
| 47 | + print("2. Finding Linux hosts:") |
| 48 | + linux_hosts = j1.query_v1(query='FIND Host WITH platform = "linux" LIMIT 5') |
| 49 | + print(f"Found {len(linux_hosts)} Linux hosts\n") |
| 50 | + |
| 51 | + # 3. Query with relationships |
| 52 | + print("3. Finding hosts with applications:") |
| 53 | + hosts_with_apps = j1.query_v1( |
| 54 | + query='FIND Host AS h THAT HAS Application AS a RETURN h.displayName, a.displayName LIMIT 5' |
| 55 | + ) |
| 56 | + print(f"Found {len(hosts_with_apps)} host-application relationships\n") |
| 57 | + |
| 58 | + # 4. Tree query |
| 59 | + print("4. Tree query for host relationships:") |
| 60 | + j1.query_v1(query='FIND Host with displayName = "server-001" THAT RELATES TO * RETURN TREE') |
| 61 | + print(f"Tree query completed\n") |
| 62 | + |
| 63 | + # 5. Query with deleted entities |
| 64 | + print("5. Query including deleted entities:") |
| 65 | + all_hosts = j1.query_v1(query='FIND Host LIMIT 5', include_deleted=True) |
| 66 | + print(f"Found {len(all_hosts)} hosts (including deleted)\n") |
| 67 | + |
| 68 | +def pagination_examples(j1): |
| 69 | + """Demonstrate different pagination methods.""" |
| 70 | + |
| 71 | + print("=== Pagination Examples ===\n") |
| 72 | + |
| 73 | + # 1. Cursor-based pagination (recommended for large datasets) |
| 74 | + print("1. Cursor-based pagination:") |
| 75 | + cursor_result = j1._cursor_query( |
| 76 | + query="FIND (Device | Person)", |
| 77 | + max_workers=3 # Parallel processing |
| 78 | + ) |
| 79 | + print(f"Cursor query found {len(cursor_result)} total results\n") |
| 80 | + |
| 81 | + # 2. Limit and skip pagination |
| 82 | + print("2. Limit and skip pagination:") |
| 83 | + j1._limit_and_skip_query( |
| 84 | + query="FIND User", |
| 85 | + skip=0, |
| 86 | + limit=100 |
| 87 | + ) |
| 88 | + print(f"Limit/skip query completed\n") |
| 89 | + |
| 90 | + # 3. Deferred response for very large datasets |
| 91 | + print("3. Deferred response for large datasets:") |
| 92 | + deferred_result = j1.query_with_deferred_response( |
| 93 | + query="FIND UnifiedDevice" |
| 94 | + ) |
| 95 | + print(f"Deferred response query completed with {len(deferred_result)} results\n") |
| 96 | + |
| 97 | +def complex_query_examples(j1): |
| 98 | + """Demonstrate complex query patterns.""" |
| 99 | + |
| 100 | + print("=== Complex Query Examples ===\n") |
| 101 | + |
| 102 | + # 1. Multi-step relationship traversal |
| 103 | + print("1. Multi-step relationship query:") |
| 104 | + complex_query = """ |
| 105 | + FIND User AS u |
| 106 | + THAT HAS AccessPolicy AS ap |
| 107 | + THAT ALLOWS * AS resource |
| 108 | + WHERE resource.tag.Environment = 'production' |
| 109 | + RETURN u.displayName, ap.displayName, resource.displayName |
| 110 | + LIMIT 10 |
| 111 | + """ |
| 112 | + complex_result = j1.query_v1(query=complex_query) |
| 113 | + print(f"Complex query found {len(complex_result)} results\n") |
| 114 | + |
| 115 | + # 2. Aggregation query |
| 116 | + print("2. Aggregation query:") |
| 117 | + agg_query = """ |
| 118 | + FIND Host AS h |
| 119 | + RETURN h.platform, count(h) |
| 120 | + ORDER BY count(h) DESC |
| 121 | + LIMIT 10 |
| 122 | + """ |
| 123 | + j1.query_v1(query=agg_query) |
| 124 | + print(f"Aggregation query completed\n") |
| 125 | + |
| 126 | + # 3. Time-based query |
| 127 | + print("3. Time-based query:") |
| 128 | + time_query = """ |
| 129 | + FIND Finding |
| 130 | + WITH createdOn > date.now - 7 days |
| 131 | + RETURN displayName, severity, createdOn |
| 132 | + ORDER BY createdOn DESC |
| 133 | + LIMIT 10 |
| 134 | + """ |
| 135 | + time_result = j1.query_v1(query=time_query) |
| 136 | + print(f"Time-based query found {len(time_result)} recent findings\n") |
| 137 | + |
| 138 | +def natural_language_to_j1ql(j1): |
| 139 | + """Demonstrate natural language to J1QL conversion.""" |
| 140 | + |
| 141 | + print("=== Natural Language to J1QL Examples ===\n") |
| 142 | + |
| 143 | + prompts = [ |
| 144 | + "Find all AWS EC2 instances that are running and tagged as production", |
| 145 | + "Show me all databases that are not encrypted", |
| 146 | + "Find users who have admin access to production systems", |
| 147 | + "List all applications that haven't been updated in the last 30 days" |
| 148 | + ] |
| 149 | + |
| 150 | + for i, prompt in enumerate(prompts, 1): |
| 151 | + print(f"{i}. Prompt: {prompt}") |
| 152 | + try: |
| 153 | + result = j1.generate_j1ql(natural_language_prompt=prompt) |
| 154 | + print(f" Generated J1QL: {result['j1ql']}") |
| 155 | + except Exception as e: |
| 156 | + print(f" Error: {e}") |
| 157 | + print() |
| 158 | + |
| 159 | +def main(): |
| 160 | + """Main function to run all examples.""" |
| 161 | + |
| 162 | + print("JupiterOne Python SDK - Client Setup and Query Examples") |
| 163 | + print("=" * 60) |
| 164 | + |
| 165 | + try: |
| 166 | + # Set up client |
| 167 | + j1 = setup_client() |
| 168 | + print("✓ Client setup successful\n") |
| 169 | + |
| 170 | + # Run examples |
| 171 | + basic_query_examples(j1) |
| 172 | + pagination_examples(j1) |
| 173 | + complex_query_examples(j1) |
| 174 | + natural_language_to_j1ql(j1) |
| 175 | + |
| 176 | + print("✓ All examples completed successfully!") |
| 177 | + |
| 178 | + except Exception as e: |
| 179 | + print(f"✗ Error: {e}") |
| 180 | + print("\nMake sure you have set the following environment variables:") |
| 181 | + print("- JUPITERONE_ACCOUNT_ID") |
| 182 | + print("- JUPITERONE_API_TOKEN") |
| 183 | + print("- JUPITERONE_URL (optional)") |
| 184 | + print("- JUPITERONE_SYNC_URL (optional)") |
| 185 | + |
| 186 | +if __name__ == "__main__": |
| 187 | + main() |
0 commit comments