go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/group.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package resources
     5  
     6  import (
     7  	"errors"
     8  	"strconv"
     9  	"sync"
    10  
    11  	"go.mondoo.com/cnquery/llx"
    12  	"go.mondoo.com/cnquery/providers/os/connection/shared"
    13  	"go.mondoo.com/cnquery/providers/os/resources/groups"
    14  )
    15  
    16  type mqlGroupInternal struct {
    17  	membersArr []string
    18  }
    19  
    20  func (x *mqlGroup) id() (string, error) {
    21  	var id string
    22  	if len(x.Sid.Data) > 0 {
    23  		id = x.Sid.Data
    24  	} else {
    25  		id = strconv.FormatInt(x.Gid.Data, 10)
    26  	}
    27  
    28  	return "group/" + id + "/" + x.Name.Data, nil
    29  }
    30  
    31  func (x *mqlGroup) members() ([]interface{}, error) {
    32  	raw, err := CreateResource(x.MqlRuntime, "users", nil)
    33  	if err != nil {
    34  		return nil, errors.New("cannot get users info for group: " + err.Error())
    35  	}
    36  	users := raw.(*mqlUsers)
    37  
    38  	if err := users.refreshCache(nil); err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	res := make([]interface{}, len(x.membersArr))
    43  	for i, name := range x.membersArr {
    44  		res[i] = users.usersByName[name]
    45  	}
    46  
    47  	return res, nil
    48  }
    49  
    50  type mqlGroupsInternal struct {
    51  	lock       sync.Mutex
    52  	groupsByID map[int64]*mqlGroup
    53  }
    54  
    55  func (x *mqlGroups) list() ([]interface{}, error) {
    56  	x.lock.Lock()
    57  	defer x.lock.Unlock()
    58  
    59  	// in the unlikely case that we get called twice into the same method,
    60  	// any subsequent calls are locked until user detection finishes; at this point
    61  	// we only need to return a non-nil error field and it will pull the data from cache
    62  	if x.groupsByID != nil {
    63  		return nil, nil
    64  	}
    65  	x.groupsByID = map[int64]*mqlGroup{}
    66  
    67  	conn := x.MqlRuntime.Connection.(shared.Connection)
    68  	gm, err := groups.ResolveManager(conn)
    69  	if gm == nil || err != nil {
    70  		return nil, errors.New("cannot find groups manager")
    71  	}
    72  
    73  	groups, err := gm.List()
    74  	if err != nil {
    75  		return nil, errors.New("could not retrieve groups list")
    76  	}
    77  
    78  	var res []interface{}
    79  	for i := range groups {
    80  		group := groups[i]
    81  		nu, err := CreateResource(x.MqlRuntime, "group", map[string]*llx.RawData{
    82  			"name": llx.StringData(group.Name),
    83  			"gid":  llx.IntData(group.Gid),
    84  			"sid":  llx.StringData(group.Sid),
    85  		})
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  
    90  		res = append(res, nu)
    91  
    92  		g := nu.(*mqlGroup)
    93  		g.membersArr = group.Members
    94  		x.groupsByID[g.Gid.Data] = g
    95  	}
    96  
    97  	return res, nil
    98  }
    99  
   100  func (x *mqlGroups) findID(id int64) (*mqlGroup, error) {
   101  	if x := x.GetList(); x.Error != nil {
   102  		return nil, x.Error
   103  	}
   104  
   105  	res, ok := x.mqlGroupsInternal.groupsByID[id]
   106  	if !ok {
   107  		return nil, errors.New("cannot find group for uid " + strconv.Itoa(int(id)))
   108  	}
   109  	return res, nil
   110  }