Skip to content

Commit

Permalink
Use lowercase group names
Browse files Browse the repository at this point in the history
Currently, we only support groups with msentraid. The names of those
groups are case-insensitive:

  https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules

So we also store those group names case-insensitive, same as for
usernames.

Note that Unix groups are case-sensitive, so we treat local groups as
case-sensitive.
  • Loading branch information
adombeck committed Jan 15, 2025
1 parent 706499b commit 6e9ca74
Show file tree
Hide file tree
Showing 18 changed files with 188 additions and 119 deletions.
2 changes: 1 addition & 1 deletion internal/users/cache/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func New(cacheDir string) (cache *Cache, err error) {

cache = &Cache{db: db, mu: sync.RWMutex{}}

if err = maybeMigrateLowercaseUsernames(cache); err != nil {
if err = maybeMigrateToLowercaseUserAndGroupNames(cache); err != nil {
log.Warningf(context.Background(), "Error migrating database to lowercase usernames: %v", err)
} else {
// Store the current version in the database
Expand Down
10 changes: 5 additions & 5 deletions internal/users/cache/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ func TestNew(t *testing.T) {

wantErr bool
}{
"New without any initialized database": {},
"New with already existing database": {dbFile: "multiple_users_and_groups"},
"New recreates any missing buckets and delete unknowns": {dbFile: "database_with_unknown_bucket"},
"New removes orphaned user records from UserByID bucket": {dbFile: "orphaned_user_record"},
"New migrates database to lowercase usernames": {dbFile: "one_user_and_group_with_uppercase"},
"New without any initialized database": {},
"New with already existing database": {dbFile: "multiple_users_and_groups"},
"New recreates any missing buckets and delete unknowns": {dbFile: "database_with_unknown_bucket"},
"New removes orphaned user records from UserByID bucket": {dbFile: "orphaned_user_record"},
"New migrates database to lowercase user and group names": {dbFile: "one_user_and_group_with_uppercase"},

"Error on cacheDir non existent cacheDir": {dbFile: "-", wantErr: true},
"Error on corrupted db file": {corruptedDbFile: true, wantErr: true},
Expand Down
3 changes: 3 additions & 0 deletions internal/users/cache/getgroups.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cache
import (
"encoding/json"
"fmt"
"strings"

"go.etcd.io/bbolt"
)
Expand Down Expand Up @@ -30,6 +31,8 @@ func (c *Cache) GroupByID(gid uint32) (GroupDB, error) {

// GroupByName returns a group matching a given name or an error if the database is corrupted or no entry was found.
func (c *Cache) GroupByName(name string) (GroupDB, error) {
// authd uses lowercase group names
name = strings.ToLower(name)
return getGroup(c, groupByNameBucketName, name)
}

Expand Down
50 changes: 44 additions & 6 deletions internal/users/cache/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"golang.org/x/mod/semver"
)

const initialLowercaseUsernameVersion = "0.3.8"
const initialLowercaseUserAndGroupNamesVersion = "0.3.8"

func maybeMigrateLowercaseUsernames(c *Cache) error {
func maybeMigrateToLowercaseUserAndGroupNames(c *Cache) error {
// Get the current version.
version, err := c.GetVersion()
if err != nil {
Expand All @@ -27,17 +27,16 @@ func maybeMigrateLowercaseUsernames(c *Cache) error {

// If the version is less than 0.3.8-pre1, we need to migrate lowercase usernames.
// Use semantic versioning to compare versions.
if version == "" || semver.Compare(version, initialLowercaseUsernameVersion) < 0 {
// Migrate lowercase usernames.
if err := migrateLowercaseUsernames(c); err != nil {
if version == "" || semver.Compare(version, initialLowercaseUserAndGroupNamesVersion) < 0 {
if err := migrateToLowercaseUserAndGroupNames(c); err != nil {
return err
}
}

return nil
}

func migrateLowercaseUsernames(c *Cache) error {
func migrateToLowercaseUserAndGroupNames(c *Cache) error {
log.Debug(context.Background(), "Migrating lowercase usernames")

// Convert the user and group names to lowercase in all user and group buckets.
Expand Down Expand Up @@ -84,6 +83,45 @@ func migrateLowercaseUsernames(c *Cache) error {
return err
}

err = buckets[groupByNameBucketName].ForEach(func(k, v []byte) error {
var grp GroupDB
if err := json.Unmarshal(v, &grp); err != nil {
return err
}

grp.Name = strings.ToLower(grp.Name)

err = buckets[groupByNameBucketName].Delete(k)
if err != nil {
return err
}

updateBucket(buckets[groupByNameBucketName], grp.Name, grp)

return nil
})
if err != nil {
return err
}

for _, bucket := range []bucketWithName{buckets[groupByIDBucketName], buckets[groupByUGIDBucketName]} {
err = bucket.ForEach(func(k, v []byte) error {
var grp GroupDB
if err := json.Unmarshal(v, &grp); err != nil {
return err
}

grp.Name = strings.ToLower(grp.Name)

updateBucket(bucket, string(k), grp)

return nil
})
if err != nil {
return err
}
}

return nil
})
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
GroupByID:
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupToUsers:
"22222": '{"GID":22222,"UIDs":[2222]}'
"33333": '{"GID":33333,"UIDs":[3333]}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
GroupByID:
"11111": '{"Name":"Group1","GID":11111,"UGID":"12345678"}'
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
GroupByName:
Group1: '{"Name":"Group1","GID":11111,"UGID":"12345678"}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
GroupByUGID:
"12345678": '{"Name":"Group1","GID":11111,"UGID":"12345678"}'
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
GroupToUsers:
"11111": '{"GID":11111,"UIDs":[1111]}'
UserByID:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupToUsers:
"11111": '{"GID":11111,"UIDs":[1111]}'
"22222": '{"GID":22222,"UIDs":[2222]}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupToUsers:
"11111": '{"GID":11111,"UIDs":[1111]}'
"22222": '{"GID":22222,"UIDs":[2222,1111]}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ UserToGroups:
"1111": '{"UID":1111,"GIDs":[11111]}'
UserToLocalGroups:
"1111": "null"
Version:
version: Dev
Version: {}
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupToUsers:
"11111": '{"GID":11111,"UIDs":[1111]}'
"22222": '{"GID":22222,"UIDs":[2222]}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"45678123": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"56781234": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"87654321": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupToUsers:
"11111": '{"GID":11111,"UIDs":[1111]}'
"22222": '{"GID":22222,"UIDs":[2222]}'
Expand Down
3 changes: 3 additions & 0 deletions internal/users/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ func (m *Manager) UpdateUser(u UserInfo) (err error) {
localGroups = append(localGroups, g.Name)
continue
}

// authd groups are lowercase
g.Name = strings.ToLower(g.Name)
authdGroups = append(authdGroups, cache.NewGroupDB(g.Name, *g.GID, g.UGID, nil))
}

Expand Down
6 changes: 4 additions & 2 deletions internal/users/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ func TestUpdateUser(t *testing.T) {
}

groupsCases := map[string][]users.GroupInfo{
"cloud-group": {{Name: "group1", GID: ptrUint32(11111), UGID: "1"}},
"local-group": {{Name: "localgroup1"}},
"cloud-group": {{Name: "group1", GID: ptrUint32(11111), UGID: "1"}},
"local-group": {{Name: "localgroup1"}},
"cloud-group-with-uppercase": {{Name: "Group1", GID: ptrUint32(11111), UGID: "1"}},
"mixed-groups-cloud-first": {
{Name: "group1", GID: ptrUint32(11111), UGID: "1"},
{Name: "localgroup1", GID: nil, UGID: ""},
Expand Down Expand Up @@ -139,6 +140,7 @@ func TestUpdateUser(t *testing.T) {
"Successfully update user updating local groups": {groupsCase: "mixed-groups-cloud-first", localGroupsFile: "users_in_groups.group"},
"UID does not change if user already exists": {userCase: "same-name-different-uid", dbFile: "one_user_and_group", wantSameUID: true},
"Successfully update user with different capitalization": {userCase: "different-capitalization-same-uid", dbFile: "one_user_and_group"},
"Names of authd groups are stored in lowercase": {groupsCase: "cloud-group-with-uppercase"},

"Error if user has no username": {userCase: "nameless", wantErr: true, noOutput: true},
"Error if user has conflicting uid": {userCase: "different-name-same-uid", dbFile: "one_user_and_group", wantErr: true, noOutput: true},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
|
GroupByID:
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234"}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123"}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
"11111": '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
"22222": '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
"33333": '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
"44444": '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
"99999": '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
GroupByName:
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321"}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678"}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234"}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812"}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123"}'
commongroup: '{"Name":"commongroup","GID":99999,"UGID":"87654321","Users":null}'
group1: '{"Name":"group1","GID":11111,"UGID":"12345678","Users":null}'
group2: '{"Name":"group2","GID":22222,"UGID":"56781234","Users":null}'
group3: '{"Name":"group3","GID":33333,"UGID":"34567812","Users":null}'
group4: '{"Name":"group4","GID":44444,"UGID":"45678123","Users":null}'
GroupByUGID:
"12345678": '{"Name":"group1","GID":11111,"UGID":"12345678"}'
"34567812": '{"Name":"group3","GID":33333,"UGID":"34567812"}'
Expand Down
Loading

0 comments on commit 6e9ca74

Please sign in to comment.