diff --git a/api/v1/devcontainerapp_types.go b/api/v1/devcontainerapp_types.go index 50e84ce..35c9cd2 100644 --- a/api/v1/devcontainerapp_types.go +++ b/api/v1/devcontainerapp_types.go @@ -65,6 +65,10 @@ type StatefulSetSpec struct { Image string `json:"image"` Command []string `json:"command"` + // +kubebuilder:validation:MinItems=1 + // 至少包含一个 SSH Public Key 才能通过校验规则 + SSHPublicKeyList []string `json:"sshPublicKeyList"` + // +kubebuilder:validation:Minimum=1 // +optional ContainerPort uint16 `json:"containerPort,omitempty"` diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 89ca8ce..3c94a77 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -168,6 +168,11 @@ func (in *StatefulSetSpec) DeepCopyInto(out *StatefulSetSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.SSHPublicKeyList != nil { + in, out := &in.SSHPublicKeyList, &out.SSHPublicKeyList + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetSpec. diff --git a/config/crd/bases/devcontainer.devstar.cn_devcontainerapps.yaml b/config/crd/bases/devcontainer.devstar.cn_devcontainerapps.yaml index eb00683..3478273 100644 --- a/config/crd/bases/devcontainer.devstar.cn_devcontainerapps.yaml +++ b/config/crd/bases/devcontainer.devstar.cn_devcontainerapps.yaml @@ -76,9 +76,16 @@ spec: type: integer image: type: string + sshPublicKeyList: + description: 至少包含一个 SSH Public Key 才能通过校验规则 + items: + type: string + minItems: 1 + type: array required: - command - image + - sshPublicKeyList type: object successfulJobsHistoryLimit: description: |- diff --git a/config/samples/devcontainer_v1_devcontainerapp.yaml b/config/samples/devcontainer_v1_devcontainerapp.yaml index 2f5616b..288ac0f 100644 --- a/config/samples/devcontainer_v1_devcontainerapp.yaml +++ b/config/samples/devcontainer_v1_devcontainerapp.yaml @@ -1,7 +1,7 @@ apiVersion: devcontainer.devstar.cn/v1 kind: DevcontainerApp metadata: - name: daimingchen-devstar-beef092a69c011ef9c00000c2952a362 + name: studio-test namespace: devstar-studio-ns labels: app.kubernetes.io/name: devcontainer-operator @@ -12,8 +12,11 @@ spec: command: - /bin/bash - -c - - echo 'root:root' | chpasswd && useradd -m -s /bin/bash username && echo 'username:password' | chpasswd && usermod -aG sudo username && apt-get update && apt-get install -y openssh-server && service ssh start && apt-get clean && tail -f /dev/null + - apt-get update && apt-get install -y openssh-server && service ssh start && apt-get clean && tail -f /dev/null containerPort: 22 + sshPublicKeyList: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7TXcmW9GNAUou+s1PgBcJlZkw0xZ1ZxLktfsVKvsllYhpjYL7CTgUkl+t5GCvUdBvjQkoOGjenHj7VO3fkF43cFWsHPgBqIFMNDCXHfafbw7OCaKSyPb1Bn+y4mypoYhSy6YirGKSnC/Vw32VK9rtGpBuQse6KvJCMq34wOmdt7Em1vWYWxZaAkDNYUjrmY6/7bjSgUYWNlHx/kM8YQ4gluuackotAHaDo1owCK9dc9FZX2XUZcCJZVVRxCr0LRiyQqfO4s/YIUAetDmE0PP/FKc6lotRZGoNS9t1XSrMRVApF8V2+IgWNDMIzqtap/waMSNhSAOZtiyzx/VjLk92Bm8LPYpv3M1gsoQBZlp1lKstxDjhApq/H5pHOFVNGWPGW4rW5XB8F+Yrwg1PUvV/rBolG73BUAQF+V9UpV4SGKRZtzcOyTPwVZYJx9M5zF6NKAi5Dw8HXqDEvm/r6xc2Ak47NCfikdE3Szd4FZHUJrMY24bv1W4eiON7hHul8e8= TempSessionSSHPublicKey + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDhhM6sByTFz/45YbUBNdziONY1zRdy2CQ/klUJ/MEPeJ7f2mWj3Ek3A9shGGT0sKMTiwQwGgRNYG+RsENtHm+b6yp3QMngdy3GCRlEUNSVdLHdgBCpuHKzD0ELgZSa7NIOR9A0IucxxDQAT3iPcyK0bV0ruhDnO/glSfFN0Kv/75Yehu4UUI4EkSK9kInsVbtwh/9rJJn5BiE3YXn591eYfC8KX7oryXuLw433kQzWp49v4dlpDp2ZZnoxB9qZYV95S6kDFt2XizB8hS5yJ9S2gxtRz2Far5XHNw+Hu3uJgPcvp616xfg5b7qBpRpla9yNU4J/s5w682/ahMxokoK0rP/VMNFqIx/WhQ1sgReCOu5cXzUukVDpLM+ehyvw9MYzvu6Oo/Kq3nliKGwD9a9w90Eq2C33HWOA3rUhJelGRVuFb3tea56QjLstzCY2ijjOozBg/5qilK7t86XyTfvGg7y9WPo3KaIQcPU2ZK6yZWATDp1FXbLCERRZldOPY58= YetAnotherTempSSHPublicKey service: servicePort: 22 # nodePort: 30000 # 建议动态分配,不建议写入固定 NodePort 值 diff --git a/internal/controller/devcontainerapp_controller.go b/internal/controller/devcontainerapp_controller.go index 34696f6..51eba49 100644 --- a/internal/controller/devcontainerapp_controller.go +++ b/internal/controller/devcontainerapp_controller.go @@ -95,7 +95,7 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ logger.Error(err, "Failed to update DevcontainerApp.Status.Ready", "DevcontainerApp.Status.Ready", app.Status.Ready) return ctrl.Result{}, err } - logger.Info("DevContainer is now ready", "ReadyReplicas", statefulSetInNamespace.Status.ReadyReplicas) + logger.Info("DevContainer is READY", "ReadyReplicas", statefulSetInNamespace.Status.ReadyReplicas) } else { app.Status.Ready = false if err := r.Status().Update(ctx, app); err != nil { diff --git a/internal/controller/templates/statefulset.yaml b/internal/controller/templates/statefulset.yaml index 9aa2848..6319e21 100644 --- a/internal/controller/templates/statefulset.yaml +++ b/internal/controller/templates/statefulset.yaml @@ -19,6 +19,23 @@ spec: app: {{.ObjectMeta.Name}} devstar-resource-type: devstar-devcontainer spec: + # 安全策略,禁止挂载 ServiceAccount Token + automountServiceAccountToken: false + volumes: + - name: root-ssh-dir + emptyDir: {} + initContainers: + - name: init-root-ssh-dir + image: {{.Spec.StatefulSet.Image}} + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - {{range .Spec.StatefulSet.SSHPublicKeyList}} echo "{{.}}" >> /root/.ssh/authorized_keys && {{end}} chmod -R 700 /root/.ssh/ && echo 'SSH Public Key(s) imported.' + # 注意,必须递归设置 ~/.ssh/ 目录下权限 700,否则即使配置了 ~/.ssh/authorized_keys 也不会生效 + volumeMounts: + - name: root-ssh-dir + mountPath: /root/.ssh containers: - name: {{.ObjectMeta.Name}} image: {{.Spec.StatefulSet.Image}} @@ -27,6 +44,7 @@ spec: - {{.}} {{end}} imagePullPolicy: IfNotPresent + # securityContext: TODO: 设置 DevContainer 安全策略 ports: - name: ssh-port protocol: TCP @@ -34,6 +52,8 @@ spec: volumeMounts: - name: pvc-devcontainer mountPath: /data + - name: root-ssh-dir + mountPath: /root/.ssh livenessProbe: exec: command: