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:
parent
97532900a5
commit
aad135529f
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -1020,6 +1020,7 @@ type ConfigSnapshot struct {
|
|||
Datacenter string
|
||||
IntentionDefaultAllow bool
|
||||
Locality GatewayKey
|
||||
JWTProviders map[string]*structs.JWTProviderConfigEntry
|
||||
|
||||
ServerSNIFn ServerSNIFunc
|
||||
Roots *structs.IndexedCARoots
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue