649 lines
24 KiB
Bash
649 lines
24 KiB
Bash
#!/usr/bin/env bats
|
|
# Terraform Compatibility Tests for floci
|
|
|
|
setup_file() {
|
|
load 'test_helper/common-setup'
|
|
|
|
cd "$TF_DIR"
|
|
|
|
echo "# === Terraform Compatibility Test ===" >&3
|
|
echo "# Endpoint: $FLOCI_ENDPOINT" >&3
|
|
|
|
# Clean any previous state
|
|
rm -rf .terraform .terraform.lock.hcl terraform.tfstate* 2>/dev/null || true
|
|
|
|
echo "# --- Setup: state bucket & lock table ---" >&3
|
|
create_state_backend
|
|
generate_backend_config
|
|
|
|
# 12 MiB source for aws_s3_object.large: above the provider's 5 MiB part size, so it goes multipart
|
|
head -c $((12 * 1024 * 1024)) /dev/urandom > "$TF_DIR/large-object.bin"
|
|
|
|
echo "# --- terraform init ---" >&3
|
|
run terraform init -backend-config=/tmp/floci-backend.hcl \
|
|
-var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color
|
|
if [ "$status" -ne 0 ]; then
|
|
echo "# terraform init failed: $output" >&3
|
|
return 1
|
|
fi
|
|
|
|
echo "# --- terraform validate ---" >&3
|
|
run terraform validate -no-color
|
|
if [ "$status" -ne 0 ]; then
|
|
echo "# terraform validate failed: $output" >&3
|
|
return 1
|
|
fi
|
|
|
|
echo "# --- terraform plan ---" >&3
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color
|
|
if [ "$status" -ne 0 ]; then
|
|
echo "# terraform plan failed: $output" >&3
|
|
return 1
|
|
fi
|
|
|
|
echo "# --- terraform apply ---" >&3
|
|
run terraform apply -var="endpoint=${FLOCI_ENDPOINT}" -input=false -auto-approve -no-color
|
|
if [ "$status" -ne 0 ]; then
|
|
echo "# terraform apply failed: $output" >&3
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
teardown_file() {
|
|
load 'test_helper/common-setup'
|
|
|
|
cd "$TF_DIR"
|
|
|
|
echo "# --- terraform destroy ---" >&3
|
|
terraform destroy -var="endpoint=${FLOCI_ENDPOINT}" -input=false -auto-approve -no-color || true
|
|
rm -f "$TF_DIR/large-object.bin"
|
|
}
|
|
|
|
setup() {
|
|
load 'test_helper/common-setup'
|
|
}
|
|
|
|
# --- Spot Checks ---
|
|
|
|
@test "Terraform: S3 bucket created" {
|
|
run aws_cmd s3api head-bucket --bucket floci-compat-app
|
|
assert_success
|
|
}
|
|
|
|
# Base64 of a hex SHA256 digest, the way S3 encodes checksums.
|
|
hex_to_b64() {
|
|
printf "$(echo "$1" | sed 's/../\\x&/g')" | base64 | tr -d '\n'
|
|
}
|
|
|
|
# The composite SHA256 S3 stores for a multipart object: cut the local file at the part sizes S3
|
|
# reports, hash each part, hash the concatenated binary digests and append the part count.
|
|
sha256_composite_by_sizes() {
|
|
local file="$1"
|
|
shift
|
|
local joined offset=0 count=0 size hex
|
|
joined=$(mktemp)
|
|
for size in "$@"; do
|
|
hex=$(tail -c +$((offset + 1)) "$file" | head -c "$size" | sha256sum | cut -c1-64)
|
|
printf "$(echo "$hex" | sed 's/../\\x&/g')" >> "$joined"
|
|
offset=$((offset + size))
|
|
count=$((count + 1))
|
|
done
|
|
echo "$(hex_to_b64 "$(sha256sum "$joined" | cut -c1-64)")-$count"
|
|
rm -f "$joined"
|
|
}
|
|
|
|
@test "Terraform: large aws_s3_object is multipart-uploaded with the composite SHA256 checksum" {
|
|
run aws_cmd s3api head-object --bucket floci-compat-app --key large/multipart.bin \
|
|
--checksum-mode ENABLED --output json
|
|
assert_success
|
|
local checksum type etag
|
|
checksum=$(echo "$output" | jq -r '.ChecksumSHA256')
|
|
type=$(echo "$output" | jq -r '.ChecksumType')
|
|
etag=$(echo "$output" | jq -r '.ETag')
|
|
[ "$type" = "COMPOSITE" ]
|
|
[[ "$etag" =~ -[0-9]+\"$ ]]
|
|
|
|
run aws_cmd s3api get-object-attributes --bucket floci-compat-app --key large/multipart.bin \
|
|
--object-attributes Checksum ObjectParts --output json
|
|
assert_success
|
|
[ "$(echo "$output" | jq -r '.ObjectParts.TotalPartsCount')" -gt 1 ]
|
|
local sizes expected
|
|
sizes=$(echo "$output" | jq -r '.ObjectParts.Parts[].Size')
|
|
expected=$(sha256_composite_by_sizes "$TF_DIR/large-object.bin" $sizes)
|
|
[ "$checksum" = "$expected" ]
|
|
# GetObjectAttributes reports the composite without the part-count suffix
|
|
[ "$(echo "$output" | jq -r '.Checksum.ChecksumSHA256')" = "${expected%-*}" ]
|
|
}
|
|
|
|
@test "Terraform: state holds the composite checksum S3 reports for the large object" {
|
|
cd "$TF_DIR"
|
|
run terraform output -raw large_object_checksum_sha256
|
|
assert_success
|
|
local head_checksum
|
|
head_checksum=$(aws_cmd s3api head-object --bucket floci-compat-app --key large/multipart.bin \
|
|
--checksum-mode ENABLED --output json | jq -r '.ChecksumSHA256')
|
|
[ "$output" = "$head_checksum" ]
|
|
}
|
|
|
|
@test "Terraform: re-planning the large object reports no changes" {
|
|
cd "$TF_DIR"
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color -detailed-exitcode \
|
|
-target=aws_s3_object.large
|
|
if [ "$status" -eq 2 ]; then
|
|
echo "# drift detected on re-plan:" >&3
|
|
echo "$output" >&3
|
|
fi
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "Terraform: SQS queue created" {
|
|
run aws_cmd sqs get-queue-url --queue-name floci-compat-jobs
|
|
assert_success
|
|
assert_output --partial "QueueUrl"
|
|
}
|
|
|
|
@test "Terraform: SNS topic created" {
|
|
run aws_cmd sns list-topics
|
|
assert_success
|
|
assert_output --partial "floci-compat-events"
|
|
}
|
|
|
|
@test "Terraform: SES receipt filter created" {
|
|
run aws_cmd ses list-receipt-filters
|
|
assert_success
|
|
assert_output --partial "floci-compat-filter"
|
|
assert_output --partial "10.10.10.0/24"
|
|
}
|
|
|
|
@test "Terraform: SES receipt rule set created and active" {
|
|
run aws_cmd ses describe-receipt-rule-set --rule-set-name floci-compat-rule-set
|
|
assert_success
|
|
assert_output --partial "floci-compat-rule-set"
|
|
|
|
run aws_cmd ses describe-active-receipt-rule-set
|
|
assert_success
|
|
assert_output --partial "floci-compat-rule-set"
|
|
assert_output --partial "X-Floci-Compat"
|
|
}
|
|
|
|
@test "Terraform: SES receipt rule round-trips its actions" {
|
|
run aws_cmd ses describe-receipt-rule --rule-set-name floci-compat-rule-set --rule-name floci-compat-rule
|
|
assert_success
|
|
assert_output --partial "X-Floci-Compat"
|
|
assert_output --partial "floci-compat-events"
|
|
assert_output --partial "RuleSet"
|
|
}
|
|
|
|
@test "Terraform: DynamoDB table created" {
|
|
run aws_cmd dynamodb describe-table --table-name floci-compat-items
|
|
assert_success
|
|
assert_output --partial "ACTIVE"
|
|
}
|
|
|
|
@test "Terraform: SSM parameter created" {
|
|
run aws_cmd ssm get-parameter --name /floci-compat/db-url
|
|
assert_success
|
|
assert_output --partial "jdbc:"
|
|
}
|
|
|
|
@test "Terraform: Secrets Manager secret created" {
|
|
run aws_cmd secretsmanager describe-secret --secret-id "floci-compat/db-creds"
|
|
assert_success
|
|
assert_output --partial "floci-compat"
|
|
}
|
|
|
|
@test "Terraform: ECR repository created" {
|
|
run aws_cmd ecr describe-repositories --repository-names floci-compat-app
|
|
assert_success
|
|
assert_output --partial "floci-compat-app"
|
|
}
|
|
|
|
@test "Terraform: ECS cluster created" {
|
|
run aws_cmd ecs describe-clusters --clusters floci-compat-cluster
|
|
assert_success
|
|
assert_output --partial "floci-compat-cluster"
|
|
assert_output --partial "ACTIVE"
|
|
}
|
|
|
|
@test "Terraform: KMS key created" {
|
|
run aws_cmd kms list-keys
|
|
assert_success
|
|
[ "$(aws_cmd kms list-keys --query 'length(Keys)' --output text)" -gt 0 ]
|
|
}
|
|
|
|
@test "Terraform: Kinesis stream created" {
|
|
run aws_cmd kinesis describe-stream-summary --stream-name floci-compat-events
|
|
assert_success
|
|
assert_output --partial "ACTIVE"
|
|
}
|
|
|
|
@test "Terraform: CloudWatch log group created" {
|
|
run aws_cmd logs describe-log-groups --log-group-name-prefix /floci/compat/app
|
|
assert_success
|
|
assert_output --partial "/floci/compat/app"
|
|
}
|
|
|
|
@test "Terraform: EventBridge event bus created" {
|
|
run aws_cmd events describe-event-bus --name floci-compat-bus
|
|
assert_success
|
|
assert_output --partial "floci-compat-bus"
|
|
}
|
|
|
|
@test "Terraform: Step Functions state machine created" {
|
|
run aws_cmd stepfunctions list-state-machines
|
|
assert_success
|
|
assert_output --partial "floci-compat-state-machine"
|
|
}
|
|
|
|
@test "Terraform: CloudFormation stack created" {
|
|
run aws_cmd cloudformation describe-stacks --stack-name floci-compat-stack
|
|
assert_success
|
|
assert_output --partial "floci-compat-stack"
|
|
}
|
|
|
|
@test "Terraform: EKS cluster created" {
|
|
run aws_cmd eks describe-cluster --name floci-compat-eks
|
|
assert_success
|
|
assert_output --partial "floci-compat-eks"
|
|
assert_output --partial "ACTIVE"
|
|
}
|
|
|
|
@test "Terraform: API Gateway v2 HTTP API created" {
|
|
run aws_cmd apigatewayv2 get-apis
|
|
assert_success
|
|
assert_output --partial "floci-compat-http-api"
|
|
}
|
|
|
|
@test "Terraform: AppConfig application created" {
|
|
run aws_cmd appconfig list-applications
|
|
assert_success
|
|
assert_output --partial "floci-compat-appconfig"
|
|
}
|
|
|
|
@test "Terraform: Backup vault created" {
|
|
run aws_cmd backup describe-backup-vault --backup-vault-name floci-compat-vault
|
|
assert_success
|
|
assert_output --partial "floci-compat-vault"
|
|
}
|
|
|
|
@test "Terraform: Cloud Map namespace created" {
|
|
run aws_cmd servicediscovery list-namespaces
|
|
assert_success
|
|
assert_output --partial "floci-compat.internal"
|
|
}
|
|
|
|
@test "Terraform: CodeDeploy application created" {
|
|
run aws_cmd deploy get-application --application-name floci-compat-codedeploy
|
|
assert_success
|
|
assert_output --partial "floci-compat-codedeploy"
|
|
}
|
|
|
|
@test "Terraform: ACM certificate created" {
|
|
run aws_cmd acm list-certificates
|
|
assert_success
|
|
assert_output --partial "floci-compat.internal"
|
|
}
|
|
|
|
@test "Terraform: SES identity created" {
|
|
run aws_cmd ses get-identity-verification-attributes \
|
|
--identities terraform@floci-compat.internal
|
|
assert_success
|
|
assert_output --partial "terraform@floci-compat.internal"
|
|
}
|
|
|
|
@test "Terraform: EventBridge schedule created" {
|
|
run aws_cmd scheduler get-schedule --name floci-compat-schedule
|
|
assert_success
|
|
assert_output --partial "floci-compat-schedule"
|
|
}
|
|
|
|
@test "Terraform: WAFv2 web ACL created" {
|
|
run aws_cmd wafv2 list-web-acls --scope REGIONAL
|
|
assert_success
|
|
assert_output --partial "floci-compat-waf"
|
|
}
|
|
|
|
@test "Terraform: Cost and Usage Report created" {
|
|
run aws_cmd cur describe-report-definitions
|
|
assert_success
|
|
assert_output --partial "floci-compat-report"
|
|
}
|
|
|
|
@test "Terraform: AppSync GraphQL API created" {
|
|
run aws_cmd appsync list-graphql-apis
|
|
assert_success
|
|
assert_output --partial "floci-compat-graphql"
|
|
}
|
|
|
|
@test "Terraform: ElastiCache replication group created" {
|
|
run aws_cmd elasticache describe-replication-groups --replication-group-id floci-compat-cache
|
|
assert_success
|
|
assert_output --partial "floci-compat-cache"
|
|
}
|
|
|
|
@test "Terraform: Firehose delivery stream created" {
|
|
run aws_cmd firehose list-delivery-streams
|
|
assert_success
|
|
assert_output --partial "floci-compat-firehose-basic"
|
|
}
|
|
|
|
@test "Terraform: EventBridge pipe created" {
|
|
run aws_cmd pipes list-pipes
|
|
assert_success
|
|
assert_output --partial "floci-compat-pipe"
|
|
}
|
|
|
|
@test "Terraform: RDS DB instance created and available" {
|
|
run aws_cmd rds describe-db-instances --db-instance-identifier floci-compat-db
|
|
assert_success
|
|
assert_output --partial "floci-compat-db"
|
|
assert_output --partial "available"
|
|
}
|
|
|
|
@test "Terraform: CloudWatch alarm created with tags" {
|
|
run aws_cmd cloudwatch describe-alarms --alarm-names floci-compat-cpu-alarm
|
|
assert_success
|
|
assert_output --partial "floci-compat-cpu-alarm"
|
|
|
|
ALARM_ARN=$(aws_cmd cloudwatch describe-alarms --alarm-names floci-compat-cpu-alarm \
|
|
--query 'MetricAlarms[0].AlarmArn' --output text)
|
|
run aws_cmd cloudwatch list-tags-for-resource --resource-arn "$ALARM_ARN"
|
|
assert_success
|
|
assert_output --partial "compat-test"
|
|
}
|
|
|
|
@test "Terraform: VPC created with custom DNS settings" {
|
|
run aws_cmd ec2 describe-vpcs \
|
|
--filters "Name=tag:Name,Values=floci-compat-vpc"
|
|
assert_success
|
|
assert_output --partial "floci-compat-vpc"
|
|
assert_output --partial "10.0.0.0/16"
|
|
}
|
|
|
|
@test "Terraform: VPC enableDnsSupport persisted as false" {
|
|
VPC_ID=$(aws_cmd ec2 describe-vpcs \
|
|
--filters "Name=tag:Name,Values=floci-compat-vpc" \
|
|
--query 'Vpcs[0].VpcId' --output text)
|
|
run aws_cmd ec2 describe-vpc-attribute \
|
|
--vpc-id "$VPC_ID" --attribute enableDnsSupport
|
|
assert_success
|
|
assert_output --partial '"Value": false'
|
|
}
|
|
|
|
@test "Terraform: VPC enableDnsHostnames persisted as false" {
|
|
VPC_ID=$(aws_cmd ec2 describe-vpcs \
|
|
--filters "Name=tag:Name,Values=floci-compat-vpc" \
|
|
--query 'Vpcs[0].VpcId' --output text)
|
|
run aws_cmd ec2 describe-vpc-attribute \
|
|
--vpc-id "$VPC_ID" --attribute enableDnsHostnames
|
|
assert_success
|
|
assert_output --partial '"Value": false'
|
|
}
|
|
|
|
@test "Terraform: Route53 hosted zone created" {
|
|
ZONE_ID=$(aws_cmd route53 list-hosted-zones \
|
|
--query "HostedZones[?Name=='floci-compat.internal.'].Id | [0]" \
|
|
--output text | sed 's|/hostedzone/||')
|
|
[ -n "$ZONE_ID" ]
|
|
run aws_cmd route53 get-hosted-zone --id "$ZONE_ID"
|
|
assert_success
|
|
assert_output --partial "floci-compat.internal"
|
|
}
|
|
|
|
@test "Terraform: Route53 A record created" {
|
|
ZONE_ID=$(aws_cmd route53 list-hosted-zones \
|
|
--query "HostedZones[?Name=='floci-compat.internal.'].Id | [0]" \
|
|
--output text | sed 's|/hostedzone/||')
|
|
run aws_cmd route53 list-resource-record-sets --hosted-zone-id "$ZONE_ID"
|
|
assert_success
|
|
assert_output --partial "app.floci-compat.internal"
|
|
assert_output --partial "10.0.1.10"
|
|
}
|
|
|
|
@test "Terraform: Route53 zone has auto-created SOA and NS records" {
|
|
ZONE_ID=$(aws_cmd route53 list-hosted-zones \
|
|
--query "HostedZones[?Name=='floci-compat.internal.'].Id | [0]" \
|
|
--output text | sed 's|/hostedzone/||')
|
|
run aws_cmd route53 list-resource-record-sets --hosted-zone-id "$ZONE_ID"
|
|
assert_success
|
|
assert_output --partial '"SOA"'
|
|
assert_output --partial '"NS"'
|
|
}
|
|
|
|
@test "Terraform: Route53 health check created" {
|
|
HEALTH_CHECK_ID=$(aws_cmd route53 list-health-checks \
|
|
--query "HealthChecks[?HealthCheckConfig.FullyQualifiedDomainName=='app.floci-compat.internal'].Id | [0]" \
|
|
--output text)
|
|
[ -n "$HEALTH_CHECK_ID" ]
|
|
run aws_cmd route53 get-health-check --health-check-id "$HEALTH_CHECK_ID"
|
|
assert_success
|
|
assert_output --partial "app.floci-compat.internal"
|
|
assert_output --partial "HTTP"
|
|
}
|
|
|
|
@test "Terraform: Route53 zone tags persisted" {
|
|
ZONE_ID=$(aws_cmd route53 list-hosted-zones \
|
|
--query "HostedZones[?Name=='floci-compat.internal.'].Id | [0]" \
|
|
--output text | sed 's|/hostedzone/||')
|
|
run aws_cmd route53 list-tags-for-resource \
|
|
--resource-type hostedzone --resource-id "$ZONE_ID"
|
|
assert_success
|
|
assert_output --partial "compat-test"
|
|
}
|
|
|
|
@test "Terraform: Cognito user pool client created without optional blocks" {
|
|
POOL_ID=$(aws_cmd cognito-idp list-user-pools --max-results 10 \
|
|
--query "UserPools[?Name=='floci-compat-pool'].Id | [0]" --output text)
|
|
[ -n "$POOL_ID" ]
|
|
run aws_cmd cognito-idp list-user-pool-clients --user-pool-id "$POOL_ID" \
|
|
--query "UserPoolClients[?ClientName=='floci-compat-pool-client'].ClientId | [0]" --output text
|
|
assert_success
|
|
[ -n "$output" ]
|
|
[ "$output" != "None" ]
|
|
}
|
|
|
|
@test "Terraform: Firehose extended_s3 delivery stream created with correct config" {
|
|
run aws_cmd firehose describe-delivery-stream --delivery-stream-name floci-compat-firehose \
|
|
--query "DeliveryStreamDescription.Destinations[0].ExtendedS3DestinationDescription.CompressionFormat" --output text
|
|
assert_success
|
|
assert_output "GZIP"
|
|
}
|
|
|
|
@test "Terraform: Application Auto Scaling scalable target created with tags" {
|
|
run aws_cmd application-autoscaling describe-scalable-targets --service-namespace ecs \
|
|
--resource-ids service/floci-compat-cluster/floci-compat-service \
|
|
--query "ScalableTargets[0].MaxCapacity" --output text
|
|
assert_success
|
|
assert_output "20"
|
|
|
|
run aws_cmd application-autoscaling describe-scalable-targets --service-namespace ecs \
|
|
--resource-ids service/floci-compat-cluster/floci-compat-service \
|
|
--query "ScalableTargets[0].ScalableTargetARN" --output text
|
|
assert_success
|
|
[[ "$output" == arn:aws:application-autoscaling:* ]]
|
|
|
|
run aws_cmd application-autoscaling list-tags-for-resource --resource-arn "$output" \
|
|
--query "Tags.Environment" --output text
|
|
assert_success
|
|
assert_output "compat-test"
|
|
}
|
|
|
|
@test "Terraform: Application Auto Scaling target-tracking policy round-trips resource_label" {
|
|
run aws_cmd application-autoscaling describe-scaling-policies --service-namespace ecs \
|
|
--resource-id service/floci-compat-cluster/floci-compat-service \
|
|
--query "ScalingPolicies[?PolicyName=='floci-compat-alb-request-count'].TargetTrackingScalingPolicyConfiguration.PredefinedMetricSpecification.ResourceLabel | [0]" \
|
|
--output text
|
|
assert_success
|
|
assert_output "app/floci-compat-alb/abc123/targetgroup/floci-compat-tg/def456"
|
|
|
|
run aws_cmd application-autoscaling describe-scaling-policies --service-namespace ecs \
|
|
--resource-id service/floci-compat-cluster/floci-compat-service \
|
|
--query "ScalingPolicies[?PolicyName=='floci-compat-alb-request-count'].TargetTrackingScalingPolicyConfiguration.ScaleInCooldown | [0]" \
|
|
--output text
|
|
assert_success
|
|
assert_output "240"
|
|
}
|
|
|
|
# A successful apply proves very little on its own: a response that silently drops a
|
|
# field still applies cleanly, and only shows up later as perpetual drift. Asserting an
|
|
# empty second plan is what actually catches that class of bug.
|
|
#
|
|
# Whole-config: this used to be scoped to just the Application Auto Scaling resources
|
|
# because a full re-plan reported drift on aws_cognito_user_pool (device_configuration,
|
|
# email_configuration, user_pool_add_ons), aws_db_instance (auto_minor_version_upgrade)
|
|
# and aws_kinesis_firehose_delivery_stream (s3_backup_mode) - see #2200. Now that those
|
|
# are fixed, this guards every resource in the fixture instead of a hand-picked subset.
|
|
@test "Terraform: re-planning the full configuration reports no changes" {
|
|
cd "$TF_DIR"
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color -detailed-exitcode
|
|
if [ "$status" -eq 2 ]; then
|
|
echo "# drift detected on re-plan:" >&3
|
|
echo "$output" >&3
|
|
fi
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "Terraform: IAM role attaches managed policies outside the curated set" {
|
|
run aws_cmd iam list-attached-role-policies --role-name floci-compat-managed-policy-role \
|
|
--query "sort_by(AttachedPolicies, &PolicyArn)[].PolicyArn" --output text
|
|
assert_success
|
|
assert_output --partial "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
|
|
assert_output --partial "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole"
|
|
}
|
|
|
|
# A policy AWS does not publish must still be rejected, otherwise a typo silently
|
|
# "succeeds" and Terraform/CloudFormation never surface the mistake.
|
|
@test "Terraform: attaching a nonexistent managed policy still fails" {
|
|
run aws_cmd iam attach-role-policy --role-name floci-compat-managed-policy-role \
|
|
--policy-arn "arn:aws:iam::aws:policy/AmazonS3FullAcess"
|
|
assert_failure
|
|
assert_output --partial "NoSuchEntity"
|
|
}
|
|
|
|
# Tags are stored and readable via ListRoleTags, but the provider reads them off the
|
|
# GetRole response. Omitting them there made every tagged role read back untagged.
|
|
@test "Terraform: GetRole returns the role's tags" {
|
|
run aws_cmd iam get-role --role-name floci-compat-tagged-role \
|
|
--query "Role.Tags[?Key=='Environment'].Value" --output text
|
|
assert_success
|
|
assert_output "compat"
|
|
}
|
|
|
|
@test "Terraform: GetPolicy returns the policy's tags" {
|
|
policy_arn=$(aws_cmd iam list-policies --scope Local \
|
|
--query "Policies[?PolicyName=='floci-compat-tagged-policy'].Arn" --output text)
|
|
run aws_cmd iam get-policy --policy-arn "$policy_arn" \
|
|
--query "Policy.Tags[?Key=='Environment'].Value" --output text
|
|
assert_success
|
|
assert_output "compat"
|
|
}
|
|
|
|
# The other half of the contract: IAM's listing operations deliberately return a subset
|
|
# of attributes. ListRoles "does not return the following attributes, even though they
|
|
# are an attribute of the returned object: PermissionsBoundary, RoleLastUsed, Tags".
|
|
# Emitting them here would deviate from AWS in the opposite direction.
|
|
@test "Terraform: ListRoles omits tags even for a tagged role" {
|
|
run aws_cmd iam list-roles \
|
|
--query "Roles[?RoleName=='floci-compat-tagged-role'].Tags" --output text
|
|
assert_success
|
|
refute_output --partial "compat"
|
|
}
|
|
|
|
@test "Terraform: ListPolicies omits tags and description even for a tagged policy" {
|
|
run aws_cmd iam list-policies --scope Local \
|
|
--query "Policies[?PolicyName=='floci-compat-tagged-policy'].[Tags,Description]" \
|
|
--output text
|
|
assert_success
|
|
refute_output --partial "compat"
|
|
refute_output --partial "round trip"
|
|
}
|
|
|
|
# The assertion that actually matters for the drift class: tags that do not survive the
|
|
# round trip apply cleanly and then re-plan dirty forever.
|
|
@test "Terraform: re-planning the tagged IAM resources reports no changes" {
|
|
cd "$TF_DIR"
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color -detailed-exitcode \
|
|
-target=aws_iam_role.tagged \
|
|
-target=aws_iam_policy.tagged
|
|
if [ "$status" -eq 2 ]; then
|
|
echo "# drift detected on re-plan:" >&3
|
|
echo "$output" >&3
|
|
fi
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "Terraform: GuardDuty detector is created with features" {
|
|
run aws_cmd guardduty list-detectors --query "DetectorIds[0]" --output text
|
|
assert_success
|
|
DETECTOR_ID="$output"
|
|
run aws_cmd guardduty get-detector --detector-id "$DETECTOR_ID" \
|
|
--query "[Status, FindingPublishingFrequency]" --output text
|
|
assert_success
|
|
assert_output --partial "ENABLED"
|
|
assert_output --partial "SIX_HOURS"
|
|
}
|
|
|
|
@test "Terraform: GuardDuty organization configuration round-trips" {
|
|
run aws_cmd guardduty list-detectors --query "DetectorIds[0]" --output text
|
|
assert_success
|
|
DETECTOR_ID="$output"
|
|
run aws_cmd guardduty describe-organization-configuration --detector-id "$DETECTOR_ID" \
|
|
--query "AutoEnableOrganizationMembers" --output text
|
|
assert_success
|
|
assert_output "ALL"
|
|
}
|
|
|
|
# additional_configuration is an ordered list block; drift here means the
|
|
# emulator reordered the list on read-back.
|
|
@test "Terraform: re-planning GuardDuty reports no changes" {
|
|
cd "$TF_DIR"
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color -detailed-exitcode \
|
|
-target=aws_guardduty_detector.compat \
|
|
-target=aws_guardduty_detector_feature.runtime_monitoring \
|
|
-target=aws_guardduty_organization_configuration.compat \
|
|
-target=aws_guardduty_organization_configuration_feature.runtime_monitoring
|
|
if [ "$status" -eq 2 ]; then
|
|
echo "# drift detected on re-plan:" >&3
|
|
echo "$output" >&3
|
|
fi
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "Terraform: Transfer Family server created and ONLINE" {
|
|
run aws_cmd transfer list-servers --query "Servers[0].State" --output text
|
|
assert_success
|
|
assert_output "ONLINE"
|
|
}
|
|
|
|
@test "Terraform: CloudTrail trail created, logging and tagged" {
|
|
run aws_cmd cloudtrail describe-trails --trail-name-list floci-compat-trail \
|
|
--query "trailList[0].S3BucketName" --output text
|
|
assert_success
|
|
assert_output "floci-compat-trail-logs"
|
|
run aws_cmd cloudtrail get-trail-status --name floci-compat-trail \
|
|
--query "IsLogging" --output text
|
|
assert_success
|
|
assert_output "True"
|
|
run aws_cmd cloudtrail describe-trails --trail-name-list floci-compat-trail \
|
|
--query "trailList[0].TrailARN" --output text
|
|
assert_success
|
|
TRAIL_ARN="$output"
|
|
run aws_cmd cloudtrail list-tags --resource-id-list "$TRAIL_ARN" \
|
|
--query "ResourceTagList[0].TagsList[?Key=='Environment'].Value" --output text
|
|
assert_success
|
|
assert_output "compat-test"
|
|
}
|
|
|
|
# The tag refresh path (issue #2800): a re-plan reads the trail back, including its
|
|
# tags via ListTags, and must not report drift.
|
|
@test "Terraform: re-planning CloudTrail reports no changes" {
|
|
cd "$TF_DIR"
|
|
run terraform plan -var="endpoint=${FLOCI_ENDPOINT}" -input=false -no-color -detailed-exitcode \
|
|
-target=aws_cloudtrail.compat
|
|
if [ "$status" -eq 2 ]; then
|
|
echo "# drift detected on re-plan:" >&3
|
|
echo "$output" >&3
|
|
fi
|
|
[ "$status" -eq 0 ]
|
|
}
|