github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/privilege_test.go (about)

     1  // Copyright 2015 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sqlbase
    12  
    13  import (
    14  	"testing"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/security"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    19  	"github.com/cockroachdb/cockroach/pkg/testutils"
    20  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    21  )
    22  
    23  func TestPrivilege(t *testing.T) {
    24  	defer leaktest.AfterTest(t)()
    25  	descriptor := NewDefaultPrivilegeDescriptor()
    26  
    27  	testCases := []struct {
    28  		grantee       string // User to grant/revoke privileges on.
    29  		grant, revoke privilege.List
    30  		show          []UserPrivilegeString
    31  	}{
    32  		{"", nil, nil,
    33  			[]UserPrivilegeString{
    34  				{AdminRole, []string{"ALL"}},
    35  				{security.RootUser, []string{"ALL"}},
    36  			},
    37  		},
    38  		{security.RootUser, privilege.List{privilege.ALL}, nil,
    39  			[]UserPrivilegeString{
    40  				{AdminRole, []string{"ALL"}},
    41  				{security.RootUser, []string{"ALL"}},
    42  			},
    43  		},
    44  		{security.RootUser, privilege.List{privilege.INSERT, privilege.DROP}, nil,
    45  			[]UserPrivilegeString{
    46  				{AdminRole, []string{"ALL"}},
    47  				{security.RootUser, []string{"ALL"}},
    48  			},
    49  		},
    50  		{"foo", privilege.List{privilege.INSERT, privilege.DROP}, nil,
    51  			[]UserPrivilegeString{
    52  				{AdminRole, []string{"ALL"}},
    53  				{"foo", []string{"DROP", "INSERT"}},
    54  				{security.RootUser, []string{"ALL"}},
    55  			},
    56  		},
    57  		{"bar", nil, privilege.List{privilege.INSERT, privilege.ALL},
    58  			[]UserPrivilegeString{
    59  				{AdminRole, []string{"ALL"}},
    60  				{"foo", []string{"DROP", "INSERT"}},
    61  				{security.RootUser, []string{"ALL"}},
    62  			},
    63  		},
    64  		{"foo", privilege.List{privilege.ALL}, nil,
    65  			[]UserPrivilegeString{
    66  				{AdminRole, []string{"ALL"}},
    67  				{"foo", []string{"ALL"}},
    68  				{security.RootUser, []string{"ALL"}},
    69  			},
    70  		},
    71  		{"foo", nil, privilege.List{privilege.SELECT, privilege.INSERT},
    72  			[]UserPrivilegeString{
    73  				{AdminRole, []string{"ALL"}},
    74  				{"foo", []string{"CREATE", "DELETE", "DROP", "GRANT", "UPDATE", "ZONECONFIG"}},
    75  				{security.RootUser, []string{"ALL"}},
    76  			},
    77  		},
    78  		{"foo", nil, privilege.List{privilege.ALL},
    79  			[]UserPrivilegeString{
    80  				{AdminRole, []string{"ALL"}},
    81  				{security.RootUser, []string{"ALL"}},
    82  			},
    83  		},
    84  		// Validate checks that root still has ALL privileges, but we do not call it here.
    85  		{security.RootUser, nil, privilege.List{privilege.ALL},
    86  			[]UserPrivilegeString{
    87  				{AdminRole, []string{"ALL"}},
    88  			},
    89  		},
    90  	}
    91  
    92  	for tcNum, tc := range testCases {
    93  		if tc.grantee != "" {
    94  			if tc.grant != nil {
    95  				descriptor.Grant(tc.grantee, tc.grant)
    96  			}
    97  			if tc.revoke != nil {
    98  				descriptor.Revoke(tc.grantee, tc.revoke)
    99  			}
   100  		}
   101  		show := descriptor.Show()
   102  		if len(show) != len(tc.show) {
   103  			t.Fatalf("#%d: show output for descriptor %+v differs, got: %+v, expected %+v",
   104  				tcNum, descriptor, show, tc.show)
   105  		}
   106  		for i := 0; i < len(show); i++ {
   107  			if show[i].User != tc.show[i].User || show[i].PrivilegeString() != tc.show[i].PrivilegeString() {
   108  				t.Fatalf("#%d: show output for descriptor %+v differs, got: %+v, expected %+v",
   109  					tcNum, descriptor, show, tc.show)
   110  			}
   111  		}
   112  	}
   113  }
   114  
   115  func TestCheckPrivilege(t *testing.T) {
   116  	defer leaktest.AfterTest(t)()
   117  
   118  	testCases := []struct {
   119  		pd   *PrivilegeDescriptor
   120  		user string
   121  		priv privilege.Kind
   122  		exp  bool
   123  	}{
   124  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   125  			"foo", privilege.CREATE, true},
   126  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   127  			"bar", privilege.CREATE, false},
   128  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   129  			"bar", privilege.DROP, false},
   130  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   131  			"foo", privilege.DROP, false},
   132  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.ALL}),
   133  			"foo", privilege.CREATE, true},
   134  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   135  			"foo", privilege.ALL, false},
   136  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.ALL}),
   137  			"foo", privilege.ALL, true},
   138  		{NewPrivilegeDescriptor("foo", privilege.List{}),
   139  			"foo", privilege.ALL, false},
   140  		{NewPrivilegeDescriptor("foo", privilege.List{}),
   141  			"foo", privilege.CREATE, false},
   142  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE, privilege.DROP}),
   143  			"foo", privilege.UPDATE, false},
   144  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE, privilege.DROP}),
   145  			"foo", privilege.DROP, true},
   146  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE, privilege.ALL}),
   147  			"foo", privilege.DROP, true},
   148  	}
   149  
   150  	for tcNum, tc := range testCases {
   151  		if found := tc.pd.CheckPrivilege(tc.user, tc.priv); found != tc.exp {
   152  			t.Errorf("#%d: CheckPrivilege(%s, %v) for descriptor %+v = %t, expected %t",
   153  				tcNum, tc.user, tc.priv, tc.pd, found, tc.exp)
   154  		}
   155  	}
   156  }
   157  
   158  func TestAnyPrivilege(t *testing.T) {
   159  	defer leaktest.AfterTest(t)()
   160  
   161  	testCases := []struct {
   162  		pd   *PrivilegeDescriptor
   163  		user string
   164  		exp  bool
   165  	}{
   166  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   167  			"foo", true},
   168  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE}),
   169  			"bar", false},
   170  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.ALL}),
   171  			"foo", true},
   172  		{NewPrivilegeDescriptor("foo", privilege.List{}),
   173  			"foo", false},
   174  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE, privilege.DROP}),
   175  			"foo", true},
   176  		{NewPrivilegeDescriptor("foo", privilege.List{privilege.CREATE, privilege.DROP}),
   177  			"bar", false},
   178  	}
   179  
   180  	for tcNum, tc := range testCases {
   181  		if found := tc.pd.AnyPrivilege(tc.user); found != tc.exp {
   182  			t.Errorf("#%d: AnyPrivilege(%s) for descriptor %+v = %t, expected %t",
   183  				tcNum, tc.user, tc.pd, found, tc.exp)
   184  		}
   185  	}
   186  }
   187  
   188  // TestPrivilegeValidate exercises validation for non-system descriptors.
   189  func TestPrivilegeValidate(t *testing.T) {
   190  	defer leaktest.AfterTest(t)()
   191  	id := ID(keys.MinUserDescID)
   192  	descriptor := NewDefaultPrivilegeDescriptor()
   193  	if err := descriptor.Validate(id); err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	descriptor.Grant("foo", privilege.List{privilege.ALL})
   197  	if err := descriptor.Validate(id); err != nil {
   198  		t.Fatal(err)
   199  	}
   200  	descriptor.Grant(security.RootUser, privilege.List{privilege.SELECT})
   201  	if err := descriptor.Validate(id); err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	descriptor.Revoke(security.RootUser, privilege.List{privilege.SELECT})
   205  	if err := descriptor.Validate(id); err == nil {
   206  		t.Fatal("unexpected success")
   207  	}
   208  	// TODO(marc): validate fails here because we do not aggregate
   209  	// privileges into ALL when all are set.
   210  	descriptor.Grant(security.RootUser, privilege.List{privilege.SELECT})
   211  	if err := descriptor.Validate(id); err == nil {
   212  		t.Fatal("unexpected success")
   213  	}
   214  	descriptor.Revoke(security.RootUser, privilege.List{privilege.ALL})
   215  	if err := descriptor.Validate(id); err == nil {
   216  		t.Fatal("unexpected success")
   217  	}
   218  }
   219  
   220  // TestSystemPrivilegeValidate exercises validation for system config
   221  // descriptors. We use a dummy system table installed for testing
   222  // purposes.
   223  func TestSystemPrivilegeValidate(t *testing.T) {
   224  	defer leaktest.AfterTest(t)()
   225  
   226  	id := ID(keys.MaxReservedDescID)
   227  	if _, exists := SystemAllowedPrivileges[id]; exists {
   228  		t.Fatalf("system object with maximum id %d already exists--is the reserved id space full?", id)
   229  	}
   230  	SystemAllowedPrivileges[id] = privilege.List{
   231  		privilege.SELECT,
   232  		privilege.GRANT,
   233  	}
   234  	defer delete(SystemAllowedPrivileges, id)
   235  
   236  	rootWrongPrivilegesErr := "user root must have exactly SELECT, GRANT " +
   237  		"privileges on system object with ID=.*"
   238  	adminWrongPrivilegesErr := "user admin must have exactly SELECT, GRANT " +
   239  		"privileges on system object with ID=.*"
   240  
   241  	{
   242  		// Valid: root user has one of the allowable privilege sets.
   243  		descriptor := NewCustomSuperuserPrivilegeDescriptor(
   244  			privilege.List{privilege.SELECT, privilege.GRANT},
   245  		)
   246  		if err := descriptor.Validate(id); err != nil {
   247  			t.Fatal(err)
   248  		}
   249  
   250  		// Valid: foo has a subset of the allowed privileges.
   251  		descriptor.Grant("foo", privilege.List{privilege.SELECT})
   252  		if err := descriptor.Validate(id); err != nil {
   253  			t.Fatal(err)
   254  		}
   255  
   256  		// Valid: foo has exactly the allowed privileges.
   257  		descriptor.Grant("foo", privilege.List{privilege.GRANT})
   258  		if err := descriptor.Validate(id); err != nil {
   259  			t.Fatal(err)
   260  		}
   261  	}
   262  
   263  	{
   264  		// Valid: root has exactly the allowed privileges.
   265  		descriptor := NewCustomSuperuserPrivilegeDescriptor(
   266  			privilege.List{privilege.SELECT, privilege.GRANT},
   267  		)
   268  
   269  		// Valid: foo has a subset of the allowed privileges.
   270  		descriptor.Grant("foo", privilege.List{privilege.GRANT})
   271  		if err := descriptor.Validate(id); err != nil {
   272  			t.Fatal(err)
   273  		}
   274  
   275  		// Valid: foo can have privileges revoked, including privileges it doesn't currently have.
   276  		descriptor.Revoke("foo", privilege.List{privilege.GRANT, privilege.UPDATE, privilege.ALL})
   277  		if err := descriptor.Validate(id); err != nil {
   278  			t.Fatal(err)
   279  		}
   280  
   281  		// Invalid: root user has too many privileges.
   282  		descriptor.Grant(security.RootUser, privilege.List{privilege.UPDATE})
   283  		if err := descriptor.Validate(id); !testutils.IsError(err, rootWrongPrivilegesErr) {
   284  			t.Fatalf("expected err=%s, got err=%v", rootWrongPrivilegesErr, err)
   285  		}
   286  	}
   287  
   288  	{
   289  		// Invalid: root has a non-allowable privilege set.
   290  		descriptor := NewCustomSuperuserPrivilegeDescriptor(privilege.List{privilege.UPDATE})
   291  		if err := descriptor.Validate(id); !testutils.IsError(err, rootWrongPrivilegesErr) {
   292  			t.Fatalf("expected err=%s, got err=%v", rootWrongPrivilegesErr, err)
   293  		}
   294  
   295  		// Invalid: root's invalid privileges are revoked and replaced with allowable privileges,
   296  		// but admin is still wrong.
   297  		descriptor.Revoke(security.RootUser, privilege.List{privilege.UPDATE})
   298  		descriptor.Grant(security.RootUser, privilege.List{privilege.SELECT, privilege.GRANT})
   299  		if err := descriptor.Validate(id); !testutils.IsError(err, adminWrongPrivilegesErr) {
   300  			t.Fatalf("expected err=%s, got err=%v", adminWrongPrivilegesErr, err)
   301  		}
   302  
   303  		// Valid: admin's invalid privileges are revoked and replaced with allowable privileges.
   304  		descriptor.Revoke(AdminRole, privilege.List{privilege.UPDATE})
   305  		descriptor.Grant(AdminRole, privilege.List{privilege.SELECT, privilege.GRANT})
   306  		if err := descriptor.Validate(id); err != nil {
   307  			t.Fatal(err)
   308  		}
   309  
   310  		// Valid: foo has less privileges than root.
   311  		descriptor.Grant("foo", privilege.List{privilege.GRANT})
   312  		if err := descriptor.Validate(id); err != nil {
   313  			t.Fatal(err)
   314  		}
   315  	}
   316  }
   317  
   318  func TestFixPrivileges(t *testing.T) {
   319  	defer leaktest.AfterTest(t)()
   320  
   321  	// Use a non-system ID.
   322  	userID := ID(keys.MinUserDescID)
   323  	userPrivs := privilege.List{privilege.ALL}
   324  
   325  	// And create an entry for a fake system table.
   326  	systemID := ID(keys.MaxReservedDescID)
   327  	if _, exists := SystemAllowedPrivileges[systemID]; exists {
   328  		t.Fatalf("system object with maximum id %d already exists--is the reserved id space full?", systemID)
   329  	}
   330  	systemPrivs := privilege.List{
   331  		privilege.SELECT,
   332  		privilege.GRANT,
   333  	}
   334  	SystemAllowedPrivileges[systemID] = systemPrivs
   335  	defer delete(SystemAllowedPrivileges, systemID)
   336  
   337  	type userPrivileges map[string]privilege.List
   338  
   339  	testCases := []struct {
   340  		id       ID
   341  		input    userPrivileges
   342  		modified bool
   343  		output   userPrivileges
   344  	}{
   345  		{
   346  			// Empty privileges for system ID.
   347  			systemID,
   348  			userPrivileges{},
   349  			true,
   350  			userPrivileges{
   351  				security.RootUser: systemPrivs,
   352  				AdminRole:         systemPrivs,
   353  			},
   354  		},
   355  		{
   356  			// Valid requirements for system ID.
   357  			systemID,
   358  			userPrivileges{
   359  				security.RootUser: systemPrivs,
   360  				AdminRole:         systemPrivs,
   361  				"foo":             privilege.List{privilege.SELECT},
   362  				"bar":             privilege.List{privilege.GRANT},
   363  				"baz":             privilege.List{privilege.SELECT, privilege.GRANT},
   364  			},
   365  			false,
   366  			userPrivileges{
   367  				security.RootUser: systemPrivs,
   368  				AdminRole:         systemPrivs,
   369  				"foo":             privilege.List{privilege.SELECT},
   370  				"bar":             privilege.List{privilege.GRANT},
   371  				"baz":             privilege.List{privilege.SELECT, privilege.GRANT},
   372  			},
   373  		},
   374  		{
   375  			// Too many privileges for system ID.
   376  			systemID,
   377  			userPrivileges{
   378  				security.RootUser: privilege.List{privilege.ALL},
   379  				AdminRole:         privilege.List{privilege.ALL},
   380  				"foo":             privilege.List{privilege.ALL},
   381  				"bar":             privilege.List{privilege.SELECT, privilege.UPDATE},
   382  			},
   383  			true,
   384  			userPrivileges{
   385  				security.RootUser: systemPrivs,
   386  				AdminRole:         systemPrivs,
   387  				"foo":             privilege.List{},
   388  				"bar":             privilege.List{privilege.SELECT},
   389  			},
   390  		},
   391  		{
   392  			// Empty privileges for non-system ID.
   393  			userID,
   394  			userPrivileges{},
   395  			true,
   396  			userPrivileges{
   397  				security.RootUser: userPrivs,
   398  				AdminRole:         userPrivs,
   399  			},
   400  		},
   401  		{
   402  			// Valid requirements for non-system ID.
   403  			userID,
   404  			userPrivileges{
   405  				security.RootUser: userPrivs,
   406  				AdminRole:         userPrivs,
   407  				"foo":             privilege.List{privilege.SELECT},
   408  				"bar":             privilege.List{privilege.GRANT},
   409  				"baz":             privilege.List{privilege.SELECT, privilege.GRANT},
   410  			},
   411  			false,
   412  			userPrivileges{
   413  				security.RootUser: userPrivs,
   414  				AdminRole:         userPrivs,
   415  				"foo":             privilege.List{privilege.SELECT},
   416  				"bar":             privilege.List{privilege.GRANT},
   417  				"baz":             privilege.List{privilege.SELECT, privilege.GRANT},
   418  			},
   419  		},
   420  		{
   421  			// All privileges are allowed for non-system ID, but we need super users.
   422  			userID,
   423  			userPrivileges{
   424  				"foo": privilege.List{privilege.ALL},
   425  				"bar": privilege.List{privilege.UPDATE},
   426  			},
   427  			true,
   428  			userPrivileges{
   429  				security.RootUser: privilege.List{privilege.ALL},
   430  				AdminRole:         privilege.List{privilege.ALL},
   431  				"foo":             privilege.List{privilege.ALL},
   432  				"bar":             privilege.List{privilege.UPDATE},
   433  			},
   434  		},
   435  	}
   436  
   437  	for num, testCase := range testCases {
   438  		desc := &PrivilegeDescriptor{}
   439  		for u, p := range testCase.input {
   440  			desc.Grant(u, p)
   441  		}
   442  
   443  		if a, e := desc.MaybeFixPrivileges(testCase.id), testCase.modified; a != e {
   444  			t.Errorf("#%d: expected modified=%t, got modified=%t", num, e, a)
   445  			continue
   446  		}
   447  
   448  		if a, e := len(desc.Users), len(testCase.output); a != e {
   449  			t.Errorf("#%d: expected %d users (%v), got %d (%v)", num, e, testCase.output, a, desc.Users)
   450  			continue
   451  		}
   452  
   453  		for u, p := range testCase.output {
   454  			outputUser, ok := desc.findUser(u)
   455  			if !ok {
   456  				t.Fatalf("#%d: expected user %s in output, but not found (%v)", num, u, desc.Users)
   457  			}
   458  			if a, e := privilege.ListFromBitField(outputUser.Privileges), p; a.ToBitField() != e.ToBitField() {
   459  				t.Errorf("#%d: user %s: expected privileges %v, got %v", num, u, e, a)
   460  			}
   461  		}
   462  	}
   463  }