mirror of
https://github.com/minio/minio.git
synced 2025-11-29 05:19:03 -05:00
server: Move all the top level files into cmd folder. (#2490)
This change brings a change which was done for the 'mc' package to allow for clean repo and have a cleaner github drop in experience.
This commit is contained in:
committed by
Anand Babu (AB) Periasamy
parent
73d1a46f3e
commit
bccf549463
322
cmd/bucket-notification-utils.go
Normal file
322
cmd/bucket-notification-utils.go
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import "strings"
|
||||
|
||||
// List of valid event types.
|
||||
var suppportedEventTypes = map[string]struct{}{
|
||||
// Object created event types.
|
||||
"s3:ObjectCreated:*": {},
|
||||
"s3:ObjectCreated:Put": {},
|
||||
"s3:ObjectCreated:Post": {},
|
||||
"s3:ObjectCreated:Copy": {},
|
||||
"s3:ObjectCreated:CompleteMultipartUpload": {},
|
||||
// Object removed event types.
|
||||
"s3:ObjectRemoved:*": {},
|
||||
"s3:ObjectRemoved:Delete": {},
|
||||
}
|
||||
|
||||
// checkEvent - checks if an event is supported.
|
||||
func checkEvent(event string) APIErrorCode {
|
||||
_, ok := suppportedEventTypes[event]
|
||||
if !ok {
|
||||
return ErrEventNotification
|
||||
}
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// checkEvents - checks given list of events if all of them are valid.
|
||||
// given if one of them is invalid, this function returns an error.
|
||||
func checkEvents(events []string) APIErrorCode {
|
||||
for _, event := range events {
|
||||
if s3Error := checkEvent(event); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
}
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Valid if filterName is 'prefix'.
|
||||
func isValidFilterNamePrefix(filterName string) bool {
|
||||
return "prefix" == filterName
|
||||
}
|
||||
|
||||
// Valid if filterName is 'suffix'.
|
||||
func isValidFilterNameSuffix(filterName string) bool {
|
||||
return "suffix" == filterName
|
||||
}
|
||||
|
||||
// Is this a valid filterName? - returns true if valid.
|
||||
func isValidFilterName(filterName string) bool {
|
||||
return isValidFilterNamePrefix(filterName) || isValidFilterNameSuffix(filterName)
|
||||
}
|
||||
|
||||
// checkFilterRules - checks given list of filter rules if all of them are valid.
|
||||
func checkFilterRules(filterRules []filterRule) APIErrorCode {
|
||||
ruleSetMap := make(map[string]string)
|
||||
// Validate all filter rules.
|
||||
for _, filterRule := range filterRules {
|
||||
// Unknown filter rule name found, returns an appropriate error.
|
||||
if !isValidFilterName(filterRule.Name) {
|
||||
return ErrFilterNameInvalid
|
||||
}
|
||||
|
||||
// Filter names should not be set twice per notification service
|
||||
// configuration, if found return an appropriate error.
|
||||
if _, ok := ruleSetMap[filterRule.Name]; ok {
|
||||
if isValidFilterNamePrefix(filterRule.Name) {
|
||||
return ErrFilterNamePrefix
|
||||
} else if isValidFilterNameSuffix(filterRule.Name) {
|
||||
return ErrFilterNameSuffix
|
||||
} else {
|
||||
return ErrFilterNameInvalid
|
||||
}
|
||||
}
|
||||
|
||||
if !IsValidObjectPrefix(filterRule.Value) {
|
||||
return ErrFilterValueInvalid
|
||||
}
|
||||
|
||||
// Set the new rule name to keep track of duplicates.
|
||||
ruleSetMap[filterRule.Name] = filterRule.Value
|
||||
}
|
||||
// Success all prefixes validated.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Checks validity of input ARN for a given arnType.
|
||||
func checkARN(arn, arnType string) APIErrorCode {
|
||||
if !strings.HasPrefix(arn, arnType) {
|
||||
return ErrARNNotification
|
||||
}
|
||||
if !strings.HasPrefix(arn, arnType+serverConfig.GetRegion()+":") {
|
||||
return ErrRegionNotification
|
||||
}
|
||||
account := strings.SplitN(strings.TrimPrefix(arn, arnType+serverConfig.GetRegion()+":"), ":", 2)
|
||||
switch len(account) {
|
||||
case 1:
|
||||
// This means ARN is malformed, account should have min of 2elements.
|
||||
return ErrARNNotification
|
||||
case 2:
|
||||
// Account topic id or topic name cannot be empty.
|
||||
if account[0] == "" || account[1] == "" {
|
||||
return ErrARNNotification
|
||||
}
|
||||
}
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// checkQueueARN - check if the queue arn is valid.
|
||||
func checkQueueARN(queueARN string) APIErrorCode {
|
||||
return checkARN(queueARN, minioSqs)
|
||||
}
|
||||
|
||||
// checkTopicARN - check if the topic arn is valid.
|
||||
func checkTopicARN(topicARN string) APIErrorCode {
|
||||
return checkARN(topicARN, minioTopic)
|
||||
}
|
||||
|
||||
// Returns true if the topicARN is for an Minio sns listen type.
|
||||
func isMinioSNS(topicARN arnTopic) bool {
|
||||
return strings.HasSuffix(topicARN.Type, snsTypeMinio)
|
||||
}
|
||||
|
||||
// isMinioSNSConfigured - verifies if one topic ARN is valid and is enabled.
|
||||
func isMinioSNSConfigured(topicARN string, topicConfigs []topicConfig) bool {
|
||||
for _, topicConfig := range topicConfigs {
|
||||
// Validate if topic ARN is already enabled.
|
||||
if topicARN == topicConfig.TopicARN {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Validate if we recognize the queue type.
|
||||
func isValidQueue(sqsARN arnSQS) bool {
|
||||
amqpQ := isAMQPQueue(sqsARN) // Is amqp queue?.
|
||||
elasticQ := isElasticQueue(sqsARN) // Is elastic queue?.
|
||||
redisQ := isRedisQueue(sqsARN) // Is redis queue?.
|
||||
return amqpQ || elasticQ || redisQ
|
||||
}
|
||||
|
||||
// Validate if we recognize the topic type.
|
||||
func isValidTopic(topicARN arnTopic) bool {
|
||||
return isMinioSNS(topicARN) // Is minio topic?.
|
||||
}
|
||||
|
||||
// Validates account id for input queue ARN.
|
||||
func isValidQueueID(queueARN string) bool {
|
||||
// Unmarshals QueueARN into structured object.
|
||||
sqsARN := unmarshalSqsARN(queueARN)
|
||||
// AMQP queue.
|
||||
if isAMQPQueue(sqsARN) {
|
||||
amqpN := serverConfig.GetAMQPNotifyByID(sqsARN.AccountID)
|
||||
return amqpN.Enable && amqpN.URL != ""
|
||||
} else if isElasticQueue(sqsARN) { // Elastic queue.
|
||||
elasticN := serverConfig.GetElasticSearchNotifyByID(sqsARN.AccountID)
|
||||
return elasticN.Enable && elasticN.URL != ""
|
||||
|
||||
} else if isRedisQueue(sqsARN) { // Redis queue.
|
||||
redisN := serverConfig.GetRedisNotifyByID(sqsARN.AccountID)
|
||||
return redisN.Enable && redisN.Addr != ""
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Check - validates queue configuration and returns error if any.
|
||||
func checkQueueConfig(qConfig queueConfig) APIErrorCode {
|
||||
// Check queue arn is valid.
|
||||
if s3Error := checkQueueARN(qConfig.QueueARN); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Unmarshals QueueARN into structured object.
|
||||
sqsARN := unmarshalSqsARN(qConfig.QueueARN)
|
||||
// Validate if sqsARN requested any of the known supported queues.
|
||||
if !isValidQueue(sqsARN) {
|
||||
return ErrARNNotification
|
||||
}
|
||||
|
||||
// Validate if the account ID is correct.
|
||||
if !isValidQueueID(qConfig.QueueARN) {
|
||||
return ErrARNNotification
|
||||
}
|
||||
|
||||
// Check if valid events are set in queue config.
|
||||
if s3Error := checkEvents(qConfig.Events); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Check if valid filters are set in queue config.
|
||||
if s3Error := checkFilterRules(qConfig.Filter.Key.FilterRules); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Success.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Check - validates queue configuration and returns error if any.
|
||||
func checkTopicConfig(tConfig topicConfig) APIErrorCode {
|
||||
// Check queue arn is valid.
|
||||
if s3Error := checkTopicARN(tConfig.TopicARN); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Unmarshals QueueARN into structured object.
|
||||
topicARN := unmarshalTopicARN(tConfig.TopicARN)
|
||||
// Validate if topicARN requested any of the known supported queues.
|
||||
if !isValidTopic(topicARN) {
|
||||
return ErrARNNotification
|
||||
}
|
||||
|
||||
// Check if valid events are set in queue config.
|
||||
if s3Error := checkEvents(tConfig.Events); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Check if valid filters are set in queue config.
|
||||
if s3Error := checkFilterRules(tConfig.Filter.Key.FilterRules); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Success.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Validates all incoming queue configs, checkQueueConfig validates if the
|
||||
// input fields for each queues is not malformed and has valid configuration
|
||||
// information. If validation fails bucket notifications are not enabled.
|
||||
func validateQueueConfigs(queueConfigs []queueConfig) APIErrorCode {
|
||||
for _, qConfig := range queueConfigs {
|
||||
if s3Error := checkQueueConfig(qConfig); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
}
|
||||
// Success.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Validates all incoming topic configs, checkTopicConfig validates if the
|
||||
// input fields for each queues is not malformed and has valid configuration
|
||||
// information. If validation fails bucket notifications are not enabled.
|
||||
func validateTopicConfigs(topicConfigs []topicConfig) APIErrorCode {
|
||||
for _, tConfig := range topicConfigs {
|
||||
if s3Error := checkTopicConfig(tConfig); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
}
|
||||
// Success.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Validates all the bucket notification configuration for their validity,
|
||||
// if one of the config is malformed or has invalid data it is rejected.
|
||||
// Configuration is never applied partially.
|
||||
func validateNotificationConfig(nConfig notificationConfig) APIErrorCode {
|
||||
if s3Error := validateQueueConfigs(nConfig.QueueConfigs); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
if s3Error := validateTopicConfigs(nConfig.TopicConfigs); s3Error != ErrNone {
|
||||
return s3Error
|
||||
}
|
||||
|
||||
// Add validation for other configurations.
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Unmarshals input value of AWS ARN format into minioTopic object.
|
||||
// Returned value represents minio topic type, currently supported are
|
||||
// - listen
|
||||
func unmarshalTopicARN(topicARN string) arnTopic {
|
||||
topic := arnTopic{}
|
||||
if !strings.HasPrefix(topicARN, minioTopic+serverConfig.GetRegion()+":") {
|
||||
return topic
|
||||
}
|
||||
topicType := strings.TrimPrefix(topicARN, minioTopic+serverConfig.GetRegion()+":")
|
||||
switch {
|
||||
case strings.HasSuffix(topicType, snsTypeMinio):
|
||||
topic.Type = snsTypeMinio
|
||||
} // Add more topic here.
|
||||
topic.AccountID = strings.TrimSuffix(topicType, ":"+topic.Type)
|
||||
return topic
|
||||
}
|
||||
|
||||
// Unmarshals input value of AWS ARN format into minioSqs object.
|
||||
// Returned value represents minio sqs types, currently supported are
|
||||
// - amqp
|
||||
// - elasticsearch
|
||||
// - redis
|
||||
func unmarshalSqsARN(queueARN string) (mSqs arnSQS) {
|
||||
mSqs = arnSQS{}
|
||||
if !strings.HasPrefix(queueARN, minioSqs+serverConfig.GetRegion()+":") {
|
||||
return mSqs
|
||||
}
|
||||
sqsType := strings.TrimPrefix(queueARN, minioSqs+serverConfig.GetRegion()+":")
|
||||
switch {
|
||||
case strings.HasSuffix(sqsType, queueTypeAMQP):
|
||||
mSqs.Type = queueTypeAMQP
|
||||
case strings.HasSuffix(sqsType, queueTypeElastic):
|
||||
mSqs.Type = queueTypeElastic
|
||||
case strings.HasSuffix(sqsType, queueTypeRedis):
|
||||
mSqs.Type = queueTypeRedis
|
||||
} // Add more queues here.
|
||||
mSqs.AccountID = strings.TrimSuffix(sqsType, ":"+mSqs.Type)
|
||||
return mSqs
|
||||
}
|
||||
Reference in New Issue
Block a user