Skip to content

SSH Gateway #7412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions .werft/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const installerSlices = {
INSTALLER_POST_PROCESSING: "installer post processing",
APPLY_INSTALL_MANIFESTS: "installer apply",
DEPLOYMENT_WAITING: "monitor server deployment",
DNS_ADD_RECORD: "add dns record"
}

const vmSlices = {
Expand Down Expand Up @@ -303,6 +304,8 @@ export async function build(context, version) {
withVM,
};

exec(`kubectl --namespace keys get secret host-key -o yaml > /workspace/host-key.yaml`)

if (withVM) {
werft.phase(phases.VM, "Start VM");

Expand Down Expand Up @@ -431,6 +434,7 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
// in a VM, the secrets have alreay been copied
// If using core-dev, we want to execute further kubectl operations only in the created namespace
setKubectlContextNamespace(namespace, metaEnv({ slice: installerSlices.SET_CONTEXT }));
werft.done(installerSlices.SET_CONTEXT)
try {
werft.log(installerSlices.ISSUE_CERTIFICATES, "organizing a certificate for the preview environment...");

Expand Down Expand Up @@ -533,6 +537,21 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
werft.fail('authProviders', err);
}

werft.log("SSH gateway hostkey", "copy host-key from secret")
try {
exec(`cat /workspace/host-key.yaml \
| yq w - metadata.namespace ${namespace} \
| yq d - metadata.uid \
| yq d - metadata.resourceVersion \
| yq d - metadata.creationTimestamp \
| kubectl apply -f -`, { silent: true })
exec(`yq w -i ./config.yaml sshGatewayHostKey.kind "secret"`)
exec(`yq w -i ./config.yaml sshGatewayHostKey.name "host-key"`)
werft.done('SSH gateway hostkey');
} catch (err) {
werft.fail('SSH gateway hostkey', err);
}

// validate the config and cluster
exec(`/tmp/installer validate config -c config.yaml`, {slice: installerSlices.INSTALLER_RENDER});

Expand Down Expand Up @@ -595,6 +614,8 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
werft.fail(installerSlices.DEPLOYMENT_WAITING, err);
}

await addDNSRecord(deploymentConfig.namespace, deploymentConfig.domain, !withVM)

// TODO: Fix sweeper, it does not appear to be doing clean-up
werft.log('sweeper', 'installing Sweeper');
const sweeperVersion = deploymentConfig.sweeperImage.split(":")[1];
Expand Down Expand Up @@ -680,7 +701,7 @@ export async function deployToDevWithHelm(deploymentConfig: DeploymentConfig, wo
await issueMetaCerts(namespace, domain);
await installMetaCertificates(namespace);
werft.done('certificate');

await addDNSRecord(deploymentConfig.namespace, deploymentConfig.domain, false)
werft.done('prep');
} catch (err) {
werft.fail('prep', err);
Expand Down Expand Up @@ -878,10 +899,50 @@ export async function deployToDevWithHelm(deploymentConfig: DeploymentConfig, wo
}
}

async function addDNSRecord(namespace: string, domain: string, isLoadbalancer: boolean) {
let wsProxyLBIP = null
if (isLoadbalancer === true) {
werft.log(installerSlices.DNS_ADD_RECORD, "Getting ws-proxy loadbalancer IP");
for (let i = 0; i < 60; i++) {
try {
let lb = exec(`kubectl -n ${namespace} get service ws-proxy -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'`, { silent: true })
if (lb.length > 4) {
wsProxyLBIP = lb
break
}
await sleep(1000)
} catch (err) {
await sleep(1000)
}
}
if (wsProxyLBIP == null) {
werft.fail(installerSlices.DNS_ADD_RECORD, new Error("Can't get ws-proxy loadbalancer IP"));
}
werft.log(installerSlices.DNS_ADD_RECORD, "Get ws-proxy loadbalancer IP: " + wsProxyLBIP);
} else {
wsProxyLBIP = getCoreDevIngressIP()
}

var cmd = `set -x \
&& cd /workspace/.werft/dns \
&& rm -rf .terraform* \
&& export GOOGLE_APPLICATION_CREDENTIALS="${GCLOUD_SERVICE_ACCOUNT_PATH}" \
&& terraform init -backend-config='prefix=${namespace}' -migrate-state -upgrade \
&& terraform apply -auto-approve \
-var 'dns_zone_domain=gitpod-dev.com' \
-var 'domain=${domain}' \
-var 'ingress_ip=${getCoreDevIngressIP()}' \
-var 'ws_proxy_ip=${wsProxyLBIP}'`;

werft.log(installerSlices.DNS_ADD_RECORD, "Terraform command for create dns record: " + cmd)
exec(cmd, { ...metaEnv(), slice: installerSlices.DNS_ADD_RECORD });
werft.done(installerSlices.DNS_ADD_RECORD);
}

export async function issueMetaCerts(namespace: string, domain: string) {
let additionalSubdomains: string[] = ["", "*.", "*.ws-dev."]
var metaClusterCertParams = new IssueCertificateParams();
metaClusterCertParams.pathToTerraform = "/workspace/.werft/certs";
metaClusterCertParams.pathToTemplate = "/workspace/.werft/util/templates";
metaClusterCertParams.gcpSaPath = GCLOUD_SERVICE_ACCOUNT_PATH;
metaClusterCertParams.namespace = namespace;
metaClusterCertParams.certNamespace = "certs";
Expand Down
57 changes: 0 additions & 57 deletions .werft/certs/cert/main.tf

This file was deleted.

3 changes: 0 additions & 3 deletions .werft/certs/cert/outputs.tf

This file was deleted.

46 changes: 0 additions & 46 deletions .werft/certs/cert/variables.tf

This file was deleted.

16 changes: 0 additions & 16 deletions .werft/certs/cert/versions.tf

This file was deleted.

27 changes: 0 additions & 27 deletions .werft/certs/main.tf

This file was deleted.

56 changes: 56 additions & 0 deletions .werft/dns/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# https://www.terraform.io/docs/providers/google/guides/provider_reference.html
provider "google" {
project = "gitpod-dev"
region = "europe-west-3"
# Relies on GOOGLE_APPLICATION_CREDENTIALS pointing to the service account file
}

# Added for compatibility with old branches, can be deleted if compatibility is not needed
provider "kubectl" {
load_config_file = true
}

locals {
# As we did create the zone and IP manually beforehand: have the zone name statically determined
dns_zone_name = replace(trimsuffix(var.dns_zone_domain, ".-"), ".", "-")
project = "gitpod-dev"
region = "europe-west-3"
}

#
# DNS records
#

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/dns_record_set
resource "google_dns_record_set" "gitpod" {
count = length(var.ingress_subdomains)
name = "${var.ingress_subdomains[count.index]}${var.domain}."
type = "A"
ttl = 300
managed_zone = local.dns_zone_name
rrdatas = [var.ingress_ip]
project = local.project
}
resource "google_dns_record_set" "gitpod_ws" {
name = "${var.ws_proxy_subdomain}${var.domain}."
type = "A"
ttl = 300
managed_zone = local.dns_zone_name
rrdatas = [var.ws_proxy_ip]
project = local.project
}

#
# End
#
resource "null_resource" "done" {
depends_on = [
google_dns_record_set.gitpod,
google_dns_record_set.gitpod_ws,
]
}


output "done" {
value = null_resource.done.id
}
19 changes: 10 additions & 9 deletions .werft/certs/variables.tf → .werft/dns/variables.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
variable "namespace" {
type = string
}

# e.g.: gitpod-dev.com
variable "dns_zone_domain" {
type = string
Expand All @@ -12,16 +8,21 @@ variable "domain" {
type = string
}

# e.g.: ["", "*.", "*.ws."]
variable "subdomains" {
# e.g.: ["", "*.", "*.ws-dev."]
variable "ingress_subdomains" {
type = list(string)
default = ["", "*."]
}

variable "ws_proxy_subdomain" {
type = string
default = "*.ws-dev."
}

variable "public_ip" {
variable "ingress_ip" {
type = string
}

variable "cert_namespace" {
variable "ws_proxy_ip" {
type = string
default = "certs"
}
2 changes: 2 additions & 0 deletions .werft/certs/versions.tf → .werft/dns/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ terraform {
source = "hashicorp/google"
version = "3.63.0"
}

# Added for compatibility with old branches, can be deleted if compatibility is not needed
kubectl = {
source = "gavinbunney/kubectl"
version = "1.10.1"
Expand Down
17 changes: 17 additions & 0 deletions .werft/post-process.sh
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,23 @@ while [ "$i" -le "$DOCS" ]; do
yq m -x -i k8s.yaml -d "$i" /tmp/"$NAME"overrides.yaml
fi

if [[ "ws-proxy" == "$NAME" ]] && [[ "$KIND" == "Service" ]]; then
WORK="overrides for $NAME $KIND"
echo "$WORK"
# Provide harvester compatibility by adding ports instead of modifying the original ports
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

yq w -i k8s.yaml -d "$i" "spec.ports[+].name" http-lb
yq w -i k8s.yaml -d "$i" "spec.ports.(name==http-lb).port" 80
yq w -i k8s.yaml -d "$i" "spec.ports.(name==http-lb).protocol" TCP
yq w -i k8s.yaml -d "$i" "spec.ports.(name==http-lb).targetPort" 8080

yq w -i k8s.yaml -d "$i" "spec.ports[+].name" https-lb
yq w -i k8s.yaml -d "$i" "spec.ports.(name==https-lb).port" 443
yq w -i k8s.yaml -d "$i" "spec.ports.(name==https-lb).protocol" TCP
yq w -i k8s.yaml -d "$i" "spec.ports.(name==https-lb).targetPort" 9090
yq w -i k8s.yaml -d "$i" "metadata.annotations[cloud.google.com/neg]" '{"exposed_ports": {"22":{},"80":{},"443":{}}}'
yq w -i k8s.yaml -d "$i" spec.type LoadBalancer
fi

# update workspace-templates configmap to set affinity for workspace, ghosts, image builders, etc.
# if this is not done, and they start on a node other than workspace, they won't be able to talk to registry-facade or ws-daemon
if [[ "workspace-templates" == "$NAME" ]] && [[ "$KIND" == "ConfigMap" ]]; then
Expand Down
Loading