credentials/alts: Add Client Authorization Utility API (#3271)
Add client authorization util API
This commit is contained in:
@ -31,7 +31,9 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -142,3 +144,20 @@ func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {
|
||||
}
|
||||
return altsAuthInfo, nil
|
||||
}
|
||||
|
||||
// ClientAuthorizationCheck checks whether the client is authorized to access
|
||||
// the requested resources based on the given expected client service accounts.
|
||||
// This API should be used by gRPC server RPC handlers. This API should not be
|
||||
// used by clients.
|
||||
func ClientAuthorizationCheck(ctx context.Context, expectedServiceAccounts []string) error {
|
||||
authInfo, err := AuthInfoFromContext(ctx)
|
||||
if err != nil {
|
||||
return status.Newf(codes.PermissionDenied, "The context is not an ALTS-compatible context: %v", err).Err()
|
||||
}
|
||||
for _, sa := range expectedServiceAccounts {
|
||||
if authInfo.PeerServiceAccount() == sa {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return status.Newf(codes.PermissionDenied, "Client %v is not authorized", authInfo.PeerServiceAccount()).Err()
|
||||
}
|
||||
|
@ -25,8 +25,16 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
testServiceAccount1 = "service_account1"
|
||||
testServiceAccount2 = "service_account2"
|
||||
testServiceAccount3 = "service_account3"
|
||||
)
|
||||
|
||||
func setupManufacturerReader(testOS string, reader func() (io.Reader, error)) func() {
|
||||
@ -147,7 +155,54 @@ func TestAuthInfoFromPeer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type fakeALTSAuthInfo struct{}
|
||||
func TestClientAuthorizationCheck(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
altsAuthInfo := &fakeALTSAuthInfo{testServiceAccount1}
|
||||
p := &peer.Peer{
|
||||
AuthInfo: altsAuthInfo,
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
ctx context.Context
|
||||
expectedServiceAccounts []string
|
||||
success bool
|
||||
code codes.Code
|
||||
}{
|
||||
{
|
||||
"working case",
|
||||
peer.NewContext(ctx, p),
|
||||
[]string{testServiceAccount1, testServiceAccount2},
|
||||
true,
|
||||
codes.OK, // err is nil, code is OK.
|
||||
},
|
||||
{
|
||||
"context does not have AuthInfo",
|
||||
ctx,
|
||||
[]string{testServiceAccount1, testServiceAccount2},
|
||||
false,
|
||||
codes.PermissionDenied,
|
||||
},
|
||||
{
|
||||
"unauthorized client",
|
||||
peer.NewContext(ctx, p),
|
||||
[]string{testServiceAccount2, testServiceAccount3},
|
||||
false,
|
||||
codes.PermissionDenied,
|
||||
},
|
||||
} {
|
||||
err := ClientAuthorizationCheck(tc.ctx, tc.expectedServiceAccounts)
|
||||
if got, want := (err == nil), tc.success; got != want {
|
||||
t.Errorf("%v: ClientAuthorizationCheck(_, %v)=(err=nil)=%v, want %v", tc.desc, tc.expectedServiceAccounts, got, want)
|
||||
}
|
||||
if got, want := status.Code(err), tc.code; got != want {
|
||||
t.Errorf("%v: ClientAuthorizationCheck(_, %v).Code=%v, want %v", tc.desc, tc.expectedServiceAccounts, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeALTSAuthInfo struct {
|
||||
peerServiceAccount string
|
||||
}
|
||||
|
||||
func (*fakeALTSAuthInfo) AuthType() string { return "" }
|
||||
func (*fakeALTSAuthInfo) ApplicationProtocol() string { return "" }
|
||||
@ -155,6 +210,6 @@ func (*fakeALTSAuthInfo) RecordProtocol() string { return "" }
|
||||
func (*fakeALTSAuthInfo) SecurityLevel() altspb.SecurityLevel {
|
||||
return altspb.SecurityLevel_SECURITY_NONE
|
||||
}
|
||||
func (*fakeALTSAuthInfo) PeerServiceAccount() string { return "" }
|
||||
func (f *fakeALTSAuthInfo) PeerServiceAccount() string { return f.peerServiceAccount }
|
||||
func (*fakeALTSAuthInfo) LocalServiceAccount() string { return "" }
|
||||
func (*fakeALTSAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions { return nil }
|
||||
|
Reference in New Issue
Block a user