From 05309448f1de6a09dcf19e6598e5c91b32d8dbd2 Mon Sep 17 00:00:00 2001 From: Tommi Hovi Date: Thu, 18 Jul 2024 10:14:58 +0300 Subject: [PATCH] Remove deprecated users from group command (#4) * Make info command work with email queries * Don't print deprovisioned users by default * Add comment --- README.md | 4 ++++ client/client.go | 38 +++++++++++++++++++++++++++----------- main.go | 23 +++++++++++++++++------ 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 62149ea..fc86e49 100644 --- a/README.md +++ b/README.md @@ -54,3 +54,7 @@ OKTA_INFO_API_TOKEN= okta-info rule group # Search using group name okta-info rule name # Search using rule name ``` + +## Deprovisioned users + +By default deprovisioned users are not shown. To show them, set the following environment variable to truthy value: `OKTA_INFO_SHOW_DEPROVISIONED_USERS=true` diff --git a/client/client.go b/client/client.go index 81b22b6..d758d1e 100644 --- a/client/client.go +++ b/client/client.go @@ -12,13 +12,17 @@ import ( "github.com/samber/lo" ) +const deprovisionedUserStatus = "DEPROVISIONED" + type OIClient struct { c *okta.Client // Not sure if this is needed, the okta.NewClient returns context also, so storing it here for now ctx context.Context + // showDeprovisionedUsers is a flag to enable/disable printing of deprovisioned users + showDeprovisionedUsers bool } -func NewOIClient(apiToken, oktaOrgURL string) (*OIClient, error) { +func NewOIClient(apiToken, oktaOrgURL string, showDeprovisionedUsers bool) (*OIClient, error) { ctx, client, err := okta.NewClient( context.TODO(), okta.WithOrgUrl(oktaOrgURL), @@ -40,8 +44,9 @@ func NewOIClient(apiToken, oktaOrgURL string) (*OIClient, error) { } return &OIClient{ - c: client, - ctx: ctx, + c: client, + ctx: ctx, + showDeprovisionedUsers: showDeprovisionedUsers, }, nil } @@ -58,11 +63,19 @@ func (oi *OIClient) PrintGroupsForUser(wantUserName string) error { for _, user := range users { profile := *user.Profile profileEmail := profile["email"].(string) - // strip host out from email - profileUserName := strings.Split(profileEmail, "@")[0] - if strings.EqualFold(profileUserName, wantUserName) { - userID = user.Id + // searching for username with email address + if strings.Contains(wantUserName, "@") { + if strings.EqualFold(profileEmail, wantUserName) { + userID = user.Id + } + } else { // no email address, just name + // strip host out from email + profileUserName := strings.Split(profileEmail, "@")[0] + + if strings.EqualFold(profileUserName, wantUserName) { + userID = user.Id + } } } @@ -145,6 +158,9 @@ func (oi *OIClient) PrintUsersInGroups(wantGroupsName []string) error { } for _, user := range foundUsers { + if !oi.showDeprovisionedUsers && strings.Contains(user, deprovisionedUserStatus) { + continue + } fmt.Println(user) } @@ -152,7 +168,7 @@ func (oi *OIClient) PrintUsersInGroups(wantGroupsName []string) error { } // PrintGroupDiff prints the difference of two sets of groups -func (oi *OIClient) PrintGroupDiff(groupsA, groupsB []string, hideDeprovisioned bool) error { +func (oi *OIClient) PrintGroupDiff(groupsA, groupsB []string) error { groupsAUsers, err := oi.getUsersInGroupsUnion(groupsA) if err != nil { return err @@ -169,13 +185,13 @@ func (oi *OIClient) PrintGroupDiff(groupsA, groupsB []string, hideDeprovisioned groupB := strings.Join(groupsB, ", ") headerStringFmt := "Users in %s, but not in %s:\n" - if hideDeprovisioned { + if !oi.showDeprovisionedUsers { headerStringFmt = "Users (excluding deprovisioned) in %s, but not in %s:\n" } fmt.Printf(headerStringFmt, groupA, groupB) for _, user := range notInB { - if strings.Contains(user, "(DEPROVISIONED)") && hideDeprovisioned { + if !oi.showDeprovisionedUsers && strings.Contains(user, deprovisionedUserStatus) { continue } @@ -185,7 +201,7 @@ func (oi *OIClient) PrintGroupDiff(groupsA, groupsB []string, hideDeprovisioned fmt.Printf(headerStringFmt, groupB, groupA) for _, user := range notInA { - if strings.Contains(user, "(DEPROVISIONED)") && hideDeprovisioned { + if !oi.showDeprovisionedUsers && strings.Contains(user, deprovisionedUserStatus) { continue } diff --git a/main.go b/main.go index f09ef9e..cd9c839 100644 --- a/main.go +++ b/main.go @@ -12,8 +12,9 @@ import ( ) var ( - oktaOrgURL = os.Getenv("OKTA_INFO_ORG_URL") - apiToken = os.Getenv("OKTA_INFO_API_TOKEN") + oktaOrgURL = os.Getenv("OKTA_INFO_ORG_URL") + apiToken = os.Getenv("OKTA_INFO_API_TOKEN") + showDeprovisionedUsersEnv = "OKTA_INFO_SHOW_DEPROVISIONED_USERS" ) func printHelp() { @@ -25,6 +26,18 @@ func printHelp() { fmt.Println(" rule [name/group] - print rules matching the search string or print group rules for a group") } +// showDeprecatedUsersFromEnv returns false unless environment variable +// has been set to show deprecated users. +func showDeprovisionedUsersFromEnv() bool { + val := os.Getenv(showDeprovisionedUsersEnv) + + if val == "" || strings.EqualFold(val, "false") { + return false + } + + return true +} + func run() error { // Check which subcommand was provided if len(os.Args) < 3 { @@ -37,7 +50,7 @@ func run() error { return err } - oic, err := client.NewOIClient(token, oktaOrgURL) + oic, err := client.NewOIClient(token, oktaOrgURL, showDeprovisionedUsersFromEnv()) if err != nil { return err } @@ -56,9 +69,7 @@ func run() error { groupsA := strings.Split(os.Args[2], ",") groupsB := strings.Split(os.Args[3], ",") - hideDeprovisioned := false - - return oic.PrintGroupDiff(groupsA, groupsB, hideDeprovisioned) + return oic.PrintGroupDiff(groupsA, groupsB) case "rule": switch os.Args[2] { case "group", "name":