dove
DocumentationProvisioning
Operations

Provisioning, without the black box.

Exactly what dove creates in AWS, which identity it uses, where secrets live, and what happens when you run it again.

Before anything is created

Provisioning shells out to the AWS CLI so it uses your existing credential chain or SSO profile. dove calls sts get-caller-identity, shows the account, identity ARN, derived bucket, and region, then asks for confirmation.

aws sso login --profile work
dove provision full --profile work --region us-west-2

Without --profile, dove lists configured AWS profiles and asks you to choose. That interaction means provisioning is not currently suited to an unattended CI job; use the core provisioning API only if the caller can supply the profile and owns confirmation policy.

Simple tier resources

dove provision simple creates or reconciles:

  • S3 bucketdove-shares-<account-id> by default, or the exact --bucket override.
  • Public-access block — all four S3 public-access switches are enabled.
  • Lifecycle rule — every object expires after --expire-days, default 7. This is a cleanup ceiling, separate from each link’s expiry.
  • Scoped IAM user — named after the bucket, with only S3 GetObject, PutObject, DeleteObject, and ListBucket on that bucket.
  • Long-lived access key — used for daily share operations so an SSO session’s shorter lifetime does not truncate presigned URLs.

The scoped credentials are written to ~/.config/dove/secrets.toml with mode 0600 on Unix. They are not printed and should not be committed.

What full adds

dove provision full builds on the simple tier:

ResourcePurpose and scope
S3 CORSAllows browser GETs after the gate redirects to a presigned object. It does not make the bucket public.
DynamoDB tableSame name as the bucket, on-demand billing. Stores one policy row per share; TTL is enabled on expires_at.
Gate IAM roleLogs, GetItem/UpdateItem on one table, GetObject/PutObject on one bucket, and reads one SSM parameter.
SSM SecureString/dove/<bucket>/gate-secret, the stable HMAC key for minting and rejecting forged share IDs.
Gate LambdaPython 3.12 function dove-gate-<account>; packages the handler, static decryptor page, and generic unfurl image.
API Gateway HTTP APIA default route to Lambda. Stage throttle: burst 50, sustained 25 requests/second.
CloudFrontPublic share origin, static page host, CDN, and custom-domain attachment point.
Cost breakerCloudWatch alarm → SNS → kill-switch Lambda. More than 5,000 gate invocations in five minutes sets gate concurrency to zero.

The scoped daily-use IAM user is expanded by one action: dynamodb:PutItem on the one policy table. Operator credentials are not needed for ordinary shares after provisioning.

Re-runs and retained state

Provisioning is designed to be idempotent. It tolerates already-owned resources, reuses a saved IAM access key instead of minting another, finds the API by name, and reuses the CloudFront distribution from local config. The full-tier gate secret remains stable because changing it would invalidate outstanding share IDs. A custom gate_url is preserved on re-provision.

Honest edge: current reuse depends partly on local config and secrets. Losing those files does not delete AWS resources, but it removes dove’s local knowledge and may complicate reconciliation.

Local state

  • ~/.config/dove/config.toml — active backend and non-secret resource identifiers.
  • ~/.config/dove/secrets.toml — scoped AWS key and full-tier gate secret.
  • $XDG_CONFIG_HOME/dove/… — used instead when XDG_CONFIG_HOME is set.
  • $DOVE_CONFIG — exact config-registry path override. There is no equivalent exact-path override for secrets in the current implementation.

Custom domain

dove domain add share.example.com

This full-tier command requests a DNS-validated ACM certificate in us-east-1, prints the validation CNAME, waits for issuance, attaches the alias and certificate to the existing CloudFront distribution, then prints the CNAME that points your subdomain at CloudFront. New links use the custom origin after the updated config is saved.

Operational controls and teardown

dove gate status
dove gate disable
dove gate enable

Disable sets the gate Lambda’s reserved concurrency to zero; enable removes that override. The circuit breaker uses the same mechanism automatically.

There is no dove destroy command today. Removing provisioned infrastructure is a manual AWS operation. Review dependencies before deleting resources, and revoke or preserve any required shares first.