| Crates.io | llm-shield-cloud-aws |
| lib.rs | llm-shield-cloud-aws |
| version | 0.1.1 |
| created_at | 2025-11-03 03:50:05.711189+00 |
| updated_at | 2025-11-03 03:50:05.711189+00 |
| description | AWS cloud integrations for LLM Shield - Secrets Manager, S3, CloudWatch |
| homepage | |
| repository | https://github.com/llm-shield/llm-shield-rs |
| max_upload_size | |
| id | 1913869 |
| size | 214,263 |
AWS cloud integrations for LLM Shield - Secrets Manager, S3, CloudWatch, and X-Ray.
This crate provides production-ready AWS implementations of the cloud abstraction traits defined in llm-shield-cloud:
Add to your Cargo.toml:
[dependencies]
llm-shield-cloud-aws = "0.1"
llm-shield-cloud = "0.1"
tokio = { version = "1.35", features = ["full"] }
use llm_shield_cloud_aws::AwsSecretsManager;
use llm_shield_cloud::CloudSecretManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize with default configuration
let secrets = AwsSecretsManager::new().await?;
// Fetch a secret (automatically cached for 5 minutes)
let api_key = secrets.get_secret("llm-shield/openai-api-key").await?;
println!("API Key: {}", api_key.as_string());
// Create a new secret
let new_secret = SecretValue::from_string("my-secret-value".to_string());
secrets.create_secret("llm-shield/my-secret", &new_secret).await?;
// List all secrets
let secret_names = secrets.list_secrets().await?;
println!("Found {} secrets", secret_names.len());
Ok(())
}
use llm_shield_cloud_aws::AwsS3Storage;
use llm_shield_cloud::{CloudStorage, PutObjectOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let storage = AwsS3Storage::new("llm-shield-models").await?;
// Upload a model (automatically uses multipart for files >5MB)
let model_data = tokio::fs::read("toxicity-model.onnx").await?;
storage.put_object("models/toxicity.onnx", &model_data).await?;
// Upload with options
let options = PutObjectOptions {
content_type: Some("application/octet-stream".to_string()),
storage_class: Some("INTELLIGENT_TIERING".to_string()),
encryption: Some("AES256".to_string()),
..Default::default()
};
storage.put_object_with_options("models/model.onnx", &model_data, &options).await?;
// Download and verify
let downloaded = storage.get_object("models/toxicity.onnx").await?;
assert_eq!(model_data, downloaded);
// List objects with prefix
let models = storage.list_objects("models/").await?;
println!("Found {} models", models.len());
Ok(())
}
use llm_shield_cloud_aws::CloudWatchMetrics;
use llm_shield_cloud::{CloudMetrics, Metric};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let metrics = CloudWatchMetrics::new("LLMShield").await?;
let mut dimensions = HashMap::new();
dimensions.insert("Environment".to_string(), "Production".to_string());
dimensions.insert("Scanner".to_string(), "Toxicity".to_string());
let metric = Metric {
name: "ScanDuration".to_string(),
value: 123.45,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs(),
dimensions,
unit: Some("Milliseconds".to_string()),
};
metrics.export_metric(&metric).await?;
metrics.flush().await?;
Ok(())
}
use llm_shield_cloud_aws::CloudWatchLogger;
use llm_shield_cloud::{CloudLogger, LogLevel, LogEntry};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let logger = CloudWatchLogger::new(
"/llm-shield/api",
"production-instance-1"
).await?;
// Simple logging
logger.log("API server started", LogLevel::Info).await?;
// Structured logging
let mut labels = HashMap::new();
labels.insert("request_id".to_string(), "req-123".to_string());
labels.insert("user_id".to_string(), "user-456".to_string());
let entry = LogEntry {
timestamp: std::time::SystemTime::now(),
level: LogLevel::Info,
message: "Request processed successfully".to_string(),
labels,
trace_id: Some("trace-789".to_string()),
span_id: Some("span-012".to_string()),
};
logger.log_structured(&entry).await?;
logger.flush().await?;
Ok(())
}
Configure AWS integrations via YAML or environment variables:
cloud:
provider: aws
aws:
region: us-east-1
secrets_manager:
enabled: true
cache_ttl_seconds: 300
s3:
bucket: llm-shield-models
models_prefix: models/
results_prefix: scan-results/
cloudwatch:
enabled: true
namespace: LLMShield
log_group: /llm-shield/api
log_stream: production
Or use environment variables:
export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID=<your-key-id>
export AWS_SECRET_ACCESS_KEY=<your-secret-key>
export LLM_SHIELD_S3_BUCKET=llm-shield-models
export LLM_SHIELD_CLOUDWATCH_NAMESPACE=LLMShield
This crate uses the AWS SDK's default credential provider chain:
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY~/.aws/credentialsFor local development, configure credentials:
aws configure
# Or set environment variables
export AWS_ACCESS_KEY_ID=<key-id>
export AWS_SECRET_ACCESS_KEY=<secret-key>
export AWS_DEFAULT_REGION=us-east-1
For production deployments, use IAM roles instead of access keys:
EC2 Instance:
# Attach IAM role to EC2 instance
aws ec2 associate-iam-instance-profile \
--instance-id i-xxxxx \
--iam-instance-profile Name=LLMShieldEC2Profile
ECS Task:
{
"family": "llm-shield-api",
"taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/LLMShieldECSTaskRole",
"containerDefinitions": [...]
}
EKS Pod (IRSA):
apiVersion: v1
kind: Pod
metadata:
name: llm-shield-api
spec:
serviceAccountName: llm-shield-sa
containers:
- name: api
image: llm-shield:latest
Required IAM permissions are provided in iam-policies/ directory:
secrets-manager-policy.json - Secrets Manager permissionss3-policy.json - S3 bucket access permissionscloudwatch-policy.json - CloudWatch metrics and logs permissionsllm-shield-full-policy.json - Combined policy (all permissions)For production, use least-privilege access:
aws iam put-role-policy \
--role-name LLMShieldRole \
--policy-name SecretsManagerReadOnly \
--policy-document file://iam-policies/secrets-manager-policy.json
See iam-policies/README.md for detailed setup instructions.
Follow these conventions for AWS resources:
llm-shield/llm-shield/openai-api-keyllm-shield/database-passwordllm-shield/jwt-secretllm-shield-*llm-shield-models-prodllm-shield-results-devmodels/scan-results/configs/LLMShieldLLMShield/APILLMShield/Scanners/llm-shield/*
/llm-shield/api/llm-shield/scannerscargo test -p llm-shield-cloud-aws
Integration tests require AWS credentials and appropriate permissions:
# Set test bucket for S3 tests
export TEST_S3_BUCKET=llm-shield-test-123456789012
# Run all integration tests
cargo test -p llm-shield-cloud-aws --test integration -- --ignored
# Run specific integration test
cargo test -p llm-shield-cloud-aws --test integration_secrets -- --ignored
cargo test -p llm-shield-cloud-aws --test integration_storage -- --ignored
cargo test -p llm-shield-cloud-aws --test integration_observability -- --ignored
Integration tests create resources with UUID suffixes for safety. Cleanup any leftover test resources:
# Delete test secrets
aws secretsmanager list-secrets --query 'SecretList[?starts_with(Name, `llm-shield-test`)].Name' --output text | \
xargs -I {} aws secretsmanager delete-secret --secret-id {} --force-delete-without-recovery
# Delete test S3 objects
aws s3 rm s3://llm-shield-test-ACCOUNT_ID/test/ --recursive
# Delete test log groups
aws logs describe-log-groups --log-group-name-prefix /llm-shield-test/ --query 'logGroups[].logGroupName' --output text | \
xargs -I {} aws logs delete-log-group --log-group-name {}
| Operation | Throughput | Latency (p50) | Latency (p99) |
|---|---|---|---|
| Secret fetch (cached) | 100,000/s | <1ms | <5ms |
| Secret fetch (uncached) | 1,000/s | 50ms | 150ms |
| S3 upload (1MB) | 50 MB/s | 20ms | 100ms |
| S3 upload (50MB, multipart) | 80 MB/s | 625ms | 2s |
| S3 download (1MB) | 100 MB/s | 10ms | 50ms |
| Metrics export (batch) | 1,000/s | 10ms | 50ms |
| Logs export (batch) | 10,000/s | 5ms | 25ms |
Enable secret caching (default 5 minutes):
let secrets = AwsSecretsManager::new_with_cache_ttl("us-east-1", 600).await?;
Use multipart uploads for large files (automatic for >5MB)
Batch metrics and logs:
metrics.export_metrics(&batch).await?;
logger.log_batch(&entries).await?;
Configure batch sizes:
let metrics = CloudWatchMetrics::new_with_config("LLMShield", "us-east-1", 50).await?;
let logger = CloudWatchLogger::new_with_config("/llm-shield/api", "stream", "us-east-1", 200).await?;
Use S3 Intelligent-Tiering for cost optimization:
let options = PutObjectOptions {
storage_class: Some("INTELLIGENT_TIERING".to_string()),
..Default::default()
};
Typical monthly costs for production deployment:
| Service | Usage | Cost |
|---|---|---|
| Secrets Manager | 10 secrets, 100K API calls | ~$5 |
| S3 Storage | 100 GB, 1M requests | ~$3 |
| CloudWatch Logs | 50 GB ingested, 10 GB stored | ~$27 |
| CloudWatch Metrics | 50 custom metrics | ~$15 |
| Total | ~$50/month |
Check IAM permissions:
# Verify your identity
aws sts get-caller-identity
# Check attached policies
aws iam list-attached-role-policies --role-name LLMShieldRole
# Test secret access
aws secretsmanager get-secret-value --secret-id llm-shield/test-secret
Ensure secret follows naming convention:
# List all secrets with prefix
aws secretsmanager list-secrets --query 'SecretList[?starts_with(Name, `llm-shield`)].Name'
Check bucket policy and IAM permissions:
# Test bucket access
aws s3 ls s3://llm-shield-models/
# Check bucket policy
aws s3api get-bucket-policy --bucket llm-shield-models
Ensure log group and stream exist:
# List log groups
aws logs describe-log-groups --log-group-name-prefix /llm-shield/
# Create log group if missing
aws logs create-log-group --log-group-name /llm-shield/api
Verify region configuration:
echo $AWS_DEFAULT_REGION
# Or specify region explicitly
let secrets = AwsSecretsManager::new_with_region("us-west-2").await?;
See examples/ directory for complete examples:
secrets_example.rs - Secret managementstorage_example.rs - S3 operationsmetrics_example.rs - CloudWatch metricslogging_example.rs - CloudWatch logscombined_example.rs - Using all services togetherRun examples:
cargo run --example secrets_example
cargo run --example storage_example
cargo run --example metrics_example
┌─────────────────────────────────────┐
│ LLM Shield Application │
│ (llm-shield-api crate) │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ llm-shield-cloud (traits) │
│ - CloudSecretManager │
│ - CloudStorage │
│ - CloudMetrics/Logger │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ llm-shield-cloud-aws (impl) │
│ - AwsSecretsManager │
│ - AwsS3Storage │
│ - CloudWatchMetrics/Logger │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ AWS SDK for Rust │
│ - aws-sdk-secretsmanager │
│ - aws-sdk-s3 │
│ - aws-sdk-cloudwatch │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ AWS Services │
│ - Secrets Manager │
│ - S3 │
│ - CloudWatch │
└─────────────────────────────────────┘
Report security vulnerabilities to: security@llm-shield.example.com
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
MIT OR Apache-2.0
llm-shield-cloud - Cloud abstraction traitsllm-shield-cloud-gcp - GCP integrationsllm-shield-cloud-azure - Azure integrationsllm-shield-api - LLM Shield REST API