diff --git a/aws/efs/README.md b/aws/efs/README.md index 51db96e52526224da4b60efde09344c4f3138cf8..ddf39e744ec8c2b16a90a6083dccd7ba14112463 100644 --- a/aws/efs/README.md +++ b/aws/efs/README.md @@ -181,11 +181,13 @@ provisioner: example.com/aws-efs parameters: gidMin: "40000" gidMax: "50000" + gidAllocate: "true" ``` ### Parameters -* `gidMin` + `gidMax` : The minimum and maximum value of GID range for the storage class. A unique value (GID) in this range ( gidMin-gidMax ) will be used for dynamically provisioned volumes. These are optional values. If not specified, the volume will be provisioned with a value between 2000-2147483647 which are defaults for gidMin and gidMax respectively. +* `gidMin` + `gidMax` : A unique value (GID) in this range (`gidMin`-`gidMax`) will be allocated for each dynamically provisioned volume. Each volume will be secured to its allocated GID. Any pod that consumes the claim will be able to read/write the volume because the pod will automatically receive the volume's allocated GID as a supplemental group, but non-pod mounters outside the system will not have read/write access unless they have the GID or root privileges. See [here](https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#access-control) and [here](https://docs.openshift.com/container-platform/3.6/install_config/persistent_storage/pod_security_context.html#supplemental-groups) for more information. Default to `"2000"` and `"2147483647"`. +* `gidAllocate` : Whether to allocate GIDs to volumes according to the above scheme at all. If `"false"`, dynamically provisioned volumes will not be allocated GIDs, `gidMin` and `gidMax` will be ignored, and anyone will be able to read/write volumes. Defaults to `"true"`. Once you have finished configuring the class to have the name you chose when deploying the provisioner and the parameters you want, create it. @@ -203,7 +205,6 @@ $ kubectl get pv NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE pvc-557b4436-ed73-11e6-84b3-06a700dda5f5 1Mi RWX Delete Bound default/efs 2s ``` -Note: any pod that consumes the claim will be able to read/write to the volume. This is because the volumes are provisioned with a GID (from the default range or according to `gidMin` + `gidMax`) and any pod that mounts the volume via the claim automatically gets the GID as a supplemental group. --- ##### Optional: AWS credentials secret diff --git a/aws/efs/cmd/efs-provisioner/efs-provisioner.go b/aws/efs/cmd/efs-provisioner/efs-provisioner.go index e2aaa9de0f57d947265bf79e63cb1401e7fd4e13..68f4296cf0bc4f4bf3ba6ec6e201f781bc65a457 100644 --- a/aws/efs/cmd/efs-provisioner/efs-provisioner.go +++ b/aws/efs/cmd/efs-provisioner/efs-provisioner.go @@ -124,9 +124,29 @@ func (p *efsProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis return nil, fmt.Errorf("claim.Spec.Selector is not supported") } - gid, err := p.allocator.AllocateNext(options) - if err != nil { - return nil, err + gidAllocate := true + var err error + for k, v := range options.Parameters { + switch strings.ToLower(k) { + case "gidmin": + // Let allocator handle + case "gidmax": + // Let allocator handle + case "gidallocate": + gidAllocate, err = strconv.ParseBool(v) + if err != nil { + return nil, fmt.Errorf("invalid value %s for parameter %s: %v", v, k, err) + } + } + } + + var gid *int + if gidAllocate { + allocate, err := p.allocator.AllocateNext(options) + if err != nil { + return nil, err + } + gid = &allocate } err = p.createVolume(p.getLocalPath(options), gid) @@ -137,9 +157,6 @@ func (p *efsProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis pv := &v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: options.PVName, - Annotations: map[string]string{ - gidallocator.VolumeGidAnnotationKey: strconv.FormatInt(int64(gid), 10), - }, }, Spec: v1.PersistentVolumeSpec{ PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy, @@ -156,12 +173,20 @@ func (p *efsProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis }, }, } + if gidAllocate { + pv.ObjectMeta.Annotations = map[string]string{ + gidallocator.VolumeGidAnnotationKey: strconv.FormatInt(int64(*gid), 10), + } + } return pv, nil } -func (p *efsProvisioner) createVolume(path string, gid int) error { - perm := os.FileMode(0771 | os.ModeSetgid) +func (p *efsProvisioner) createVolume(path string, gid *int) error { + perm := os.FileMode(0777) + if gid != nil { + perm = os.FileMode(0771 | os.ModeSetgid) + } if err := os.MkdirAll(path, perm); err != nil { return err @@ -173,11 +198,13 @@ func (p *efsProvisioner) createVolume(path string, gid int) error { return err } - cmd := exec.Command("chgrp", strconv.Itoa(gid), path) - out, err := cmd.CombinedOutput() - if err != nil { - os.RemoveAll(path) - return fmt.Errorf("chgrp failed with error: %v, output: %s", err, out) + if gid != nil { + cmd := exec.Command("chgrp", strconv.Itoa(*gid), path) + out, err := cmd.CombinedOutput() + if err != nil { + os.RemoveAll(path) + return fmt.Errorf("chgrp failed with error: %v, output: %s", err, out) + } } return nil