Skip to content

Commit

Permalink
grpc/acl: fix bug where ACL token was required even if disabled (#15904)
Browse files Browse the repository at this point in the history
Fixes a bug introduced by #15346 where we'd always require an ACL
token even if ACLs were disabled because we were erroneously
treating `nil` identity as anonymous.
  • Loading branch information
boxofrad committed Jan 5, 2023
1 parent ee2d47d commit b78de5a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
14 changes: 7 additions & 7 deletions agent/grpc-external/services/connectca/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestSign_ConnectDisabled(t *testing.T) {
func TestSign_Validation(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

server := NewServer(Config{
Logger: hclog.NewNullLogger(),
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestSign_Unauthenticated(t *testing.T) {
func TestSign_PermissionDenied(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand All @@ -116,7 +116,7 @@ func TestSign_PermissionDenied(t *testing.T) {
func TestSign_InvalidCSR(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand All @@ -142,7 +142,7 @@ func TestSign_InvalidCSR(t *testing.T) {
func TestSign_RateLimited(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand All @@ -168,7 +168,7 @@ func TestSign_RateLimited(t *testing.T) {
func TestSign_InternalError(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand All @@ -194,7 +194,7 @@ func TestSign_InternalError(t *testing.T) {
func TestSign_Success(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand All @@ -220,7 +220,7 @@ func TestSign_Success(t *testing.T) {
func TestSign_RPCForwarding(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything).
Return(testutils.ACLAllowAll(t), nil)
Return(testutils.ACLsDisabled(t), nil)

caManager := &MockCAManager{}
caManager.On("AuthorizeAndSignCertificate", mock.Anything, mock.Anything).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,25 @@ func TestSupportedDataplaneFeatures_Success(t *testing.T) {
}
}

func TestSupportedDataplaneFeatures_ACLsDisabled(t *testing.T) {
aclResolver := &MockACLResolver{}
aclResolver.On("ResolveTokenAndDefaultMeta", "", mock.Anything, mock.Anything).
Return(testutils.ACLsDisabled(t), nil)

options := structs.QueryOptions{Token: ""}
ctx, err := external.ContextWithQueryOptions(context.Background(), options)
require.NoError(t, err)

server := NewServer(Config{
Logger: hclog.NewNullLogger(),
ACLResolver: aclResolver,
})
client := testClient(t, server)
resp, err := client.GetSupportedDataplaneFeatures(ctx, &pbdataplane.GetSupportedDataplaneFeaturesRequest{})
require.NoError(t, err)
require.Equal(t, 3, len(resp.SupportedDataplaneFeatures))
}

func TestSupportedDataplaneFeatures_InvalidACLToken(t *testing.T) {
// Mock the ACL resolver to return ErrNotFound.
aclResolver := &MockACLResolver{}
Expand Down
5 changes: 2 additions & 3 deletions agent/grpc-external/testutils/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ func ACLAnonymous(t *testing.T) resolver.Result {
}
}

func ACLAllowAll(t *testing.T) resolver.Result {
func ACLsDisabled(t *testing.T) resolver.Result {
t.Helper()

return resolver.Result{
Authorizer: acl.AllowAll(),
ACLIdentity: randomACLIdentity(t),
Authorizer: acl.ManageAll(),
}
}

Expand Down
2 changes: 1 addition & 1 deletion agent/grpc-external/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func RequireAnyValidACLToken(resolver ACLResolver, token string) error {
return status.Error(codes.Unauthenticated, err.Error())
}

if id := authz.ACLIdentity; id == nil || id.ID() == structs.ACLTokenAnonymousID {
if id := authz.ACLIdentity; id != nil && id.ID() == structs.ACLTokenAnonymousID {
return status.Error(codes.Unauthenticated, "An ACL token must be provided (via the `x-consul-token` metadata field) to call this endpoint")
}

Expand Down

0 comments on commit b78de5a

Please sign in to comment.