Skip to content

Commit 11a4664

Browse files
authored
[BB-690] Baton ID support for matching AD users and groups (#33)
* Create group resource for groups * fix group trait * add group trait * Apply group and user traits to groups * back to syncing just as a group * fix grantableTo * give groups user traits * Undo combing user trait on groups * Comment principal types * Configure AD group grant expansion for server roles via Baton ID * Update server_role.go * fix server role matching for AD group * wire in AD baton ID matching for server role users * Wire in BatonID matching for database roles * Wire baton ID into database grants * Wire in baton ID into server grants
1 parent f6f1430 commit 11a4664

File tree

7 files changed

+84
-20
lines changed

7 files changed

+84
-20
lines changed

pkg/connector/database.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ func (d *databaseSyncer) Entitlements(ctx context.Context, resource *v2.Resource
7272
Slug: name,
7373
Purpose: v2.Entitlement_PURPOSE_VALUE_PERMISSION,
7474
Resource: resource,
75-
GrantableTo: []*v2.ResourceType{resourceTypeUser},
75+
GrantableTo: []*v2.ResourceType{resourceTypeUser, resourceTypeGroup, resourceTypeDatabaseRole},
7676
},
7777
&v2.Entitlement{
7878
Id: enTypes.NewEntitlementID(resource, key+"-grant"),
7979
DisplayName: grantSlug,
8080
Slug: grantSlug,
8181
Purpose: v2.Entitlement_PURPOSE_VALUE_PERMISSION,
8282
Resource: resource,
83-
GrantableTo: []*v2.ResourceType{resourceTypeUser},
83+
GrantableTo: []*v2.ResourceType{resourceTypeUser, resourceTypeGroup, resourceTypeDatabaseRole},
8484
})
8585
}
8686

@@ -143,15 +143,20 @@ func (d *databaseSyncer) Grants(ctx context.Context, resource *v2.Resource, pTok
143143
return nil, "", nil, fmt.Errorf("unexpected resource type: %s", rt.Id)
144144
}
145145

146+
grantOpts, err := BuildBatonIDGrantOptions(resourceID, p.PrincipalType, p.PrincipalName)
147+
if err != nil {
148+
return nil, "", nil, err
149+
}
150+
146151
switch p.State {
147152
case "G":
148153
ret = append(ret, grTypes.NewGrant(resource, perm, &v2.Resource{
149154
Id: resourceID,
150-
}))
155+
}, grantOpts...))
151156
case "W":
152157
ret = append(ret, grTypes.NewGrant(resource, perm+"-grant", &v2.Resource{
153158
Id: resourceID,
154-
}))
159+
}, grantOpts...))
155160
}
156161
}
157162
}

pkg/connector/database_role.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ func (d *databaseRolePrincipalSyncer) List(ctx context.Context, parentResourceID
7474
func (d *databaseRolePrincipalSyncer) Entitlements(ctx context.Context, resource *v2.Resource, pToken *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) {
7575
var ret []*v2.Entitlement
7676

77-
ret = append(ret, enTypes.NewAssignmentEntitlement(resource, "member"))
77+
grantableTo := enTypes.WithGrantableTo(resourceTypeUser, resourceTypeGroup, resourceTypeDatabaseRole)
78+
ret = append(ret, enTypes.NewAssignmentEntitlement(resource, "member", grantableTo))
7879

7980
return ret, "", nil, nil
8081
}
@@ -216,7 +217,12 @@ func (d *databaseRolePrincipalSyncer) Grants(
216217
return nil, "", nil, fmt.Errorf("invalid state: principalID is nil")
217218
}
218219

219-
ret = append(ret, grTypes.NewGrant(resource, "member", principalID))
220+
grantOpts, err := BuildBatonIDGrantOptions(principalID, dbPrincipal.Type, dbPrincipal.Name)
221+
if err != nil {
222+
return nil, "", nil, err
223+
}
224+
225+
ret = append(ret, grTypes.NewGrant(resource, "member", principalID, grantOpts...))
220226
}
221227

