func()

in pkg/providers/vsphere/validator.go [455:564]


func (v *Validator) validateUserPrivs(ctx context.Context, spec *Spec, vuc *config.VSphereUserConfig) (bool, error) {
	resourcePaths, err := v.collectResourcePathConfig(ctx, spec)
	if err != nil {
		return false, err
	}

	requiredPrivAssociations := []PrivAssociation{
		// validate global root priv settings are correct
		{
			objectType:   govmomi.VSphereTypeFolder,
			privsContent: config.VSphereGlobalPrivsFile,
			path:         vsphereRootPath,
		},
		{
			objectType:   govmomi.VSphereTypeNetwork,
			privsContent: config.VSphereUserPrivsFile,
			path:         spec.VSphereDatacenter.Spec.Network,
		},
	}

	seen := map[string]interface{}{}
	for _, mc := range resourcePaths {
		datastore := mc.ResourcePaths()["datastore"]
		if _, ok := seen[datastore]; !ok {
			requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
				objectType:   govmomi.VSphereTypeDatastore,
				privsContent: config.VSphereUserPrivsFile,
				path:         datastore,
			},
			)
			seen[datastore] = 1
		}
		resourcePool := mc.ResourcePaths()["resourcePool"]
		if _, ok := seen[resourcePool]; !ok {
			requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
				objectType:   govmomi.VSphereTypeResourcePool,
				privsContent: config.VSphereUserPrivsFile,
				path:         resourcePool,
			})
			seen[resourcePool] = 1
		}
		folder := mc.ResourcePaths()["folder"]
		if _, ok := seen[folder]; !ok {
			requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
				objectType:   govmomi.VSphereTypeFolder,
				privsContent: config.VSphereAdminPrivsFile,
				path:         folder,
			})
			seen[folder] = 1
		}

		switch v := mc.(type) {
		case *anywherev1.FailureDomain:
			computecluster := v.ResourcePaths()["computeCluster"]
			if _, ok := seen[computecluster]; !ok {
				requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
					objectType:   govmomi.VSphereTypeComputeCluster,
					privsContent: config.VSphereAdminPrivsFile,
					path:         computecluster,
				})
				seen[computecluster] = 1
			}

		case *anywherev1.VSphereMachineConfig:
			template := v.ResourcePaths()["template"]
			if _, ok := seen[template]; !ok {
				// ToDo: add more sophisticated validation around a scenario where someone has uploaded templates
				// on their own and does not want to allow EKSA user write access to templates
				// Verify privs on the template
				requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
					objectType:   govmomi.VSphereTypeVirtualMachine,
					privsContent: config.VSphereAdminPrivsFile,
					path:         template,
				})
				seen[template] = 1
			}

			if _, ok := seen[filepath.Dir(template)]; !ok {
				requiredPrivAssociations = append(requiredPrivAssociations, PrivAssociation{
					objectType:   govmomi.VSphereTypeFolder,
					privsContent: config.VSphereAdminPrivsFile,
					path:         filepath.Dir(template),
				})

				seen[filepath.Dir(template)] = 1
			}

		default:
			return false, errors.New("unexpected type in missing validateUserPrivs")
		}

	}

	host := spec.VSphereDatacenter.Spec.Server
	datacenter := spec.VSphereDatacenter.Spec.Datacenter

	vsc, err := v.vSphereClientBuilder.Build(
		ctx,
		host,
		vuc.EksaVsphereUsername,
		vuc.EksaVspherePassword,
		spec.VSphereDatacenter.Spec.Insecure,
		datacenter,
	)
	if err != nil {
		return false, err
	}

	return v.validatePrivs(ctx, requiredPrivAssociations, vsc)
}