Skip to content

Commit

Permalink
feature (auth/ldap): add managed groups (#2760)
Browse files Browse the repository at this point in the history
* tests (auth/ldap): add missing unit test to Repository.DeleteAccount(...)

Add bits to test the delete operation when you're not able to generate
oplog metadata

* feature (auth/ldap): add managed groups

fixup! feature (auth/ldap): add managed groups (#2760)
  • Loading branch information
jimlambrt committed Mar 15, 2023
1 parent ec85459 commit 80326af
Show file tree
Hide file tree
Showing 18 changed files with 2,301 additions and 42 deletions.
4 changes: 4 additions & 0 deletions globals/prefixes.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const (
// ids
OidcManagedGroupPrefix = "mgoidc"

// LdapManagedGroupPrefix defines the prefix for ManagedGroup public ids
// from the LDAP auth method.
LdapManagedGroupPrefix = "mgldap"

// ProjectPrefix is the prefix for project scopes
ProjectPrefix = "p"
// OrgPrefix is the prefix for org scopes
Expand Down
17 changes: 9 additions & 8 deletions internal/auth/ldap/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ func NewAccount(ctx context.Context, scopeId, authMethodId, loginName string, op
}
a := &Account{
Account: &store.Account{
ScopeId: scopeId,
AuthMethodId: authMethodId,
LoginName: loginName,
Dn: opts.withDn,
Name: opts.withName,
Description: opts.withDescription,
FullName: opts.withFullName,
Email: opts.withEmail,
ScopeId: scopeId,
AuthMethodId: authMethodId,
LoginName: loginName,
Dn: opts.withDn,
Name: opts.withName,
Description: opts.withDescription,
FullName: opts.withFullName,
Email: opts.withEmail,
MemberOfGroups: opts.withMemberOfGroups,
},
}
if err := a.validate(ctx, op); err != nil {
Expand Down
18 changes: 10 additions & 8 deletions internal/auth/ldap/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,19 @@ func TestNewAccount(t *testing.T) {
WithEmail(testCtx, "alice@bob.com"),
WithFullName(testCtx, "alice eve smith"),
WithDn(testCtx, "uid=alice, ou=people, o=test org"),
WithMemberOfGroups(testCtx, "test-group"),
},
want: &Account{
Account: &store.Account{
AuthMethodId: testAuthMethodId,
ScopeId: "global",
LoginName: "test-login-name",
Name: "test-name",
Description: "test-description",
Email: "alice@bob.com",
FullName: "alice eve smith",
Dn: "uid=alice, ou=people, o=test org",
AuthMethodId: testAuthMethodId,
ScopeId: "global",
LoginName: "test-login-name",
Name: "test-name",
Description: "test-description",
Email: "alice@bob.com",
FullName: "alice eve smith",
Dn: "uid=alice, ou=people, o=test org",
MemberOfGroups: "[\"test-group\"]",
},
},
},
Expand Down
10 changes: 10 additions & 0 deletions internal/auth/ldap/ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ldap
import (
"context"

"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
Expand Down Expand Up @@ -42,3 +43,12 @@ func newAccountId(ctx context.Context, authMethodId, loginName string) (string,
}
return id, nil
}

func newManagedGroupId(ctx context.Context) (string, error) {
const op = "ldap.newManagedGroupId"
id, err := db.NewPublicId(globals.LdapManagedGroupPrefix)
if err != nil {
return "", errors.Wrap(ctx, err, op)
}
return id, nil
}
103 changes: 103 additions & 0 deletions internal/auth/ldap/managed_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package ldap

import (
"context"
"encoding/json"

"github.com/hashicorp/boundary/internal/auth/ldap/store"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/oplog"
"google.golang.org/protobuf/proto"
)

// managedGroupTableName defines the default table name for a Managed Group
const managedGroupTableName = "auth_ldap_managed_group"

// ManagedGroup contains an LDAP managed group. It is assigned to an LDAP 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 LDAP
// AuthMethod. Supported options are WithName and WithDescription.
func NewManagedGroup(ctx context.Context, authMethodId string, groupNames []string, opt ...Option) (*ManagedGroup, error) {
const op = "ldap.NewManagedGroup"
switch {
case authMethodId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing auth method id")
case len(groupNames) == 0:
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing group names")
}
opts, err := getOpts(opt...)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
n, err := json.Marshal(groupNames)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to marshal group names"))
}
mg := &ManagedGroup{
ManagedGroup: &store.ManagedGroup{
AuthMethodId: authMethodId,
Name: opts.withName,
Description: opts.withDescription,
GroupNames: string(n),
},
}
return mg, 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 managedGroupTableName
}

// SetTableName sets the table name.
func (mg *ManagedGroup) SetTableName(n string) {
mg.tableName = n
}

// oplog will create oplog metadata for the ManagedGroup.
func (mg *ManagedGroup) oplog(ctx context.Context, opType oplog.OpType, authMethodScopeId string) (oplog.Metadata, error) {
const op = "ldap.(ManagedGroup).oplog"
switch {
case mg == nil:
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing managed group")
case opType == oplog.OpType_OP_TYPE_UNSPECIFIED:
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing op type")
case mg.PublicId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing public id")
case mg.AuthMethodId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing auth method id")
case authMethodScopeId == "":
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
}
metadata := oplog.Metadata{
"resource-public-id": []string{mg.PublicId},
"resource-type": []string{"ldap managed group"},
"op-type": []string{opType.String()},
"scope-id": []string{authMethodScopeId},
"auth-method-id": []string{mg.AuthMethodId},
}
return metadata, nil
}
Loading

0 comments on commit 80326af

Please sign in to comment.