func writePodVolume(m map[string]interface{}, item *api.Volume) { if x, ok := m["name"].(string); ok { item.Name = x } if n, ok := extractSingleMap(m["host_path"]); ok { item.HostPath = &api.HostPathVolumeSource{} if x, ok := n["path"].(string); ok { item.HostPath.Path = x } } if n, ok := extractSingleMap(m["empty_dir"]); ok { item.EmptyDir = &api.EmptyDirVolumeSource{} if x, ok := n["medium"].(string); ok { item.EmptyDir.Medium = api.StorageMedium(x) } } if n, ok := extractSingleMap(m["gce_persistent_disk"]); ok { item.GCEPersistentDisk = &api.GCEPersistentDiskVolumeSource{} if x, ok := n["pd_name"].(string); ok { item.GCEPersistentDisk.PDName = x } if x, ok := n["fs_type"].(string); ok { item.GCEPersistentDisk.FSType = x } if x, ok := n["partition"].(int); ok { item.GCEPersistentDisk.Partition = x } if x, ok := n["read_only"].(bool); ok { item.GCEPersistentDisk.ReadOnly = x } } if n, ok := extractSingleMap(m["aws_elastic_block_store"]); ok { item.AWSElasticBlockStore = &api.AWSElasticBlockStoreVolumeSource{} if x, ok := n["volume_id"].(string); ok { item.AWSElasticBlockStore.VolumeID = x } if x, ok := n["fs_type"].(string); ok { item.AWSElasticBlockStore.FSType = x } if x, ok := n["partition"].(int); ok { item.AWSElasticBlockStore.Partition = x } if x, ok := n["read_only"].(bool); ok { item.AWSElasticBlockStore.ReadOnly = x } } if n, ok := extractSingleMap(m["git_repo"]); ok { item.GitRepo = &api.GitRepoVolumeSource{} if x, ok := n["repository"].(string); ok { item.GitRepo.Repository = x } if x, ok := n["revision"].(string); ok { item.GitRepo.Revision = x } if x, ok := n["directory"].(string); ok { item.GitRepo.Directory = x } } if n, ok := extractSingleMap(m["secret"]); ok { item.Secret = &api.SecretVolumeSource{} if x, ok := n["secret_name"].(string); ok { item.Secret.SecretName = x } } // TODO: // NFS *NFSVolumeSource // ISCSI *ISCSIVolumeSource // Glusterfs *GlusterfsVolumeSource // PersistentVolumeClaim *PersistentVolumeClaimVolumeSource // RBD *RBDVolumeSource // FlexVolume *FlexVolumeSource // Cinder *CinderVolumeSource // CephFS *CephFSVolumeSource // Flocker *FlockerVolumeSource // DownwardAPI *DownwardAPIVolumeSource // FC *FCVolumeSource // AzureFile *AzureFileVolumeSource // ConfigMap *ConfigMapVolumeSource }
func setVolumeSourceByType(kv *kapi.Volume, opts *AddVolumeOptions) error { switch strings.ToLower(opts.Type) { case "emptydir": kv.EmptyDir = &kapi.EmptyDirVolumeSource{} case "hostpath": kv.HostPath = &kapi.HostPathVolumeSource{ Path: opts.Path, } case "secret": kv.Secret = &kapi.SecretVolumeSource{ SecretName: opts.SecretName, } case "configmap": kv.ConfigMap = &kapi.ConfigMapVolumeSource{ LocalObjectReference: kapi.LocalObjectReference{ Name: opts.ConfigMapName, }, } case "persistentvolumeclaim", "pvc": kv.PersistentVolumeClaim = &kapi.PersistentVolumeClaimVolumeSource{ ClaimName: opts.ClaimName, } default: return fmt.Errorf("invalid volume type: %s", opts.Type) } return nil }
func TestEnforcingServiceAccount(t *testing.T) { masterConfig, err := testserver.DefaultMasterOptions() masterConfig.ServiceAccountConfig.LimitSecretReferences = false if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminConfig, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // Get a service account token saToken, err := waitForServiceAccountToken(clusterAdminKubeClient, api.NamespaceDefault, serviceaccountadmission.DefaultServiceAccountName, 20, time.Second) if err != nil { t.Errorf("unexpected error: %v", err) } if len(saToken) == 0 { t.Errorf("token was not created") } pod := &api.Pod{} pod.Name = "foo" pod.Namespace = api.NamespaceDefault pod.Spec.ServiceAccountName = serviceaccountadmission.DefaultServiceAccountName container := api.Container{} container.Name = "foo" container.Image = "openshift/hello-openshift" pod.Spec.Containers = []api.Container{container} secretVolume := api.Volume{} secretVolume.Name = "bar-vol" secretVolume.Secret = &api.SecretVolumeSource{} secretVolume.Secret.SecretName = "bar" pod.Spec.Volumes = []api.Volume{secretVolume} err = wait.Poll(100*time.Millisecond, 5*time.Second, func() (bool, error) { if _, err := clusterAdminKubeClient.Pods(api.NamespaceDefault).Create(pod); err != nil { // The SA admission controller cache seems to take forever to update. This check comes after the limit check, so until we get it sorted out // check if we're getting this particular error if strings.Contains(err.Error(), "no API token found for service account") { return true, nil } t.Log(err) return false, nil } return true, nil }) if err != nil { t.Errorf("unexpected error: %v", err) } clusterAdminKubeClient.Pods(api.NamespaceDefault).Delete(pod.Name, nil) sa, err := clusterAdminKubeClient.ServiceAccounts(api.NamespaceDefault).Get(bootstrappolicy.DeployerServiceAccountName) if err != nil { t.Fatalf("unexpected error: %v", err) } if sa.Annotations == nil { sa.Annotations = map[string]string{} } sa.Annotations[serviceaccountadmission.EnforceMountableSecretsAnnotation] = "true" time.Sleep(5) _, err = clusterAdminKubeClient.ServiceAccounts(api.NamespaceDefault).Update(sa) if err != nil { t.Fatalf("unexpected error: %v", err) } expectedMessage := "is not allowed because service account deployer does not reference that secret" pod.Spec.ServiceAccountName = bootstrappolicy.DeployerServiceAccountName err = wait.Poll(100*time.Millisecond, 5*time.Second, func() (bool, error) { if _, err := clusterAdminKubeClient.Pods(api.NamespaceDefault).Create(pod); err == nil || !strings.Contains(err.Error(), expectedMessage) { clusterAdminKubeClient.Pods(api.NamespaceDefault).Delete(pod.Name, nil) return false, nil } return true, nil }) if err != nil { t.Errorf("unexpected error: %v", err) } }