Skip to content

Commit 9ea5181

Browse files
committed
Add option to disable auth on streaming endpoint
1 parent 31751fb commit 9ea5181

5 files changed

Lines changed: 48 additions & 26 deletions

File tree

common/authorization/interceptor.go

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ type Interceptor struct {
9090
authExtraHeaderName string
9191
exposeAuthorizerErrors dynamicconfig.BoolPropertyFn
9292
enableCrossNamespaceCommands dynamicconfig.BoolPropertyFn
93+
disableStreamingAuthorizer dynamicconfig.BoolPropertyFn
9394
}
9495

9596
// NewInterceptor creates an authorization interceptor.
@@ -104,6 +105,7 @@ func NewInterceptor(
104105
authExtraHeaderName string,
105106
exposeAuthorizerErrors dynamicconfig.BoolPropertyFn,
106107
enableCrossNamespaceCommands dynamicconfig.BoolPropertyFn,
108+
disableStreamingAuthorizer dynamicconfig.BoolPropertyFn,
107109
) *Interceptor {
108110
return &Interceptor{
109111
claimMapper: claimMapper,
@@ -116,6 +118,7 @@ func NewInterceptor(
116118
audienceGetter: audienceGetter,
117119
exposeAuthorizerErrors: exposeAuthorizerErrors,
118120
enableCrossNamespaceCommands: enableCrossNamespaceCommands,
121+
disableStreamingAuthorizer: disableStreamingAuthorizer,
119122
}
120123
}
121124

@@ -177,34 +180,37 @@ func (a *Interceptor) InterceptStream(
177180
handler grpc.StreamHandler,
178181
) error {
179182
ctx := ss.Context()
180-
tlsConnection := TLSInfoFromContext(ctx)
181-
182-
authInfo := a.GetAuthInfo(tlsConnection, headers.NewGRPCHeaderGetter(ctx), func() string {
183-
// JWTAudienceMapper only supports UnaryServerInfo; no request is available at stream init.
184-
return ""
185-
})
186-
187-
var claims *Claims
188-
if authInfo != nil {
189-
var err error
190-
claims, err = a.GetClaims(authInfo)
191-
if err != nil {
192-
a.logger.Error("Authorization error", tag.Error(err))
193-
return errUnauthorized
183+
bypassAuth := a.disableStreamingAuthorizer()
184+
if !bypassAuth {
185+
tlsConnection := TLSInfoFromContext(ctx)
186+
187+
authInfo := a.GetAuthInfo(tlsConnection, headers.NewGRPCHeaderGetter(ctx), func() string {
188+
// JWTAudienceMapper only supports UnaryServerInfo; no request is available at stream init.
189+
return ""
190+
})
191+
192+
var claims *Claims
193+
if authInfo != nil {
194+
var err error
195+
claims, err = a.GetClaims(authInfo)
196+
if err != nil {
197+
a.logger.Error("Authorization error", tag.Error(err))
198+
return errUnauthorized
199+
}
200+
ctx = a.EnhanceContext(ctx, authInfo, claims)
194201
}
195-
ctx = a.EnhanceContext(ctx, authInfo, claims)
196-
}
197202

198-
if a.authorizer != nil {
199-
// Namespace is not available in the stream handshake (no initial request body).
200-
ct := &CallTarget{
201-
Namespace: "",
202-
APIName: info.FullMethod,
203-
Request: nil,
204-
}
205-
if err := a.Authorize(ctx, claims, ct); err != nil {
206-
a.logger.Error("Authorization error", tag.Error(err))
207-
return err
203+
if a.authorizer != nil {
204+
// Namespace is not available in the stream handshake (no initial request body).
205+
ct := &CallTarget{
206+
Namespace: "",
207+
APIName: info.FullMethod,
208+
Request: nil,
209+
}
210+
if err := a.Authorize(ctx, claims, ct); err != nil {
211+
a.logger.Error("Authorization error", tag.Error(err))
212+
return err
213+
}
208214
}
209215
}
210216

common/authorization/interceptor_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func (s *authorizerInterceptorSuite) SetupTest() {
8484
"",
8585
dynamicconfig.GetBoolPropertyFn(false), // exposeAuthorizerErrors
8686
dynamicconfig.GetBoolPropertyFn(false), // enableCrossNamespaceCommands
87+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
8788
)
8889
s.handler = func(ctx context.Context, req interface{}) (interface{}, error) { return true, nil }
8990
}
@@ -159,6 +160,7 @@ func (s *authorizerInterceptorSuite) TestAuthorizationFailedExposed() {
159160
"",
160161
dynamicconfig.GetBoolPropertyFn(true), // exposeAuthorizerErrors
161162
dynamicconfig.GetBoolPropertyFn(false), // enableCrossNamespaceCommands
163+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
162164
)
163165

164166
authErr := serviceerror.NewInternal("intentional test failure")
@@ -192,6 +194,7 @@ func (s *authorizerInterceptorSuite) TestNoopClaimMapperWithoutTLS() {
192194
"",
193195
dynamicconfig.GetBoolPropertyFn(false), // exposeAuthorizerErrors
194196
dynamicconfig.GetBoolPropertyFn(false), // enableCrossNamespaceCommands
197+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
195198
)
196199
_, err := interceptor.Intercept(ctx, describeNamespaceRequest, describeNamespaceInfo, s.handler)
197200
s.NoError(err)
@@ -209,6 +212,7 @@ func (s *authorizerInterceptorSuite) TestAlternateHeaders() {
209212
"custom-extra-header",
210213
dynamicconfig.GetBoolPropertyFn(false), // exposeAuthorizerErrors
211214
dynamicconfig.GetBoolPropertyFn(false), // enableCrossNamespaceCommands
215+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
212216
)
213217

214218
cases := []struct {
@@ -318,6 +322,7 @@ func (s *authorizerInterceptorSuite) newCrossNamespaceInterceptor(namespaces ...
318322
"",
319323
dynamicconfig.GetBoolPropertyFn(false), // exposeAuthorizerErrors
320324
dynamicconfig.GetBoolPropertyFn(true), // enableCrossNamespaceCommands
325+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
321326
)
322327
}
323328

@@ -634,6 +639,8 @@ func (s *authorizerInterceptorSuite) TestInterceptStream_AuthDisabled() {
634639
"",
635640
"",
636641
dynamicconfig.GetBoolPropertyFn(false),
642+
dynamicconfig.GetBoolPropertyFn(false),
643+
dynamicconfig.GetBoolPropertyFn(false),
637644
)
638645

639646
handlerCalled := false
@@ -659,6 +666,8 @@ func (s *authorizerInterceptorSuite) TestInterceptStream_InvalidToken() {
659666
"",
660667
"",
661668
dynamicconfig.GetBoolPropertyFn(false),
669+
dynamicconfig.GetBoolPropertyFn(false),
670+
dynamicconfig.GetBoolPropertyFn(false),
662671
)
663672

664673
// Provide an incoming context with an auth token so GetAuthInfo returns non-nil.

common/dynamicconfig/constants.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ for signal / start / signal with start API if namespace is not active`,
149149
true,
150150
`EnableCrossNamespaceCommands is the key to enable commands for external namespaces`,
151151
)
152+
DisableStreamingAuthorizer = NewGlobalBoolSetting(
153+
"system.disableStreamingAuthorizer",
154+
false,
155+
`DisableStreamingAuthorizer is the key to disable the auth on streaming endpoint`,
156+
)
152157
ClusterMetadataRefreshInterval = NewGlobalDurationSetting(
153158
"system.clusterMetadataRefreshInterval",
154159
time.Minute,

service/frontend/fx.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ func AuthorizationInterceptorProvider(
172172
cfg.Global.Authorization.AuthExtraHeaderName,
173173
serviceConfig.ExposeAuthorizerErrors,
174174
dynamicconfig.EnableCrossNamespaceCommands.Get(dc),
175+
dynamicconfig.DisableStreamingAuthorizer.Get(dc),
175176
)
176177
}
177178

service/frontend/nexus_handler_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func newOperationContext(options contextOptions) *operationContext {
128128
"",
129129
dynamicconfig.GetBoolPropertyFn(false), // exposeAuthorizerErrors
130130
dynamicconfig.GetBoolPropertyFn(false), // enableCrossNamespaceCommands
131+
dynamicconfig.GetBoolPropertyFn(false), // disableStreamingAuthorizer
131132
)
132133
oc.namespaceConcurrencyLimitInterceptor = interceptor.NewConcurrentRequestLimitInterceptor(
133134
nil,

0 commit comments

Comments
 (0)