This repository has been archived by the owner on May 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
/
group.go
150 lines (127 loc) · 3.65 KB
/
group.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package group
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"github.com/ubuntu/aad-auth/internal/cache"
"github.com/ubuntu/aad-auth/internal/logger"
"github.com/ubuntu/aad-auth/internal/nss"
)
// Group is the nss group object.
type Group struct {
name string /* username */
passwd string /* user password */
gid uint /* group ID */
members []string /* Members of the group */
}
// String creates a string with Group values.
func (g Group) String() string {
v := []string{
g.name,
g.passwd,
strconv.FormatUint(uint64(g.gid), 10),
}
v = append(v, g.members...)
return strings.Join(v, ":")
}
// NewByName returns a passwd entry from a name.
func NewByName(ctx context.Context, name string, cacheOpts ...cache.Option) (g Group, err error) {
defer func() {
if err != nil {
err = fmt.Errorf("failed to get group entry from name %q: %w", name, err)
}
}()
logger.Debug(ctx, "Requesting a group entry matching name %q", name)
if name == "shadow" {
logger.Debug(ctx, "Ignoring shadow group as it's not in our database")
return Group{}, nss.ErrNotFoundENoEnt
}
c, err := cache.New(ctx, cacheOpts...)
if err != nil {
return Group{}, nss.ConvertErr(err)
}
defer c.Close(ctx)
grp, err := c.GetGroupByName(ctx, name)
if err != nil {
return Group{}, nss.ConvertErr(err)
}
return Group{
name: grp.Name,
passwd: grp.Password,
gid: uint(grp.GID),
members: grp.Members,
}, nil
}
// NewByGID returns a group entry from a GID.
func NewByGID(ctx context.Context, gid uint, cacheOpts ...cache.Option) (g Group, err error) {
defer func() {
if err != nil {
err = fmt.Errorf("failed to get group entry from GID %d: %w", gid, err)
}
}()
logger.Debug(ctx, "Requesting an group entry matching GID %d", gid)
c, err := cache.New(ctx, cacheOpts...)
if err != nil {
return Group{}, nss.ConvertErr(err)
}
defer c.Close(ctx)
grp, err := c.GetGroupByGID(ctx, gid)
if err != nil {
return Group{}, nss.ConvertErr(err)
}
return Group{
name: grp.Name,
passwd: grp.Password,
gid: uint(grp.GID),
members: grp.Members,
}, nil
}
var groupIterationCache *cache.Cache
// StartEntryIteration open a new cache for iteration.
// This needs to be called prior to calling NextEntry and be closed with EndEntryIteration.
func StartEntryIteration(ctx context.Context, cacheOpts ...cache.Option) error {
if groupIterationCache != nil {
return nss.ConvertErr(errors.New("group entry iteration already in progress. End it before starting a new one"))
}
c, err := cache.New(ctx, cacheOpts...)
if err != nil {
return nss.ConvertErr(err)
}
groupIterationCache = c
return nil
}
// EndEntryIteration closes the underlying DB iteration.
func EndEntryIteration(ctx context.Context) error {
if groupIterationCache == nil {
logger.Warn(ctx, "group entry iteration ended without initialization first")
return nil
}
c := groupIterationCache
defer c.Close(ctx)
groupIterationCache = nil
return nss.ConvertErr(c.CloseGroupIterator(ctx))
}
// NextEntry returns next available entry in Group. It will returns ENOENT from cache when the iteration is done.
func NextEntry(ctx context.Context) (g Group, err error) {
defer func() {
if err != nil {
err = fmt.Errorf("failed to get group entry: %w", err)
}
}()
logger.Debug(ctx, "get next group entry")
if groupIterationCache == nil {
return Group{}, nss.ConvertErr(errors.New("group entry iteration called without initialization first"))
}
grp, err := groupIterationCache.NextGroupEntry(ctx)
if err != nil {
return Group{}, nss.ConvertErr(err)
}
return Group{
name: grp.Name,
passwd: grp.Password,
gid: uint(grp.GID),
members: grp.Members,
}, nil
}