aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/s3_policy_templates.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/s3api/s3_policy_templates.go')
-rw-r--r--weed/s3api/s3_policy_templates.go618
1 files changed, 618 insertions, 0 deletions
diff --git a/weed/s3api/s3_policy_templates.go b/weed/s3api/s3_policy_templates.go
new file mode 100644
index 000000000..811872aee
--- /dev/null
+++ b/weed/s3api/s3_policy_templates.go
@@ -0,0 +1,618 @@
+package s3api
+
+import (
+ "time"
+
+ "github.com/seaweedfs/seaweedfs/weed/iam/policy"
+)
+
+// S3PolicyTemplates provides pre-built IAM policy templates for common S3 use cases
+type S3PolicyTemplates struct{}
+
+// NewS3PolicyTemplates creates a new policy templates provider
+func NewS3PolicyTemplates() *S3PolicyTemplates {
+ return &S3PolicyTemplates{}
+}
+
+// GetS3ReadOnlyPolicy returns a policy that allows read-only access to all S3 resources
+func (t *S3PolicyTemplates) GetS3ReadOnlyPolicy() *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "S3ReadOnlyAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:GetObjectVersion",
+ "s3:ListBucket",
+ "s3:ListBucketVersions",
+ "s3:GetBucketLocation",
+ "s3:GetBucketVersioning",
+ "s3:ListAllMyBuckets",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ },
+ },
+ }
+}
+
+// GetS3WriteOnlyPolicy returns a policy that allows write-only access to all S3 resources
+func (t *S3PolicyTemplates) GetS3WriteOnlyPolicy() *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "S3WriteOnlyAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:PutObject",
+ "s3:PutObjectAcl",
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploads",
+ "s3:ListParts",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ },
+ },
+ }
+}
+
+// GetS3AdminPolicy returns a policy that allows full admin access to all S3 resources
+func (t *S3PolicyTemplates) GetS3AdminPolicy() *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "S3FullAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:*",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ },
+ },
+ }
+}
+
+// GetBucketSpecificReadPolicy returns a policy for read-only access to a specific bucket
+func (t *S3PolicyTemplates) GetBucketSpecificReadPolicy(bucketName string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "BucketSpecificReadAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:GetObjectVersion",
+ "s3:ListBucket",
+ "s3:ListBucketVersions",
+ "s3:GetBucketLocation",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ },
+ },
+ }
+}
+
+// GetBucketSpecificWritePolicy returns a policy for write-only access to a specific bucket
+func (t *S3PolicyTemplates) GetBucketSpecificWritePolicy(bucketName string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "BucketSpecificWriteAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:PutObject",
+ "s3:PutObjectAcl",
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploads",
+ "s3:ListParts",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ },
+ },
+ }
+}
+
+// GetPathBasedAccessPolicy returns a policy that restricts access to a specific path within a bucket
+func (t *S3PolicyTemplates) GetPathBasedAccessPolicy(bucketName, pathPrefix string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "ListBucketPermission",
+ Effect: "Allow",
+ Action: []string{
+ "s3:ListBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ },
+ Condition: map[string]map[string]interface{}{
+ "StringLike": map[string]interface{}{
+ "s3:prefix": []string{pathPrefix + "/*"},
+ },
+ },
+ },
+ {
+ Sid: "PathBasedObjectAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:DeleteObject",
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ "s3:AbortMultipartUpload",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName + "/" + pathPrefix + "/*",
+ },
+ },
+ },
+ }
+}
+
+// GetIPRestrictedPolicy returns a policy that restricts access based on source IP
+func (t *S3PolicyTemplates) GetIPRestrictedPolicy(allowedCIDRs []string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "IPRestrictedS3Access",
+ Effect: "Allow",
+ Action: []string{
+ "s3:*",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ Condition: map[string]map[string]interface{}{
+ "IpAddress": map[string]interface{}{
+ "aws:SourceIp": allowedCIDRs,
+ },
+ },
+ },
+ },
+ }
+}
+
+// GetTimeBasedAccessPolicy returns a policy that allows access only during specific hours
+func (t *S3PolicyTemplates) GetTimeBasedAccessPolicy(startHour, endHour int) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "TimeBasedS3Access",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:ListBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ Condition: map[string]map[string]interface{}{
+ "DateGreaterThan": map[string]interface{}{
+ "aws:CurrentTime": time.Now().Format("2006-01-02") + "T" +
+ formatHour(startHour) + ":00:00Z",
+ },
+ "DateLessThan": map[string]interface{}{
+ "aws:CurrentTime": time.Now().Format("2006-01-02") + "T" +
+ formatHour(endHour) + ":00:00Z",
+ },
+ },
+ },
+ },
+ }
+}
+
+// GetMultipartUploadPolicy returns a policy specifically for multipart upload operations
+func (t *S3PolicyTemplates) GetMultipartUploadPolicy(bucketName string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "MultipartUploadOperations",
+ Effect: "Allow",
+ Action: []string{
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploads",
+ "s3:ListParts",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ },
+ {
+ Sid: "ListBucketForMultipart",
+ Effect: "Allow",
+ Action: []string{
+ "s3:ListBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ },
+ },
+ },
+ }
+}
+
+// GetPresignedURLPolicy returns a policy for generating and using presigned URLs
+func (t *S3PolicyTemplates) GetPresignedURLPolicy(bucketName string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "PresignedURLAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:PutObject",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ Condition: map[string]map[string]interface{}{
+ "StringEquals": map[string]interface{}{
+ "s3:x-amz-signature-version": "AWS4-HMAC-SHA256",
+ },
+ },
+ },
+ },
+ }
+}
+
+// GetTemporaryAccessPolicy returns a policy for temporary access with expiration
+func (t *S3PolicyTemplates) GetTemporaryAccessPolicy(bucketName string, expirationHours int) *policy.PolicyDocument {
+ expirationTime := time.Now().Add(time.Duration(expirationHours) * time.Hour)
+
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "TemporaryS3Access",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:ListBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ Condition: map[string]map[string]interface{}{
+ "DateLessThan": map[string]interface{}{
+ "aws:CurrentTime": expirationTime.UTC().Format("2006-01-02T15:04:05Z"),
+ },
+ },
+ },
+ },
+ }
+}
+
+// GetContentTypeRestrictedPolicy returns a policy that restricts uploads to specific content types
+func (t *S3PolicyTemplates) GetContentTypeRestrictedPolicy(bucketName string, allowedContentTypes []string) *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "ContentTypeRestrictedUpload",
+ Effect: "Allow",
+ Action: []string{
+ "s3:PutObject",
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ Condition: map[string]map[string]interface{}{
+ "StringEquals": map[string]interface{}{
+ "s3:content-type": allowedContentTypes,
+ },
+ },
+ },
+ {
+ Sid: "ReadAccess",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:ListBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::" + bucketName,
+ "arn:seaweed:s3:::" + bucketName + "/*",
+ },
+ },
+ },
+ }
+}
+
+// GetDenyDeletePolicy returns a policy that allows all operations except delete
+func (t *S3PolicyTemplates) GetDenyDeletePolicy() *policy.PolicyDocument {
+ return &policy.PolicyDocument{
+ Version: "2012-10-17",
+ Statement: []policy.Statement{
+ {
+ Sid: "AllowAllExceptDelete",
+ Effect: "Allow",
+ Action: []string{
+ "s3:GetObject",
+ "s3:GetObjectVersion",
+ "s3:PutObject",
+ "s3:PutObjectAcl",
+ "s3:ListBucket",
+ "s3:ListBucketVersions",
+ "s3:CreateMultipartUpload",
+ "s3:UploadPart",
+ "s3:CompleteMultipartUpload",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploads",
+ "s3:ListParts",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ },
+ {
+ Sid: "DenyDeleteOperations",
+ Effect: "Deny",
+ Action: []string{
+ "s3:DeleteObject",
+ "s3:DeleteObjectVersion",
+ "s3:DeleteBucket",
+ },
+ Resource: []string{
+ "arn:seaweed:s3:::*",
+ "arn:seaweed:s3:::*/*",
+ },
+ },
+ },
+ }
+}
+
+// Helper function to format hour with leading zero
+func formatHour(hour int) string {
+ if hour < 10 {
+ return "0" + string(rune('0'+hour))
+ }
+ return string(rune('0'+hour/10)) + string(rune('0'+hour%10))
+}
+
+// PolicyTemplateDefinition represents metadata about a policy template
+type PolicyTemplateDefinition struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Category string `json:"category"`
+ UseCase string `json:"use_case"`
+ Parameters []PolicyTemplateParam `json:"parameters,omitempty"`
+ Policy *policy.PolicyDocument `json:"policy"`
+}
+
+// PolicyTemplateParam represents a parameter for customizing policy templates
+type PolicyTemplateParam struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Description string `json:"description"`
+ Required bool `json:"required"`
+ DefaultValue string `json:"default_value,omitempty"`
+ Example string `json:"example,omitempty"`
+}
+
+// GetAllPolicyTemplates returns all available policy templates with metadata
+func (t *S3PolicyTemplates) GetAllPolicyTemplates() []PolicyTemplateDefinition {
+ return []PolicyTemplateDefinition{
+ {
+ Name: "S3ReadOnlyAccess",
+ Description: "Provides read-only access to all S3 buckets and objects",
+ Category: "Basic Access",
+ UseCase: "Data consumers, backup services, monitoring applications",
+ Policy: t.GetS3ReadOnlyPolicy(),
+ },
+ {
+ Name: "S3WriteOnlyAccess",
+ Description: "Provides write-only access to all S3 buckets and objects",
+ Category: "Basic Access",
+ UseCase: "Data ingestion services, backup applications",
+ Policy: t.GetS3WriteOnlyPolicy(),
+ },
+ {
+ Name: "S3AdminAccess",
+ Description: "Provides full administrative access to all S3 resources",
+ Category: "Administrative",
+ UseCase: "S3 administrators, service accounts with full control",
+ Policy: t.GetS3AdminPolicy(),
+ },
+ {
+ Name: "BucketSpecificRead",
+ Description: "Provides read-only access to a specific bucket",
+ Category: "Bucket-Specific",
+ UseCase: "Applications that need access to specific data sets",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket to grant access to",
+ Required: true,
+ Example: "my-data-bucket",
+ },
+ },
+ Policy: t.GetBucketSpecificReadPolicy("${bucketName}"),
+ },
+ {
+ Name: "BucketSpecificWrite",
+ Description: "Provides write-only access to a specific bucket",
+ Category: "Bucket-Specific",
+ UseCase: "Upload services, data ingestion for specific datasets",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket to grant access to",
+ Required: true,
+ Example: "my-upload-bucket",
+ },
+ },
+ Policy: t.GetBucketSpecificWritePolicy("${bucketName}"),
+ },
+ {
+ Name: "PathBasedAccess",
+ Description: "Restricts access to a specific path/prefix within a bucket",
+ Category: "Path-Restricted",
+ UseCase: "Multi-tenant applications, user-specific directories",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket",
+ Required: true,
+ Example: "shared-bucket",
+ },
+ {
+ Name: "pathPrefix",
+ Type: "string",
+ Description: "Path prefix to restrict access to",
+ Required: true,
+ Example: "user123/documents",
+ },
+ },
+ Policy: t.GetPathBasedAccessPolicy("${bucketName}", "${pathPrefix}"),
+ },
+ {
+ Name: "IPRestrictedAccess",
+ Description: "Allows access only from specific IP addresses or ranges",
+ Category: "Security",
+ UseCase: "Corporate networks, office-based access, VPN restrictions",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "allowedCIDRs",
+ Type: "array",
+ Description: "List of allowed IP addresses or CIDR ranges",
+ Required: true,
+ Example: "[\"192.168.1.0/24\", \"10.0.0.0/8\"]",
+ },
+ },
+ Policy: t.GetIPRestrictedPolicy([]string{"${allowedCIDRs}"}),
+ },
+ {
+ Name: "MultipartUploadOnly",
+ Description: "Allows only multipart upload operations on a specific bucket",
+ Category: "Upload-Specific",
+ UseCase: "Large file upload services, streaming applications",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket for multipart uploads",
+ Required: true,
+ Example: "large-files-bucket",
+ },
+ },
+ Policy: t.GetMultipartUploadPolicy("${bucketName}"),
+ },
+ {
+ Name: "PresignedURLAccess",
+ Description: "Policy for generating and using presigned URLs",
+ Category: "Presigned URLs",
+ UseCase: "Frontend applications, temporary file sharing",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket for presigned URL access",
+ Required: true,
+ Example: "shared-files-bucket",
+ },
+ },
+ Policy: t.GetPresignedURLPolicy("${bucketName}"),
+ },
+ {
+ Name: "ContentTypeRestricted",
+ Description: "Restricts uploads to specific content types",
+ Category: "Content Control",
+ UseCase: "Image galleries, document repositories, media libraries",
+ Parameters: []PolicyTemplateParam{
+ {
+ Name: "bucketName",
+ Type: "string",
+ Description: "Name of the S3 bucket",
+ Required: true,
+ Example: "media-bucket",
+ },
+ {
+ Name: "allowedContentTypes",
+ Type: "array",
+ Description: "List of allowed MIME content types",
+ Required: true,
+ Example: "[\"image/jpeg\", \"image/png\", \"video/mp4\"]",
+ },
+ },
+ Policy: t.GetContentTypeRestrictedPolicy("${bucketName}", []string{"${allowedContentTypes}"}),
+ },
+ {
+ Name: "DenyDeleteAccess",
+ Description: "Allows all operations except delete (immutable storage)",
+ Category: "Data Protection",
+ UseCase: "Compliance storage, audit logs, backup retention",
+ Policy: t.GetDenyDeletePolicy(),
+ },
+ }
+}
+
+// GetPolicyTemplateByName returns a specific policy template by name
+func (t *S3PolicyTemplates) GetPolicyTemplateByName(name string) *PolicyTemplateDefinition {
+ templates := t.GetAllPolicyTemplates()
+ for _, template := range templates {
+ if template.Name == name {
+ return &template
+ }
+ }
+ return nil
+}
+
+// GetPolicyTemplatesByCategory returns all policy templates in a specific category
+func (t *S3PolicyTemplates) GetPolicyTemplatesByCategory(category string) []PolicyTemplateDefinition {
+ var result []PolicyTemplateDefinition
+ templates := t.GetAllPolicyTemplates()
+ for _, template := range templates {
+ if template.Category == category {
+ result = append(result, template)
+ }
+ }
+ return result
+}