File size: 10,084 Bytes
115612d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# Testing Guide for OpenEnv-CloudSOC

## Quick Start Testing

### 1. Quick Smoke Tests (2 minutes)
```bash
python test_cloudsoc.py --quick
```

Tests:
- Environment initialization for all 3 tasks
- Tool execution
- Deterministic seeding
- Action preconditions
- Adversarial traps

### 2. Full Unit Test Suite (10 minutes)
```bash
python test_cloudsoc.py --verbose
```

Runs 20+ unit tests covering:
- Task initialization
- Tool execution
- Validation
- Preconditions
- Reward shaping
- Adversarial traps
- Incident closure
- Timeline grading
- Multi-task campaigns
- State serialization

### 3. Single Task Manual Test (5-10 minutes per task)
```bash
# Test easy task
python -c "
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
obs, info = env.reset()

print('Task:', env.scenario['name'])
print('Max steps:', env.max_steps)
print('Required flags:', env.scenario['required_flags'])
print()

# Execute a sequence of tools
tools_to_test = [
    ('aws.soc.get_alerts', {}),
    ('aws.cloudwatch.query_basic', {'log_group': '/aws/ec2'}),
    ('aws.s3.get_bucket_policy', {'bucket_name': 'company-backup-2024'}),
]

for tool, args in tools_to_test:
    action = json.dumps({'thought': f'Test {tool}', 'tool': tool, 'args': args})
    obs, reward, term, trunc, info = env.step(action)
    print(f'{tool}: reward={reward:.2f}, error={info[\"last_action_error\"]}')
    if term:
        break

env.close()
"
```

## Advanced Manual Testing

### Test with Mock LLM Responses

```bash
# Create mock_test.py
python -c "
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
env.reset()

# Simulate agent actions
agent_actions = [
    {'thought': 'Check current alerts', 'tool': 'aws.soc.get_alerts', 'args': {}},
    {'thought': 'Query CloudWatch logs', 'tool': 'aws.cloudwatch.query_deep', 'args': {'log_group': '/aws/ec2'}},
    {'thought': 'Check S3 bucket policy', 'tool': 'aws.s3.get_bucket_policy', 'args': {'bucket_name': 'company-backup-2024'}},
    {'thought': 'List S3 objects', 'tool': 'aws.s3.list_objects', 'args': {'bucket_name': 'company-backup-2024'}},
    {'thought': 'Block public access', 'tool': 'aws.s3.block_public_access', 'args': {'bucket_name': 'company-backup-2024'}},
    {'thought': 'Close incident', 'tool': 'aws.soc.close_incident', 'args': {'timeline': ['Bucket detected', 'Creds found', 'Access blocked']}},
]

total_reward = 0
for i, action_dict in enumerate(agent_actions, 1):
    action_str = json.dumps(action_dict)
    obs, reward, term, trunc, info = env.step(action_str)
    total_reward += reward
    
    print(f'Step {i}: {action_dict[\"tool\"]}')
    print(f'  Reward: {reward:.2f}, Total: {total_reward:.2f}')
    print(f'  Flags: {len(env.state.discovered_flags)}/{len(env.scenario[\"required_flags\"])}')
    print(f'  Error: {info[\"last_action_error\"]}')
    print()
    
    if term:
        print('Episode terminated')
        break

print(f'Final: Total reward={total_reward:.2f}, Flags={len(env.state.discovered_flags)}/{len(env.scenario[\"required_flags\"])}')
"
```

### Test Preconditions

```bash
# Test: Isolate without snapshot should fail
python -c "
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
env.reset()

instance_id = list(env.state.instances.keys())[0]

# Try isolate without snapshot
action = json.dumps({
    'thought': 'Try isolate without snapshot',
    'tool': 'aws.ec2.isolate',
    'args': {'instance_id': instance_id}
})

obs, reward, term, trunc, info = env.step(action)
print('Isolate without snapshot:')
print(f'  Reward: {reward}')
print(f'  Error: {info[\"last_action_error\"]}')
print(f'  Expected: PRECONDITION_FAILED')
"
```

### Test Adversarial Trap

```bash
# Test: Terminate compromised instance
python -c "
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
env.reset()

# Find compromised instance
compromised = None
for iid, inst in env.state.instances.items():
    if inst.is_compromised:
        compromised = iid
        break

if compromised:
    action = json.dumps({
        'thought': 'Terminate compromised instance',
        'tool': 'aws.ec2.terminate',
        'args': {'instance_id': compromised}
    })
    
    obs, reward, term, trunc, info = env.step(action)
    print('Terminate compromised instance:')
    print(f'  Reward: {reward} (expected: -1.0)')
    print(f'  Terminated: {term} (expected: true)')
    print(f'  Error: {info[\"last_action_error\"]}')
else:
    print('No compromised instance found')
"
```

### Test Timeline Grading

```bash
# Test: Timeline accuracy grading
python -c "
from cloud_soc_env import CloudSOCEnv

env = CloudSOCEnv(task='easy', seed=42)
env.reset()

ground_truth = env.scenario['ground_truth_timeline']
print('Ground truth:', ground_truth)
print()

test_cases = [
    ground_truth,  # Perfect match
    ground_truth[:1],  # Partial
    ['Wrong event'],  # Wrong
    ground_truth + ['Extra event'],  # Extra
]

for i, timeline in enumerate(test_cases, 1):
    score = env._grade_timeline(timeline)
    print(f'Test {i}: {score:.2f}')
    print(f'  Timeline: {timeline}')
"
```

