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

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package resources
     5  
     6  import (
     7  	"errors"
     8  	"math"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/rs/zerolog/log"
    13  	"go.mondoo.com/cnquery/llx"
    14  	"go.mondoo.com/cnquery/providers/os/resources/shadow"
    15  )
    16  
    17  const defaultShadowConfig = "/etc/shadow"
    18  
    19  func (s *mqlShadow) id() (string, error) {
    20  	return defaultShadowConfig, nil
    21  }
    22  
    23  func parseInt(s string, dflt int64, msg string) (int64, error) {
    24  	if s == "" {
    25  		return dflt, nil
    26  	}
    27  
    28  	res, err := strconv.ParseInt(s, 10, 64)
    29  	if err != nil {
    30  		return 0, errors.New("failed to parse " + msg + " as a number, it is '" + s + "'")
    31  	}
    32  	return res, nil
    33  }
    34  
    35  func (s *mqlShadow) list() ([]interface{}, error) {
    36  	// TODO: we may want to create a real mondoo file resource
    37  	o, err := CreateResource(s.MqlRuntime, "file", map[string]*llx.RawData{
    38  		"path": llx.StringData(defaultShadowConfig),
    39  	})
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	file := o.(*mqlFile)
    45  	content := file.GetContent()
    46  	if content.Error != nil {
    47  		return nil, content.Error
    48  	}
    49  
    50  	entries, err := shadow.ParseShadow(strings.NewReader(content.Data))
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	shadowEntryResources := make([]interface{}, len(entries))
    56  	for i := range entries {
    57  		entry := entries[i]
    58  
    59  		maxdays, err := parseInt(entry.MaxDays, math.MaxInt64, "MaxDays")
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  
    64  		mindays, err := parseInt(entry.MinDays, -1, "MinDays")
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  
    69  		warndays, err := parseInt(entry.WarnDays, -1, "WarnDays")
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		inactivedays, err := parseInt(entry.InactiveDays, math.MaxInt64, "InactiveDays")
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  
    79  		lastChanged := llx.NilData
    80  		if entry.LastChanged != nil {
    81  			lastChanged = llx.TimeData(*entry.LastChanged)
    82  		}
    83  
    84  		o, err := CreateResource(s.MqlRuntime, "shadow.entry", map[string]*llx.RawData{
    85  			"user":         llx.StringData(entry.User),
    86  			"password":     llx.StringData(entry.Password),
    87  			"lastchanged":  lastChanged,
    88  			"mindays":      llx.IntData(mindays),
    89  			"maxdays":      llx.IntData(maxdays),
    90  			"warndays":     llx.IntData(warndays),
    91  			"inactivedays": llx.IntData(inactivedays),
    92  			"expirydates":  llx.StringData(entry.ExpiryDates),
    93  			"reserved":     llx.StringData(entry.Reserved),
    94  		})
    95  		if err != nil {
    96  			log.Error().Err(err).Str("shadow_entry", entry.User).Msg("mql[shadow_entry]> could not create shadow entry resource")
    97  			return nil, err
    98  		}
    99  		shadowEntryResources[i] = o.(*mqlShadowEntry)
   100  	}
   101  
   102  	return shadowEntryResources, nil
   103  }
   104  
   105  func (se *mqlShadowEntry) id() (string, error) {
   106  	return se.User.Data, nil
   107  }