diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index e4b2e0a8..3ba38b6f 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -27,6 +27,38 @@ services: volumes: - shared:/shared - sshconfig_publickey:/config + + host-k8s-proxy: + build: ./kubetools + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ../plugin/kubernetes/crd.yaml:/kubernetes/crd.yaml:ro + - ./k8sworkload.yaml:/kubernetes/workload.yaml:ro + # networks: + # - kind + # - default + command: + - bash + - -c + - | + # kind delete cluster -n sshpipertest && + (kind get kubeconfig -q -n sshpipertest || kind create cluster -n sshpipertest) && + docker network connect kind $$(hostname) && # self contain + docker network connect e2e_default sshpipertest-control-plane + kind export kubeconfig -n sshpipertest --internal + kind load docker-image -n sshpipertest e2e_piper-imageonly && + kubectl wait --for=condition=ready pod -A --all --timeout=2m && + kubectl apply -f /kubernetes/crd.yaml && + kubectl apply -f /kubernetes/workload.yaml && + #kubectl set image deployment/sshpiper-deployment sshpiper=e2e_piper-imageonly && + kubectl delete pod -l app=sshpiper && + kubectl wait deployment --all --for condition=Available=True + kubectl port-forward service/sshpiper --pod-running-timeout=2m --address 0.0.0.0 2222:2222 + privileged: true + depends_on: + - host-publickey + - host-password + - piper-imageonly testrunner: environment: @@ -48,6 +80,7 @@ services: depends_on: - host-publickey - host-password + - host-k8s-proxy # ensure sshpiperd image works piper-imageonly: @@ -63,4 +96,8 @@ volumes: sshconfig_publickey: - sshconfig_password: \ No newline at end of file + sshconfig_password: + +# networks: +# kind: +# external: true \ No newline at end of file diff --git a/e2e/docker_test.go b/e2e/docker_test.go index 6f5eae07..764feaf3 100644 --- a/e2e/docker_test.go +++ b/e2e/docker_test.go @@ -68,45 +68,7 @@ func TestDocker(t *testing.T) { keyfile := path.Join(keyfiledir, "key") - if err := os.WriteFile(keyfile, []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -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 ------END OPENSSH PRIVATE KEY----- -`), 0400); err != nil { + if err := os.WriteFile(keyfile, []byte(testprivatekey), 0400); err != nil { t.Errorf("failed to write to test key: %v", err) } diff --git a/e2e/k8sworkload.yaml b/e2e/k8sworkload.yaml new file mode 100644 index 00000000..eeb0f7d8 --- /dev/null +++ b/e2e/k8sworkload.yaml @@ -0,0 +1,134 @@ +# sshpiper service +--- +apiVersion: v1 +kind: Service +metadata: + name: sshpiper +spec: + selector: + app: sshpiper + ports: + - protocol: TCP + port: 2222 +--- +apiVersion: v1 +data: + server_key: | + LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUJsd0FBQUFkemMyZ3RjbgpOaEFBQUFBd0VBQVFBQUFZRUFxNEVNbmlFR3ZXTXNSNEdqWDc4UWRNcUxjVHlhRTNWSUlLMU5KdmpZaDFnUUtyZnU3OUI2Ckx2N3ZpOUl0SHNjQmRGTEhEYW5od0ZzdWw4MjRibkJ0dlgya3ZjbzY0eFpKcC9nZ0R2NUhUV2svQ0Fkek5TTWxTVjlERXIKcW9kTUlEYmJ1WWxoSXBBNEVKeVpqbEFmQWFtTlFtZGdHVmtMdzlVN1NiN3BPUnovWlVRZ0NkcU1KQjU4NlYzYmRoZGVudgp3NVQ4WnhnZGlQMzlhblpkdjV3TTQyOU8vT2Rjb0VEcFpxWDlpYVJUbGdwdUZBOWp0b1IrbzNyRjZzNFUyNS9XbXdHeHU1CnNaQVdncjBBTjgwSTZEVEZjN0cvUG9nSFpUek5ZcGNzdHZiY21leXV1bmFnUE83RXA5OWt3dEQ5UVdCUDFFZXFrSk0wdjAKL1ViT1l3aDY4QnIzT2t5SXVPak9CTU5OYkRpRkU2eXFENlI4bTY1MWpSZHg1eFVnckpjQjEzK2pzbi9sVFo0LzQ1L3VQQQpBNy8xUy9sV0V5OHRHdzVNSVZPWUd4L2h2cXdVSmJnUndCc1NVNExsUEVLRXp3d1FHeEw1b09QaWdJYmszNUhYaWowd2J0CjB4TWRiOHgybVl2Mzl4ZDZBWGllTGVGc1VLYmtZbW1USmhmRlJkSjdBQUFGaUltZ2Z3MkpvSDhOQUFBQUIzTnphQzF5YzIKRUFBQUdCQUt1QkRKNGhCcjFqTEVlQm8xKy9FSFRLaTNFOG1oTjFTQ0N0VFNiNDJJZFlFQ3EzN3UvUWVpNys3NHZTTFI3SApBWFJTeHcycDRjQmJMcGZOdUc1d2JiMTlwTDNLT3VNV1NhZjRJQTcrUjAxcFB3Z0hjelVqSlVsZlF4SzZxSFRDQTIyN21KCllTS1FPQkNjbVk1UUh3R3BqVUpuWUJsWkM4UFZPMG0rNlRrYy8yVkVJQW5hakNRZWZPbGQyM1lYWHA3OE9VL0djWUhZajkKL1dwMlhiK2NET052VHZ6blhLQkE2V2FsL1lta1U1WUtiaFFQWTdhRWZxTjZ4ZXJPRk51ZjFwc0JzYnViR1FGb0s5QURmTgpDT2cweFhPeHZ6NklCMlU4eldLWExMYjIzSm5zcnJwMm9EenV4S2ZmWk1MUS9VRmdUOVJIcXBDVE5MOVAxR3ptTUlldkFhCjl6cE1pTGpvemdURFRXdzRoUk9zcWcra2ZKdXVkWTBYY2VjVklLeVhBZGQvbzdKLzVVMmVQK09mN2p3QU8vOVV2NVZoTXYKTFJzT1RDRlRtQnNmNGI2c0ZDVzRFY0FiRWxPQzVUeENoTThNRUJzUythRGo0b0NHNU4rUjE0bzlNRzdkTVRIVy9NZHBtTAo5L2NYZWdGNG5pM2hiRkNtNUdKcGt5WVh4VVhTZXdBQUFBTUJBQUVBQUFHQWE2ZDc5aDZoRG15Y05ONkpZT2FjTzlPUUtDCnAwUk5hUHlnTSt0TUhybVRtTUhHU00xWGcxMmg0bzI4bTRqT002Wkh3NWVyZ3lmdjQ5aHdpWlJxbklHUFF2WHZyOGIrTmoKcE00NXdXK1g3bDJzTlN3SUEwam1kT0laUmo1bzA3R2RXVm95YzdFK2tYYUVZRWxiSnhaQ2U4QmZ6QjgrZFRYVUFTRVQ2SApRMVNTZEV5SkYrWlpwYXFGbWk5U1BSUjZUcTNnZzlUN0Z4aUxaMlJrZTZuVFlsV1BaYnpLQ21JZW5kR0pRRlRFc2NOTWlqClJIQk1sUnNpS3hnNytDSVlNYXhva0o4MUI3N2lJUTFTVmRzaXpnVTZ5eklERDRPOGlqTVdmVVVaZ3FoY3FYTnp6T3NpZTEKRXVEdkk1ZlpVNGRuVU1MdmxEZGMxUGUyS09BSVFTVnlrNCtHWGFMZEl0SzE4TnhjdmEvM255SVNKMWFCQXV4YkNRQkdRYQpycmRZUitNdndJdkRlbndyTUs0bWtWR2w2NnBySTZRdW56bU9vN01OUXlkODlLQ1RBblJjWlhVNCtkZnZWaVJubFRlK3VZCnZtbE5sc1hhOEpRZjlvRlV3a1VLZmxRdnovZ0NrdXFqdkNsamxrZThxM3VTa05MMXhDTVpQRkJSTEd4WWdlWjNEeEFBQUEKd0RrakpPQjlVMXNMRDFrUzc4ZlNObm9tbGRXaFFQeGxKa1JYUk80MjJqYXZ5OThMb1JWOWpNU2N0R3JpODljTHFFcEV5dApsSHVVTjNJSU1rU1RVcFhtS3NNVXB2SnBZMmpHYUs2SlhKMGR1VG4rbDNQd3gzVU05TW0zOFY4R3BablFWMmMydmlXeTNqCmU2c1hrWDVwV01WRHpqZHd1b0c4c1JrYTZ1TnM0d1N3a0RKdXIrLzh4WnczM0k1eVJCd2M3bHBBczZBMVUvNnZDVGJiQ0kKb0QwMWcvTEtldVpHRjNYcWRLMXhqc2xTZmR5TERBMGNLYzRITXpnUkYwckVGMWtBQUFBTUVBMDAyL3lsaEkzVXdPRU01LwpjQUlBanJSZC9FQjdMUE5zVldGNjdaZEFMVXRrRmVVMGlsY3ZaaUxJMlMwYkJqVXUwUWtCMW5SU3pFamdGSTVldGY5eWs4CnRiSHFGa1htUnNwbGtKUEhRU09QL1ByMWNzb1o0QXlGWWhJOE9ucHkzNVVyNnZlNGQxeHR6RURLWmdMOWo5QTlFKzdwUUgKdWVZZ3pvTUJacXNhcGdsaXJjWDhtQXRiREQ2SFdOMjlrZm1VYjlRYi91aURFb3h2WmtVMmhvVTNZOHI4YXN3dVhCU3JTaAp5TkdQQjQxSitpelUyM0pQS0IyeVZ5VS9SNlRaaWZBQUFBd1FEUHlCOUFoNUNucEVRUGY3WCtIU29jVzJYUis4L3BJM0NSCmpyT0diS0dMUGhaMldxeUlaOW5WRmRoSmY4TXgyVlVzeHJyL3paUGlzd1ZiZ2pkczE0d0EzYUJrT2RwbkhHbWFTM0lCRUgKN2g5d0NlaFl6Z0htS0t0T1oxRWhSWjFaQmEzU0dnMlp2d3lXRVBOM0RRK0l0QUsyaWllQm9UbFpmS0pieWpwWEhNL2tPcApmSUZFVm5QbTFDa1dyb3NBOGlVUXBWMzhWbGk0ZXAyWU95NVJCMFo3UGlyek5PSFdsTHFicEVWV0F2QjVPU3ljV0lGWTBrCkJZdnB3Q01zMEZES1VBQUFBTlltOXNhV0Z1UUhWaWRXNTBkUUVDQXdRRkJnPT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg== +kind: Secret +metadata: + name: sshpiper-server-key +type: Opaque +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sshpiper-deployment + labels: + app: sshpiper +spec: + replicas: 1 + selector: + matchLabels: + app: sshpiper + template: + metadata: + labels: + app: sshpiper + spec: + serviceAccountName: sshpiper-account + containers: + - name: sshpiper + imagePullPolicy: Never + image: e2e_piper-imageonly + ports: + - containerPort: 2222 + env: + - name: PLUGIN + value: "kubernetes" + - name: SSHPIPERD_SERVER_KEY + value: "/serverkey/ssh_host_rsa_key" + - name: SSHPIPERD_LOG_LEVEL + value: "trace" + volumeMounts: + - name: sshpiper-server-key + mountPath: "/serverkey/" + readOnly: true + volumes: + - name: sshpiper-server-key + secret: + secretName: sshpiper-server-key + items: + - key: server_key + path: ssh_host_rsa_key +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: sshpiper-reader +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] +- apiGroups: ["sshpiper.com"] + resources: ["pipes"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: read-sshpiper +subjects: +- kind: ServiceAccount + name: sshpiper-account +roleRef: + kind: Role + name: sshpiper-reader + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sshpiper-account + +# pipe to a password based sshd +--- +apiVersion: sshpiper.com/v1beta1 +kind: Pipe +metadata: + name: pipe-password +spec: + from: + - username: "pass" + to: + host: host-password:2222 + username: "user" + ignore_hostkey: true +--- + +# pipe to a key based sshd +--- +apiVersion: v1 +data: + privatekey: | + LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUJsd0FBQUFkemMyZ3RjbgpOaEFBQUFBd0VBQVFBQUFZRUExYzZJYW5VVTdrK3ZrcjJuSEVYUFhwb3I2ZStBc2xhenRXM29scXhqcnRJRnN1bktIQXBLCkhSVUYydEtvdWIzR0R1VTErTlBqNzRNREpUV0wwTUMyNTdiNTFNUnlOaCsxTXBnU2tDdG84dWhZN2ZvUVJMeFFVV3dvaTkKTnZXRVlpUk4zM3hqR05vTE9LNUwrWmMxNmpDWm9OaDZwOEFKN09hQ1ZsZFU2UlZkaFFhUERScndEbDNGR3R6YnBQNXdpcgpWYnE1MnFleHFHUTl2d2dJU2Nic1cxdnUyTm5CckxmT3hGK0JMSlBLZkVCZmdZdVVaUS9RTE5ybTVYT1d5REtWd09LNjBDCm5PWUVhdzdhaDZJMzFxclhhMEtrSllOYVFUaXg4bnU1VWtYSDhZUnU2bU84YzcySjVGc2R0eWp0clMyK1ZncnFSdmxlMEUKU1JhTEdNTHJRUUtxYVRLVFV1dEZuNVJQcHNwbEZYL3FiUzU5NkVReFJHcGFOWkNaTXBuZXJzcWZnVDJZS3hrazdmZzh4MAp5TUtDZlVhTU1BVlUxTnJDczlkMW9UL3VreW4vTmlJY296cktYaW8yem95MUNDUDdTK091Ty8rMS9WV2pyN3llVUxlYkR3CkhYTUpPNTBqMzVDUksvMVBRb1oxRFNoSitoOVhqWnR1bldhWk80WWxBQUFGaU9PZ2RDRGpvSFFnQUFBQUIzTnphQzF5YzIKRUFBQUdCQU5YT2lHcDFGTzVQcjVLOXB4eEZ6MTZhSytudmdMSldzN1Z0Nkphc1k2N1NCYkxweWh3S1NoMFZCZHJTcUxtOQp4ZzdsTmZqVDQrK0RBeVUxaTlEQXR1ZTIrZFRFY2pZZnRUS1lFcEFyYVBMb1dPMzZFRVM4VUZGc0tJdlRiMWhHSWtUZDk4Cll4amFDeml1Uy9tWE5lb3dtYURZZXFmQUNlem1nbFpYVk9rVlhZVUdqdzBhOEE1ZHhScmMyNlQrY0lxMVc2dWRxbnNhaGsKUGI4SUNFbkc3RnRiN3RqWndheTN6c1JmZ1N5VHlueEFYNEdMbEdVUDBDemE1dVZ6bHNneWxjRGl1dEFwem1CR3NPMm9laQpOOWFxMTJ0Q3BDV0RXa0U0c2ZKN3VWSkZ4L0dFYnVwanZITzlpZVJiSGJjbzdhMHR2bFlLNmtiNVh0QkVrV2l4akM2MEVDCnFta3lrMUxyUlorVVQ2YktaUlYvNm0wdWZlaEVNVVJxV2pXUW1US1ozcTdLbjRFOW1Dc1pKTzM0UE1kTWpDZ24xR2pEQUYKVk5UYXdyUFhkYUUvN3BNcC96WWlIS002eWw0cU5zNk10UWdqKzB2anJqdi90ZjFWbzYrOG5sQzNtdzhCMXpDVHVkSTkrUQprU3Y5VDBLR2RRMG9TZm9mVjQyYmJwMW1tVHVHSlFBQUFBTUJBQUVBQUFHQUZmK05DNThHUzBySm5zaUNwQ2NPb2dZczFJCkgrOU5wMDNRcjA3bVBJVWRsc0dxOXhTeGRIN3R3VjRTRGhtVkxNU1FZT1dvNjZtZzhaeUw5TXBtcmRwdE90dXRXSGhzZ1cKWmFFOTc3VjNzOTV5SC9JbHNGekx5c1RkR3gzakMrc1RaWkNOQ01oYWNSbG9CZ2NzcTdFbUJ6dmhmbjd0Q1VkTnAydUpsOQp0QW10dUowbkpNc0x2ZjZwNUF5clVMdVpLcnhrTlRFZ3RFL1RWcklQZWJtck9yNSs1NmtiYzk5UjVvV000V3hWWmpkQXRQCmlFMnJOQWEvZlkzOFNjbHR6eVZkRU5YZlhiYlBiR3hMenFWUjFoTWwyeDdkOXBGTE1IRDJxRmNhalpiOWx0SzJnOXkxTmcKRWdOU3F3cE5UK2VYWTIxRnBFc0tXbzVWM0xTeG1ENUdsQkdPc2hLZFVOdDRqRFdjR2xVekNJUWduaU5RME5JQ3pIZTBOWQpqWk1TK3lyb1VOV0tNYVJob1d5aVJVcWJENGpXUHVMbGdYbjhNVnJ6MXluK1Y3TkN2SVpYNG5KZWIreXhpUndFRVFTT1hBCmQzcE4yRk1yVEpVeXRVanQ1dU9lOUtEQlA5Q3Myc0ZJcG5tM2dmUFNVSlNEc2tWdHRXZ1ZHVFNPRFRsYVRqR241aEFBQUEKd0VwS3VFWE5aeDIyclkwWmJLZW5KQ3F0Z1dyYUtBUEVjVDA3azJKeXl4ck5zazhFSlJKNjBCL1pja2ZDTS95UTErcVVTSgpBbnhvS0NXWjdyaEdWcE1KbEVKN3ZGcWExbFBDb1Nld3VGM0FRRjgzVDQybVhQTC9nTlVqekxvVTdCR3ZMZ2VxNzU0azFGCnJwK28yb0tzd2N5ZHMwZnlyTFdCdFlsZmFyUVVINmYwTzBiUUZWUlFjMkRjTyt5Y243UFVVSDAzcHEwZ094cXpQKzZOVEQKTjliMWNIMUE3eFlPL0ZDRDZuNnhEQ0hjSmVNRnFDb1hsbTRFWUpDUnY5Z0ZLYW9BQUFBTUVBL0lqdmw0VlpjNnFvYzh2Qwp4NlA3WGVUbzFyKzZEa1B3cXFoY25PRnBIMDJZeGVtM1Z3RDdCM1BieXZybmhVTkFyQ0VyMXh5eU05SlFLY1ZESnB0NEpzCmlsZVp1N1BLb09JdWw4MytHeGxSQ2daSHJwbDdQYld0TURRVmh5M3FQQTRjTERONmo2TDRRcm0xVUxjUm1PSU8xRzdtSHMKdStySnFPNURoZmI5MS80SlRIQWxJdWI5a0ZGM0hQMnlHZUEyRDBSWjRtVUd2RlYySUVMUXhWMXRnZ2xiOHIyNWdFSUhycwpOQmlnMXR3anFIcmlqWmMrQlVvMUNvRVhpWFk0bE5BQUFBd1FEWXZZOFpsSUdPenRKcVo4MkQrckh1QWx1eEZiNFh1bUJCClVwUWVybktLNVplME9kcWhrQ1VEN2QzQWk4RkZ4MlZ4STVMWTRqcDZWb01KaUY1MlRrVFE4ZXVKM3prYW1qL3UreDNxbzgKYjB5d0VIZWc0akFsSUoxSXYwNFArT1pPc3o5Y20zS2gwMk9uQXg2b1FpT29TTXYwMXFtdDlPMm5xRVU1V2N2VkEvUUZjTApYblJNeVpFOEg2MzJqMjZPU2hRM09vUk55aFZqeEJ2SzRpVUJXK3R3ek82YnFuVXlEaEtxaDIyVHVrSDErUkMzZ2RZcnFHCnNKYTE3RkF2ay94RGtBQUFBTlltOXNhV0Z1UUhWaWRXNTBkUUVDQXdRRkJnPT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg== +kind: Secret +metadata: + name: host-publickey-key +type: Opaque +--- +apiVersion: sshpiper.com/v1beta1 +kind: Pipe +metadata: + name: pipe-publickey +spec: + from: + - username: ".*" # catch all + username_regex_match: true + authorized_keys_data: "c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCZ1FEWndMdmN5eXFoWFhWZkxRU1hEdkFOMVQwZWQyNEVSRGFVUGdWS2xZaE5sR1RPNTh1TW1tc1gvOUc0SlRzZGlWSHFvR29OSDZ1a0Y4ZFNNMG1nWmdNT0dNdTE2VHdld2xqd01GcksrS1NZYTVaYzQ2Vnk1N2F6MFpFbml2WlZwY1RhdXpndHZwUTRjOXNhd3dVY2M5M0Y1eHdlZnNuTEl5eTJVc0s0SXhOeGFSV1NPMFdvanJGL3A2di9SaE1aeXZkcXlYUk9aVVl3aFRiUE1OZE1ZblROanY3YmVHL3dlR1Y3Wkhpc25TTzhiUDNjYStMVllkeVJINXhlMmp6Vm5HMmNjOHl5MUZZbjJOaHRLaUo5c1k5VFlCbndlSi8xNXZjbE9UY2xRMVBBa3pGZGt4WDM4aWM0VlhKNDhFREYwenR2cVdQeVpNQ2ZCQ2N4TGpHZVBwUW0xR1hRWU9udmthTEJPU1NNcDltRW9SZmUyZENmNjE4b3B1TTFjcEhxT2s2Z2RwZ3BKNXh5dzdFcUxVNWRVNmVYS1RrcCtoYXM4S01yRjN5SWo5R0drbFo3clNteENEWWVLMnZmY0FvT0RuWENuMjBBT2ZjMUdQZW5nSmJhL1ZUN3JiTmRUek4vZTYrTG15WHhmQThmbEVBN3VaUHF5WWtKKzVpTEFUYUdnTE09IGJvbGlhbkB1YnVudHUK" + to: + host: host-publickey:2222 + username: "user" + private_key_secret: + name: host-publickey-key + ignore_hostkey: true \ No newline at end of file diff --git a/e2e/kubernetes_test.go b/e2e/kubernetes_test.go new file mode 100644 index 00000000..f5f03410 --- /dev/null +++ b/e2e/kubernetes_test.go @@ -0,0 +1,98 @@ +package e2e_test + +import ( + "fmt" + "os" + "path" + "testing" + "time" + + "github.com/google/uuid" +) + +func TestKubernetes(t *testing.T) { + piperhost := "host-k8s-proxy" + piperport := "2222" + piperaddr := piperhost + ":" + piperport + waitForEndpointReadyWithTimeout(piperaddr, time.Minute*5) + + t.Run("password", func(t *testing.T) { + randtext := uuid.New().String() + targetfie := uuid.New().String() + + c, stdin, stdout, err := runCmd( + "ssh", + "-v", + "-o", + "StrictHostKeyChecking=no", + "-o", + "UserKnownHostsFile=/dev/null", + "-p", + piperport, + "-l", + "pass", + piperhost, + fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie), + ) + + if err != nil { + t.Errorf("failed to ssh to piper-fixed, %v", err) + } + + defer killCmd(c) + + enterPassword(stdin, stdout, "pass") + + time.Sleep(time.Second) // wait for file flush + + checkSharedFileContent(t, targetfie, randtext) + }) + + t.Run("key", func(t *testing.T) { + + keyfiledir, err := os.MkdirTemp("", "") + if err != nil { + t.Errorf("failed to create temp key file: %v", err) + } + + keyfile := path.Join(keyfiledir, "key") + + if err := os.WriteFile(keyfile, []byte(testprivatekey), 0400); err != nil { + t.Errorf("failed to write to test key: %v", err) + } + + if err := os.WriteFile("/sshconfig_publickey/.ssh/authorized_keys", []byte(`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVzohqdRTuT6+SvaccRc9emivp74CyVrO1beiWrGOu0gWy6cocCkodFQXa0qi5vcYO5TX40+PvgwMlNYvQwLbntvnUxHI2H7UymBKQK2jy6Fjt+hBEvFBRbCiL029YRiJE3ffGMY2gs4rkv5lzXqMJmg2HqnwAns5oJWV1TpFV2FBo8NGvAOXcUa3Nuk/nCKtVurnap7GoZD2/CAhJxuxbW+7Y2cGst87EX4Esk8p8QF+Bi5RlD9As2ublc5bIMpXA4rrQKc5gRrDtqHojfWqtdrQqQlg1pBOLHye7lSRcfxhG7qY7xzvYnkWx23KO2tLb5WCupG+V7QRJFosYwutBAqppMpNS60WflE+mymUVf+ptLn3oRDFEalo1kJkymd6uyp+BPZgrGSTt+DzHTIwoJ9RowwBVTU2sKz13WhP+6TKf82IhyjOspeKjbOjLUII/tL4647/7X9VaOvvJ5Qt5sPAdcwk7nSPfkJEr/U9ChnUNKEn6H1eNm26dZpk7hiU=`), 0400); err != nil { + t.Errorf("failed to write to authorized_keys: %v", err) + } + + randtext := uuid.New().String() + targetfie := uuid.New().String() + + c, _, _, err := runCmd( + "ssh", + "-v", + "-o", + "StrictHostKeyChecking=no", + "-o", + "UserKnownHostsFile=/dev/null", + "-p", + piperport, + "-l", + "anyuser", + "-i", + keyfile, + piperhost, + fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie), + ) + + if err != nil { + t.Errorf("failed to ssh to piper-fixed, %v", err) + } + + defer killCmd(c) + + time.Sleep(time.Second) // wait for file flush + + checkSharedFileContent(t, targetfie, randtext) + }) +} diff --git a/e2e/kubetools/Dockerfile b/e2e/kubetools/Dockerfile new file mode 100644 index 00000000..5248c6ea --- /dev/null +++ b/e2e/kubetools/Dockerfile @@ -0,0 +1,24 @@ +FROM ubuntu + +RUN apt-get update && apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + lsb-release + +RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.16.0/kind-linux-amd64 && \ + chmod +x ./kind && \ + mv ./kind /bin/kind + +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ + chmod +x ./kubectl && \ + mv ./kubectl /bin/kubectl + +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + +RUN echo "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + +RUN apt-get update && apt-get install -y docker-ce-cli \ No newline at end of file diff --git a/e2e/main_test.go b/e2e/main_test.go index 26116dc0..7e257dea 100644 --- a/e2e/main_test.go +++ b/e2e/main_test.go @@ -20,9 +20,53 @@ import ( "github.com/creack/pty" ) +const testprivatekey = `-----BEGIN OPENSSH PRIVATE KEY----- +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 +-----END OPENSSH PRIVATE KEY----- +` + const waitTimeout = time.Second * 10 func waitForEndpointReady(addr string) { + waitForEndpointReadyWithTimeout(addr, waitTimeout) +} + +func waitForEndpointReadyWithTimeout(addr string, timeout time.Duration) { now := time.Now() for { if time.Since(now) > waitTimeout { diff --git a/plugin/kubernetes/sample.yaml b/plugin/kubernetes/sample.yaml index 98d07d50..12b37fe2 100644 --- a/plugin/kubernetes/sample.yaml +++ b/plugin/kubernetes/sample.yaml @@ -39,6 +39,7 @@ spec: serviceAccountName: sshpiper-account containers: - name: sshpiper + imagePullPolicy: IfNotPresent image: farmer1992/sshpiperd:latest ports: - containerPort: 2222 @@ -124,6 +125,7 @@ metadata: spec: containers: - name: host-password + imagePullPolicy: IfNotPresent image: lscr.io/linuxserver/openssh-server:latest ports: - containerPort: 2222 @@ -184,6 +186,7 @@ spec: containers: - name: host-publickey image: lscr.io/linuxserver/openssh-server:latest + imagePullPolicy: IfNotPresent ports: - containerPort: 2222 env: