Skip to content

nullplatform/services-s-3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 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