Skip to content
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

Add support for using Jupyterhub behind the Unity Proxy #172

Merged
merged 8 commits into from
Aug 16, 2024
23 changes: 0 additions & 23 deletions common/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,3 @@ variable "efs_identifier" {
type = string
# Example value:uads-development-efs-fs"
}

# These are for validation of the input variables
data "aws_ssm_parameter" "project" {
name = "/unity/${var.project}/${var.venue}/project-name"

lifecycle {
postcondition {
condition = self.value == var.project
error_message = "project variable value ${var.project} does not match SSM parameter value in /unity/${var.project}/${var.venue}/project-name: {$data.aws_ssm_parameter.project}"
}
}
}

data "aws_ssm_parameter" "venue" {
name = "/unity/${var.project}/${var.venue}/venue-name"

lifecycle {
postcondition {
condition = self.value == var.venue
error_message = "venue variable value ${var.venue} does not match SSM parameter value in /unity/${var.project}/${var.venue}/venue-name: {$data.aws_ssm_parameter.venue}"
}
}
}
2 changes: 1 addition & 1 deletion dev_env/cognito/cognito_client.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ data "aws_cognito_user_pools" "unity_user_pool" {
}

resource "aws_cognito_user_pool_client" "jupyter_cognito_client" {
name = "${var.resource_prefix}-jupyter-${var.tenant_identifier}-client"
name = "${var.resource_prefix}-jupyter-${var.venue_prefix}${var.venue}-client"
user_pool_id = tolist(data.aws_cognito_user_pools.unity_user_pool.ids)[0]

callback_urls = var.jupyter_base_url != null ? ["${var.jupyter_base_url}/${var.jupyter_base_path}/hub/oauth_callback"] : null
Expand Down
84 changes: 58 additions & 26 deletions dev_env/jupyterhub/frontend.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,29 @@
# Only one of the two choices below can be enabled at a time
# Run terraform init if changing between the two

###################################################################
# Use an API Gateway connected to a NLB as the Jupyterhub Frontend
#
# This options mostly works except that websockets fail to properly
# be routed through the REST API gateway, more work would be needed
# to get it working.

# module "frontend" {
# source = "./modules/api_gateway"
#
# project = var.project
# venue = var.venue
# venue_prefix = var.venue_prefix
# resource_prefix = var.resource_prefix
# load_balancer_port = var.load_balancer_port
# jupyter_proxy_port = var.jupyter_proxy_port
#
# vpc_id = data.aws_ssm_parameter.vpc_id.value
# lb_subnet_ids = local.subnet_map["private"]
# security_group_id = aws_security_group.jupyter_lb_sg.id
# autoscaling_group_name = module.eks.eks_managed_node_groups_autoscaling_group_names[0]
# }
#################################################################
# Set up these data values to allow overriding of values by variables

data "aws_ssm_parameter" "ssAcctNum" {
name = "/unity/shared-services/aws/account"
}

data "aws_ssm_parameter" "proxy_url" {
name = "arn:aws:ssm:us-west-2:${data.aws_ssm_parameter.ssAcctNum.value}:parameter/unity/shared-services/domain"
}

locals {
# Extract info on the proxy from the SSM parameter
proxy_proto = "https"
proxy_address = data.aws_ssm_parameter.proxy_url.value
proxy_port = 4443

# Allow overriding from variables
url_terminus_path = "jupyter"
load_balancer_port = local.proxy_port
jupyter_base_url = var.jupyter_base_url != null ? var.jupyter_base_url : "${local.proxy_proto}://www.${local.proxy_address}:${local.proxy_port}"
jupyter_base_path = var.jupyter_base_path != null ? var.jupyter_base_path : "${var.project}/${var.venue}/${local.url_terminus_path}"
}

#################################################################
# Use only a Application Load Balancer as the Jupyterhub Frontend
Expand All @@ -37,14 +38,45 @@ module "frontend" {
venue = var.venue
venue_prefix = var.venue_prefix
resource_prefix = var.resource_prefix
load_balancer_port = var.load_balancer_port
load_balancer_port = local.load_balancer_port
jupyter_proxy_port = var.jupyter_proxy_port

jupyter_base_url = var.jupyter_base_url
jupyter_base_path = var.jupyter_base_path
jupyter_base_url = local.jupyter_base_url
jupyter_base_path = local.jupyter_base_path

vpc_id = data.aws_ssm_parameter.vpc_id.value
lb_subnet_ids = local.subnet_map["public"]
internal = true
lb_subnet_ids = local.subnet_map["private"]
security_group_id = aws_security_group.jupyter_lb_sg.id
autoscaling_group_name = module.eks.eks_managed_node_groups_autoscaling_group_names[0]
}

#################################################################
# Initialize connection to HTTP proxy
resource "aws_ssm_parameter" "serviceproxy_config" {
depends_on = [module.frontend]
name = "/unity/${var.project}/${var.venue}/cs/management/proxy/configurations/042-jupyterlab"
type = "String"
value = <<-EOT
<Location /${var.project}/${var.venue}/${local.url_terminus_path}/>
# preserve Host header to avoid cross-origin problems
ProxyPreserveHost on
Header always set Strict-Transport-Security "max-age=63072000"
# proxy to JupyterHub
ProxyPass "${module.frontend.internal_base_url}/${local.jupyter_base_path}/" upgrade=websocket
ProxyPassReverse "${module.frontend.internal_base_url}/${local.jupyter_base_path}/"
RequestHeader set "X-Forwarded-Proto" expr=%%{REQUEST_SCHEME}
</Location>
EOT
}

resource "aws_lambda_invocation" "unity_proxy_lambda_invocation" {
depends_on = [aws_ssm_parameter.serviceproxy_config]
function_name = "${var.project}-${var.venue}-httpdproxymanagement"
input = "{}"
triggers = {
redeployment = sha1(jsonencode([
aws_ssm_parameter.serviceproxy_config
]))
}
}
8 changes: 1 addition & 7 deletions dev_env/jupyterhub/jupyter_variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ variable "component_cost_name" {
default = "jupyterhub"
}

variable "load_balancer_port" {
description = "Incoming port where load balancer will accept traffic"
type = number
default = 8000
}

# Should be an integer between 30000 and 32767
variable "jupyter_proxy_port" {
description = "Listening port for Jupyter kubernetes cluster"
Expand All @@ -29,7 +23,7 @@ variable "jupyter_base_url" {
variable "jupyter_base_path" {
description = "Base path for Jupyter as accessed at its public facing location"
type = string
default = ""
default = null
}

variable "cognito_oauth_base_url" {
Expand Down
Loading