diff --git a/controllers/workspace/devworkspace_controller.go b/controllers/workspace/devworkspace_controller.go index 9be8b84e4..35de14e14 100644 --- a/controllers/workspace/devworkspace_controller.go +++ b/controllers/workspace/devworkspace_controller.go @@ -360,6 +360,11 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request return r.failWorkspace(workspace, fmt.Sprintf("Failed to mount ServiceAccount tokens to workspace: %s", err), metrics.ReasonBadRequest, reqLogger, &reconcileStatus), nil } + // Add SSH ask-pass script into devfile containers + if err := wsprovision.ProvisionSshSshAskPass(clusterAPI, workspace.Namespace, devfilePodAdditions); err != nil { + return r.failWorkspace(workspace, fmt.Sprintf("Failed to mount SSH askpass script to workspace: %s", err), metrics.ReasonBadRequest, reqLogger, &reconcileStatus), nil + } + // Add automount resources into devfile containers err = automount.ProvisionAutoMountResourcesInto(devfilePodAdditions, clusterAPI, workspace.Namespace, home.PersistUserHomeEnabled(workspace)) if shouldReturn, reconcileResult, reconcileErr := r.checkDWError(workspace, err, "Failed to process automount resources", metrics.ReasonBadRequest, reqLogger, &reconcileStatus); shouldReturn { diff --git a/pkg/library/env/workspaceenv.go b/pkg/library/env/workspaceenv.go index 9c0dff7b1..d65ca4ef4 100644 --- a/pkg/library/env/workspaceenv.go +++ b/pkg/library/env/workspaceenv.go @@ -19,7 +19,7 @@ import ( "fmt" "os" - "github.com/devfile/devworkspace-operator/pkg/provision/automount" + "github.com/devfile/devworkspace-operator/pkg/provision/workspace" dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" @@ -82,20 +82,27 @@ func commonEnvironmentVariables(workspaceWithConfig *common.DevWorkspaceWithConf Name: constants.DevWorkspaceIdleTimeout, Value: workspaceWithConfig.Config.Workspace.IdleTimeout, }, - { - Name: constants.DISPLAY, - Value: ":0", - }, { - Name: constants.SSHAskPass, - Value: automount.SshAskPassMountPath + automount.SshAskPassScriptFileName, - }, } envvars = append(envvars, GetProxyEnvVars(workspaceWithConfig.Config.Routing.ProxyConfig)...) + envvars = append(envvars, GetSshAskPassEnvVars()...) return envvars } +func GetSshAskPassEnvVars() []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: constants.SSHAskPass, + Value: fmt.Sprintf("%s%s", workspace.SshAskPassMountPath, workspace.SshAskPassScriptFileName), + }, + { + Name: constants.DISPLAY, + Value: ":0", + }, + } +} + func GetProxyEnvVars(proxyConfig *v1alpha1.Proxy) []corev1.EnvVar { if proxyConfig == nil { return nil diff --git a/pkg/library/ssh/event.go b/pkg/library/ssh/event.go index 72d609e05..80130e1e5 100644 --- a/pkg/library/ssh/event.go +++ b/pkg/library/ssh/event.go @@ -34,8 +34,8 @@ func AddSshAgentPostStartEvent(spec *v1alpha2.DevWorkspaceTemplateSpec) error { && if [ -f /etc/ssh/passphrase ] && command -v ssh-add >/dev/null; \ then ssh-agent | sed 's/^echo/#echo/' > $SSH_ENV_PATH \ && chmod 600 $SSH_ENV_PATH && . $SSH_ENV_PATH \ -&& ssh-add /etc/ssh/dwo_ssh_key < /etc/ssh/passphrase \ -&& echo ". ${SSH_ENV_PATH}" >> /home/user/.bashrc; fi` +&& ssh-add /etc/ssh/dwo_ssh_key < /etc/ssh/passphrase; fi \ +&& if [ -f /home/user/.bashrc ]; then echo ". ${SSH_ENV_PATH}" >> /home/user/.bashrc; fi` _, mainComponents, err := lifecycle.GetInitContainers(spec.DevWorkspaceTemplateSpecContent) for _, component := range mainComponents { if component.Container == nil { diff --git a/pkg/provision/automount/common.go b/pkg/provision/automount/common.go index b47f2765e..23ce1ce96 100644 --- a/pkg/provision/automount/common.go +++ b/pkg/provision/automount/common.go @@ -109,12 +109,7 @@ func getAutomountResources(api sync.ClusterAPI, namespace string) (*Resources, e return nil, err } - sshCMAutoMountResources, err := ProvisionSshAskPassScript(api, namespace) - if err != nil { - return nil, err - } - - return mergeAutomountResources(gitCMAutoMountResources, mergedResources, pvcAutoMountResources, sshCMAutoMountResources), nil + return mergeAutomountResources(gitCMAutoMountResources, mergedResources, pvcAutoMountResources), nil } func checkAutomountVolumesForCollision(podAdditions *v1alpha1.PodAdditions, automount *Resources) error { diff --git a/pkg/provision/automount/common_persistenthome_test.go b/pkg/provision/automount/common_persistenthome_test.go index 055ff30a6..159f05b95 100644 --- a/pkg/provision/automount/common_persistenthome_test.go +++ b/pkg/provision/automount/common_persistenthome_test.go @@ -58,7 +58,7 @@ func TestProvisionAutomountResourcesIntoPersistentHomeEnabled(t *testing.T) { err := ProvisionAutoMountResourcesInto(podAdditions, testAPI, testNamespace, true) - if assert.ErrorContains(t, err, "Created object") || !assert.NoError(t, err, "Unexpected error") { + if !assert.NoError(t, err, "Unexpected error") { return } assert.Truef(t, cmp.Equal(tt.Output.Volumes, podAdditions.Volumes, testDiffOpts), diff --git a/pkg/provision/automount/ssh-askpass.sh b/pkg/provision/workspace/ssh-askpass.sh similarity index 100% rename from pkg/provision/automount/ssh-askpass.sh rename to pkg/provision/workspace/ssh-askpass.sh diff --git a/pkg/provision/automount/ssh.go b/pkg/provision/workspace/ssh.go similarity index 56% rename from pkg/provision/automount/ssh.go rename to pkg/provision/workspace/ssh.go index 26e10a9f9..9c0866628 100644 --- a/pkg/provision/automount/ssh.go +++ b/pkg/provision/workspace/ssh.go @@ -13,11 +13,13 @@ // limitations under the License. // -package automount +package workspace import ( _ "embed" + "path" + "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" "github.com/devfile/devworkspace-operator/pkg/constants" "github.com/devfile/devworkspace-operator/pkg/dwerrors" "github.com/devfile/devworkspace-operator/pkg/provision/sync" @@ -32,15 +34,23 @@ const SshAskPassScriptFileName = "ssh-askpass.sh" //go:embed ssh-askpass.sh var data string -func ProvisionSshAskPassScript(api sync.ClusterAPI, namespace string) (*Resources, error) { +func ProvisionSshSshAskPass(api sync.ClusterAPI, namespace string, podAdditions *v1alpha1.PodAdditions) error { sshAskPassConfigMap := constructSshAskPassCM(namespace) if _, err := sync.SyncObjectWithCluster(sshAskPassConfigMap, api); err != nil { - return nil, dwerrors.WrapSyncError(err) + switch err.(type) { + case *sync.NotInSyncError: // Ignore the object created error + default: + return dwerrors.WrapSyncError(err) + } } - resources := flattenAutomountResources([]Resources{ - getAutomountConfigmap(SshAskPassMountPath, constants.DevWorkspaceMountAsSubpath, pointer.Int32(0755), sshAskPassConfigMap), - }) - return &resources, nil + + sshAskPassVolumeMounts, sshAskPassVolumes, err := getSshAskPassVolumesAndVolumeMounts() + if err != nil { + return err + } + podAdditions.VolumeMounts = append(podAdditions.VolumeMounts, sshAskPassVolumeMounts...) + podAdditions.Volumes = append(podAdditions.Volumes, sshAskPassVolumes...) + return nil } func constructSshAskPassCM(namespace string) *corev1.ConfigMap { @@ -60,3 +70,25 @@ func constructSshAskPassCM(namespace string) *corev1.ConfigMap { } return askPassConfigMap } + +func getSshAskPassVolumesAndVolumeMounts() ([]corev1.VolumeMount, []corev1.Volume, error) { + name := "ssh-askpass" + volume := corev1.Volume{ + Name: name, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: constants.SshAskPassConfigMapName, + }, + DefaultMode: pointer.Int32(0755), + }, + }, + } + volumeMount := corev1.VolumeMount{ + Name: name, + ReadOnly: true, + MountPath: path.Join(SshAskPassMountPath, SshAskPassScriptFileName), + SubPath: SshAskPassScriptFileName, + } + return []corev1.VolumeMount{volumeMount}, []corev1.Volume{volume}, nil +} diff --git a/project-clone/Dockerfile b/project-clone/Dockerfile index fe9d762f7..b5a5b28de 100644 --- a/project-clone/Dockerfile +++ b/project-clone/Dockerfile @@ -44,14 +44,10 @@ COPY --from=builder /project-clone/_output/bin/project-clone /usr/local/bin/proj ENV USER_UID=1001 \ USER_NAME=project-clone \ - HOME=/home/user \ - DISPLAY=":0" \ - SSH_ASKPASS=/usr/local/bin/ssh-askpass.sh + HOME=/home/user COPY build/bin /usr/local/bin -COPY pkg/provision/automount/ssh-askpass.sh /usr/local/bin RUN /usr/local/bin/user_setup -RUN chmod +x /usr/local/bin/ssh-askpass.sh USER ${USER_UID}