diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 9e69574803a9ad89ccfc6b18e923a7ce3550fa79..166832edcf430981c109d71077d520726d94150d 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -50,17 +50,16 @@ services: - DJANGO_DEBUG=True - DJANGO_LOG_LEVEL=CRITICAL - ROSETTA_LOG_LEVEL=DEBUG - #- ROSETTA_TUNNEL_HOST= - #- ROSETTA_WEBAPP_HOST= - #- ROSETTA_WEBAPP_PORT=8080 + #- ROSETTA_WEBAPP_HOST=localhost # Internal, for the agent + #- ROSETTA_WEBAPP_PORT=8080 # Internal, for the agent #- LOCAL_DOCKER_REGISTRY_HOST= #- LOCAL_DOCKER_REGISTRY_PORT=5000 #- DJANGO_EMAIL_APIKEY="" #- DJANGO_EMAIL_FROM="Rosetta Platform <notifications@rosetta.platform>" - #- DJANGO_PUBLIC_HTTP_HOST=http://localhost:8080 #- DJANGO_SECRET_KEY="" - - TASK_PROXY_HOST="localhost" - - TASK_TUNNEL_HOST="localhost" + - TASK_PROXY_HOST=localhost + - TASK_TUNNEL_HOST=localhost + - ROSETTA_HOST=localhost ports: - "8080:8080" - "7000-7020:7000-7020" @@ -78,6 +77,7 @@ services: hostname: proxy environment: - SAFEMODE=False + - ROSETTA_HOST=localhost ports: - "80:80" - "443:443" diff --git a/services/proxy/000-default.conf b/services/proxy/000-default.conf deleted file mode 100644 index 2d43f2b62b835dbaa3e16107276a3d2b2781d563..0000000000000000000000000000000000000000 --- a/services/proxy/000-default.conf +++ /dev/null @@ -1,51 +0,0 @@ -<VirtualHost *:80> - # The ServerName directive sets the request scheme, hostname and port that - # the server uses to identify itself. This is used when creating - # redirection URLs. In the context of virtual hosts, the ServerName - # specifies what hostname must appear in the request's Host: header to - # match this virtual host. For the default virtual host (this file) this - # value is not decisive as it is used as a last resort host regardless. - # However, you must set it for any further virtual host explicitly. - #ServerName www.example.com - - ServerAdmin webmaster@backfrontend - ProxyPass / http://webapp:8080/ - ProxyPassReverse / http://webapp:8080/ - - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - #ErrorLog ${APACHE_LOG_DIR}/error.log - #CustomLog ${APACHE_LOG_DIR}/access.log combined - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - #---------------------------------- - # Force https except on localhost - #---------------------------------- - - # This is somehow a bad idea, as - # 1) dev env is different than staging/production, and - # 2) other roules in 001-proxy.conf are never reached - - RewriteEngine On - RewriteCond %{HTTPS} off - RewriteCond %{HTTP_HOST} !=localhost - RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} - - ProxyPass / http://webapp:8080/ - ProxyPassReverse / http://webapp:8080/ - -</VirtualHost> - - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet \ No newline at end of file diff --git a/services/proxy/001-proxy.conf b/services/proxy/001-proxy.conf deleted file mode 100644 index 6f02cde7f5f9d65e93a05e0cd3fa3ee97156095b..0000000000000000000000000000000000000000 --- a/services/proxy/001-proxy.conf +++ /dev/null @@ -1,30 +0,0 @@ - -#--------------------------- -# Rosetta platform -#--------------------------- - -# WARNING: not relevant anymore, see 000-default.conf - -# Non-SSL -#<VirtualHost *:80> -# ServerName rosetta.platform -# Redirect 301 / https://rosetta.platform/ -#</VirtualHost> - -# SSL -#<VirtualHost *:443> -# -# ServerName rosetta.platform -# -# SSLEngine on -# SSLCertificateFile /root/certificates/rosetta_platform/rosetta_platform.crt -# SSLCertificateKeyFile /root/certificates/rosetta_platform/rosetta_platform.key -# SSLCACertificateFile /root/certificates/rosetta_platform/rosetta_platform.ca-bundle -# -# ProxyPass / http://webapp:8080/ -# ProxyPassReverse / http://webapp:8080/ - -#</VirtualHost> - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet - diff --git a/services/proxy/Dockerfile b/services/proxy/Dockerfile index 51e0669c2f6c151ad98c38f2a1e47acb7b7ae48e..3da9629f1c13dac8cb94ae20dc558ec11062778d 100644 --- a/services/proxy/Dockerfile +++ b/services/proxy/Dockerfile @@ -23,26 +23,17 @@ RUN a2enmod rewrite RUN a2enmod headers RUN a2enmod proxy_wstunnel -# Copy and enable conf for proxy -COPY 001-proxy.conf /etc/apache2/sites-available/ -RUN ln -s /etc/apache2/sites-available/001-proxy.conf /etc/apache2/sites-enabled/001-proxy.conf - -# We overwrite default Apache conf as we force https -COPY 000-default.conf /etc/apache2/sites-available/ - -# Copy and enable conf for ssl. Not enabling ssl default site causes the first ssl -# site in sites-avaialbe to be used as default. "Check with apachectl -t -D DUMP_VHOSTS". -# A custom conf is not really necessary as defaults are ok (it is the original file) -# Note: not naming this file with "000" causes to load other sites-available before, same problem. -COPY default-ssl.conf /etc/apache2/sites-available/ -RUN ln -s /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/000-default-ssl.conf +# Clean up default stuff +RUN rm /etc/apache2/sites-available/000-default.conf +RUN rm /etc/apache2/sites-enabled/000-default.conf +RUN rm /etc/apache2/sites-available/default-ssl.conf +#RUN rm /etc/apache2/sites-enabled/default-ssl.conf # Copy certificates (snakeoil or real) RUN mkdir /certificates COPY certificates/rosetta_platform.crt /root/certificates/rosetta_platform/rosetta_platform.crt COPY certificates/rosetta_platform.key /root/certificates/rosetta_platform/rosetta_platform.key COPY certificates/rosetta_platform.ca-bundle /root/certificates/rosetta_platform/rosetta_platform.ca-bundle - COPY certificates/rosetta_tasks.crt /root/certificates/rosetta_platform/rosetta_tasks.crt COPY certificates/rosetta_tasks.key /root/certificates/rosetta_platform/rosetta_tasks.key COPY certificates/rosetta_tasks.ca-bundle /root/certificates/rosetta_platform/rosetta_tasks.ca-bundle @@ -54,5 +45,10 @@ COPY norobots.txt /var/www/html/ # Prestartup COPY prestartup_proxy.sh /prestartup/ -# reyns: expose 80/tcp -# reyns: expose 443/tcp +# Copy and enable conf for proxy and ssl. Warning: there are issues with precedences if splitting +# the conf over multiple files (including task proxy files), as the first conf found in files which +# are read in alphabetical order wins. You can cheeck ordering with "apachectl -t -D DUMP_VHOSTS". +COPY proxy-global.conf /etc/apache2/sites-available/ +RUN ln -s /etc/apache2/sites-available/proxy-global.conf /etc/apache2/sites-enabled/proxy-global.conf + + diff --git a/services/proxy/default-ssl.conf b/services/proxy/default-ssl.conf deleted file mode 100644 index 1124d7dc6ce621cce28da113d36f31fb0709ed77..0000000000000000000000000000000000000000 --- a/services/proxy/default-ssl.conf +++ /dev/null @@ -1,143 +0,0 @@ -<IfModule mod_ssl.c> - <VirtualHost _default_:443> - ServerAdmin webmaster@localhost - - ProxyPass / http://webapp:8080/ - ProxyPassReverse / http://webapp:8080/ - - # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, - # error, crit, alert, emerg. - # It is also possible to configure the loglevel for particular - # modules, e.g. - #LogLevel info ssl:warn - - #ErrorLog ${APACHE_LOG_DIR}/error.log - #CustomLog ${APACHE_LOG_DIR}/access.log combined - - # For most configuration files from conf-available/, which are - # enabled or disabled at a global level, it is possible to - # include a line for only one particular virtual host. For example the - # following line enables the CGI configuration for this host only - # after it has been globally disabled with "a2disconf". - #Include conf-available/serve-cgi-bin.conf - - # SSL Engine Switch: - # Enable/Disable SSL for this virtual host. - SSLEngine on - - # A self-signed (snakeoil) certificate can be created by installing - # the ssl-cert package. See - # /usr/share/doc/apache2/README.Debian.gz for more info. - # If both key and certificate are stored in the same file, only the - # SSLCertificateFile directive is needed. - #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem - #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key - SSLCertificateFile /root/certificates/rosetta_platform/rosetta_platform.crt - SSLCertificateKeyFile /root/certificates/rosetta_platform/rosetta_platform.key - SSLCACertificateFile /root/certificates/rosetta_platform/rosetta_platform.ca-bundle - - # Server Certificate Chain: - # Point SSLCertificateChainFile at a file containing the - # concatenation of PEM encoded CA certificates which form the - # certificate chain for the server certificate. Alternatively - # the referenced file can be the same as SSLCertificateFile - # when the CA certificates are directly appended to the server - # certificate for convinience. - #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt - - # Certificate Authority (CA): - # Set the CA certificate verification path where to find CA - # certificates for client authentication or alternatively one - # huge file containing all of them (file must be PEM encoded) - # Note: Inside SSLCACertificatePath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCACertificatePath /etc/ssl/certs/ - #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt - - # Certificate Revocation Lists (CRL): - # Set the CA revocation path where to find CA CRLs for client - # authentication or alternatively one huge file containing all - # of them (file must be PEM encoded) - # Note: Inside SSLCARevocationPath you need hash symlinks - # to point to the certificate files. Use the provided - # Makefile to update the hash symlinks after changes. - #SSLCARevocationPath /etc/apache2/ssl.crl/ - #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl - - # Client Authentication (Type): - # Client certificate verification type and depth. Types are - # none, optional, require and optional_no_ca. Depth is a - # number which specifies how deeply to verify the certificate - # issuer chain before deciding the certificate is not valid. - #SSLVerifyClient require - #SSLVerifyDepth 10 - - # SSL Engine Options: - # Set various options for the SSL engine. - # o FakeBasicAuth: - # Translate the client X.509 into a Basic Authorisation. This means that - # the standard Auth/DBMAuth methods can be used for access control. The - # user name is the `one line' version of the client's X.509 certificate. - # Note that no password is obtained from the user. Every entry in the user - # file needs this password: `xxj31ZMTZzkVA'. - # o ExportCertData: - # This exports two additional environment variables: SSL_CLIENT_CERT and - # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the - # server (always existing) and the client (only existing when client - # authentication is used). This can be used to import the certificates - # into CGI scripts. - # o StdEnvVars: - # This exports the standard SSL/TLS related `SSL_*' environment variables. - # Per default this exportation is switched off for performance reasons, - # because the extraction step is an expensive operation and is usually - # useless for serving static content. So one usually enables the - # exportation for CGI and SSI requests only. - # o OptRenegotiate: - # This enables optimized SSL connection renegotiation handling when SSL - # directives are used in per-directory context. - #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire - <FilesMatch "\.(cgi|shtml|phtml|php)$"> - SSLOptions +StdEnvVars - </FilesMatch> - <Directory /usr/lib/cgi-bin> - SSLOptions +StdEnvVars - </Directory> - - # SSL Protocol Adjustments: - # The safe and default but still SSL/TLS standard compliant shutdown - # approach is that mod_ssl sends the close notify alert but doesn't wait for - # the close notify alert from client. When you need a different shutdown - # approach you can use one of the following variables: - # o ssl-unclean-shutdown: - # This forces an unclean shutdown when the connection is closed, i.e. no - # SSL close notify alert is send or allowed to received. This violates - # the SSL/TLS standard but is needed for some brain-dead browsers. Use - # this when you receive I/O errors because of the standard approach where - # mod_ssl sends the close notify alert. - # o ssl-accurate-shutdown: - # This forces an accurate shutdown when the connection is closed, i.e. a - # SSL close notify alert is send and mod_ssl waits for the close notify - # alert of the client. This is 100% SSL/TLS standard compliant, but in - # practice often causes hanging connections with brain-dead browsers. Use - # this only for browsers where you know that their SSL implementation - # works correctly. - # Notice: Most problems of broken clients are also related to the HTTP - # keep-alive facility, so you usually additionally want to disable - # keep-alive for those clients, too. Use variable "nokeepalive" for this. - # Similarly, one has to force some clients to use HTTP/1.0 to workaround - # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and - # "force-response-1.0" for this. - BrowserMatch "MSIE [2-6]" \ - nokeepalive ssl-unclean-shutdown \ - downgrade-1.0 force-response-1.0 - # MSIE 7 and newer should be able to use keepalive - BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown - - # Required for the Open ID connect redirects to work properly - RequestHeader set X-Forwarded-Proto 'https' env=HTTPS - - </VirtualHost> -</IfModule> - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet \ No newline at end of file diff --git a/services/proxy/index.html b/services/proxy/index.html index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76738930c3ab0ce0c6ff8ee1d1c06f1eea42eeb9 100644 --- a/services/proxy/index.html +++ b/services/proxy/index.html @@ -0,0 +1 @@ +Nothing here \ No newline at end of file diff --git a/services/proxy/proxy-global.conf b/services/proxy/proxy-global.conf new file mode 100644 index 0000000000000000000000000000000000000000..a681b87d1f30d93b13dad4de6b2371f5fb5e7db9 --- /dev/null +++ b/services/proxy/proxy-global.conf @@ -0,0 +1,53 @@ +<VirtualHost *:80> + + ServerAdmin admin@rosetta.platform + + #---------------------------------- + # Force https (except on localhost) + #---------------------------------- + + RewriteEngine On + RewriteCond %{HTTPS} off + RewriteCond %{HTTP_HOST} !=localhost + RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} + + ProxyPass / http://webapp:8080/ + ProxyPassReverse / http://webapp:8080/ + +</VirtualHost> + + +<VirtualHost *:443> + ServerAdmin admin@rosetta.platform + SSLEngine on + SSLCertificateFile /root/certificates/rosetta_platform/rosetta_platform.crt + SSLCertificateKeyFile /root/certificates/rosetta_platform/rosetta_platform.key + SSLCACertificateFile /root/certificates/rosetta_platform/rosetta_platform.ca-bundle + DocumentRoot /var/www/html +</VirtualHost> + + +<VirtualHost *:443> + ServerAdmin admin@rosetta.platform + ServerName ${ROSETTA_HOST} + ProxyPass / http://webapp:8080/ + ProxyPassReverse / http://webapp:8080/ + + SSLEngine on + + SSLCertificateFile /root/certificates/rosetta_platform/rosetta_platform.crt + SSLCertificateKeyFile /root/certificates/rosetta_platform/rosetta_platform.key + SSLCACertificateFile /root/certificates/rosetta_platform/rosetta_platform.ca-bundle + + # Browser-specific fixes + BrowserMatch "MSIE [2-6]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown + + # Required for the Open ID connect redirects to work properly + RequestHeader set X-Forwarded-Proto 'https' env=HTTPS + +</VirtualHost> + + diff --git a/services/webapp/code/rosetta/core_app/api.py b/services/webapp/code/rosetta/core_app/api.py index e279fdf74bd4cb47844010cd8e64611f230a010e..feb7d9d3d60e1656692906516ac913a4ed8303c2 100644 --- a/services/webapp/code/rosetta/core_app/api.py +++ b/services/webapp/code/rosetta/core_app/api.py @@ -329,7 +329,7 @@ print(port) # Notify the user that the task called back home logger.info('Sending task ready mail notification to "{}"'.format(task.user.email)) mail_subject = 'Your Task "{}" is now starting up'.format(task.container.name) - mail_text = 'Hello,\n\nyour Task "{}" on {} is now starting up. Check logs or connect here: {}/tasks/?uuid={}\n\nThe Rosetta notifications bot.'.format(task.container.name, task.computing, settings.DJANGO_PUBLIC_HTTP_HOST, task.uuid) + mail_text = 'Hello,\n\nyour Task "{}" on {} is now starting up. Check logs or connect here: https://{}/tasks/?uuid={}\n\nThe Rosetta notifications bot.'.format(task.container.name, task.computing, settings.ROSETTA_HOST, task.uuid) try: send_email(to=task.user.email, subject=mail_subject, text=mail_text) except Exception as e: diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py index bd53d68ef06661f07eb4ffe39ff9ca15b4985f1d..700281d39ee4987fe0e3788da4cf8f93b9bc1a64 100644 --- a/services/webapp/code/rosetta/core_app/models.py +++ b/services/webapp/code/rosetta/core_app/models.py @@ -4,7 +4,7 @@ from django.conf import settings from django.db import models from django.contrib.auth.models import User from django.utils import timezone -from .utils import os_shell, color_map, hash_string_to_int +from .utils import os_shell, color_map, hash_string_to_int, get_task_tunnel_host from .exceptions import ConsistencyException if 'sqlite' in settings.DATABASES['default']['ENGINE']: @@ -373,12 +373,11 @@ class Task(models.Model): @property def sharable_link(self): - return '{}/t/{}'.format(settings.DJANGO_PUBLIC_HTTP_HOST, str(self.uuid)[0:8]) + return 'https://{}/t/{}'.format(settings.ROSETTA_HOST, str(self.uuid)[0:8]) @property def tcp_tunnel_host(self): - # If separate host for tasks is set use that, otherwise: - return settings.DJANGO_PUBLIC_HTTP_HOST + return get_task_tunnel_host() #========================= diff --git a/services/webapp/code/rosetta/core_app/utils.py b/services/webapp/code/rosetta/core_app/utils.py index 27f9cfd20fafa2724fa38419ec2ce2e8f02d4fd9..9824ea110d2de563da360fe7ac563bc3900f4cef 100644 --- a/services/webapp/code/rosetta/core_app/utils.py +++ b/services/webapp/code/rosetta/core_app/utils.py @@ -621,23 +621,21 @@ def setup_tunnel_and_proxy(task): # Task interface proxy #--------------------------- -#<Location /desktop/{0}/> -# - -#ProxyPass http://desktop-{0}:8590/ -#ProxyPassReverse http://desktop-{0}:8590/ -#</Location> +Listen '''+str(task.tcp_tunnel_port)+''' -#<Location /sessions/{1}> -#ProxyPass ws://desktop-{0}:8590/websockify -#ProxyPassReverse ws://desktop-{0}:8590/websockify -#</Location> +<VirtualHost *:'''+str(task.tcp_tunnel_port)+'''> + ServerAdmin admin@rosetta.platform + SSLEngine on + SSLCertificateFile /root/certificates/rosetta_platform/rosetta_platform.crt + SSLCertificateKeyFile /root/certificates/rosetta_platform/rosetta_platform.key + SSLCACertificateFile /root/certificates/rosetta_platform/rosetta_platform.ca-bundle + DocumentRoot /var/www/html +</VirtualHost> -Listen '''+str(task.tcp_tunnel_port)+''' -<VirtualHost _default_:'''+str(task.tcp_tunnel_port)+'''> +<VirtualHost *:'''+str(task.tcp_tunnel_port)+'''> ServerName '''+task_proxy_host+''' - ServerAdmin admin@rosetta + ServerAdmin admin@rosetta.platform SSLEngine on SSLCertificateFile /root/certificates/rosetta_platform/rosetta_tasks.crt diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py index beb52d96ae9817624eb1b692a6b66f6c6473bbfe..972a72b77362f4950cfbe42bc9da3d0b445d91b8 100644 --- a/services/webapp/code/rosetta/core_app/views.py +++ b/services/webapp/code/rosetta/core_app/views.py @@ -76,7 +76,7 @@ def login_view(request): loginToken.token = token loginToken.save() try: - send_email(to=user.email, subject='Rosetta login link', text='Hello,\n\nhere is your login link: {}/login/?token={}\n\nOnce logged in, you can go to "My Account" and change password (or just keep using the login link feature).\n\nThe Rosetta Team.'.format(settings.DJANGO_PUBLIC_HTTP_HOST, token)) + send_email(to=user.email, subject='Rosetta login link', text='Hello,\n\nhere is your login link: https://{}/login/?token={}\n\nOnce logged in, you can go to "My Account" and change password (or just keep using the login link feature).\n\nThe Rosetta Team.'.format(settings.ROSETTA_HOST, token)) except Exception as e: logger.error(format_exception(e)) raise ErrorMessage('Something went wrong. Please retry later.') diff --git a/services/webapp/code/rosetta/settings.py b/services/webapp/code/rosetta/settings.py index 436f9d8ed56adda20eeba27ca57f2c62a885f1a9..464cd04bf0a249566eb91ed0d0ab6afcfd3b11d8 100644 --- a/services/webapp/code/rosetta/settings.py +++ b/services/webapp/code/rosetta/settings.py @@ -152,13 +152,13 @@ SWAGGER_SETTINGS = { 'USE_SESSION_AUTH': False } +# Public Rosetta host +ROSETTA_HOST = os.environ.get('ROSETTA_HOST', 'localhost') #=============================== # Email settings #=============================== -DJANGO_PUBLIC_HTTP_HOST = os.environ.get('DJANGO_PUBLIC_HTTP_HOST', 'http://localhost') - DJANGO_EMAIL_SERVICE = os.environ.get('DJANGO_EMAIL_SERVICE', 'Sendgrid') if not DJANGO_EMAIL_SERVICE in ['Sendgrid', None]: raise ImproperlyConfigured('Invalid EMAIL_METHOD ("{}")'.format(DJANGO_EMAIL_SERVICE))