Skip to content

Commit 353c96b

Browse files
committed
Add mechanism for synchronizing group membership to Okta
1 parent 06c9da8 commit 353c96b

3 files changed

Lines changed: 106 additions & 1 deletion

File tree

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0
3838
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3939
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4040
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
41+
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
4142
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
4243
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
4344
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=

impl/groupsync.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package impl
2+
3+
import (
4+
"time"
5+
6+
"github.com/NetAuth/NetAuth/pkg/client"
7+
8+
pb "github.com/NetAuth/Protocol"
9+
)
10+
11+
func (o OktaPlugin) groupSyncTimer() {
12+
ticker := time.NewTicker(cfg.GetDuration("interval"))
13+
14+
for range ticker.C {
15+
o.syncGroups()
16+
}
17+
}
18+
19+
func (o OktaPlugin) syncGroups() {
20+
c, err := client.New()
21+
groups, err := c.SearchGroups("*")
22+
if err != nil {
23+
appLogger.Warn("Not running syncGroups()", "error", err)
24+
return
25+
}
26+
27+
// Filter on manageable groups
28+
oktaGroups := make(map[string]pb.Group)
29+
for _, g := range groups.GetGroups() {
30+
oktaID := getGroupOktaID(*g)
31+
if oktaID != "" {
32+
oktaGroups[oktaID] = *g
33+
}
34+
}
35+
36+
// Compute what we want the groups to look like
37+
want := make(map[string]map[string]struct{})
38+
for gid, g := range oktaGroups {
39+
want[gid] = make(map[string]struct{})
40+
41+
members, err := c.ListGroupMembers(g.GetName())
42+
if err != nil {
43+
appLogger.Warn("Failed to get memberships", "group", g.GetName(), "error", err)
44+
continue
45+
}
46+
for _, e := range members {
47+
if id := getEntityOktaID(*e); id != "" {
48+
want[gid][id] = struct{}{}
49+
}
50+
}
51+
}
52+
53+
// Get existing memberships
54+
for gid := range oktaGroups {
55+
users, _, err := o.c.Group.ListGroupUsers(gid, nil)
56+
if err != nil {
57+
appLogger.Warn("Not updating membership for group",
58+
"group", oktaGroups[gid].Name,
59+
"error", err)
60+
continue
61+
}
62+
for i := range users {
63+
if _, ok := want[gid][users[i].Id]; ok {
64+
// User is already there, drop it from
65+
// the want list
66+
delete(want[gid], users[i].Id)
67+
} else {
68+
// User is there and shouldn't be, get
69+
// rid of them.
70+
_, err := o.c.Group.RemoveGroupUser(gid, users[i].Id)
71+
if err != nil {
72+
appLogger.Warn("Failed to remove user from group",
73+
"group", gid,
74+
"user", users[i].Id,
75+
"error", err)
76+
}
77+
appLogger.Trace("Removing okta user",
78+
"group", gid,
79+
"user", users[i].Id)
80+
}
81+
}
82+
}
83+
84+
// Add the remaining users
85+
for gid := range oktaGroups {
86+
for user := range want[gid] {
87+
if _, err := o.c.Group.AddUserToGroup(gid, user); err != nil {
88+
appLogger.Warn("Failed to add user to group",
89+
"group", gid,
90+
"user", user,
91+
"error", err)
92+
}
93+
}
94+
}
95+
}

impl/main.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package impl
33
import (
44
"context"
55
"os"
6+
"time"
67

78
"github.com/hashicorp/go-hclog"
89
"github.com/okta/okta-sdk-golang/okta"
@@ -38,6 +39,9 @@ func init() {
3839
viper.SetDefault("plugin.okta.orgurl", "")
3940
viper.SetDefault("plugin.okta.tokan", "")
4041
viper.SetDefault("plugin.okta.domain", "")
42+
viper.SetDefault("plugin.okta.interval", time.Minute*20)
43+
44+
viper.Set("client.ServiceName", "okta-groupsync")
4145

4246
cfg = viper.Sub("plugin.okta")
4347
}
@@ -54,8 +58,13 @@ func New() tree.Plugin {
5458
appLogger.Error("Okta Error during initailization", "error", err)
5559
}
5660

57-
return OktaPlugin{
61+
x := OktaPlugin{
5862
NullPlugin: tree.NullPlugin{},
5963
c: client,
6064
}
65+
66+
x.syncGroups()
67+
go x.groupSyncTimer()
68+
69+
return x
6170
}

0 commit comments

Comments
 (0)