Creating an S3 bucket

1Password SaaS Manager supports writing data to AWS S3 buckets for external analytics. This article walks you through configuring setting up AWS S3 for automated exports with proper IAM role-based access.

Feature currently in closed beta.

Quick start (recommended)

For the easiest setup, use the s3-setup.sh interactive script (download from GitHub):

# Make the script executable
chmod +x setup-s3.sh

# Run the setup script
./setup-s3.sh

The script provides:

  1. Checks prerequisites (AWS CLI, jq, valid credentials)
  2. Prompts for configuration (or uses defaults)
  3. Creates S3 bucket with encryption and versioning
  4. Creates IAM user and role with proper permissions
  5. Generates access keys (or uses existing ones)
  6. Displays ready-to-use configuration

Example session

═══════════════════════════════════════════════════════════════
  AWS S3 Setup for Data Warehouse Export
═══════════════════════════════════════════════════════════════

ℹ Checking prerequisites...
✓ AWS CLI found: aws-cli/2.x.x
✓ jq found: jq-1.x
✓ AWS credentials valid

═══════════════════════════════════════════════════════════════
  Configuration
═══════════════════════════════════════════════════════════════

? AWS Region [us-east-1]:
? S3 Bucket Name (must be globally unique) [trelica-dw-data]: my-company-dw
? IAM User Name [trelica-dw-user]:
? IAM Role Name [TrelicaDWRole]:

Proceed with this configuration? [Y/n]: y

The script uses secure temporary files that are automatically deleted when the script completes. No sensitive files are left on disk.


Manual setup instructions

If you prefer to set up resources manually or need to understand what the automated script does, follow these step-by-step instructions.

Prerequisites

  • AWS CLI installed and configured with admin credentials
  • Bash shell (macOS/Linux) or Git Bash (Windows)

Configuration variables

Before starting, set these variables to match your environment:

export AWS_REGION="us-east-1"
export BUCKET_NAME="trelica-dw-data"
export IAM_USER="trelica-dw-user"
export IAM_ROLE="TrelicaDWRole"

Note: Choose a globally unique bucket name (S3 bucket names must be unique across all AWS accounts).

Verify your AWS identity

# Check your identity
aws sts get-caller-identity

# Get your Account ID
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "Account ID: $AWS_ACCOUNT_ID"

Create S3 bucket

# Create the bucket
aws s3 mb s3://${BUCKET_NAME} --region ${AWS_REGION}

# Verify bucket was created
aws s3 ls | grep ${BUCKET_NAME}

Create IAM user

# Create the IAM user
aws iam create-user --user-name ${IAM_USER}

echo "User created: arn:aws:iam::${AWS_ACCOUNT_ID}:user/${IAM_USER}"

Create IAM role with Trust policy

# Create the role with inline trust policy (no temp file needed)
aws iam create-role \
  --role-name ${IAM_ROLE} \
  --assume-role-policy-document "{
    \"Version\": \"2012-10-17\",
    \"Statement\": [{
      \"Effect\": \"Allow\",
      \"Principal\": {
        \"AWS\": \"arn:aws:iam::${AWS_ACCOUNT_ID}:user/${IAM_USER}\"
      },
      \"Action\": \"sts:AssumeRole\"
    }]
  }"

echo "Role created: arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IAM_ROLE}"

Attach S3 permissions to role

# Attach S3 policy to the role with inline policy (no temp file needed)
aws iam put-role-policy \
  --role-name ${IAM_ROLE} \
  --policy-name S3AccessPolicy \
  --policy-document "{
    \"Version\": \"2012-10-17\",
    \"Statement\": [{
      \"Effect\": \"Allow\",
      \"Action\": [
        \"s3:GetObject\",
        \"s3:PutObject\",
        \"s3:DeleteObject\",
        \"s3:ListBucket\"
      ],
      \"Resource\": [
        \"arn:aws:s3:::${BUCKET_NAME}\",
        \"arn:aws:s3:::${BUCKET_NAME}/*\"
      ]
    }]
  }"

