When to Use
- Tenant environment provisioning: Automatically create a dedicated S3 bucket when a new tenant is onboarded, applying standard encryption and access block policies.
- Per-environment bucket setup: Provision separate dev, staging, and prod buckets at workflow start to isolate data between environments.
- Backup destination creation: Create a timestamped backup bucket at the start of a scheduled backup workflow before writing any data.
- Media storage provisioning: Set up an application-specific bucket with the correct ACL and CORS settings when deploying a new application module.
- Compliance archive bucket: Create a KMS-encrypted, versioned bucket with all public access blocked for regulated data retention workflows.
Configuration
Connection
| Field | Required | Description |
accessKeyId | Required | AWS Access Key ID. Pattern: ^[A-Z0-9]+$, 16–128 characters. Store in BizFirst Credentials Manager. |
secretKey | Required | AWS Secret Access Key. Never log or expose. Use Credentials Manager. |
sessionToken | Optional | STS session token for temporary credentials. |
region | Required | Target AWS region (e.g. us-east-1). The bucket will be created in this region. |
Operation Fields
| Field | Required | Description |
bucketName | Required | Globally unique bucket name. 3–63 lowercase characters; letters, numbers, and hyphens only. Must not look like an IP address. |
cannedAcl | Optional | Canned ACL: private (default), public-read, public-read-write, authenticated-read. Default: private. |
serverSideEncryption | Optional | Encryption algorithm: AES256 (default), aws:kms, none. Default: AES256. |
kmsKeyId | Optional | KMS key ARN or alias. Required when serverSideEncryption is aws:kms. |
enableVersioning | Optional | Enable S3 versioning on the bucket. Default: false. Recommended for buckets subject to automated deletions. |
blockPublicAcls | Optional | Block new public ACLs and public ACL uploads. Default: true. |
blockPublicPolicy | Optional | Block new public bucket policies. Default: true. |
ignorePublicAcls | Optional | Ignore public ACLs even if set. Default: true. |
restrictPublicBuckets | Optional | Restrict access to buckets with public policies to only AWS services and authorized users. Default: true. |
Sample Configuration
{
"connection": {
"accessKeyId": "{{ $credentials.s3_prod.accessKeyId }}",
"secretKey": "{{ $credentials.s3_prod.secretKey }}",
"region": "us-east-1"
},
"operation": {
"resource": "bucket",
"action": "create",
"bucketName": "acme-tenant-{{ $node.TenantOnboard.output.tenantSlug }}-docs",
"cannedAcl": "private",
"serverSideEncryption": "AES256",
"enableVersioning": true,
"blockPublicAcls": true,
"blockPublicPolicy": true,
"ignorePublicAcls": true,
"restrictPublicBuckets": true
}
}
Validation Errors
| Error Code | Cause & Resolution |
BucketAlreadyExists | A bucket with this name already exists in a different AWS account. S3 bucket names are globally unique — choose a different name. |
BucketAlreadyOwnedByYou | The bucket already exists in your account. If the intent was idempotent provisioning, check downstream logic to skip creation when this error occurs. |
InvalidBucketName | Bucket name violates naming rules. Ensure 3–63 lowercase alphanumeric characters or hyphens, no consecutive hyphens, does not start/end with a hyphen. |
AccessDenied | The IAM identity lacks s3:CreateBucket permission. Update the IAM policy to include s3:CreateBucket and s3:PutBucketPolicy as needed. |
InvalidLocationConstraint | The specified region is invalid or the bucket creation request conflicts with the region constraint. Verify the region field value. |
Output
Success Port
| Field | Type | Description |
status | string | success on successful bucket creation. |
errorCode | string | Empty string on success. |
bucketName | string | The name of the created bucket. |
bucketArn | string | Full ARN of the bucket, e.g. arn:aws:s3:::my-bucket. |
region | string | AWS region where the bucket was created. |
createdAt | string | ISO 8601 timestamp of bucket creation. |
versioningStatus | string | Enabled or Suspended depending on the enableVersioning setting. |
Error Port
On failure, the error port activates with errorCode (e.g. BucketAlreadyExists), errorMessage (human-readable description), and httpStatusCode from the AWS API response. Route to a notification or compensation node.
Sample Output
{
"status": "success",
"errorCode": "",
"bucketName": "acme-tenant-northstar-docs",
"bucketArn": "arn:aws:s3:::acme-tenant-northstar-docs",
"region": "us-east-1",
"createdAt": "2026-05-26T10:14:33Z",
"versioningStatus": "Enabled"
}
Expression Reference
| Expression | Result |
{{ $node.CreateBucket.output.bucketName }} | The created bucket name — use in subsequent upload or policy nodes. |
{{ $node.CreateBucket.output.bucketArn }} | Full ARN — use in IAM policy attachment or SNS notification nodes. |
{{ $node.CreateBucket.output.region }} | Region string — pass to downstream S3 nodes targeting the same bucket. |
{{ $node.CreateBucket.output.createdAt }} | Creation timestamp — log to audit trail or emit in confirmation notification. |
{{ $node.CreateBucket.output.versioningStatus }} | Confirm versioning was applied — use in conditional post-provision checks. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Credential Storage | Store accessKeyId and secretKey in BizFirst Credentials Manager. Never hardcode in workflow configuration. |
| IAM Permissions | Grant s3:CreateBucket, s3:PutBucketEncryption, s3:PutBucketVersioning, and s3:PutBucketPublicAccessBlock — nothing more. |
| Default ACL | Always use private ACL. Never configure public-read-write without a reviewed security exception. |
| Encryption Default | Always set serverSideEncryption to at least AES256 for all buckets. Use aws:kms for PII or regulated data. |
| Public Access Block | Leave all four public access block settings as true unless the bucket explicitly serves public static assets. |
| Versioning on Critical Buckets | Set enableVersioning: true for any bucket that will receive automated writes or deletions. |
| Idempotency | Handle BucketAlreadyOwnedByYou gracefully in workflow error routing — re-provisioning scenarios should not fail the workflow. |
| Bucket Name Pattern | Use consistent naming conventions (e.g. {company}-{tenant}-{purpose}) to prevent collisions and support IAM wildcard policies. |
Examples
Example 1: Tenant Onboarding — Create Isolated Storage
When a new tenant completes signup, a workflow provisions their dedicated S3 bucket with KMS encryption and versioning enabled.
// Node: CreateTenantBucket (S3 — bucket/create)
{
"bucketName": "bfai-tenant-{{ $node.TenantRecord.output.tenantId }}-storage",
"serverSideEncryption": "aws:kms",
"kmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/mrk-abc123",
"enableVersioning": true,
"blockPublicAcls": true,
"blockPublicPolicy": true,
"ignorePublicAcls": true,
"restrictPublicBuckets": true
}
// Next node: RecordBucketArn (Variable Assignment)
// Sets $workflow.tenantBucketArn = {{ $node.CreateTenantBucket.output.bucketArn }}
Example 2: CI/CD Pipeline — Per-Environment Provisioning
A deployment workflow creates environment-specific buckets if they do not yet exist, using error routing to skip BucketAlreadyOwnedByYou and proceed.
// Node: CreateEnvBucket (S3 — bucket/create)
{
"bucketName": "myapp-{{ $node.DeployConfig.output.environment }}-artifacts",
"cannedAcl": "private",
"serverSideEncryption": "AES256",
"enableVersioning": false
}
// Error port route: IF errorCode == "BucketAlreadyOwnedByYou" → Continue
// Success port route: LogBucketCreation → UploadArtifacts
Example 3: Compliance Archive Bucket Setup
A quarterly compliance workflow creates a WORM-style archive bucket with all public access blocked and KMS encryption for regulated financial records.
// Node: CreateArchiveBucket (S3 — bucket/create)
{
"bucketName": "acme-compliance-archive-{{ $now | date: 'YYYY-Q' }}",
"cannedAcl": "private",
"serverSideEncryption": "aws:kms",
"kmsKeyId": "{{ $env.COMPLIANCE_KMS_KEY_ARN }}",
"enableVersioning": true,
"blockPublicAcls": true,
"blockPublicPolicy": true,
"ignorePublicAcls": true,
"restrictPublicBuckets": true
}
// Next: NotifyComplianceTeam with bucketArn in message body