diff --git a/cmd/admin-handlers-users.go b/cmd/admin-handlers-users.go index dca603469..8c0c74422 100644 --- a/cmd/admin-handlers-users.go +++ b/cmd/admin-handlers-users.go @@ -1990,6 +1990,84 @@ func (a adminAPIHandlers) AttachDetachPolicyBuiltin(w http.ResponseWriter, r *ht writeSuccessResponseJSON(w, encryptedData) } +// RevokeTokens - POST /minio/admin/v3/revoke-tokens/{userProvider} +func (a adminAPIHandlers) RevokeTokens(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + // Get current object layer instance. + objectAPI := newObjectLayerFn() + if objectAPI == nil || globalNotificationSys == nil { + writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) + return + } + + cred, owner, s3Err := validateAdminSignature(ctx, r, "") + if s3Err != ErrNone { + writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) + return + } + + userProvider := mux.Vars(r)["userProvider"] + + user := r.Form.Get("user") + tokenRevokeType := r.Form.Get("tokenRevokeType") + fullRevoke := r.Form.Get("fullRevoke") == "true" + isTokenSelfRevoke := user == "" + if !isTokenSelfRevoke { + var err error + user, err = getUserWithProvider(ctx, userProvider, user, false) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + } + + if (user != "" && tokenRevokeType == "" && !fullRevoke) || (tokenRevokeType != "" && fullRevoke) { + writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) + return + } + + adminPrivilege := globalIAMSys.IsAllowed(policy.Args{ + AccountName: cred.AccessKey, + Groups: cred.Groups, + Action: policy.RemoveServiceAccountAdminAction, + ConditionValues: getConditionValues(r, "", cred), + IsOwner: owner, + Claims: cred.Claims, + }) + + if !adminPrivilege || isTokenSelfRevoke { + parentUser := cred.AccessKey + if cred.ParentUser != "" { + parentUser = cred.ParentUser + } + if !isTokenSelfRevoke && user != parentUser { + writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) + return + } + user = parentUser + } + + // Infer token revoke type from the request if requestor is STS. + if isTokenSelfRevoke && tokenRevokeType == "" && !fullRevoke { + if cred.IsTemp() { + tokenRevokeType, _ = cred.Claims[tokenRevokeTypeClaim].(string) + } + if tokenRevokeType == "" { + writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNoTokenRevokeType), r.URL) + return + } + } + + err := globalIAMSys.RevokeTokens(ctx, user, tokenRevokeType) + if err != nil { + writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) + return + } + + writeSuccessNoContent(w) +} + const ( allPoliciesFile = "policies.json" allUsersFile = "users.json" diff --git a/cmd/admin-router.go b/cmd/admin-router.go index f48a027d5..4e5ac8dba 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -424,6 +424,9 @@ func registerAdminRouter(router *mux.Router, enableConfigOps bool) { // -- Health API -- adminRouter.Methods(http.MethodGet).Path(adminVersion + "/healthinfo"). HandlerFunc(adminMiddleware(adminAPI.HealthInfoHandler)) + + // STS Revocation + adminRouter.Methods(http.MethodPost).Path(adminVersion + "/revoke-tokens/{userProvider}").HandlerFunc(adminMiddleware(adminAPI.RevokeTokens)) } // If none of the routes match add default error handler routes diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 13b135dad..bc108814a 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -214,6 +214,7 @@ const ( ErrPolicyNotAttached ErrExcessData ErrPolicyInvalidName + ErrNoTokenRevokeType // Add new error codes here. // SSE-S3/SSE-KMS related API errors @@ -1264,6 +1265,11 @@ var errorCodes = errorCodeMap{ Description: "The security token included in the request is invalid", HTTPStatusCode: http.StatusForbidden, }, + ErrNoTokenRevokeType: { + Code: "InvalidArgument", + Description: "No token revoke type specified and one could not be inferred from the request", + HTTPStatusCode: http.StatusBadRequest, + }, // S3 extensions. ErrContentSHA256Mismatch: { diff --git a/cmd/apierrorcode_string.go b/cmd/apierrorcode_string.go index 41b7382b2..2953a8616 100644 --- a/cmd/apierrorcode_string.go +++ b/cmd/apierrorcode_string.go @@ -140,208 +140,209 @@ func _() { _ = x[ErrPolicyNotAttached-129] _ = x[ErrExcessData-130] _ = x[ErrPolicyInvalidName-131] - _ = x[ErrInvalidEncryptionMethod-132] - _ = x[ErrInvalidEncryptionKeyID-133] - _ = x[ErrInsecureSSECustomerRequest-134] - _ = x[ErrSSEMultipartEncrypted-135] - _ = x[ErrSSEEncryptedObject-136] - _ = x[ErrInvalidEncryptionParameters-137] - _ = x[ErrInvalidEncryptionParametersSSEC-138] - _ = x[ErrInvalidSSECustomerAlgorithm-139] - _ = x[ErrInvalidSSECustomerKey-140] - _ = x[ErrMissingSSECustomerKey-141] - _ = x[ErrMissingSSECustomerKeyMD5-142] - _ = x[ErrSSECustomerKeyMD5Mismatch-143] - _ = x[ErrInvalidSSECustomerParameters-144] - _ = x[ErrIncompatibleEncryptionMethod-145] - _ = x[ErrKMSNotConfigured-146] - _ = x[ErrKMSKeyNotFoundException-147] - _ = x[ErrKMSDefaultKeyAlreadyConfigured-148] - _ = x[ErrNoAccessKey-149] - _ = x[ErrInvalidToken-150] - _ = x[ErrEventNotification-151] - _ = x[ErrARNNotification-152] - _ = x[ErrRegionNotification-153] - _ = x[ErrOverlappingFilterNotification-154] - _ = x[ErrFilterNameInvalid-155] - _ = x[ErrFilterNamePrefix-156] - _ = x[ErrFilterNameSuffix-157] - _ = x[ErrFilterValueInvalid-158] - _ = x[ErrOverlappingConfigs-159] - _ = x[ErrUnsupportedNotification-160] - _ = x[ErrContentSHA256Mismatch-161] - _ = x[ErrContentChecksumMismatch-162] - _ = x[ErrStorageFull-163] - _ = x[ErrRequestBodyParse-164] - _ = x[ErrObjectExistsAsDirectory-165] - _ = x[ErrInvalidObjectName-166] - _ = x[ErrInvalidObjectNamePrefixSlash-167] - _ = x[ErrInvalidResourceName-168] - _ = x[ErrInvalidLifecycleQueryParameter-169] - _ = x[ErrServerNotInitialized-170] - _ = x[ErrBucketMetadataNotInitialized-171] - _ = x[ErrRequestTimedout-172] - _ = x[ErrClientDisconnected-173] - _ = x[ErrTooManyRequests-174] - _ = x[ErrInvalidRequest-175] - _ = x[ErrTransitionStorageClassNotFoundError-176] - _ = x[ErrInvalidStorageClass-177] - _ = x[ErrBackendDown-178] - _ = x[ErrMalformedJSON-179] - _ = x[ErrAdminNoSuchUser-180] - _ = x[ErrAdminNoSuchUserLDAPWarn-181] - _ = x[ErrAdminLDAPExpectedLoginName-182] - _ = x[ErrAdminNoSuchGroup-183] - _ = x[ErrAdminGroupNotEmpty-184] - _ = x[ErrAdminGroupDisabled-185] - _ = x[ErrAdminInvalidGroupName-186] - _ = x[ErrAdminNoSuchJob-187] - _ = x[ErrAdminNoSuchPolicy-188] - _ = x[ErrAdminPolicyChangeAlreadyApplied-189] - _ = x[ErrAdminInvalidArgument-190] - _ = x[ErrAdminInvalidAccessKey-191] - _ = x[ErrAdminInvalidSecretKey-192] - _ = x[ErrAdminConfigNoQuorum-193] - _ = x[ErrAdminConfigTooLarge-194] - _ = x[ErrAdminConfigBadJSON-195] - _ = x[ErrAdminNoSuchConfigTarget-196] - _ = x[ErrAdminConfigEnvOverridden-197] - _ = x[ErrAdminConfigDuplicateKeys-198] - _ = x[ErrAdminConfigInvalidIDPType-199] - _ = x[ErrAdminConfigLDAPNonDefaultConfigName-200] - _ = x[ErrAdminConfigLDAPValidation-201] - _ = x[ErrAdminConfigIDPCfgNameAlreadyExists-202] - _ = x[ErrAdminConfigIDPCfgNameDoesNotExist-203] - _ = x[ErrInsecureClientRequest-204] - _ = x[ErrObjectTampered-205] - _ = x[ErrAdminLDAPNotEnabled-206] - _ = x[ErrSiteReplicationInvalidRequest-207] - _ = x[ErrSiteReplicationPeerResp-208] - _ = x[ErrSiteReplicationBackendIssue-209] - _ = x[ErrSiteReplicationServiceAccountError-210] - _ = x[ErrSiteReplicationBucketConfigError-211] - _ = x[ErrSiteReplicationBucketMetaError-212] - _ = x[ErrSiteReplicationIAMError-213] - _ = x[ErrSiteReplicationConfigMissing-214] - _ = x[ErrSiteReplicationIAMConfigMismatch-215] - _ = x[ErrAdminRebalanceAlreadyStarted-216] - _ = x[ErrAdminRebalanceNotStarted-217] - _ = x[ErrAdminBucketQuotaExceeded-218] - _ = x[ErrAdminNoSuchQuotaConfiguration-219] - _ = x[ErrHealNotImplemented-220] - _ = x[ErrHealNoSuchProcess-221] - _ = x[ErrHealInvalidClientToken-222] - _ = x[ErrHealMissingBucket-223] - _ = x[ErrHealAlreadyRunning-224] - _ = x[ErrHealOverlappingPaths-225] - _ = x[ErrIncorrectContinuationToken-226] - _ = x[ErrEmptyRequestBody-227] - _ = x[ErrUnsupportedFunction-228] - _ = x[ErrInvalidExpressionType-229] - _ = x[ErrBusy-230] - _ = x[ErrUnauthorizedAccess-231] - _ = x[ErrExpressionTooLong-232] - _ = x[ErrIllegalSQLFunctionArgument-233] - _ = x[ErrInvalidKeyPath-234] - _ = x[ErrInvalidCompressionFormat-235] - _ = x[ErrInvalidFileHeaderInfo-236] - _ = x[ErrInvalidJSONType-237] - _ = x[ErrInvalidQuoteFields-238] - _ = x[ErrInvalidRequestParameter-239] - _ = x[ErrInvalidDataType-240] - _ = x[ErrInvalidTextEncoding-241] - _ = x[ErrInvalidDataSource-242] - _ = x[ErrInvalidTableAlias-243] - _ = x[ErrMissingRequiredParameter-244] - _ = x[ErrObjectSerializationConflict-245] - _ = x[ErrUnsupportedSQLOperation-246] - _ = x[ErrUnsupportedSQLStructure-247] - _ = x[ErrUnsupportedSyntax-248] - _ = x[ErrUnsupportedRangeHeader-249] - _ = x[ErrLexerInvalidChar-250] - _ = x[ErrLexerInvalidOperator-251] - _ = x[ErrLexerInvalidLiteral-252] - _ = x[ErrLexerInvalidIONLiteral-253] - _ = x[ErrParseExpectedDatePart-254] - _ = x[ErrParseExpectedKeyword-255] - _ = x[ErrParseExpectedTokenType-256] - _ = x[ErrParseExpected2TokenTypes-257] - _ = x[ErrParseExpectedNumber-258] - _ = x[ErrParseExpectedRightParenBuiltinFunctionCall-259] - _ = x[ErrParseExpectedTypeName-260] - _ = x[ErrParseExpectedWhenClause-261] - _ = x[ErrParseUnsupportedToken-262] - _ = x[ErrParseUnsupportedLiteralsGroupBy-263] - _ = x[ErrParseExpectedMember-264] - _ = x[ErrParseUnsupportedSelect-265] - _ = x[ErrParseUnsupportedCase-266] - _ = x[ErrParseUnsupportedCaseClause-267] - _ = x[ErrParseUnsupportedAlias-268] - _ = x[ErrParseUnsupportedSyntax-269] - _ = x[ErrParseUnknownOperator-270] - _ = x[ErrParseMissingIdentAfterAt-271] - _ = x[ErrParseUnexpectedOperator-272] - _ = x[ErrParseUnexpectedTerm-273] - _ = x[ErrParseUnexpectedToken-274] - _ = x[ErrParseUnexpectedKeyword-275] - _ = x[ErrParseExpectedExpression-276] - _ = x[ErrParseExpectedLeftParenAfterCast-277] - _ = x[ErrParseExpectedLeftParenValueConstructor-278] - _ = x[ErrParseExpectedLeftParenBuiltinFunctionCall-279] - _ = x[ErrParseExpectedArgumentDelimiter-280] - _ = x[ErrParseCastArity-281] - _ = x[ErrParseInvalidTypeParam-282] - _ = x[ErrParseEmptySelect-283] - _ = x[ErrParseSelectMissingFrom-284] - _ = x[ErrParseExpectedIdentForGroupName-285] - _ = x[ErrParseExpectedIdentForAlias-286] - _ = x[ErrParseUnsupportedCallWithStar-287] - _ = x[ErrParseNonUnaryAggregateFunctionCall-288] - _ = x[ErrParseMalformedJoin-289] - _ = x[ErrParseExpectedIdentForAt-290] - _ = x[ErrParseAsteriskIsNotAloneInSelectList-291] - _ = x[ErrParseCannotMixSqbAndWildcardInSelectList-292] - _ = x[ErrParseInvalidContextForWildcardInSelectList-293] - _ = x[ErrIncorrectSQLFunctionArgumentType-294] - _ = x[ErrValueParseFailure-295] - _ = x[ErrEvaluatorInvalidArguments-296] - _ = x[ErrIntegerOverflow-297] - _ = x[ErrLikeInvalidInputs-298] - _ = x[ErrCastFailed-299] - _ = x[ErrInvalidCast-300] - _ = x[ErrEvaluatorInvalidTimestampFormatPattern-301] - _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbolForParsing-302] - _ = x[ErrEvaluatorTimestampFormatPatternDuplicateFields-303] - _ = x[ErrEvaluatorTimestampFormatPatternHourClockAmPmMismatch-304] - _ = x[ErrEvaluatorUnterminatedTimestampFormatPatternToken-305] - _ = x[ErrEvaluatorInvalidTimestampFormatPatternToken-306] - _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbol-307] - _ = x[ErrEvaluatorBindingDoesNotExist-308] - _ = x[ErrMissingHeaders-309] - _ = x[ErrInvalidColumnIndex-310] - _ = x[ErrAdminConfigNotificationTargetsFailed-311] - _ = x[ErrAdminProfilerNotEnabled-312] - _ = x[ErrInvalidDecompressedSize-313] - _ = x[ErrAddUserInvalidArgument-314] - _ = x[ErrAddUserValidUTF-315] - _ = x[ErrAdminResourceInvalidArgument-316] - _ = x[ErrAdminAccountNotEligible-317] - _ = x[ErrAccountNotEligible-318] - _ = x[ErrAdminServiceAccountNotFound-319] - _ = x[ErrPostPolicyConditionInvalidFormat-320] - _ = x[ErrInvalidChecksum-321] - _ = x[ErrLambdaARNInvalid-322] - _ = x[ErrLambdaARNNotFound-323] - _ = x[ErrInvalidAttributeName-324] - _ = x[ErrAdminNoAccessKey-325] - _ = x[ErrAdminNoSecretKey-326] - _ = x[ErrIAMNotInitialized-327] - _ = x[apiErrCodeEnd-328] + _ = x[ErrNoTokenRevokeType-132] + _ = x[ErrInvalidEncryptionMethod-133] + _ = x[ErrInvalidEncryptionKeyID-134] + _ = x[ErrInsecureSSECustomerRequest-135] + _ = x[ErrSSEMultipartEncrypted-136] + _ = x[ErrSSEEncryptedObject-137] + _ = x[ErrInvalidEncryptionParameters-138] + _ = x[ErrInvalidEncryptionParametersSSEC-139] + _ = x[ErrInvalidSSECustomerAlgorithm-140] + _ = x[ErrInvalidSSECustomerKey-141] + _ = x[ErrMissingSSECustomerKey-142] + _ = x[ErrMissingSSECustomerKeyMD5-143] + _ = x[ErrSSECustomerKeyMD5Mismatch-144] + _ = x[ErrInvalidSSECustomerParameters-145] + _ = x[ErrIncompatibleEncryptionMethod-146] + _ = x[ErrKMSNotConfigured-147] + _ = x[ErrKMSKeyNotFoundException-148] + _ = x[ErrKMSDefaultKeyAlreadyConfigured-149] + _ = x[ErrNoAccessKey-150] + _ = x[ErrInvalidToken-151] + _ = x[ErrEventNotification-152] + _ = x[ErrARNNotification-153] + _ = x[ErrRegionNotification-154] + _ = x[ErrOverlappingFilterNotification-155] + _ = x[ErrFilterNameInvalid-156] + _ = x[ErrFilterNamePrefix-157] + _ = x[ErrFilterNameSuffix-158] + _ = x[ErrFilterValueInvalid-159] + _ = x[ErrOverlappingConfigs-160] + _ = x[ErrUnsupportedNotification-161] + _ = x[ErrContentSHA256Mismatch-162] + _ = x[ErrContentChecksumMismatch-163] + _ = x[ErrStorageFull-164] + _ = x[ErrRequestBodyParse-165] + _ = x[ErrObjectExistsAsDirectory-166] + _ = x[ErrInvalidObjectName-167] + _ = x[ErrInvalidObjectNamePrefixSlash-168] + _ = x[ErrInvalidResourceName-169] + _ = x[ErrInvalidLifecycleQueryParameter-170] + _ = x[ErrServerNotInitialized-171] + _ = x[ErrBucketMetadataNotInitialized-172] + _ = x[ErrRequestTimedout-173] + _ = x[ErrClientDisconnected-174] + _ = x[ErrTooManyRequests-175] + _ = x[ErrInvalidRequest-176] + _ = x[ErrTransitionStorageClassNotFoundError-177] + _ = x[ErrInvalidStorageClass-178] + _ = x[ErrBackendDown-179] + _ = x[ErrMalformedJSON-180] + _ = x[ErrAdminNoSuchUser-181] + _ = x[ErrAdminNoSuchUserLDAPWarn-182] + _ = x[ErrAdminLDAPExpectedLoginName-183] + _ = x[ErrAdminNoSuchGroup-184] + _ = x[ErrAdminGroupNotEmpty-185] + _ = x[ErrAdminGroupDisabled-186] + _ = x[ErrAdminInvalidGroupName-187] + _ = x[ErrAdminNoSuchJob-188] + _ = x[ErrAdminNoSuchPolicy-189] + _ = x[ErrAdminPolicyChangeAlreadyApplied-190] + _ = x[ErrAdminInvalidArgument-191] + _ = x[ErrAdminInvalidAccessKey-192] + _ = x[ErrAdminInvalidSecretKey-193] + _ = x[ErrAdminConfigNoQuorum-194] + _ = x[ErrAdminConfigTooLarge-195] + _ = x[ErrAdminConfigBadJSON-196] + _ = x[ErrAdminNoSuchConfigTarget-197] + _ = x[ErrAdminConfigEnvOverridden-198] + _ = x[ErrAdminConfigDuplicateKeys-199] + _ = x[ErrAdminConfigInvalidIDPType-200] + _ = x[ErrAdminConfigLDAPNonDefaultConfigName-201] + _ = x[ErrAdminConfigLDAPValidation-202] + _ = x[ErrAdminConfigIDPCfgNameAlreadyExists-203] + _ = x[ErrAdminConfigIDPCfgNameDoesNotExist-204] + _ = x[ErrInsecureClientRequest-205] + _ = x[ErrObjectTampered-206] + _ = x[ErrAdminLDAPNotEnabled-207] + _ = x[ErrSiteReplicationInvalidRequest-208] + _ = x[ErrSiteReplicationPeerResp-209] + _ = x[ErrSiteReplicationBackendIssue-210] + _ = x[ErrSiteReplicationServiceAccountError-211] + _ = x[ErrSiteReplicationBucketConfigError-212] + _ = x[ErrSiteReplicationBucketMetaError-213] + _ = x[ErrSiteReplicationIAMError-214] + _ = x[ErrSiteReplicationConfigMissing-215] + _ = x[ErrSiteReplicationIAMConfigMismatch-216] + _ = x[ErrAdminRebalanceAlreadyStarted-217] + _ = x[ErrAdminRebalanceNotStarted-218] + _ = x[ErrAdminBucketQuotaExceeded-219] + _ = x[ErrAdminNoSuchQuotaConfiguration-220] + _ = x[ErrHealNotImplemented-221] + _ = x[ErrHealNoSuchProcess-222] + _ = x[ErrHealInvalidClientToken-223] + _ = x[ErrHealMissingBucket-224] + _ = x[ErrHealAlreadyRunning-225] + _ = x[ErrHealOverlappingPaths-226] + _ = x[ErrIncorrectContinuationToken-227] + _ = x[ErrEmptyRequestBody-228] + _ = x[ErrUnsupportedFunction-229] + _ = x[ErrInvalidExpressionType-230] + _ = x[ErrBusy-231] + _ = x[ErrUnauthorizedAccess-232] + _ = x[ErrExpressionTooLong-233] + _ = x[ErrIllegalSQLFunctionArgument-234] + _ = x[ErrInvalidKeyPath-235] + _ = x[ErrInvalidCompressionFormat-236] + _ = x[ErrInvalidFileHeaderInfo-237] + _ = x[ErrInvalidJSONType-238] + _ = x[ErrInvalidQuoteFields-239] + _ = x[ErrInvalidRequestParameter-240] + _ = x[ErrInvalidDataType-241] + _ = x[ErrInvalidTextEncoding-242] + _ = x[ErrInvalidDataSource-243] + _ = x[ErrInvalidTableAlias-244] + _ = x[ErrMissingRequiredParameter-245] + _ = x[ErrObjectSerializationConflict-246] + _ = x[ErrUnsupportedSQLOperation-247] + _ = x[ErrUnsupportedSQLStructure-248] + _ = x[ErrUnsupportedSyntax-249] + _ = x[ErrUnsupportedRangeHeader-250] + _ = x[ErrLexerInvalidChar-251] + _ = x[ErrLexerInvalidOperator-252] + _ = x[ErrLexerInvalidLiteral-253] + _ = x[ErrLexerInvalidIONLiteral-254] + _ = x[ErrParseExpectedDatePart-255] + _ = x[ErrParseExpectedKeyword-256] + _ = x[ErrParseExpectedTokenType-257] + _ = x[ErrParseExpected2TokenTypes-258] + _ = x[ErrParseExpectedNumber-259] + _ = x[ErrParseExpectedRightParenBuiltinFunctionCall-260] + _ = x[ErrParseExpectedTypeName-261] + _ = x[ErrParseExpectedWhenClause-262] + _ = x[ErrParseUnsupportedToken-263] + _ = x[ErrParseUnsupportedLiteralsGroupBy-264] + _ = x[ErrParseExpectedMember-265] + _ = x[ErrParseUnsupportedSelect-266] + _ = x[ErrParseUnsupportedCase-267] + _ = x[ErrParseUnsupportedCaseClause-268] + _ = x[ErrParseUnsupportedAlias-269] + _ = x[ErrParseUnsupportedSyntax-270] + _ = x[ErrParseUnknownOperator-271] + _ = x[ErrParseMissingIdentAfterAt-272] + _ = x[ErrParseUnexpectedOperator-273] + _ = x[ErrParseUnexpectedTerm-274] + _ = x[ErrParseUnexpectedToken-275] + _ = x[ErrParseUnexpectedKeyword-276] + _ = x[ErrParseExpectedExpression-277] + _ = x[ErrParseExpectedLeftParenAfterCast-278] + _ = x[ErrParseExpectedLeftParenValueConstructor-279] + _ = x[ErrParseExpectedLeftParenBuiltinFunctionCall-280] + _ = x[ErrParseExpectedArgumentDelimiter-281] + _ = x[ErrParseCastArity-282] + _ = x[ErrParseInvalidTypeParam-283] + _ = x[ErrParseEmptySelect-284] + _ = x[ErrParseSelectMissingFrom-285] + _ = x[ErrParseExpectedIdentForGroupName-286] + _ = x[ErrParseExpectedIdentForAlias-287] + _ = x[ErrParseUnsupportedCallWithStar-288] + _ = x[ErrParseNonUnaryAggregateFunctionCall-289] + _ = x[ErrParseMalformedJoin-290] + _ = x[ErrParseExpectedIdentForAt-291] + _ = x[ErrParseAsteriskIsNotAloneInSelectList-292] + _ = x[ErrParseCannotMixSqbAndWildcardInSelectList-293] + _ = x[ErrParseInvalidContextForWildcardInSelectList-294] + _ = x[ErrIncorrectSQLFunctionArgumentType-295] + _ = x[ErrValueParseFailure-296] + _ = x[ErrEvaluatorInvalidArguments-297] + _ = x[ErrIntegerOverflow-298] + _ = x[ErrLikeInvalidInputs-299] + _ = x[ErrCastFailed-300] + _ = x[ErrInvalidCast-301] + _ = x[ErrEvaluatorInvalidTimestampFormatPattern-302] + _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbolForParsing-303] + _ = x[ErrEvaluatorTimestampFormatPatternDuplicateFields-304] + _ = x[ErrEvaluatorTimestampFormatPatternHourClockAmPmMismatch-305] + _ = x[ErrEvaluatorUnterminatedTimestampFormatPatternToken-306] + _ = x[ErrEvaluatorInvalidTimestampFormatPatternToken-307] + _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbol-308] + _ = x[ErrEvaluatorBindingDoesNotExist-309] + _ = x[ErrMissingHeaders-310] + _ = x[ErrInvalidColumnIndex-311] + _ = x[ErrAdminConfigNotificationTargetsFailed-312] + _ = x[ErrAdminProfilerNotEnabled-313] + _ = x[ErrInvalidDecompressedSize-314] + _ = x[ErrAddUserInvalidArgument-315] + _ = x[ErrAddUserValidUTF-316] + _ = x[ErrAdminResourceInvalidArgument-317] + _ = x[ErrAdminAccountNotEligible-318] + _ = x[ErrAccountNotEligible-319] + _ = x[ErrAdminServiceAccountNotFound-320] + _ = x[ErrPostPolicyConditionInvalidFormat-321] + _ = x[ErrInvalidChecksum-322] + _ = x[ErrLambdaARNInvalid-323] + _ = x[ErrLambdaARNNotFound-324] + _ = x[ErrInvalidAttributeName-325] + _ = x[ErrAdminNoAccessKey-326] + _ = x[ErrAdminNoSecretKey-327] + _ = x[ErrIAMNotInitialized-328] + _ = x[apiErrCodeEnd-329] } -const _APIErrorCode_name = "NoneAccessDeniedBadDigestEntityTooSmallEntityTooLargePolicyTooLargeIncompleteBodyInternalErrorInvalidAccessKeyIDAccessKeyDisabledInvalidArgumentInvalidBucketNameInvalidDigestInvalidRangeInvalidRangePartNumberInvalidCopyPartRangeInvalidCopyPartRangeSourceInvalidMaxKeysInvalidEncodingMethodInvalidMaxUploadsInvalidMaxPartsInvalidPartNumberMarkerInvalidPartNumberInvalidRequestBodyInvalidCopySourceInvalidMetadataDirectiveInvalidCopyDestInvalidPolicyDocumentInvalidObjectStateMalformedXMLMissingContentLengthMissingContentMD5MissingRequestBodyErrorMissingSecurityHeaderNoSuchBucketNoSuchBucketPolicyNoSuchBucketLifecycleNoSuchLifecycleConfigurationInvalidLifecycleWithObjectLockNoSuchBucketSSEConfigNoSuchCORSConfigurationNoSuchWebsiteConfigurationReplicationConfigurationNotFoundErrorRemoteDestinationNotFoundErrorReplicationDestinationMissingLockRemoteTargetNotFoundErrorReplicationRemoteConnectionErrorReplicationBandwidthLimitErrorBucketRemoteIdenticalToSourceBucketRemoteAlreadyExistsBucketRemoteLabelInUseBucketRemoteArnTypeInvalidBucketRemoteArnInvalidBucketRemoteRemoveDisallowedRemoteTargetNotVersionedErrorReplicationSourceNotVersionedErrorReplicationNeedsVersioningErrorReplicationBucketNeedsVersioningErrorReplicationDenyEditErrorRemoteTargetDenyAddErrorReplicationNoExistingObjectsReplicationValidationErrorReplicationPermissionCheckErrorObjectRestoreAlreadyInProgressNoSuchKeyNoSuchUploadInvalidVersionIDNoSuchVersionNotImplementedPreconditionFailedRequestTimeTooSkewedSignatureDoesNotMatchMethodNotAllowedInvalidPartInvalidPartOrderMissingPartAuthorizationHeaderMalformedMalformedPOSTRequestPOSTFileRequiredSignatureVersionNotSupportedBucketNotEmptyAllAccessDisabledPolicyInvalidVersionMissingFieldsMissingCredTagCredMalformedInvalidRegionInvalidServiceS3InvalidServiceSTSInvalidRequestVersionMissingSignTagMissingSignHeadersTagMalformedDateMalformedPresignedDateMalformedCredentialDateMalformedExpiresNegativeExpiresAuthHeaderEmptyExpiredPresignRequestRequestNotReadyYetUnsignedHeadersMissingDateHeaderInvalidQuerySignatureAlgoInvalidQueryParamsBucketAlreadyOwnedByYouInvalidDurationBucketAlreadyExistsMetadataTooLargeUnsupportedMetadataUnsupportedHostHeaderMaximumExpiresSlowDownReadSlowDownWriteMaxVersionsExceededInvalidPrefixMarkerBadRequestKeyTooLongErrorInvalidBucketObjectLockConfigurationObjectLockConfigurationNotFoundObjectLockConfigurationNotAllowedNoSuchObjectLockConfigurationObjectLockedInvalidRetentionDatePastObjectLockRetainDateUnknownWORMModeDirectiveBucketTaggingNotFoundObjectLockInvalidHeadersInvalidTagDirectivePolicyAlreadyAttachedPolicyNotAttachedExcessDataPolicyInvalidNameInvalidEncryptionMethodInvalidEncryptionKeyIDInsecureSSECustomerRequestSSEMultipartEncryptedSSEEncryptedObjectInvalidEncryptionParametersInvalidEncryptionParametersSSECInvalidSSECustomerAlgorithmInvalidSSECustomerKeyMissingSSECustomerKeyMissingSSECustomerKeyMD5SSECustomerKeyMD5MismatchInvalidSSECustomerParametersIncompatibleEncryptionMethodKMSNotConfiguredKMSKeyNotFoundExceptionKMSDefaultKeyAlreadyConfiguredNoAccessKeyInvalidTokenEventNotificationARNNotificationRegionNotificationOverlappingFilterNotificationFilterNameInvalidFilterNamePrefixFilterNameSuffixFilterValueInvalidOverlappingConfigsUnsupportedNotificationContentSHA256MismatchContentChecksumMismatchStorageFullRequestBodyParseObjectExistsAsDirectoryInvalidObjectNameInvalidObjectNamePrefixSlashInvalidResourceNameInvalidLifecycleQueryParameterServerNotInitializedBucketMetadataNotInitializedRequestTimedoutClientDisconnectedTooManyRequestsInvalidRequestTransitionStorageClassNotFoundErrorInvalidStorageClassBackendDownMalformedJSONAdminNoSuchUserAdminNoSuchUserLDAPWarnAdminLDAPExpectedLoginNameAdminNoSuchGroupAdminGroupNotEmptyAdminGroupDisabledAdminInvalidGroupNameAdminNoSuchJobAdminNoSuchPolicyAdminPolicyChangeAlreadyAppliedAdminInvalidArgumentAdminInvalidAccessKeyAdminInvalidSecretKeyAdminConfigNoQuorumAdminConfigTooLargeAdminConfigBadJSONAdminNoSuchConfigTargetAdminConfigEnvOverriddenAdminConfigDuplicateKeysAdminConfigInvalidIDPTypeAdminConfigLDAPNonDefaultConfigNameAdminConfigLDAPValidationAdminConfigIDPCfgNameAlreadyExistsAdminConfigIDPCfgNameDoesNotExistInsecureClientRequestObjectTamperedAdminLDAPNotEnabledSiteReplicationInvalidRequestSiteReplicationPeerRespSiteReplicationBackendIssueSiteReplicationServiceAccountErrorSiteReplicationBucketConfigErrorSiteReplicationBucketMetaErrorSiteReplicationIAMErrorSiteReplicationConfigMissingSiteReplicationIAMConfigMismatchAdminRebalanceAlreadyStartedAdminRebalanceNotStartedAdminBucketQuotaExceededAdminNoSuchQuotaConfigurationHealNotImplementedHealNoSuchProcessHealInvalidClientTokenHealMissingBucketHealAlreadyRunningHealOverlappingPathsIncorrectContinuationTokenEmptyRequestBodyUnsupportedFunctionInvalidExpressionTypeBusyUnauthorizedAccessExpressionTooLongIllegalSQLFunctionArgumentInvalidKeyPathInvalidCompressionFormatInvalidFileHeaderInfoInvalidJSONTypeInvalidQuoteFieldsInvalidRequestParameterInvalidDataTypeInvalidTextEncodingInvalidDataSourceInvalidTableAliasMissingRequiredParameterObjectSerializationConflictUnsupportedSQLOperationUnsupportedSQLStructureUnsupportedSyntaxUnsupportedRangeHeaderLexerInvalidCharLexerInvalidOperatorLexerInvalidLiteralLexerInvalidIONLiteralParseExpectedDatePartParseExpectedKeywordParseExpectedTokenTypeParseExpected2TokenTypesParseExpectedNumberParseExpectedRightParenBuiltinFunctionCallParseExpectedTypeNameParseExpectedWhenClauseParseUnsupportedTokenParseUnsupportedLiteralsGroupByParseExpectedMemberParseUnsupportedSelectParseUnsupportedCaseParseUnsupportedCaseClauseParseUnsupportedAliasParseUnsupportedSyntaxParseUnknownOperatorParseMissingIdentAfterAtParseUnexpectedOperatorParseUnexpectedTermParseUnexpectedTokenParseUnexpectedKeywordParseExpectedExpressionParseExpectedLeftParenAfterCastParseExpectedLeftParenValueConstructorParseExpectedLeftParenBuiltinFunctionCallParseExpectedArgumentDelimiterParseCastArityParseInvalidTypeParamParseEmptySelectParseSelectMissingFromParseExpectedIdentForGroupNameParseExpectedIdentForAliasParseUnsupportedCallWithStarParseNonUnaryAggregateFunctionCallParseMalformedJoinParseExpectedIdentForAtParseAsteriskIsNotAloneInSelectListParseCannotMixSqbAndWildcardInSelectListParseInvalidContextForWildcardInSelectListIncorrectSQLFunctionArgumentTypeValueParseFailureEvaluatorInvalidArgumentsIntegerOverflowLikeInvalidInputsCastFailedInvalidCastEvaluatorInvalidTimestampFormatPatternEvaluatorInvalidTimestampFormatPatternSymbolForParsingEvaluatorTimestampFormatPatternDuplicateFieldsEvaluatorTimestampFormatPatternHourClockAmPmMismatchEvaluatorUnterminatedTimestampFormatPatternTokenEvaluatorInvalidTimestampFormatPatternTokenEvaluatorInvalidTimestampFormatPatternSymbolEvaluatorBindingDoesNotExistMissingHeadersInvalidColumnIndexAdminConfigNotificationTargetsFailedAdminProfilerNotEnabledInvalidDecompressedSizeAddUserInvalidArgumentAddUserValidUTFAdminResourceInvalidArgumentAdminAccountNotEligibleAccountNotEligibleAdminServiceAccountNotFoundPostPolicyConditionInvalidFormatInvalidChecksumLambdaARNInvalidLambdaARNNotFoundInvalidAttributeNameAdminNoAccessKeyAdminNoSecretKeyIAMNotInitializedapiErrCodeEnd" +const _APIErrorCode_name = "NoneAccessDeniedBadDigestEntityTooSmallEntityTooLargePolicyTooLargeIncompleteBodyInternalErrorInvalidAccessKeyIDAccessKeyDisabledInvalidArgumentInvalidBucketNameInvalidDigestInvalidRangeInvalidRangePartNumberInvalidCopyPartRangeInvalidCopyPartRangeSourceInvalidMaxKeysInvalidEncodingMethodInvalidMaxUploadsInvalidMaxPartsInvalidPartNumberMarkerInvalidPartNumberInvalidRequestBodyInvalidCopySourceInvalidMetadataDirectiveInvalidCopyDestInvalidPolicyDocumentInvalidObjectStateMalformedXMLMissingContentLengthMissingContentMD5MissingRequestBodyErrorMissingSecurityHeaderNoSuchBucketNoSuchBucketPolicyNoSuchBucketLifecycleNoSuchLifecycleConfigurationInvalidLifecycleWithObjectLockNoSuchBucketSSEConfigNoSuchCORSConfigurationNoSuchWebsiteConfigurationReplicationConfigurationNotFoundErrorRemoteDestinationNotFoundErrorReplicationDestinationMissingLockRemoteTargetNotFoundErrorReplicationRemoteConnectionErrorReplicationBandwidthLimitErrorBucketRemoteIdenticalToSourceBucketRemoteAlreadyExistsBucketRemoteLabelInUseBucketRemoteArnTypeInvalidBucketRemoteArnInvalidBucketRemoteRemoveDisallowedRemoteTargetNotVersionedErrorReplicationSourceNotVersionedErrorReplicationNeedsVersioningErrorReplicationBucketNeedsVersioningErrorReplicationDenyEditErrorRemoteTargetDenyAddErrorReplicationNoExistingObjectsReplicationValidationErrorReplicationPermissionCheckErrorObjectRestoreAlreadyInProgressNoSuchKeyNoSuchUploadInvalidVersionIDNoSuchVersionNotImplementedPreconditionFailedRequestTimeTooSkewedSignatureDoesNotMatchMethodNotAllowedInvalidPartInvalidPartOrderMissingPartAuthorizationHeaderMalformedMalformedPOSTRequestPOSTFileRequiredSignatureVersionNotSupportedBucketNotEmptyAllAccessDisabledPolicyInvalidVersionMissingFieldsMissingCredTagCredMalformedInvalidRegionInvalidServiceS3InvalidServiceSTSInvalidRequestVersionMissingSignTagMissingSignHeadersTagMalformedDateMalformedPresignedDateMalformedCredentialDateMalformedExpiresNegativeExpiresAuthHeaderEmptyExpiredPresignRequestRequestNotReadyYetUnsignedHeadersMissingDateHeaderInvalidQuerySignatureAlgoInvalidQueryParamsBucketAlreadyOwnedByYouInvalidDurationBucketAlreadyExistsMetadataTooLargeUnsupportedMetadataUnsupportedHostHeaderMaximumExpiresSlowDownReadSlowDownWriteMaxVersionsExceededInvalidPrefixMarkerBadRequestKeyTooLongErrorInvalidBucketObjectLockConfigurationObjectLockConfigurationNotFoundObjectLockConfigurationNotAllowedNoSuchObjectLockConfigurationObjectLockedInvalidRetentionDatePastObjectLockRetainDateUnknownWORMModeDirectiveBucketTaggingNotFoundObjectLockInvalidHeadersInvalidTagDirectivePolicyAlreadyAttachedPolicyNotAttachedExcessDataPolicyInvalidNameNoTokenRevokeTypeInvalidEncryptionMethodInvalidEncryptionKeyIDInsecureSSECustomerRequestSSEMultipartEncryptedSSEEncryptedObjectInvalidEncryptionParametersInvalidEncryptionParametersSSECInvalidSSECustomerAlgorithmInvalidSSECustomerKeyMissingSSECustomerKeyMissingSSECustomerKeyMD5SSECustomerKeyMD5MismatchInvalidSSECustomerParametersIncompatibleEncryptionMethodKMSNotConfiguredKMSKeyNotFoundExceptionKMSDefaultKeyAlreadyConfiguredNoAccessKeyInvalidTokenEventNotificationARNNotificationRegionNotificationOverlappingFilterNotificationFilterNameInvalidFilterNamePrefixFilterNameSuffixFilterValueInvalidOverlappingConfigsUnsupportedNotificationContentSHA256MismatchContentChecksumMismatchStorageFullRequestBodyParseObjectExistsAsDirectoryInvalidObjectNameInvalidObjectNamePrefixSlashInvalidResourceNameInvalidLifecycleQueryParameterServerNotInitializedBucketMetadataNotInitializedRequestTimedoutClientDisconnectedTooManyRequestsInvalidRequestTransitionStorageClassNotFoundErrorInvalidStorageClassBackendDownMalformedJSONAdminNoSuchUserAdminNoSuchUserLDAPWarnAdminLDAPExpectedLoginNameAdminNoSuchGroupAdminGroupNotEmptyAdminGroupDisabledAdminInvalidGroupNameAdminNoSuchJobAdminNoSuchPolicyAdminPolicyChangeAlreadyAppliedAdminInvalidArgumentAdminInvalidAccessKeyAdminInvalidSecretKeyAdminConfigNoQuorumAdminConfigTooLargeAdminConfigBadJSONAdminNoSuchConfigTargetAdminConfigEnvOverriddenAdminConfigDuplicateKeysAdminConfigInvalidIDPTypeAdminConfigLDAPNonDefaultConfigNameAdminConfigLDAPValidationAdminConfigIDPCfgNameAlreadyExistsAdminConfigIDPCfgNameDoesNotExistInsecureClientRequestObjectTamperedAdminLDAPNotEnabledSiteReplicationInvalidRequestSiteReplicationPeerRespSiteReplicationBackendIssueSiteReplicationServiceAccountErrorSiteReplicationBucketConfigErrorSiteReplicationBucketMetaErrorSiteReplicationIAMErrorSiteReplicationConfigMissingSiteReplicationIAMConfigMismatchAdminRebalanceAlreadyStartedAdminRebalanceNotStartedAdminBucketQuotaExceededAdminNoSuchQuotaConfigurationHealNotImplementedHealNoSuchProcessHealInvalidClientTokenHealMissingBucketHealAlreadyRunningHealOverlappingPathsIncorrectContinuationTokenEmptyRequestBodyUnsupportedFunctionInvalidExpressionTypeBusyUnauthorizedAccessExpressionTooLongIllegalSQLFunctionArgumentInvalidKeyPathInvalidCompressionFormatInvalidFileHeaderInfoInvalidJSONTypeInvalidQuoteFieldsInvalidRequestParameterInvalidDataTypeInvalidTextEncodingInvalidDataSourceInvalidTableAliasMissingRequiredParameterObjectSerializationConflictUnsupportedSQLOperationUnsupportedSQLStructureUnsupportedSyntaxUnsupportedRangeHeaderLexerInvalidCharLexerInvalidOperatorLexerInvalidLiteralLexerInvalidIONLiteralParseExpectedDatePartParseExpectedKeywordParseExpectedTokenTypeParseExpected2TokenTypesParseExpectedNumberParseExpectedRightParenBuiltinFunctionCallParseExpectedTypeNameParseExpectedWhenClauseParseUnsupportedTokenParseUnsupportedLiteralsGroupByParseExpectedMemberParseUnsupportedSelectParseUnsupportedCaseParseUnsupportedCaseClauseParseUnsupportedAliasParseUnsupportedSyntaxParseUnknownOperatorParseMissingIdentAfterAtParseUnexpectedOperatorParseUnexpectedTermParseUnexpectedTokenParseUnexpectedKeywordParseExpectedExpressionParseExpectedLeftParenAfterCastParseExpectedLeftParenValueConstructorParseExpectedLeftParenBuiltinFunctionCallParseExpectedArgumentDelimiterParseCastArityParseInvalidTypeParamParseEmptySelectParseSelectMissingFromParseExpectedIdentForGroupNameParseExpectedIdentForAliasParseUnsupportedCallWithStarParseNonUnaryAggregateFunctionCallParseMalformedJoinParseExpectedIdentForAtParseAsteriskIsNotAloneInSelectListParseCannotMixSqbAndWildcardInSelectListParseInvalidContextForWildcardInSelectListIncorrectSQLFunctionArgumentTypeValueParseFailureEvaluatorInvalidArgumentsIntegerOverflowLikeInvalidInputsCastFailedInvalidCastEvaluatorInvalidTimestampFormatPatternEvaluatorInvalidTimestampFormatPatternSymbolForParsingEvaluatorTimestampFormatPatternDuplicateFieldsEvaluatorTimestampFormatPatternHourClockAmPmMismatchEvaluatorUnterminatedTimestampFormatPatternTokenEvaluatorInvalidTimestampFormatPatternTokenEvaluatorInvalidTimestampFormatPatternSymbolEvaluatorBindingDoesNotExistMissingHeadersInvalidColumnIndexAdminConfigNotificationTargetsFailedAdminProfilerNotEnabledInvalidDecompressedSizeAddUserInvalidArgumentAddUserValidUTFAdminResourceInvalidArgumentAdminAccountNotEligibleAccountNotEligibleAdminServiceAccountNotFoundPostPolicyConditionInvalidFormatInvalidChecksumLambdaARNInvalidLambdaARNNotFoundInvalidAttributeNameAdminNoAccessKeyAdminNoSecretKeyIAMNotInitializedapiErrCodeEnd" -var _APIErrorCode_index = [...]uint16{0, 4, 16, 25, 39, 53, 67, 81, 94, 112, 129, 144, 161, 174, 186, 208, 228, 254, 268, 289, 306, 321, 344, 361, 379, 396, 420, 435, 456, 474, 486, 506, 523, 546, 567, 579, 597, 618, 646, 676, 697, 720, 746, 783, 813, 846, 871, 903, 933, 962, 987, 1009, 1035, 1057, 1085, 1114, 1148, 1179, 1216, 1240, 1264, 1292, 1318, 1349, 1379, 1388, 1400, 1416, 1429, 1443, 1461, 1481, 1502, 1518, 1529, 1545, 1556, 1584, 1604, 1620, 1648, 1662, 1679, 1699, 1712, 1726, 1739, 1752, 1768, 1785, 1806, 1820, 1841, 1854, 1876, 1899, 1915, 1930, 1945, 1966, 1984, 1999, 2016, 2041, 2059, 2082, 2097, 2116, 2132, 2151, 2172, 2186, 2198, 2211, 2230, 2249, 2259, 2274, 2310, 2341, 2374, 2403, 2415, 2435, 2459, 2483, 2504, 2528, 2547, 2568, 2585, 2595, 2612, 2635, 2657, 2683, 2704, 2722, 2749, 2780, 2807, 2828, 2849, 2873, 2898, 2926, 2954, 2970, 2993, 3023, 3034, 3046, 3063, 3078, 3096, 3125, 3142, 3158, 3174, 3192, 3210, 3233, 3254, 3277, 3288, 3304, 3327, 3344, 3372, 3391, 3421, 3441, 3469, 3484, 3502, 3517, 3531, 3566, 3585, 3596, 3609, 3624, 3647, 3673, 3689, 3707, 3725, 3746, 3760, 3777, 3808, 3828, 3849, 3870, 3889, 3908, 3926, 3949, 3973, 3997, 4022, 4057, 4082, 4116, 4149, 4170, 4184, 4203, 4232, 4255, 4282, 4316, 4348, 4378, 4401, 4429, 4461, 4489, 4513, 4537, 4566, 4584, 4601, 4623, 4640, 4658, 4678, 4704, 4720, 4739, 4760, 4764, 4782, 4799, 4825, 4839, 4863, 4884, 4899, 4917, 4940, 4955, 4974, 4991, 5008, 5032, 5059, 5082, 5105, 5122, 5144, 5160, 5180, 5199, 5221, 5242, 5262, 5284, 5308, 5327, 5369, 5390, 5413, 5434, 5465, 5484, 5506, 5526, 5552, 5573, 5595, 5615, 5639, 5662, 5681, 5701, 5723, 5746, 5777, 5815, 5856, 5886, 5900, 5921, 5937, 5959, 5989, 6015, 6043, 6077, 6095, 6118, 6153, 6193, 6235, 6267, 6284, 6309, 6324, 6341, 6351, 6362, 6400, 6454, 6500, 6552, 6600, 6643, 6687, 6715, 6729, 6747, 6783, 6806, 6829, 6851, 6866, 6894, 6917, 6935, 6962, 6994, 7009, 7025, 7042, 7062, 7078, 7094, 7111, 7124} +var _APIErrorCode_index = [...]uint16{0, 4, 16, 25, 39, 53, 67, 81, 94, 112, 129, 144, 161, 174, 186, 208, 228, 254, 268, 289, 306, 321, 344, 361, 379, 396, 420, 435, 456, 474, 486, 506, 523, 546, 567, 579, 597, 618, 646, 676, 697, 720, 746, 783, 813, 846, 871, 903, 933, 962, 987, 1009, 1035, 1057, 1085, 1114, 1148, 1179, 1216, 1240, 1264, 1292, 1318, 1349, 1379, 1388, 1400, 1416, 1429, 1443, 1461, 1481, 1502, 1518, 1529, 1545, 1556, 1584, 1604, 1620, 1648, 1662, 1679, 1699, 1712, 1726, 1739, 1752, 1768, 1785, 1806, 1820, 1841, 1854, 1876, 1899, 1915, 1930, 1945, 1966, 1984, 1999, 2016, 2041, 2059, 2082, 2097, 2116, 2132, 2151, 2172, 2186, 2198, 2211, 2230, 2249, 2259, 2274, 2310, 2341, 2374, 2403, 2415, 2435, 2459, 2483, 2504, 2528, 2547, 2568, 2585, 2595, 2612, 2629, 2652, 2674, 2700, 2721, 2739, 2766, 2797, 2824, 2845, 2866, 2890, 2915, 2943, 2971, 2987, 3010, 3040, 3051, 3063, 3080, 3095, 3113, 3142, 3159, 3175, 3191, 3209, 3227, 3250, 3271, 3294, 3305, 3321, 3344, 3361, 3389, 3408, 3438, 3458, 3486, 3501, 3519, 3534, 3548, 3583, 3602, 3613, 3626, 3641, 3664, 3690, 3706, 3724, 3742, 3763, 3777, 3794, 3825, 3845, 3866, 3887, 3906, 3925, 3943, 3966, 3990, 4014, 4039, 4074, 4099, 4133, 4166, 4187, 4201, 4220, 4249, 4272, 4299, 4333, 4365, 4395, 4418, 4446, 4478, 4506, 4530, 4554, 4583, 4601, 4618, 4640, 4657, 4675, 4695, 4721, 4737, 4756, 4777, 4781, 4799, 4816, 4842, 4856, 4880, 4901, 4916, 4934, 4957, 4972, 4991, 5008, 5025, 5049, 5076, 5099, 5122, 5139, 5161, 5177, 5197, 5216, 5238, 5259, 5279, 5301, 5325, 5344, 5386, 5407, 5430, 5451, 5482, 5501, 5523, 5543, 5569, 5590, 5612, 5632, 5656, 5679, 5698, 5718, 5740, 5763, 5794, 5832, 5873, 5903, 5917, 5938, 5954, 5976, 6006, 6032, 6060, 6094, 6112, 6135, 6170, 6210, 6252, 6284, 6301, 6326, 6341, 6358, 6368, 6379, 6417, 6471, 6517, 6569, 6617, 6660, 6704, 6732, 6746, 6764, 6800, 6823, 6846, 6868, 6883, 6911, 6934, 6952, 6979, 7011, 7026, 7042, 7059, 7079, 7095, 7111, 7128, 7141} func (i APIErrorCode) String() string { if i < 0 || i >= APIErrorCode(len(_APIErrorCode_index)-1) { diff --git a/cmd/iam-store.go b/cmd/iam-store.go index 3f8c86bfa..5640a8b8f 100644 --- a/cmd/iam-store.go +++ b/cmd/iam-store.go @@ -2032,6 +2032,50 @@ func (store *IAMStoreSys) SetTempUser(ctx context.Context, accessKey string, cre return u.UpdatedAt, nil } +// RevokeTokens - revokes all temporary credentials, or those with matching type, +// associated with the parent user. +func (store *IAMStoreSys) RevokeTokens(ctx context.Context, parentUser string, tokenRevokeType string) error { + if parentUser == "" { + return errInvalidArgument + } + + cache := store.lock() + defer store.unlock() + + secret, err := getTokenSigningKey() + if err != nil { + return err + } + + var revoked bool + for _, ui := range cache.iamSTSAccountsMap { + if ui.Credentials.ParentUser != parentUser { + continue + } + if tokenRevokeType != "" { + claims, err := getClaimsFromTokenWithSecret(ui.Credentials.SessionToken, secret) + if err != nil { + continue // skip if token is invalid + } + // skip if token type is given and does not match + if v, _ := claims.Lookup(tokenRevokeTypeClaim); v != tokenRevokeType { + continue + } + } + if err := store.deleteUserIdentity(ctx, ui.Credentials.AccessKey, stsUser); err != nil { + return err + } + delete(cache.iamSTSAccountsMap, ui.Credentials.AccessKey) + revoked = true + } + + if revoked { + cache.updatedAt = time.Now() + } + + return nil +} + // DeleteUsers - given a set of users or access keys, deletes them along with // any derived credentials (STS or service accounts) and any associated policy // mappings. diff --git a/cmd/iam.go b/cmd/iam.go index 7ee09c895..2c59405ee 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -662,6 +662,16 @@ func (sys *IAMSys) SetPolicy(ctx context.Context, policyName string, p policy.Po return updatedAt, nil } +// RevokeTokens - revokes all STS tokens, or those of specified type, for a user +// If `tokenRevokeType` is empty, all tokens are revoked. +func (sys *IAMSys) RevokeTokens(ctx context.Context, accessKey, tokenRevokeType string) error { + if !sys.Initialized() { + return errServerNotInitialized + } + + return sys.store.RevokeTokens(ctx, accessKey, tokenRevokeType) +} + // DeleteUser - delete user (only for long-term users not STS users). func (sys *IAMSys) DeleteUser(ctx context.Context, accessKey string, notifyPeers bool) error { if !sys.Initialized() { diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go index c2b1fa172..9ac887a89 100644 --- a/cmd/sts-handlers.go +++ b/cmd/sts-handlers.go @@ -55,6 +55,7 @@ const ( stsDurationSeconds = "DurationSeconds" stsLDAPUsername = "LDAPUsername" stsLDAPPassword = "LDAPPassword" + stsRevokeTokenType = "TokenRevokeType" // STS API action constants clientGrants = "AssumeRoleWithClientGrants" @@ -85,6 +86,9 @@ const ( // Role Claim key roleArnClaim = "roleArn" + // STS revoke type claim key + tokenRevokeTypeClaim = "tokenRevokeType" + // maximum supported STS session policy size maxSTSSessionPolicySize = 2048 ) @@ -307,6 +311,11 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) { claims[expClaim] = UTCNow().Add(duration).Unix() claims[parentClaim] = user.AccessKey + tokenRevokeType := r.Form.Get(stsRevokeTokenType) + if tokenRevokeType != "" { + claims[tokenRevokeTypeClaim] = tokenRevokeType + } + // Validate that user.AccessKey's policies can be retrieved - it may not // be in case the user is disabled. if _, err = globalIAMSys.PolicyDBGet(user.AccessKey, user.Groups...); err != nil { @@ -471,6 +480,11 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ claims[iamPolicyClaimNameOpenID()] = policyName } + tokenRevokeType := r.Form.Get(stsRevokeTokenType) + if tokenRevokeType != "" { + claims[tokenRevokeTypeClaim] = tokenRevokeType + } + if err := claims.populateSessionPolicy(r.Form); err != nil { writeSTSErrorResponse(ctx, w, ErrSTSInvalidParameterValue, err) return @@ -691,6 +705,10 @@ func (sts *stsAPIHandlers) AssumeRoleWithLDAPIdentity(w http.ResponseWriter, r * for attrib, value := range lookupResult.Attributes { claims[ldapAttribPrefix+attrib] = value } + tokenRevokeType := r.Form.Get(stsRevokeTokenType) + if tokenRevokeType != "" { + claims[tokenRevokeTypeClaim] = tokenRevokeType + } secret, err := getTokenSigningKey() if err != nil { @@ -887,6 +905,11 @@ func (sts *stsAPIHandlers) AssumeRoleWithCertificate(w http.ResponseWriter, r *h claims[audClaim] = certificate.Subject.Organization claims[issClaim] = certificate.Issuer.CommonName claims[parentClaim] = parentUser + tokenRevokeType := r.Form.Get(stsRevokeTokenType) + if tokenRevokeType != "" { + claims[tokenRevokeTypeClaim] = tokenRevokeType + } + secretKey, err := getTokenSigningKey() if err != nil { writeSTSErrorResponse(ctx, w, ErrSTSInternalError, err) @@ -1012,6 +1035,10 @@ func (sts *stsAPIHandlers) AssumeRoleWithCustomToken(w http.ResponseWriter, r *h claims[subClaim] = parentUser claims[roleArnClaim] = roleArn.String() claims[parentClaim] = parentUser + tokenRevokeType := r.Form.Get(stsRevokeTokenType) + if tokenRevokeType != "" { + claims[tokenRevokeTypeClaim] = tokenRevokeType + } // Add all other claims from the plugin **without** replacing any // existing claims. diff --git a/cmd/sts-handlers_test.go b/cmd/sts-handlers_test.go index daa46b053..dc6b99e2e 100644 --- a/cmd/sts-handlers_test.go +++ b/cmd/sts-handlers_test.go @@ -46,6 +46,7 @@ func runAllIAMSTSTests(suite *TestSuiteIAM, c *check) { suite.TestSTSWithTags(c) suite.TestSTSServiceAccountsWithUsername(c) suite.TestSTSWithGroupPolicy(c) + suite.TestSTSTokenRevoke(c) suite.TearDownSuite(c) } @@ -657,6 +658,129 @@ func (s *TestSuiteIAM) TestSTSForRoot(c *check) { } } +// TestSTSTokenRevoke - tests the token revoke API +func (s *TestSuiteIAM) TestSTSTokenRevoke(c *check) { + ctx, cancel := context.WithTimeout(context.Background(), 100*testDefaultTimeout) + defer cancel() + + bucket := getRandomBucketName() + err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) + if err != nil { + c.Fatalf("bucket create error: %v", err) + } + + // Create policy, user and associate policy + policy := "mypolicy" + policyBytes := []byte(fmt.Sprintf(`{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket" + ], + "Resource": [ + "arn:aws:s3:::%s/*" + ] + } + ] +}`, bucket)) + err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) + if err != nil { + c.Fatalf("policy add error: %v", err) + } + + accessKey, secretKey := mustGenerateCredentials(c) + err = s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled) + if err != nil { + c.Fatalf("Unable to set user: %v", err) + } + + _, err = s.adm.AttachPolicy(ctx, madmin.PolicyAssociationReq{ + Policies: []string{policy}, + User: accessKey, + }) + if err != nil { + c.Fatalf("Unable to attach policy: %v", err) + } + + cases := []struct { + tokenType string + fullRevoke bool + selfRevoke bool + }{ + {"", true, false}, // Case 1 + {"", true, true}, // Case 2 + {"type-1", false, false}, // Case 3 + {"type-2", false, true}, // Case 4 + {"type-2", true, true}, // Case 5 - repeat type 2 to ensure previous revoke does not affect it. + } + + for i, tc := range cases { + // Create STS user. + assumeRole := cr.STSAssumeRole{ + Client: s.TestSuiteCommon.client, + STSEndpoint: s.endPoint, + Options: cr.STSAssumeRoleOptions{ + AccessKey: accessKey, + SecretKey: secretKey, + TokenRevokeType: tc.tokenType, + }, + } + + value, err := assumeRole.Retrieve() + if err != nil { + c.Fatalf("err calling assumeRole: %v", err) + } + + minioClient, err := minio.New(s.endpoint, &minio.Options{ + Creds: cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), + Secure: s.secure, + Transport: s.TestSuiteCommon.client.Transport, + }) + if err != nil { + c.Fatalf("Error initializing client: %v", err) + } + + // Validate that the client from sts creds can access the bucket. + c.mustListObjects(ctx, minioClient, bucket) + + // Set up revocation + user := accessKey + tokenType := tc.tokenType + reqAdmClient := s.adm + if tc.fullRevoke { + tokenType = "" + } + if tc.selfRevoke { + user = "" + tokenType = "" + reqAdmClient, err = madmin.NewWithOptions(s.endpoint, &madmin.Options{ + Creds: cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), + Secure: s.secure, + }) + if err != nil { + c.Fatalf("Err creating user admin client: %v", err) + } + reqAdmClient.SetCustomTransport(s.TestSuiteCommon.client.Transport) + } + + err = reqAdmClient.RevokeTokens(ctx, madmin.RevokeTokensReq{ + User: user, + TokenRevokeType: tokenType, + FullRevoke: tc.fullRevoke, + }) + if err != nil { + c.Fatalf("Case %d: unexpected error: %v", i+1, err) + } + + // Validate that the client cannot access the bucket after revocation. + c.mustNotListObjects(ctx, minioClient, bucket) + } +} + // SetUpLDAP - expects to setup an LDAP test server using the test LDAP // container and canned data from https://github.com/minio/minio-ldap-testing func (s *TestSuiteIAM) SetUpLDAP(c *check, serverAddr string) { diff --git a/cmd/user-provider-utils.go b/cmd/user-provider-utils.go new file mode 100644 index 000000000..5f5501350 --- /dev/null +++ b/cmd/user-provider-utils.go @@ -0,0 +1,57 @@ +// Copyright (c) 2015-2023 MinIO, Inc. +// +// This file is part of MinIO Object Storage stack +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package cmd + +import ( + "context" + + "github.com/minio/madmin-go/v3" +) + +// getUserWithProvider - returns the appropriate internal username based on the user provider. +// if validate is true, an error is returned if the user does not exist. +func getUserWithProvider(ctx context.Context, userProvider, user string, validate bool) (string, error) { + switch userProvider { + case madmin.BuiltinProvider: + if validate { + if _, ok := globalIAMSys.GetUser(ctx, user); !ok { + return "", errNoSuchUser + } + } + return user, nil + case madmin.LDAPProvider: + if globalIAMSys.GetUsersSysType() != LDAPUsersSysType { + return "", errIAMActionNotAllowed + } + res, err := globalIAMSys.LDAPConfig.GetValidatedDNForUsername(user) + if res == nil { + err = errNoSuchUser + } + if err != nil { + if validate { + return "", err + } + if !globalIAMSys.LDAPConfig.ParsesAsDN(user) { + return "", errNoSuchUser + } + } + return res.NormDN, nil + default: + return "", errIAMActionNotAllowed + } +} diff --git a/go.mod b/go.mod index 8983239e0..51b8d5c43 100644 --- a/go.mod +++ b/go.mod @@ -51,8 +51,8 @@ require ( github.com/minio/highwayhash v1.0.3 github.com/minio/kms-go/kes v0.3.1 github.com/minio/kms-go/kms v0.4.0 - github.com/minio/madmin-go/v3 v3.0.97 - github.com/minio/minio-go/v7 v7.0.88 + github.com/minio/madmin-go/v3 v3.0.102 + github.com/minio/minio-go/v7 v7.0.89 github.com/minio/mux v1.9.2 github.com/minio/pkg/v3 v3.1.0 github.com/minio/selfupdate v0.6.0 diff --git a/go.sum b/go.sum index 59b362e04..36d2bb401 100644 --- a/go.sum +++ b/go.sum @@ -436,15 +436,15 @@ github.com/minio/kms-go/kes v0.3.1 h1:K3sPFAvFbJx33XlCTUBnQo8JRmSZyDvT6T2/MQ2iC3 github.com/minio/kms-go/kes v0.3.1/go.mod h1:Q9Ct0KUAuN9dH0hSVa0eva45Jg99cahbZpPxeqR9rOQ= github.com/minio/kms-go/kms v0.4.0 h1:cLPZceEp+05xHotVBaeFJrgL7JcXM4lBy6PU0idkE7I= github.com/minio/kms-go/kms v0.4.0/go.mod h1:q12CehiIy2qgBnDKq6Q7wmPi2PHSyRVug5DKp0HAVeE= -github.com/minio/madmin-go/v3 v3.0.97 h1:P7XO+ofPexkXy9akxG9Xoif1zIkbmWKeKtG3AquVzEY= -github.com/minio/madmin-go/v3 v3.0.97/go.mod h1:pMLdj9OtN0CANNs5tdm6opvOlDFfj0WhbztboZAjRWE= +github.com/minio/madmin-go/v3 v3.0.102 h1:bqy15D6d9uQOh/3B/sLfzRtWSJgZeuKnAI5VRDhvRQw= +github.com/minio/madmin-go/v3 v3.0.102/go.mod h1:pMLdj9OtN0CANNs5tdm6opvOlDFfj0WhbztboZAjRWE= github.com/minio/mc v0.0.0-20250312172924-c1d5d4cbb4ca h1:Zeu+Gbsw/yoqJofAFaU3zbIVr51j9LULUrQqKFLQnGA= github.com/minio/mc v0.0.0-20250312172924-c1d5d4cbb4ca/go.mod h1:h5UQZ+5Qfq6XV81E4iZSgStPZ6Hy+gMuHMkLkjq4Gys= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= -github.com/minio/minio-go/v7 v7.0.88 h1:v8MoIJjwYxOkehp+eiLIuvXk87P2raUtoU5klrAAshs= -github.com/minio/minio-go/v7 v7.0.88/go.mod h1:33+O8h0tO7pCeCWwBVa07RhVVfB/3vS4kEX7rwYKmIg= +github.com/minio/minio-go/v7 v7.0.89 h1:hx4xV5wwTUfyv8LarhJAwNecnXpoTsj9v3f3q/ZkiJU= +github.com/minio/minio-go/v7 v7.0.89/go.mod h1:2rFnGAp02p7Dddo1Fq4S2wYOfpF0MUTSeLTRC90I204= github.com/minio/mux v1.9.2 h1:dQchne49BUBgOlxIHjx5wVe1gl5VXF2sxd4YCXkikTw= github.com/minio/mux v1.9.2/go.mod h1:OuHAsZsux+e562bcO2P3Zv/P0LMo6fPQ310SmoyG7mQ= github.com/minio/pkg/v3 v3.1.0 h1:RoR1TMXV5y4LvKPkaB1WoeuM6CO7A+I55xYb1tzrvLQ=