forked from cleveragents/cleveragents-core
3556481681
Implements real AWS SDK integration for CloudResourceHandler using boto3 as an optional dependency. Key changes: - Add boto3/botocore as optional [aws] dependency in pyproject.toml - Implement CloudResourceHandler.resolve() for AWS: builds boto3 session, verifies credentials via STS get_caller_identity for account-level types, and returns a BoundResource with the resource ARN as sandbox_path - Implement discover_aws_resources() to enumerate VPCs, subnets, instances, S3 buckets, IAM roles, RDS instances, ECS clusters, Lambda functions, and EKS clusters via the AWS API - Implement CloudResourceHandler.discover_children() for AWS resource types using the new discovery function - Implement CloudSandboxStrategy.create/commit/rollback for AWS using a tag-based isolation strategy (CleverAgents:PlanId tag) - GCP and Azure providers still raise NotImplementedError (pending) - boto3 is optional: handler raises ImportError with helpful install message when boto3 is not installed - Credentials are never logged (existing redaction infrastructure preserved) - Update cloud_resources.feature to reflect new AWS behavior - Add comprehensive cloud_aws_sdk.feature with 47 BDD scenarios covering all new code paths with mocked boto3 Closes #1021
232 lines
12 KiB
Gherkin
232 lines
12 KiB
Gherkin
Feature: AWS SDK integration for CloudResourceHandler
|
|
As a CleverAgents user
|
|
I want the CloudResourceHandler to use real AWS SDK operations
|
|
So that I can resolve and discover AWS cloud resources
|
|
|
|
# ── boto3 availability ────────────────────────────────────────────────────
|
|
|
|
Scenario: boto3 availability flag is exposed
|
|
Given awssdk the cloud handler module is imported
|
|
Then awssdk the boto3 availability flag should be a boolean
|
|
|
|
# ── _build_aws_session ────────────────────────────────────────────────────
|
|
|
|
Scenario: _build_aws_session raises ImportError when boto3 is unavailable
|
|
Given awssdk boto3 is not available
|
|
When awssdk I try to build an AWS session with valid credentials
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: _build_aws_session builds a session from explicit credentials
|
|
Given awssdk boto3 is available via mock
|
|
When awssdk I build an AWS session with explicit credentials
|
|
Then awssdk the session should be created successfully
|
|
|
|
Scenario: _build_aws_session builds a session from profile name
|
|
Given awssdk boto3 is available via mock
|
|
When awssdk I build an AWS session with a profile name "test-profile"
|
|
Then awssdk the session should be created with profile "test-profile"
|
|
|
|
# ── CloudResourceHandler.resolve for AWS ─────────────────────────────────
|
|
|
|
Scenario: resolve returns BoundResource for AWS account type with mocked STS
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk AWS STS returns account id "123456789012"
|
|
And awssdk a valid AWS cloud resource of type "aws"
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk a BoundResource should be returned
|
|
And awssdk the BoundResource slot_name should be "cloud-slot"
|
|
And awssdk the BoundResource resource_type should be "aws"
|
|
And awssdk the BoundResource sandbox_path should contain "123456789012"
|
|
|
|
Scenario: resolve returns BoundResource for aws-vpc type (no STS check)
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a valid AWS cloud resource of type "aws-vpc"
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk a BoundResource should be returned
|
|
And awssdk the BoundResource resource_type should be "aws-vpc"
|
|
|
|
Scenario: resolve raises ValueError when STS call fails
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk AWS STS raises a ClientError
|
|
And awssdk a valid AWS cloud resource of type "aws"
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk a ValueError should be raised mentioning "credential verification failed"
|
|
|
|
Scenario: resolve raises ImportError for AWS when boto3 is not installed
|
|
Given awssdk boto3 is not available
|
|
And awssdk a valid AWS cloud resource of type "aws-vpc"
|
|
When awssdk I call resolve on the cloud handler without boto3
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: resolve raises NotImplementedError for GCP provider
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a valid GCP cloud resource with credentials
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk a NotImplementedError should be raised mentioning "gcp"
|
|
|
|
Scenario: resolve raises NotImplementedError for Azure provider
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a valid Azure cloud resource with credentials
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk a NotImplementedError should be raised mentioning "azure"
|
|
|
|
# ── discover_aws_resources ────────────────────────────────────────────────
|
|
|
|
Scenario: discover_aws_resources returns empty list for unmapped type
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a mock boto3 session
|
|
And awssdk a cloud resource of type "aws-unknown-type"
|
|
When awssdk I call discover_aws_resources
|
|
Then awssdk the discovery result should be an empty list
|
|
|
|
Scenario: discover_aws_resources discovers VPCs from EC2
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk EC2 describe_vpcs returns 2 VPCs
|
|
And awssdk a cloud resource of type "aws-vpc"
|
|
When awssdk I call discover_aws_resources
|
|
Then awssdk the discovery result should have 2 items
|
|
And awssdk each discovery item should have an "id" key
|
|
And awssdk each discovery item should have an "arn" key
|
|
|
|
Scenario: discover_aws_resources discovers S3 buckets
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk S3 list_buckets returns 3 buckets
|
|
And awssdk a cloud resource of type "aws-s3-bucket"
|
|
When awssdk I call discover_aws_resources
|
|
Then awssdk the discovery result should have 3 items
|
|
And awssdk each discovery item arn should start with "arn:aws:s3:::"
|
|
|
|
Scenario: discover_aws_resources discovers ECS clusters
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk ECS list_clusters returns 2 cluster ARNs
|
|
And awssdk a cloud resource of type "aws-ecs-cluster"
|
|
When awssdk I call discover_aws_resources
|
|
Then awssdk the discovery result should have 2 items
|
|
|
|
Scenario: discover_aws_resources handles API errors gracefully
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a mock boto3 session that raises an exception
|
|
And awssdk a cloud resource of type "aws-vpc"
|
|
When awssdk I call discover_aws_resources
|
|
Then awssdk the discovery result should be an empty list
|
|
|
|
# ── CloudResourceHandler.discover_children ────────────────────────────────
|
|
|
|
Scenario: discover_children raises NotImplementedError for non-AWS provider
|
|
Given awssdk a CloudResourceHandler instance
|
|
And awssdk a cloud resource of type "gcp-project"
|
|
When awssdk I call discover_children on the cloud handler
|
|
Then awssdk a NotImplementedError should be raised mentioning "aws"
|
|
|
|
Scenario: discover_children raises ImportError when boto3 is not installed
|
|
Given awssdk boto3 is not available
|
|
And awssdk a CloudResourceHandler instance
|
|
And awssdk a valid AWS cloud resource of type "aws-vpc"
|
|
When awssdk I call discover_children on the cloud handler without boto3
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: discover_children returns Resource objects for discovered VPCs
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a CloudResourceHandler instance
|
|
And awssdk EC2 describe_vpcs returns 2 VPCs
|
|
And awssdk a valid AWS cloud resource of type "aws-vpc"
|
|
When awssdk I call discover_children on the cloud handler with mocked boto3
|
|
Then awssdk the aws discovery result should be a list of Resource objects
|
|
And awssdk the aws discovery result should have 2 items
|
|
|
|
# ── CloudSandboxStrategy AWS implementation ───────────────────────────────
|
|
|
|
Scenario: CloudSandboxStrategy.create succeeds for AWS with boto3 available
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call create on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk no exception should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.create raises ImportError without boto3
|
|
Given awssdk boto3 is not available
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call create on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: CloudSandboxStrategy.create raises NotImplementedError for GCP
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "gcp"
|
|
When awssdk I call create on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk a NotImplementedError should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.commit succeeds for AWS with boto3 available
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call commit on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk no exception should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.commit raises ImportError without boto3
|
|
Given awssdk boto3 is not available
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call commit on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: CloudSandboxStrategy.commit raises NotImplementedError for Azure
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "azure"
|
|
When awssdk I call commit on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk a NotImplementedError should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.rollback succeeds for AWS with boto3 available
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call rollback on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk no exception should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.rollback raises ImportError without boto3
|
|
Given awssdk boto3 is not available
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call rollback on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk an ImportError should be raised mentioning "cleveragents[aws]"
|
|
|
|
Scenario: CloudSandboxStrategy.rollback raises NotImplementedError for GCP
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "gcp"
|
|
When awssdk I call rollback on the AWS sandbox strategy with plan "PLAN-001"
|
|
Then awssdk a NotImplementedError should be raised
|
|
|
|
Scenario: CloudSandboxStrategy.create raises ValueError for empty plan_id
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call create on the AWS sandbox strategy with plan ""
|
|
Then awssdk a ValueError should be raised mentioning "plan_id"
|
|
|
|
Scenario: CloudSandboxStrategy.commit raises ValueError for empty plan_id
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call commit on the AWS sandbox strategy with plan ""
|
|
Then awssdk a ValueError should be raised mentioning "plan_id"
|
|
|
|
Scenario: CloudSandboxStrategy.rollback raises ValueError for empty plan_id
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a cloud sandbox strategy for "aws"
|
|
When awssdk I call rollback on the AWS sandbox strategy with plan ""
|
|
Then awssdk a ValueError should be raised mentioning "plan_id"
|
|
|
|
# ── Credential masking (regression) ──────────────────────────────────────
|
|
|
|
Scenario: AWS credentials are never logged in plain text
|
|
Given awssdk boto3 is available via mock
|
|
And awssdk a valid AWS cloud resource of type "aws"
|
|
When awssdk I call resolve on the cloud handler with mocked boto3
|
|
Then awssdk no raw credential values should appear in log output
|
|
|
|
# ── _AWS_RESOURCE_MAP coverage ────────────────────────────────────────────
|
|
|
|
Scenario: _AWS_RESOURCE_MAP contains expected AWS resource types
|
|
Given awssdk the cloud handler module is imported
|
|
Then awssdk the AWS resource map should contain "aws-vpc"
|
|
And awssdk the AWS resource map should contain "aws-subnet"
|
|
And awssdk the AWS resource map should contain "aws-instance"
|
|
And awssdk the AWS resource map should contain "aws-s3-bucket"
|
|
And awssdk the AWS resource map should contain "aws-iam-role"
|
|
And awssdk the AWS resource map should contain "aws-rds-instance"
|
|
And awssdk the AWS resource map should contain "aws-ecs-cluster"
|
|
And awssdk the AWS resource map should contain "aws-lambda-function"
|
|
And awssdk the AWS resource map should contain "aws-eks-cluster"
|