222228
visited[b.ResourceID()] = true

pkg/connector/group.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@ func (d *groupPrincipalSyncer) List(ctx context.Context, parentResourceID *v2.Re
3232

3333
var ret []*v2.Resource
3434
for _, principalModel := range principals {
35-
r, err := resource.NewUserResource(
35+
r, err := resource.NewGroupResource(
3636
principalModel.Name,
3737
d.ResourceType(ctx),
3838
principalModel.ID,
3939
nil,
4040
resource.WithParentResourceID(parentResourceID),
4141
)
42+
4243
if err != nil {
4344
return nil, "", nil, err
4445
}

pkg/connector/helpers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ func resourceTypeFromDatabasePrincipal(pType string) (*v2.ResourceType, error) {
2323
switch pType {
2424
case "R":
2525
return resourceTypeDatabaseRole, nil
26-
case "G", "X":
26+
case "G", "X": // Windows group, External group from Microsoft Entra ID
2727
return resourceTypeGroup, nil
28-
case "S", "U", "C", "E", "K":
28+
case "S", "U", "C", "E", "K", "A": // SQL login, Windows login, Certificate, External login from Microsoft Entra ID, Asymmetric key, Application role?
2929
return resourceTypeUser, nil
3030
default:
3131
return nil, fmt.Errorf("unknown principal type: %s", pType)

pkg/connector/resource_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var (
2323
resourceTypeGroup = &v2.ResourceType{
2424
Id: mssqldb.GroupType,
2525
DisplayName: "Group",
26-
Traits: []v2.ResourceType_Trait{v2.ResourceType_TRAIT_USER},
26+
Traits: []v2.ResourceType_Trait{v2.ResourceType_TRAIT_GROUP},
2727
}
2828
resourceTypeServerRole = &v2.ResourceType{
2929
Id: mssqldb.ServerRoleType,

pkg/connector/server.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,15 @@ func (d *serverSyncer) Entitlements(ctx context.Context, resource *v2.Resource,
9999
Slug: name,
100100
Purpose: v2.Entitlement_PURPOSE_VALUE_PERMISSION,
101101
Resource: resource,
102+
GrantableTo: []*v2.ResourceType{resourceTypeUser, resourceTypeGroup, resourceTypeServerRole},
102103
})
103104
ret = append(ret, &v2.Entitlement{
104105
Id: enTypes.NewEntitlementID(resource, key+"-grant"),
105106
DisplayName: fmt.Sprintf("%s (With Grant)", name),
106107
Slug: fmt.Sprintf("%s (With Grant)", name),
107108
Purpose: v2.Entitlement_PURPOSE_VALUE_PERMISSION,
108109
Resource: resource,
110+
GrantableTo: []*v2.ResourceType{resourceTypeUser, resourceTypeGroup, resourceTypeServerRole},
109111
})
110112
}
111113

@@ -129,17 +131,22 @@ func (d *serverSyncer) Grants(ctx context.Context, resource *v2.Resource, pToken
129131
if err != nil {
130132
return nil, "", nil, err
131133
}
134+
135+
principal := &v2.ResourceId{
136+
ResourceType: rt.Id,
137+
Resource: strconv.FormatInt(p.PrincipalID, 10),
138+
}
139+
140+
grantOpts, err := BuildBatonIDGrantOptions(principal, p.PrincipalType, p.PrincipalName)
141+
if err != nil {
142+
return nil, "", nil, err
143+
}
144+
132145
switch p.State {
133146
case "G":
134-
ret = append(ret, grTypes.NewGrant(resource, perm, &v2.ResourceId{
135-
ResourceType: rt.Id,
136-
Resource: strconv.FormatInt(p.PrincipalID, 10),
137-
}))
147+
ret = append(ret, grTypes.NewGrant(resource, perm, principal, grantOpts...))
138148
case "W":
139-
ret = append(ret, grTypes.NewGrant(resource, perm+"-grant", &v2.ResourceId{
140-
ResourceType: rt.Id,
141-
Resource: strconv.FormatInt(p.PrincipalID, 10),
142-
}))
149+
ret = append(ret, grTypes.NewGrant(resource, perm+"-grant", principal, grantOpts...))
143150
}
144151
}
145152
}

pkg/connector/server_role.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
1111
"github.com/conductorone/baton-sdk/pkg/annotations"
1212
_ "github.com/conductorone/baton-sdk/pkg/annotations"
13+
bid "github.com/conductorone/baton-sdk/pkg/bid"
1314
"github.com/conductorone/baton-sdk/pkg/pagination"
1415
enTypes "github.com/conductorone/baton-sdk/pkg/types/entitlement"
1516
grTypes "github.com/conductorone/baton-sdk/pkg/types/grant"
@@ -62,7 +63,7 @@ func (d *serverRolePrincipalSyncer) Entitlements(ctx context.Context, resource *
6263
ret = append(ret, enTypes.NewAssignmentEntitlement(
6364
resource,
6465
"member",
65-
enTypes.WithGrantableTo(resourceTypeUser),
66+
enTypes.WithGrantableTo(resourceTypeUser, resourceTypeGroup, resourceTypeServerRole),
6667
))
6768

6869
return ret, "", nil, nil
@@ -178,7 +179,12 @@ func (d *serverRolePrincipalSyncer) Grants(ctx context.Context, resource *v2.Res
178179
return nil, "", nil, err
179180
}
180181

181-
ret = append(ret, grTypes.NewGrant(resource, "member", principalID))
182+
grantOpts, err := BuildBatonIDGrantOptions(principalID, principal.Type, principal.Name)
183+
if err != nil {
184+
return nil, "", nil, err
185+
}
186+
187+
ret = append(ret, grTypes.NewGrant(resource, "member", principalID, grantOpts...))
182188
}
183189

184190
visited[b.ResourceID()] = true
@@ -195,6 +201,45 @@ func (d *serverRolePrincipalSyncer) Grants(ctx context.Context, resource *v2.Res
195201
return ret, npt, nil, nil
196202
}
197203

204+
func BuildBatonIDGrantOptions(principalID *v2.ResourceId, principalType string, principalName string) ([]grTypes.GrantOption, error) {
205+
grantOpts := []grTypes.GrantOption{}
206+
207+
switch principalType {
208+
case "G": // Configure BatonID matching for Active Directory groups
209+
gr := &v2.Resource{
210+
Id: principalID,
211+
}
212+
213+
ent := enTypes.NewAssignmentEntitlement(gr, "member")
214+
bidEnt, err := bid.MakeBid(ent)
215+
if err != nil {
216+
return nil, err
217+
}
218+
219+
grantOpts = append(grantOpts,
220+
grTypes.WithAnnotation(&v2.ExternalResourceMatch{
221+
ResourceType: v2.ResourceType_TRAIT_GROUP,
222+
Key: "downlevel_logon_name",
223+
Value: principalName,
224+
}),
225+
grTypes.WithAnnotation(&v2.GrantExpandable{
226+
EntitlementIds: []string{bidEnt},
227+
Shallow: true,
228+
}),
229+
)
230+
case "U": // Configure BatonID matching for Active Directory users
231+
grantOpts = append(grantOpts,
232+
grTypes.WithAnnotation(&v2.ExternalResourceMatch{
233+
ResourceType: v2.ResourceType_TRAIT_USER,
234+
Key: "downlevel_logon_name",
235+
Value: principalName,
236+
}),
237+
)
238+
}
239+
240+
return grantOpts, nil
241+
}
242+
198243
func (d *serverRolePrincipalSyncer) Grant(ctx context.Context, resource *v2.Resource, entitlement *v2.Entitlement) ([]*v2.Grant, annotations.Annotations, error) {
199244
var err error
200245

0 commit comments

Comments
 (0)