mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 11:21:49 +00:00
7.3 KiB
7.3 KiB
EKS access entry: lifecycle contract
Present contract under ADR-0003 S1, recorded before the resource moved and updated after the owner extraction.
It describes the code as it stands, so it claims no conformance; the gaps below are observed behaviour, not targets.
The extraction establishes resource ownership and dependency direction only; it adds no ADR-0003 evidence for interruption, recovery, fencing or readiness.
Paths are relative to spinifex/ unless they start with tests/.
Scope
An access entry has no realization of its own.
Create, update, delete and policy association complete synchronously within the request as writes to the account's EKS bucket; the token webhook reads the record when it authenticates a get-token bearer.
Contract
| Item | Present behaviour | Evidence |
|---|---|---|
| Identity | Cluster name plus principal ARN. Key and ARN suffix use sha256hex(principalARN) (domains/eks/access/store.go PrincipalARNHash). ARN arn:aws:eks:{region}:{account}:access-entry/{cluster}/{hash} (foundation/aws/arn/eks.go); the AWS ARN shape differs and is not verified. |
handlers/eks/service_impl_test.go TestAccessEntry_CreateDescribeListDelete, domains/eks/access/store_test.go TestKeyPaths, gateway/eks/authz_test.go TestResourceARNsAccessEntryMatchesHandler |
| Scope | Account and Region, within one cluster: keys live under clusters/{cluster}/access-entries/ in the eks-account-{account} bucket. |
handlers/eks/access_lifecycle_test.go TestAccessEntryPersistedLayout_TopLevelAndNestedFieldNames, TestAccessEntryRecord_DecodesHandWrittenJSON, handlers/eks/create_cluster_test.go TestCreateCluster_SeedsCreatorAdminAccessEntry |
| Durable owner and record | domains/eks/access (Owner) is the only writer of Record with nested AssociatedPolicy and Scope: Create, SeedCreatorAdmin (cluster launch), Update, Associate, Disassociate and Delete. Keys and field names are unchanged by the move. DeleteClusterPrefix (handlers/eks/cluster_state.go) still erases entries with the cluster, and the gateway process reads records through the exported access.Get in ResolveTokenReview (handlers/eks/token_review.go). |
handlers/eks/access_lifecycle_test.go TestAccessEntryPersistedLayout_TopLevelAndNestedFieldNames, TestAccessEntryRecord_DecodesHandWrittenJSON, domains/eks/access/owner_test.go, domains/eks/access/store_test.go, handlers/eks/create_cluster_test.go TestCreateCluster_SeedsCreatorAdminAccessEntry |
| AWS adapter | handlers/eks keeps request validation (entry type, supported policy, scope), the cluster existence check (acctKVForCluster), awserrors mapping and the AWS projection. gateway/eks/authz.go uses access.PrincipalARNHash. |
handlers/eks/service_impl_test.go access cases, gateway/eks/authz_test.go TestResourceARNsAccessEntryMatchesHandler |
| Desired state | Principal, Kubernetes username and groups, type (STANDARD only), tags (set at create only) and cluster-scoped access policy associations. |
handlers/eks/service_impl_test.go TestAccessEntry_RejectsNodeType, TestAccessPolicy_AssociateRejectsUnsupportedPolicyAndScope, TestAccessPolicy_AssociateRejectsNamespaceScope, handlers/eks/access_lifecycle_test.go TestAccessEntry_UpdateWithNoFieldsKeepsUsernameAndGroups |
| Generation | None. Update, associate and disassociate retry against the KV revision; create and delete do not. | |
| Observed state | Not tracked; the record is the only state. | |
| Readiness | Usable by token review as soon as the write returns. | handlers/eks/token_review_test.go TestResolveTokenReview_AuthenticatesViaVerifyAndKV, TestResolveTokenReview_NoAccessEntryDenies, handlers/eks/service_impl_test.go TestAccessPolicy_DisassociateRemovesProjectedGroup |
| Idempotency | clientRequestToken is ignored. Update always advances modifiedAt, even when nothing changes. A duplicate create returns ResourceInUseException; a repeated delete returns ResourceNotFoundException; disassociating an unbound policy succeeds without change. Internal NATS redelivery of create returns ResourceInUseException to the redelivered request. |
handlers/eks/service_impl_test.go TestAccessEntry_CreateDescribeListDelete, TestAccessEntry_DescribeDeleteMissingIsNotFound, handlers/eks/access_lifecycle_test.go TestAccessPolicy_DisassociateUnassociatedLeavesRecordUnchanged, TestAccessPolicy_AssociateWithNoEntryIsNotFound |
| Dependencies | Every action requires only that the cluster's meta record exists (acctKVForCluster); cluster status is not read, so actions succeed on a CREATING, FAILED or DELETING cluster. Token review does not check the cluster at all. The principal is not checked against IAM. |
handlers/eks/service_impl_test.go TestAccessEntry_UnknownClusterIsNotFound, handlers/eks/access_lifecycle_test.go TestAccessEntryActionsIgnoreClusterLifecycleStatus, TestResolveTokenReview_AuthenticatesWithoutClusterMeta |
| Authorization | Gateway authz derives the access-entry ARN with PrincipalARNHash (gateway/eks/authz.go). No iam:PassRole. The STS step of token review is the existing eks.VerifyToken NATS contract served by awsgw. |
gateway/eks/authz_test.go TestResourceARNsAccessEntryMatchesHandler |
| Deletion ordering | Delete is get-then-delete, not conditional. Cluster delete erases entries in the prefix purge only after all infrastructure teardown succeeds; on failure they survive while the cluster stays DELETING. |
handlers/eks/access_lifecycle_test.go TestDeleteClusterPrefix_SweepsAccessEntriesScopedToCluster |
| Restart and interruption | The prefix purge deletes keys in listing order; an interruption after the meta key is gone leaves entries that a new cluster of the same name inherits. Reclaiming a FAILED cluster and a failed launch purge with the meta kept, so the recreated cluster inherits the failed attempt's entries. |
none |
| End-to-end | tests/e2e/eks/eks_test.go AccessEntry and GetToken; tests/integration/cross_tenant_test.go. No Terraform apply/destroy evidence for aws_eks_access_entry or aws_eks_access_policy_association. |
Gaps
- Create is get-then-put with no exclusive create, so concurrent creates for one principal both succeed and the later write wins.
- The creator-admin seed at cluster launch is an unconditional put after the cluster meta is final, so it replaces an entry for the same principal created while the cluster was
CREATING, including its policy associations. - Access actions do not check cluster status (see dependencies row), and opening the bucket creates it for an account that has none.
- Entries can outlive their cluster (interrupted prefix purge) or carry over to a recreated cluster (reclaim and failed launch keep the meta and do not purge entries separately).
- Token review authenticates against an entry without checking the cluster exists or its status.
ResolveTokenReviewopens the EKS bucket and reads the record in the gateway process through the exportedaccess.Get, outside the owner.- List ignores
maxResultsandnextToken; tagging an access-entry ARN returnsNotImplemented. - No ADR-0003 S5 failure or recovery evidence.
- Handler code receives the persisted
Recordfrom the owner, so the storage shape still crosses into the AWS adapter and token review. It is a temporary extraction boundary, not the narrow projection ADR-0004 asks for.