Skip to content

Commit e0adf54

Browse files
committed
[ws-manager-mk2] Support public SSH keys
1 parent a02a5d9 commit e0adf54

File tree

6 files changed

+80
-9
lines changed

6 files changed

+80
-9
lines changed

components/ws-manager-api/go/crd/v1/workspace_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type WorkspaceSpec struct {
4545

4646
// +kubebuilder:validation:MinItems=0
4747
Ports []PortSpec `json:"ports"`
48+
49+
SshPublicKeys []byte `json:"sshPublicKeys,omitempty"`
4850
}
4951

5052
type Ownership struct {

components/ws-manager-api/go/crd/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ws-manager-mk2/config/crd/bases/workspace.gitpod.io_workspaces.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ spec:
151151
type: object
152152
minItems: 0
153153
type: array
154+
sshPublicKey:
155+
format: byte
156+
type: string
154157
sysEnvVars:
155158
items:
156159
description: EnvVar represents an environment variable present in

components/ws-manager-mk2/service/manager.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ func (wsm *WorkspaceManagerServer) StartWorkspace(ctx context.Context, req *wsma
188188
}
189189
}
190190

191+
sshPublicKeys, err := setSshPublicKeys(req.Spec.SshPublicKeys)
192+
if err != nil {
193+
return nil, status.Errorf(codes.InvalidArgument, "invalid SSH public keys")
194+
}
195+
191196
ws := workspacev1.Workspace{
192197
TypeMeta: metav1.TypeMeta{
193198
APIVersion: workspacev1.GroupVersion.String(),
@@ -230,7 +235,8 @@ func (wsm *WorkspaceManagerServer) StartWorkspace(ctx context.Context, req *wsma
230235
Admission: workspacev1.AdmissionSpec{
231236
Level: admissionLevel,
232237
},
233-
Ports: ports,
238+
Ports: ports,
239+
SshPublicKeys: sshPublicKeys,
234240
},
235241
}
236242
controllerutil.AddFinalizer(&ws, workspacev1.GitpodFinalizerName)
@@ -523,6 +529,28 @@ func (wsm *WorkspaceManagerServer) ControlAdmission(ctx context.Context, req *ws
523529
return &wsmanapi.ControlAdmissionResponse{}, nil
524530
}
525531

532+
func (wsm *WorkspaceManagerServer) UpdateSSHKey(ctx context.Context, req *api.UpdateSSHKeyRequest) (res *api.UpdateSSHKeyResponse, err error) {
533+
span, ctx := tracing.FromContext(ctx, "UpdateSSHKey")
534+
tracing.ApplyOWI(span, log.OWI("", "", req.Id))
535+
defer tracing.FinishSpan(span, &err)
536+
537+
if err = validateUpdateSSHKeyRequest(req); err != nil {
538+
return &api.UpdateSSHKeyResponse{}, err
539+
}
540+
541+
err = wsm.modifyWorkspace(ctx, req.Id, false, func(ws *workspacev1.Workspace) error {
542+
sshKeys, err := setSshPublicKeys(req.Keys)
543+
if err != nil {
544+
return err
545+
}
546+
547+
ws.Spec.SshPublicKeys = sshKeys
548+
return nil
549+
})
550+
551+
return &api.UpdateSSHKeyResponse{}, err
552+
}
553+
526554
// modifyWorkspace modifies a workspace object using the mod function. If the mod function returns a gRPC status error, that error
527555
// is returned directly. If mod returns a non-gRPC error it is turned into one.
528556
func (wsm *WorkspaceManagerServer) modifyWorkspace(ctx context.Context, id string, updateStatus bool, mod func(ws *workspacev1.Workspace) error) error {
@@ -586,6 +614,19 @@ func validateStartWorkspaceRequest(req *api.StartWorkspaceRequest) error {
586614
return nil
587615
}
588616

617+
func validateUpdateSSHKeyRequest(req *api.UpdateSSHKeyRequest) error {
618+
err := validation.ValidateStruct(req,
619+
validation.Field(&req.Id, validation.Required),
620+
validation.Field(&req.Keys, validation.Required),
621+
)
622+
623+
if err != nil {
624+
return status.Errorf(codes.InvalidArgument, "invalid request: %v", err)
625+
}
626+
627+
return nil
628+
}
629+
589630
func isValidWorkspaceType(value interface{}) error {
590631
s, ok := value.(api.WorkspaceType)
591632
if !ok {
@@ -653,6 +694,21 @@ func setEnvironment(envs []*wsmanapi.EnvironmentVariable) []corev1.EnvVar {
653694
return envVars
654695
}
655696

697+
func setSshPublicKeys(keys []string) ([]byte, error) {
698+
if len(keys) != 0 {
699+
spec := &api.SSHPublicKeys{
700+
Keys: keys,
701+
}
702+
sshSpec, err := proto.Marshal(spec)
703+
if err != nil {
704+
return nil, xerrors.Errorf("cannot create remarshal of ssh key spec: %w", err)
705+
}
706+
return sshSpec, nil
707+
}
708+
709+
return nil, nil
710+
}
711+
656712
func extractWorkspaceStatus(ws *workspacev1.Workspace) *wsmanapi.WorkspaceStatus {
657713
version, _ := strconv.ParseUint(ws.ResourceVersion, 10, 64)
658714

components/ws-proxy/cmd/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ var runCmd = &cobra.Command{
8080
infoprov = append(infoprov, podInfoProv)
8181

8282
if cfg.EnableWorkspaceCRD {
83-
crdInfoProv, err := proxy.NewCRDWorkspaceInfoProvider(context.TODO(), mgr.GetClient(), mgr.GetScheme())
83+
crdInfoProv, err := proxy.NewCRDWorkspaceInfoProvider(mgr.GetClient(), mgr.GetScheme())
8484
if err == nil {
8585
if err = crdInfoProv.SetupWithManager(mgr); err != nil {
8686
log.WithError(err).Warn(err, "unable to create CRD-based info provider", "controller", "Workspace")

components/ws-proxy/pkg/proxy/infoprovider.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ type CRDWorkspaceInfoProvider struct {
214214
}
215215

216216
// NewRemoteWorkspaceInfoProvider creates a fresh WorkspaceInfoProvider.
217-
func NewCRDWorkspaceInfoProvider(ctx context.Context, client client.Client, scheme *runtime.Scheme) (*CRDWorkspaceInfoProvider, error) {
217+
func NewCRDWorkspaceInfoProvider(client client.Client, scheme *runtime.Scheme) (*CRDWorkspaceInfoProvider, error) {
218218
// create custom indexer for searches
219219
indexers := cache.Indexers{
220220
workspaceIndex: func(obj interface{}) ([]string, error) {
@@ -291,6 +291,7 @@ func (r *CRDWorkspaceInfoProvider) Reconcile(ctx context.Context, req ctrl.Reque
291291
Ports: ports,
292292
Auth: &wsapi.WorkspaceAuthentication{Admission: admission, OwnerToken: ws.Status.OwnerToken},
293293
StartedAt: ws.CreationTimestamp.Time,
294+
SSHPublicKeys: unmarshalUserSSHPublicKey(ws.Spec.SshPublicKeys),
294295
}
295296

296297
r.store.Update(req.Name, wsinfo)
@@ -350,12 +351,16 @@ func extractUserSSHPublicKeys(pod *corev1.Pod) []string {
350351
if err != nil {
351352
return nil
352353
}
353-
var spec api.SSHPublicKeys
354-
err = proto.Unmarshal(specPB, &spec)
355-
if err != nil {
356-
return nil
357-
}
358-
return spec.Keys
354+
return unmarshalUserSSHPublicKey(specPB)
359355
}
360356
return nil
361357
}
358+
359+
func unmarshalUserSSHPublicKey(keys []byte) []string {
360+
var spec api.SSHPublicKeys
361+
err := proto.Unmarshal(keys, &spec)
362+
if err != nil {
363+
return nil
364+
}
365+
return spec.Keys
366+
}

0 commit comments

Comments
 (0)