Skip to content

Commit 595ed4f

Browse files
authored
Merge pull request #495 from byepolr/link-following
Enabled symbolic link following in mounts
2 parents ad1142c + 3fa3af4 commit 595ed4f

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

pkg/hostagent/mount.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,20 @@ func (a *HostAgent) setupMount(ctx context.Context, m limayaml.Mount) (*mount, e
4040
if err := os.MkdirAll(expanded, 0755); err != nil {
4141
return nil, err
4242
}
43+
// NOTE: allow_other requires "user_allow_other" in /etc/fuse.conf
44+
sshfsOptions := "allow_other"
45+
if *m.SSHFS.FollowSymlinks {
46+
sshfsOptions = sshfsOptions + ",follow_symlinks"
47+
}
4348
logrus.Infof("Mounting %q", expanded)
4449
rsf := &reversesshfs.ReverseSSHFS{
45-
SSHConfig: a.sshConfig,
46-
LocalPath: expanded,
47-
Host: "127.0.0.1",
48-
Port: a.sshLocalPort,
49-
RemotePath: expanded,
50-
Readonly: !m.Writable,
51-
// NOTE: allow_other requires "user_allow_other" in /etc/fuse.conf
52-
SSHFSAdditionalArgs: []string{"-o", "allow_other"},
50+
SSHConfig: a.sshConfig,
51+
LocalPath: expanded,
52+
Host: "127.0.0.1",
53+
Port: a.sshLocalPort,
54+
RemotePath: expanded,
55+
Readonly: !m.Writable,
56+
SSHFSAdditionalArgs: []string{"-o", sshfsOptions},
5357
}
5458
if err := rsf.Prepare(); err != nil {
5559
return nil, fmt.Errorf("failed to prepare reverse sshfs for %q: %w", expanded, err)

pkg/limayaml/default.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,17 @@ mounts:
4242
# CAUTION: `writable` SHOULD be false for the home directory.
4343
# Setting `writable` to true is possible, but untested and dangerous.
4444
writable: false
45+
# SSHFS has an optional flag called 'follow_symlinks'. This allows mounts
46+
# to be properly resolved in the guest os and allow for access to the
47+
# contents of the symlnk. This defaults to false if not supplied. As a result,
48+
# symlinked files & folders on the Host system will look and feel like regular
49+
# files directories in the Guest OS.
50+
sshfs:
51+
followSymlinks: false
4552
- location: "/tmp/lima"
4653
writable: true
54+
sshfs:
55+
followSymlinks: false
4756

4857
ssh:
4958
# A localhost port of the host. Forwarded to port 22 of the guest.

pkg/limayaml/defaults.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
298298
location := make(map[string]int)
299299
for _, mount := range append(append(d.Mounts, y.Mounts...), o.Mounts...) {
300300
if i, ok := location[mount.Location]; ok {
301+
if mount.SSHFS.FollowSymlinks != nil {
302+
mounts[i].SSHFS.FollowSymlinks = mount.SSHFS.FollowSymlinks
303+
}
301304
mounts[i].Writable = mount.Writable
302305
} else {
303306
location[mount.Location] = len(mounts)
@@ -306,6 +309,13 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
306309
}
307310
y.Mounts = mounts
308311

312+
for i := range y.Mounts {
313+
mount := &y.Mounts[i]
314+
if mount.SSHFS.FollowSymlinks == nil {
315+
mount.SSHFS.FollowSymlinks = pointer.Bool(false)
316+
}
317+
}
318+
309319
// Note: DNS lists are not combined; highest priority setting is picked
310320
if len(y.DNS) == 0 {
311321
y.DNS = d.DNS

pkg/limayaml/defaults_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func TestFillDefault(t *testing.T) {
116116

117117
expect := builtin
118118
expect.Mounts = y.Mounts
119+
expect.Mounts[0].SSHFS.FollowSymlinks = pointer.Bool(false)
119120
// Only missing Mounts field is Writable, and the default value is also the null value: false
120121

121122
expect.Provision = y.Provision
@@ -235,6 +236,7 @@ func TestFillDefault(t *testing.T) {
235236
expect = d
236237
// Also verify that archive arch is filled in
237238
expect.Containerd.Archives[0].Arch = *d.Arch
239+
expect.Mounts[0].SSHFS.FollowSymlinks = pointer.Bool(false)
238240

239241
y = LimaYAML{}
240242
FillDefault(&y, &d, &LimaYAML{}, filePath)
@@ -302,6 +304,7 @@ func TestFillDefault(t *testing.T) {
302304
{
303305
Location: "/var/log",
304306
Writable: true,
307+
SSHFS: SSHFS{FollowSymlinks: pointer.Bool(true)},
305308
},
306309
},
307310
Provision: []Provision{
@@ -358,6 +361,7 @@ func TestFillDefault(t *testing.T) {
358361
// o.Mounts just makes d.Mounts[0] writable because the Location matches
359362
expect.Mounts = append(d.Mounts, y.Mounts...)
360363
expect.Mounts[0].Writable = true
364+
expect.Mounts[0].SSHFS.FollowSymlinks = pointer.Bool(true)
361365

362366
// o.Networks[1] is overriding the d.Networks[0].Lima entry for the "def0" interface
363367
expect.Networks = append(append(d.Networks, y.Networks...), o.Networks[0])

pkg/limayaml/limayaml.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ type File struct {
4545
type Mount struct {
4646
Location string `yaml:"location" json:"location"` // REQUIRED
4747
Writable bool `yaml:"writable,omitempty" json:"writable,omitempty"`
48+
SSHFS SSHFS `yaml:"sshfs,omitempty" json:"sshfs,omitempty"`
49+
}
50+
51+
type SSHFS struct {
52+
FollowSymlinks *bool `yaml:"followSymlinks,omitempty" json:"followSymlinks,omitempty"`
4853
}
4954

5055
type SSH struct {

0 commit comments

Comments
 (0)