Learn: Self-Service Cloud Resources — reference
A lookup page. The orientation covers the model.
The claim
Section titled “The claim”A field on your Environment claim, under each service:
services: <service>: serviceAccount: <sa-name> resources: <name>: # your logical name → becomes env var + resource suffix kind: <class> # objectstore | stream | keyvalue | (schema: relational | cache) engine: <impl> # s3 | sqs | sns | dynamodb access: read | readwritekindis the abstract class;enginethe concrete implementation;accessyour intent.- Built + live today:
s3(objectstore),sqs+sns(stream),dynamodb(keyvalue) — all four provisioned & ready on preprod (bravo/dispatch/dev).
Derived least-privilege IAM (per engine)
Section titled “Derived least-privilege IAM (per engine)”Generated from access, scoped to that one resource’s ARN, appended to the service’s Pod-Identity
RolePolicy. You never author it.
| engine | read |
readwrite adds |
|---|---|---|
| s3 | GetObject, ListBucket, GetBucketLocation |
PutObject, DeleteObject, AbortMultipartUpload |
| sqs | ReceiveMessage, DeleteMessage, ChangeMessageVisibility, GetQueueAttributes, GetQueueUrl |
SendMessage |
| sns | GetTopicAttributes, Subscribe, ListSubscriptionsByTopic |
Publish |
| dynamodb | GetItem, BatchGetItem, Query, Scan, DescribeTable, ConditionCheckItem |
PutItem, UpdateItem, DeleteItem, BatchWriteItem |
The safety floor (below the claim, non-overridable)
Section titled “The safety floor (below the claim, non-overridable)”- S3: PublicAccessBlock, TLS-only (
DenyInsecureTransportbucket policy), Versioning, OwnershipControls, region-pinned, encrypted. - All engines: encrypted +
DenyInsecureTransport. Encryption today is service-managed for every engine (SSE-S3 / SSE-SQS / SNSalias/aws/sns/ DynamoDB default, zero key ops).
Designed, not yet built: per-tier encryption —
elevated/pci/hipaa→ a per-team KMS CMK (cryptographic tenancy isolation, key policy scoped to the team’s roles). The Composition currently uses service-managed keys unconditionally; its comments mark the CMK path deferred, so this is not part of the non-overridable floor yet.
Consumption
Section titled “Consumption”A <service>-resources ConfigMap injects the real coordinates as env vars — read these, never hardcode:
BLOB_BUCKET · JOBS_QUEUE_URL · EVENTS_TOPIC_ARN · SESSIONS_TABLE (⇒ <NAME>_<SUFFIX> per resource)Naming: refplat-<team>-<product>-<stage>-<name>-<hash> (deterministic, ≤63-char safe, collision-resistant).
Front doors (above the claim)
Section titled “Front doors (above the claim)”All produce the same governed claim → same validation → same realization. Built: PR-as-code, Backstage form. Designed: a natural-language agent. New front doors never touch the safety floor.
Gotchas
Section titled “Gotchas”accessgates the verbs.readcan’t write — noPutObject/SendMessage/Publish. Bump toreadwrite.- The IAM lands on the named ServiceAccount’s Pod-Identity role. A pod under a different SA won’t have
it. Match
serviceAccount. - The resources are namespaced MRs (
s3.aws.m.upbound.io, Crossplane v2) — cluster-scopedkubectl get managedwon’t list them; usekubectl -n <env-ns> get bucket.s3.aws.m.upbound.io …. - The floor is non-overridable — no public access, no non-TLS, no disabling encryption. By design.
Glossary
Section titled “Glossary”- claim — your
XEnvironment;resources:is a field on each service. - kind / engine / access — abstract class / concrete impl / intent (read vs readwrite).
- derived IAM — the least-privilege policy the platform computes from
access, scoped to the ARN. - safe-by-construction — hardening applied below the claim that you can’t configure or disable.
- managed resource (MR) — the Crossplane object representing the real AWS resource.
Go deeper
Section titled “Go deeper”- Extending the catalog (platform engineers): add a new resource engine — the producer-side recipe + gotchas.
- The Environment API (the claim) · Identity & Access (where the IAM lands).
- Substrate: Crossplane · Upbound AWS provider · AWS IAM least-privilege.