Managed Groups OIDC Repo (#1254)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2021-06-01 15:12:34 -04:00
1 parent 15bd1a5245
commit 7da892a054
17 files changed
+1660 -45

No files matched your search

@@ -116,7 +116,10 @@ func TestFetchActionSetForId(t *testing.T) {
func TestRecursiveListingDifferentOutputFields(t *testing.T) {
require, assert := require.New(t), assert.New(t)
tc := controller.NewTestController(t, nil)
tc := controller.NewTestController(t, &controller.TestControllerOpts{
// Disable this to avoid having to deal with sorting them in the test
DisableOidcAuthMethodCreation: true,
})
defer tc.Shutdown()
conn := tc.DbConn()
+11
View File
@@ -10,6 +10,8 @@ const (
AuthMethodPrefix = "amoidc"
// AccountPrefix defines the prefix for Account public ids.
AccountPrefix = "acctoidc"
// ManagedGroupPrefix defines the prefix for ManagedGroup public ids.
ManagedGroupPrefix = "mgoidc"
)
func newAuthMethodId() (string, error) {
@@ -38,3 +40,12 @@ func newAccountId(authMethodId, issuer, sub string) (string, error) {
}
return id, nil
}
func newManagedGroupId() (string, error) {
const op = "oidc.newManagedGroupId"
id, err := db.NewPublicId(ManagedGroupPrefix)
if err != nil {
return "", errors.Wrap(err, op)
}
return id, nil
}
+98
View File
@@ -0,0 +1,98 @@
package oidc
import (
"github.com/hashicorp/boundary/internal/auth/oidc/store"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/go-bexpr"
"google.golang.org/protobuf/proto"
)
// defaultManagedGroupTableName defines the default table name for a Managed Group
const defaultManagedGroupTableName = "auth_oidc_managed_group"
// ManagedGroup contains an OIDC managed group. It is assigned to an OIDC AuthMethod
// and updates/deletes to that AuthMethod are cascaded to its Managed Groups.
type ManagedGroup struct {
*store.ManagedGroup
tableName string
}
// NewManagedGroup creates a new in memory ManagedGroup assigned to OIDC
// AuthMethod. Supported options are withName and withDescription.
func NewManagedGroup(authMethodId string, filter string, opt ...Option) (*ManagedGroup, error) {
const op = "oidc.NewManagedGroup"
opts := getOpts(opt...)
mg := &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethodId,
Name: opts.withName,
Description: opts.withDescription,
Filter: filter,
},
}
if err := mg.validate(op); err != nil {
return nil, err // intentionally not wrapped.
}
return mg, nil
}
// validate the Managed Group. On success, it will return nil.
func (mg *ManagedGroup) validate(caller errors.Op) error {
if mg.AuthMethodId == "" {
return errors.New(errors.InvalidParameter, caller, "missing auth method id")
}
if mg.Filter == "" {
return errors.New(errors.InvalidParameter, caller, "missing filter")
}
if _, err := bexpr.CreateEvaluator(mg.Filter); err != nil {
return errors.New(errors.InvalidParameter, caller, "error evaluating filter expression", errors.WithWrap(err))
}
return nil
}
// AllocManagedGroup makes an empty one in memory
func AllocManagedGroup() *ManagedGroup {
return &ManagedGroup{
ManagedGroup: &store.ManagedGroup{},
}
}
// Clone a ManagedGroup.
func (mg *ManagedGroup) Clone() *ManagedGroup {
cp := proto.Clone(mg.ManagedGroup)
return &ManagedGroup{
ManagedGroup: cp.(*store.ManagedGroup),
}
}
// TableName returns the table name.
func (mg *ManagedGroup) TableName() string {
if mg.tableName != "" {
return mg.tableName
}
return defaultManagedGroupTableName
}
// SetTableName sets the table name.
func (mg *ManagedGroup) SetTableName(n string) {
mg.tableName = n
}
// oplog will create oplog metadata for the ManagedGroup.
func (c *ManagedGroup) oplog(op oplog.OpType, authMethodScopeId string) oplog.Metadata {
metadata := oplog.Metadata{
"resource-public-id": []string{c.GetPublicId()},
"resource-type": []string{"oidc managed group"},
"op-type": []string{op.String()},
}
if c.AuthMethodId != "" {
metadata["auth-method-id"] = []string{c.AuthMethodId}
}
if authMethodScopeId != "" {
metadata["scope-id"] = []string{authMethodScopeId}
}
return metadata
}
+32
View File
@@ -0,0 +1,32 @@
package oidc
import (
"testing"
"github.com/hashicorp/boundary/internal/errors"
"github.com/stretchr/testify/assert"
)
func Test_ManagedGroups_RepoValidate(t *testing.T) {
t.Parallel()
assert := assert.New(t)
const op = "test"
mg := AllocManagedGroup()
t.Run("empty auth method", func(t *testing.T) {
assert.Contains(mg.validate(op).Error(), errors.New(errors.InvalidParameter, op, "missing auth method id").Error())
})
t.Run("empty filter", func(t *testing.T) {
mg.AuthMethodId = "amoidc_1234567890"
assert.Contains(mg.validate(op).Error(), errors.New(errors.InvalidParameter, op, "missing filter").Error())
})
t.Run("bad filter", func(t *testing.T) {
mg.AuthMethodId = "amoidc_1234567890"
mg.Filter = "foobar"
assert.Contains(mg.validate(op).Error(), errors.New(errors.InvalidParameter, op, "error evaluating filter expression").Error())
})
t.Run("valid", func(t *testing.T) {
mg.AuthMethodId = "amoidc_1234567890"
mg.Filter = testFakeFilter
assert.NoError(mg.validate(op))
})
}
@@ -67,7 +67,7 @@ func TestRepository_CreateAccount(t *testing.T) {
wantErrMsg: "oidc.(Repository).CreateAccount: missing embedded Account: parameter violation: error #100",
},
{
name: "invalid-no-scope-id",
name: "invalid-no-auth-method-id",
in: &Account{
Account: &store.Account{},
},
@@ -21,6 +21,7 @@ const (
VersionField = "Version"
NameField = "Name"
DescriptionField = "Description"
FilterField = "Filter"
IssuerField = "Issuer"
ClientIdField = "ClientId"
ClientSecretField = "ClientSecret"
@@ -0,0 +1,251 @@
package oidc
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/boundary/internal/db"
dbcommon "github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
)
// CreateManagedGroup inserts an ManagedGroup, mg, into the repository and
// returns a new ManagedGroup containing its PublicId. mg is not changed. mg
// must contain a valid AuthMethodId. mg must not contain a PublicId. The
// PublicId is generated and assigned by this method.
//
// Both mg.Name and mg.Description are optional. If mg.Name is set, it must be
// unique within mg.AuthMethodId.
func (r *Repository) CreateManagedGroup(ctx context.Context, scopeId string, mg *ManagedGroup, opt ...Option) (*ManagedGroup, error) {
const op = "oidc.(Repository).CreateManagedGroup"
if mg == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing ManagedGroup")
}
if mg.ManagedGroup == nil {
return nil, errors.New(errors.InvalidParameter, op, "missing embedded ManagedGroup")
}
if mg.AuthMethodId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing auth method id")
}
if mg.Filter == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing filter")
}
if mg.PublicId != "" {
return nil, errors.New(errors.InvalidParameter, op, "public id must be empty")
}
if scopeId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing scope id")
}
mg = mg.Clone()
id, err := newManagedGroupId()
if err != nil {
return nil, errors.Wrap(err, op)
}
mg.PublicId = id
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
if err != nil {
return nil, errors.Wrap(err, op, errors.WithMsg("unable to get oplog wrapper"), errors.WithCode(errors.Encrypt))
}
var newManagedGroup *ManagedGroup
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
newManagedGroup = mg.Clone()
if err := w.Create(ctx, newManagedGroup, db.WithOplog(oplogWrapper, mg.oplog(oplog.OpType_OP_TYPE_CREATE, scopeId))); err != nil {
return errors.Wrap(err, op)
}
return nil
},
)
if err != nil {
if errors.IsUniqueError(err) {
return nil, errors.New(errors.NotUnique, op, fmt.Sprintf(
"in auth method %s: name %q already exists",
mg.AuthMethodId, mg.Name))
}
return nil, errors.Wrap(err, op, errors.WithMsg(mg.AuthMethodId))
}
return newManagedGroup, nil
}
// LookupManagedGroup will look up a managed group in the repository. If the managed group is not
// found, it will return nil, nil. All options are ignored.
func (r *Repository) LookupManagedGroup(ctx context.Context, withPublicId string, opt ...Option) (*ManagedGroup, error) {
const op = "oidc.(Repository).LookupManagedGroup"
if withPublicId == "" {
return nil, errors.New(errors.InvalidPublicId, op, "missing public id")
}
a := AllocManagedGroup()
a.PublicId = withPublicId
if err := r.reader.LookupByPublicId(ctx, a); err != nil {
if errors.IsNotFoundError(err) {
return nil, nil
}
return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", withPublicId)))
}
return a, nil
}
// ListManagedGroups in an auth method and supports WithLimit option.
func (r *Repository) ListManagedGroups(ctx context.Context, withAuthMethodId string, opt ...Option) ([]*ManagedGroup, error) {
const op = "oidc.(Repository).ListManagedGroups"
if withAuthMethodId == "" {
return nil, errors.New(errors.InvalidParameter, op, "missing auth method id")
}
opts := getOpts(opt...)
limit := r.defaultLimit
if opts.withLimit != 0 {
// non-zero signals an override of the default limit for the repo.
limit = opts.withLimit
}
var mgs []*ManagedGroup
err := r.reader.SearchWhere(ctx, &mgs, "auth_method_id = ?", []interface{}{withAuthMethodId}, db.WithLimit(limit))
if err != nil {
return nil, errors.Wrap(err, op)
}
return mgs, nil
}
// DeleteManagedGroup deletes the managed group for the provided id from the
// repository returning a count of the number of records deleted. All options
// are ignored.
func (r *Repository) DeleteManagedGroup(ctx context.Context, scopeId, withPublicId string, opt ...Option) (int, error) {
const op = "oidc.(Repository).DeleteManagedGroup"
if withPublicId == "" {
return db.NoRowsAffected, errors.New(errors.InvalidPublicId, op, "missing public id")
}
if scopeId == "" {
return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing scope id")
}
mg := AllocManagedGroup()
mg.PublicId = withPublicId
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
if err != nil {
return db.NoRowsAffected, errors.Wrap(err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("unable to get oplog wrapper"))
}
var rowsDeleted int
_, err = r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(_ db.Reader, w db.Writer) (err error) {
metadata := mg.oplog(oplog.OpType_OP_TYPE_DELETE, scopeId)
dMg := mg.Clone()
rowsDeleted, err = w.Delete(ctx, dMg, db.WithOplog(oplogWrapper, metadata))
if err != nil {
return errors.Wrap(err, op)
}
if rowsDeleted > 1 {
return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted")
}
return nil
},
)
if err != nil {
return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(withPublicId))
}
return rowsDeleted, nil
}
// UpdateManagedGroup updates the repository entry for mg.PublicId with the
// values in mg for the fields listed in fieldMaskPaths. It returns a new
// ManagedGroup containing the updated values and a count of the number of
// records updated. mg is not changed.
//
// mg must contain a valid PublicId. Only mg.Name, mg.Description, and mg.Filter
// can be updated. If mg.Name is set to a non-empty string, it must be unique
// within mg.AuthMethodId.
//
// An attribute of a will be set to NULL in the database if the attribute in a
// is the zero value and it is included in fieldMaskPaths.
func (r *Repository) UpdateManagedGroup(ctx context.Context, scopeId string, mg *ManagedGroup, version uint32, fieldMaskPaths []string, opt ...Option) (*ManagedGroup, int, error) {
const op = "oidc.(Repository).UpdateManagedGroup"
if mg == nil {
return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing ManagedGroup")
}
if mg.ManagedGroup == nil {
return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing embedded ManagedGroup")
}
if mg.PublicId == "" {
return nil, db.NoRowsAffected, errors.New(errors.InvalidPublicId, op, "missing public id")
}
if version == 0 {
return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing version")
}
if scopeId == "" {
return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing scope id")
}
for _, f := range fieldMaskPaths {
switch {
case strings.EqualFold(NameField, f):
case strings.EqualFold(DescriptionField, f):
case strings.EqualFold(FilterField, f):
default:
return nil, db.NoRowsAffected, errors.New(errors.InvalidFieldMask, op, f)
}
}
var dbMask, nullFields []string
dbMask, nullFields = dbcommon.BuildUpdatePaths(
map[string]interface{}{
NameField: mg.Name,
DescriptionField: mg.Description,
FilterField: mg.Filter,
},
fieldMaskPaths,
nil,
)
if len(dbMask) == 0 && len(nullFields) == 0 {
return nil, db.NoRowsAffected, errors.New(errors.EmptyFieldMask, op, "missing field mask")
}
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
if err != nil {
return nil, db.NoRowsAffected, errors.Wrap(err, op, errors.WithCode(errors.Encrypt),
errors.WithMsg(("unable to get oplog wrapper")))
}
mg = mg.Clone()
metadata := mg.oplog(oplog.OpType_OP_TYPE_UPDATE, scopeId)
// TODO/FIXME: if the filter is updated, remove all account/mg associations
var rowsUpdated int
var returnedManagedGroup *ManagedGroup
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
returnedManagedGroup = mg.Clone()
var err error
rowsUpdated, err = w.Update(ctx, returnedManagedGroup, dbMask, nullFields, db.WithOplog(oplogWrapper, metadata), db.WithVersion(&version))
if err != nil {
return errors.Wrap(err, op)
}
if rowsUpdated > 1 {
return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been updated")
}
return nil
},
)
if err != nil {
if errors.IsUniqueError(err) {
return nil, db.NoRowsAffected, errors.New(errors.NotUnique, op,
fmt.Sprintf("name %s already exists: %s", mg.Name, mg.PublicId))
}
return nil, db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(mg.PublicId))
}
return returnedManagedGroup, rowsUpdated, nil
}
@@ -0,0 +1,972 @@
package oidc
import (
"context"
"fmt"
"sort"
"strings"
"testing"
"time"
"github.com/hashicorp/boundary/internal/auth/oidc/store"
"github.com/hashicorp/boundary/internal/db"
dbassert "github.com/hashicorp/boundary/internal/db/assert"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const testFakeFilter = `"/foo" == "bar"`
func TestRepository_CreateManagedGroup(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
ctx := context.Background()
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
authMethod := TestAuthMethod(
t, conn, databaseWrapper, org.GetPublicId(), ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
tests := []struct {
name string
scopeId string
in *ManagedGroup
opts []Option
want *ManagedGroup
wantIsErr errors.Code
wantErrMsg string
wantErrContains string
}{
{
name: "nil-ManagedGroup",
scopeId: org.GetPublicId(),
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: missing ManagedGroup: parameter violation: error #100",
},
{
name: "nil-embedded-ManagedGroup",
scopeId: org.GetPublicId(),
in: &ManagedGroup{},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: missing embedded ManagedGroup: parameter violation: error #100",
},
{
name: "invalid-no-auth-method-id",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{},
},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: missing auth method id: parameter violation: error #100",
},
{
name: "invalid-no-filter",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
},
},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: missing filter: parameter violation: error #100",
},
{
name: "invalid-public-id-set",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
PublicId: "mgoidc_OOOOOOOOOO",
},
},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: public id must be empty: parameter violation: error #100",
},
{
name: "no-scope",
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
},
},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).CreateManagedGroup: missing scope id: parameter violation: error #100",
},
{
name: "valid-no-options",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
},
},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
},
},
},
{
name: "valid-with-name",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
Name: "test-name-repo",
},
},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
Name: "test-name-repo",
},
},
},
{
name: "valid-with-description",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
Description: ("test-description-repo"),
Name: "myname",
},
},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
Description: ("test-description-repo"),
Name: "myname",
},
},
},
{
name: "duplicate-name",
scopeId: org.GetPublicId(),
in: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethod.PublicId,
Filter: testFakeFilter,
Description: ("test-description-repo"),
Name: "myname",
},
},
wantIsErr: errors.NotUnique,
wantErrContains: `name "myname" already exists`,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache)
assert.NoError(err)
require.NotNil(repo)
got, err := repo.CreateManagedGroup(context.Background(), tt.scopeId, tt.in, tt.opts...)
if tt.wantIsErr != 0 {
require.Error(err)
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "Unexpected error %s", err)
if tt.wantErrContains != "" {
assert.True(strings.Contains(err.Error(), tt.wantErrContains))
} else {
assert.Equal(tt.wantErrMsg, err.Error())
}
return
}
require.NoError(err)
assert.Empty(tt.in.PublicId)
require.NotNil(got)
assertPublicId(t, ManagedGroupPrefix, got.PublicId)
assert.NotSame(tt.in, got)
assert.Equal(tt.want.Name, got.Name)
assert.Equal(tt.want.Description, got.Description)
assert.Equal(got.CreateTime, got.UpdateTime)
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
})
}
}
func TestRepository_LookupManagedGroup(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
ctx := context.Background()
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
authMethod := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
mg := TestManagedGroup(t, conn, authMethod, testFakeFilter)
newMgId, err := newManagedGroupId()
require.NoError(t, err)
tests := []struct {
name string
in string
want *ManagedGroup
wantIsErr errors.Code
wantErrMsg string
}{
{
name: "With no public id",
wantIsErr: errors.InvalidPublicId,
wantErrMsg: "oidc.(Repository).LookupManagedGroup: missing public id: parameter violation: error #102",
},
{
name: "With non existing mg id",
in: newMgId,
},
{
name: "With existing mg id",
in: mg.GetPublicId(),
want: mg,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache)
assert.NoError(err)
require.NotNil(repo)
got, err := repo.LookupManagedGroup(context.Background(), tt.in)
if tt.wantIsErr != 0 {
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "Unexpected error %s", err)
assert.Equal(tt.wantErrMsg, err.Error())
return
}
require.NoError(err)
assert.EqualValues(tt.want, got)
})
}
}
func TestRepository_DeleteManagedGroup(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
ctx := context.Background()
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
authMethod := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
mg := TestManagedGroup(t, conn, authMethod, testFakeFilter)
newMgId, err := newManagedGroupId()
require.NoError(t, err)
tests := []struct {
name string
scopeId string
in string
want int
wantIsErr errors.Code
wantErrMsg string
}{
{
name: "With no scope id",
scopeId: "",
in: mg.GetPublicId(),
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).DeleteManagedGroup: missing scope id: parameter violation: error #100",
},
{
name: "With no public id",
scopeId: org.GetPublicId(),
wantIsErr: errors.InvalidPublicId,
wantErrMsg: "oidc.(Repository).DeleteManagedGroup: missing public id: parameter violation: error #102",
},
{
name: "With non existing managed group id",
scopeId: org.GetPublicId(),
in: newMgId,
want: 0,
},
{
name: "With existing managed group id",
scopeId: org.GetPublicId(),
in: mg.GetPublicId(),
want: 1,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache)
assert.NoError(err)
require.NotNil(repo)
got, err := repo.DeleteManagedGroup(context.Background(), tt.scopeId, tt.in)
if tt.wantIsErr != 0 {
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "Unexpected error %s", err)
assert.Equal(tt.wantErrMsg, err.Error())
return
}
require.NoError(err)
assert.EqualValues(tt.want, got)
})
}
}
func TestRepository_ListManagedGroups(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
ctx := context.Background()
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
authMethod1 := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice1.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
authMethod2 := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice2.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
authMethod3 := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice3.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
mgs1 := []*ManagedGroup{
TestManagedGroup(t, conn, authMethod1, testFakeFilter),
TestManagedGroup(t, conn, authMethod1, testFakeFilter),
TestManagedGroup(t, conn, authMethod1, testFakeFilter),
}
sort.Slice(mgs1, func(i, j int) bool {
return strings.Compare(mgs1[i].PublicId, mgs1[j].PublicId) < 0
})
mgs2 := []*ManagedGroup{
TestManagedGroup(t, conn, authMethod2, testFakeFilter),
TestManagedGroup(t, conn, authMethod2, testFakeFilter),
TestManagedGroup(t, conn, authMethod2, testFakeFilter),
}
sort.Slice(mgs2, func(i, j int) bool {
return strings.Compare(mgs2[i].PublicId, mgs2[j].PublicId) < 0
})
tests := []struct {
name string
in string
opts []Option
want []*ManagedGroup
wantIsErr errors.Code
wantErrMsg string
}{
{
name: "With no auth method id",
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).ListManagedGroups: missing auth method id: parameter violation: error #100",
},
{
name: "With no managed groups",
in: authMethod3.GetPublicId(),
want: []*ManagedGroup{},
},
{
name: "With first auth method id",
in: authMethod1.GetPublicId(),
want: mgs1,
},
{
name: "With first auth method id",
in: authMethod2.GetPublicId(),
want: mgs2,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache)
assert.NoError(err)
require.NotNil(repo)
got, err := repo.ListManagedGroups(context.Background(), tt.in, tt.opts...)
if tt.wantIsErr != 0 {
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "Unexpected error %s", err)
assert.Equal(tt.wantErrMsg, err.Error())
return
}
require.NoError(err)
sort.Slice(got, func(i, j int) bool {
return strings.Compare(got[i].PublicId, got[j].PublicId) < 0
})
assert.EqualValues(tt.want, got)
})
}
}
func TestRepository_ListManagedGroups_Limits(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
ctx := context.Background()
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
am := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice1.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
mgCount := 10
for i := 0; i < mgCount; i++ {
TestManagedGroup(t, conn, am, fmt.Sprintf(`"/foo/%d" == "bar"`, i))
}
tests := []struct {
name string
repoOpts []Option
listOpts []Option
wantLen int
}{
{
name: "With no limits",
wantLen: mgCount,
},
{
name: "With repo limit",
repoOpts: []Option{WithLimit(3)},
wantLen: 3,
},
{
name: "With negative repo limit",
repoOpts: []Option{WithLimit(-1)},
wantLen: mgCount,
},
{
name: "With List limit",
listOpts: []Option{WithLimit(3)},
wantLen: 3,
},
{
name: "With negative List limit",
listOpts: []Option{WithLimit(-1)},
wantLen: mgCount,
},
{
name: "With repo smaller than list limit",
repoOpts: []Option{WithLimit(2)},
listOpts: []Option{WithLimit(6)},
wantLen: 6,
},
{
name: "With repo larger than list limit",
repoOpts: []Option{WithLimit(6)},
listOpts: []Option{WithLimit(2)},
wantLen: 2,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache, tt.repoOpts...)
assert.NoError(err)
require.NotNil(repo)
got, err := repo.ListManagedGroups(context.Background(), am.GetPublicId(), tt.listOpts...)
require.NoError(err)
assert.Len(got, tt.wantLen)
})
}
}
func TestRepository_UpdateManagedGroup(t *testing.T) {
ctx := context.Background()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kmsCache := kms.TestKms(t, conn, wrapper)
iamRepo := iam.TestRepo(t, conn, wrapper)
org, _ := iam.TestScopes(t, iamRepo)
databaseWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase)
require.NoError(t, err)
am := TestAuthMethod(
t, conn, databaseWrapper, org.PublicId, ActivePrivateState,
"alice-rp", "fido",
WithSigningAlgs(RS256),
WithIssuer(TestConvertToUrls(t, "https://www.alice.com")[0]),
WithApiUrl(TestConvertToUrls(t, "https://www.alice.com/callback")[0]),
)
changeName := func(s string) func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
mg.Name = s
return mg
}
}
changeDescription := func(s string) func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
mg.Description = s
return mg
}
}
changeFilter := func(s string) func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
mg.Filter = s
return mg
}
}
makeNil := func() func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
return nil
}
}
makeEmbeddedNil := func() func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
return &ManagedGroup{}
}
}
deletePublicId := func() func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
mg.PublicId = ""
return mg
}
}
nonExistentPublicId := func() func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
mg.PublicId = "abcd_OOOOOOOOOO"
return mg
}
}
combine := func(fns ...func(mg *ManagedGroup) *ManagedGroup) func(*ManagedGroup) *ManagedGroup {
return func(mg *ManagedGroup) *ManagedGroup {
for _, fn := range fns {
mg = fn(mg)
}
return mg
}
}
tests := []struct {
name string
scopeId string
version uint32
orig *ManagedGroup
chgFn func(*ManagedGroup) *ManagedGroup
masks []string
want *ManagedGroup
wantCount int
wantIsErr errors.Code
wantErrMsg string
wantErrContains string
}{
{
name: "nil-ManagedGroup",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{},
},
chgFn: makeNil(),
masks: []string{NameField, DescriptionField},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing ManagedGroup: parameter violation: error #100",
},
{
name: "nil-embedded-ManagedGroup",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{},
},
chgFn: makeEmbeddedNil(),
masks: []string{NameField, DescriptionField},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing embedded ManagedGroup: parameter violation: error #100",
},
{
name: "no-scope-id",
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "no-scope-id-test-name-repo",
},
},
chgFn: changeName("no-scope-id-test-update-name-repo"),
masks: []string{NameField},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing scope id: parameter violation: error #100",
},
{
name: "missing-version",
scopeId: org.GetPublicId(),
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "missing-version-test-name-repo",
},
},
chgFn: changeName("test-update-name-repo"),
masks: []string{NameField},
wantIsErr: errors.InvalidParameter,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing version: parameter violation: error #100",
},
{
name: "no-public-id",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{},
},
chgFn: deletePublicId(),
masks: []string{NameField, DescriptionField},
wantIsErr: errors.InvalidPublicId,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing public id: parameter violation: error #102",
},
{
name: "updating-non-existent-ManagedGroup",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "updating-non-existent-ManagedGroup-test-name-repo",
},
},
chgFn: combine(nonExistentPublicId(), changeName("updating-non-existent-ManagedGroup-test-update-name-repo")),
masks: []string{NameField},
wantIsErr: errors.RecordNotFound,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: abcd_OOOOOOOOOO: db.DoTx: oidc.(Repository).UpdateManagedGroup: db.Update: db.lookupAfterWrite: db.LookupById: record not found, search issue: error #1100",
},
{
name: "empty-field-mask",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "empty-field-mask-test-name-repo",
},
},
chgFn: changeName("empty-field-mask-test-update-name-repo"),
wantIsErr: errors.EmptyFieldMask,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: missing field mask: parameter violation: error #104",
},
{
name: "read-only-fields-in-field-mask",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "read-only-fields-in-field-mask-test-name-repo",
},
},
chgFn: changeName("read-only-fields-in-field-mask-test-update-name-repo"),
masks: []string{"PublicId", "CreateTime", "UpdateTime", "AuthMethodId"},
wantIsErr: errors.InvalidFieldMask,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: PublicId: parameter violation: error #103",
},
{
name: "unknown-field-in-field-mask",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "unknown-field-in-field-mask-test-name-repo",
},
},
chgFn: changeName("unknown-field-in-field-mask-test-update-name-repo"),
masks: []string{"Bilbo"},
wantIsErr: errors.InvalidFieldMask,
wantErrMsg: "oidc.(Repository).UpdateManagedGroup: Bilbo: parameter violation: error #103",
},
{
name: "change-name",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "change-name-test-name-repo",
},
},
chgFn: changeName("change-name-test-update-name-repo"),
masks: []string{NameField},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "change-name-test-update-name-repo",
},
},
wantCount: 1,
},
{
name: "change-description",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Description: "test-description-repo",
},
},
chgFn: changeDescription("test-update-description-repo"),
masks: []string{DescriptionField},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Description: "test-update-description-repo",
},
},
wantCount: 1,
},
{
name: "change-filter",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Filter: testFakeFilter,
},
},
chgFn: changeFilter(`"/zip" == "zap"`),
masks: []string{FilterField},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Filter: `"/zip" == "zap"`,
},
},
wantCount: 1,
},
{
name: "change-name-and-description",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "change-name-and-description-test-name-repo",
Description: "test-description-repo",
},
},
chgFn: combine(changeDescription("test-update-description-repo"), changeName("change-name-and-description-test-update-name-repo")),
masks: []string{NameField, DescriptionField},
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "change-name-and-description-test-update-name-repo",
Description: "test-update-description-repo",
},
},
wantCount: 1,
},
{
name: "delete-name",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "delete-name-test-name-repo",
Description: "test-description-repo",
},
},
masks: []string{NameField},
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Description: "test-description-repo",
},
},
wantCount: 1,
},
{
name: "delete-description",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "delete-description-test-name-repo",
Description: "test-description-repo",
},
},
masks: []string{DescriptionField},
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "delete-description-test-name-repo",
},
},
wantCount: 1,
},
{
name: "delete-filter",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Filter: testFakeFilter,
},
},
masks: []string{FilterField},
chgFn: combine(changeFilter("")),
wantIsErr: errors.NotNull,
wantErrContains: "oidc.(Repository).UpdateManagedGroup: db.Update: filter must not be empty: not null constraint violated: integrity violation: error #1001",
},
{
name: "do-not-delete-name",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "do-not-delete-name-test-name-repo",
Description: "test-description-repo",
},
},
masks: []string{DescriptionField},
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "do-not-delete-name-test-name-repo",
Description: "test-update-description-repo",
},
},
wantCount: 1,
},
{
name: "do-not-delete-description",
scopeId: org.GetPublicId(),
version: 1,
orig: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "do-not-delete-description-test-name-repo",
Description: "test-description-repo",
},
},
masks: []string{NameField},
chgFn: combine(changeDescription(""), changeName("do-not-delete-description-test-update-name-repo")),
want: &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
Name: "do-not-delete-description-test-update-name-repo",
Description: "test-description-repo",
},
},
wantCount: 1,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
repo, err := NewRepository(rw, rw, kmsCache)
assert.NoError(err)
require.NotNil(repo)
orig := TestManagedGroup(t, conn, am, testFakeFilter, WithName(tt.orig.GetName()), WithDescription(tt.orig.GetDescription()))
tt.orig.AuthMethodId = am.PublicId
if tt.chgFn != nil {
orig = tt.chgFn(orig)
}
got, gotCount, err := repo.UpdateManagedGroup(context.Background(), tt.scopeId, orig, tt.version, tt.masks)
if tt.wantIsErr != 0 {
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "want err: %q got: %q", tt.wantIsErr, err)
if tt.wantErrContains != "" {
assert.True(strings.Contains(err.Error(), tt.wantErrContains))
} else {
assert.Equal(tt.wantErrMsg, err.Error())
}
assert.Equal(tt.wantCount, gotCount, "row count")
assert.Nil(got)
return
}
assert.NoError(err)
assert.Empty(tt.orig.PublicId)
if tt.wantCount == 0 {
assert.Equal(tt.wantCount, gotCount, "row count")
assert.Nil(got)
return
}
require.NotNil(got)
assertPublicId(t, ManagedGroupPrefix, got.PublicId)
assert.Equal(tt.wantCount, gotCount, "row count")
assert.NotSame(tt.orig, got)
assert.Equal(tt.orig.AuthMethodId, got.AuthMethodId)
dbassert := dbassert.New(t, conn.DB())
if tt.want.Name == "" {
dbassert.IsNull(got, "name")
return
}
assert.Equal(tt.want.Name, got.Name)
if tt.want.Description == "" {
dbassert.IsNull(got, "description")
return
}
assert.Equal(tt.want.Description, got.Description)
if tt.wantCount > 0 {
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second)))
}
})
}
}
+184 -22
View File
@@ -829,6 +829,125 @@ func (x *AccountClaimMap) GetCreateTime() *timestamp.Timestamp {
return nil
}
// ManagedGroup entries provide an OIDC auth method implementation of managed
// groups.
type ManagedGroup struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// @inject_tag: `gorm:"primary_key"`
PublicId string `protobuf:"bytes,10,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
// The create_time is set by the database.
// @inject_tag: `gorm:"default:current_timestamp"`
CreateTime *timestamp.Timestamp `protobuf:"bytes,20,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
// The update_time is set by the database.
// @inject_tag: `gorm:"default:current_timestamp"`
UpdateTime *timestamp.Timestamp `protobuf:"bytes,30,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
// name is optional. If set, it must be unique within auth_method_id.
// @inject_tag: `gorm:"default:null"`
Name string `protobuf:"bytes,40,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
// description is optional.
// @inject_tag: `gorm:"default:null"`
Description string `protobuf:"bytes,50,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
// @inject_tag: `gorm:"default:null"`
Version uint32 `protobuf:"varint,60,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
// auth_method_id is the fk to the account's auth method.
// @inject_tag: `gorm:"not_null"`
AuthMethodId string `protobuf:"bytes,70,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty" gorm:"not_null"`
// filter is a go-bexpr filter
// @inject_tag: `gorm:"not_null"`
Filter string `protobuf:"bytes,80,opt,name=filter,proto3" json:"filter,omitempty" gorm:"not_null"`
}
func (x *ManagedGroup) Reset() {
*x = ManagedGroup{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_storage_auth_oidc_store_v1_oidc_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ManagedGroup) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ManagedGroup) ProtoMessage() {}
func (x *ManagedGroup) ProtoReflect() protoreflect.Message {
mi := &file_controller_storage_auth_oidc_store_v1_oidc_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ManagedGroup.ProtoReflect.Descriptor instead.
func (*ManagedGroup) Descriptor() ([]byte, []int) {
return file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDescGZIP(), []int{7}
}
func (x *ManagedGroup) GetPublicId() string {
if x != nil {
return x.PublicId
}
return ""
}
func (x *ManagedGroup) GetCreateTime() *timestamp.Timestamp {
if x != nil {
return x.CreateTime
}
return nil
}
func (x *ManagedGroup) GetUpdateTime() *timestamp.Timestamp {
if x != nil {
return x.UpdateTime
}
return nil
}
func (x *ManagedGroup) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ManagedGroup) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *ManagedGroup) GetVersion() uint32 {
if x != nil {
return x.Version
}
return 0
}
func (x *ManagedGroup) GetAuthMethodId() string {
if x != nil {
return x.AuthMethodId
}
return ""
}
func (x *ManagedGroup) GetFilter() string {
if x != nil {
return x.Filter
}
return ""
}
var File_controller_storage_auth_oidc_store_v1_oidc_proto protoreflect.FileDescriptor
var file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDesc = []byte{
@@ -1012,11 +1131,39 @@ var file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDesc = []byte{
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54,
0x69, 0x6d, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e,
0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x75,
0x74, 0x68, 0x2f, 0x6f, 0x69, 0x64, 0x63, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74,
0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x6d, 0x65, 0x22, 0xbf, 0x03, 0x0a, 0x0c, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69,
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49,
0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b,
0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a,
0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x40, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x3c,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a,
0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18,
0x46, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xc2, 0xdd, 0x29, 0x1e, 0x0a, 0x0c, 0x41, 0x75, 0x74,
0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f,
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x4d,
0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65,
0x72, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xc2, 0xdd, 0x29, 0x10, 0x0a, 0x06, 0x46,
0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66,
0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
0x61, 0x75, 0x74, 0x68, 0x2f, 0x6f, 0x69, 0x64, 0x63, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b,
0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1031,7 +1178,7 @@ func file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDescGZIP() []byte
return file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDescData
}
var file_controller_storage_auth_oidc_store_v1_oidc_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_controller_storage_auth_oidc_store_v1_oidc_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_controller_storage_auth_oidc_store_v1_oidc_proto_goTypes = []interface{}{
(*AuthMethod)(nil), // 0: controller.storage.auth.oidc.store.v1.AuthMethod
(*Account)(nil), // 1: controller.storage.auth.oidc.store.v1.Account
@@ -1040,23 +1187,26 @@ var file_controller_storage_auth_oidc_store_v1_oidc_proto_goTypes = []interface{
(*Certificate)(nil), // 4: controller.storage.auth.oidc.store.v1.Certificate
(*ClaimsScope)(nil), // 5: controller.storage.auth.oidc.store.v1.ClaimsScope
(*AccountClaimMap)(nil), // 6: controller.storage.auth.oidc.store.v1.AccountClaimMap
(*timestamp.Timestamp)(nil), // 7: controller.storage.timestamp.v1.Timestamp
(*ManagedGroup)(nil), // 7: controller.storage.auth.oidc.store.v1.ManagedGroup
(*timestamp.Timestamp)(nil), // 8: controller.storage.timestamp.v1.Timestamp
}
var file_controller_storage_auth_oidc_store_v1_oidc_proto_depIdxs = []int32{
7, // 0: controller.storage.auth.oidc.store.v1.AuthMethod.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 1: controller.storage.auth.oidc.store.v1.AuthMethod.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 2: controller.storage.auth.oidc.store.v1.Account.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 3: controller.storage.auth.oidc.store.v1.Account.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 4: controller.storage.auth.oidc.store.v1.SigningAlg.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 5: controller.storage.auth.oidc.store.v1.AudClaim.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 6: controller.storage.auth.oidc.store.v1.Certificate.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 7: controller.storage.auth.oidc.store.v1.ClaimsScope.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
7, // 8: controller.storage.auth.oidc.store.v1.AccountClaimMap.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
9, // [9:9] is the sub-list for method output_type
9, // [9:9] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
8, // 0: controller.storage.auth.oidc.store.v1.AuthMethod.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 1: controller.storage.auth.oidc.store.v1.AuthMethod.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 2: controller.storage.auth.oidc.store.v1.Account.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 3: controller.storage.auth.oidc.store.v1.Account.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 4: controller.storage.auth.oidc.store.v1.SigningAlg.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 5: controller.storage.auth.oidc.store.v1.AudClaim.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 6: controller.storage.auth.oidc.store.v1.Certificate.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 7: controller.storage.auth.oidc.store.v1.ClaimsScope.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 8: controller.storage.auth.oidc.store.v1.AccountClaimMap.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 9: controller.storage.auth.oidc.store.v1.ManagedGroup.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // 10: controller.storage.auth.oidc.store.v1.ManagedGroup.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
11, // [11:11] is the sub-list for method output_type
11, // [11:11] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
}
func init() { file_controller_storage_auth_oidc_store_v1_oidc_proto_init() }
@@ -1149,6 +1299,18 @@ func file_controller_storage_auth_oidc_store_v1_oidc_proto_init() {
return nil
}
}
file_controller_storage_auth_oidc_store_v1_oidc_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ManagedGroup); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -1156,7 +1318,7 @@ func file_controller_storage_auth_oidc_store_v1_oidc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_storage_auth_oidc_store_v1_oidc_proto_rawDesc,
NumEnums: 0,
NumMessages: 7,
NumMessages: 8,
NumExtensions: 0,
NumServices: 0,
},
+18
View File
@@ -176,6 +176,24 @@ func TestAccount(t *testing.T, conn *gorm.DB, am *AuthMethod, subject string, op
return a
}
// TestManagedGroup creates a test oidc managed group.
func TestManagedGroup(t *testing.T, conn *gorm.DB, am *AuthMethod, filter string, opt ...Option) *ManagedGroup {
t.Helper()
require := require.New(t)
rw := db.New(conn)
ctx := context.Background()
mg, err := NewManagedGroup(am.PublicId, filter, opt...)
require.NoError(err)
id, err := newManagedGroupId()
require.NoError(err)
mg.PublicId = id
require.NoError(rw.Create(ctx, mg))
return mg
}
// TestConvertToUrls will convert URL string representations to a slice of
// *url.URL
func TestConvertToUrls(t *testing.T, urls ...string) []*url.URL {
+14 -1
View File
@@ -58,6 +58,18 @@ var (
_ Account = (*password.Account)(nil)
)
type ManagedGroup interface {
GetPublicId() string
GetCreateTime() *timestamp.Timestamp
GetUpdateTime() *timestamp.Timestamp
GetName() string
GetDescription() string
GetAuthMethodId() string
GetVersion() uint32
}
var _ ManagedGroup = (*oidc.ManagedGroup)(nil)
// SubtypeFromType converts a string to a Subtype.
// returns UnknownSubtype if no Subtype with that name is found.
func SubtypeFromType(t string) Subtype {
@@ -79,7 +91,8 @@ func SubtypeFromId(id string) Subtype {
strings.HasPrefix(strings.TrimSpace(id), password.AccountPrefix):
return PasswordSubtype
case strings.HasPrefix(strings.TrimSpace(id), oidc.AuthMethodPrefix),
strings.HasPrefix(strings.TrimSpace(id), oidc.AccountPrefix):
strings.HasPrefix(strings.TrimSpace(id), oidc.AccountPrefix),
strings.HasPrefix(strings.TrimSpace(id), oidc.ManagedGroupPrefix):
return OidcSubtype
}
return UnknownSubtype
+6 -4
View File
@@ -119,8 +119,10 @@ func (b *Server) CreateDevDatabase(ctx context.Context, opt ...Option) error {
return err
}
if err := b.CreateDevOidcAuthMethod(ctx); err != nil {
return err
if !opts.withSkipOidcAuthMethodCreation {
if err := b.CreateDevOidcAuthMethod(ctx); err != nil {
return err
}
}
if opts.withSkipScopesCreation {
@@ -225,7 +227,7 @@ func (b *Server) CreateDevOidcAuthMethod(ctx context.Context) error {
// re-use it. This is a sort of hacky way to get around the chicken and egg
// of the auth method needing to know the discovery URL and the test
// provider needing to know the callback URL.
l, err := net.Listen("tcp", fmt.Sprintf("%s:0", b.DevOidcSetup.hostAddr))
l, err := net.Listen("tcp", net.JoinHostPort(b.DevOidcSetup.hostAddr, "0"))
if err != nil {
return fmt.Errorf("error finding port for oidc test provider: %w", err)
}
@@ -233,7 +235,7 @@ func (b *Server) CreateDevOidcAuthMethod(ctx context.Context) error {
if err := l.Close(); err != nil {
return fmt.Errorf("error closing initial test port: %w", err)
}
b.DevOidcSetup.callbackUrl, err = url.Parse(fmt.Sprintf("http://%s:%s", b.DevOidcSetup.hostAddr, b.DevOidcSetup.callbackPort))
b.DevOidcSetup.callbackUrl, err = url.Parse(fmt.Sprintf("http://%s", net.JoinHostPort(b.DevOidcSetup.hostAddr, b.DevOidcSetup.callbackPort)))
if err != nil {
return fmt.Errorf("error parsing oidc test provider callback url: %w", err)
}
+19 -10
View File
@@ -14,15 +14,16 @@ type Option func(*Options)
// Options - how Options are represented.
type Options struct {
withNoTokenScope bool
withNoTokenValue bool
withSkipDatabaseDestruction bool
withSkipAuthMethodCreation bool
withSkipScopesCreation bool
withSkipHostResourcesCreation bool
withSkipTargetCreation bool
withContainerImage string
withDialect string
withNoTokenScope bool
withNoTokenValue bool
withSkipDatabaseDestruction bool
withSkipAuthMethodCreation bool
withSkipOidcAuthMethodCreation bool
withSkipScopesCreation bool
withSkipHostResourcesCreation bool
withSkipTargetCreation bool
withContainerImage string
withDialect string
}
func getDefaultOptions() Options {
@@ -57,7 +58,7 @@ func WithNoTokenValue() Option {
}
}
// WithSkipAuthMethodCreation tells the command not to instantiate an auth
// WithSkipAuthMethodCreation tells the command not to instantiate any auth
// method on first run.
func WithSkipAuthMethodCreation() Option {
return func(o *Options) {
@@ -65,6 +66,14 @@ func WithSkipAuthMethodCreation() Option {
}
}
// WithSkipOidcAuthMethodCreation tells the command not to instantiate an OIDC auth
// method on first run, useful in some tests.
func WithSkipOidcAuthMethodCreation() Option {
return func(o *Options) {
o.withSkipOidcAuthMethodCreation = true
}
}
// WithSkipScopesCreation tells the command not to instantiate scopes on first
// run.
func WithSkipScopesCreation() Option {
+1 -2
View File
@@ -36,8 +36,7 @@ func testServerCommand(t *testing.T, controllerKey string) *Command {
require.NoError(err)
require.NoError(cmd.SetupKMSes(cmd.UI, parsedKmsConfig))
opts := base.WithContainerImage("postgres")
err = cmd.CreateDevDatabase(cmd.Context, opts)
err = cmd.CreateDevDatabase(cmd.Context, base.WithContainerImage("postgres"), base.WithSkipOidcAuthMethodCreation())
if err != nil {
if cmd.DevDatabaseCleanupFunc != nil {
require.NoError(cmd.DevDatabaseCleanupFunc())
@@ -251,4 +251,38 @@ message AccountClaimMap {
// The create_time is set by the database.
// @inject_tag: `gorm:"default:current_timestamp"`
timestamp.v1.Timestamp create_time = 40;
}
// ManagedGroup entries provide an OIDC auth method implementation of managed
// groups.
message ManagedGroup {
// @inject_tag: `gorm:"primary_key"`
string public_id = 10;
// The create_time is set by the database.
// @inject_tag: `gorm:"default:current_timestamp"`
timestamp.v1.Timestamp create_time = 20;
// The update_time is set by the database.
// @inject_tag: `gorm:"default:current_timestamp"`
timestamp.v1.Timestamp update_time = 30;
// name is optional. If set, it must be unique within auth_method_id.
// @inject_tag: `gorm:"default:null"`
string name = 40 [(custom_options.v1.mask_mapping) = { this: "Name" that: "name" }];
// description is optional.
// @inject_tag: `gorm:"default:null"`
string description = 50 [(custom_options.v1.mask_mapping) = { this: "Description" that: "description" }];
// @inject_tag: `gorm:"default:null"`
uint32 version = 60;
// auth_method_id is the fk to the account's auth method.
// @inject_tag: `gorm:"not_null"`
string auth_method_id = 70 [(custom_options.v1.mask_mapping) = { this: "AuthMethodId" that: "auth_method_id" }];
// filter is a go-bexpr filter
// @inject_tag: `gorm:"not_null"`
string filter = 80 [(custom_options.v1.mask_mapping) = { this: "Filter" that: "filter" }];
}
+11 -2
View File
@@ -304,6 +304,10 @@ type TestControllerOpts struct {
// method automatically.
DisableAuthMethodCreation bool
// DisableOidcAuthMethodCreation can be set true to disable the built-in
// OIDC listener. Useful for e.g. unix listener tests.
DisableOidcAuthMethodCreation bool
// DisableScopesCreation can be set true to disable creating scopes
// automatically.
DisableScopesCreation bool
@@ -510,8 +514,10 @@ func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
if _, _, err := tc.b.CreateInitialPasswordAuthMethod(ctx); err != nil {
t.Fatal(err)
}
if err := tc.b.CreateDevOidcAuthMethod(ctx); err != nil {
t.Fatal(err)
if !opts.DisableOidcAuthMethodCreation {
if err := tc.b.CreateDevOidcAuthMethod(ctx); err != nil {
t.Fatal(err)
}
}
if !opts.DisableScopesCreation {
if _, _, err := tc.b.CreateInitialScopes(ctx); err != nil {
@@ -536,6 +542,9 @@ func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
if opts.DisableAuthMethodCreation {
createOpts = append(createOpts, base.WithSkipAuthMethodCreation())
}
if opts.DisableOidcAuthMethodCreation {
createOpts = append(createOpts, base.WithSkipOidcAuthMethodCreation())
}
if err := tc.b.CreateDevDatabase(ctx, createOpts...); err != nil {
t.Fatal(err)
}
+3 -2
View File
@@ -47,8 +47,9 @@ func TestUnixListener(t *testing.T) {
}
c1 := controller.NewTestController(t, &controller.TestControllerOpts{
Config: conf,
Logger: logger.Named("c1"),
Config: conf,
Logger: logger.Named("c1"),
DisableOidcAuthMethodCreation: true,
})
defer c1.Shutdown()