JWT Authentication with service intentions: xds package update (#17414)

* JWT Authentication with service intentions: update xds package to translate config to envoy
This commit is contained in:
Ronald 2023-05-19 18:14:16 -04:00 committed by GitHub
parent 134aac7c26
commit 113202d541
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 3707 additions and 1304 deletions

View File

@ -426,6 +426,12 @@ func (c *FSM) registerStreamSnapshotHandlers() {
return c.State().SamenessGroupSnapshot(req, buf)
}, true)
panicIfErr(err)
err = c.deps.Publisher.RegisterHandler(state.EventTopicJWTProvider, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) {
return c.State().JWTProviderSnapshot(req, buf)
}, true)
panicIfErr(err)
}
func panicIfErr(err error) {

View File

@ -27,6 +27,7 @@ var configEntryKindToTopic = map[string]stream.Topic{
structs.BoundAPIGateway: EventTopicBoundAPIGateway,
structs.RateLimitIPConfig: EventTopicIPRateLimit,
structs.SamenessGroup: EventTopicSamenessGroup,
structs.JWTProvider: EventTopicJWTProvider,
}
// EventSubjectConfigEntry is a stream.Subject used to route and receive events
@ -169,6 +170,12 @@ func (s *Store) SamenessGroupSnapshot(req stream.SubscribeRequest, buf stream.Sn
return s.configEntrySnapshot(structs.SamenessGroup, req, buf)
}
// JWTProviderSnapshot is a stream.SnapshotFunc that returns a snapshot of
// jwt-provider config entries.
func (s *Store) JWTProviderSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) {
return s.configEntrySnapshot(structs.JWTProvider, req, buf)
}
func (s *Store) configEntrySnapshot(kind string, req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) {
var (
idx uint64

View File

@ -45,7 +45,7 @@ func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.E
}
case EventTopicMeshConfig, EventTopicServiceResolver, EventTopicIngressGateway,
EventTopicServiceIntentions, EventTopicServiceDefaults, EventTopicAPIGateway,
EventTopicTCPRoute, EventTopicHTTPRoute, EventTopicInlineCertificate,
EventTopicTCPRoute, EventTopicHTTPRoute, EventTopicJWTProvider, EventTopicInlineCertificate,
EventTopicBoundAPIGateway, EventTopicSamenessGroup:
subject = EventSubjectConfigEntry{
Name: named.Key,

View File

@ -211,6 +211,7 @@ var (
EventTopicBoundAPIGateway = pbsubscribe.Topic_BoundAPIGateway
EventTopicIPRateLimit = pbsubscribe.Topic_IPRateLimit
EventTopicSamenessGroup = pbsubscribe.Topic_SamenessGroup
EventTopicJWTProvider = pbsubscribe.Topic_JWTProvider
)
func processDBChanges(tx ReadTxn, changes Changes) ([]stream.Event, error) {

View File

@ -75,6 +75,8 @@ func newConfigEntryRequest(req *structs.ConfigEntryQuery, deps ServerDataSourceD
topic = pbsubscribe.Topic_BoundAPIGateway
case structs.RateLimitIPConfig:
topic = pbsubscribe.Topic_IPRateLimit
case structs.JWTProvider:
topic = pbsubscribe.Topic_JWTProvider
default:
return nil, fmt.Errorf("cannot map config entry kind: %q to a topic", req.Kind)
}

View File

@ -90,6 +90,20 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e
return snap, err
}
// Watch for JWT provider updates.
// While we could optimize by only watching providers referenced by intentions,
// this should be okay because we expect few JWT providers and infrequent JWT
// provider updates.
err = s.dataSources.ConfigEntryList.Notify(ctx, &structs.ConfigEntryQuery{
Kind: structs.JWTProvider,
Datacenter: s.source.Datacenter,
QueryOptions: structs.QueryOptions{Token: s.token},
EnterpriseMeta: *structs.DefaultEnterpriseMetaInPartition(s.proxyID.PartitionOrDefault()),
}, jwtProviderID, s.ch)
if err != nil {
return snap, err
}
// Get information about the entire service mesh.
err = s.dataSources.ConfigEntry.Notify(ctx, &structs.ConfigEntryQuery{
Kind: structs.MeshConfig,
@ -322,6 +336,23 @@ func (s *handlerConnectProxy) handleUpdate(ctx context.Context, u UpdateEvent, s
snap.ConnectProxy.Intentions = resp
snap.ConnectProxy.IntentionsSet = true
case u.CorrelationID == jwtProviderID:
resp, ok := u.Result.(*structs.IndexedConfigEntries)
if !ok {
return fmt.Errorf("invalid type for response: %T", u.Result)
}
providers := make(map[string]*structs.JWTProviderConfigEntry, len(resp.Entries))
for _, entry := range resp.Entries {
jwtEntry, ok := entry.(*structs.JWTProviderConfigEntry)
if !ok {
return fmt.Errorf("invalid type for response: %T", entry)
}
providers[jwtEntry.Name] = jwtEntry
}
snap.JWTProviders = providers
case u.CorrelationID == peeredUpstreamsID:
resp, ok := u.Result.(*structs.IndexedPeeredServiceList)
if !ok {

View File

@ -29,6 +29,77 @@ func (o *ConfigSnapshot) DeepCopy() *ConfigSnapshot {
retV := o.Proxy.DeepCopy()
cp.Proxy = *retV
}
if o.JWTProviders != nil {
cp.JWTProviders = make(map[string]*structs.JWTProviderConfigEntry, len(o.JWTProviders))
for k2, v2 := range o.JWTProviders {
var cp_JWTProviders_v2 *structs.JWTProviderConfigEntry
if v2 != nil {
cp_JWTProviders_v2 = new(structs.JWTProviderConfigEntry)
*cp_JWTProviders_v2 = *v2
if v2.JSONWebKeySet != nil {
cp_JWTProviders_v2.JSONWebKeySet = new(structs.JSONWebKeySet)
*cp_JWTProviders_v2.JSONWebKeySet = *v2.JSONWebKeySet
if v2.JSONWebKeySet.Local != nil {
cp_JWTProviders_v2.JSONWebKeySet.Local = new(structs.LocalJWKS)
*cp_JWTProviders_v2.JSONWebKeySet.Local = *v2.JSONWebKeySet.Local
}
if v2.JSONWebKeySet.Remote != nil {
cp_JWTProviders_v2.JSONWebKeySet.Remote = new(structs.RemoteJWKS)
*cp_JWTProviders_v2.JSONWebKeySet.Remote = *v2.JSONWebKeySet.Remote
if v2.JSONWebKeySet.Remote.RetryPolicy != nil {
cp_JWTProviders_v2.JSONWebKeySet.Remote.RetryPolicy = new(structs.JWKSRetryPolicy)
*cp_JWTProviders_v2.JSONWebKeySet.Remote.RetryPolicy = *v2.JSONWebKeySet.Remote.RetryPolicy
if v2.JSONWebKeySet.Remote.RetryPolicy.RetryPolicyBackOff != nil {
cp_JWTProviders_v2.JSONWebKeySet.Remote.RetryPolicy.RetryPolicyBackOff = new(structs.RetryPolicyBackOff)
*cp_JWTProviders_v2.JSONWebKeySet.Remote.RetryPolicy.RetryPolicyBackOff = *v2.JSONWebKeySet.Remote.RetryPolicy.RetryPolicyBackOff
}
}
}
}
if v2.Audiences != nil {
cp_JWTProviders_v2.Audiences = make([]string, len(v2.Audiences))
copy(cp_JWTProviders_v2.Audiences, v2.Audiences)
}
if v2.Locations != nil {
cp_JWTProviders_v2.Locations = make([]*structs.JWTLocation, len(v2.Locations))
copy(cp_JWTProviders_v2.Locations, v2.Locations)
for i5 := range v2.Locations {
if v2.Locations[i5] != nil {
cp_JWTProviders_v2.Locations[i5] = new(structs.JWTLocation)
*cp_JWTProviders_v2.Locations[i5] = *v2.Locations[i5]
if v2.Locations[i5].Header != nil {
cp_JWTProviders_v2.Locations[i5].Header = new(structs.JWTLocationHeader)
*cp_JWTProviders_v2.Locations[i5].Header = *v2.Locations[i5].Header
}
if v2.Locations[i5].QueryParam != nil {
cp_JWTProviders_v2.Locations[i5].QueryParam = new(structs.JWTLocationQueryParam)
*cp_JWTProviders_v2.Locations[i5].QueryParam = *v2.Locations[i5].QueryParam
}
if v2.Locations[i5].Cookie != nil {
cp_JWTProviders_v2.Locations[i5].Cookie = new(structs.JWTLocationCookie)
*cp_JWTProviders_v2.Locations[i5].Cookie = *v2.Locations[i5].Cookie
}
}
}
}
if v2.Forwarding != nil {
cp_JWTProviders_v2.Forwarding = new(structs.JWTForwardingConfig)
*cp_JWTProviders_v2.Forwarding = *v2.Forwarding
}
if v2.CacheConfig != nil {
cp_JWTProviders_v2.CacheConfig = new(structs.JWTCacheConfig)
*cp_JWTProviders_v2.CacheConfig = *v2.CacheConfig
}
if v2.Meta != nil {
cp_JWTProviders_v2.Meta = make(map[string]string, len(v2.Meta))
for k5, v5 := range v2.Meta {
cp_JWTProviders_v2.Meta[k5] = v5
}
}
}
cp.JWTProviders[k2] = cp_JWTProviders_v2
}
}
if o.Roots != nil {
cp.Roots = o.Roots.DeepCopy()
}

View File

@ -1020,6 +1020,7 @@ type ConfigSnapshot struct {
Datacenter string
IntentionDefaultAllow bool
Locality GatewayKey
JWTProviders map[string]*structs.JWTProviderConfigEntry
ServerSNIFn ServerSNIFunc
Roots *structs.IndexedCARoots

View File

@ -44,6 +44,7 @@ const (
serviceResolverIDPrefix = "service-resolver:"
serviceIntentionsIDPrefix = "service-intentions:"
intentionUpstreamsID = "intention-upstreams"
jwtProviderID = "jwt-provider"
peerServersWatchID = "peer-servers"
peeredUpstreamsID = "peered-upstreams"
intentionUpstreamsDestinationID = "intention-upstreams-destination"

264
agent/xds/jwt_authn.go Normal file
View File

@ -0,0 +1,264 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package xds
import (
"encoding/base64"
"fmt"
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
envoy_http_jwt_authn_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3"
envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
"github.com/hashicorp/consul/agent/structs"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
func makeJWTAuthFilter(pCE map[string]*structs.JWTProviderConfigEntry, intentions structs.SimplifiedIntentions) (*envoy_http_v3.HttpFilter, error) {
providers := map[string]*envoy_http_jwt_authn_v3.JwtProvider{}
var rules []*envoy_http_jwt_authn_v3.RequirementRule
for _, intention := range intentions {
if intention.JWT == nil && !hasJWTconfig(intention.Permissions) {
continue
}
for _, jwtReq := range collectJWTRequirements(intention) {
if _, ok := providers[jwtReq.Name]; ok {
continue
}
jwtProvider, ok := pCE[jwtReq.Name]
if !ok {
return nil, fmt.Errorf("provider specified in intention does not exist. Provider name: %s", jwtReq.Name)
}
envoyCfg, err := buildJWTProviderConfig(jwtProvider)
if err != nil {
return nil, err
}
providers[jwtReq.Name] = envoyCfg
}
for _, perm := range intention.Permissions {
if perm.JWT == nil {
continue
}
for _, prov := range perm.JWT.Providers {
rule := buildRouteRule(prov, perm, "/")
rules = append(rules, rule)
}
}
if intention.JWT != nil {
for _, provider := range intention.JWT.Providers {
// The top-level provider applies to all requests.
// TODO(roncodingenthusiast): Handle provider.VerifyClaims
rule := buildRouteRule(provider, nil, "/")
rules = append(rules, rule)
}
}
}
if len(intentions) == 0 && len(providers) == 0 {
//do not add jwt_authn filter when intentions don't have JWT
return nil, nil
}
cfg := &envoy_http_jwt_authn_v3.JwtAuthentication{
Providers: providers,
Rules: rules,
}
return makeEnvoyHTTPFilter("envoy.filters.http.jwt_authn", cfg)
}
func collectJWTRequirements(i *structs.Intention) []*structs.IntentionJWTProvider {
var jReqs []*structs.IntentionJWTProvider
if i.JWT != nil {
jReqs = append(jReqs, i.JWT.Providers...)
}
jReqs = append(jReqs, getPermissionsProviders(i.Permissions)...)
return jReqs
}
func getPermissionsProviders(p []*structs.IntentionPermission) []*structs.IntentionJWTProvider {
intentionProviders := []*structs.IntentionJWTProvider{}
for _, perm := range p {
intentionProviders = append(intentionProviders, perm.JWT.Providers...)
}
return intentionProviders
}
func buildJWTProviderConfig(p *structs.JWTProviderConfigEntry) (*envoy_http_jwt_authn_v3.JwtProvider, error) {
envoyCfg := envoy_http_jwt_authn_v3.JwtProvider{
Issuer: p.Issuer,
Audiences: p.Audiences,
}
if p.Forwarding != nil {
envoyCfg.ForwardPayloadHeader = p.Forwarding.HeaderName
envoyCfg.PadForwardPayloadHeader = p.Forwarding.PadForwardPayloadHeader
}
if local := p.JSONWebKeySet.Local; local != nil {
specifier, err := makeLocalJWKS(local, p.Name)
if err != nil {
return nil, err
}
envoyCfg.JwksSourceSpecifier = specifier
} else if remote := p.JSONWebKeySet.Remote; remote.URI != "" {
specifier, err := makeRemoteJWKS(remote)
if err != nil {
return nil, err
}
envoyCfg.JwksSourceSpecifier = specifier
} else {
return nil, fmt.Errorf("invalid jwt provider config; missing JSONWebKeySet for provider: %s", p.Name)
}
for _, location := range p.Locations {
if location.Header != nil {
//only setting forward here because it is only useful for headers not the other options
envoyCfg.Forward = location.Header.Forward
envoyCfg.FromHeaders = append(envoyCfg.FromHeaders, &envoy_http_jwt_authn_v3.JwtHeader{
Name: location.Header.Name,
ValuePrefix: location.Header.ValuePrefix,
})
} else if location.QueryParam != nil {
envoyCfg.FromParams = append(envoyCfg.FromParams, location.QueryParam.Name)
} else if location.Cookie != nil {
envoyCfg.FromCookies = append(envoyCfg.FromCookies, location.Cookie.Name)
}
}
return &envoyCfg, nil
}
func makeLocalJWKS(l *structs.LocalJWKS, pName string) (*envoy_http_jwt_authn_v3.JwtProvider_LocalJwks, error) {
var specifier *envoy_http_jwt_authn_v3.JwtProvider_LocalJwks
if l.JWKS != "" {
decodedJWKS, err := base64.StdEncoding.DecodeString(l.JWKS)
if err != nil {
return nil, err
}
specifier = &envoy_http_jwt_authn_v3.JwtProvider_LocalJwks{
LocalJwks: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_InlineString{
InlineString: string(decodedJWKS),
},
},
}
} else if l.Filename != "" {
specifier = &envoy_http_jwt_authn_v3.JwtProvider_LocalJwks{
LocalJwks: &envoy_core_v3.DataSource{
Specifier: &envoy_core_v3.DataSource_Filename{
Filename: l.Filename,
},
},
}
} else {
return nil, fmt.Errorf("invalid jwt provider config; missing JWKS/Filename for local provider: %s", pName)
}
return specifier, nil
}
func makeRemoteJWKS(r *structs.RemoteJWKS) (*envoy_http_jwt_authn_v3.JwtProvider_RemoteJwks, error) {
remote_specifier := envoy_http_jwt_authn_v3.JwtProvider_RemoteJwks{
RemoteJwks: &envoy_http_jwt_authn_v3.RemoteJwks{
HttpUri: &envoy_core_v3.HttpUri{
Uri: r.URI,
// TODO(roncodingenthusiast): An explicit cluster is required.
// Need to figure out replacing `jwks_cluster` will an actual cluster
HttpUpstreamType: &envoy_core_v3.HttpUri_Cluster{Cluster: "jwks_cluster"},
},
AsyncFetch: &envoy_http_jwt_authn_v3.JwksAsyncFetch{
FastListener: r.FetchAsynchronously,
},
},
}
timeOutSecond := int64(r.RequestTimeoutMs) / 1000
remote_specifier.RemoteJwks.HttpUri.Timeout = &durationpb.Duration{Seconds: timeOutSecond}
cacheDuration := int64(r.CacheDuration)
if cacheDuration > 0 {
remote_specifier.RemoteJwks.CacheDuration = &durationpb.Duration{Seconds: cacheDuration}
}
p := buildJWTRetryPolicy(r.RetryPolicy)
if p != nil {
remote_specifier.RemoteJwks.RetryPolicy = p
}
return &remote_specifier, nil
}
func buildJWTRetryPolicy(r *structs.JWKSRetryPolicy) *envoy_core_v3.RetryPolicy {
var pol envoy_core_v3.RetryPolicy
if r == nil {
return nil
}
if r.RetryPolicyBackOff != nil {
pol.RetryBackOff = &envoy_core_v3.BackoffStrategy{
BaseInterval: structs.DurationToProto(r.RetryPolicyBackOff.BaseInterval),
MaxInterval: structs.DurationToProto(r.RetryPolicyBackOff.MaxInterval),
}
}
pol.NumRetries = &wrapperspb.UInt32Value{
Value: uint32(r.NumRetries),
}
return &pol
}
func buildRouteRule(provider *structs.IntentionJWTProvider, perm *structs.IntentionPermission, defaultPrefix string) *envoy_http_jwt_authn_v3.RequirementRule {
rule := &envoy_http_jwt_authn_v3.RequirementRule{
Match: &envoy_route_v3.RouteMatch{
PathSpecifier: &envoy_route_v3.RouteMatch_Prefix{Prefix: defaultPrefix},
},
RequirementType: &envoy_http_jwt_authn_v3.RequirementRule_Requires{
Requires: &envoy_http_jwt_authn_v3.JwtRequirement{
RequiresType: &envoy_http_jwt_authn_v3.JwtRequirement_ProviderName{
ProviderName: provider.Name,
},
},
},
}
if perm != nil {
if perm.HTTP.PathPrefix != "" {
rule.Match.PathSpecifier = &envoy_route_v3.RouteMatch_Prefix{
Prefix: perm.HTTP.PathPrefix,
}
}
if perm.HTTP.PathExact != "" {
rule.Match.PathSpecifier = &envoy_route_v3.RouteMatch_Path{
Path: perm.HTTP.PathExact,
}
}
if perm.HTTP.PathRegex != "" {
rule.Match.PathSpecifier = &envoy_route_v3.RouteMatch_SafeRegex{
SafeRegex: makeEnvoyRegexMatch(perm.HTTP.PathRegex),
}
}
}
return rule
}
func hasJWTconfig(p []*structs.IntentionPermission) bool {
for _, perm := range p {
if perm.JWT != nil {
return true
}
}
return false
}

146
agent/xds/jwt_authn_test.go Normal file
View File

@ -0,0 +1,146 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package xds
import (
"path/filepath"
"testing"
"github.com/hashicorp/consul/agent/structs"
"github.com/stretchr/testify/require"
)
func TestMakeJWTAUTHFilters(t *testing.T) {
type ixnOpts struct {
src string
action structs.IntentionAction
jwt *structs.IntentionJWTRequirement
perms *structs.IntentionPermission
}
testIntention := func(t *testing.T, opts ixnOpts) *structs.Intention {
t.Helper()
ixn := structs.TestIntention(t)
ixn.SourceName = opts.src
if opts.jwt != nil {
ixn.JWT = opts.jwt
}
if opts.perms != nil {
ixn.Permissions = append(ixn.Permissions, opts.perms)
} else {
ixn.Action = opts.action
}
return ixn
}
simplified := func(ixns ...*structs.Intention) structs.SimplifiedIntentions {
return structs.SimplifiedIntentions(ixns)
}
var (
oktaProvider = structs.IntentionJWTProvider{
Name: "okta",
}
auth0Provider = structs.IntentionJWTProvider{
Name: "auth0",
}
singleProviderIntention = &structs.IntentionJWTRequirement{
Providers: []*structs.IntentionJWTProvider{
&oktaProvider,
},
}
multiProviderIntentions = &structs.IntentionJWTRequirement{
Providers: []*structs.IntentionJWTProvider{
&oktaProvider,
&auth0Provider,
},
}
remoteCE = map[string]*structs.JWTProviderConfigEntry{
"okta": {
Kind: "jwt-provider",
Name: "okta",
Issuer: "test-issuer",
JSONWebKeySet: &structs.JSONWebKeySet{
Remote: &structs.RemoteJWKS{
FetchAsynchronously: true,
URI: "https://example-okta.com/.well-known/jwks.json",
},
},
},
"auth0": {
Kind: "jwt-provider",
Name: "auth0",
Issuer: "another-issuer",
JSONWebKeySet: &structs.JSONWebKeySet{
Remote: &structs.RemoteJWKS{
FetchAsynchronously: true,
URI: "https://example-auth0.com/.well-known/jwks.json",
},
},
},
}
localCE = map[string]*structs.JWTProviderConfigEntry{
"okta": {
Kind: "jwt-provider",
Name: "okta",
Issuer: "test-issuer",
JSONWebKeySet: &structs.JSONWebKeySet{
Local: &structs.LocalJWKS{
JWKS: "eyJrZXlzIjogW3sKICAiY3J2IjogIlAtMjU2IiwKICAia2V5X29wcyI6IFsKICAgICJ2ZXJpZnkiCiAgXSwKICAia3R5IjogIkVDIiwKICAieCI6ICJXYzl1WnVQYUI3S2gyRk1jOXd0SmpSZThYRDR5VDJBWU5BQWtyWWJWanV3IiwKICAieSI6ICI2OGhSVEppSk5Pd3RyaDRFb1BYZVZuUnVIN2hpU0RKX2xtYmJqZkRmV3EwIiwKICAiYWxnIjogIkVTMjU2IiwKICAidXNlIjogInNpZyIsCiAgImtpZCI6ICJhYzFlOGY5MGVkZGY2MWM0MjljNjFjYTA1YjRmMmUwNyIKfV19",
},
},
},
}
pWithOneProvider = &structs.IntentionPermission{
Action: structs.IntentionActionAllow,
HTTP: &structs.IntentionHTTPPermission{
PathPrefix: "/some-special-path",
},
JWT: singleProviderIntention,
}
)
tests := map[string]struct {
intentions structs.SimplifiedIntentions
provider map[string]*structs.JWTProviderConfigEntry
}{
"remote-provider": {
intentions: simplified(testIntention(t, ixnOpts{src: "web", action: structs.IntentionActionAllow, jwt: singleProviderIntention})),
provider: remoteCE,
},
"local-provider": {
intentions: simplified(testIntention(t, ixnOpts{src: "web", action: structs.IntentionActionAllow, jwt: singleProviderIntention})),
provider: localCE,
},
"intention-with-path": {
intentions: simplified(testIntention(t, ixnOpts{src: "web", action: structs.IntentionActionAllow, perms: pWithOneProvider})),
provider: remoteCE,
},
"top-level-provider-with-permission": {
intentions: simplified(testIntention(t, ixnOpts{src: "web", action: structs.IntentionActionAllow, jwt: singleProviderIntention, perms: pWithOneProvider})),
provider: remoteCE,
},
"multiple-providers-and-one-permission": {
intentions: simplified(testIntention(t, ixnOpts{src: "web", action: structs.IntentionActionAllow, jwt: multiProviderIntentions, perms: pWithOneProvider})),
provider: remoteCE,
},
}
for name, tt := range tests {
tt := tt
t.Run(name, func(t *testing.T) {
t.Run("jwt filter", func(t *testing.T) {
filter, err := makeJWTAuthFilter(tt.provider, tt.intentions)
require.NoError(t, err)
t.Run("current", func(t *testing.T) {
gotJSON := protoToJSON(t, filter)
require.JSONEq(t, goldenSimple(t, filepath.Join("jwt_authn", name), gotJSON), gotJSON)
})
})
})
}
}

View File

@ -1369,6 +1369,10 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot
logger: s.Logger,
}
if useHTTPFilter {
jwtFilter, jwtFilterErr := makeJWTAuthFilter(cfgSnap.JWTProviders, cfgSnap.ConnectProxy.Intentions)
if jwtFilterErr != nil {
return nil, jwtFilterErr
}
rbacFilter, err := makeRBACHTTPFilter(
cfgSnap.ConnectProxy.Intentions,
cfgSnap.IntentionDefaultAllow,
@ -1385,6 +1389,10 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot
filterOpts.httpAuthzFilters = []*envoy_http_v3.HttpFilter{rbacFilter}
if jwtFilter != nil {
filterOpts.httpAuthzFilters = append(filterOpts.httpAuthzFilters, jwtFilter)
}
meshConfig := cfgSnap.MeshConfig()
includeXFCC := meshConfig == nil || meshConfig.HTTP == nil || !meshConfig.HTTP.SanitizeXForwardedClientCert
notGRPC := cfg.Protocol != "grpc"

View File

@ -0,0 +1,31 @@
{
"name": "envoy.filters.http.jwt_authn",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
"providers": {
"okta": {
"issuer": "test-issuer",
"remoteJwks": {
"httpUri": {
"uri": "https://example-okta.com/.well-known/jwks.json",
"cluster": "jwks_cluster",
"timeout": "0s"
},
"asyncFetch": {
"fastListener": true
}
}
}
},
"rules": [
{
"match": {
"prefix": "/some-special-path"
},
"requires": {
"providerName": "okta"
}
}
]
}
}

View File

@ -0,0 +1,24 @@
{
"name": "envoy.filters.http.jwt_authn",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
"providers": {
"okta": {
"issuer": "test-issuer",
"localJwks": {
"inlineString": "{\"keys\": [{\n \"crv\": \"P-256\",\n \"key_ops\": [\n \"verify\"\n ],\n \"kty\": \"EC\",\n \"x\": \"Wc9uZuPaB7Kh2FMc9wtJjRe8XD4yT2AYNAAkrYbVjuw\",\n \"y\": \"68hRTJiJNOwtrh4EoPXeVnRuH7hiSDJ_lmbbjfDfWq0\",\n \"alg\": \"ES256\",\n \"use\": \"sig\",\n \"kid\": \"ac1e8f90eddf61c429c61ca05b4f2e07\"\n}]}"
}
}
},
"rules": [
{
"match": {
"prefix": "/"
},
"requires": {
"providerName": "okta"
}
}
]
}
}

View File

@ -0,0 +1,60 @@
{
"name": "envoy.filters.http.jwt_authn",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
"providers": {
"okta": {
"issuer": "test-issuer",
"remoteJwks": {
"httpUri": {
"uri": "https://example-okta.com/.well-known/jwks.json",
"cluster": "jwks_cluster",
"timeout": "0s"
},
"asyncFetch": {
"fastListener": true
}
}
},
"auth0": {
"issuer": "another-issuer",
"remoteJwks": {
"httpUri": {
"uri": "https://example-auth0.com/.well-known/jwks.json",
"cluster": "jwks_cluster",
"timeout": "0s"
},
"asyncFetch": {
"fastListener": true
}
}
}
},
"rules": [
{
"match": {
"prefix": "/some-special-path"
},
"requires": {
"providerName": "okta"
}
},
{
"match": {
"prefix": "/"
},
"requires": {
"providerName": "okta"
}
},
{
"match": {
"prefix": "/"
},
"requires": {
"providerName": "auth0"
}
}
]
}
}

View File

@ -0,0 +1,31 @@
{
"name": "envoy.filters.http.jwt_authn",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
"providers": {
"okta": {
"issuer": "test-issuer",
"remoteJwks": {
"httpUri": {
"uri": "https://example-okta.com/.well-known/jwks.json",
"cluster": "jwks_cluster",
"timeout": "0s"
},
"asyncFetch": {
"fastListener": true
}
}
}
},
"rules": [
{
"match": {
"prefix": "/"
},
"requires": {
"providerName": "okta"
}
}
]
}
}

View File

@ -0,0 +1,39 @@
{
"name": "envoy.filters.http.jwt_authn",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication",
"providers": {
"okta": {
"issuer": "test-issuer",
"remoteJwks": {
"httpUri": {
"uri": "https://example-okta.com/.well-known/jwks.json",
"cluster": "jwks_cluster",
"timeout": "0s"
},
"asyncFetch": {
"fastListener": true
}
}
}
},
"rules": [
{
"match": {
"prefix": "/some-special-path"
},
"requires": {
"providerName": "okta"
}
},
{
"match": {
"prefix": "/"
},
"requires": {
"providerName": "okta"
}
}
]
}
}

View File

@ -1052,6 +1052,232 @@ func IntentionPermissionFromStructs(t *structs.IntentionPermission, s *Intention
s.JWT = &x
}
}
func JSONWebKeySetToStructs(s *JSONWebKeySet, t *structs.JSONWebKeySet) {
if s == nil {
return
}
if s.Local != nil {
var x structs.LocalJWKS
LocalJWKSToStructs(s.Local, &x)
t.Local = &x
}
if s.Remote != nil {
var x structs.RemoteJWKS
RemoteJWKSToStructs(s.Remote, &x)
t.Remote = &x
}
}
func JSONWebKeySetFromStructs(t *structs.JSONWebKeySet, s *JSONWebKeySet) {
if s == nil {
return
}
if t.Local != nil {
var x LocalJWKS
LocalJWKSFromStructs(t.Local, &x)
s.Local = &x
}
if t.Remote != nil {
var x RemoteJWKS
RemoteJWKSFromStructs(t.Remote, &x)
s.Remote = &x
}
}
func JWKSRetryPolicyToStructs(s *JWKSRetryPolicy, t *structs.JWKSRetryPolicy) {
if s == nil {
return
}
t.NumRetries = int(s.NumRetries)
if s.RetryPolicyBackOff != nil {
var x structs.RetryPolicyBackOff
RetryPolicyBackOffToStructs(s.RetryPolicyBackOff, &x)
t.RetryPolicyBackOff = &x
}
}
func JWKSRetryPolicyFromStructs(t *structs.JWKSRetryPolicy, s *JWKSRetryPolicy) {
if s == nil {
return
}
s.NumRetries = int32(t.NumRetries)
if t.RetryPolicyBackOff != nil {
var x RetryPolicyBackOff
RetryPolicyBackOffFromStructs(t.RetryPolicyBackOff, &x)
s.RetryPolicyBackOff = &x
}
}
func JWTCacheConfigToStructs(s *JWTCacheConfig, t *structs.JWTCacheConfig) {
if s == nil {
return
}
t.Size = int(s.Size)
}
func JWTCacheConfigFromStructs(t *structs.JWTCacheConfig, s *JWTCacheConfig) {
if s == nil {
return
}
s.Size = int32(t.Size)
}
func JWTForwardingConfigToStructs(s *JWTForwardingConfig, t *structs.JWTForwardingConfig) {
if s == nil {
return
}
t.HeaderName = s.HeaderName
t.PadForwardPayloadHeader = s.PadForwardPayloadHeader
}
func JWTForwardingConfigFromStructs(t *structs.JWTForwardingConfig, s *JWTForwardingConfig) {
if s == nil {
return
}
s.HeaderName = t.HeaderName
s.PadForwardPayloadHeader = t.PadForwardPayloadHeader
}
func JWTLocationToStructs(s *JWTLocation, t *structs.JWTLocation) {
if s == nil {
return
}
if s.Header != nil {
var x structs.JWTLocationHeader
JWTLocationHeaderToStructs(s.Header, &x)
t.Header = &x
}
if s.QueryParam != nil {
var x structs.JWTLocationQueryParam
JWTLocationQueryParamToStructs(s.QueryParam, &x)
t.QueryParam = &x
}
if s.Cookie != nil {
var x structs.JWTLocationCookie
JWTLocationCookieToStructs(s.Cookie, &x)
t.Cookie = &x
}
}
func JWTLocationFromStructs(t *structs.JWTLocation, s *JWTLocation) {
if s == nil {
return
}
if t.Header != nil {
var x JWTLocationHeader
JWTLocationHeaderFromStructs(t.Header, &x)
s.Header = &x
}
if t.QueryParam != nil {
var x JWTLocationQueryParam
JWTLocationQueryParamFromStructs(t.QueryParam, &x)
s.QueryParam = &x
}
if t.Cookie != nil {
var x JWTLocationCookie
JWTLocationCookieFromStructs(t.Cookie, &x)
s.Cookie = &x
}
}
func JWTLocationCookieToStructs(s *JWTLocationCookie, t *structs.JWTLocationCookie) {
if s == nil {
return
}
t.Name = s.Name
}
func JWTLocationCookieFromStructs(t *structs.JWTLocationCookie, s *JWTLocationCookie) {
if s == nil {
return
}
s.Name = t.Name
}
func JWTLocationHeaderToStructs(s *JWTLocationHeader, t *structs.JWTLocationHeader) {
if s == nil {
return
}
t.Name = s.Name
t.ValuePrefix = s.ValuePrefix
t.Forward = s.Forward
}
func JWTLocationHeaderFromStructs(t *structs.JWTLocationHeader, s *JWTLocationHeader) {
if s == nil {
return
}
s.Name = t.Name
s.ValuePrefix = t.ValuePrefix
s.Forward = t.Forward
}
func JWTLocationQueryParamToStructs(s *JWTLocationQueryParam, t *structs.JWTLocationQueryParam) {
if s == nil {
return
}
t.Name = s.Name
}
func JWTLocationQueryParamFromStructs(t *structs.JWTLocationQueryParam, s *JWTLocationQueryParam) {
if s == nil {
return
}
s.Name = t.Name
}
func JWTProviderToStructs(s *JWTProvider, t *structs.JWTProviderConfigEntry) {
if s == nil {
return
}
if s.JSONWebKeySet != nil {
var x structs.JSONWebKeySet
JSONWebKeySetToStructs(s.JSONWebKeySet, &x)
t.JSONWebKeySet = &x
}
t.Issuer = s.Issuer
t.Audiences = s.Audiences
{
t.Locations = make([]*structs.JWTLocation, len(s.Locations))
for i := range s.Locations {
if s.Locations[i] != nil {
var x structs.JWTLocation
JWTLocationToStructs(s.Locations[i], &x)
t.Locations[i] = &x
}
}
}
if s.Forwarding != nil {
var x structs.JWTForwardingConfig
JWTForwardingConfigToStructs(s.Forwarding, &x)
t.Forwarding = &x
}
t.ClockSkewSeconds = int(s.ClockSkewSeconds)
if s.CacheConfig != nil {
var x structs.JWTCacheConfig
JWTCacheConfigToStructs(s.CacheConfig, &x)
t.CacheConfig = &x
}
t.Meta = s.Meta
}
func JWTProviderFromStructs(t *structs.JWTProviderConfigEntry, s *JWTProvider) {
if s == nil {
return
}
if t.JSONWebKeySet != nil {
var x JSONWebKeySet
JSONWebKeySetFromStructs(t.JSONWebKeySet, &x)
s.JSONWebKeySet = &x
}
s.Issuer = t.Issuer
s.Audiences = t.Audiences
{
s.Locations = make([]*JWTLocation, len(t.Locations))
for i := range t.Locations {
if t.Locations[i] != nil {
var x JWTLocation
JWTLocationFromStructs(t.Locations[i], &x)
s.Locations[i] = &x
}
}
}
if t.Forwarding != nil {
var x JWTForwardingConfig
JWTForwardingConfigFromStructs(t.Forwarding, &x)
s.Forwarding = &x
}
s.ClockSkewSeconds = int32(t.ClockSkewSeconds)
if t.CacheConfig != nil {
var x JWTCacheConfig
JWTCacheConfigFromStructs(t.CacheConfig, &x)
s.CacheConfig = &x
}
s.Meta = t.Meta
}
func LeastRequestConfigToStructs(s *LeastRequestConfig, t *structs.LeastRequestConfig) {
if s == nil {
return
@ -1114,6 +1340,20 @@ func LoadBalancerFromStructs(t *structs.LoadBalancer, s *LoadBalancer) {
}
}
}
func LocalJWKSToStructs(s *LocalJWKS, t *structs.LocalJWKS) {
if s == nil {
return
}
t.JWKS = s.JWKS
t.Filename = s.Filename
}
func LocalJWKSFromStructs(t *structs.LocalJWKS, s *LocalJWKS) {
if s == nil {
return
}
s.JWKS = t.JWKS
s.Filename = t.Filename
}
func MeshConfigToStructs(s *MeshConfig, t *structs.MeshConfigEntry) {
if s == nil {
return
@ -1268,6 +1508,34 @@ func PeeringMeshConfigFromStructs(t *structs.PeeringMeshConfig, s *PeeringMeshCo
}
s.PeerThroughMeshGateways = t.PeerThroughMeshGateways
}
func RemoteJWKSToStructs(s *RemoteJWKS, t *structs.RemoteJWKS) {
if s == nil {
return
}
t.URI = s.URI
t.RequestTimeoutMs = int(s.RequestTimeoutMs)
t.CacheDuration = structs.DurationFromProto(s.CacheDuration)
t.FetchAsynchronously = s.FetchAsynchronously
if s.RetryPolicy != nil {
var x structs.JWKSRetryPolicy
JWKSRetryPolicyToStructs(s.RetryPolicy, &x)
t.RetryPolicy = &x
}
}
func RemoteJWKSFromStructs(t *structs.RemoteJWKS, s *RemoteJWKS) {
if s == nil {
return
}
s.URI = t.URI
s.RequestTimeoutMs = int32(t.RequestTimeoutMs)
s.CacheDuration = structs.DurationToProto(t.CacheDuration)
s.FetchAsynchronously = t.FetchAsynchronously
if t.RetryPolicy != nil {
var x JWKSRetryPolicy
JWKSRetryPolicyFromStructs(t.RetryPolicy, &x)
s.RetryPolicy = &x
}
}
func ResourceReferenceToStructs(s *ResourceReference, t *structs.ResourceReference) {
if s == nil {
return
@ -1286,6 +1554,20 @@ func ResourceReferenceFromStructs(t *structs.ResourceReference, s *ResourceRefer
s.SectionName = t.SectionName
s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta)
}
func RetryPolicyBackOffToStructs(s *RetryPolicyBackOff, t *structs.RetryPolicyBackOff) {
if s == nil {
return
}
t.BaseInterval = structs.DurationFromProto(s.BaseInterval)
t.MaxInterval = structs.DurationFromProto(s.MaxInterval)
}
func RetryPolicyBackOffFromStructs(t *structs.RetryPolicyBackOff, s *RetryPolicyBackOff) {
if s == nil {
return
}
s.BaseInterval = structs.DurationToProto(t.BaseInterval)
s.MaxInterval = structs.DurationToProto(t.MaxInterval)
}
func RingHashConfigToStructs(s *RingHashConfig, t *structs.RingHashConfig) {
if s == nil {
return

View File

@ -108,6 +108,14 @@ func ConfigEntryToStructs(s *ConfigEntry) structs.ConfigEntry {
pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex)
pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta)
return &target
case Kind_KindJWTProvider:
var target structs.JWTProviderConfigEntry
target.Name = s.Name
JWTProviderToStructs(s.GetJWTProvider(), &target)
pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex)
pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta)
return &target
default:
panic(fmt.Sprintf("unable to convert ConfigEntry of kind %s to structs", s.Kind))
}
@ -211,7 +219,14 @@ func ConfigEntryFromStructs(s structs.ConfigEntry) *ConfigEntry {
configEntry.Entry = &ConfigEntry_SamenessGroup{
SamenessGroup: &sg,
}
case *structs.JWTProviderConfigEntry:
var jwtProvider JWTProvider
JWTProviderFromStructs(v, &jwtProvider)
configEntry.Kind = Kind_KindJWTProvider
configEntry.Entry = &ConfigEntry_JWTProvider{
JWTProvider: &jwtProvider,
}
default:
panic(fmt.Sprintf("unable to convert %T to proto", s))
}

View File

@ -686,3 +686,123 @@ func (msg *SamenessGroupMember) MarshalBinary() ([]byte, error) {
func (msg *SamenessGroupMember) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTProvider) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTProvider) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JSONWebKeySet) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JSONWebKeySet) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *LocalJWKS) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *LocalJWKS) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *RemoteJWKS) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *RemoteJWKS) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWKSRetryPolicy) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWKSRetryPolicy) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *RetryPolicyBackOff) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *RetryPolicyBackOff) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTLocation) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTLocation) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTLocationHeader) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTLocationHeader) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTLocationQueryParam) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTLocationQueryParam) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTLocationCookie) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTLocationCookie) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTForwardingConfig) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTForwardingConfig) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}
// MarshalBinary implements encoding.BinaryMarshaler
func (msg *JWTCacheConfig) MarshalBinary() ([]byte, error) {
return proto.Marshal(msg)
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler
func (msg *JWTCacheConfig) UnmarshalBinary(b []byte) error {
return proto.Unmarshal(b, msg)
}

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,7 @@ enum Kind {
KindHTTPRoute = 9;
KindTCPRoute = 10;
KindSamenessGroup = 11;
KindJWTProvider = 12;
}
message ConfigEntry {
@ -43,6 +44,7 @@ message ConfigEntry {
HTTPRoute HTTPRoute = 13;
InlineCertificate InlineCertificate = 14;
SamenessGroup SamenessGroup = 15;
JWTProvider JWTProvider = 16;
}
}
@ -967,3 +969,139 @@ message SamenessGroupMember {
string Partition = 1;
string Peer = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTProviderConfigEntry
// output=config_entry.gen.go
// name=Structs
// ignore-fields=Name,Kind,RaftIndex,EnterpriseMeta
message JWTProvider {
JSONWebKeySet JSONWebKeySet = 1;
string Issuer = 2;
repeated string Audiences = 3;
repeated JWTLocation Locations = 4;
JWTForwardingConfig Forwarding = 5;
JWTCacheConfig CacheConfig = 6;
map<string, string> Meta = 7;
// mog: func-to=int func-from=int32
int32 ClockSkewSeconds = 8;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JSONWebKeySet
// output=config_entry.gen.go
// name=Structs
message JSONWebKeySet {
LocalJWKS Local = 1;
RemoteJWKS Remote = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.LocalJWKS
// output=config_entry.gen.go
// name=Structs
message LocalJWKS {
string JWKS = 1;
string Filename = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.RemoteJWKS
// output=config_entry.gen.go
// name=Structs
message RemoteJWKS {
string URI = 1;
// mog: func-to=int func-from=int32
int32 RequestTimeoutMs = 2;
// mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto
google.protobuf.Duration CacheDuration = 3;
bool FetchAsynchronously = 4;
JWKSRetryPolicy RetryPolicy = 5;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWKSRetryPolicy
// output=config_entry.gen.go
// name=Structs
message JWKSRetryPolicy {
// mog: func-to=int func-from=int32
int32 NumRetries = 1;
RetryPolicyBackOff RetryPolicyBackOff = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.RetryPolicyBackOff
// output=config_entry.gen.go
// name=Structs
message RetryPolicyBackOff {
// mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto
google.protobuf.Duration BaseInterval = 1;
// mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto
google.protobuf.Duration MaxInterval = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTLocation
// output=config_entry.gen.go
// name=Structs
message JWTLocation {
JWTLocationHeader Header = 1;
JWTLocationQueryParam QueryParam = 2;
JWTLocationCookie Cookie = 3;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTLocationHeader
// output=config_entry.gen.go
// name=Structs
message JWTLocationHeader {
string Name = 1;
string ValuePrefix = 2;
bool Forward = 3;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTLocationQueryParam
// output=config_entry.gen.go
// name=Structs
message JWTLocationQueryParam {
string Name = 1;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTLocationCookie
// output=config_entry.gen.go
// name=Structs
message JWTLocationCookie {
string Name = 1;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTForwardingConfig
// output=config_entry.gen.go
// name=Structs
message JWTForwardingConfig {
string HeaderName = 1;
bool PadForwardPayloadHeader = 2;
}
// mog annotation:
//
// target=github.com/hashicorp/consul/agent/structs.JWTCacheConfig
// output=config_entry.gen.go
// name=Structs
message JWTCacheConfig {
// mog: func-to=int func-from=int32
int32 Size = 1;
}

View File

@ -76,6 +76,8 @@ const (
Topic_IPRateLimit Topic = 14
// SamenessGroup topic contains events for changes to Sameness Groups
Topic_SamenessGroup Topic = 15
// JWTProvider topic contains events for changes to jwt-provider
Topic_JWTProvider Topic = 16
)
// Enum value maps for Topic.
@ -97,6 +99,7 @@ var (
13: "BoundAPIGateway",
14: "IPRateLimit",
15: "SamenessGroup",
16: "JWTProvider",
}
Topic_value = map[string]int32{
"Unknown": 0,
@ -115,6 +118,7 @@ var (
"BoundAPIGateway": 13,
"IPRateLimit": 14,
"SamenessGroup": 15,
"JWTProvider": 16,
}
)
@ -996,7 +1000,7 @@ var file_private_pbsubscribe_subscribe_proto_rawDesc = []byte{
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a,
0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0xb4, 0x02, 0x0a, 0x05, 0x54, 0x6f,
0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0xc5, 0x02, 0x0a, 0x05, 0x54, 0x6f,
0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00,
0x12, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74,
0x68, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65,
@ -1016,26 +1020,27 @@ var file_private_pbsubscribe_subscribe_proto_rawDesc = []byte{
0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x0d, 0x12, 0x0f, 0x0a, 0x0b,
0x49, 0x50, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0x0e, 0x12, 0x11, 0x0a,
0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0f,
0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, 0x0a,
0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x44,
0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x61, 0x0a, 0x17, 0x53,
0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e,
0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x09, 0x30, 0x01, 0x42, 0x9a,
0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62,
0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa,
0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, 0x75,
0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x12, 0x0f, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10,
0x10, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c,
0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a,
0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x61, 0x0a, 0x17,
0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63,
0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x09, 0x30, 0x01, 0x42,
0x9a, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62,
0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70,
0x62, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58,
0xaa, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53,
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63,
0x72, 0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0xea, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -103,6 +103,9 @@ enum Topic {
// SamenessGroup topic contains events for changes to Sameness Groups
SamenessGroup = 15;
// JWTProvider topic contains events for changes to jwt-provider
JWTProvider = 16;
}
message NamedSubject {