github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/test/test_idm.go (about)

     1  //
     2  //  Copyright 2020 The AVFS authors
     3  //
     4  //  Licensed under the Apache License, Version 2.0 (the "License");
     5  //  you may not use this file except in compliance with the License.
     6  //  You may obtain a copy of the License at
     7  //
     8  //  	http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  //  Unless required by applicable law or agreed to in writing, software
    11  //  distributed under the License is distributed on an "AS IS" BASIS,
    12  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  //  See the License for the specific language governing permissions and
    14  //  limitations under the License.
    15  //
    16  
    17  package test
    18  
    19  import (
    20  	"fmt"
    21  	"io/fs"
    22  	"math"
    23  	"math/rand"
    24  	"testing"
    25  
    26  	"github.com/avfs/avfs"
    27  )
    28  
    29  // TestIdmAll runs all identity manager tests.
    30  func (ts *Suite) TestIdmAll(t *testing.T) {
    31  	defer ts.setInitUser(t)
    32  
    33  	ts.TestAdminGroupUser(t)
    34  	ts.TestGroupAddDel(t)
    35  	ts.TestUserAddDel(t)
    36  	ts.TestLookup(t)
    37  }
    38  
    39  // TestAdminGroupUser tests AdminGroup and AdminUser.
    40  func (ts *Suite) TestAdminGroupUser(t *testing.T) {
    41  	idm := ts.idm
    42  
    43  	if !idm.HasFeature(avfs.FeatIdentityMgr) {
    44  		wantGroup, wantUser := avfs.DefaultName, avfs.DefaultName
    45  
    46  		ag := idm.AdminGroup()
    47  		if ag.Name() != wantGroup {
    48  			t.Errorf("AdminGroup : want name to be %s, got %s", wantGroup, ag.Name())
    49  		}
    50  
    51  		if ag.Gid() != math.MaxInt {
    52  			t.Errorf("AdminGroup : want Gid to be %d, got %d", math.MaxInt, ag.Gid())
    53  		}
    54  
    55  		au := idm.AdminUser()
    56  		if au.Name() != wantUser {
    57  			t.Errorf("AdminUser : want name to be %s, got %s", wantUser, au.Name())
    58  		}
    59  
    60  		if au.Uid() != math.MaxInt {
    61  			t.Errorf("AdminUser : want Uid to be %d, got %d", math.MaxInt, au.Uid())
    62  		}
    63  
    64  		if au.Gid() != math.MaxInt {
    65  			t.Errorf("AdminUser : want Gid to be %d, got %d", math.MaxInt, au.Gid())
    66  		}
    67  
    68  		if au.IsAdmin() {
    69  			t.Errorf("AdminUser : want IsAdmin to be false, got true")
    70  		}
    71  
    72  		return
    73  	}
    74  
    75  	t.Run("Admin", func(t *testing.T) {
    76  		wantGroupName := avfs.AdminGroupName(avfs.CurrentOSType())
    77  		ag := idm.AdminGroup()
    78  
    79  		if ag.Name() != wantGroupName {
    80  			t.Errorf("AdminGroup : want name to be %s, got %s", wantGroupName, ag.Name())
    81  		}
    82  
    83  		wantUserName := avfs.AdminUserName(avfs.CurrentOSType())
    84  		au := idm.AdminUser()
    85  
    86  		if au.Name() != wantUserName {
    87  			t.Errorf("AdminUser : want name to be %s, got %s", wantUserName, au.Name())
    88  		}
    89  	})
    90  }
    91  
    92  // TestGroupAddDel tests GroupAdd and GroupDel functions.
    93  func (ts *Suite) TestGroupAddDel(t *testing.T) {
    94  	idm := ts.idm
    95  	suffix := fmt.Sprintf("GroupAddDel%x", rand.Uint32())
    96  
    97  	if !idm.HasFeature(avfs.FeatIdentityMgr) || idm.HasFeature(avfs.FeatReadOnlyIdm) {
    98  		groupName := "AGroup" + suffix
    99  
   100  		_, err := idm.GroupAdd(groupName)
   101  		if err != avfs.ErrPermDenied {
   102  			t.Errorf("GroupAdd : want error to be %v, got %v", avfs.ErrPermDenied, err)
   103  		}
   104  
   105  		err = idm.GroupDel(groupName)
   106  		if err != avfs.ErrPermDenied {
   107  			t.Errorf("GroupDel : want error to be %v, got %v", avfs.ErrPermDenied, err)
   108  		}
   109  
   110  		return
   111  	}
   112  
   113  	gis := GroupInfos()
   114  	prevGid := 0
   115  
   116  	t.Run("GroupAdd", func(t *testing.T) {
   117  		for _, gi := range gis {
   118  			groupName := gi.Name + suffix
   119  			wantGroupErr := avfs.UnknownGroupError(groupName)
   120  
   121  			_, err := idm.LookupGroup(groupName)
   122  			if err != wantGroupErr {
   123  				t.Errorf("LookupGroupName %s : want error to be %v, got %v", groupName, wantGroupErr, err)
   124  			}
   125  
   126  			g, err := idm.GroupAdd(groupName)
   127  			if !AssertNoError(t, err, "GroupAdd %s", groupName) {
   128  				continue
   129  			}
   130  
   131  			if g.Name() != groupName {
   132  				t.Errorf("GroupAdd %s : want Name to be %s, got %s", groupName, groupName, g.Name())
   133  			}
   134  
   135  			if g.Gid() <= prevGid {
   136  				t.Errorf("GroupAdd %s : want gid to be > %d, got %d", groupName, prevGid, g.Gid())
   137  			} else {
   138  				prevGid = g.Gid()
   139  			}
   140  
   141  			_, err = idm.LookupGroup(groupName)
   142  			RequireNoError(t, err, "LookupGroup %s", groupName)
   143  
   144  			_, err = idm.LookupGroupId(g.Gid())
   145  			RequireNoError(t, err, "LookupGroupId %s", groupName)
   146  		}
   147  	})
   148  
   149  	t.Run("GroupAddExists", func(t *testing.T) {
   150  		for _, gi := range gis {
   151  			groupName := gi.Name + suffix
   152  
   153  			_, err := idm.GroupAdd(groupName)
   154  			if err != avfs.AlreadyExistsGroupError(groupName) {
   155  				t.Errorf("GroupAdd %s : want error to be %v, got %v",
   156  					groupName, avfs.AlreadyExistsGroupError(groupName), err)
   157  			}
   158  		}
   159  	})
   160  
   161  	t.Run("GroupDel", func(t *testing.T) {
   162  		for _, gi := range gis {
   163  			groupName := gi.Name + suffix
   164  
   165  			g, err := idm.LookupGroup(groupName)
   166  			RequireNoError(t, err, "LookupGroup %s", groupName)
   167  
   168  			err = idm.GroupDel(groupName)
   169  			RequireNoError(t, err, "GroupDel %s", groupName)
   170  
   171  			_, err = idm.LookupGroup(g.Name())
   172  			wantGroupErr := avfs.UnknownGroupError(groupName)
   173  
   174  			if err != wantGroupErr {
   175  				t.Errorf("LookupGroup %s : want error to be %v, got %v", groupName, wantGroupErr, err)
   176  			}
   177  
   178  			_, err = idm.LookupGroupId(g.Gid())
   179  			wantGroupIdErr := avfs.UnknownGroupIdError(g.Gid())
   180  
   181  			if err != wantGroupIdErr {
   182  				t.Errorf("LookupGroupId %s : want error to be %v, got %v", groupName, wantGroupIdErr, err)
   183  			}
   184  
   185  			err = idm.GroupDel(groupName)
   186  			if err != wantGroupErr {
   187  				t.Errorf("GroupDel %s : want error to be %v, got %v", groupName, wantGroupErr, err)
   188  			}
   189  		}
   190  	})
   191  }
   192  
   193  // TestUserAddDel tests UserAdd and UserDel functions.
   194  func (ts *Suite) TestUserAddDel(t *testing.T) {
   195  	idm := ts.idm
   196  	suffix := fmt.Sprintf("UserAddDel%x", rand.Uint32())
   197  
   198  	if !idm.HasFeature(avfs.FeatIdentityMgr) || idm.HasFeature(avfs.FeatReadOnlyIdm) {
   199  		groupName := "InvalidGroup" + suffix
   200  		userName := "InvalidUser" + suffix
   201  
   202  		_, err := idm.UserAdd(userName, groupName)
   203  		if err != avfs.ErrPermDenied {
   204  			t.Errorf("UserAdd : want error to be %v, got %v", avfs.ErrPermDenied, err)
   205  		}
   206  
   207  		err = idm.UserDel(userName)
   208  		if err != avfs.ErrPermDenied {
   209  			t.Errorf("UserDel : want error to be %v, got %v", avfs.ErrPermDenied, err)
   210  		}
   211  
   212  		return
   213  	}
   214  
   215  	ts.CreateGroups(t, suffix)
   216  
   217  	prevUid := 0
   218  	uis := UserInfos()
   219  
   220  	t.Run("UserAdd", func(t *testing.T) {
   221  		for _, ui := range uis {
   222  			groupName := ui.GroupName + suffix
   223  
   224  			g, err := idm.LookupGroup(groupName)
   225  			RequireNoError(t, err, "LookupGroup %s", groupName)
   226  
   227  			userName := ui.Name + suffix
   228  			wantUserErr := avfs.UnknownUserError(userName)
   229  
   230  			_, err = idm.LookupUser(userName)
   231  			if err != wantUserErr {
   232  				t.Errorf("LookupUser %s : want error to be %v, got %v", userName, wantUserErr, err)
   233  			}
   234  
   235  			u, err := idm.UserAdd(userName, groupName)
   236  			RequireNoError(t, err, "UserAdd %s", userName)
   237  
   238  			if u == nil {
   239  				t.Errorf("UserAdd %s : want user to be not nil, got nil", userName)
   240  
   241  				continue
   242  			}
   243  
   244  			if u.Name() != userName {
   245  				t.Errorf("UserAdd %s : want Name to be %s, got %s", userName, userName, u.Name())
   246  			}
   247  
   248  			if u.Uid() <= prevUid {
   249  				t.Errorf("UserAdd %s : want uid to be > %d, got %d", userName, prevUid, u.Uid())
   250  			} else {
   251  				prevUid = u.Uid()
   252  			}
   253  
   254  			if u.Gid() != g.Gid() {
   255  				t.Errorf("UserAdd %s : want gid to be %d, got %d", userName, g.Gid(), u.Gid())
   256  			}
   257  
   258  			if u.IsAdmin() {
   259  				t.Errorf("IsAdmin %s : want IsAdmin to be false, got true", userName)
   260  			}
   261  
   262  			_, err = idm.LookupUser(userName)
   263  			RequireNoError(t, err, "LookupUser %s", userName)
   264  
   265  			_, err = idm.LookupUserId(u.Uid())
   266  			RequireNoError(t, err, "LookupUserId %s", userName)
   267  		}
   268  	})
   269  
   270  	t.Run("UserAddDelErrors", func(t *testing.T) {
   271  		for _, ui := range uis {
   272  			groupName := ui.GroupName + suffix
   273  			userName := ui.Name + suffix
   274  
   275  			_, err := idm.UserAdd(userName, groupName)
   276  			if err != avfs.AlreadyExistsUserError(userName) {
   277  				t.Errorf("UserAdd %s : want error to be %v, got %v", userName,
   278  					avfs.AlreadyExistsUserError(userName), err)
   279  			}
   280  
   281  			groupNameNotFound := ui.GroupName + "NotFound"
   282  
   283  			_, err = idm.UserAdd(userName, groupNameNotFound)
   284  			if err != avfs.UnknownGroupError(groupNameNotFound) {
   285  				t.Errorf("UserAdd %s : want error to be %v, got %v", userName,
   286  					avfs.UnknownGroupError(groupNameNotFound), err)
   287  			}
   288  
   289  			userNameNotFound := ui.Name + "NotFound"
   290  
   291  			err = idm.UserDel(userNameNotFound)
   292  			if err != avfs.UnknownUserError(userNameNotFound) {
   293  				t.Errorf("UserDel %s : want error to be %v, got %v", userName,
   294  					avfs.UnknownUserError(userNameNotFound), err)
   295  			}
   296  		}
   297  	})
   298  
   299  	t.Run("UserDel", func(t *testing.T) {
   300  		for _, ui := range uis {
   301  			userName := ui.Name + suffix
   302  
   303  			u, err := idm.LookupUser(userName)
   304  			RequireNoError(t, err, "LookupUser %s", userName)
   305  
   306  			err = idm.UserDel(userName)
   307  			RequireNoError(t, err, "UserDel %s", userName)
   308  
   309  			_, err = idm.LookupUser(u.Name())
   310  			wantUserErr := avfs.UnknownUserError(userName)
   311  
   312  			if err != wantUserErr {
   313  				t.Errorf("LookupUser %s : want error to be %v, got %v", userName, wantUserErr, err)
   314  			}
   315  
   316  			_, err = idm.LookupUserId(u.Uid())
   317  			wantUserIdErr := avfs.UnknownUserIdError(u.Uid())
   318  
   319  			if err != wantUserIdErr {
   320  				t.Errorf("LookupUserId %s : want error to be %v, got %v", userName, wantUserIdErr, err)
   321  			}
   322  		}
   323  	})
   324  }
   325  
   326  // TestLookup tests Lookup* functions.
   327  func (ts *Suite) TestLookup(t *testing.T) {
   328  	idm := ts.idm
   329  	suffix := fmt.Sprintf("Lookup%x", rand.Uint32())
   330  
   331  	if !idm.HasFeature(avfs.FeatIdentityMgr) {
   332  		groupName := "InvalidGroup" + suffix
   333  
   334  		_, err := idm.LookupGroup(groupName)
   335  		if err != avfs.ErrPermDenied {
   336  			t.Errorf("LookupGroup : want error to be %v, got %v", avfs.ErrPermDenied, err)
   337  		}
   338  
   339  		_, err = idm.LookupGroupId(0)
   340  		if err != avfs.ErrPermDenied {
   341  			t.Errorf("LookupGroupId : want error to be %v, got %v", avfs.ErrPermDenied, err)
   342  		}
   343  
   344  		_, err = idm.LookupUser("")
   345  		if err != avfs.ErrPermDenied {
   346  			t.Errorf("LookupUser : want error to be %v, got %v", avfs.ErrPermDenied, err)
   347  		}
   348  
   349  		_, err = idm.LookupUserId(0)
   350  		if err != avfs.ErrPermDenied {
   351  			t.Errorf("LookupUserId : want error to be %v, got %v", avfs.ErrPermDenied, err)
   352  		}
   353  
   354  		return
   355  	}
   356  
   357  	if idm.HasFeature(avfs.FeatReadOnlyIdm) {
   358  		groupName := "InvalidGroup" + suffix
   359  		_, err := idm.LookupGroup(groupName)
   360  
   361  		wantGroupErr := avfs.UnknownGroupError(groupName)
   362  		if err != wantGroupErr {
   363  			t.Errorf("LookupGroup %s : want error to be %v, got %v", groupName, wantGroupErr, err)
   364  		}
   365  	}
   366  
   367  	groups := ts.CreateGroups(t, suffix)
   368  	users := ts.CreateUsers(t, suffix)
   369  
   370  	t.Run("LookupGroup", func(t *testing.T) {
   371  		for _, wantGroup := range groups {
   372  			groupName := wantGroup.Name()
   373  			wantErr := avfs.UnknownGroupError(groupName)
   374  
   375  			g, err := idm.LookupGroup(groupName)
   376  			if idm.HasFeature(avfs.FeatReadOnlyIdm) {
   377  				if err != wantErr {
   378  					t.Errorf("LookupGroup %s : want error to be %v, got %v", groupName, wantErr, err)
   379  				}
   380  
   381  				continue
   382  			}
   383  
   384  			if !AssertNoError(t, err, "LookupGroup %s", groupName) {
   385  				continue
   386  			}
   387  
   388  			if g.Name() != groupName {
   389  				t.Errorf("LookupGroup %s : want name to be %s, got %s", groupName, groupName, g.Name())
   390  			}
   391  
   392  			if g.Gid() != wantGroup.Gid() {
   393  				t.Errorf("LookupGroup %s : want gid to be %d, got %d", groupName, wantGroup.Gid(), g.Gid())
   394  			}
   395  		}
   396  	})
   397  
   398  	t.Run("LookupUser", func(t *testing.T) {
   399  		for _, wantUser := range users {
   400  			userName := wantUser.Name()
   401  			wantErr := avfs.UnknownUserError(userName)
   402  
   403  			u, err := idm.LookupUser(userName)
   404  			if idm.HasFeature(avfs.FeatReadOnlyIdm) {
   405  				if err != wantErr {
   406  					t.Errorf("LookupUser %s : want error to be %v, got %v", userName, wantErr, err)
   407  				}
   408  
   409  				continue
   410  			}
   411  
   412  			if !AssertNoError(t, err, "LookupUser %s", userName) {
   413  				continue
   414  			}
   415  
   416  			if u.Name() != userName {
   417  				t.Errorf("LookupUser %s : want name to be %s, got %s", userName, userName, u.Name())
   418  			}
   419  
   420  			if u.Uid() != wantUser.Uid() {
   421  				t.Errorf("LookupUser %s : want uid to be %d, got %d", userName, wantUser.Uid(), u.Uid())
   422  			}
   423  
   424  			if u.Gid() != wantUser.Gid() {
   425  				t.Errorf("LookupUser %s : want gid to be %d, got %d", userName, wantUser.Gid(), u.Gid())
   426  			}
   427  
   428  			if (u.Uid() != 0 && u.Gid() != 0) && u.IsAdmin() {
   429  				t.Errorf("LookupUser %s : want IsAdmin to be false, got true", userName)
   430  			}
   431  		}
   432  	})
   433  }
   434  
   435  const (
   436  	grpTest  = "grpTest"  // grpTest is the default group of the default test user UsrTest.
   437  	grpOther = "grpOther" // grpOther is the group to test users who are not members of grpTest.
   438  	grpEmpty = "grpEmpty" // grpEmpty is a group without users.
   439  )
   440  
   441  // GroupInfo contains information to create a test group.
   442  type GroupInfo struct {
   443  	Name string
   444  }
   445  
   446  // GroupInfos returns a GroupInfo slice describing the test groups.
   447  func GroupInfos() []*GroupInfo {
   448  	gis := []*GroupInfo{
   449  		{Name: grpTest},
   450  		{Name: grpOther},
   451  		{Name: grpEmpty},
   452  	}
   453  
   454  	return gis
   455  }
   456  
   457  // CreateGroups creates and returns test groups with a suffix appended to each group.
   458  // Errors are ignored if the group already exists.
   459  func (ts *Suite) CreateGroups(tb testing.TB, suffix string) (groups []avfs.GroupReader) {
   460  	idm := ts.idm
   461  	if !idm.HasFeature(avfs.FeatIdentityMgr) || idm.HasFeature(avfs.FeatReadOnlyIdm) {
   462  		return nil
   463  	}
   464  
   465  	for _, group := range GroupInfos() {
   466  		groupName := group.Name + suffix
   467  
   468  		g, err := idm.GroupAdd(groupName)
   469  		if err != avfs.AlreadyExistsGroupError(groupName) {
   470  			RequireNoError(tb, err, "GroupAdd %s", groupName)
   471  		}
   472  
   473  		groups = append(groups, g)
   474  	}
   475  
   476  	return groups
   477  }
   478  
   479  const (
   480  	UsrTest = "UsrTest" // UsrTest is used to test user access rights.
   481  	UsrGrp  = "UsrGrp"  // UsrGrp is a member of the group GrpTest used to test default group access rights.
   482  	UsrOth  = "UsrOth"  // UsrOth is a member of the group GrpOth used to test non-members access rights.
   483  )
   484  
   485  // UserInfo contains information to create a test user.
   486  type UserInfo struct {
   487  	Name      string
   488  	GroupName string
   489  }
   490  
   491  // UserInfos returns a UserInfo slice describing the test users.
   492  func UserInfos() []*UserInfo {
   493  	uis := []*UserInfo{
   494  		{Name: UsrTest, GroupName: grpTest},
   495  		{Name: UsrGrp, GroupName: grpTest},
   496  		{Name: UsrOth, GroupName: grpOther},
   497  	}
   498  
   499  	return uis
   500  }
   501  
   502  // CreateUsers creates and returns test users with a suffix appended to each user.
   503  // Errors are ignored if the user or his home directory already exists.
   504  func (ts *Suite) CreateUsers(tb testing.TB, suffix string) (users []avfs.UserReader) {
   505  	idm := ts.idm
   506  	if !idm.HasFeature(avfs.FeatIdentityMgr) || idm.HasFeature(avfs.FeatReadOnlyIdm) {
   507  		return nil
   508  	}
   509  
   510  	for _, ui := range UserInfos() {
   511  		userName := ui.Name + suffix
   512  		groupName := ui.GroupName + suffix
   513  
   514  		u, err := idm.UserAdd(userName, groupName)
   515  		if err != nil {
   516  			switch e := err.(type) {
   517  			case *fs.PathError:
   518  				if e.Op != "mkdir" || e.Err != avfs.ErrFileExists {
   519  					tb.Fatalf("UserAdd %s : want Mkdir error, got %v", userName, err)
   520  				}
   521  			default:
   522  				if err != avfs.AlreadyExistsUserError(userName) {
   523  					tb.Fatalf("UserAdd %s : want error to be nil, got %v", userName, err)
   524  				}
   525  			}
   526  
   527  			if u == nil {
   528  				u, err = idm.LookupUser(userName)
   529  				RequireNoError(tb, err, "LookupUser %s", userName)
   530  			}
   531  		}
   532  
   533  		users = append(users, u)
   534  	}
   535  
   536  	return users
   537  }