echo "S3 permissions attached to role"

Give user permission to assume role

# Attach assume-role policy to user with inline policy (no temp file needed)
aws iam put-user-policy \
  --user-name ${IAM_USER} \
  --policy-name AssumeRolePolicy \
  --policy-document "{
    \"Version\": \"2012-10-17\",
    \"Statement\": [{
      \"Effect\": \"Allow\",
      \"Action\": \"sts:AssumeRole\",
      \"Resource\": \"arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IAM_ROLE}\"
    }]
  }"

echo "User can now assume the role"

Create Access Keys for the user

# Create access key
aws iam create-access-key \
  --user-name ${IAM_USER} \
  --output json > access-key.json

# Display the keys
cat access-key.json

echo ""
echo "==================================="
echo "SAVE THESE CREDENTIALS!"
echo "==================================="
cat access-key.json | jq -r '"AccessKeyId: " + .AccessKey.AccessKeyId'
cat access-key.json | jq -r '"SecretAccessKey: " + .AccessKey.SecretAccessKey'
echo ""
echo "Role ARN: arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IAM_ROLE}"
echo "==================================="

# Clean up the temporary file
rm access-key.json
⚠️ Save the AccessKeyId, SecretAccessKey, and Role ARN immediately. You cannot retrieve the secret key later!

Security Note: The temporary access-key.json file is deleted automatically after displaying the credentials.

Test the setup

# Test assuming the role
aws sts assume-role \
  --role-arn "arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IAM_ROLE}" \
  --role-session-name test-session

# Test uploading a file
echo "test" > test.txt
aws s3 cp test.txt s3://${BUCKET_NAME}/test.txt
aws s3 ls s3://${BUCKET_NAME}/
aws s3 rm s3://${BUCKET_NAME}/test.txt
rm test.txt

Cleanup (optional)

If you need to remove the setup:

# Delete access keys first
aws iam list-access-keys --user-name ${IAM_USER} --query 'AccessKeyMetadata[*].AccessKeyId' --output text | \
  xargs -I {} aws iam delete-access-key --user-name ${IAM_USER} --access-key-id {}

# Delete user policies
aws iam delete-user-policy --user-name ${IAM_USER} --policy-name AssumeRolePolicy

# Delete user
aws iam delete-user --user-name ${IAM_USER}

# Delete role policies
aws iam delete-role-policy --role-name ${IAM_ROLE} --policy-name S3AccessPolicy

# Delete role
aws iam delete-role --role-name ${IAM_ROLE}

# Empty and delete bucket (be careful!)
aws s3 rm s3://${BUCKET_NAME} --recursive
aws s3 rb s3://${BUCKET_NAME}

Next steps

Once your data is published you can then connect analysis tools to your S3 bucket, e.g.

Troubleshooting

Access denied errors

  1. Verify role ARN: Ensure the roleArn in your config matches the role created
  2. Check credentials: Verify AccessKeyId and SecretAccessKey are correct
  3. Test assume role:

    aws sts assume-role \
      --role-arn "arn:aws:iam::${AWS_ACCOUNT_ID}:role/${IAM_ROLE}" \
      --role-session-name test

Bucket access issues

  1. Check bucket name: Ensure it matches exactly (case-sensitive)
  2. Verify region: Bucket and configuration must use the same region
  3. Test bucket access:

    aws s3 ls s3://${BUCKET_NAME}/

Role assumption fails

  1. Check trust policy: User must be listed in the role's trust policy
  2. Verify assume-role permission: User must have sts:AssumeRole permission
  3. Check user ARN:

    aws iam get-user --user-name ${IAM_USER}

Security best practices

  1. Use least privilege: Only grant permissions actually needed
  2. Rotate access keys: Periodically create new keys and delete old ones
  3. Monitor usage: Enable CloudTrail logging to track S3 access

Was this article helpful?

0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.