From 7f0119c3c45ab84d1333ff5edb0759ae1e06a4f1 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Thu, 20 Oct 2022 10:28:38 +0000 Subject: [PATCH] [ws-daemon] Add support for idmapped mounts --- components/workspacekit/cmd/rings.go | 65 ++-- .../ws-daemon-api/go/workspace_daemon.pb.go | 280 +++++++++--------- .../typescript/src/workspace_daemon_pb.d.ts | 4 + .../typescript/src/workspace_daemon_pb.js | 34 ++- .../ws-daemon-api/workspace_daemon.proto | 5 +- components/ws-daemon/nsinsider/main.go | 82 +++++ components/ws-daemon/pkg/iws/iws.go | 70 +++-- 7 files changed, 336 insertions(+), 204 deletions(-) diff --git a/components/workspacekit/cmd/rings.go b/components/workspacekit/cmd/rings.go index d5249043b8e1b2..8ea7e7aaf46289 100644 --- a/components/workspacekit/cmd/rings.go +++ b/components/workspacekit/cmd/rings.go @@ -22,6 +22,7 @@ import ( "runtime" "strconv" "strings" + "sync" "syscall" "time" @@ -78,21 +79,7 @@ var ring0Cmd = &cobra.Command{ defer log.Info("ring0 stopped") - ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) - defer cancel() - - client, err := connectToInWorkspaceDaemonService(ctx) - if err != nil { - log.WithError(err).Error("cannot connect to daemon from ring0") - return - } - - prep, err := client.PrepareForUserNS(ctx, &daemonapi.PrepareForUserNSRequest{}) - if err != nil { - log.WithError(err).Fatal("cannot prepare for user namespaces") - return - } - client.Close() + var err error defer func() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -119,10 +106,6 @@ var ring0Cmd = &cobra.Command{ cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - cmd.Env = append(os.Environ(), - "WORKSPACEKIT_FSSHIFT="+prep.FsShift.String(), - fmt.Sprintf("WORKSPACEKIT_NO_WORKSPACE_MOUNT=%v", prep.FullWorkspaceBackup || prep.PersistentVolumeClaim), - ) if err := cmd.Start(); err != nil { log.WithError(err).Error("failed to start ring0") @@ -210,7 +193,7 @@ var ring1Cmd = &cobra.Command{ defer log.Info("ring1 stopped") - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) defer cancel() mapping := []*daemonapi.WriteIDMappingRequest_Mapping{ @@ -258,11 +241,23 @@ var ring1Cmd = &cobra.Command{ log.WithError(err).Fatal("cannot create tempdir") } - var fsshift api.FSShiftMethod - if v, ok := api.FSShiftMethod_value[os.Getenv("WORKSPACEKIT_FSSHIFT")]; !ok { - log.WithField("fsshift", os.Getenv("WORKSPACEKIT_FSSHIFT")).Fatal("unknown FS shift method") - } else { - fsshift = api.FSShiftMethod(v) + client, err := connectToInWorkspaceDaemonService(ctx) + if err != nil { + log.WithError(err).Error("cannot connect to daemon from ring0") + return + } + var closeOnce sync.Once + closeClient := func() { + closeOnce.Do(func() { client.Close() }) + } + defer closeClient() + + prep, err := client.PrepareForUserNS(ctx, &daemonapi.PrepareForUserNSRequest{ + UsernsPid: int64(os.Getpid()), + }) + if err != nil { + log.WithError(err).Fatal("cannot prepare for user namespaces") + return } type mnte struct { @@ -273,8 +268,8 @@ var ring1Cmd = &cobra.Command{ } var mnts []mnte - switch fsshift { - case api.FSShiftMethod_FUSE: + switch prep.FsShift { + case api.FSShiftMethod_FUSE, api.FSShiftMethod_IDMAPPED: mnts = append(mnts, mnte{Target: "/", Source: "/.workspace/mark", Flags: unix.MS_BIND | unix.MS_REC}, ) @@ -283,7 +278,7 @@ var ring1Cmd = &cobra.Command{ mnte{Target: "/", Source: "/.workspace/mark", FSType: "shiftfs"}, ) default: - log.WithField("fsshift", fsshift).Fatal("unknown FS shift method") + log.WithField("fsshift", prep.FsShift).Fatal("unknown FS shift method") } procMounts, err := ioutil.ReadFile("/proc/mounts") @@ -320,7 +315,7 @@ var ring1Cmd = &cobra.Command{ // FWB workspaces do not require mounting /workspace // if that is done, the backup will not contain any change in the directory // same applies to persistent volume claims, we cannot mount /workspace folder when PVC is used - if os.Getenv("WORKSPACEKIT_NO_WORKSPACE_MOUNT") != "true" { + if !prep.PersistentVolumeClaim && !prep.FullWorkspaceBackup { mnts = append(mnts, mnte{Target: "/workspace", Flags: unix.MS_BIND | unix.MS_REC}, ) @@ -410,29 +405,21 @@ var ring1Cmd = &cobra.Command{ log.WithError(err).Error("cannot create directory for mounting proc") return } - - client, err := connectToInWorkspaceDaemonService(ctx) - if err != nil { - log.WithError(err).Error("cannot connect to daemon from ring1") - return - } _, err = client.MountProc(ctx, &daemonapi.MountProcRequest{ Target: procLoc, Pid: int64(cmd.Process.Pid), }) if err != nil { - client.Close() log.WithError(err).Error("cannot mount proc") return } _, err = client.EvacuateCGroup(ctx, &daemonapi.EvacuateCGroupRequest{}) if err != nil { - client.Close() log.WithError(err).Error("cannot evacuate cgroup") return } - client.Close() + defer closeClient() // We have to wait for ring2 to come back to us and connect to the socket we've passed along. // There's a chance that ring2 crashes or misbehaves, so we don't want to wait forever, hence @@ -496,7 +483,7 @@ var ring1Cmd = &cobra.Command{ _, err = msgutil.MarshalToWriter(ring2Conn, ringSyncMsg{ Stage: 1, Rootfs: ring2Root, - FSShift: fsshift, + FSShift: prep.FsShift, }) if err != nil { log.WithError(err).Error("cannot send ring sync msg to ring2") diff --git a/components/ws-daemon-api/go/workspace_daemon.pb.go b/components/ws-daemon-api/go/workspace_daemon.pb.go index 7bbb73360a2db2..0c6fe4b0630b94 100644 --- a/components/ws-daemon-api/go/workspace_daemon.pb.go +++ b/components/ws-daemon-api/go/workspace_daemon.pb.go @@ -29,8 +29,9 @@ const ( type FSShiftMethod int32 const ( - FSShiftMethod_SHIFTFS FSShiftMethod = 0 - FSShiftMethod_FUSE FSShiftMethod = 1 + FSShiftMethod_SHIFTFS FSShiftMethod = 0 + FSShiftMethod_FUSE FSShiftMethod = 1 + FSShiftMethod_IDMAPPED FSShiftMethod = 2 ) // Enum value maps for FSShiftMethod. @@ -38,10 +39,12 @@ var ( FSShiftMethod_name = map[int32]string{ 0: "SHIFTFS", 1: "FUSE", + 2: "IDMAPPED", } FSShiftMethod_value = map[string]int32{ - "SHIFTFS": 0, - "FUSE": 1, + "SHIFTFS": 0, + "FUSE": 1, + "IDMAPPED": 2, } ) @@ -76,6 +79,8 @@ type PrepareForUserNSRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + UsernsPid int64 `protobuf:"varint,1,opt,name=userns_pid,json=usernsPid,proto3" json:"userns_pid,omitempty"` } func (x *PrepareForUserNSRequest) Reset() { @@ -110,6 +115,13 @@ func (*PrepareForUserNSRequest) Descriptor() ([]byte, []int) { return file_workspace_daemon_proto_rawDescGZIP(), []int{0} } +func (x *PrepareForUserNSRequest) GetUsernsPid() int64 { + if x != nil { + return x.UsernsPid + } + return 0 +} + type PrepareForUserNSResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1040,136 +1052,138 @@ var File_workspace_daemon_proto protoreflect.FileDescriptor var file_workspace_daemon_proto_rawDesc = []byte{ 0x0a, 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x69, 0x77, 0x73, 0x22, 0x19, 0x0a, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x69, 0x77, 0x73, 0x22, 0x38, 0x0a, 0x17, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, - 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb5, 0x01, 0x0a, 0x18, 0x50, 0x72, 0x65, - 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x66, 0x73, 0x5f, 0x73, 0x68, 0x69, 0x66, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x46, 0x53, - 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x66, 0x73, 0x53, - 0x68, 0x69, 0x66, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x66, 0x75, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x65, 0x72, 0x73, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x63, 0x6c, - 0x61, 0x69, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x72, 0x73, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x22, 0x51, 0x0a, 0x16, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, - 0x6f, 0x64, 0x65, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, - 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x67, 0x69, - 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, - 0x59, 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, - 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, - 0x10, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x3d, 0x0a, 0x11, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, - 0x14, 0x0a, 0x12, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2c, 0x0a, 0x10, 0x54, 0x65, 0x61, 0x72, - 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, - 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, - 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, - 0x64, 0x22, 0x18, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, - 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x45, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x09, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x09, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x43, 0x70, 0x75, 0x52, 0x03, - 0x63, 0x70, 0x75, 0x12, 0x23, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, - 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x22, 0x2f, 0x0a, 0x03, 0x43, 0x70, 0x75, 0x12, - 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x32, 0x0a, 0x06, 0x4d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2a, 0x26, 0x0a, - 0x0d, 0x46, 0x53, 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0b, - 0x0a, 0x07, 0x53, 0x48, 0x49, 0x46, 0x54, 0x46, 0x53, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, - 0x55, 0x53, 0x45, 0x10, 0x01, 0x32, 0xd3, 0x05, 0x0a, 0x12, 0x49, 0x6e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x10, - 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, - 0x12, 0x1c, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4b, 0x0a, 0x0e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, - 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, - 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x55, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x50, 0x72, 0x6f, 0x63, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0a, 0x4d, 0x6f, 0x75, 0x6e, - 0x74, 0x53, 0x79, 0x73, 0x66, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, 0x55, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x53, 0x79, 0x73, 0x66, 0x73, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x54, 0x65, 0x61, - 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x14, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x54, 0x65, 0x61, 0x72, - 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x77, - 0x73, 0x2e, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, - 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, - 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, - 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x48, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, - 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0x60, 0x0a, 0x14, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2b, 0x5a, - 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, - 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x73, 0x5f, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x6e, 0x73, 0x50, 0x69, 0x64, 0x22, 0xb5, 0x01, 0x0a, 0x18, 0x50, 0x72, 0x65, 0x70, + 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x66, 0x73, 0x5f, 0x73, 0x68, 0x69, 0x66, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x46, 0x53, 0x53, + 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x66, 0x73, 0x53, 0x68, + 0x69, 0x66, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x13, 0x66, 0x75, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x65, 0x72, 0x73, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x22, + 0x51, 0x0a, 0x16, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, + 0x64, 0x65, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, + 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, + 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x67, 0x69, 0x64, + 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, 0x59, + 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, + 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, 0x10, + 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x4d, 0x6f, + 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x3d, 0x0a, 0x11, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, + 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x14, + 0x0a, 0x12, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2c, 0x0a, 0x10, 0x54, 0x65, 0x61, 0x72, 0x64, + 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, + 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, + 0x22, 0x18, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, + 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x45, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x09, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4c, 0x0a, 0x09, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x43, 0x70, 0x75, 0x52, 0x03, 0x63, + 0x70, 0x75, 0x12, 0x23, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, + 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x22, 0x2f, 0x0a, 0x03, 0x43, 0x70, 0x75, 0x12, 0x12, + 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, + 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x32, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2a, 0x34, 0x0a, 0x0d, + 0x46, 0x53, 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0b, 0x0a, + 0x07, 0x53, 0x48, 0x49, 0x46, 0x54, 0x46, 0x53, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x55, + 0x53, 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x44, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, + 0x10, 0x02, 0x32, 0xd3, 0x05, 0x0a, 0x12, 0x49, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x10, 0x50, 0x72, 0x65, + 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x12, 0x1c, 0x2e, + 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, + 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, + 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, 0x73, + 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, + 0x6f, 0x63, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x77, 0x73, + 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0a, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x79, + 0x73, 0x66, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, 0x73, + 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x79, + 0x73, 0x66, 0x73, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, + 0x77, 0x6e, 0x12, 0x14, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x54, + 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, + 0x74, 0x68, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, + 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, + 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, + 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x19, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x69, 0x77, 0x73, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0x60, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x48, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x19, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x69, + 0x77, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, + 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts index df590c639a4acc..e201ec76539443 100644 --- a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts +++ b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts @@ -13,6 +13,8 @@ import * as jspb from "google-protobuf"; export class PrepareForUserNSRequest extends jspb.Message { + getUsernsPid(): number; + setUsernsPid(value: number): PrepareForUserNSRequest; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): PrepareForUserNSRequest.AsObject; @@ -26,6 +28,7 @@ export class PrepareForUserNSRequest extends jspb.Message { export namespace PrepareForUserNSRequest { export type AsObject = { + usernsPid: number, } } @@ -440,4 +443,5 @@ export namespace Memory { export enum FSShiftMethod { SHIFTFS = 0, FUSE = 1, + IDMAPPED = 2, } diff --git a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js index 4ee6875bad27ba..1918f45c6adf8a 100644 --- a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js +++ b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js @@ -494,7 +494,7 @@ proto.iws.PrepareForUserNSRequest.prototype.toObject = function(opt_includeInsta */ proto.iws.PrepareForUserNSRequest.toObject = function(includeInstance, msg) { var f, obj = { - + usernsPid: jspb.Message.getFieldWithDefault(msg, 1, 0) }; if (includeInstance) { @@ -531,6 +531,10 @@ proto.iws.PrepareForUserNSRequest.deserializeBinaryFromReader = function(msg, re } var field = reader.getFieldNumber(); switch (field) { + case 1: + var value = /** @type {number} */ (reader.readInt64()); + msg.setUsernsPid(value); + break; default: reader.skipField(); break; @@ -560,6 +564,31 @@ proto.iws.PrepareForUserNSRequest.prototype.serializeBinary = function() { */ proto.iws.PrepareForUserNSRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; + f = message.getUsernsPid(); + if (f !== 0) { + writer.writeInt64( + 1, + f + ); + } +}; + + +/** + * optional int64 userns_pid = 1; + * @return {number} + */ +proto.iws.PrepareForUserNSRequest.prototype.getUsernsPid = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.iws.PrepareForUserNSRequest} returns this + */ +proto.iws.PrepareForUserNSRequest.prototype.setUsernsPid = function(value) { + return jspb.Message.setProto3IntField(this, 1, value); }; @@ -3288,7 +3317,8 @@ proto.iws.Memory.prototype.setLimit = function(value) { */ proto.iws.FSShiftMethod = { SHIFTFS: 0, - FUSE: 1 + FUSE: 1, + IDMAPPED: 2 }; goog.object.extend(exports, proto.iws); diff --git a/components/ws-daemon-api/workspace_daemon.proto b/components/ws-daemon-api/workspace_daemon.proto index 762bc8f6930045..091c76cd529465 100644 --- a/components/ws-daemon-api/workspace_daemon.proto +++ b/components/ws-daemon-api/workspace_daemon.proto @@ -58,7 +58,9 @@ service WorkspaceInfoService { rpc WorkspaceInfo(WorkspaceInfoRequest) returns (WorkspaceInfoResponse) {} } -message PrepareForUserNSRequest {} +message PrepareForUserNSRequest { + int64 userns_pid = 1; +} message PrepareForUserNSResponse { FSShiftMethod fs_shift = 1; bool full_workspace_backup = 2; @@ -70,6 +72,7 @@ message PrepareForUserNSResponse { enum FSShiftMethod { SHIFTFS = 0; FUSE = 1; + IDMAPPED = 2; } message WriteIDMappingResponse { diff --git a/components/ws-daemon/nsinsider/main.go b/components/ws-daemon/nsinsider/main.go index b8d02bcbff395e..2aa8eb6c6101a3 100644 --- a/components/ws-daemon/nsinsider/main.go +++ b/components/ws-daemon/nsinsider/main.go @@ -12,6 +12,7 @@ import ( "os/exec" "path/filepath" "strings" + "sync" "time" "unsafe" @@ -155,6 +156,87 @@ func main() { return nil }, }, + { + Name: "mount-idmapped-mark", + Usage: "mounts a idmapped mark", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "source", + Required: true, + }, + &cli.StringFlag{ + Name: "merged", + Required: true, + }, + &cli.StringFlag{ + Name: "upper", + Required: true, + }, + &cli.StringFlag{ + Name: "work", + Required: true, + }, + &cli.StringFlag{ + Name: "userns", + Required: true, + }, + }, + Action: func(c *cli.Context) error { + target := filepath.Clean(c.String("merged")) + upper := filepath.Clean(c.String("upper")) + work := filepath.Clean(c.String("work")) + source := filepath.Clean(c.String("source")) + userns := filepath.Clean(c.String("userns")) + + mappedLower, err := os.MkdirTemp("", "idmapped-mark") + if err != nil { + return xerrors.Errorf("mkdirtemp: %w", err) + } + + mappedFD, err := unix.OpenTree(unix.AT_FDCWD, source, unix.OPEN_TREE_CLONE) + if err != nil { + return xerrors.Errorf("opentree: %w", err) + } + var closeOnce sync.Once + closeMappedFD := func() { + closeOnce.Do(func() { unix.Close(mappedFD) }) + } + defer closeMappedFD() + + usernsFD, err := os.Open(userns) + if err != nil { + return xerrors.Errorf("open(userns): %w", err) + } + defer usernsFD.Close() + err = unix.MountSetattr(mappedFD, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE, &unix.MountAttr{ + Attr_set: unix.MOUNT_ATTR_IDMAP, + Attr_clr: 0, + Propagation: 0, + Userns_fd: uint64(usernsFD.Fd()), + }) + if err != nil { + return xerrors.Errorf("mountsetattr: %w", err) + } + + err = unix.MoveMount(mappedFD, "", unix.AT_FDCWD, mappedLower, flagMoveMountFEmptyPath) + if err != nil { + return xerrors.Errorf("moveMount: %w", err) + } + + err = unix.Mount("overlay", target, "overlay", 0, fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", mappedLower, upper, work)) + if err != nil { + return xerrors.Errorf("mount(overlay): %w", err) + } + + closeMappedFD() + err = unix.Unmount(mappedLower, 0) + if err != nil { + return xerrors.Errorf("Unmount(mappedLower): %w", err) + } + + return nil + }, + }, { Name: "mount-shiftfs-mark", Usage: "mounts a shiftfs mark", diff --git a/components/ws-daemon/pkg/iws/iws.go b/components/ws-daemon/pkg/iws/iws.go index c34c43c86450ab..0f3585ff052eee 100644 --- a/components/ws-daemon/pkg/iws/iws.go +++ b/components/ws-daemon/pkg/iws/iws.go @@ -254,7 +254,29 @@ func (wbs *InWorkspaceServiceServer) PrepareForUserNS(ctx context.Context, req * mountpoint := filepath.Join(wbs.Session.ServiceLocNode, "mark") - if wbs.FSShift == api.FSShiftMethod_FUSE || wbs.Session.FullWorkspaceBackup { + switch { + case wbs.FSShift == api.FSShiftMethod_IDMAPPED: + procPID, err := wbs.Uidmapper.findHostPID(containerPID, uint64(req.UsernsPid)) + if err != nil { + log.WithError(err).WithField("containerPID", containerPID).WithField("processPID", req.UsernsPid).Error("cannot map in-container PID") + return nil, status.Error(codes.InvalidArgument, "cannot map in-container PID") + } + + err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { + // In case of any change in the user mapping, the next line must be updated. + c.Args = append(c.Args, "mount-idmapped-mark", + "--source", rootfs, + "--merged", filepath.Join(wbs.Session.ServiceLocNode, "mark"), + "--upper", filepath.Join(wbs.Session.ServiceLocNode, "upper"), + "--work", filepath.Join(wbs.Session.ServiceLocNode, "work"), + "--userns", fmt.Sprintf("/proc/%d/ns/user", procPID)) + }) + if err != nil { + log.WithField("rootfs", rootfs).WithError(err).Error("cannot mount idmapped mark") + return nil, status.Errorf(codes.Internal, "cannot mount idmapped mark") + } + + case wbs.FSShift == api.FSShiftMethod_FUSE, wbs.Session.FullWorkspaceBackup: err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { // In case of any change in the user mapping, the next line must be updated. mappings := fmt.Sprintf("0:%v:1:1:100000:65534", wsinit.GitpodUID) @@ -271,35 +293,25 @@ func (wbs *InWorkspaceServiceServer) PrepareForUserNS(ctx context.Context, req * return nil, status.Errorf(codes.Internal, "cannot mount fusefs mark") } - log.WithFields(wbs.Session.OWI()).WithField("configuredShift", wbs.FSShift).WithField("fwb", wbs.Session.FullWorkspaceBackup).Info("fs-shift using fuse") - - if err := wbs.createWorkspaceCgroup(ctx, wscontainerID); err != nil { - return nil, err + case wbs.FSShift == api.FSShiftMethod_SHIFTFS: + err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { + c.Args = append(c.Args, "make-shared", "--target", "/") + }) + if err != nil { + log.WithField("containerPID", containerPID).WithError(err).Error("cannot make container's rootfs shared") + return nil, status.Errorf(codes.Internal, "cannot make container's rootfs shared") + } + err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { + c.Args = append(c.Args, "mount-shiftfs-mark", "--source", rootfs, "--target", mountpoint) + }) + if err != nil { + log.WithField("rootfs", rootfs).WithField("mountpoint", mountpoint).WithError(err).Error("cannot mount shiftfs mark") + return nil, status.Errorf(codes.Internal, "cannot mount shiftfs mark") } - return &api.PrepareForUserNSResponse{ - FsShift: api.FSShiftMethod_FUSE, - FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, - PersistentVolumeClaim: wbs.Session.PersistentVolumeClaim, - }, nil - } - - // We cannot use the nsenter syscall here because mount namespaces affect the whole process, not just the current thread. - // That's why we resort to exec'ing "nsenter ... mount ...". - err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { - c.Args = append(c.Args, "make-shared", "--target", "/") - }) - if err != nil { - log.WithField("containerPID", containerPID).WithError(err).Error("cannot make container's rootfs shared") - return nil, status.Errorf(codes.Internal, "cannot make container's rootfs shared") - } - - err = nsi.Nsinsider(wbs.Session.InstanceID, int(1), func(c *exec.Cmd) { - c.Args = append(c.Args, "mount-shiftfs-mark", "--source", rootfs, "--target", mountpoint) - }) - if err != nil { - log.WithField("rootfs", rootfs).WithField("mountpoint", mountpoint).WithError(err).Error("cannot mount shiftfs mark") - return nil, status.Errorf(codes.Internal, "cannot mount shiftfs mark") + default: + log.WithField("fsshift", wbs.FSShift).Error("unknown fs shift") + return nil, status.Errorf(codes.FailedPrecondition, "unknown fs shift") } if err := wbs.createWorkspaceCgroup(ctx, wscontainerID); err != nil { @@ -307,7 +319,7 @@ func (wbs *InWorkspaceServiceServer) PrepareForUserNS(ctx context.Context, req * } return &api.PrepareForUserNSResponse{ - FsShift: api.FSShiftMethod_SHIFTFS, + FsShift: wbs.FSShift, FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, PersistentVolumeClaim: wbs.Session.PersistentVolumeClaim, }, nil