From 3d841d5a2ef8cf5e6e86471a691cef132ae30c7e Mon Sep 17 00:00:00 2001 From: Hanno Kolvenbach Date: Tue, 3 Apr 2018 12:50:58 +0200 Subject: [PATCH] Enable single-level DNS domains (*.domain.tld) in SINGLE_PORT mode to simplify HTTPS setup (#8983) Enable single-level DNS domains (*.domain.tld) in SINGLE_PORT mode to simplify HTTPS setup. Use whole folder for traefik conf to inject SSL certificates and custom configuration. CHE_SINGLEPORT_WILDCARD__DOMAIN_IPLESS to che.env. Signed-off-by: Hanno Kolvenbach --- .../webapp/WEB-INF/classes/che/che.properties | 3 +++ dockerfiles/init/manifests/che.env | 4 ++++ dockerfiles/init/manifests/che.pp | 1 + .../init/modules/che/templates/che.env.erb | 4 +++- .../compose/templates/docker-compose.yml.erb | 6 ++++-- .../labels/SinglePortLabelsProvisioner.java | 12 ++++++----- .../mapping/SinglePortHostnameBuilder.java | 20 ++++++++++++------- 7 files changed, 35 insertions(+), 15 deletions(-) diff --git a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties index 7f6cc24911..6954103205 100644 --- a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties +++ b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties @@ -471,3 +471,6 @@ che.infra.openshift.tls_enabled=false # Single port mode wildcard domain host & port. nip.io is used by default che.singleport.wildcard_domain.host=NULL che.singleport.wildcard_domain.port=NULL + +# Enable single port custom DNS without inserting the IP +che.singleport.wildcard_domain.ipless=false diff --git a/dockerfiles/init/manifests/che.env b/dockerfiles/init/manifests/che.env index d0b0758668..21de0201bb 100644 --- a/dockerfiles/init/manifests/che.env +++ b/dockerfiles/init/manifests/che.env @@ -249,6 +249,10 @@ CHE_SINGLE_PORT=false #CHE_SINGLEPORT_WILDCARD__DOMAIN_HOST=NULL #CHE_SINGLEPORT_WILDCARD__DOMAIN_PORT=NULL +# IP-less wildcard dns in single mode. This needs a *.domain.tld DNS entry. (Use it instead of +# nip.io) +#CHE_SINGLEPORT_WILDCARD__DOMAIN_IPLESS=false + # Default rewriter for URLs in links. # This variable is automatically overridden in single port mode. #CHE_INFRA_DOCKER_URL__REWRITER=DEFAULT diff --git a/dockerfiles/init/manifests/che.pp b/dockerfiles/init/manifests/che.pp index a1e3d8d08a..e615c10e4e 100644 --- a/dockerfiles/init/manifests/che.pp +++ b/dockerfiles/init/manifests/che.pp @@ -40,6 +40,7 @@ node default { # $che_single_port = getValue("CHE_SINGLE_PORT","false") $che_single_port_wildcard_domain_host = getValue("CHE_SINGLEPORT_WILDCARD__DOMAIN_HOST","nip.io") + $che_single_port_wildcard_domain_ipless = getValue("CHE_SINGLEPORT_WILDCARD__DOMAIN_IPLESS","false") ############################### # Che multiuser diff --git a/dockerfiles/init/modules/che/templates/che.env.erb b/dockerfiles/init/modules/che/templates/che.env.erb index 99328fe936..08b962aa7f 100644 --- a/dockerfiles/init/modules/che/templates/che.env.erb +++ b/dockerfiles/init/modules/che/templates/che.env.erb @@ -90,7 +90,9 @@ CHE_WORKSPACE_HTTP__PROXY__JAVA__OPTIONS=<% if ! @http_proxy_for_che_workspaces. CHE_INFRA_DOCKER_URL__REWRITER=singleport <% if scope.lookupvar('che::che_multiuser') == 'true' -%> -<% if ! @che_docker_ip_external.empty? -%> +<% if scope.lookupvar('che::che_single_port') == 'true' and scope.lookupvar('che::che_single_port_wildcard_domain_ipless') == 'true' -%> +CHE_KEYCLOAK_AUTH__SERVER__URL=http://keycloak.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>/auth +<% elsif ! @che_docker_ip_external.empty? -%> CHE_KEYCLOAK_AUTH__SERVER__URL=http://keycloak.<%= scope.lookupvar('che::che_docker_ip_external') -%>.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>:<%= scope.lookupvar('che::che_port') -%>/auth <% else -%> CHE_KEYCLOAK_AUTH__SERVER__URL=http://keycloak.<%= scope.lookupvar('che::docker_ip') -%>.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>:<%= scope.lookupvar('che::che_port') -%>/auth diff --git a/dockerfiles/init/modules/compose/templates/docker-compose.yml.erb b/dockerfiles/init/modules/compose/templates/docker-compose.yml.erb index 737e688d07..4e4037445b 100644 --- a/dockerfiles/init/modules/compose/templates/docker-compose.yml.erb +++ b/dockerfiles/init/modules/compose/templates/docker-compose.yml.erb @@ -100,7 +100,7 @@ services: <% end -%> volumes: - /var/run/docker.sock:/var/run/docker.sock - - '<%= scope.lookupvar('che::che_instance') -%>/config/traefik/traefik.toml:/etc/traefik/traefik.toml' + - '<%= scope.lookupvar('che::che_instance') -%>/config/traefik:/etc/traefik' restart: always <% end -%> @@ -168,7 +168,9 @@ services: labels: traefik.keycloak.frontend.entryPoints: "http" traefik.keycloak.port: "8080" -<% if ! @che_docker_ip_external.empty? -%> +<% if scope.lookupvar('che::che_single_port') == 'true' and scope.lookupvar('che::che_single_port_wildcard_domain_ipless') == 'true' -%> + traefik.keycloak.frontend.rule: "Host:keycloak.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>" +<% elsif ! @che_docker_ip_external.empty? -%> traefik.keycloak.frontend.rule: "Host:keycloak.<%= scope.lookupvar('che::che_docker_ip_external') -%>.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>" <% else -%> traefik.keycloak.frontend.rule: "Host:keycloak.<%= scope.lookupvar('che::docker_ip') -%>.<%= scope.lookupvar('che::che_single_port_wildcard_domain_host') -%>" diff --git a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/provisioner/labels/SinglePortLabelsProvisioner.java b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/provisioner/labels/SinglePortLabelsProvisioner.java index ed4655a6bb..4dc7a654b8 100644 --- a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/provisioner/labels/SinglePortLabelsProvisioner.java +++ b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/provisioner/labels/SinglePortLabelsProvisioner.java @@ -94,10 +94,12 @@ public class SinglePortLabelsProvisioner implements ConfigurationProvisioner { * exec-agent-http-dev-machine-workspaceao6k83hkdav975g5 */ private String getServiceName(String host) { - int idx = - (externalIpOfContainers != null && host.contains(externalIpOfContainers)) - ? host.indexOf(externalIpOfContainers) - : host.indexOf(internalIpOfContainers); - return host.substring(0, idx - 1).replaceAll("\\.", "-"); + int idx = host.indexOf("."); + if (idx > 1) { + return host.substring(0, idx - 1); + } else { + // the hostname does not contain the external or internal IPs (or in general any dots) + return host; + } } } diff --git a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/server/mapping/SinglePortHostnameBuilder.java b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/server/mapping/SinglePortHostnameBuilder.java index b041cf0f7e..170d7e2d2f 100644 --- a/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/server/mapping/SinglePortHostnameBuilder.java +++ b/infrastructures/docker/infrastructure/src/main/java/org/eclipse/che/workspace/infrastructure/docker/server/mapping/SinglePortHostnameBuilder.java @@ -22,7 +22,7 @@ import org.eclipse.che.inject.ConfigurationException; /** * Produces host names in form: - * [serverName].[machineName].[workspaceId].. If + * [serverName]-[machineName]-[workspaceId].. If * some of the server name or machine name or workspace id is null, they will be not included. * * @author Max Shaposhnik (mshaposh@redhat.com) @@ -54,7 +54,7 @@ public class SinglePortHostnameBuilder { * @return composite hostname */ public String build(String serverName, String machineName, String workspaceID) { - StringJoiner joiner = new StringJoiner("."); + StringJoiner joiner = new StringJoiner("-"); if (serverName != null) { joiner.add(normalize(serverName)); } @@ -64,18 +64,24 @@ public class SinglePortHostnameBuilder { if (workspaceID != null) { joiner.add(normalize(workspaceID)); } - joiner.add(wildcardDomain); - return joiner.toString(); + return joiner.toString() + "." + wildcardDomain; } /** - * Gets a Wildcard domain based on the ip using an external provider like nip.io + * Gets a Wildcard domain based on the ip using an external provider like nip.io or by providing + * an IP-less DNS yourself * * @return wildcard domain */ private String getWildcardDomain(String localAddress, String wildcardHost) { - return String.format( - "%s.%s", getExternalIp(localAddress), wildcardHost == null ? "nip.io" : wildcardHost); + if (wildcardHost == null) { + return String.format("%s.%s", getExternalIp(localAddress), "nip.io"); + } else if (wildcardHost.contains("nip.io") || wildcardHost.contains("xip.io")) { + return String.format("%s.%s", getExternalIp(localAddress), wildcardHost); + } else { + // IP-less DNS + return wildcardHost; + } } private String getExternalIp(String localAddress) {