From da62b231851b6ec45dae7d2d1df97d6d613aaf6a Mon Sep 17 00:00:00 2001 From: Michael Aldridge Date: Mon, 9 Sep 2019 00:58:21 -0700 Subject: [PATCH] Add group handling --- impl/entity.go | 8 ++--- impl/group.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ impl/util.go | 11 ++++++- 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 impl/group.go diff --git a/impl/entity.go b/impl/entity.go index e11ca9b..410cf22 100644 --- a/impl/entity.go +++ b/impl/entity.go @@ -51,7 +51,7 @@ func (o OktaPlugin) EntityCreate(e, de pb.Entity) (pb.Entity, error) { // EntityUpdate pushes changes to the base entity profile, nothing // else. Custom attributes are not supported in this plugin. func (o OktaPlugin) EntityUpdate(e pb.Entity) (pb.Entity, error) { - oktaID := getOktaID(e) + oktaID := getEntityOktaID(e) if oktaID == "" { return e, nil } @@ -87,7 +87,7 @@ func (o OktaPlugin) EntityUpdate(e pb.Entity) (pb.Entity, error) { // EntityLock translates to a suspended entity in Okta. func (o OktaPlugin) EntityLock(e pb.Entity) (pb.Entity, error) { - oktaID := getOktaID(e) + oktaID := getEntityOktaID(e) if oktaID == "" { return e, nil } @@ -102,7 +102,7 @@ func (o OktaPlugin) EntityLock(e pb.Entity) (pb.Entity, error) { // EntityUnlock translates to a force un-suspend in Okta. func (o OktaPlugin) EntityUnlock(e pb.Entity) (pb.Entity, error) { - oktaID := getOktaID(e) + oktaID := getEntityOktaID(e) if oktaID == "" { return e, nil } @@ -119,7 +119,7 @@ func (o OktaPlugin) EntityUnlock(e pb.Entity) (pb.Entity, error) { // bad, but if you must, then this function will ensure that users in // Okta have also been wiped. func (o OktaPlugin) EntityDestroy(e pb.Entity) error { - oktaID := getOktaID(e) + oktaID := getEntityOktaID(e) if oktaID == "" { return nil } diff --git a/impl/group.go b/impl/group.go new file mode 100644 index 0000000..ef51ea8 --- /dev/null +++ b/impl/group.go @@ -0,0 +1,80 @@ +package impl + +import ( + "github.com/okta/okta-sdk-golang/okta" + + "github.com/NetAuth/NetAuth/pkg/plugin/tree" + + pb "github.com/NetAuth/Protocol" +) + +// GroupCreate will create a matched group in Okta. Assigning +// applications to this group must still be done in Okta directly, but +// the group and its attributes are mapped from NetAuth. +func (o OktaPlugin) GroupCreate(g pb.Group) (pb.Group, error) { + og := okta.Group{ + Profile: &okta.GroupProfile{ + Description: g.GetDisplayName(), + Name: g.GetName(), + }, + } + + group, resp, err := o.c.Group.CreateGroup(og) + if err != nil { + appLogger.Error("Okta group was not created!", "error", err) + return g, err + } + + appLogger.Debug("Okta Response", "response", resp) + + g.UntypedMeta = tree.PatchKeyValueSlice(g.UntypedMeta, "UPSERT", "oktaID", group.Id) + + return g, nil +} + +// GroupUpdate is called to manage ongoing changes to a group. This +// function does not push membership changes. +func (o OktaPlugin) GroupUpdate(g pb.Group) (pb.Group, error) { + oktaID := getGroupOktaID(g) + if oktaID == "" { + return g, nil + } + + grp, resp, err := o.c.Group.GetGroup(oktaID, nil) + if err != nil { + appLogger.Warn("No group with OktaID", "name", g.GetName(), "oktaID", oktaID, "error", err) + return g, nil + } + + appLogger.Debug("Okta Response", "response", resp) + + grp.Profile.Description = g.GetDisplayName() + + _, resp, err = o.c.Group.UpdateGroup(oktaID, *grp) + if err != nil { + appLogger.Warn("Error updating Okta group", "error", err) + return g, nil + } + + appLogger.Debug("Okta Response", "response", resp) + + return g, nil +} + +// GroupDestroy pushes the destruction of groups to Okta. It is +// recommended to never destroy a group, but if this is desired this +// function will ensure the group is removed in Okta as well. +func (o OktaPlugin) GroupDestroy(g pb.Group) error { + appLogger.Info("Attempting to remove group from Okta", "group", g.GetName()) + oktaID := getGroupOktaID(g) + if oktaID == "" { + return nil + } + resp, err := o.c.Group.DeleteGroup(oktaID) + if err != nil { + appLogger.Warn("Failed to delete Okta Group", "group", g.GetName(), "oktaID", oktaID, "error", err) + } + + appLogger.Debug("Okta Response", "response", resp) + return nil +} diff --git a/impl/util.go b/impl/util.go index 4230996..9136790 100644 --- a/impl/util.go +++ b/impl/util.go @@ -8,7 +8,7 @@ import ( pb "github.com/NetAuth/Protocol" ) -func getOktaID(e pb.Entity) string { +func getEntityOktaID(e pb.Entity) string { m := e.GetMeta() if m == nil { return "" @@ -21,3 +21,12 @@ func getOktaID(e pb.Entity) string { oktaID := strings.SplitN(res[0], ":", 2)[1] return oktaID } + +func getGroupOktaID(g pb.Group) string { + res := tree.PatchKeyValueSlice(g.UntypedMeta, "READ", "oktaID", "") + if len(res) != 1 || res[0] == "" { + return "" + } + oktaID := strings.SplitN(res[0], ":", 2)[1] + return oktaID +}