Skip to content

nullplatform/services-s-3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AWS S3 Service

Nullplatform dependency service that provisions and manages an Amazon S3 bucket on AWS. Each application link creates a dedicated IAM user + access key with scoped S3 permissions, so apps authenticate with standard AWS credentials (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY).

The service lives under aws-s3-bucket/ to keep the repo open for future S3-related services.

What It Does

  • Provisions an S3 bucket via OpenTofu (versioning, server-side encryption, public access block)
  • Creates a dedicated IAM user per link with an inline policy scoped to the bucket (and optional path prefix)
  • Exposes AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY per link (each linked app gets its own IAM user) plus BUCKET_NAME / BUCKET_ARN / BUCKET_REGION from the service itself
  • Stores per-instance OpenTofu state in a dedicated bucket (np-service-<SERVICE_ID>) with native S3 locking (use_lockfile=true)

Repository Layout

.
├── aws-s3-bucket/
│   ├── specs/
│   │   ├── service-spec.json.tpl   # Service schema (attributes user sees)
│   │   └── links/connect.json.tpl  # Link schema (access_level, path_prefix, credentials)
│   ├── deployment/                 # OpenTofu module: S3 bucket + versioning + encryption
│   ├── permissions/                # OpenTofu module: IAM user + access key + scoped policy (per link)
│   ├── requirements/               # OpenTofu module: IAM policies the agent role needs
│   ├── workflows/aws/              # Workflow YAMLs (create/update/delete/link/link-update/unlink)
│   ├── scripts/aws/                # build_context, do_tofu, write_service_outputs, write_link_outputs, delete_tfstate_bucket
│   ├── entrypoint/                 # entrypoint/service/link (agent entrypoint)
│   └── values.yaml                 # Static config (aws_profile for local dev)
└── README.md

Service Configuration Parameters

Exposed in the nullplatform UI when creating/updating the service:

Parameter Type Default Allowed Values Editable After Create
bucket_name_suffix string lowercase alphanumeric + -, 3–40 chars No
versioning bool true Yes
encryption string AES256 AES256, aws:kms Yes
public_access_block bool true Yes
force_destroy bool false Yes

Bucket naming: np-<sanitized-service-name>-<bucket_name_suffix> (computed once on first create, then persisted — immutable to prevent accidental replacement on service rename).

Link Parameters (connect)

Parameter Type Default Description
access_level enum read-write read, write, read-write
path_prefix string "" Scope IAM permissions to a key prefix (empty = full bucket)

Service Attributes (post-create, exported as env vars)

Attribute Description
bucket_name S3 bucket name
bucket_arn S3 bucket ARN
bucket_region AWS region

Link Attributes (per link, exported as env vars)

Only credentials are exposed at the link level — bucket identity (name / ARN / region) comes from the service attributes above to avoid duplicate env vars in linked apps.

Attribute Env Var Type Description
aws_access_key_id plain IAM user access key ID
aws_secret_access_key secret IAM user secret access key

Workflows

Workflow Trigger What It Does
create Service created Creates bucket, versioning, encryption, public access block
update Service updated Re-applies terraform with updated attributes
delete Service deleted Destroys bucket (needs force_destroy=true if non-empty) and tfstate bucket
link Application linked Creates IAM user + access key scoped to the bucket and access level
link-update Link updated In-place update of the IAM user policy (access_level or path_prefix changes). Credentials are preserved.
unlink Application unlinked Destroys the IAM user and access key

Requirements

nullplatform prerequisites

  • An account-level provider exposing account.region

AWS IAM permissions (for the agent role)

The agent executing this service needs the IAM policies defined in aws-s3-bucket/requirements/main.tf:

  • S3 bucket management (s3:CreateBucket, s3:PutBucketVersioning, etc.) over *
  • IAM user management (iam:CreateUser, iam:CreateAccessKey, iam:PutUserPolicy, etc.) over arn:aws:iam::*:user/np-s3-* (or * for simpler scope)
  • S3 tfstate management over arn:aws:s3:::np-service-*

Runtime dependencies

  • OpenTofu 1.11.6 — auto-downloaded to /tmp/np-tofu-bin/ if not in PATH. Version 1.10+ is required for native S3 state locking (use_lockfile=true), which avoids the need for a DynamoDB lock table.
  • AWS CLI
  • jq

How to register this service in nullplatform

Use the nullplatform/service_definition and nullplatform/service_definition_agent_association modules. Example:

module "service_definition_aws_s3_bucket" {
  source = "git::https://github.com/nullplatform/tofu-modules.git//nullplatform/service_definition?ref=v1.51.0"
  nrn    = var.nrn

  git_provider      = "github"
  repository_org    = "nullplatform"
  repository_name   = "services-s-3"
  repository_branch = "main"
  service_path      = "aws-s3-bucket"

  service_name = "AWS S3 Bucket"
}

module "service_definition_channel_association_aws_s3_bucket" {
  source = "git::https://github.com/nullplatform/tofu-modules.git//nullplatform/service_definition_agent_association?ref=v1.51.0"

  nrn                          = var.nrn
  api_key                      = module.service_notification_api_key.api_key
  tags_selectors               = var.tags_selectors
  service_specification_slug   = module.service_definition_aws_s3_bucket.service_specification_slug
  repository_service_spec_repo = "nullplatform/services-s-3"
  service_path                 = "aws-s3-bucket"
}

Important considerations

Data loss on delete

Deleting the service destroys the bucket. If force_destroy=false (default) and the bucket is non-empty, OpenTofu refuses to destroy. Set force_destroy=true before deleting if you want the agent to wipe objects.

Access keys are long-lived

Links use static IAM access keys. Rotate by re-creating the link or manually in the AWS console if needed.

Bucket name global uniqueness

S3 bucket names are globally unique across all AWS accounts. The combination np-<service-name>-<bucket_name_suffix> must be globally unique.

State locking

OpenTofu uses native S3 lockfile (use_lockfile=true). Concurrent apply runs are serialized — the second one waits for the lock and then sees the up-to-date state, producing idempotent behavior on retries.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors