You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.3 KiB
214 lines
7.3 KiB
package s3tables
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/iam/utils"
|
|
)
|
|
|
|
// Permission represents a specific action permission
|
|
type Permission string
|
|
|
|
const (
|
|
// Table bucket permissions
|
|
PermCreateTableBucket Permission = "s3tables:CreateTableBucket"
|
|
PermDeleteTableBucket Permission = "s3tables:DeleteTableBucket"
|
|
PermGetTableBucket Permission = "s3tables:GetTableBucket"
|
|
PermListTableBuckets Permission = "s3tables:ListTableBuckets"
|
|
|
|
// Namespace permissions
|
|
PermCreateNamespace Permission = "s3tables:CreateNamespace"
|
|
PermDeleteNamespace Permission = "s3tables:DeleteNamespace"
|
|
PermGetNamespace Permission = "s3tables:GetNamespace"
|
|
PermListNamespaces Permission = "s3tables:ListNamespaces"
|
|
|
|
// Table permissions
|
|
PermCreateTable Permission = "s3tables:CreateTable"
|
|
PermDeleteTable Permission = "s3tables:DeleteTable"
|
|
PermGetTable Permission = "s3tables:GetTable"
|
|
PermListTables Permission = "s3tables:ListTables"
|
|
|
|
// Policy permissions
|
|
PermPutTableBucketPolicy Permission = "s3tables:PutTableBucketPolicy"
|
|
PermGetTableBucketPolicy Permission = "s3tables:GetTableBucketPolicy"
|
|
PermDeleteTableBucketPolicy Permission = "s3tables:DeleteTableBucketPolicy"
|
|
PermPutTablePolicy Permission = "s3tables:PutTablePolicy"
|
|
PermGetTablePolicy Permission = "s3tables:GetTablePolicy"
|
|
PermDeleteTablePolicy Permission = "s3tables:DeleteTablePolicy"
|
|
|
|
// Tagging permissions
|
|
PermTagResource Permission = "s3tables:TagResource"
|
|
PermListTagsForResource Permission = "s3tables:ListTagsForResource"
|
|
PermUntagResource Permission = "s3tables:UntagResource"
|
|
)
|
|
|
|
// PermissionSet represents a set of allowed permissions for a principal
|
|
type PermissionSet map[Permission]bool
|
|
|
|
// PermissionPolicy defines access control rules
|
|
type PermissionPolicy struct {
|
|
// Owner has full access to all operations
|
|
Owner string
|
|
|
|
// Permissions map principal (account ID) to allowed permissions
|
|
Permissions map[string]PermissionSet
|
|
}
|
|
|
|
// OperationPermissions maps S3 Tables operations to required permissions
|
|
var OperationPermissions = map[string]Permission{
|
|
"CreateTableBucket": PermCreateTableBucket,
|
|
"DeleteTableBucket": PermDeleteTableBucket,
|
|
"GetTableBucket": PermGetTableBucket,
|
|
"ListTableBuckets": PermListTableBuckets,
|
|
"CreateNamespace": PermCreateNamespace,
|
|
"DeleteNamespace": PermDeleteNamespace,
|
|
"GetNamespace": PermGetNamespace,
|
|
"ListNamespaces": PermListNamespaces,
|
|
"CreateTable": PermCreateTable,
|
|
"DeleteTable": PermDeleteTable,
|
|
"GetTable": PermGetTable,
|
|
"ListTables": PermListTables,
|
|
"PutTableBucketPolicy": PermPutTableBucketPolicy,
|
|
"GetTableBucketPolicy": PermGetTableBucketPolicy,
|
|
"DeleteTableBucketPolicy": PermDeleteTableBucketPolicy,
|
|
"PutTablePolicy": PermPutTablePolicy,
|
|
"GetTablePolicy": PermGetTablePolicy,
|
|
"DeleteTablePolicy": PermDeleteTablePolicy,
|
|
"TagResource": PermTagResource,
|
|
"ListTagsForResource": PermListTagsForResource,
|
|
"UntagResource": PermUntagResource,
|
|
}
|
|
|
|
// CheckPermission checks if a principal has permission to perform an operation
|
|
func CheckPermission(operation, principal, owner string) bool {
|
|
// Deny access if identities are empty
|
|
if principal == "" || owner == "" {
|
|
return false
|
|
}
|
|
|
|
// Owner always has permission
|
|
if principal == owner {
|
|
return true
|
|
}
|
|
|
|
// For now, only the owner can perform operations
|
|
// This can be extended to support more granular permissions via policies
|
|
// TODO: Integrate with full IAM policy evaluation
|
|
return false
|
|
}
|
|
|
|
// CanCreateTableBucket checks if principal can create table buckets
|
|
func CanCreateTableBucket(principal, owner string) bool {
|
|
return CheckPermission("CreateTableBucket", principal, owner)
|
|
}
|
|
|
|
// CanDeleteTableBucket checks if principal can delete table buckets
|
|
func CanDeleteTableBucket(principal, owner string) bool {
|
|
return CheckPermission("DeleteTableBucket", principal, owner)
|
|
}
|
|
|
|
// CanGetTableBucket checks if principal can read table bucket details
|
|
func CanGetTableBucket(principal, owner string) bool {
|
|
return CheckPermission("GetTableBucket", principal, owner)
|
|
}
|
|
|
|
// CanListTableBuckets checks if principal can list table buckets
|
|
func CanListTableBuckets(principal, owner string) bool {
|
|
return CheckPermission("ListTableBuckets", principal, owner)
|
|
}
|
|
|
|
// CanCreateNamespace checks if principal can create namespaces
|
|
func CanCreateNamespace(principal, owner string) bool {
|
|
return CheckPermission("CreateNamespace", principal, owner)
|
|
}
|
|
|
|
// CanDeleteNamespace checks if principal can delete namespaces
|
|
func CanDeleteNamespace(principal, owner string) bool {
|
|
return CheckPermission("DeleteNamespace", principal, owner)
|
|
}
|
|
|
|
// CanGetNamespace checks if principal can read namespace details
|
|
func CanGetNamespace(principal, owner string) bool {
|
|
return CheckPermission("GetNamespace", principal, owner)
|
|
}
|
|
|
|
// CanListNamespaces checks if principal can list namespaces
|
|
func CanListNamespaces(principal, owner string) bool {
|
|
return CheckPermission("ListNamespaces", principal, owner)
|
|
}
|
|
|
|
// CanCreateTable checks if principal can create tables
|
|
func CanCreateTable(principal, owner string) bool {
|
|
return CheckPermission("CreateTable", principal, owner)
|
|
}
|
|
|
|
// CanDeleteTable checks if principal can delete tables
|
|
func CanDeleteTable(principal, owner string) bool {
|
|
return CheckPermission("DeleteTable", principal, owner)
|
|
}
|
|
|
|
// CanGetTable checks if principal can read table details
|
|
func CanGetTable(principal, owner string) bool {
|
|
return CheckPermission("GetTable", principal, owner)
|
|
}
|
|
|
|
// CanListTables checks if principal can list tables
|
|
func CanListTables(principal, owner string) bool {
|
|
return CheckPermission("ListTables", principal, owner)
|
|
}
|
|
|
|
// CanManagePolicy checks if principal can manage policies
|
|
func CanManagePolicy(principal, owner string) bool {
|
|
return CheckPermission("ManagePolicy", principal, owner)
|
|
}
|
|
|
|
// CanManageTags checks if principal can manage tags
|
|
func CanManageTags(principal, owner string) bool {
|
|
return CheckPermission("TagResource", principal, owner)
|
|
}
|
|
|
|
// ExtractPrincipalFromContext extracts the principal (account ID) from request context
|
|
// For now, this returns the owner/creator, but can be extended to parse from request headers/certs
|
|
func ExtractPrincipalFromContext(contextID string) string {
|
|
// Try to parse as ARN first
|
|
if strings.HasPrefix(contextID, "arn:") {
|
|
info := utils.ParsePrincipalARN(contextID)
|
|
if info.AccountID != "" {
|
|
return info.AccountID
|
|
}
|
|
if info.RoleName != "" {
|
|
return info.RoleName
|
|
}
|
|
}
|
|
|
|
// Extract from context, e.g., "user123" or "account-id"
|
|
// Extract from context, e.g., "user123" or "account-id"
|
|
// This is a simplified version - in production, this would parse AWS auth headers
|
|
// TODO: Parse AWS Signature V4 identity or mTLS identity
|
|
if strings.Contains(contextID, ":") {
|
|
parts := strings.Split(contextID, ":")
|
|
return parts[0]
|
|
}
|
|
return contextID
|
|
}
|
|
|
|
// AuthError represents an authorization error
|
|
type AuthError struct {
|
|
Operation string
|
|
Principal string
|
|
Message string
|
|
}
|
|
|
|
func (e *AuthError) Error() string {
|
|
return fmt.Sprintf("unauthorized: %s is not permitted to perform %s: %s", e.Principal, e.Operation, e.Message)
|
|
}
|
|
|
|
// NewAuthError creates a new authorization error
|
|
func NewAuthError(operation, principal, message string) *AuthError {
|
|
return &AuthError{
|
|
Operation: operation,
|
|
Principal: principal,
|
|
Message: message,
|
|
}
|
|
}
|