#!/usr/bin/env bash
set -euo pipefail

umask 077
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
module_dir="${TF_MODULE_DIR:-$(cd "$script_dir/.." && pwd)}"
tf=(terraform -chdir="$module_dir")

profile="$("${tf[@]}" output -raw aws_profile)"
region="$("${tf[@]}" output -raw aws_region)"
storage_json="$("${tf[@]}" output -json s3_storage)"
credentials_json="$("${tf[@]}" output -json service_credentials)"

bucket="$(jq -r '.bucket_name' <<<"$storage_json")"
role_arn="$(jq -r '.role_arn' <<<"$storage_json")"
access_key_id="$(jq -r '.s3.access_key_id' <<<"$credentials_json")"
secret_access_key="$(jq -r '.s3.secret_access_key' <<<"$credentials_json")"
external_id="$(jq -r '.s3.role_external_id // empty' <<<"$credentials_json")"
suffix="$(date +%s)-$$"
user_key="cdc/smoke/aksk-$suffix"
role_key="cdc/smoke/role-$suffix"
role_outside_key="backup-export/smoke/role-outside-cdc-$suffix"
import_key="import/smoke/read-$suffix"
import_write_key="import/smoke/denied-write-$suffix"

aws_user() {
  env -u AWS_PROFILE -u AWS_SESSION_TOKEN \
    AWS_ACCESS_KEY_ID="$access_key_id" \
    AWS_SECRET_ACCESS_KEY="$secret_access_key" \
    aws --region "$region" "$@"
}

assume_args=(
  sts assume-role
  --role-arn "$role_arn"
  --role-session-name "date-integration-s3-smoke"
  --duration-seconds 900
  --output json
)
if [[ -n "$external_id" ]]; then
  assume_args+=(--external-id "$external_id")
fi

role_credentials="$(aws --profile "$profile" --region "$region" "${assume_args[@]}")"
role_access_key_id="$(jq -r '.Credentials.AccessKeyId' <<<"$role_credentials")"
role_secret_access_key="$(jq -r '.Credentials.SecretAccessKey' <<<"$role_credentials")"
role_session_token="$(jq -r '.Credentials.SessionToken' <<<"$role_credentials")"

aws_role() {
  env -u AWS_PROFILE \
    AWS_ACCESS_KEY_ID="$role_access_key_id" \
    AWS_SECRET_ACCESS_KEY="$role_secret_access_key" \
    AWS_SESSION_TOKEN="$role_session_token" \
    aws --region "$region" "$@"
}

cleanup() {
  aws_user s3api delete-object --bucket "$bucket" --key "$user_key" >/dev/null 2>&1 || true
  aws_user s3api delete-object --bucket "$bucket" --key "$role_outside_key" >/dev/null 2>&1 || true
  aws_role s3api delete-object --bucket "$bucket" --key "$role_key" >/dev/null 2>&1 || true
  # The import fixture is seeded and removed with the bootstrap profile only:
  # neither the AK/SK user nor the role may write to import/ (read-only scope).
  aws --profile "$profile" --region "$region" s3api delete-object --bucket "$bucket" --key "$import_key" >/dev/null 2>&1 || true
  aws --profile "$profile" --region "$region" s3api delete-object --bucket "$bucket" --key "$import_write_key" >/dev/null 2>&1 || true
}
trap cleanup EXIT

retry() {
  local attempt
  for attempt in {1..10}; do
    if "$@"; then
      return 0
    fi
    sleep 3
  done
  return 1
}

aws --profile "$profile" --region "$region" s3api get-public-access-block --bucket "$bucket" >/dev/null

retry aws_user s3api put-object --bucket "$bucket" --key "$user_key" --body "$script_dir/smoke-s3.sh" >/dev/null
aws_user s3api head-object --bucket "$bucket" --key "$user_key" >/dev/null

retry aws_role s3api put-object --bucket "$bucket" --key "$role_key" --body "$script_dir/smoke-s3.sh" >/dev/null
aws_role s3api head-object --bucket "$bucket" --key "$role_key" >/dev/null

if aws_user s3api put-object --bucket "$bucket" --key "outside-allowed-prefix-$suffix" --body "$script_dir/smoke-s3.sh" >/dev/null 2>&1; then
  echo "AK/SK identity unexpectedly wrote outside the allowed prefixes" >&2
  exit 1
fi

if aws_role s3api put-object --bucket "$bucket" --key "$role_outside_key" --body "$script_dir/smoke-s3.sh" >/dev/null 2>&1; then
  echo "AssumeRole identity unexpectedly wrote outside the CDC prefix" >&2
  exit 1
fi

# Import fixtures are read-only for the fixture identities: seed with the
# bootstrap profile, then confirm both the AK/SK user and the role can read
# them (import task source access) but cannot write to import/.
retry aws --profile "$profile" --region "$region" s3api put-object --bucket "$bucket" --key "$import_key" --body "$script_dir/smoke-s3.sh" >/dev/null
aws_user s3api head-object --bucket "$bucket" --key "$import_key" >/dev/null
aws_role s3api head-object --bucket "$bucket" --key "$import_key" >/dev/null

if aws_user s3api put-object --bucket "$bucket" --key "$import_write_key" --body "$script_dir/smoke-s3.sh" >/dev/null 2>&1; then
  echo "AK/SK identity unexpectedly wrote to the read-only import prefix" >&2
  exit 1
fi

if aws_role s3api put-object --bucket "$bucket" --key "$import_write_key" --body "$script_dir/smoke-s3.sh" >/dev/null 2>&1; then
  echo "AssumeRole identity unexpectedly wrote to the read-only import prefix" >&2
  exit 1
fi

echo "S3 AK/SK and AssumeRole access checks passed."
