1// Copyright 2016-2018 VMware, Inc. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package rbac 16 17import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/require" 23 24 "github.com/vmware/govmomi/simulator" 25 "github.com/vmware/govmomi/vim25/types" 26 "github.com/vmware/vic/pkg/vsphere/session" 27 "github.com/vmware/vic/pkg/vsphere/test" 28 "github.com/vmware/vic/pkg/vsphere/test/env" 29) 30 31var role1 = types.AuthorizationRole{ 32 Name: "vcenter", 33 Privilege: []string{ 34 "Datastore.Config", 35 }, 36} 37 38var role2 = types.AuthorizationRole{ 39 Name: "datacenter", 40 Privilege: []string{ 41 "Datastore.Config", 42 "Datastore.FileManagement", 43 "VirtualMachine.Config.AddNewDisk", 44 "VirtualMachine.Config.AdvancedConfig", 45 "VirtualMachine.Config.RemoveDisk", 46 "VirtualMachine.Inventory.Create", 47 "VirtualMachine.Inventory.Delete", 48 }, 49} 50 51var role3 = types.AuthorizationRole{ 52 Name: "cluster", 53 Privilege: []string{ 54 "Datastore.AllocateSpace", 55 "Datastore.Browse", 56 "Datastore.Config", 57 "Datastore.DeleteFile", 58 "Datastore.FileManagement", 59 "Host.Config.SystemManagement", 60 }, 61} 62 63var readOnlyRole = types.AuthorizationRole{ 64 Name: "readonly", 65 Privilege: []string{ 66 sysAnonPriv, 67 sysReadPriv, 68 sysViewPriv, 69 }, 70} 71 72var dcReadOnlyConfig = Config{ 73 Resources: []Resource{ 74 { 75 Type: Datacenter, 76 Propagate: true, 77 Role: readOnlyRole, 78 }, 79 }, 80} 81 82// Configuration for the ops-user 83var testRBACConfig = Config{ 84 Resources: []Resource{ 85 { 86 Type: VCenter, 87 Propagate: false, 88 Role: role1, 89 }, 90 { 91 Type: Datacenter, 92 Propagate: true, 93 Role: role2, 94 }, 95 { 96 Type: Cluster, 97 Propagate: true, 98 Role: role3, 99 }, 100 }, 101} 102 103var ( 104 testRolePrefix = "test-role-prefix" 105 testUser = "test-user" 106) 107 108func TestReadPermsOnDC(t *testing.T) { 109 ctx := context.Background() 110 111 // Create the VPX model and server. 112 m := simulator.VPX() 113 defer m.Remove() 114 err := m.Create() 115 require.NoError(t, err, "Cannot create VPX simulator") 116 117 server := m.Service.NewServer() 118 defer server.Close() 119 120 s, err := test.SessionWithVPX(ctx, server.URL.String()) 121 require.NoError(t, err, "Cannot initialize the VPX session") 122 123 // Initialize the AuthzManager. 124 am := NewAuthzManager(ctx, s.Vim25()) 125 am.InitConfig(testUser, testRolePrefix, &dcReadOnlyConfig) 126 127 _, err = am.createOrRepairRoles(ctx) 128 require.NoError(t, err, "Cannot create the read-only role") 129 130 // Test that ReadPermsOnDC returns an error when a non-existent entity ref is supplied. 131 // TODO(anchal): govmomi simulator's RetrieveEntityPermissions func assumes a validated 132 // moref. This test case requires an update to govmomi. 133 // fakeRef := types.ManagedObjectReference{ 134 // Type: "VirtualMachine", 135 // Value: "foo", 136 // } 137 // hasPrivs, err := am.ReadPermsOnDC(ctx, fakeRef) 138 // require.Error(t, err, "Received no error from ReadPermsOnDC") 139 140 // Test that ReadPermsOnDC returns false when no permissions have been set on an object. 141 dcRef := s.Datacenter.Reference() 142 hasPrivs, err := am.ReadPermsOnDC(ctx, dcRef) 143 require.NoError(t, err, "Received unexpected error from ReadPermsOnDC") 144 require.False(t, hasPrivs, "Expected ReadPermsOnDC to return false") 145 146 // Test that ReadPermsOnDC returns false when a subset of read-only privileges is 147 // assigned to an entity. 148 clusterRef := s.Cluster.Reference() 149 clusterPerms := []types.Permission{ 150 { 151 Principal: am.Principal, 152 // RoleId -3 is for the View role, which has only System.Anonymous 153 // and System.View privileges. 154 RoleId: int32(-3), 155 }, 156 } 157 err = am.authzManager.SetEntityPermissions(ctx, clusterRef, clusterPerms) 158 require.NoError(t, err, "Cannot set permissions on cluster ref") 159 160 hasPrivs, err = am.ReadPermsOnDC(ctx, clusterRef) 161 require.NoError(t, err, "Received unexpected error from ReadPermsOnDC") 162 require.False(t, hasPrivs, "Expected ReadPermsOnDC to return false") 163 164 // Test that ReadPermsOnDC returns false when the permissions are assigned to a 165 // user who does not match the ops-user (am.Principal). 166 fakePrincipal := "foo@vsphere.local" 167 dcPerms := []types.Permission{ 168 { 169 Principal: fakePrincipal, 170 RoleId: readOnlyRole.RoleId, 171 }, 172 } 173 err = am.authzManager.SetEntityPermissions(ctx, dcRef, dcPerms) 174 require.NoError(t, err, "Cannot set permissions on dc ref") 175 176 hasPrivs, err = am.ReadPermsOnDC(ctx, dcRef) 177 require.NoError(t, err, "Received unexpected error from ReadPermsOnDC") 178 require.False(t, hasPrivs, "Expected ReadPermsOnDC to return false") 179 180 // Test that ReadPermsOnDC returns true when read-only permissions are assigned to 181 // the ops-user. 182 dcPerms = []types.Permission{ 183 { 184 Principal: am.Principal, 185 RoleId: readOnlyRole.RoleId, 186 }, 187 } 188 err = am.authzManager.SetEntityPermissions(ctx, dcRef, dcPerms) 189 require.NoError(t, err, "Cannot set permissions on dc ref") 190 191 hasPrivs, err = am.ReadPermsOnDC(ctx, dcRef) 192 require.NoError(t, err, "Received unexpected error from ReadPermsOnDC") 193 require.True(t, hasPrivs, "Expected ReadPermsOnDC to return true") 194} 195 196func TestRolesSimulatorVPX(t *testing.T) { 197 ctx := context.Background() 198 m := simulator.VPX() 199 defer m.Remove() 200 201 err := m.Create() 202 require.NoError(t, err, "Cannot create VPX Simulator") 203 204 s := m.Service.NewServer() 205 defer s.Close() 206 207 config := &session.Config{ 208 Service: s.URL.String(), 209 Insecure: true, 210 Keepalive: time.Duration(5) * time.Minute, 211 } 212 213 sess, err := session.NewSession(config).Connect(ctx) 214 require.NoError(t, err, "Cannot connect to VPX Simulator") 215 216 am := NewAuthzManager(ctx, sess.Vim25()) 217 am.InitConfig(testUser, testRolePrefix, &testRBACConfig) 218 219 var testRoleNames = []string{ 220 "datacenter", 221 "cluster", 222 } 223 224 var testRolePrivileges = []string{ 225 "VirtualMachine.Config.AddNewDisk", 226 "Host.Config.SystemManagement", 227 } 228 229 DoTestRoles(ctx, t, am, testRoleNames, testRolePrivileges) 230} 231 232func TestRolesVCenter(t *testing.T) { 233 ctx := context.Background() 234 235 config := &session.Config{ 236 Service: env.URL(t), 237 Insecure: true, 238 Keepalive: time.Duration(5) * time.Minute, 239 } 240 241 sess, err := session.NewSession(config).Connect(ctx) 242 if err != nil { 243 t.SkipNow() 244 } 245 246 am := NewAuthzManager(ctx, sess.Vim25()) 247 am.InitConfig(testUser, testRolePrefix, &testRBACConfig) 248 249 var testRoleNames = []string{ 250 "datacenter", 251 "cluster", 252 } 253 254 var testRolePrivileges = []string{ 255 "VirtualMachine.Config.AddNewDisk", 256 "Host.Config.SystemManagement", 257 } 258 259 DoTestRoles(ctx, t, am, testRoleNames, testRolePrivileges) 260} 261 262func TestAdminSimulatorVPX(t *testing.T) { 263 ctx := context.Background() 264 m := simulator.VPX() 265 defer m.Remove() 266 267 err := m.Create() 268 require.NoError(t, err, "Cannot create VPX Simulator") 269 270 s := m.Service.NewServer() 271 defer s.Close() 272 273 config := &session.Config{ 274 Service: s.URL.String(), 275 Insecure: true, 276 Keepalive: time.Duration(5) * time.Minute, 277 } 278 279 sess, err := session.NewSession(config).Connect(ctx) 280 require.NoError(t, err, "Cannot connect to VPX Simulator") 281 282 am := NewAuthzManager(ctx, sess.Vim25()) 283 am.InitConfig("admin", "test-role-prefix", &testRBACConfig) 284 285 // Unfortunately the Sim does not have support for looking up group membership 286 // therefore we can only test the presence of the Admin role 287 288 res, err := am.PrincipalHasRole(ctx, "Admin") 289 require.NoError(t, err, "Failed to verify Admin Privileges") 290 require.True(t, res, "User Administrator@vsphere.local should have an Admin role") 291 292 // Negative test, principal does not have that role 293 res, err = am.PrincipalHasRole(ctx, "NoAccess") 294 require.NoError(t, err, "Failed to verify Admin Privileges") 295 require.False(t, res, "User Administrator@vsphere.local should have an NoAccess role") 296 297 // Check regular user 298 am.Principal = "nouser@vshpere.local" 299 res, err = am.PrincipalHasRole(ctx, "Admin") 300 require.NoError(t, err, "Failed to verify Admin Privileges") 301 require.False(t, res, "User nouser@vsphere.local should not have an Admin role") 302} 303 304func TestAdminVCenter(t *testing.T) { 305 ctx := context.Background() 306 307 config := &session.Config{ 308 Service: env.URL(t), 309 Insecure: true, 310 Keepalive: time.Duration(5) * time.Minute, 311 } 312 313 sess, err := session.NewSession(config).Connect(ctx) 314 if err != nil { 315 t.SkipNow() 316 } 317 318 am := NewAuthzManager(ctx, sess.Vim25()) 319 am.InitConfig("Administrator@vsphere.local", "test-role-prefix", &testRBACConfig) 320 321 res, err := am.PrincipalBelongsToGroup(ctx, "Administrators") 322 require.NoError(t, err, "Failed to verify Admin Privileges") 323 require.True(t, res, "User Administrator@vsphere.local should be a member of Administrators") 324 325 res, err = am.PrincipalHasRole(ctx, "Admin") 326 require.NoError(t, err, "Failed to verify Admin Privileges") 327 require.True(t, res, "User Administrator@vsphere.local should have an Admin role") 328 329 // Negative test, principal does not belong 330 res, err = am.PrincipalBelongsToGroup(ctx, "TestUsers") 331 require.NoError(t, err, "Failed to verify Admin Privileges") 332 require.False(t, res, "User Administrator@vsphere.local should not be a member of TestUsers") 333 334 // Negative test, principal does not have that role 335 res, err = am.PrincipalHasRole(ctx, "NoAccess") 336 require.NoError(t, err, "Failed to verify Admin Privileges") 337 require.False(t, res, "User Administrator@vsphere.local should have an NoAccess role") 338 339 // Check regular user 340 am.Principal = "nouser@vshpere.local" 341 res, err = am.PrincipalHasRole(ctx, "Admin") 342 require.NoError(t, err, "Failed to verify Admin Privileges") 343 require.False(t, res, "User nouser@vsphere.local should not have an Admin role") 344 345 // Check regular user 346 am.Principal = "nouser" 347 res, err = am.PrincipalHasRole(ctx, "Admin") 348 require.NoError(t, err, "Failed to verify Admin Privileges") 349 require.False(t, res, "User nouser@vsphere.local should not have an Admin role") 350} 351