Restrict auth method listing for u_anon (#1122)

This keeps only essential information in list output for auth methods
when the user is u_anon. Boundary's default is to allow listing of
auth methods for anonymous users to allow discovery of authentication
points, but there's no need to return more information about internal
configuration than necessary.
pull/1125/head
Jeff Mitchell 5 years ago committed by GitHub
parent 344880dafc
commit 604d642e1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -386,18 +386,18 @@ func (s Service) getFromRepo(ctx context.Context, id string) (*pb.AuthMethod, er
return toAuthMethodProto(am)
}
func (s Service) listFromRepo(ctx context.Context, scopeIds []string, unauthn bool) ([]*pb.AuthMethod, error) {
func (s Service) listFromRepo(ctx context.Context, scopeIds []string, anonUser bool) ([]*pb.AuthMethod, error) {
oidcRepo, err := s.oidcRepoFn()
if err != nil {
return nil, err
}
ol, err := oidcRepo.ListAuthMethods(ctx, scopeIds, oidc.WithUnauthenticatedUser(unauthn))
ol, err := oidcRepo.ListAuthMethods(ctx, scopeIds, oidc.WithUnauthenticatedUser(anonUser))
if err != nil {
return nil, err
}
var outUl []*pb.AuthMethod
for _, u := range ol {
ou, err := toAuthMethodProto(u)
ou, err := toAuthMethodProto(u, handlers.WithAnonymousListing(anonUser))
if err != nil {
return nil, err
}
@ -413,7 +413,7 @@ func (s Service) listFromRepo(ctx context.Context, scopeIds []string, unauthn bo
return nil, err
}
for _, u := range pl {
ou, err := toAuthMethodProto(u)
ou, err := toAuthMethodProto(u, handlers.WithAnonymousListing(anonUser))
if err != nil {
return nil, err
}
@ -470,7 +470,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId string, req *pbs.Upda
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to update auth method but no error returned from repository.")
}
if dryRun {
storageToWire = func(in auth.AuthMethod) (*pb.AuthMethod, error) {
storageToWire = func(in auth.AuthMethod, opt ...handlers.Option) (*pb.AuthMethod, error) {
am, err := toAuthMethodProto(in)
if err != nil {
return nil, errors.Wrap(err, op)
@ -630,14 +630,12 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.
return auth.Verify(ctx, opts...)
}
func toAuthMethodProto(in auth.AuthMethod) (*pb.AuthMethod, error) {
func toAuthMethodProto(in auth.AuthMethod, opt ...handlers.Option) (*pb.AuthMethod, error) {
anonListing := handlers.GetOpts(opt...).WithAnonymousListing
out := &pb.AuthMethod{
Id: in.GetPublicId(),
ScopeId: in.GetScopeId(),
CreatedTime: in.GetCreateTime().GetTimestamp(),
UpdatedTime: in.GetUpdateTime().GetTimestamp(),
Version: in.GetVersion(),
IsPrimary: in.GetIsPrimaryAuthMethod(),
Id: in.GetPublicId(),
ScopeId: in.GetScopeId(),
IsPrimary: in.GetIsPrimaryAuthMethod(),
}
if in.GetDescription() != "" {
out.Description = wrapperspb.String(in.GetDescription())
@ -645,9 +643,17 @@ func toAuthMethodProto(in auth.AuthMethod) (*pb.AuthMethod, error) {
if in.GetName() != "" {
out.Name = wrapperspb.String(in.GetName())
}
if !anonListing {
out.CreatedTime = in.GetCreateTime().GetTimestamp()
out.UpdatedTime = in.GetUpdateTime().GetTimestamp()
out.Version = in.GetVersion()
}
switch i := in.(type) {
case *password.AuthMethod:
out.Type = auth.PasswordSubtype.String()
if anonListing {
break
}
st, err := handlers.ProtoToStruct(&pb.PasswordAuthMethodAttributes{
MinLoginNameLength: i.GetMinLoginNameLength(),
MinPasswordLength: i.GetMinPasswordLength(),
@ -658,6 +664,9 @@ func toAuthMethodProto(in auth.AuthMethod) (*pb.AuthMethod, error) {
out.Attributes = st
case *oidc.AuthMethod:
out.Type = auth.OidcSubtype.String()
if anonListing {
break
}
attrs := &pb.OidcAuthMethodAttributes{
ClientId: wrapperspb.String(i.GetClientId()),
ClientSecretHmac: i.ClientSecretHmac,

@ -350,7 +350,8 @@ func TestList(t *testing.T) {
s, err := authmethods.NewService(kmsCache, pwRepoFn, oidcRepoFn, iamRepoFn, atRepoFn)
require.NoError(err, "Couldn't create new auth_method service.")
got, gErr := s.ListAuthMethods(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId()), tc.req)
// First check with non-anonymous user
got, gErr := s.ListAuthMethods(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId(), auth.WithUserId("u_auth")), tc.req)
if tc.err != nil {
require.Error(gErr)
assert.True(errors.Is(gErr, tc.err), "ListAuthMethods() for scope %q got error %v, wanted %v", tc.req.GetScopeId(), gErr, tc.err)
@ -365,6 +366,21 @@ func TestList(t *testing.T) {
}
}
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListAuthMethods() for scope %q got response %q, wanted %q", tc.req.GetScopeId(), got, tc.res)
// Now check with anonymous user
got, gErr = s.ListAuthMethods(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId()), tc.req)
if tc.err != nil {
require.Error(gErr)
assert.True(errors.Is(gErr, tc.err), "ListAuthMethods() for scope %q got error %v, wanted %v", tc.req.GetScopeId(), gErr, tc.err)
return
}
require.NoError(gErr)
for _, g := range got.Items {
assert.Nil(g.Attributes)
assert.Nil(g.CreatedTime)
assert.Nil(g.UpdatedTime)
assert.Empty(g.Version)
}
})
}
}

@ -36,4 +36,14 @@ func Test_GetOpts(t *testing.T) {
opts = GetOpts(WithLogger(hclog.New(nil)))
assert.NotNil(opts.WithLogger)
})
t.Run("WithAnonymousListing", func(t *testing.T) {
assert := assert.New(t)
opts := GetOpts()
assert.False(opts.WithAnonymousListing)
opts = GetOpts(WithAnonymousListing(true))
assert.True(opts.WithAnonymousListing)
})
}

@ -20,6 +20,7 @@ type Option func(*options)
type options struct {
withDiscardUnknownFields bool
WithLogger hclog.Logger
WithAnonymousListing bool
}
func getDefaultOptions() options {
@ -41,3 +42,11 @@ func WithLogger(logger hclog.Logger) Option {
o.WithLogger = logger
}
}
// WithAnonymousListing provides an option when creating responses to only include those
// desired for listing to anonymous users.
func WithAnonymousListing(anonListing bool) Option {
return func(o *options) {
o.WithAnonymousListing = anonListing
}
}

Loading…
Cancel
Save