## Inference Testing

### Test Inference Loop (Requires HF_TOKEN)

```bash
# Set environment variables first
export API_BASE_URL="https://api.openai.com/v1"
export MODEL_NAME="gpt-4.1-mini"
export HF_TOKEN="your_token_here"

# Run single task
python inference.py --task easy --seed 42 --verbose

# Run full campaign
python inference.py --task campaign --seed 42 --verbose
```

### Expected Output Format

```
[START] task=easy env=cloudsoc model=gpt-4.1-mini
[STEP] step=1 action=aws.soc.get_alerts({}) reward=0.00 done=false error=null
[STEP] step=2 action=aws.cloudwatch.query_deep(...) reward=-0.05 done=false error=null
...
[END] success=true steps=N rewards=0.00,-0.05,0.02,...
```

## Docker Testing

### Build Docker Image

```bash
# Build
docker build -t cloudsoc:latest .

# Run
docker run --rm \
  -e API_BASE_URL="https://api.openai.com/v1" \
  -e MODEL_NAME="gpt-4.1-mini" \
  -e HF_TOKEN="your_token_here" \
  cloudsoc:latest

# Run with custom task
docker run --rm \
  -e HF_TOKEN="your_token_here" \
  cloudsoc:latest \
  python inference.py --task medium
```

### Check Resource Usage

```bash
# Monitor during run
docker stats cloudsoc

# Expected: <2 vCPU, <2GB RAM
```

## Performance Testing

### Measure Execution Time

```bash
python -c "
import time
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
start = time.time()
env.reset()

for i in range(5):
    action = json.dumps({
        'thought': 'Test',
        'tool': 'aws.soc.get_alerts',
        'args': {}
    })
    env.step(action)

elapsed = time.time() - start
print(f'5 steps in {elapsed:.2f}s ({elapsed/5:.3f}s per step)')
"
```

### Memory Usage

```bash
python -c "
import sys
from cloud_soc_env import CloudSOCEnv

env = CloudSOCEnv(task='hard', seed=42)
env.reset()

print(f'Environment size: ~{sys.getsizeof(env) / 1024:.1f} KB')
print(f'Instances: {len(env.state.instances)}')
print(f'Logs: {len(env.state.logs)}')
print(f'Alerts: {len(env.state.alerts)}')
"
```

## Debugging Tips

### Enable Verbose Logging

```python
env = CloudSOCEnv(task='easy', seed=42, verbose=True)
obs, info = env.reset()

# Check discovered flags
print('Flags:', env.state.discovered_flags)

# Check phase scores
print('Scores:', env.phase_scores)

# Check tool usage
print('Tools used:', env.tool_usage)

# Check query costs
print('Query costs:', env.query_costs)
```

### Inspect State

```python
from cloud_soc_env import CloudSOCEnv
import json

env = CloudSOCEnv(task='easy', seed=42)
env.reset()

# Export state to dict for inspection
state_dict = env.state.to_dict()
print(json.dumps(state_dict, indent=2))

# Check specific instance
instance_id = list(env.state.instances.keys())[0]
inst = env.state.instances[instance_id]
print(f'Instance {instance_id}:')
print(f'  Compromised: {inst.is_compromised}')
print(f'  Has snapshot: {inst.has_forensic_snapshot}')
print(f'  State: {inst.state.value}')
```

### Test Parser

```python
from inference import parse_llm_response
import json

test_responses = [
    # Clean JSON
    json.dumps({'thought': 'Test', 'tool': 'aws.soc.get_alerts', 'args': {}}),
    
    # Markdown code block
    '```json\n{"thought": "Test", "tool": "aws.soc.get_alerts", "args": {}}\n```',
    
    # Embedded in text
    'I will check alerts. {"thought": "Test", "tool": "aws.soc.get_alerts", "args": {}}',
    
    # Malformed JSON
    '{"thought": "Test", "tool": "aws.soc.get_alerts"',
]

for i, response in enumerate(test_responses, 1):
    parsed, error = parse_llm_response(response)
    print(f'Test {i}: {"βœ“" if parsed else "βœ—"} {error}')
```

## Continuous Integration

### GitHub Actions Example

```yaml
name: Test CloudSOC

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: 3.11
      
      - name: Install dependencies
        run: pip install -r requirements.txt
      
      - name: Run tests
        run: python test_cloudsoc.py --quick
      
      - name: Build Docker
        run: docker build -t cloudsoc:latest .
```

## Troubleshooting

| Issue | Solution |
|-------|----------|
| ModuleNotFoundError: gymnasium | `pip install gymnasium` |
| ModuleNotFoundError: openai | `pip install openai` |
| HF_TOKEN environment variable is required | Set `export HF_TOKEN="your_token"` |
| API timeout | Increase timeout in inference.py call_llm() |
| Out of memory | Use --task easy instead of hard |
| LLM response parsing fails | Check verbose output with --verbose flag |

## Test Coverage

- βœ… Unit tests: 20+ tests covering all mechanics
- βœ… Integration tests: End-to-end scenarios
- βœ… Performance tests: Time and memory profiling
- βœ… Docker tests: Container build and runtime
- βœ… Output format: Hackathon compliance validation

Run: `python test_cloudsoc.py --verbose` for full coverage report.