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 21
/
integration_test.go
186 lines (155 loc) · 7.34 KB
/
integration_test.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/ubuntu/aad-auth/internal/testutils"
)
func TestIntegration(t *testing.T) {
t.Parallel()
originOuts := make(map[string]string)
for _, db := range []string{"passwd", "group", "shadow"} {
//#nosec:G204 - We control the cmd arguments in tests.
data, err := exec.Command("getent", db).CombinedOutput()
require.NoError(t, err, "Setup: can't run getent to get original output from system")
originOuts[db] = string(data)
}
noShadow := 0
//nolint:dupl // We use the same table for the integration and the package tests.
tests := map[string]struct {
db string
key string
cacheDB string
rootUID int
shadowMode *int
wantErr bool
}{
// List entry by name
"list entry from passwd by name": {db: "passwd", key: "myuser@domain.com"},
"list entry from group by name": {db: "group", key: "myuser@domain.com"},
"list entry from shadow by name": {db: "shadow", key: "myuser@domain.com"},
// List entry by UID/GID
"list entry from passwd by uid": {db: "passwd", key: "165119649"},
"list entry from group by gid": {db: "group", key: "165119649"},
"error when listing entry from shadow by uid": {db: "shadow", key: "165119649", wantErr: true},
// List entries
"list passwd": {db: "passwd"},
"list group": {db: "group"},
"list shadow": {db: "shadow"},
// List entries without access to shadow
"list passwd without access to shadow": {db: "passwd", shadowMode: &noShadow},
"list group without access to shadow": {db: "group", shadowMode: &noShadow},
"returns nothing when listing shadow without access": {db: "shadow", shadowMode: &noShadow},
// List entries by name without access to shadow
"list entry from passwd by name without access to shadow": {db: "passwd", key: "myuser@domain.com", shadowMode: &noShadow},
"list entry from group by name without access to shadow": {db: "group", key: "myuser@domain.com", shadowMode: &noShadow},
"error when listing entry from shadow by name without access": {db: "shadow", key: "myuser@domain.com", shadowMode: &noShadow, wantErr: true},
// List entries by UID/GID without access to shadow
"list entry from passwd by uid without access to shadow": {db: "passwd", key: "165119649", shadowMode: &noShadow},
"list entry from group by gid without access to shadow": {db: "group", key: "165119649", shadowMode: &noShadow},
"error when listing entry from shadow by uid without access": {db: "shadow", key: "165119649", shadowMode: &noShadow, wantErr: true},
// Error when listing non-existent entry
"error when listing non-existent entry in passwd": {db: "passwd", key: "doesnotexist@domain.com", wantErr: true},
"error when listing non-existent entry in group": {db: "group", key: "doesnotexist@domain.com", wantErr: true},
"error when listing non-existent entry in shadow": {db: "shadow", key: "doesnotexist@domain.com", wantErr: true},
// Returns nothing when listing without cache
"returns nothing when listing passwd without cache and no permission to create it": {db: "passwd", cacheDB: "nocache", rootUID: 4242},
"returns nothing when listing group without cache and no permission to create it": {db: "group", cacheDB: "nocache", rootUID: 4242},
"returns nothing when listing shadow without cache and no permission to create it": {db: "shadow", cacheDB: "nocache", rootUID: 4242},
// Returns nothing when listing with empty cache
"returns nothing when listing passwd with empty cache": {db: "passwd", cacheDB: "empty"},
"returns nothing when listing group with empty cache": {db: "group", cacheDB: "empty"},
"returns nothing when listing shadow with empty cache": {db: "shadow", cacheDB: "empty"},
// List local entry without cache
"list local passwd entry without cache": {db: "passwd", cacheDB: "nocache", key: "0"},
"list local group entry without cache": {db: "group", cacheDB: "nocache", key: "0"},
"list local shadow entry without cache": {db: "shadow", cacheDB: "nocache", key: "root", wantErr: true},
// Cleans up old entries
"old entries in passwd are cleaned": {db: "passwd", cacheDB: "db_with_old_users"},
"old entries in group are cleaned": {db: "group", cacheDB: "db_with_old_users"},
"old entries in shadow are cleaned": {db: "shadow", cacheDB: "db_with_old_users"},
// Returns nothing when listing without permission on cache
"returns nothing when listing passwd without permission on cache": {db: "passwd", rootUID: 4242},
"returns nothing when listing group without permission on cache": {db: "group", rootUID: 4242},
"returns nothing when listing shadow without permission on cache": {db: "shadow", rootUID: 4242},
// Error when trying to list from unsupported database
"error on trying to list entry by name from unsupported db": {db: "unsupported", key: "myuser@domain.com", wantErr: true},
"error on trying to list unsupported db": {db: "unsupported", wantErr: true},
// Error when trying to list from db with an explicit empty key
"error on get entry from passwd with explicit empty key": {db: "passwd", key: "-", wantErr: true},
"error on get entry from group with explicit empty key": {db: "group", key: "-", wantErr: true},
"error on get entry from shadow with explicit empty key": {db: "shadow", key: "-", wantErr: true},
}
for name, tc := range tests {
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
uid, gid := testutils.GetCurrentUIDGID(t)
if tc.rootUID != 0 {
uid = tc.rootUID
}
cacheDir := t.TempDir()
switch tc.cacheDB {
case "":
testutils.PrepareDBsForTests(t, cacheDir, "users_in_db")
case "db_with_old_users":
testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB)
case "empty":
testutils.NewCacheForTests(t, cacheDir)
case "nocache":
break
default:
t.Fatalf("Unexpected value used for cacheDB: %q", tc.cacheDB)
}
shadowMode := -1
if tc.shadowMode != nil {
shadowMode = *tc.shadowMode
}
cmds := []string{"getent", tc.db}
if tc.key == "-" {
cmds = append(cmds, "")
} else if tc.key != "" {
cmds = append(cmds, tc.key)
}
got, err := outNSSCommandForLib(t, uid, gid, shadowMode, cacheDir, originOuts[tc.db], cmds...)
if tc.wantErr {
require.Error(t, err, "Expected an error but got none: %v", got)
return
}
require.NoError(t, err, "Expected no error but got one: %v", err)
want := testutils.LoadAndUpdateFromGolden(t, got)
require.Equal(t, want, got, "Output must match")
})
}
}
func TestMain(m *testing.M) {
// Build the NSS library and executable in a temporary directory and allow linking to it.
tmpDir, cleanup, err := createTempDir()
if err != nil {
os.Exit(1)
}
defer cleanup()
libPath = filepath.Join(tmpDir, "libnss_aad.so.2")
execPath = filepath.Join(tmpDir, "aad-auth")
// Builds the NSS Go CLI.
// #nosec:G204 - we control the command arguments in tests
cmd := exec.Command("go", "build", "-tags", "integrationtests", "-o", execPath)
if err = cmd.Run(); err != nil {
cleanup()
fmt.Fprintf(os.Stderr, "Can not build nss Go module: %v", err)
os.Exit(1)
}
// Builds the NSS Library.
if err = buildNSSCLib(); err != nil {
cleanup()
fmt.Fprintf(os.Stderr, "Can not build nss C library: %v", err)
os.Exit(1)
}
testutils.InstallUpdateFlag()
flag.Parse()
m.Run()
}