88 lines
No EOL
3.3 KiB
Python
88 lines
No EOL
3.3 KiB
Python
import datetime
|
|
import time
|
|
import statistics
|
|
import concurrent.futures
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
from cryptography import x509
|
|
from cryptography.x509.oid import NameOID
|
|
from cryptography.hazmat.primitives import hashes
|
|
import resource
|
|
import psutil
|
|
import prometheus_client
|
|
from prometheus_client import Gauge, Histogram
|
|
|
|
# Prometheus metrics
|
|
REQUEST_LATENCY = Histogram('rbac_latency_seconds', 'RBAC operation latency')
|
|
REQUEST_RATE = Gauge('rbac_requests_per_second', 'RBAC request rate')
|
|
MEMORY_USAGE = Gauge('rbac_memory_bytes', 'RBAC memory usage')
|
|
|
|
class RBACPerformanceTest:
|
|
def __init__(self):
|
|
self.cert_cache = []
|
|
self._setup_metrics()
|
|
|
|
def _setup_metrics(self):
|
|
prometheus_client.start_http_server(8000)
|
|
|
|
def generate_test_cert(self, role):
|
|
"""Generate test certificate per SYM-SEC-004"""
|
|
key = ec.generate_private_key(ec.SECP384R1())
|
|
subject = issuer = x509.Name([
|
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Test Org"),
|
|
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, role),
|
|
x509.NameAttribute(NameOID.COMMON_NAME, "test.example.com"),
|
|
])
|
|
|
|
cert = x509.CertificateBuilder().subject_name(
|
|
subject
|
|
).issuer_name(
|
|
issuer
|
|
).public_key(
|
|
key.public_key()
|
|
).serial_number(
|
|
x509.random_serial_number()
|
|
).not_valid_before(
|
|
datetime.datetime.utcnow()
|
|
).not_valid_after(
|
|
datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
|
).add_extension(
|
|
x509.BasicConstraints(ca=False, path_length=None), critical=True,
|
|
).sign(key, hashes.SHA256())
|
|
|
|
return cert.public_bytes(serialization.Encoding.PEM)
|
|
|
|
def test_role_resolution(self, cert_pem):
|
|
"""Test role resolution performance"""
|
|
start = time.time()
|
|
# Simulate RBAC role resolution
|
|
cert = x509.load_pem_x509_certificate(cert_pem)
|
|
ou = cert.subject.get_attributes_for_oid(NameOID.ORGANIZATIONAL_UNIT_NAME)[0].value
|
|
latency = time.time() - start
|
|
REQUEST_LATENCY.observe(latency)
|
|
return latency
|
|
|
|
def run_concurrent_tests(self, num_threads=10000):
|
|
"""Run concurrent session test"""
|
|
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
|
futures = [executor.submit(self.test_role_resolution, self.cert_cache[i % 100])
|
|
for i in range(num_threads)]
|
|
results = [f.result() for f in futures]
|
|
|
|
MEMORY_USAGE.set(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
|
|
return {
|
|
'p50': statistics.median(results),
|
|
'p90': statistics.quantiles(results, n=10)[8],
|
|
'p99': statistics.quantiles(results, n=100)[98],
|
|
'success_rate': len([r for r in results if r < 0.05]) / len(results)
|
|
}
|
|
|
|
if __name__ == "__main__":
|
|
test = RBACPerformanceTest()
|
|
# Pre-generate 100 test certs
|
|
test.cert_cache = [test.generate_test_cert(f"role_{i}") for i in range(100)]
|
|
|
|
# Run tests
|
|
print("Running role resolution benchmark...")
|
|
resolution_stats = test.run_concurrent_tests()
|
|
print(f"Resolution stats: {resolution_stats}") |