diff --git a/.github/workflows/qa.yaml b/.github/workflows/qa.yaml index d034c952..03ab22b8 100644 --- a/.github/workflows/qa.yaml +++ b/.github/workflows/qa.yaml @@ -15,7 +15,7 @@ jobs: - name: Install dependencies run: | sudo DEBIAN_FRONTEND=noninteractive apt update - sudo DEBIAN_FRONTEND=noninteractive apt install -y libpam-dev + sudo DEBIAN_FRONTEND=noninteractive apt install -y libpam-dev libglib2.0-dev gcc - uses: actions/checkout@v3 - name: Code formatting, vet, static checker Security… uses: golangci/golangci-lint-action@v3 @@ -38,8 +38,12 @@ jobs: # Build PAM library go build -ldflags='-s -w' -buildmode=c-shared -o pam_aad.so ./pam - # Build NSS library - go build -ldflags='-s -w' -buildmode=c-shared -o libnss_aad.so.2 ./nss/integration_tests + # Build NSS CLI executable + go build -o aad-auth ./nss/aad-auth + + # Build NSS C library + make -C nss/ libnss_aad.so.2 + if: ${{ always() }} tests: diff --git a/nss/integration_tests/nss_dboverride.go b/nss/aad-auth/db_override.go similarity index 82% rename from nss/integration_tests/nss_dboverride.go rename to nss/aad-auth/db_override.go index 03aaba63..0b9923a0 100644 --- a/nss/integration_tests/nss_dboverride.go +++ b/nss/aad-auth/db_override.go @@ -10,21 +10,6 @@ import ( "github.com/ubuntu/aad-auth/internal/cache" ) -/* -#include -#include - -static void __attribute__((constructor)) -nsstest_ctor(void) -{ - __nss_configure_lookup("passwd", "files aad"); - __nss_configure_lookup("group", "files aad"); - __nss_configure_lookup("shadow", "go aad"); - -} -*/ -import "C" - // initialize via env variables in mock test func init() { uidEnv := os.Getenv("NSS_AAD_ROOT_UID") diff --git a/nss/aad-auth/getent.go b/nss/aad-auth/getent.go index 79ad4ac0..3b05f7e6 100644 --- a/nss/aad-auth/getent.go +++ b/nss/aad-auth/getent.go @@ -17,30 +17,29 @@ import ( var supportedDbs = []string{"group", "passwd", "shadow"} // Getent processes the args and queries the database for the requested entries. -func Getent(ctx context.Context, dbName, key string, cacheOpts ...cache.Option) (string, error) { +func Getent(ctx context.Context, dbName string, key *string, cacheOpts ...cache.Option) (string, error) { if !dbIsSupported(dbName) { return "", fmt.Errorf("database %q is not supported", dbName) } - logger.Debug(ctx, "Getting entry %q from %s ", key, dbName) - var entries []fmt.Stringer var err error - if key != "" { + if key == nil { + entries, err = getAllEntries(ctx, dbName, cacheOpts...) + } else { var e fmt.Stringer - e, err = getEntryByKey(ctx, dbName, key, cacheOpts...) + e, err = getEntryByKey(ctx, dbName, *key, cacheOpts...) entries = []fmt.Stringer{e} if err != nil { entries = nil } - } else { - entries, err = getAllEntries(ctx, dbName, cacheOpts...) } return fmtGetentOutput(ctx, entries, err), nil } func getEntryByKey(ctx context.Context, dbName, key string, cacheOpts ...cache.Option) (entry fmt.Stringer, err error) { + logger.Debug(ctx, "Getting entry %q from %s", key, dbName) u, err := strconv.ParseUint(key, 10, 64) if err != nil { return getEntryByName(ctx, dbName, key, cacheOpts...) diff --git a/nss/aad-auth/aadauth_test.go b/nss/aad-auth/getent_test.go similarity index 88% rename from nss/aad-auth/aadauth_test.go rename to nss/aad-auth/getent_test.go index fa3f8ef5..9c211c8a 100644 --- a/nss/aad-auth/aadauth_test.go +++ b/nss/aad-auth/getent_test.go @@ -2,7 +2,6 @@ package main import ( "context" - "flag" "testing" "github.com/stretchr/testify/require" @@ -10,8 +9,9 @@ import ( "github.com/ubuntu/aad-auth/internal/testutils" ) -func TestGetEnt(t *testing.T) { +func TestGetent(t *testing.T) { noShadow := 0 + //nolint:dupl // We use the same table for the integration and the package tests. tests := map[string]struct { db string key string @@ -72,6 +72,11 @@ func TestGetEnt(t *testing.T) { "try to list group without permission on cache": {db: "group", rootUID: 4242}, "try to list shadow without permission on cache": {db: "shadow", rootUID: 4242}, + // Try to get entry with empty value + "try to get passwd entry with explicit empty key": {db: "passwd", key: "-"}, + "try to get group entry with explicit empty key": {db: "group", key: "-"}, + "try to get shadow entry with explicit empty key": {db: "shadow", key: "-"}, + // Error when trying to list from unsupported database "error trying to list entry by name from unsupported db": {db: "unsupported", key: "myuser@domain.com", wantErr: true}, "error trying to list unsupported db": {db: "unsupported", wantErr: true}, @@ -105,7 +110,15 @@ func TestGetEnt(t *testing.T) { opts = append(opts, cache.WithShadowMode(*tc.shadowMode)) } - got, err := Getent(context.Background(), tc.db, tc.key, opts...) + var key *string + var emptyString string + if tc.key == "-" { + key = &emptyString + } else if tc.key != "" { + key = &tc.key + } + + got, err := Getent(context.Background(), tc.db, key, opts...) if tc.wantErr { require.Error(t, err, "Expected an error but got none.") return @@ -117,9 +130,3 @@ func TestGetEnt(t *testing.T) { }) } } - -func TestMain(m *testing.M) { - testutils.InstallUpdateFlag() - flag.Parse() - m.Run() -} diff --git a/nss/integration_tests/common_test.go b/nss/aad-auth/helper_test.go similarity index 54% rename from nss/integration_tests/common_test.go rename to nss/aad-auth/helper_test.go index d1a19efd..87b901da 100644 --- a/nss/integration_tests/common_test.go +++ b/nss/aad-auth/helper_test.go @@ -2,7 +2,6 @@ package main import ( "bytes" - "flag" "fmt" "io" "os" @@ -10,15 +9,13 @@ import ( "path/filepath" "strings" "testing" - - "github.com/ubuntu/aad-auth/internal/testutils" ) -var libPath string +var libPath, execPath string -// outNSSCommandForLib returns the specific part by the nss command to got, filtering originOut. -// It uses the locally build aad nss module. -func outNSSCommandForLib(t *testing.T, rootUID, rootGID, shadowMode int, cacheDir string, originOut []byte, cmds ...string) (got string, err error) { +// outNSSCommandForLib returns the specific part for the nss command, filtering originOut. +// It uses the locally build aad nss module for the integration tests. +func outNSSCommandForLib(t *testing.T, rootUID, rootGID, shadowMode int, cacheDir string, originOut string, cmds ...string) (got string, err error) { t.Helper() // #nosec:G204 - we control the command arguments in tests @@ -42,7 +39,7 @@ func outNSSCommandForLib(t *testing.T, rootUID, rootGID, shadowMode int, cacheDi cmd.Stdout = io.MultiWriter(os.Stdout, &out) cmd.Stderr = os.Stderr err = cmd.Run() - got = strings.Replace(out.String(), string(originOut), "", 1) + got = strings.Replace(out.String(), originOut, "", 1) return got, err } @@ -60,24 +57,34 @@ func createTempDir() (tmp string, cleanup func(), err error) { }, nil } -func TestMain(m *testing.M) { - // Build the pam module in a temporary directory and allow linking to it. - libDir, cleanup, err := createTempDir() +func buildNSSCLib() error { + // Gets the .c files required to build the NSS C library. + cFiles, err := filepath.Glob("../*.c") if err != nil { - os.Exit(1) + return fmt.Errorf("error when fetching the required c files: %w", err) } - libPath = filepath.Join(libDir, "libnss_aad.so.2") - // #nosec:G204 - we control the command arguments in tests - out, err := exec.Command("go", "build", "-buildmode=c-shared", "-tags", "integrationtests", "-o", libPath).CombinedOutput() + // Gets the cflags and ldflags. + flags := []string{"-g", "-Wall", "-Wextra"} + out, err := exec.Command("pkg-config", "--cflags", "--libs", "glib-2.0").CombinedOutput() if err != nil { - cleanup() - fmt.Fprintf(os.Stderr, "Can not build nss module (%v) : %s", err, out) - os.Exit(1) + return fmt.Errorf("could not get the required cflags (%s): %w", out, err) } + flags = append(flags, strings.Fields(string(out))...) + + // Assembles the flags required to build the NSS library. + c := []string{fmt.Sprintf(`-DSCRIPTPATH="%s"`, execPath)} + c = append(c, "-DINTEGRATIONTESTS=1") + c = append(c, cFiles...) + c = append(c, flags...) + c = append(c, "-fPIC", "-shared", "-Wl,-soname,libnss_aad.so.2", "-o", libPath) - testutils.InstallUpdateFlag() - flag.Parse() + // #nosec:G204 - we control the command arguments in tests. + cmd := exec.Command("gcc", c...) + out, err = cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("can not build nss library (%s): %w", out, err) + } - m.Run() + return nil } diff --git a/nss/aad-auth/integration_test.go b/nss/aad-auth/integration_test.go new file mode 100644 index 00000000..1145c9bf --- /dev/null +++ b/nss/aad-auth/integration_test.go @@ -0,0 +1,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() +} diff --git a/nss/aad-auth/main.go b/nss/aad-auth/main.go index 19345728..c17c7191 100644 --- a/nss/aad-auth/main.go +++ b/nss/aad-auth/main.go @@ -7,10 +7,13 @@ import ( "os" "strings" + "github.com/ubuntu/aad-auth/internal/cache" "github.com/ubuntu/aad-auth/internal/logger" "github.com/ubuntu/aad-auth/internal/nss" ) +var opts []cache.Option + func main() { flag.Usage = aadAuthUsage flag.Parse() @@ -20,11 +23,17 @@ func main() { ctx := nss.CtxWithSyslogLogger(context.Background()) defer logger.CloseLoggerFromContext(ctx) - db, key := flag.Arg(1), flag.Arg(2) + db := flag.Arg(1) + + var key *string + if len(flag.Args()) > 2 { + k := flag.Arg(2) + key = &k + } - out, err := Getent(ctx, db, key) + out, err := Getent(ctx, db, key, opts...) if err != nil { - exit(1, fmt.Sprintf("Error when trying to list %q from %s: %v", key, db, err)) + exit(1, fmt.Sprintf("Error when trying to list %v from %s: %v", key, db, err)) } fmt.Print(out) case "": diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_group b/nss/aad-auth/testdata/golden/TestGetent/list_entries_in_group similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_group rename to nss/aad-auth/testdata/golden/TestGetent/list_entries_in_group diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_group_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestGetent/list_entries_in_group_without_access_to_shadow similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_group_without_access_to_shadow rename to nss/aad-auth/testdata/golden/TestGetent/list_entries_in_group_without_access_to_shadow diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_passwd b/nss/aad-auth/testdata/golden/TestGetent/list_entries_in_passwd similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_passwd rename to nss/aad-auth/testdata/golden/TestGetent/list_entries_in_passwd diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_passwd_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestGetent/list_entries_in_passwd_without_access_to_shadow similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_passwd_without_access_to_shadow rename to nss/aad-auth/testdata/golden/TestGetent/list_entries_in_passwd_without_access_to_shadow diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_shadow b/nss/aad-auth/testdata/golden/TestGetent/list_entries_in_shadow similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entries_in_shadow rename to nss/aad-auth/testdata/golden/TestGetent/list_entries_in_shadow diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_group_by_gid b/nss/aad-auth/testdata/golden/TestGetent/list_entry_from_group_by_gid similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_group_by_gid rename to nss/aad-auth/testdata/golden/TestGetent/list_entry_from_group_by_gid diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_group_by_name b/nss/aad-auth/testdata/golden/TestGetent/list_entry_from_group_by_name similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_group_by_name rename to nss/aad-auth/testdata/golden/TestGetent/list_entry_from_group_by_name diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_passwd_by_name b/nss/aad-auth/testdata/golden/TestGetent/list_entry_from_passwd_by_name similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_passwd_by_name rename to nss/aad-auth/testdata/golden/TestGetent/list_entry_from_passwd_by_name diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_passwd_by_uid b/nss/aad-auth/testdata/golden/TestGetent/list_entry_from_passwd_by_uid similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_passwd_by_uid rename to nss/aad-auth/testdata/golden/TestGetent/list_entry_from_passwd_by_uid diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_shadow_by_name b/nss/aad-auth/testdata/golden/TestGetent/list_entry_from_shadow_by_name similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_entry_from_shadow_by_name rename to nss/aad-auth/testdata/golden/TestGetent/list_entry_from_shadow_by_name diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_local_group_entry_without_cache b/nss/aad-auth/testdata/golden/TestGetent/list_local_group_entry_without_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_local_group_entry_without_cache rename to nss/aad-auth/testdata/golden/TestGetent/list_local_group_entry_without_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_local_passwd_entry_without_cache b/nss/aad-auth/testdata/golden/TestGetent/list_local_passwd_entry_without_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_local_passwd_entry_without_cache rename to nss/aad-auth/testdata/golden/TestGetent/list_local_passwd_entry_without_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/list_local_shadow_entry_without_cache b/nss/aad-auth/testdata/golden/TestGetent/list_local_shadow_entry_without_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/list_local_shadow_entry_without_cache rename to nss/aad-auth/testdata/golden/TestGetent/list_local_shadow_entry_without_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_group_are_cleaned b/nss/aad-auth/testdata/golden/TestGetent/old_entries_in_group_are_cleaned similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_group_are_cleaned rename to nss/aad-auth/testdata/golden/TestGetent/old_entries_in_group_are_cleaned diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_passwd_are_cleaned b/nss/aad-auth/testdata/golden/TestGetent/old_entries_in_passwd_are_cleaned similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_passwd_are_cleaned rename to nss/aad-auth/testdata/golden/TestGetent/old_entries_in_passwd_are_cleaned diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_shadow_are_cleaned b/nss/aad-auth/testdata/golden/TestGetent/old_entries_in_shadow_are_cleaned similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/old_entries_in_shadow_are_cleaned rename to nss/aad-auth/testdata/golden/TestGetent/old_entries_in_shadow_are_cleaned diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_entry_from_shadow_by_uid b/nss/aad-auth/testdata/golden/TestGetent/try_to_get_group_entry_with_explicit_empty_key similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_entry_from_shadow_by_uid rename to nss/aad-auth/testdata/golden/TestGetent/try_to_get_group_entry_with_explicit_empty_key diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_group b/nss/aad-auth/testdata/golden/TestGetent/try_to_get_passwd_entry_with_explicit_empty_key similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_group rename to nss/aad-auth/testdata/golden/TestGetent/try_to_get_passwd_entry_with_explicit_empty_key diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_passwd b/nss/aad-auth/testdata/golden/TestGetent/try_to_get_shadow_entry_with_explicit_empty_key similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_passwd rename to nss/aad-auth/testdata/golden/TestGetent/try_to_get_shadow_entry_with_explicit_empty_key diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_entry_from_shadow_by_name_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_entry_from_shadow_by_name_without_access_to_shadow similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_entry_from_shadow_by_name_without_access_to_shadow rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_entry_from_shadow_by_name_without_access_to_shadow diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_shadow b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_entry_from_shadow_by_uid similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_non-existent_entry_in_shadow rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_entry_from_shadow_by_uid diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_with_empty_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_with_empty_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_with_empty_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_with_empty_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_without_cache_and_no_permission_to_create_it b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_without_cache_and_no_permission_to_create_it similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_without_cache_and_no_permission_to_create_it rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_without_cache_and_no_permission_to_create_it diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_without_permission_on_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_without_permission_on_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_group_without_permission_on_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_group_without_permission_on_cache diff --git a/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_group b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_group new file mode 100644 index 00000000..14678bb4 --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_group @@ -0,0 +1 @@ +"0:2" diff --git a/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_passwd b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_passwd new file mode 100644 index 00000000..14678bb4 --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_passwd @@ -0,0 +1 @@ +"0:2" diff --git a/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_shadow b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_shadow new file mode 100644 index 00000000..14678bb4 --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_non-existent_entry_in_shadow @@ -0,0 +1 @@ +"0:2" diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_with_empty_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_with_empty_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_with_empty_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_with_empty_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_without_cache_and_no_permission_to_create_it b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_without_cache_and_no_permission_to_create_it similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_without_cache_and_no_permission_to_create_it rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_without_cache_and_no_permission_to_create_it diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_without_permission_on_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_without_permission_on_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_passwd_without_permission_on_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_passwd_without_permission_on_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_with_empty_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_with_empty_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_with_empty_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_with_empty_cache diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_access_to_shadow similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_access_to_shadow rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_access_to_shadow diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_cache_and_no_permission_to_create_it b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_cache_and_no_permission_to_create_it similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_cache_and_no_permission_to_create_it rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_cache_and_no_permission_to_create_it diff --git a/nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_permission_on_cache b/nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_permission_on_cache similarity index 100% rename from nss/aad-auth/testdata/golden/TestGetEnt/try_to_list_shadow_without_permission_on_cache rename to nss/aad-auth/testdata/golden/TestGetent/try_to_list_shadow_without_permission_on_cache diff --git a/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid new file mode 100644 index 00000000..b4e9b27a --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid @@ -0,0 +1,2 @@ +| + user@otherdomain.com:x:165119649:user@otherdomain.com diff --git a/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid_without_access_to_shadow new file mode 100644 index 00000000..b4e9b27a --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_gid_without_access_to_shadow @@ -0,0 +1,2 @@ +| + user@otherdomain.com:x:165119649:user@otherdomain.com diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByGID/access_to_shadow_is_not_needed_to_list_existing_group b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_name similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroupByGID/access_to_shadow_is_not_needed_to_list_existing_group rename to nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_name diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByGID/list_existing_group b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_name_without_access_to_shadow similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroupByGID/list_existing_group rename to nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_group_by_name_without_access_to_shadow diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByName/access_to_shadow_is_not_needed_to_list_existing_user b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_name similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswdByName/access_to_shadow_is_not_needed_to_list_existing_user rename to nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_name diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByName/list_existing_user b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_name_without_access_to_shadow similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswdByName/list_existing_user rename to nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_name_without_access_to_shadow diff --git a/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid new file mode 100644 index 00000000..084173c5 --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid @@ -0,0 +1,2 @@ +| + user@otherdomain.com:x:165119649:165119649::/home/user@otherdomain.com:/bin/bash diff --git a/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid_without_access_to_shadow b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid_without_access_to_shadow new file mode 100644 index 00000000..084173c5 --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_passwd_by_uid_without_access_to_shadow @@ -0,0 +1,2 @@ +| + user@otherdomain.com:x:165119649:165119649::/home/user@otherdomain.com:/bin/bash diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadowByName/list_existing_shadow_user b/nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_shadow_by_name similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadowByName/list_existing_shadow_user rename to nss/aad-auth/testdata/golden/TestIntegration/list_entry_from_shadow_by_name diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroup/access_to_shadow_is_not_needed_to_list_groups b/nss/aad-auth/testdata/golden/TestIntegration/list_group similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroup/access_to_shadow_is_not_needed_to_list_groups rename to nss/aad-auth/testdata/golden/TestIntegration/list_group diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroup/list_all_groups b/nss/aad-auth/testdata/golden/TestIntegration/list_group_without_access_to_shadow similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroup/list_all_groups rename to nss/aad-auth/testdata/golden/TestIntegration/list_group_without_access_to_shadow diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByGID/no_cache_no_error_on_existing_local_group b/nss/aad-auth/testdata/golden/TestIntegration/list_local_group_entry_without_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroupByGID/no_cache_no_error_on_existing_local_group rename to nss/aad-auth/testdata/golden/TestIntegration/list_local_group_entry_without_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByName/no_cache_no_error_on_existing_local_user b/nss/aad-auth/testdata/golden/TestIntegration/list_local_passwd_entry_without_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswdByName/no_cache_no_error_on_existing_local_user rename to nss/aad-auth/testdata/golden/TestIntegration/list_local_passwd_entry_without_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswd/access_to_shadow_is_not_needed_to_list_users b/nss/aad-auth/testdata/golden/TestIntegration/list_passwd similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswd/access_to_shadow_is_not_needed_to_list_users rename to nss/aad-auth/testdata/golden/TestIntegration/list_passwd diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswd/list_all_users b/nss/aad-auth/testdata/golden/TestIntegration/list_passwd_without_access_to_shadow similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswd/list_all_users rename to nss/aad-auth/testdata/golden/TestIntegration/list_passwd_without_access_to_shadow diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadow/list_all_shadow_users b/nss/aad-auth/testdata/golden/TestIntegration/list_shadow similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadow/list_all_shadow_users rename to nss/aad-auth/testdata/golden/TestIntegration/list_shadow diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroup/old_groups_are_cleaned_up b/nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_group_are_cleaned similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroup/old_groups_are_cleaned_up rename to nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_group_are_cleaned diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswd/old_users_are_cleaned_up b/nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_passwd_are_cleaned similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswd/old_users_are_cleaned_up rename to nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_passwd_are_cleaned diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadow/old_shadow_users_are_cleaned_up b/nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_shadow_are_cleaned similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadow/old_shadow_users_are_cleaned_up rename to nss/aad-auth/testdata/golden/TestIntegration/old_entries_in_shadow_are_cleaned diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroup/invalid_permissions_on_cache_lists_no_groups b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_with_empty_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroup/invalid_permissions_on_cache_lists_no_groups rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_with_empty_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroup/no_cache_lists_no_groups b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_without_cache_and_no_permission_to_create_it similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetGroup/no_cache_lists_no_groups rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_without_cache_and_no_permission_to_create_it diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswd/invalid_permissions_on_cache_lists_no_users b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_without_permission_on_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswd/invalid_permissions_on_cache_lists_no_users rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_group_without_permission_on_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswd/no_cache_lists_no_user b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_with_empty_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetPasswd/no_cache_lists_no_user rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_with_empty_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadow/invalid_permissions_on_cache_lists_no_shadow_users b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_without_cache_and_no_permission_to_create_it similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadow/invalid_permissions_on_cache_lists_no_shadow_users rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_without_cache_and_no_permission_to_create_it diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadow/no_access_to_shadow_list_no_users b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_without_permission_on_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadow/no_access_to_shadow_list_no_users rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_passwd_without_permission_on_cache diff --git a/nss/integration_tests/testdata/golden/TestNssGetShadow/no_cache_lists_no_shadow_user b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_with_empty_cache similarity index 100% rename from nss/integration_tests/testdata/golden/TestNssGetShadow/no_cache_lists_no_shadow_user rename to nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_with_empty_cache diff --git a/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_access b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_access new file mode 100644 index 00000000..e16c76df --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_access @@ -0,0 +1 @@ +"" diff --git a/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_cache_and_no_permission_to_create_it b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_cache_and_no_permission_to_create_it new file mode 100644 index 00000000..e16c76df --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_cache_and_no_permission_to_create_it @@ -0,0 +1 @@ +"" diff --git a/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_permission_on_cache b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_permission_on_cache new file mode 100644 index 00000000..e16c76df --- /dev/null +++ b/nss/aad-auth/testdata/golden/TestIntegration/returns_nothing_when_listing_shadow_without_permission_on_cache @@ -0,0 +1 @@ +"" diff --git a/nss/common.c b/nss/common.c index b191d22e..82894908 100644 --- a/nss/common.c +++ b/nss/common.c @@ -18,13 +18,19 @@ enum nss_status run_aad_auth(const char *db, const char *name, const uid_t uid, int *errnop, GPtrArray *entries) { - gchar *stdout = NULL; - gchar *stderr = NULL; + gchar *out = NULL; + gchar *err = NULL; GError *error = NULL; gchar *cmd; - if (name) + if (name != NULL) { + // Empty name would be trimmed by g_spawn_command_line_sync and no argument will be provided, forcing it + // to list every entries. + if (!g_strcmp0(name, "")) { + name = g_strdup("''"); + } + // Concatenate name with cmd cmd = g_strconcat(SCRIPTPATH, " ", "getent", " ", db, " ", name, NULL); } @@ -41,16 +47,21 @@ enum nss_status run_aad_auth(const char *db, const char *name, const uid_t uid, } gint exit_status; - if (!g_spawn_command_line_sync(cmd, &stdout, &stderr, &exit_status, &error) || exit_status != 0) + if (!g_spawn_command_line_sync(cmd, &out, &err, &exit_status, &error) || exit_status != 0) { + g_fprintf(stderr, err); *errnop = ENOENT; g_free(cmd); return NSS_STATUS_UNAVAIL; } g_free(cmd); + if(!g_strcmp0(getenv("NSS_AAD_DEBUG"), "stderr")) { + g_fprintf(stderr, err); + } + enum nss_status nss_exit_status; - gchar **lines = g_strsplit(stdout, "\n", -1); + gchar **lines = g_strsplit(out, "\n", -1); for (gint i = 0; lines[i]; i++) { if (!g_strcmp0(lines[i], "")) diff --git a/nss/db_override_test.c b/nss/db_override_test.c new file mode 100644 index 00000000..dfff9e97 --- /dev/null +++ b/nss/db_override_test.c @@ -0,0 +1,14 @@ +#include +#include + +#ifdef INTEGRATIONTESTS + +static void __attribute__((constructor)) +nsstest_ctor(void) +{ + __nss_configure_lookup("passwd", "files aad"); + __nss_configure_lookup("group", "files aad"); + __nss_configure_lookup("shadow", "files aad"); +} + +#endif \ No newline at end of file diff --git a/nss/integration_tests/group_c.go b/nss/integration_tests/group_c.go deleted file mode 100644 index 466c28af..00000000 --- a/nss/integration_tests/group_c.go +++ /dev/null @@ -1,105 +0,0 @@ -//nolint:dupl // nss/(group|passwd|shadow)_c.go files have similar code that triggers dupl, but they are different. -package main - -/* -#cgo LDFLAGS: -fPIC -#include -#include -#include - -typedef enum nss_status nss_status; -*/ -import "C" -import ( - "context" - "unsafe" - - "github.com/ubuntu/aad-auth/internal/logger" - "github.com/ubuntu/aad-auth/internal/nss" - "github.com/ubuntu/aad-auth/internal/nss/group" - "github.com/ubuntu/aad-auth/internal/user" -) - -//export _nss_aad_getgrnam_r -func _nss_aad_getgrnam_r(name *C.char, grp *C.struct_group, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - n := C.GoString(name) - logger.Debug(ctx, "_nss_aad_getgrname_r called for %q", n) - n = user.NormalizeName(n) - - p, err := group.NewByName(ctx, n, opts...) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - if err = p.ToCgroup(group.CGroup(unsafe.Pointer(grp)), (*group.CChar)(buf), group.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_getgrgid_r -func _nss_aad_getgrgid_r(gid C.gid_t, grp *C.struct_group, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_getgrgid_r called for %d", gid) - - g, err := group.NewByGID(ctx, uint(gid), opts...) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - if err = g.ToCgroup(group.CGroup(unsafe.Pointer(grp)), (*group.CChar)(buf), group.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_setgrent -func _nss_aad_setgrent(stayopen C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_setgrent called") - - err := group.StartEntryIteration(ctx, opts...) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Initialization of the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_endgrent -func _nss_aad_endgrent() C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_endgrent called") - - err := group.EndEntryIteration(ctx) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Closing the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_getgrent_r -func _nss_aad_getgrent_r(grbuf *C.struct_group, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_getgrent_r called") - - g, err := group.NextEntry(ctx) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - - if err = g.ToCgroup(group.CGroup(unsafe.Pointer(grbuf)), (*group.CChar)(buf), group.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} diff --git a/nss/integration_tests/group_test.go b/nss/integration_tests/group_test.go deleted file mode 100644 index a33a752f..00000000 --- a/nss/integration_tests/group_test.go +++ /dev/null @@ -1,194 +0,0 @@ -package main - -import ( - "os/exec" - "testing" - - "github.com/stretchr/testify/require" - "github.com/ubuntu/aad-auth/internal/testutils" -) - -// TODO: process coverage once https://github.com/golang/go/issues/51430 is implemented in Go. - -//nolint:dupl // TestNssGetGroupByName and TestGetPasswdByName have similar code that triggers dupl, despite being different. -func TestNssGetGroupByName(t *testing.T) { - t.Parallel() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - name string - - cacheDB string - rootUID int - shadowMode *int - - wantErr bool - }{ - "list existing group": {}, - "access to shadow is not needed to list existing group": {shadowMode: &noShadow}, - - "no cache no error on existing local group": {name: "root", cacheDB: "-"}, - - // error cases - "group does not exists": {name: "doesnotexist@domain.com", wantErr: true}, - "no cache can't get group": {cacheDB: "-", wantErr: true}, - "invalid permissions on cache can't get group": {rootUID: 4242, wantErr: true}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.name == "" { - tc.name = "myuser@domain.com" - } - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, nil, "getent", "group", tc.name) - if tc.wantErr { - require.Error(t, err, "getent should have errored out but didn't") - return - } - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad group") - }) - } -} - -//nolint:dupl // TestNssGetGroupByGID and TestGetPasswdByUID have similar code that triggers dupl, despite being different. -func TestNssGetGroupByGID(t *testing.T) { - t.Parallel() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - gid string - - cacheDB string - rootUID int - shadowMode *int - - wantErr bool - }{ - "list existing group": {}, - "access to shadow is not needed to list existing group": {shadowMode: &noShadow}, - - "no cache no error on existing local group": {gid: "0", cacheDB: "-"}, - - // error cases - "group does not exists": {gid: "4242", wantErr: true}, - "no cache can't get group": {cacheDB: "-", wantErr: true}, - "invalid permissions on cache can't get group": {rootUID: 4242, wantErr: true}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.gid == "" { - tc.gid = "1929326240" - } - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, nil, "getent", "group", tc.gid) - if tc.wantErr { - require.Error(t, err, "getent should have errored out but didn't") - return - } - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad group") - }) - } -} - -func TestNssGetGroup(t *testing.T) { - t.Parallel() - - originOut, err := exec.Command("getent", "group").CombinedOutput() - require.NoError(t, err, "Setup: can't run getent to get original output from system") - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - cacheDB string - - rootUID int - shadowGid int - shadowMode *int - }{ - "list all groups": {}, - "access to shadow is not needed to list groups": {shadowMode: &noShadow}, - - // special cases - "no cache lists no groups": {cacheDB: "-"}, - "invalid permissions on cache lists no groups": {rootUID: 4242}, - "old groups are cleaned up": {cacheDB: "db_with_old_users"}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, originOut, "getent", "group") - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad groups listed") - }) - } -} diff --git a/nss/integration_tests/nss.go b/nss/integration_tests/nss.go deleted file mode 100644 index 1010c5c6..00000000 --- a/nss/integration_tests/nss.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "github.com/ubuntu/aad-auth/internal/cache" -) - -var ( - opts = []cache.Option{} -) - -func main() { - -} diff --git a/nss/integration_tests/passwd_c.go b/nss/integration_tests/passwd_c.go deleted file mode 100644 index 3b47f660..00000000 --- a/nss/integration_tests/passwd_c.go +++ /dev/null @@ -1,107 +0,0 @@ -//nolint:dupl // nss/(group|passwd|shadow)_c.go files have similar code that triggers dupl, but they are different. -package main - -/* -#cgo LDFLAGS: -fPIC -#include -#include -#include - -typedef enum nss_status nss_status; -*/ -import "C" -import ( - "context" - "unsafe" - - "github.com/ubuntu/aad-auth/internal/logger" - "github.com/ubuntu/aad-auth/internal/nss" - "github.com/ubuntu/aad-auth/internal/nss/passwd" - "github.com/ubuntu/aad-auth/internal/user" -) - -//go:generate sh -c "go build -ldflags='-extldflags -Wl,-soname,libnss_aad.so.2' -buildmode=c-shared -o libnss_aad.so.2" - -//export _nss_aad_getpwnam_r -func _nss_aad_getpwnam_r(name *C.char, pwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - n := C.GoString(name) - logger.Debug(ctx, "_nss_aad_getpwnam_r called for %q", n) - n = user.NormalizeName(n) - - p, err := passwd.NewByName(ctx, n, opts...) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - if err = p.ToCpasswd(passwd.CPasswd(unsafe.Pointer(pwd)), (*passwd.CChar)(buf), passwd.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_getpwuid_r -func _nss_aad_getpwuid_r(uid C.uid_t, pwd *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_getpwuid_r called for %d", uid) - - p, err := passwd.NewByUID(ctx, uint(uid), opts...) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - if err = p.ToCpasswd(passwd.CPasswd(unsafe.Pointer(pwd)), (*passwd.CChar)(buf), passwd.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_setpwent -func _nss_aad_setpwent(stayopen C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_setpwent called") - - err := passwd.StartEntryIteration(ctx, opts...) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Initialization of the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_endpwent -func _nss_aad_endpwent() C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_endpwent called") - - err := passwd.EndEntryIteration(ctx) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Closing the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_getpwent_r -func _nss_aad_getpwent_r(pwbuf *C.struct_passwd, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_getpwent_r called") - - p, err := passwd.NextEntry(ctx) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - - if err = p.ToCpasswd(passwd.CPasswd(unsafe.Pointer(pwbuf)), (*passwd.CChar)(buf), passwd.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} diff --git a/nss/integration_tests/passwd_test.go b/nss/integration_tests/passwd_test.go deleted file mode 100644 index 8135f4d7..00000000 --- a/nss/integration_tests/passwd_test.go +++ /dev/null @@ -1,192 +0,0 @@ -package main - -import ( - "os/exec" - "testing" - - "github.com/stretchr/testify/require" - "github.com/ubuntu/aad-auth/internal/testutils" -) - -// TODO: process coverage once https://github.com/golang/go/issues/51430 is implemented in Go. - -//nolint:dupl // TestNssGetGroupByName and TestGetPasswdByName have similar code that triggers dupl, despite being different. -func TestNssGetPasswdByName(t *testing.T) { - t.Parallel() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - name string - - cacheDB string - rootUID int - shadowMode *int - - wantErr bool - }{ - "list existing user": {}, - "access to shadow is not needed to list existing user": {shadowMode: &noShadow}, - - "no cache no error on existing local user": {name: "root", cacheDB: "-"}, - - // error cases - "user does not exists": {name: "doesnotexist@domain.com", wantErr: true}, - "no cache can't get user": {cacheDB: "-", wantErr: true}, - "invalid permissions on cache can't get user": {rootUID: 4242, wantErr: true}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.name == "" { - tc.name = "myuser@domain.com" - } - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, nil, "getent", "passwd", tc.name) - if tc.wantErr { - require.Error(t, err, "getent should have errored out but didn't") - return - } - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad user") - }) - } -} - -//nolint:dupl // TestNssGetGroupByGID and TestGetPasswdByUID have similar code that triggers dupl, despite being different. -func TestNssGetPasswdByUID(t *testing.T) { - t.Parallel() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - uid string - - cacheDB string - rootUID int - shadowMode *int - - wantErr bool - }{ - "list existing user": {}, - "access to shadow is not needed to list existing user": {shadowMode: &noShadow}, - - "no cache no error on existing local user": {uid: "0", cacheDB: "-"}, - - // error cases - "user does not exists": {uid: "4242", wantErr: true}, - "no cache can't get user": {cacheDB: "-", wantErr: true}, - "invalid permissions on cache can't get user": {rootUID: 4242, wantErr: true}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.uid == "" { - tc.uid = "1929326240" - } - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, nil, "getent", "passwd", tc.uid) - if tc.wantErr { - require.Error(t, err, "getent should have errored out but didn't") - return - } - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad user") - }) - } -} -func TestNssGetPasswd(t *testing.T) { - t.Parallel() - - originOut, err := exec.Command("getent", "passwd").CombinedOutput() - require.NoError(t, err, "Setup: can't run getent to get original output from system") - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - cacheDB string - - rootUID int - shadowMode *int - }{ - "list all users": {}, - "access to shadow is not needed to list users": {shadowMode: &noShadow}, - - // special cases - "no cache lists no user": {cacheDB: "-"}, - "invalid permissions on cache lists no users": {rootUID: 4242}, - "old users are cleaned up": {cacheDB: "db_with_old_users"}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, originOut, "getent", "passwd") - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad users listed") - }) - } -} diff --git a/nss/integration_tests/shadow_c.go b/nss/integration_tests/shadow_c.go deleted file mode 100644 index 64cb29db..00000000 --- a/nss/integration_tests/shadow_c.go +++ /dev/null @@ -1,88 +0,0 @@ -//nolint:dupl // nss/(group|passwd|shadow)_c.go files have similar code that triggers dupl, but they are different. -package main - -/* -#cgo LDFLAGS: -fPIC -#include -#include -#include - -typedef enum nss_status nss_status; -*/ -import "C" -import ( - "context" - "unsafe" - - "github.com/ubuntu/aad-auth/internal/logger" - "github.com/ubuntu/aad-auth/internal/nss" - "github.com/ubuntu/aad-auth/internal/nss/shadow" - "github.com/ubuntu/aad-auth/internal/user" -) - -//export _nss_aad_getspnam_r -func _nss_aad_getspnam_r(name *C.char, spwd *C.struct_spwd, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - n := C.GoString(name) - logger.Debug(ctx, "_nss_aad_getspnam_r called for %q", n) - n = user.NormalizeName(n) - - sp, err := shadow.NewByName(ctx, n, opts...) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - if err = sp.ToCshadow(shadow.CShadow(unsafe.Pointer(spwd)), (*shadow.CChar)(buf), shadow.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_setspent -func _nss_aad_setspent() C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_setspent called") - - err := shadow.StartEntryIteration(ctx, opts...) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Initialization of the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_endspent -func _nss_aad_endspent() C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_endspent called") - - err := shadow.EndEntryIteration(ctx) - if err != nil { - return errToCStatus(ctx, err, nil) - } - - // Closing the database is done in the read primitive - return C.NSS_STATUS_SUCCESS -} - -//export _nss_aad_getspent_r -func _nss_aad_getspent_r(spwd *C.struct_spwd, buf *C.char, buflen C.size_t, errnop *C.int) C.nss_status { - ctx := nss.CtxWithSyslogLogger(context.Background()) - defer logger.CloseLoggerFromContext(ctx) - logger.Debug(ctx, "_nss_aad_getspent_r called") - - sp, err := shadow.NextEntry(ctx) - if err != nil { - return errToCStatus(ctx, err, errnop) - } - - if err = sp.ToCshadow(shadow.CShadow(unsafe.Pointer(spwd)), (*shadow.CChar)(buf), shadow.CSizeT(buflen)); err != nil { - return errToCStatus(ctx, err, errnop) - } - - return C.NSS_STATUS_SUCCESS -} diff --git a/nss/integration_tests/shadow_test.go b/nss/integration_tests/shadow_test.go deleted file mode 100644 index 0097ce9c..00000000 --- a/nss/integration_tests/shadow_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package main - -import ( - "os/exec" - "testing" - - "github.com/stretchr/testify/require" - "github.com/ubuntu/aad-auth/internal/testutils" -) - -// TODO: process coverage once https://github.com/golang/go/issues/51430 is implemented in Go. -func TestNssGetShadowByName(t *testing.T) { - t.Parallel() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - name string - - cacheDB string - rootUID int - shadowMode *int - - wantErr bool - }{ - // password is anonymized to not trigger pam_unix self-check. - "list existing shadow user": {}, - - "no cache no error on existing local shadow user": {name: "root", cacheDB: "-"}, - - // error cases - "error on no access to shadow": {shadowMode: &noShadow, wantErr: true}, - "shadow user does not exists": {name: "doesnotexist@domain.com", wantErr: true}, - "no cache can't get shadow user": {cacheDB: "-", wantErr: true}, - "invalid permissions on cache can't get user": {rootUID: 4242, wantErr: true}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - if tc.name == "root" && uid != 0 { - t.Skip("can't test getting local user from shadow when not being root or part of shadow group") - } - - cacheDir := t.TempDir() - if tc.name == "" { - tc.name = "myuser@domain.com" - } - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, nil, "getent", "shadow", tc.name) - if tc.wantErr { - require.Error(t, err, "getent should have errored out but didn't") - return - } - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad shadow user") - }) - } -} - -func TestNssGetShadow(t *testing.T) { - t.Parallel() - - // No need to check for err on originOut as we don’t necessarily have the right to access them. - originOut, _ := exec.Command("getent", "shadow").CombinedOutput() - - uid, gid := testutils.GetCurrentUIDGID(t) - - noShadow := 0 - - tests := map[string]struct { - cacheDB string - - rootUID int - shadowMode *int - }{ - "list all shadow users": {}, - - // special cases - "no access to shadow list no users": {shadowMode: &noShadow}, - "no cache lists no shadow user": {cacheDB: "-"}, - "invalid permissions on cache lists no shadow users": {rootUID: 4242}, - "old shadow users are cleaned up": {cacheDB: "db_with_old_users"}, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - cacheDir := t.TempDir() - if tc.cacheDB == "" { - tc.cacheDB = "users_in_db" - } - if tc.cacheDB != "-" { - testutils.PrepareDBsForTests(t, cacheDir, tc.cacheDB) - } - - if tc.rootUID == 0 { - tc.rootUID = uid - } - shadowMode := -1 - if tc.shadowMode != nil { - shadowMode = *tc.shadowMode - } - - got, err := outNSSCommandForLib(t, tc.rootUID, gid, shadowMode, cacheDir, originOut, "getent", "shadow") - require.NoError(t, err, "getent should succeed") - - want := testutils.LoadAndUpdateFromGolden(t, got) - require.Equal(t, want, got, "Should get expected aad shadow users listed") - }) - } -} diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/access_to_shadow_is_not_needed_to_list_existing_group b/nss/integration_tests/testdata/golden/TestNssGetGroupByName/access_to_shadow_is_not_needed_to_list_existing_group deleted file mode 100644 index 891cb878..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/access_to_shadow_is_not_needed_to_list_existing_group +++ /dev/null @@ -1,2 +0,0 @@ -| - myuser@domain.com:x:1929326240:myuser@domain.com diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/list_existing_group b/nss/integration_tests/testdata/golden/TestNssGetGroupByName/list_existing_group deleted file mode 100644 index 891cb878..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/list_existing_group +++ /dev/null @@ -1,2 +0,0 @@ -| - myuser@domain.com:x:1929326240:myuser@domain.com diff --git a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/no_cache_no_error_on_existing_local_group b/nss/integration_tests/testdata/golden/TestNssGetGroupByName/no_cache_no_error_on_existing_local_group deleted file mode 100644 index b682179d..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetGroupByName/no_cache_no_error_on_existing_local_group +++ /dev/null @@ -1,2 +0,0 @@ -| - root:x:0: diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/access_to_shadow_is_not_needed_to_list_existing_user b/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/access_to_shadow_is_not_needed_to_list_existing_user deleted file mode 100644 index 0fe2cf62..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/access_to_shadow_is_not_needed_to_list_existing_user +++ /dev/null @@ -1,2 +0,0 @@ -| - myuser@domain.com:x:1929326240:1929326240::/home/myuser@domain.com:/bin/bash diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/list_existing_user b/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/list_existing_user deleted file mode 100644 index 0fe2cf62..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/list_existing_user +++ /dev/null @@ -1,2 +0,0 @@ -| - myuser@domain.com:x:1929326240:1929326240::/home/myuser@domain.com:/bin/bash diff --git a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/no_cache_no_error_on_existing_local_user b/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/no_cache_no_error_on_existing_local_user deleted file mode 100644 index af91e8da..00000000 --- a/nss/integration_tests/testdata/golden/TestNssGetPasswdByUID/no_cache_no_error_on_existing_local_user +++ /dev/null @@ -1,2 +0,0 @@ -| - root:x:0:0:root:/root:/bin/bash diff --git a/nss/integration_tests/util_c.go b/nss/integration_tests/util_c.go deleted file mode 100644 index 992210ab..00000000 --- a/nss/integration_tests/util_c.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -/* -#include -#include - -typedef enum nss_status nss_status; -*/ -import "C" -import ( - "context" - "errors" - - "github.com/ubuntu/aad-auth/internal/logger" - "github.com/ubuntu/aad-auth/internal/nss" -) - -// errToCStatus converts our Go errors to corresponding nss status returned code and errno. -// If err is nil, it returns a success. -func errToCStatus(ctx context.Context, err error, errnop *C.int) C.nss_status { - var nssStatus C.nss_status = C.NSS_STATUS_SUCCESS - var errno int - - switch { - case errors.Is(err, nss.ErrTryAgainEAgain): - nssStatus = C.NSS_STATUS_TRYAGAIN - errno = C.EAGAIN - case errors.Is(err, nss.ErrTryAgainERange): - nssStatus = C.NSS_STATUS_TRYAGAIN - errno = C.ERANGE - case errors.Is(err, nss.ErrUnavailableENoEnt): - nssStatus = C.NSS_STATUS_UNAVAIL - errno = C.ENOENT - case errors.Is(err, nss.ErrNotFoundENoEnt): - nssStatus = C.NSS_STATUS_NOTFOUND - errno = C.ENOENT - case errors.Is(err, nss.ErrNotFoundSuccess): - nssStatus = C.NSS_STATUS_SUCCESS - errno = C.ENOENT - case err != nil: // Unexpected returned error - nssStatus = C.NSS_STATUS_SUCCESS - errno = C.EINVAL - } - - if err != nil { - logger.Debug(ctx, "%v", err) - } - - if errnop != nil { - *errnop = C.int(errno) - logger.Debug(ctx, "Returning to NSS error: %d with errno: %d", nssStatus, errno) - } else { - logger.Debug(ctx, "Returning to NSS error: %d", nssStatus) - } - - return nssStatus -}