mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	Remove SQS plugin (#26524)
To be moved to Enterprise. The paths and plugin itself were not activated.
This commit is contained in:
		 Christopher Swenson
					Christopher Swenson
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							dd939d9a7e
						
					
				
				
					commit
					1e36019f1c
				
			| @@ -50,7 +50,6 @@ import ( | |||||||
| 	physSpanner "github.com/hashicorp/vault/physical/spanner" | 	physSpanner "github.com/hashicorp/vault/physical/spanner" | ||||||
| 	physSwift "github.com/hashicorp/vault/physical/swift" | 	physSwift "github.com/hashicorp/vault/physical/swift" | ||||||
| 	physZooKeeper "github.com/hashicorp/vault/physical/zookeeper" | 	physZooKeeper "github.com/hashicorp/vault/physical/zookeeper" | ||||||
| 	"github.com/hashicorp/vault/plugins/event" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" | 	"github.com/hashicorp/vault/sdk/logical" | ||||||
| 	"github.com/hashicorp/vault/sdk/physical" | 	"github.com/hashicorp/vault/sdk/physical" | ||||||
| 	physFile "github.com/hashicorp/vault/sdk/physical/file" | 	physFile "github.com/hashicorp/vault/sdk/physical/file" | ||||||
| @@ -172,8 +171,6 @@ var ( | |||||||
| 		"plugin": plugin.Factory, | 		"plugin": plugin.Factory, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	eventBackends = map[string]event.Factory{} |  | ||||||
|  |  | ||||||
| 	logicalBackends = map[string]logical.Factory{ | 	logicalBackends = map[string]logical.Factory{ | ||||||
| 		"plugin":   plugin.Factory, | 		"plugin":   plugin.Factory, | ||||||
| 		"database": logicalDb.Factory, | 		"database": logicalDb.Factory, | ||||||
| @@ -731,7 +728,6 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) map[string]cli.Co | |||||||
| 				}, | 				}, | ||||||
| 				AuditBackends:      auditBackends, | 				AuditBackends:      auditBackends, | ||||||
| 				CredentialBackends: credentialBackends, | 				CredentialBackends: credentialBackends, | ||||||
| 				EventBackends:      eventBackends, |  | ||||||
| 				LogicalBackends:    logicalBackends, | 				LogicalBackends:    logicalBackends, | ||||||
| 				PhysicalBackends:   physicalBackends, | 				PhysicalBackends:   physicalBackends, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,7 +52,6 @@ import ( | |||||||
| 	vaulthttp "github.com/hashicorp/vault/http" | 	vaulthttp "github.com/hashicorp/vault/http" | ||||||
| 	"github.com/hashicorp/vault/internalshared/configutil" | 	"github.com/hashicorp/vault/internalshared/configutil" | ||||||
| 	"github.com/hashicorp/vault/internalshared/listenerutil" | 	"github.com/hashicorp/vault/internalshared/listenerutil" | ||||||
| 	"github.com/hashicorp/vault/plugins/event" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/consts" | 	"github.com/hashicorp/vault/sdk/helper/consts" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/jsonutil" | 	"github.com/hashicorp/vault/sdk/helper/jsonutil" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/strutil" | 	"github.com/hashicorp/vault/sdk/helper/strutil" | ||||||
| @@ -97,7 +96,6 @@ type ServerCommand struct { | |||||||
| 	CredentialBackends map[string]logical.Factory | 	CredentialBackends map[string]logical.Factory | ||||||
| 	LogicalBackends    map[string]logical.Factory | 	LogicalBackends    map[string]logical.Factory | ||||||
| 	PhysicalBackends   map[string]physical.Factory | 	PhysicalBackends   map[string]physical.Factory | ||||||
| 	EventBackends      map[string]event.Factory |  | ||||||
|  |  | ||||||
| 	ServiceRegistrations map[string]sr.Factory | 	ServiceRegistrations map[string]sr.Factory | ||||||
|  |  | ||||||
| @@ -3108,7 +3106,6 @@ func createCoreConfig(c *ServerCommand, config *server.Config, backend physical. | |||||||
| 		AuditBackends:                  c.AuditBackends, | 		AuditBackends:                  c.AuditBackends, | ||||||
| 		CredentialBackends:             c.CredentialBackends, | 		CredentialBackends:             c.CredentialBackends, | ||||||
| 		LogicalBackends:                c.LogicalBackends, | 		LogicalBackends:                c.LogicalBackends, | ||||||
| 		EventBackends:                  c.EventBackends, |  | ||||||
| 		LogLevel:                       config.LogLevel, | 		LogLevel:                       config.LogLevel, | ||||||
| 		Logger:                         c.logger, | 		Logger:                         c.logger, | ||||||
| 		DetectDeadlocks:                config.DetectDeadlocks, | 		DetectDeadlocks:                config.DetectDeadlocks, | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -51,7 +51,6 @@ require ( | |||||||
| 	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 | 	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 | ||||||
| 	github.com/aws/aws-sdk-go v1.50.13 | 	github.com/aws/aws-sdk-go v1.50.13 | ||||||
| 	github.com/aws/aws-sdk-go-v2/config v1.18.19 | 	github.com/aws/aws-sdk-go-v2/config v1.18.19 | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/sqs v1.29.1 |  | ||||||
| 	github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a | 	github.com/axiomhq/hyperloglog v0.0.0-20220105174342-98591331716a | ||||||
| 	github.com/cenkalti/backoff/v3 v3.2.2 | 	github.com/cenkalti/backoff/v3 v3.2.2 | ||||||
| 	github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 | 	github.com/chrismalek/oktasdk-go v0.0.0-20181212195951-3430665dfaa0 | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1442,8 +1442,6 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBf | |||||||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= | ||||||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ= | github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ= | ||||||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= | github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sqs v1.29.1 h1:OZI2aJxnfOZzB0uhyTaYIW6MeRMb1Qd2eLMjh0bFsRg= |  | ||||||
| github.com/aws/aws-sdk-go-v2/service/sqs v1.29.1/go.mod h1:GiU88YWgOho2cyEyS2YZo3GYz/j4etRYKWbJdcYgpuQ= |  | ||||||
| github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= | github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= | ||||||
| github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= | github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= | ||||||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= | ||||||
|   | |||||||
| @@ -1,95 +0,0 @@ | |||||||
| // Copyright (c) HashiCorp, Inc. |  | ||||||
| // SPDX-License-Identifier: MPL-2.0 |  | ||||||
|  |  | ||||||
| package event |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/backoff" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Factory func(context.Context) (SubscriptionPlugin, error) |  | ||||||
|  |  | ||||||
| // SubscriptionPlugin is the interface implemented by plugins that can subscribe to and receive events. |  | ||||||
| type SubscriptionPlugin interface { |  | ||||||
| 	// Subscribe is used to set up a new connection. |  | ||||||
| 	Subscribe(context.Context, *SubscribeRequest) error |  | ||||||
| 	// Send is used to send events to a connection. |  | ||||||
| 	Send(context.Context, *SendRequest) error |  | ||||||
| 	// Unsubscribe is used to teardown a connection. |  | ||||||
| 	Unsubscribe(context.Context, *UnsubscribeRequest) error |  | ||||||
| 	// PluginMetadata returns the name and version for the particular event subscription plugin. |  | ||||||
| 	// The name is usually set as a constant the backend, e.g., "sqs" for the |  | ||||||
| 	// AWS SQS backend. |  | ||||||
| 	PluginMetadata() *PluginMetadata |  | ||||||
| 	// Close closes all connections. |  | ||||||
| 	Close(ctx context.Context) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type Request struct { |  | ||||||
| 	Subscribe   *SubscribeRequest |  | ||||||
| 	Unsubscribe *UnsubscribeRequest |  | ||||||
| 	Event       *SendRequest |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type SubscribeRequest struct { |  | ||||||
| 	SubscriptionID   string |  | ||||||
| 	Config           map[string]interface{} |  | ||||||
| 	VerifyConnection bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type UnsubscribeRequest struct { |  | ||||||
| 	SubscriptionID string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type SendRequest struct { |  | ||||||
| 	SubscriptionID string |  | ||||||
| 	EventJSON      string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type PluginMetadata struct { |  | ||||||
| 	Name    string |  | ||||||
| 	Version string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // SubscribeConfigDefaults defines configuration map keys for common default options. |  | ||||||
| // Embed this in your own config struct to pick up these default options. |  | ||||||
| type SubscribeConfigDefaults struct { |  | ||||||
| 	Retries         *int           `mapstructure:"retries"` |  | ||||||
| 	RetryMinBackoff *time.Duration `mapstructure:"retry_min_backoff"` |  | ||||||
| 	RetryMaxBackoff *time.Duration `mapstructure:"retry_max_backoff"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // default values for common configuration keys |  | ||||||
| const ( |  | ||||||
| 	DefaultRetries         = 3 |  | ||||||
| 	DefaultRetryMinBackoff = 100 * time.Millisecond |  | ||||||
| 	DefaultRetryMaxBackoff = 5 * time.Second |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func (c *SubscribeConfigDefaults) GetRetries() int { |  | ||||||
| 	if c.Retries == nil { |  | ||||||
| 		return DefaultRetries |  | ||||||
| 	} |  | ||||||
| 	return *c.Retries |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *SubscribeConfigDefaults) GetRetryMinBackoff() time.Duration { |  | ||||||
| 	if c.RetryMinBackoff == nil { |  | ||||||
| 		return DefaultRetryMinBackoff |  | ||||||
| 	} |  | ||||||
| 	return *c.RetryMinBackoff |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *SubscribeConfigDefaults) GetRetryMaxBackoff() time.Duration { |  | ||||||
| 	if c.RetryMaxBackoff == nil { |  | ||||||
| 		return DefaultRetryMaxBackoff |  | ||||||
| 	} |  | ||||||
| 	return *c.RetryMaxBackoff |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (c *SubscribeConfigDefaults) NewRetryBackoff() *backoff.Backoff { |  | ||||||
| 	return backoff.NewBackoff(c.GetRetries(), c.GetRetryMinBackoff(), c.GetRetryMaxBackoff()) |  | ||||||
| } |  | ||||||
| @@ -1,239 +0,0 @@ | |||||||
| // Copyright (c) HashiCorp, Inc. |  | ||||||
| // SPDX-License-Identifier: BUSL-1.1 |  | ||||||
|  |  | ||||||
| package sqs |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"sync" |  | ||||||
|  |  | ||||||
| 	"github.com/aws/aws-sdk-go/aws/awserr" |  | ||||||
| 	"github.com/aws/aws-sdk-go/service/sqs" |  | ||||||
| 	"github.com/hashicorp/go-secure-stdlib/awsutil" |  | ||||||
| 	"github.com/hashicorp/vault/plugins/event" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" |  | ||||||
| 	"github.com/hashicorp/vault/version" |  | ||||||
| 	"github.com/mitchellh/mapstructure" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	_ event.Factory            = New |  | ||||||
| 	_ event.SubscriptionPlugin = (*sqsBackend)(nil) |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| const pluginName = "sqs" |  | ||||||
|  |  | ||||||
| // ErrQueueRequired is returned if the required queue parameters are not present. |  | ||||||
| var ErrQueueRequired = errors.New("queue_name or queue_url must be specified") |  | ||||||
|  |  | ||||||
| // New returns a new instance of the SQS plugin backend. |  | ||||||
| func New(_ context.Context) (event.SubscriptionPlugin, error) { |  | ||||||
| 	return &sqsBackend{ |  | ||||||
| 		connections: map[string]*sqsConnection{}, |  | ||||||
| 	}, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type sqsBackend struct { |  | ||||||
| 	connections map[string]*sqsConnection |  | ||||||
| 	clientLock  sync.RWMutex |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type sqsConnection struct { |  | ||||||
| 	client   *sqs.SQS |  | ||||||
| 	config   *sqsConfig |  | ||||||
| 	queueURL string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type sqsConfig struct { |  | ||||||
| 	event.SubscribeConfigDefaults |  | ||||||
| 	CreateQueue     bool   `mapstructure:"create_queue"` |  | ||||||
| 	AccessKeyID     string `mapstructure:"access_key_id"` |  | ||||||
| 	SecretAccessKey string `mapstructure:"secret_access_key"` |  | ||||||
| 	Region          string `mapstructure:"region"` |  | ||||||
| 	QueueName       string `mapstructure:"queue_name"` |  | ||||||
| 	QueueURL        string `mapstructure:"queue_url"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func newClient(sconfig *sqsConfig) (*sqs.SQS, error) { |  | ||||||
| 	var options []awsutil.Option |  | ||||||
| 	if sconfig.AccessKeyID != "" && sconfig.SecretAccessKey != "" { |  | ||||||
| 		options = append(options, awsutil.WithAccessKey(sconfig.AccessKeyID)) |  | ||||||
| 		options = append(options, awsutil.WithSecretKey(sconfig.SecretAccessKey)) |  | ||||||
| 	} |  | ||||||
| 	if sconfig.Region != "" { |  | ||||||
| 		options = append(options, awsutil.WithRegion(sconfig.Region)) |  | ||||||
| 	} |  | ||||||
| 	options = append(options, awsutil.WithEnvironmentCredentials(true)) |  | ||||||
| 	options = append(options, awsutil.WithSharedCredentials(true)) |  | ||||||
| 	credConfig, err := awsutil.NewCredentialsConfig(options...) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	session, err := credConfig.GetSession() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return sqs.New(session), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) Subscribe(_ context.Context, request *event.SubscribeRequest) error { |  | ||||||
| 	var sconfig sqsConfig |  | ||||||
| 	err := mapstructure.Decode(request.Config, &sconfig) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if sconfig.QueueName == "" && sconfig.QueueURL == "" { |  | ||||||
| 		return ErrQueueRequired |  | ||||||
| 	} |  | ||||||
| 	client, err := newClient(&sconfig) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	var queueURL string |  | ||||||
| 	if sconfig.CreateQueue && sconfig.QueueName != "" { |  | ||||||
| 		resp, err := client.CreateQueue(&sqs.CreateQueueInput{ |  | ||||||
| 			QueueName: &sconfig.QueueName, |  | ||||||
| 		}) |  | ||||||
| 		var aerr awserr.Error |  | ||||||
| 		if errors.As(err, &aerr) { |  | ||||||
| 			if aerr.Code() == sqs.ErrCodeQueueNameExists { |  | ||||||
| 				// that's okay |  | ||||||
| 				err = nil |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if resp == nil || resp.QueueUrl == nil { |  | ||||||
| 			return fmt.Errorf("invalid response from AWS: missing queue URL") |  | ||||||
| 		} |  | ||||||
| 		queueURL = *resp.QueueUrl |  | ||||||
| 	} else if sconfig.QueueURL != "" { |  | ||||||
| 		queueURL = sconfig.QueueURL |  | ||||||
| 	} else { |  | ||||||
| 		resp, err := client.GetQueueUrl(&sqs.GetQueueUrlInput{ |  | ||||||
| 			QueueName: &sconfig.QueueName, |  | ||||||
| 		}) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		if resp == nil || resp.QueueUrl == nil { |  | ||||||
| 			return fmt.Errorf("invalid response from AWS: missing queue URL") |  | ||||||
| 		} |  | ||||||
| 		queueURL = *resp.QueueUrl |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	conn := &sqsConnection{ |  | ||||||
| 		client:   client, |  | ||||||
| 		config:   &sconfig, |  | ||||||
| 		queueURL: queueURL, |  | ||||||
| 	} |  | ||||||
| 	s.clientLock.Lock() |  | ||||||
| 	defer s.clientLock.Unlock() |  | ||||||
| 	if _, ok := s.connections[request.SubscriptionID]; ok { |  | ||||||
| 		s.killConnectionWithLock(request.SubscriptionID) |  | ||||||
| 	} |  | ||||||
| 	s.connections[request.SubscriptionID] = conn |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) killConnection(subscriptionID string) { |  | ||||||
| 	s.clientLock.Lock() |  | ||||||
| 	defer s.clientLock.Unlock() |  | ||||||
| 	s.killConnectionWithLock(subscriptionID) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) killConnectionWithLock(subscriptionID string) { |  | ||||||
| 	delete(s.connections, subscriptionID) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) getConn(subscriptionID string) (*sqsConnection, error) { |  | ||||||
| 	s.clientLock.RLock() |  | ||||||
| 	defer s.clientLock.RUnlock() |  | ||||||
| 	conn, ok := s.connections[subscriptionID] |  | ||||||
| 	if !ok { |  | ||||||
| 		return nil, fmt.Errorf("invalid subscription_id") |  | ||||||
| 	} |  | ||||||
| 	return conn, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) Send(_ context.Context, send *event.SendRequest) error { |  | ||||||
| 	return s.sendSubscriptionEventInternal(send.SubscriptionID, send.EventJSON, false) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) refreshClient(subscriptionID string) error { |  | ||||||
| 	conn, err := s.getConn(subscriptionID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	client, err := newClient(conn.config) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	s.clientLock.Lock() |  | ||||||
| 	defer s.clientLock.Unlock() |  | ||||||
| 	conn.client = client |  | ||||||
| 	// probably not necessary, but just in case |  | ||||||
| 	s.connections[subscriptionID] = conn |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) sendSubscriptionEventInternal(subscriptionID string, eventJson string, isRetry bool) error { |  | ||||||
| 	conn, err := s.getConn(subscriptionID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	backoff := conn.config.NewRetryBackoff() |  | ||||||
| 	err = backoff.Retry(func() error { |  | ||||||
| 		_, err = conn.client.SendMessage(&sqs.SendMessageInput{ |  | ||||||
| 			MessageBody: &eventJson, |  | ||||||
| 			QueueUrl:    &conn.queueURL, |  | ||||||
| 		}) |  | ||||||
| 		return err |  | ||||||
| 	}) |  | ||||||
| 	if err != nil && !isRetry { |  | ||||||
| 		// refresh client and try again, once |  | ||||||
| 		err2 := s.refreshClient(subscriptionID) |  | ||||||
| 		if err2 != nil { |  | ||||||
| 			return errors.Join(err, err2) |  | ||||||
| 		} |  | ||||||
| 		return s.sendSubscriptionEventInternal(subscriptionID, eventJson, true) |  | ||||||
| 	} else if err != nil && isRetry { |  | ||||||
| 		s.killConnection(subscriptionID) |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) Unsubscribe(_ context.Context, request *event.UnsubscribeRequest) error { |  | ||||||
| 	s.killConnection(request.SubscriptionID) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) PluginMetadata() *event.PluginMetadata { |  | ||||||
| 	return &event.PluginMetadata{ |  | ||||||
| 		Name:    pluginName, |  | ||||||
| 		Version: version.GetVersion().Version, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) PluginVersion() logical.PluginVersion { |  | ||||||
| 	return logical.PluginVersion{ |  | ||||||
| 		Version: version.GetVersion().Version, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *sqsBackend) Close(_ context.Context) error { |  | ||||||
| 	s.clientLock.Lock() |  | ||||||
| 	defer s.clientLock.Unlock() |  | ||||||
| 	var subscriptions []string |  | ||||||
| 	for k := range s.connections { |  | ||||||
| 		subscriptions = append(subscriptions, k) |  | ||||||
| 	} |  | ||||||
| 	for _, subscription := range subscriptions { |  | ||||||
| 		s.killConnectionWithLock(subscription) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| @@ -1,118 +0,0 @@ | |||||||
| // Copyright (c) HashiCorp, Inc. |  | ||||||
| // SPDX-License-Identifier: BUSL-1.1 |  | ||||||
|  |  | ||||||
| package sqs |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"os" |  | ||||||
| 	"testing" |  | ||||||
|  |  | ||||||
| 	"github.com/aws/aws-sdk-go-v2/config" |  | ||||||
| 	"github.com/aws/aws-sdk-go-v2/service/sqs" |  | ||||||
| 	"github.com/hashicorp/go-uuid" |  | ||||||
| 	"github.com/hashicorp/vault/plugins/event" |  | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func getTestClient(t *testing.T) *sqs.Client { |  | ||||||
| 	awsConfig, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(os.Getenv("AWS_REGION"))) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	return sqs.NewFromConfig(awsConfig) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func createQueue(t *testing.T, client *sqs.Client, queueName string) string { |  | ||||||
| 	resp, err := client.CreateQueue(context.Background(), &sqs.CreateQueueInput{ |  | ||||||
| 		QueueName: &queueName, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	return *resp.QueueUrl |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func deleteQueue(t *testing.T, client *sqs.Client, queueURL string) { |  | ||||||
| 	_, err := client.DeleteQueue(context.Background(), &sqs.DeleteQueueInput{ |  | ||||||
| 		QueueUrl: &queueURL, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func receiveMessage(t *testing.T, client *sqs.Client, queueURL string) string { |  | ||||||
| 	resp, err := client.ReceiveMessage(context.Background(), &sqs.ReceiveMessageInput{ |  | ||||||
| 		QueueUrl:        &queueURL, |  | ||||||
| 		WaitTimeSeconds: 5, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	assert.Len(t, resp.Messages, 1) |  | ||||||
| 	msg := resp.Messages[0] |  | ||||||
| 	_, err = client.DeleteMessage(context.Background(), &sqs.DeleteMessageInput{ |  | ||||||
| 		QueueUrl:      &queueURL, |  | ||||||
| 		ReceiptHandle: msg.ReceiptHandle, |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 	return *msg.Body |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // TestSQS_SendOneMessage tests that the plugin basic flow of subscribe/sendevent/unsubscribe will send a message to SQS. |  | ||||||
| func TestSQS_SendOneMessage(t *testing.T) { |  | ||||||
| 	region := os.Getenv("AWS_REGION") |  | ||||||
| 	if region == "" { |  | ||||||
| 		t.Skip("Must set AWS_REGION") |  | ||||||
| 	} |  | ||||||
| 	sqsClient := getTestClient(t) |  | ||||||
| 	temp, err := uuid.GenerateUUID() |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
| 	tempQueueName := "event-sqs-test-" + temp |  | ||||||
| 	tempQueueURL := createQueue(t, sqsClient, tempQueueName) |  | ||||||
| 	t.Cleanup(func() { |  | ||||||
| 		deleteQueue(t, sqsClient, tempQueueURL) |  | ||||||
| 	}) |  | ||||||
|  |  | ||||||
| 	backend, _ := New(nil) |  | ||||||
| 	subID, err := uuid.GenerateUUID() |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
|  |  | ||||||
| 	err = backend.Subscribe(nil, &event.SubscribeRequest{ |  | ||||||
| 		SubscriptionID: subID, |  | ||||||
| 		Config: map[string]interface{}{ |  | ||||||
| 			"queue_name":   tempQueueName, |  | ||||||
| 			"region":       os.Getenv("AWS_REGION"), |  | ||||||
| 			"create_queue": true, |  | ||||||
| 		}, |  | ||||||
| 		VerifyConnection: false, |  | ||||||
| 	}) |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
|  |  | ||||||
| 	// create another subscription with the same queue to make sure we are okay with using an existing queue |  | ||||||
| 	err = backend.Subscribe(nil, &event.SubscribeRequest{ |  | ||||||
| 		SubscriptionID: subID + "2", |  | ||||||
| 		Config: map[string]interface{}{ |  | ||||||
| 			"queue_name":   tempQueueName, |  | ||||||
| 			"region":       os.Getenv("AWS_REGION"), |  | ||||||
| 			"create_queue": true, |  | ||||||
| 		}, |  | ||||||
| 		VerifyConnection: false, |  | ||||||
| 	}) |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
|  |  | ||||||
| 	err = backend.Send(nil, &event.SendRequest{ |  | ||||||
| 		SubscriptionID: subID, |  | ||||||
| 		EventJSON:      "{}", |  | ||||||
| 	}) |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
|  |  | ||||||
| 	msg := receiveMessage(t, sqsClient, tempQueueURL) |  | ||||||
| 	assert.Equal(t, "{}", msg) |  | ||||||
|  |  | ||||||
| 	err = backend.Unsubscribe(nil, &event.UnsubscribeRequest{SubscriptionID: subID}) |  | ||||||
| 	assert.Nil(t, err) |  | ||||||
| } |  | ||||||
| @@ -50,7 +50,6 @@ import ( | |||||||
| 	"github.com/hashicorp/vault/helper/namespace" | 	"github.com/hashicorp/vault/helper/namespace" | ||||||
| 	"github.com/hashicorp/vault/helper/osutil" | 	"github.com/hashicorp/vault/helper/osutil" | ||||||
| 	"github.com/hashicorp/vault/physical/raft" | 	"github.com/hashicorp/vault/physical/raft" | ||||||
| 	"github.com/hashicorp/vault/plugins/event" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/certutil" | 	"github.com/hashicorp/vault/sdk/helper/certutil" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/consts" | 	"github.com/hashicorp/vault/sdk/helper/consts" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/jsonutil" | 	"github.com/hashicorp/vault/sdk/helper/jsonutil" | ||||||
| @@ -322,9 +321,6 @@ type Core struct { | |||||||
| 	// auditBackends is the mapping of backends to use for this core | 	// auditBackends is the mapping of backends to use for this core | ||||||
| 	auditBackends map[string]audit.Factory | 	auditBackends map[string]audit.Factory | ||||||
|  |  | ||||||
| 	// eventBackends is the mapping of event plugins to use for this core |  | ||||||
| 	eventBackends map[string]event.Factory |  | ||||||
|  |  | ||||||
| 	// stateLock protects mutable state | 	// stateLock protects mutable state | ||||||
| 	stateLock locking.RWMutex | 	stateLock locking.RWMutex | ||||||
| 	sealed    *uint32 | 	sealed    *uint32 | ||||||
| @@ -764,8 +760,6 @@ type CoreConfig struct { | |||||||
|  |  | ||||||
| 	AuditBackends map[string]audit.Factory | 	AuditBackends map[string]audit.Factory | ||||||
|  |  | ||||||
| 	EventBackends map[string]event.Factory |  | ||||||
|  |  | ||||||
| 	Physical physical.Backend | 	Physical physical.Backend | ||||||
|  |  | ||||||
| 	StorageType string | 	StorageType string | ||||||
| @@ -1282,9 +1276,6 @@ func NewCore(conf *CoreConfig) (*Core, error) { | |||||||
| 	// Audit backends | 	// Audit backends | ||||||
| 	c.configureAuditBackends(conf.AuditBackends) | 	c.configureAuditBackends(conf.AuditBackends) | ||||||
|  |  | ||||||
| 	// Event plugins |  | ||||||
| 	c.configureEventBackends(conf.EventBackends) |  | ||||||
|  |  | ||||||
| 	// UI | 	// UI | ||||||
| 	uiStoragePrefix := systemBarrierPrefix + "ui" | 	uiStoragePrefix := systemBarrierPrefix + "ui" | ||||||
| 	c.uiConfig = NewUIConfig(conf.EnableUI, physical.NewView(c.physical, uiStoragePrefix), NewBarrierView(c.barrier, uiStoragePrefix)) | 	c.uiConfig = NewUIConfig(conf.EnableUI, physical.NewView(c.physical, uiStoragePrefix), NewBarrierView(c.barrier, uiStoragePrefix)) | ||||||
| @@ -1446,19 +1437,6 @@ func (c *Core) configureLogicalBackends(backends map[string]logical.Factory, log | |||||||
| 	c.addExtraLogicalBackends(adminNamespacePath) | 	c.addExtraLogicalBackends(adminNamespacePath) | ||||||
| } | } | ||||||
|  |  | ||||||
| // configureEventBackends configures the Core with the ability to create |  | ||||||
| // event backends for various types. |  | ||||||
| func (c *Core) configureEventBackends(backends map[string]event.Factory) { |  | ||||||
| 	eventBackends := make(map[string]event.Factory, len(backends)) |  | ||||||
| 	for k, f := range backends { |  | ||||||
| 		eventBackends[k] = f |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	c.eventBackends = eventBackends |  | ||||||
|  |  | ||||||
| 	c.addExtraEventBackends() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // handleVersionTimeStamps stores the current version at the current time to | // handleVersionTimeStamps stores the current version at the current time to | ||||||
| // storage, and then loads all versions and upgrade timestamps out from storage. | // storage, and then loads all versions and upgrade timestamps out from storage. | ||||||
| func (c *Core) handleVersionTimeStamps(ctx context.Context) error { | func (c *Core) handleVersionTimeStamps(ctx context.Context) error { | ||||||
|   | |||||||
| @@ -1,30 +0,0 @@ | |||||||
| // Copyright (c) HashiCorp, Inc. |  | ||||||
| // SPDX-License-Identifier: BUSL-1.1 |  | ||||||
|  |  | ||||||
| package vault |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"net/http" |  | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/sdk/framework" |  | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // handleEventsSubscribe |  | ||||||
| func (b *SystemBackend) handleEventsSubscribe(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { |  | ||||||
| 	// TODO |  | ||||||
| 	return logical.RespondWithStatusCode(nil, req, http.StatusNoContent) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // handleEventsUnsubscribe |  | ||||||
| func (b *SystemBackend) handleEventsUnsubscribe(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { |  | ||||||
| 	// TODO |  | ||||||
| 	return logical.RespondWithStatusCode(nil, req, http.StatusNoContent) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // handleEventsListSubscriptions |  | ||||||
| func (b *SystemBackend) handleEventsListSubscriptions(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { |  | ||||||
| 	// TODO |  | ||||||
| 	return logical.RespondWithStatusCode(nil, req, http.StatusNoContent) |  | ||||||
| } |  | ||||||
| @@ -5075,111 +5075,6 @@ func (b *SystemBackend) lockedUserPaths() []*framework.Path { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *SystemBackend) eventPaths() []*framework.Path { |  | ||||||
| 	return []*framework.Path{ |  | ||||||
| 		{ |  | ||||||
| 			Pattern: "events/subscriptions$", |  | ||||||
|  |  | ||||||
| 			DisplayAttrs: &framework.DisplayAttributes{ |  | ||||||
| 				OperationPrefix: "subscriptions", |  | ||||||
| 				OperationVerb:   "create", |  | ||||||
| 			}, |  | ||||||
|  |  | ||||||
| 			Fields: map[string]*framework.FieldSchema{ |  | ||||||
| 				"config": { |  | ||||||
| 					Type:     framework.TypeMap, |  | ||||||
| 					Required: true, |  | ||||||
| 					// Description: strings.TrimSpace(sysHelp["mount_accessor"][0]), |  | ||||||
| 				}, |  | ||||||
| 				"plugin": { |  | ||||||
| 					Type:     framework.TypeString, |  | ||||||
| 					Required: true, |  | ||||||
| 				}, |  | ||||||
| 				//"alias_identifier": { |  | ||||||
| 				//	Type: framework.TypeString, |  | ||||||
| 				//	// Description: strings.TrimSpace(sysHelp["alias_identifier"][0]), |  | ||||||
| 				//}, |  | ||||||
| 			}, |  | ||||||
|  |  | ||||||
| 			Operations: map[logical.Operation]framework.OperationHandler{ |  | ||||||
| 				logical.UpdateOperation: &framework.PathOperation{ |  | ||||||
| 					Callback: b.handleEventsSubscribe, |  | ||||||
| 					Summary:  "", |  | ||||||
| 					Responses: map[int][]framework.Response{ |  | ||||||
| 						http.StatusOK: {{ |  | ||||||
| 							Description: "OK", |  | ||||||
| 							Fields: map[string]*framework.FieldSchema{ |  | ||||||
| 								"id": { |  | ||||||
| 									Type:     framework.TypeString, |  | ||||||
| 									Required: true, |  | ||||||
| 								}, |  | ||||||
| 							}, |  | ||||||
| 						}}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			// HelpSynopsis:    strings.TrimSpace(sysHelp["unlock_user"][0]), |  | ||||||
| 			// HelpDescription: strings.TrimSpace(sysHelp["unlock_user"][1]), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			Pattern: "events/subscriptions/(?P<plugin>.+)/(?P<id>.+)", |  | ||||||
|  |  | ||||||
| 			DisplayAttrs: &framework.DisplayAttributes{ |  | ||||||
| 				OperationPrefix: "subscriptions", |  | ||||||
| 				OperationVerb:   "create", |  | ||||||
| 			}, |  | ||||||
|  |  | ||||||
| 			Fields: map[string]*framework.FieldSchema{ |  | ||||||
| 				"plugin": { |  | ||||||
| 					Type: framework.TypeString, |  | ||||||
| 				}, |  | ||||||
| 				"id": { |  | ||||||
| 					Type: framework.TypeString, |  | ||||||
| 					// Description: strings.TrimSpace(sysHelp["mount_accessor"][0]), |  | ||||||
| 				}, |  | ||||||
| 				"list": { |  | ||||||
| 					Type: framework.TypeBool, |  | ||||||
| 				}, |  | ||||||
| 				//"alias_identifier": { |  | ||||||
| 				//	Type: framework.TypeString, |  | ||||||
| 				//	// Description: strings.TrimSpace(sysHelp["alias_identifier"][0]), |  | ||||||
| 				//}, |  | ||||||
| 			}, |  | ||||||
| 			Operations: map[logical.Operation]framework.OperationHandler{ |  | ||||||
| 				logical.ListOperation: &framework.PathOperation{ |  | ||||||
| 					Callback: b.handleEventsListSubscriptions, |  | ||||||
| 					Summary:  "", |  | ||||||
| 					Responses: map[int][]framework.Response{ |  | ||||||
| 						http.StatusNoContent: {{ |  | ||||||
| 							Description: "OK", |  | ||||||
| 						}}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 				logical.ReadOperation: &framework.PathOperation{ |  | ||||||
| 					Callback: b.handleEventsListSubscriptions, |  | ||||||
| 					Summary:  "", |  | ||||||
| 					Responses: map[int][]framework.Response{ |  | ||||||
| 						http.StatusNoContent: {{ |  | ||||||
| 							Description: "OK", |  | ||||||
| 						}}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 				logical.DeleteOperation: &framework.PathOperation{ |  | ||||||
| 					Callback: b.handleEventsUnsubscribe, |  | ||||||
| 					Summary:  "", |  | ||||||
| 					Responses: map[int][]framework.Response{ |  | ||||||
| 						http.StatusNoContent: {{ |  | ||||||
| 							Description: "OK", |  | ||||||
| 						}}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 			// HelpSynopsis:    strings.TrimSpace(sysHelp["unlock_user"][0]), |  | ||||||
| 			// HelpDescription: strings.TrimSpace(sysHelp["unlock_user"][1]), |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (b *SystemBackend) wellKnownPaths() []*framework.Path { | func (b *SystemBackend) wellKnownPaths() []*framework.Path { | ||||||
| 	return []*framework.Path{ | 	return []*framework.Path{ | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user