-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interface for event subscription plugins; SQS plugin #24352
Conversation
CI Results: |
sdk/eventplugin/eventplugin.proto
Outdated
string eventJson = 2; | ||
} | ||
|
||
message SubscribeRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to subscribe to a grouping of events, or is each one a separate thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's flexible -- this is a low-level interface that is more about plumbing events to SQS (e.g.), but it will depend on how we want to configure the endpoint that matches up event topics / bexpr to the subscription.
My current inclination is to support globs in the event topic and bexpr, similar to how we do websockets, so that the interfaces are similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will we reference a particular events plugin mount in that matching up endpoint, and where in the API are we hosting this? Will it all be in the sys/ mount? In particular, secrets engines give us a bit of a headache because they can occupy basically any path that isn't already reserved for e.g. auth/ or sys/
da162db
to
bad8e6d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay reviewing, left some thoughts and questions. I'd be interested to understand the plans for plumbing events into this interface in a bit more detail, I don't have a great feel for the whole flow yet.
sdk/eventplugin/eventplugin.proto
Outdated
string eventJson = 2; | ||
} | ||
|
||
message SubscribeRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will we reference a particular events plugin mount in that matching up endpoint, and where in the API are we hosting this? Will it all be in the sys/ mount? In particular, secrets engines give us a bit of a headache because they can occupy basically any path that isn't already reserved for e.g. auth/ or sys/
sdk/eventplugin/eventplugin.proto
Outdated
rpc Initialize(InitializeRequest) returns (InitializeResponse); | ||
// Start a new subscription. | ||
rpc Subscribe(SubscribeRequest) returns (SubscribeResponse); | ||
// Used by Vault to send events to a subscription. Only one stream is allowed per subscription. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to get my head around the model here - do we envisage mounting events plugins like other plugins, or is there only ever going to be a single instance of them and they'll handle multiple subscriptions?
Then there's a 1-1 mapping between subscription and stream - is there any case where a stream will restart or is closing a stream tantamount to calling Unsubscribe?
And there's going to be a many:many mapping from event filters to subscriptions that's not defined in this PR right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, there's a 1-1 mapping between subscriptions and plugin instances, but I wanted to leave the interface flexible about that, so that it could potentially support multiplexing natively without having to be retrofitted later.
I think closing the stream and unsubscribing should be synonymous.
And yes, a subscription will allow (potentially many) event type globs + event filters mapped to a subscription.
bad8e6d
to
5f87693
Compare
@tomhjp My current thinking is that this isn't a mount, but more like how the database plugin works: you configure a new subscription, which specifies the event sub-plugin you want (like SQS) along with the event type glob and event filter, and then the event system/backend will manage the plugin instance and route everything. This will be the next PR, I think. |
Build Results: |
"github.com/hashicorp/vault/sdk/logical" | ||
) | ||
|
||
type EventSubscriptionPlugin interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the plugin interface and proto definition should probably live in plugins/event
until we enable external plugins, otherwise it becomes part of our external facing API unnecessarily early.
options = append(options, awsutil.WithRegion(sconfig.Region)) | ||
} | ||
options = append(options, awsutil.WithEnvironmentCredentials(true)) | ||
credConfig, err := awsutil.NewCredentialsConfig(options...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right that NewCredentialsConfig
doesn't support WithEnvironmentCredentials
from what I'm seeing. I'm not exactly sure what the motivation for that was. The only place the option is applied is within GenerateCredentialChain
. I think you can also pass it through via GetSession
.
I wish awsutil
was more opinionated to help with consistency. A good start that's consistent with most AWS integrations would be to make sure the following credentials providers are in the chain (in order):
1.credentials.StaticProvider
2. credentials.EnvProvider
3. credentials.SharedCredentialsProvider
I do think it'd be worth checking out awsutil/v2
to get ahead of a potential future migration.
Looking to get feedback on how this is looking so far. I've sketched out a plugin interface for how event subscription plugins would work, that is, a plugin that would grab events from Vault's event bus and publish them to an external place. (Perhaps calling them event publish plugins would be better?) As a POC, I've started sketching what such a plugin would look like for AWS SQS.
And rename Type() to PluginName() and PluginVersion()
Co-authored-by: Tom Proctor <[email protected]>
7c16b13
to
6954046
Compare
I realized that I probably could use |
Okay, this is ready for review again.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good 👍 I think we should spin out a separate ticket to look at updates we need to make to the awsutil
library based on the use-case here, as it would be nice to get there eventually but it shouldn't block the rest of the PR.
@@ -185,6 +187,10 @@ var ( | |||
"plugin": plugin.Factory, | |||
} | |||
|
|||
eventBackends = map[string]event.Factory{ | |||
"sqs": sqs.New, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really matter right now, but just FYI we'll want to move this to helper/builtinplugins/registry.go
instead when we enable external plugins. It's one of the most confusing parts of how plugins are configured, but these plugin maps just cover the plugins that can't be overridden or registered externally - the mounting code completely skips checking the plugin registry if it finds an entry here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack. It is definitely confusing :)
plugins/event/sqs/sqs.go
Outdated
if !ok { | ||
return | ||
} | ||
conn.ctxCancelFunc() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this will ever have an effect on network calls, because we only ever set the ctx
in the connection struct, and never use it. I think there are two contexts we care about for cancelling in-flight requests; this one for the whole subscription ID and the per-request ctx
that gets passed with the Send method call. However, neither ctx
is passed into the retry loop's logic or API call currently AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right, we never use the context. I think in a previous iteration we did, but I simplified the logic and left the context in still.
I'll go ahead and remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be really nice to be able to cancel/timeout in-flight requests, but I'm ok with deferring that for now as it seems a little tied up in the v1/v2 package concerns. Please could we also track that as part of the ticket for updating to v2 awsutil and sdk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Thanks! |
Initial version of an internal plugin interface for event subscription plugins, and an AWS SQS plugin as an example. Co-authored-by: Tom Proctor <[email protected]>
Looking to get feedback on how this is looking so far.
I've sketched out a plugin interface for how event subscription plugins would work, that is, a plugin that would grab events from Vault's event bus and publish them to an external place.
(Perhaps calling them event publish plugins would be better?)
As a POC, I've started sketching what such a plugin would look like for AWS SQS.