Restrict access keys for users and groups to not allow '=' or ',' (#19749)

* initial commit

* Add UTF check

---------

Co-authored-by: Harshavardhana <harsha@minio.io>
This commit is contained in:
Taran Pelkey 2024-05-28 13:14:16 -04:00 committed by GitHub
parent e5c83535af
commit 2d53854b19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 185 additions and 142 deletions

View File

@ -29,6 +29,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"time" "time"
"unicode/utf8"
"github.com/klauspost/compress/zip" "github.com/klauspost/compress/zip"
"github.com/minio/madmin-go/v3" "github.com/minio/madmin-go/v3"
@ -474,6 +475,11 @@ func (a adminAPIHandlers) AddUser(w http.ResponseWriter, r *http.Request) {
return return
} }
if !utf8.ValidString(accessKey) {
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAddUserValidUTF), r.URL)
return
}
checkDenyOnly := false checkDenyOnly := false
if accessKey == cred.AccessKey { if accessKey == cred.AccessKey {
// Check that there is no explicit deny - otherwise it's allowed // Check that there is no explicit deny - otherwise it's allowed

View File

@ -287,6 +287,7 @@ const (
ErrAdminNoSuchGroup ErrAdminNoSuchGroup
ErrAdminGroupNotEmpty ErrAdminGroupNotEmpty
ErrAdminGroupDisabled ErrAdminGroupDisabled
ErrAdminInvalidGroupName
ErrAdminNoSuchJob ErrAdminNoSuchJob
ErrAdminNoSuchPolicy ErrAdminNoSuchPolicy
ErrAdminPolicyChangeAlreadyApplied ErrAdminPolicyChangeAlreadyApplied
@ -425,6 +426,7 @@ const (
ErrAdminProfilerNotEnabled ErrAdminProfilerNotEnabled
ErrInvalidDecompressedSize ErrInvalidDecompressedSize
ErrAddUserInvalidArgument ErrAddUserInvalidArgument
ErrAddUserValidUTF
ErrAdminResourceInvalidArgument ErrAdminResourceInvalidArgument
ErrAdminAccountNotEligible ErrAdminAccountNotEligible
ErrAccountNotEligible ErrAccountNotEligible
@ -2101,6 +2103,16 @@ var errorCodes = errorCodeMap{
Description: "Expected LDAP short username but was given full DN.", Description: "Expected LDAP short username but was given full DN.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrAdminInvalidGroupName: {
Code: "XMinioInvalidGroupName",
Description: "The group name is invalid.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrAddUserValidUTF: {
Code: "XMinioInvalidUTF",
Description: "Invalid UTF-8 character detected.",
HTTPStatusCode: http.StatusBadRequest,
},
} }
// toAPIErrorCode - Converts embedded errors. Convenience // toAPIErrorCode - Converts embedded errors. Convenience
@ -2140,6 +2152,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrAdminNoSuchGroup apiErr = ErrAdminNoSuchGroup
case errGroupNotEmpty: case errGroupNotEmpty:
apiErr = ErrAdminGroupNotEmpty apiErr = ErrAdminGroupNotEmpty
case errGroupNameContainsReservedChars:
apiErr = ErrAdminInvalidGroupName
case errNoSuchJob: case errNoSuchJob:
apiErr = ErrAdminNoSuchJob apiErr = ErrAdminNoSuchJob
case errNoPolicyToAttachOrDetach: case errNoPolicyToAttachOrDetach:
@ -2154,6 +2168,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrEntityTooSmall apiErr = ErrEntityTooSmall
case errAuthentication: case errAuthentication:
apiErr = ErrAccessDenied apiErr = ErrAccessDenied
case auth.ErrContainsReservedChars:
apiErr = ErrAdminInvalidAccessKey
case auth.ErrInvalidAccessKeyLength: case auth.ErrInvalidAccessKeyLength:
apiErr = ErrAdminInvalidAccessKey apiErr = ErrAdminInvalidAccessKey
case auth.ErrInvalidSecretKeyLength: case auth.ErrInvalidSecretKeyLength:

File diff suppressed because one or more lines are too long

View File

@ -1273,6 +1273,10 @@ func (sys *IAMSys) CreateUser(ctx context.Context, accessKey string, ureq madmin
return updatedAt, auth.ErrInvalidAccessKeyLength return updatedAt, auth.ErrInvalidAccessKeyLength
} }
if auth.ContainsReservedChars(accessKey) {
return updatedAt, auth.ErrContainsReservedChars
}
if !auth.IsSecretKeyValid(ureq.SecretKey) { if !auth.IsSecretKeyValid(ureq.SecretKey) {
return updatedAt, auth.ErrInvalidSecretKeyLength return updatedAt, auth.ErrInvalidSecretKeyLength
} }
@ -1766,6 +1770,10 @@ func (sys *IAMSys) AddUsersToGroup(ctx context.Context, group string, members []
return updatedAt, errServerNotInitialized return updatedAt, errServerNotInitialized
} }
if auth.ContainsReservedChars(group) {
return updatedAt, errGroupNameContainsReservedChars
}
updatedAt, err = sys.store.AddUsersToGroup(ctx, group, members) updatedAt, err = sys.store.AddUsersToGroup(ctx, group, members)
if err != nil { if err != nil {
return updatedAt, err return updatedAt, err

View File

@ -125,3 +125,6 @@ var errSftpPublicKeyWithoutCert = errors.New("public key authentication without
// error returned in SFTP when user used certificate which does not contain principal(s) // error returned in SFTP when user used certificate which does not contain principal(s)
var errSftpCertWithoutPrincipals = errors.New("certificates without principal(s) are not accepted") var errSftpCertWithoutPrincipals = errors.New("certificates without principal(s) are not accepted")
// error returned when group name contains reserved characters
var errGroupNameContainsReservedChars = errors.New("Group name contains reserved characters '=' or ','")

View File

@ -54,6 +54,8 @@ const (
// Total length of the alpha numeric table. // Total length of the alpha numeric table.
alphaNumericTableLen = byte(len(alphaNumericTable)) alphaNumericTableLen = byte(len(alphaNumericTable))
reservedChars = "=,"
) )
// Common errors generated for access and secret key validation. // Common errors generated for access and secret key validation.
@ -62,11 +64,17 @@ var (
ErrInvalidSecretKeyLength = fmt.Errorf("secret key length should be between %d and %d", secretKeyMinLen, secretKeyMaxLen) ErrInvalidSecretKeyLength = fmt.Errorf("secret key length should be between %d and %d", secretKeyMinLen, secretKeyMaxLen)
ErrNoAccessKeyWithSecretKey = fmt.Errorf("access key must be specified if secret key is specified") ErrNoAccessKeyWithSecretKey = fmt.Errorf("access key must be specified if secret key is specified")
ErrNoSecretKeyWithAccessKey = fmt.Errorf("secret key must be specified if access key is specified") ErrNoSecretKeyWithAccessKey = fmt.Errorf("secret key must be specified if access key is specified")
ErrContainsReservedChars = fmt.Errorf("access key contains one of reserved characters '=' or ','")
) )
// AnonymousCredentials simply points to empty credentials // AnonymousCredentials simply points to empty credentials
var AnonymousCredentials = Credentials{} var AnonymousCredentials = Credentials{}
// ContainsReservedChars - returns whether the input string contains reserved characters.
func ContainsReservedChars(s string) bool {
return strings.ContainsAny(s, reservedChars)
}
// IsAccessKeyValid - validate access key for right length. // IsAccessKeyValid - validate access key for right length.
func IsAccessKeyValid(accessKey string) bool { func IsAccessKeyValid(accessKey string) bool {
return len(accessKey) >= accessKeyMinLen return len(accessKey) >= accessKeyMinLen