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.
This commit is contained in:
1 parent
344880dafc
commit
604d642e1e
4 files changed
+57
-13
No files matched your search
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user