diff options
Diffstat (limited to 'weed/iam/helpers.go')
| -rw-r--r-- | weed/iam/helpers.go | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/weed/iam/helpers.go b/weed/iam/helpers.go new file mode 100644 index 000000000..02b5fe5b4 --- /dev/null +++ b/weed/iam/helpers.go @@ -0,0 +1,126 @@ +package iam + +import ( + "crypto/rand" + "crypto/sha1" + "fmt" + "math/big" + "sort" + + "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" +) + +// Hash computes a SHA1 hash of the input string. +func Hash(s *string) string { + h := sha1.New() + h.Write([]byte(*s)) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +// GenerateRandomString generates a cryptographically secure random string. +// Uses crypto/rand for security-sensitive credential generation. +func GenerateRandomString(length int, charset string) (string, error) { + if length <= 0 { + return "", fmt.Errorf("length must be positive, got %d", length) + } + if charset == "" { + return "", fmt.Errorf("charset must not be empty") + } + b := make([]byte, length) + for i := range b { + n, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) + if err != nil { + return "", fmt.Errorf("failed to generate random index: %w", err) + } + b[i] = charset[n.Int64()] + } + return string(b), nil +} + +// GenerateAccessKeyId generates a new access key ID. +func GenerateAccessKeyId() (string, error) { + return GenerateRandomString(AccessKeyIdLength, CharsetUpper) +} + +// GenerateSecretAccessKey generates a new secret access key. +func GenerateSecretAccessKey() (string, error) { + return GenerateRandomString(SecretAccessKeyLength, Charset) +} + +// StringSlicesEqual compares two string slices for equality, ignoring order. +// This is used instead of reflect.DeepEqual to avoid order-dependent comparisons. +func StringSlicesEqual(a, b []string) bool { + if len(a) != len(b) { + return false + } + // Make copies to avoid modifying the originals + aCopy := make([]string, len(a)) + bCopy := make([]string, len(b)) + copy(aCopy, a) + copy(bCopy, b) + sort.Strings(aCopy) + sort.Strings(bCopy) + for i := range aCopy { + if aCopy[i] != bCopy[i] { + return false + } + } + return true +} + +// MapToStatementAction converts a policy statement action to an S3 action constant. +func MapToStatementAction(action string) string { + switch action { + case StatementActionAdmin: + return s3_constants.ACTION_ADMIN + case StatementActionWrite: + return s3_constants.ACTION_WRITE + case StatementActionWriteAcp: + return s3_constants.ACTION_WRITE_ACP + case StatementActionRead: + return s3_constants.ACTION_READ + case StatementActionReadAcp: + return s3_constants.ACTION_READ_ACP + case StatementActionList: + return s3_constants.ACTION_LIST + case StatementActionTagging: + return s3_constants.ACTION_TAGGING + case StatementActionDelete: + return s3_constants.ACTION_DELETE_BUCKET + default: + return "" + } +} + +// MapToIdentitiesAction converts an S3 action constant to a policy statement action. +func MapToIdentitiesAction(action string) string { + switch action { + case s3_constants.ACTION_ADMIN: + return StatementActionAdmin + case s3_constants.ACTION_WRITE: + return StatementActionWrite + case s3_constants.ACTION_WRITE_ACP: + return StatementActionWriteAcp + case s3_constants.ACTION_READ: + return StatementActionRead + case s3_constants.ACTION_READ_ACP: + return StatementActionReadAcp + case s3_constants.ACTION_LIST: + return StatementActionList + case s3_constants.ACTION_TAGGING: + return StatementActionTagging + case s3_constants.ACTION_DELETE_BUCKET: + return StatementActionDelete + default: + return "" + } +} + +// MaskAccessKey masks an access key for logging, showing only the first 4 characters. +func MaskAccessKey(accessKeyId string) string { + if len(accessKeyId) > 4 { + return accessKeyId[:4] + "***" + } + return accessKeyId +} + |
