Skip to content

Commit fa3e64e

Browse files
AObuchowdkwon17
authored andcommitted
fix: conditionally add SSH agent postStart event
Only add the SSH agent initialization postStart event if an SSH key with a passphrase is being used & experimental features are enabled. We don't use the config package's ExperimentalFeaturesEnabled function so that the SSH agent initialization postStart event injection can be enabled from an external DWOC, or the global DWOC if no external DWOC is used. fix #1340 Signed-off-by: Andrew Obuchowicz <[email protected]>
1 parent 00b1704 commit fa3e64e

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

controllers/workspace/devworkspace_controller.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,14 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request
281281
}
282282
workspace.Spec.Template = *flattenedWorkspace
283283

284-
err = ssh.AddSshAgentPostStartEvent(&workspace.Spec.Template)
285-
if err != nil {
286-
return r.failWorkspace(workspace, "Failed to add ssh-agent post start event", metrics.ReasonWorkspaceEngineFailure, reqLogger, &reconcileStatus), nil
284+
if workspace.Config.EnableExperimentalFeatures != nil && *workspace.Config.EnableExperimentalFeatures {
285+
if needsSSHAgentPostStartEvent, err := ssh.NeedsSSHPostStartEvent(clusterAPI, workspace.Namespace); err != nil {
286+
reqLogger.Error(err, "Error retrieving SSH secret")
287+
} else if needsSSHAgentPostStartEvent {
288+
if err = ssh.AddSshAgentPostStartEvent(&workspace.Spec.Template); err != nil {
289+
return r.failWorkspace(workspace, "Failed to add ssh-agent post start event", metrics.ReasonWorkspaceEngineFailure, reqLogger, &reconcileStatus), nil
290+
}
291+
}
287292
}
288293

289294
reconcileStatus.setConditionTrue(conditions.DevWorkspaceResolved, "Resolved plugins and parents from DevWorkspace")

pkg/constants/metadata.go

+9
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ const (
8787
// in a given namespace. It is used when e.g. adding Git credentials via secret
8888
GitCredentialsConfigMapName = "devworkspace-gitconfig"
8989

90+
// SSHSecretName is the name used for the secret that stores the SSH key data for workspaces in a given namespace.
91+
// TODO: This is a workaround for https://github.com/devfile/devworkspace-operator/issues/1340.
92+
// We do not enforce the SSH secret to have this name, but it is used by the Che Dashboard and this allows us
93+
// to detect if the user has provided an SSH key with a passhprase.
94+
SSHSecretName = "git-ssh-key"
95+
96+
// SSHSecretPassphraseKey is the key used to retrieve the optional passphrase stored inside the SSH secret.
97+
SSHSecretPassphraseKey = "passphrase"
98+
9099
SshAskPassConfigMapName = "devworkspace-ssh-askpass"
91100

92101
// GitCredentialsMergedSecretName is the name for the merged Git credentials secret that is mounted to workspaces

pkg/library/ssh/event.go

+30
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import (
1919
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
2020
"github.com/devfile/devworkspace-operator/pkg/constants"
2121
"github.com/devfile/devworkspace-operator/pkg/library/lifecycle"
22+
"github.com/devfile/devworkspace-operator/pkg/provision/sync"
23+
corev1 "k8s.io/api/core/v1"
24+
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
25+
"k8s.io/apimachinery/pkg/types"
2226
)
2327

2428
const commandLine = `(
@@ -63,3 +67,29 @@ func AddSshAgentPostStartEvent(spec *v1alpha2.DevWorkspaceTemplateSpec) error {
6367
}
6468
return err
6569
}
70+
71+
// Determines whether an SSH key with a passphrase is provided for the namespace where the workspace exists.
72+
// If an SSH key with a passphrase is used, then the SSH Agent Post Start event is needed for it to automatically
73+
// be used by the workspace's SSH agent.
74+
// If no SSH key is provided, or the SSH key does not provide a passphrase, then the SSH Agent Post Start event is not required.
75+
func NeedsSSHPostStartEvent(api sync.ClusterAPI, namespace string) (bool, error) {
76+
secretNN := types.NamespacedName{
77+
Name: constants.SSHSecretName,
78+
Namespace: namespace,
79+
}
80+
sshSecret := &corev1.Secret{}
81+
if err := api.Client.Get(api.Ctx, secretNN, sshSecret); err != nil {
82+
if k8sErrors.IsNotFound(err) {
83+
// No SSH secret found
84+
return false, nil
85+
}
86+
return false, err
87+
}
88+
89+
if _, ok := sshSecret.Data[constants.SSHSecretPassphraseKey]; ok {
90+
// SSH secret exists and has a passphrase set
91+
return true, nil
92+
}
93+
94+
return false, nil
95+
}

0 commit comments

Comments
 (0)