Skip to content

Commit 0da3d99

Browse files
authored
Default authorizer always allow health checks (#3920)
1 parent 908a672 commit 0da3d99

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

common/authorization/default_authorizer.go

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ var resultAllow = Result{Decision: DecisionAllow}
4545
var resultDeny = Result{Decision: DecisionDeny}
4646

4747
func (a *defaultAuthorizer) Authorize(_ context.Context, claims *Claims, target *CallTarget) (Result, error) {
48+
// APIs that are essentially read-only health checks with no sensitive information are
49+
// always allowed
50+
if IsHealthCheckAPI(target.APIName) {
51+
return resultAllow, nil
52+
}
4853

4954
if claims == nil {
5055
return resultDeny, nil

common/authorization/default_authorizer_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ import (
3737
)
3838

3939
var (
40+
claimsNone = Claims{}
41+
claimsNamespaceOnly = Claims{
42+
Namespaces: map[string]Role{
43+
testNamespace: RoleWriter,
44+
},
45+
}
4046
claimsSystemAdmin = Claims{
4147
System: RoleAdmin,
4248
}
@@ -75,6 +81,14 @@ var (
7581
APIName: "/temporal.api.workflowservice.v1.WorkflowService/DescribeNamespace",
7682
Namespace: "BAR",
7783
}
84+
targetGrpcHealthCheck = CallTarget{
85+
APIName: "/grpc.health.v1.Health/Check",
86+
Namespace: "",
87+
}
88+
targetGetSystemInfo = CallTarget{
89+
APIName: "/temporal.api.workflowservice.v1.WorkflowService/GetSystemInfo",
90+
Namespace: "",
91+
}
7892
)
7993

8094
type (
@@ -162,6 +176,29 @@ func (s *defaultAuthorizerSuite) TestSystemAdminListNamespaces() {
162176
s.NoError(err)
163177
s.Equal(DecisionAllow, result.Decision)
164178
}
179+
func (s *defaultAuthorizerSuite) TestNamespaceOnly() {
180+
// don't need any system-level claims to do namespace-level apis
181+
result, err := s.authorizer.Authorize(context.TODO(), &claimsNamespaceOnly, startWorkflowExecutionTarget)
182+
s.NoError(err)
183+
s.Equal(DecisionAllow, result.Decision)
184+
}
185+
func (s *defaultAuthorizerSuite) TestHealthChecks() {
186+
// all health checks should work all the time
187+
for _, claims := range []*Claims{
188+
nil,
189+
&claimsNone,
190+
&claimsNamespaceOnly,
191+
} {
192+
for _, target := range []*CallTarget{
193+
&targetGrpcHealthCheck,
194+
&targetGetSystemInfo,
195+
} {
196+
result, err := s.authorizer.Authorize(context.TODO(), claims, target)
197+
s.NoError(err)
198+
s.Equal(DecisionAllow, result.Decision)
199+
}
200+
}
201+
}
165202

166203
func (s *defaultAuthorizerSuite) TestGetAuthorizerFromConfigNoop() {
167204
s.testGetAuthorizerFromConfig("", true, reflect.TypeOf(&noopAuthorizer{}))

common/authorization/frontend_api.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ var readOnlyNamespaceAPI = map[string]struct{}{
3737
"QueryWorkflow": {},
3838
"DescribeWorkflowExecution": {},
3939
"DescribeTaskQueue": {},
40-
"GetSystemInfo": {},
4140
"ListTaskQueuePartitions": {},
4241
"DescribeSchedule": {},
4342
"ListSchedules": {},
@@ -50,6 +49,13 @@ var readOnlyGlobalAPI = map[string]struct{}{
5049
"ListNamespaces": {},
5150
"GetSearchAttributes": {},
5251
"GetClusterInfo": {},
52+
"GetSystemInfo": {},
53+
}
54+
55+
// note that these use the fully-qualified name
56+
var healthCheckAPI = map[string]struct{}{
57+
"/grpc.health.v1.Health/Check": {},
58+
"/temporal.api.workflowservice.v1.WorkflowService/GetSystemInfo": {},
5359
}
5460

5561
func IsReadOnlyNamespaceAPI(api string) bool {
@@ -61,3 +67,8 @@ func IsReadOnlyGlobalAPI(api string) bool {
6167
_, found := readOnlyGlobalAPI[api]
6268
return found
6369
}
70+
71+
func IsHealthCheckAPI(fullApi string) bool {
72+
_, found := healthCheckAPI[fullApi]
73+
return found
74+
}

0 commit comments

Comments
 (0)