I’ve been playing around quite a bit with MinIO lately – after all, why use cloud services where everything is readily available if I can complicate things a bit by doing everything manually?
Anyway… I came across a situation here and had it noted down in my Obsidian, but I thought it would be interesting to put it here on the blog (which I’m not sure if it still makes sense to maintain, to be honest).
The idea:
- I have several projects and want to keep bucket access separated by project, so that one doesn’t impact the other.
- I want each project to have its own access user, keeping them isolated.
- Yes, I could do it the easy way, creating just folders for each project and be happy, but who said happiness is an option when we work in IT? 🙂
Now, why?
Advantages of This Approach
- Isolation: Each project has its own storage space
- Security: Each application only has access to its own bucket
- Operational efficiency: A single MinIO instance for all projects
- Flexibility: Easy to add new projects without reconfiguring the entire infrastructure
Alright, let’s go!
Prerequisites
- Docker installed (for MinIO execution)
- Windows PowerShell
1. MinIO Configuration
1.1 Check if MinIO is already running
# Check if MinIO is running
docker ps | findstr minio
1.2 If MinIO is not running
If the command above doesn’t return any results, you need to create and start the MinIO container:
# Create a directory for data persistence
mkdir -p d:\Projetos\minio\data
# Run the MinIO container
docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
-e "MINIO_ROOT_USER=minioadmin" \
-e "MINIO_ROOT_PASSWORD=minioadmin" \
-v d:\Projetos\minio\data:/data \
minio/minio server /data --console-address ":9001"
What we’re doing with this:
- Creating a container called “minio”
- Exposing the MinIO API on port 9000
- Exposing the web administration interface on port 9001
- Setting the default user and password as “minioadmin”
- Mounting the local directory for data persistence
To access the MinIO administration console, just use the URL: http://localhost:9001
2. MinIO Client (mc) Installation
# Download the MinIO client for Windows
Invoke-WebRequest -Uri https://dl.min.io/client/mc/release/windows-amd64/mc.exe -OutFile mc.exe
# Configure the client to connect to the local MinIO instance
.\mc.exe alias set local http://localhost:9000 minioadmin minioadmin
3. Creating Buckets
# Create buckets for each project
.\mc.exe mb local/project-a
.\mc.exe mb local/project-b
4. Creating Access Policies
For greater references about the JSON, go to the end of the page.
Create policy file for Project A (policy-project-a.json):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::project-a"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::project-a/*"
]
}
]
}
Create policy file for Project B (policy-project-b.json):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::project-b"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::project-b/*"
]
}
]
}
# Create policies from JSON files
.\mc.exe admin policy create local policy-project-a .\policy-project-a.json
.\mc.exe admin policy create local policy-project-b .\policy-project-b.json
# Associate policies with users
.\mc.exe admin user add local user-project-a password123
.\mc.exe admin user add local user-project-b password456
# Apply policies to users
.\mc.exe admin policy attach local policy-project-a --user user-project-a
.\mc.exe admin policy attach local policy-project-b --user user-project-b
5. Testing Access
5.1 Testing with MinIO Client
# Configure alias for Project A user
.\mc.exe alias set project-a-alias http://localhost:9000 user-project-a password123
# Test access to Project A bucket
.\mc.exe ls project-a-alias/project-a
# Try to access Project B bucket (should fail)
.\mc.exe ls project-a-alias/project-b
5.2 Testing with Python (boto3)
import boto3
from botocore.exceptions import ClientError
# Configure S3 client for Project A
s3_client = boto3.client(
's3',
endpoint_url='http://localhost:9000',
aws_access_key_id='user-project-a',
aws_secret_access_key='password123',
region_name='us-east-1'
)
# List objects in bucket
response = s3_client.list_objects_v2(Bucket='project-a')
6. Adding New Projects
To add a new project, follow these steps:
Create a new bucket:
.\mc.exe mb local/project-nameCreate a policy file for the new project (
policy-project-name.json)Create the policy in MinIO:
.\mc.exe admin policy create local policy-project-name .\policy-project-name.jsonCreate a user for the project:
.\mc.exe admin user add local user-project-name secure-passwordAssociate the policy with the user:
.\mc.exe admin policy attach local policy-project-name --user user-project-name
JSON Policy Reference
Basic Structure
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:<ActionName>", ...],
"Resource": "arn:aws:s3:::*",
"Condition": { ... }
}
]
}
Valid Values for Each Field
1. Version
- Fixed value:
"2012-10-17"(current specification standard)
2. Effect
- Valid values:
"Allow"or"Deny"
3. Action
Common S3 actions supported by MinIO:
"s3:*"– All actions"s3:GetObject"– Get objects"s3:PutObject"– Put objects"s3:DeleteObject"– Delete objects"s3:ListBucket"– List bucket contents"s3:GetBucketLocation"– Get bucket location"s3:CreateBucket"– Create bucket"s3:DeleteBucket"– Delete bucket
4. Resource
The format follows the ARN (Amazon Resource Name) standard:
"arn:aws:s3:::*"– All buckets and objects"arn:aws:s3:::bucket-name"– A specific bucket"arn:aws:s3:::bucket-name/*"– All objects in a specific bucket"arn:aws:s3:::bucket-name/prefix/*"– Objects with a specific prefix
Supports wildcard characters:
*– Matches zero or more characters?– Matches exactly one character
5. Principal
{"AWS": ["*"]}– Any user (anonymous access){"AWS": ["arn:aws:iam::account-id:user/username"]}– Specific user
6. Condition (Not used here)
Allows defining additional conditions for policy application, such as:
- IP-based conditions
- Tag-based conditions
- Date/time-based conditions
Additional References
Useful Commands
- List all buckets:
.\mc.exe ls local - List objects in a bucket:
.\mc.exe ls local/bucket-name - Upload a file:
.\mc.exe cp ./file.txt local/bucket-name/ - Download a file:
.\mc.exe cp local/bucket-name/file.txt ./ - Remove a file:
.\mc.exe rm local/bucket-name/file.txt
