@@ -24,6 +24,7 @@ import (
24
24
"io/ioutil"
25
25
"os"
26
26
"path/filepath"
27
+ "strconv"
27
28
28
29
"github.com/go-logr/logr"
29
30
apiequality "k8s.io/apimachinery/pkg/api/equality"
@@ -47,6 +48,18 @@ type Filesystem struct {
47
48
48
49
// used by the 'read only' methods
49
50
fs fs.FS
51
+
52
+ // FixedFSGroup is an optional field which will set the gid ownership of all
53
+ // volume's data directories to this value.
54
+ // If this value is set, FSGroupVolumeAttributeKey has no effect.
55
+ FixedFSGroup * int64
56
+
57
+ // FSGroupVolumeAttributeKey is an optional well-known key in the volume
58
+ // attributes. If this attribute is present in the context when writing
59
+ // files, gid ownership of the volume's data directory will be changed to
60
+ // the value. Attribute value must be a valid int64 value.
61
+ // If FixedFSGroup is defined, this field has no effect.
62
+ FSGroupVolumeAttributeKey * string
50
63
}
51
64
52
65
// Ensure the Filesystem implementation is fully featured
@@ -177,27 +190,32 @@ func (f *Filesystem) RegisterMetadata(meta metadata.Metadata) (bool, error) {
177
190
}
178
191
179
192
// WriteFiles writes the given data to filesystem files within the volume's
180
- // data directory. Filesystem supports setting custom fsUser UID to these
181
- // files.
182
- func (f * Filesystem ) WriteFiles (volumeID string , files map [string ][]byte , fsUser * int64 ) error {
183
- // Data directory should be read, write and execute only to the fs user
184
- if err := os .MkdirAll (f .dataPathForVolumeID (volumeID ), 0700 ); err != nil {
193
+ // data directory. Filesystem supports changing ownership of the data directory
194
+ // to a custom gid.
195
+ func (f * Filesystem ) WriteFiles (meta metadata.Metadata , files map [string ][]byte ) error {
196
+ // Data directory should be read, write and execute only to the fs user; read and executable to group
197
+ if err := os .MkdirAll (f .dataPathForVolumeID (meta .VolumeID ), 0750 ); err != nil {
198
+ return err
199
+ }
200
+
201
+ fsGroup , err := f .fsGroupForMetadata (meta )
202
+ if err != nil {
185
203
return err
186
204
}
187
205
188
- // If a fsUser is defined, Chown the directory to that user .
189
- if fsUser != nil {
190
- if err := os .Chown (f .dataPathForVolumeID (volumeID ), int (* fsUser ), - 1 ); err != nil {
191
- return fmt .Errorf ("failed to chown data dir to uid %v: %w" , * fsUser , err )
206
+ // If a fsGroup is defined, Chown the directory to that group .
207
+ if fsGroup != nil {
208
+ if err := os .Chown (f .dataPathForVolumeID (meta . VolumeID ), - 1 , int (* fsGroup ) ); err != nil {
209
+ return fmt .Errorf ("failed to chown data dir to gid %v: %w" , * fsGroup , err )
192
210
}
193
211
}
194
212
195
- writer , err := util .NewAtomicWriter (f .dataPathForVolumeID (volumeID ), fmt .Sprintf ("volumeID %v" , volumeID ))
213
+ writer , err := util .NewAtomicWriter (f .dataPathForVolumeID (meta . VolumeID ), fmt .Sprintf ("volumeID %v" , meta . VolumeID ))
196
214
if err != nil {
197
215
return err
198
216
}
199
217
200
- payload := makePayload (files , fsUser )
218
+ payload := makePayload (files , fsGroup )
201
219
return writer .Write (payload )
202
220
}
203
221
@@ -234,14 +252,42 @@ func (f *Filesystem) tempfsPath() string {
234
252
return filepath .Join (f .baseDir , "inmemfs" )
235
253
}
236
254
237
- func makePayload (in map [string ][]byte , fsUser * int64 ) map [string ]util.FileProjection {
255
+ func makePayload (in map [string ][]byte , fsGroup * int64 ) map [string ]util.FileProjection {
238
256
out := make (map [string ]util.FileProjection , len (in ))
239
257
for name , data := range in {
240
258
out [name ] = util.FileProjection {
241
- Data : data ,
242
- FsUser : fsUser ,
243
- Mode : readOnlyUserAndGroupFileMode ,
259
+ Data : data ,
260
+ FsGroup : fsGroup ,
261
+ Mode : readOnlyUserAndGroupFileMode ,
244
262
}
245
263
}
246
264
return out
247
265
}
266
+
267
+ // fsGroupForMetadata returns the gid that ownership of the volume data
268
+ // directory should be changed to. Returns nil if ownership should not be
269
+ // changed.
270
+ func (f * Filesystem ) fsGroupForMetadata (meta metadata.Metadata ) (* int64 , error ) {
271
+ // FixedFSGroup takes precedence over attribute key.
272
+ if f .FixedFSGroup != nil {
273
+ return f .FixedFSGroup , nil
274
+ }
275
+
276
+ // If the FSGroupVolumeAttributeKey is not defined, no ownership can change.
277
+ if f .FSGroupVolumeAttributeKey == nil {
278
+ return nil , nil
279
+ }
280
+
281
+ fsGroupStr , ok := meta .VolumeContext [* f .FSGroupVolumeAttributeKey ]
282
+ if ! ok {
283
+ // If the attribute has not been set, return no ownership change.
284
+ return nil , nil
285
+ }
286
+
287
+ fsGroup , err := strconv .ParseInt (fsGroupStr , 10 , 64 )
288
+ if err != nil {
289
+ return nil , fmt .Errorf ("failed to parse %q, value must be a valid integer: %w" , * f .FSGroupVolumeAttributeKey , err )
290
+ }
291
+
292
+ return & fsGroup , nil
293
+ }
0 commit comments