Skip to content
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

Merged
merged 15 commits into from
Feb 5, 2024

Conversation

swenson
Copy link
Contributor

@swenson swenson commented Dec 4, 2023

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.

@swenson swenson requested a review from a team December 4, 2023 19:28
@github-actions github-actions bot added the hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed label Dec 4, 2023
Copy link

github-actions bot commented Dec 4, 2023

CI Results:
All Go tests succeeded! ✅

string eventJson = 2;
}

message SubscribeRequest {
Copy link
Collaborator

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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/

@swenson swenson force-pushed the vault-16977/event-plugin-interface branch from da162db to bad8e6d Compare January 2, 2024 18:28
Copy link
Contributor

@tomhjp tomhjp left a 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.

string eventJson = 2;
}

message SubscribeRequest {
Copy link
Contributor

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/

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.
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@swenson swenson force-pushed the vault-16977/event-plugin-interface branch from bad8e6d to 5f87693 Compare January 5, 2024 18:51
@swenson
Copy link
Contributor Author

swenson commented Jan 5, 2024

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/

@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.

@swenson swenson marked this pull request as ready for review January 5, 2024 20:04
@swenson swenson requested a review from a team as a code owner January 5, 2024 20:04
@swenson swenson added this to the 1.16.0-rc1 milestone Jan 5, 2024
Copy link

github-actions bot commented Jan 5, 2024

Build Results:
All builds succeeded! ✅

@swenson swenson changed the title Draft interface for event subscription plugins Interface for event subscription plugins; SQS plugin Jan 9, 2024
"github.com/hashicorp/vault/sdk/logical"
)

type EventSubscriptionPlugin interface {
Copy link
Contributor

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...)
Copy link
Contributor

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.

Christopher Swenson and others added 11 commits January 31, 2024 14:02
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()
@swenson swenson force-pushed the vault-16977/event-plugin-interface branch from 7c16b13 to 6954046 Compare January 31, 2024 22:05
@swenson
Copy link
Contributor Author

swenson commented Jan 31, 2024

I realized that I probably could use awsutil/v2, so I'm going to rework this to pull that in if I can.

@swenson
Copy link
Contributor Author

swenson commented Jan 31, 2024

Okay, this is ready for review again.

  • I've decided not to go with awsutil/v2 for now, as it doesn't seem to support environment credentials, and in general I'm having a lot harder of a time getting it to be useful. (I kept finding myself not able to use the options it provides, or bypassing it since it does not have what we need.)
  • Even though the awsutil.NewCredentialsConfig says it does not support awsutil.WithEnvironmentCredentials, the credentials are correctly getting picked up from the environment. (Otherwise my tests would not pass when I run them.)

Copy link
Contributor

@tomhjp tomhjp left a 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,
Copy link
Contributor

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.

Copy link
Contributor Author

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 :)

if !ok {
return
}
conn.ctxCancelFunc()
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

@tomhjp tomhjp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@swenson
Copy link
Contributor Author

swenson commented Feb 5, 2024

Thanks!

@swenson swenson merged commit 8f6dfaa into main Feb 5, 2024
113 checks passed
@swenson swenson deleted the vault-16977/event-plugin-interface branch February 5, 2024 21:17
Monkeychip pushed a commit that referenced this pull request Feb 7, 2024
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants