-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathgroup_check.go
127 lines (103 loc) · 2.84 KB
/
group_check.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
package checks
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
"github.com/DataDog/datadog-agent/pkg/compliance"
"github.com/DataDog/datadog-agent/pkg/compliance/checks/env"
"github.com/DataDog/datadog-agent/pkg/compliance/eval"
"github.com/DataDog/datadog-agent/pkg/util/log"
)
var groupReportedFields = []string{
compliance.GroupFieldName,
compliance.GroupFieldUsers,
compliance.GroupFieldID,
}
// ErrGroupNotFound is returned when a group cannot be found
var ErrGroupNotFound = errors.New("group not found")
func resolveGroup(_ context.Context, e env.Env, id string, res compliance.ResourceCommon, rego bool) (resolved, error) {
if res.Group == nil {
return nil, fmt.Errorf("%s: expecting group resource in group check", id)
}
group := res.Group
f, err := os.Open(e.EtcGroupPath())
if err != nil {
log.Errorf("%s: failed to open %s: %v", id, e.EtcGroupPath(), err)
return nil, err
}
defer f.Close()
finder := &groupFinder{
groupName: group.Name,
}
err = readEtcGroup(f, finder.findGroup)
if err != nil {
return nil, wrapErrorWithID(id, err)
}
if finder.instance == nil {
return nil, ErrGroupNotFound
}
return newResolvedInstance(finder.instance, group.Name, "group"), nil
}
type groupFinder struct {
groupName string
instance eval.Instance
}
func (f *groupFinder) findGroup(line []byte) (bool, error) {
substr := []byte(f.groupName + ":")
if !bytes.HasPrefix(line, substr) {
return false, nil
}
const expectParts = 4
parts := strings.SplitN(string(line), ":", expectParts)
if len(parts) != expectParts {
log.Errorf("malformed line in group file - expected %d, found %d segments", expectParts, len(parts))
return false, errors.New("malformed group file format")
}
gid, err := strconv.Atoi(parts[2])
if err != nil {
log.Errorf("failed to parse group ID for %s: %v", f.groupName, err)
}
users := strings.Split(parts[3], ",")
f.instance = eval.NewInstance(
eval.VarMap{
compliance.GroupFieldName: f.groupName,
compliance.GroupFieldUsers: users,
compliance.GroupFieldID: gid,
},
nil,
eval.RegoInputMap{
"name": f.groupName,
"users": users,
"id": gid,
},
)
return true, nil
}
type lineFunc func(line []byte) (bool, error)
// Copyright (c) 2009 The Go Authors. All rights reserved.
// Adapted from Go readGroup code
func readEtcGroup(r io.Reader, fn lineFunc) error {
bs := bufio.NewScanner(r)
for bs.Scan() {
line := bs.Bytes()
line = bytes.TrimSpace(line)
if len(line) == 0 || line[0] == '#' {
continue
}
done, err := fn(line)
if done || err != nil {
return err
}
}
return bs.Err()
}