Team sharing (S3) explains how to point a folder at a bucket. This page is for whoever administers that bucket: it gives two ready-made access levels so a publisher can push results without being able to read them back, and readers can pull everything without being able to change it.
Both levels are locked to your office / VPN IP addresses.
Level | Can do | Cannot do |
Publisher | Upload every shared file; read and write | Read any other shared file |
Reader | List and download everything shared; write | Change anything except |
issues.csv is the exception in both directions on purpose — it is the one file both sides need to write, so issues raised by readers survive and publishers can see them.
Replace these placeholders everywhere they appear:
stood-flows-share — your bucket name.
shared — the S3 folder configured in Stood Flows (drop the shared/ part of the paths entirely if you left the S3 folder blank).
203.0.113.0/24, 198.51.100.7/32 — the IP ranges allowed to reach the bucket.
Attach each policy to its own identity, so one set of keys is a publisher and the other a reader.
Uploads anything, reads nothing but issues.csv.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideAllowedIPs",
"Effect": "Deny",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::stood-flows-share",
"arn:aws:s3:::stood-flows-share/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["203.0.113.0/24", "198.51.100.7/32"]
}
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::stood-flows-share",
"arn:aws:s3:::stood-flows-share/*"
],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
},
{
"Sid": "ListBucketForConnectionTest",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::stood-flows-share"
},
{
"Sid": "PublishAnyShareableObject",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::stood-flows-share/shared/*"
},
{
"Sid": "ReadIssuesCsvOnly",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:GetObjectVersion"],
"Resource": "arn:aws:s3:::stood-flows-share/shared/graphs/*/issues.csv"
},
{
"Sid": "DenyReadingAnythingElse",
"Effect": "Deny",
"Action": ["s3:GetObject", "s3:GetObjectVersion"],
"NotResource": "arn:aws:s3:::stood-flows-share/shared/graphs/*/issues.csv"
}
]
}Downloads everything, writes nothing but issues.csv.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideAllowedIPs",
"Effect": "Deny",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::stood-flows-share",
"arn:aws:s3:::stood-flows-share/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["203.0.113.0/24", "198.51.100.7/32"]
}
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::stood-flows-share",
"arn:aws:s3:::stood-flows-share/*"
],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
},
{
"Sid": "ListShared",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::stood-flows-share"
},
{
"Sid": "ReadEverythingShared",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:GetObjectVersion"],
"Resource": "arn:aws:s3:::stood-flows-share/shared/*"
},
{
"Sid": "WriteIssuesCsvOnly",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::stood-flows-share/shared/graphs/*/issues.csv"
},
{
"Sid": "DenyWritingAnythingElse",
"Effect": "Deny",
"Action": ["s3:PutObject", "s3:PutObjectAcl", "s3:DeleteObject", "s3:DeleteObjectVersion"],
"NotResource": "arn:aws:s3:::stood-flows-share/shared/graphs/*/issues.csv"
}
]
}Stood Flows signs in with an Access Key ID and Secret Access Key, so attach these policies to two IAM users. Temporary role credentials (which also carry a session token) are not accepted by the S3 settings form.
A publisher should not press Refresh. Refresh pulls down every shared file, so with the publisher policy it stops with an access-denied error as soon as it reaches a file that is not issues.csv. Publishers publish; readers refresh.
Issue lists are merged, never overwritten. Both sides write issues.csv — a publisher publishes it with the analysis, and readers raise, comment on and close issues against their own copy — so publishing and refreshing each merge the two lists instead of one replacing the other. Readers also get a Publish issues button that sends their issue changes back to the bucket and touches nothing else: exactly what the Reader policy above allows.
Listing is allowed on the whole bucket in both policies. That is what makes the Test button in the S3 settings work — it checks the bucket itself, not a folder inside it. You can restrict listing to the shared folder only, but then Test always reports a failure even though publishing and refreshing work.
Nothing can be deleted with either policy. Stood Flows never deletes from S3 — it only overwrites — so old files stay until you remove them. Turning on bucket versioning plus a lifecycle rule gives you history and automatic tidying.
IP restrictions have edges. They apply to traffic arriving over the internet, so anyone off the VPN, on a home connection with a changing IP, or reaching S3 through a VPC endpoint will be denied. Keep the allowed ranges under review.