Skip to content

Commit 98210da

Browse files
committed
Added more information when permission is denied
1 parent 21a7c67 commit 98210da

File tree

6 files changed

+23
-17
lines changed

6 files changed

+23
-17
lines changed

backend/acl/config.go

+5-10
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ import (
1616
"gopkg.in/yaml.v2"
1717
)
1818

19-
var (
20-
// ErrUnauthorized indicates that a client doesn't have access to a resource
21-
ErrUnauthorized = status.Errorf(codes.PermissionDenied, "unauthorised")
22-
)
23-
2419
// Config allows retrieve of access scope for the current client
2520
type Config interface {
2621
GetClientScope(ctx context.Context) (*Scope, error)
@@ -103,29 +98,29 @@ func (s *config) GetClientScope(ctx context.Context) (*Scope, error) {
10398

10499
basicAuth, err := grpc_auth.AuthFromMD(ctx, "Bearer")
105100
if err != nil {
106-
return nil, ErrUnauthorized
101+
return nil, status.Errorf(codes.PermissionDenied, "failed getting Bearrer auth, %v", err)
107102
}
108103

109104
payload, err := base64.StdEncoding.DecodeString(basicAuth)
110105
if err != nil {
111-
return nil, ErrUnauthorized
106+
return nil, status.Errorf(codes.PermissionDenied, "failed getting payload: %v", err)
112107
}
113108

114109
pair := strings.SplitN(string(payload), ":", 2)
115110

116111
if len(pair) != 2 {
117-
return nil, ErrUnauthorized
112+
return nil, status.Errorf(codes.PermissionDenied, "malformed payload: should contain 2 pairs, but got %d", len(pair))
118113
}
119114

120115
id, secret := pair[0], pair[1]
121116

122117
hashPass, ok := s.auth[id]
123118
if !ok {
124-
return nil, ErrUnauthorized
119+
return nil, status.Errorf(codes.PermissionDenied, "no password configured for id %v", id)
125120
}
126121

127122
if err := bcrypt.CompareHashAndPassword(hashPass, []byte(secret)); err != nil {
128-
return nil, ErrUnauthorized
123+
return nil, status.Errorf(codes.PermissionDenied, "passwords do not match for id %v", id)
129124
}
130125

131126
return s.scopes[id], nil

backend/acl/config_test.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"testing"
88

99
"github.com/stretchr/testify/require"
10+
"google.golang.org/grpc/codes"
1011
"google.golang.org/grpc/metadata"
12+
"google.golang.org/grpc/status"
1113
)
1214

1315
var (
@@ -85,7 +87,14 @@ clients:
8587
ctx := createCtx("dog-consumer", "123")
8688
_, err = c.GetClientScope(ctx)
8789

88-
assert.Equal(err, ErrUnauthorized)
90+
assertPermissionDenied(t, err, "passwords do not match")
91+
}
92+
93+
func assertPermissionDenied(t *testing.T, err error, expString string) {
94+
s, ok := status.FromError(err)
95+
require.True(t, ok)
96+
require.Equal(t, codes.PermissionDenied, s.Code())
97+
require.ErrorContains(t, err, expString)
8998
}
9099

91100
func Test_ClientWithNoAuthHasDefaultAccess(t *testing.T) {

backend/acl/sink.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"github.com/uw-labs/proximo"
77
"github.com/uw-labs/proximo/proto"
88
"github.com/uw-labs/substrate"
9+
"google.golang.org/grpc/codes"
10+
"google.golang.org/grpc/status"
911
)
1012

1113
type AsyncSinkFactory struct {
@@ -20,7 +22,7 @@ func (s AsyncSinkFactory) NewAsyncSink(ctx context.Context, req *proto.StartPubl
2022
}
2123

2224
if !containsRegex(scope.Publish, req.Topic) {
23-
return nil, ErrUnauthorized
25+
return nil, status.Errorf(codes.PermissionDenied, "no publish permissions for topic %v", req.Topic)
2426
}
2527

2628
return s.Next.NewAsyncSink(ctx, req)

backend/acl/sink_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
)
1212

1313
func Test_FactoryConsumeOnlyClientCannotPublish(t *testing.T) {
14-
assert := require.New(t)
1514

1615
c, err := ConfigFromString(fmt.Sprintf(`
1716
default:
@@ -37,7 +36,7 @@ clients:
3736
Topic: "dogs",
3837
})
3938

40-
assert.Equal(err, ErrUnauthorized)
39+
assertPermissionDenied(t, err, "no publish permissions for topic dogs")
4140
}
4241

4342
func Test_FactoryPublishOnlyClientCanPublish(t *testing.T) {

backend/acl/source.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"github.com/uw-labs/proximo"
77
"github.com/uw-labs/proximo/proto"
88
"github.com/uw-labs/substrate"
9+
"google.golang.org/grpc/codes"
10+
"google.golang.org/grpc/status"
911
)
1012

1113
type AsyncSourceFactory struct {
@@ -20,7 +22,7 @@ func (s AsyncSourceFactory) NewAsyncSource(ctx context.Context, req *proto.Start
2022
}
2123

2224
if !containsRegex(scope.Consume, req.Topic) {
23-
return nil, ErrUnauthorized
25+
return nil, status.Errorf(codes.PermissionDenied, "no consume permissions for topic %v", req.Topic)
2426
}
2527

2628
return s.Next.NewAsyncSource(ctx, req)

backend/acl/source_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
)
1010

1111
func Test_FactoryPublishOnlyClientCannotConsume(t *testing.T) {
12-
assert := require.New(t)
1312

1413
c, err := ConfigFromString(fmt.Sprintf(`
1514
default:
@@ -35,7 +34,7 @@ clients:
3534
Topic: "dogs",
3635
})
3736

38-
assert.Equal(err, ErrUnauthorized)
37+
assertPermissionDenied(t, err, "no consume permissions for topic dogs")
3938
}
4039

4140
func Test_FactoryConsumeOnlyClientCanConsume(t *testing.T) {

0 commit comments

Comments
 (0)