diff --git a/.dockerignore b/.dockerignore index 4d895b5656233f4fc49f9d0aeb28677e5bb72ec3..fd13482a4cd2a977338e60677f9cc9dff76f702b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,5 @@ node_modules/ -.git +* +.* +!appsrc/ +!docker/ diff --git a/README.md b/README.md index ac0a3e300945d239b7b042e6e7a16d3372e070b7..6b0cb19551d742e4e4193f749584f27870b4dc9b 100644 --- a/README.md +++ b/README.md @@ -28,19 +28,3 @@ Run `yarn e2e` or `ng e2e` to execute the end-to-end tests via [Protractor](http ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). - -# DECODER Reverse proxy -This section should be moved to a dedicated repository on time. For now the reverse proxy is embedded in the frontend container but in the long term it should be independent (if we keep a reverse-proxy approach). - -The reverse proxy mission is to route requests from the Internet to either the DECODER tools - as REST APIs or webapps - or to the frontend. It is the single entry point (of failure) for browsers. - -The current setup leverages two domain names: -- https://decoder-tool.ow2.org (backend tools) -- https://decoder-frontend.ow2.org (frontend) - -They are certified through let's encrypt certification authority. - -## Prefix and container -Tools are mapped to their related backend container through NGINX using a `location` prefix matching pattern, except for `/pkm` which use a dedicated `location` match in order to preserve [URL-encoding](https://en.wikipedia.org/wiki/Percent-encoding). - -The matching prefix is associated to a container using a dynamic `map` (see [decoder.conf.template](docker/decoder.conf.template)) diff --git a/docker/Dockerfile b/docker/Dockerfile index ad2a229e62a255702a95a02a544768e65acede9f..cc050064f30ac63ee61c08d9aca1c9e1c8cccf8d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,14 +10,11 @@ RUN yarn build --configuration=production # 2. Deploy FROM nginx:alpine -RUN apk add certbot certbot-nginx -COPY docker/nginx.conf docker/cors.conf /etc/nginx/ -COPY docker/decoder.conf.template /etc/nginx/templates/ +COPY docker/nginx.conf /etc/nginx/ +COPY docker/frontend.conf.template /etc/nginx/templates/ +# deleting unused default configuration to avoid listen conflict on port 80 +RUN rm /etc/nginx/conf.d/default.conf COPY --from=app /app/dist/. /var/www/ -# MH / I don't see the point of this -# RUN chown -R nginx /var/cache/nginx && chmod -R 755 /var/cache/nginx && chmod 777 /var/cache/nginx -# RUN chown -R nginx /run && chmod -R 755 /run && chmod 777 /run - -EXPOSE 8500 80 443 +EXPOSE 80 diff --git a/docker/Dockerfile.ci b/docker/Dockerfile.ci deleted file mode 100644 index b5a166aaeaef4e80c2c1669ac511e77d148548ff..0000000000000000000000000000000000000000 --- a/docker/Dockerfile.ci +++ /dev/null @@ -1,15 +0,0 @@ -FROM nginx:alpine-perl - -ENV NGINX_URL_JUPY=https://jupyterhub-decoder.apps.itaas.s2-eu.capgemini.com/ -#ENV NGINX_URL_JUPY=http://jupyterhub:8081/ -ENV NGINX_URL_API=https://decoder-search-engine-backend-dev-decoder.apps.itaas.s2-eu.capgemini.com - -COPY nginx.conf /etc/nginx/nginx.conf -COPY . /var/www/ - -RUN rm -f ./var/www/nginx.conf - -RUN chown -R nginx /var/cache/nginx && chmod -R 755 /var/cache/nginx && chmod 777 /var/cache/nginx -RUN chown -R nginx /run && chmod -R 755 /run && chmod 777 /run - -EXPOSE 8080 \ No newline at end of file diff --git a/docker/cors.conf b/docker/cors.conf deleted file mode 100644 index 080df2293ebf9d4ad8dd02e73667c7c6505a468b..0000000000000000000000000000000000000000 --- a/docker/cors.conf +++ /dev/null @@ -1,29 +0,0 @@ -if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' $allowOrigin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - - # - # Custom headers and headers various browsers *should* be OK with but aren't - # - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key'; - - # - # Tell client that this pre-flight info is valid for 20 days - # - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain charset=UTF-8'; - add_header 'Content-Length' 0; - return 204; -} -if ($request_method = 'POST') { - add_header 'Access-Control-Allow-Origin' $allowOrigin always; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key'; -} -if ($request_method = 'GET') { - add_header 'Access-Control-Allow-Origin' $allowOrigin always; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key'; -} diff --git a/docker/decoder.conf.template b/docker/decoder.conf.template deleted file mode 100644 index 221aa26576412fc593855851d3c229ae30eb4470..0000000000000000000000000000000000000000 --- a/docker/decoder.conf.template +++ /dev/null @@ -1,181 +0,0 @@ -# uriPrefix is the first slash component of the URL -# ie /frama-c -# upstreamNameWithPortAndPrefix is the placeholder for $2 in the proxy_pass -map $uriPrefix $upstreamNameWithPortAndPrefix { - default noService; - pkm pkm:8080; - frama_c frama-c:8081; - frama_clang frama-clang:8082; - code_summarization code-summarization:8083; - smmodel smmodelxmi2jsontransformer:5004; - classmodel classmodelxmi2jsontransformer:5003; - openjml_analyzer openjmlanalyzer:5002; - javaparser javaparser:5001; - jmlgen jmlgen:5005; - testar ow2-testar-decoder.xsalto.net:8080; - srl srl; - ner ner; - semparsing semanticparsing; - trace_recovery trace_recovery; - asfm asfm:8086; - excavator excavator:8087; -} - -map $upstream_http_access_control_allow_origin $allowOrigin { - '' '*'; - default ''; -} - -# certificate file for DECODER_TOOL_HOSTNAME is (should be) valid -# for both server_name (tool and frontend) -ssl_certificate /etc/letsencrypt/live/${DECODER_TOOL_HOSTNAME}/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/${DECODER_TOOL_HOSTNAME}/privkey.pem; -include /etc/letsencrypt/options-ssl-nginx.conf; -ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - -server { - listen 8500; - listen [::]:8500; - server_name ${DECODER_FRONTEND_HOSTNAME}; - large_client_header_buffers 4 16k; - - listen [::]:443 ssl ipv6only=on; - listen 443 ssl; - - # certificate file for DECODER_TOOL_HOSTNAME is (should be) valid - # for both server_name (tool and frontend) - ssl_certificate /etc/letsencrypt/live/${DECODER_TOOL_HOSTNAME}/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/${DECODER_TOOL_HOSTNAME}/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot - - root /var/www/; - try_files $uri $uri/ /index.html; - - # security headers - # add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; - - # gzip - gzip on; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; -} - -server { - listen 8500; - listen [::]:8500; - server_name ${DECODER_TOOL_HOSTNAME}; - large_client_header_buffers 4 16k; - - client_header_timeout 600s; - client_body_timeout 600s; - proxy_read_timeout 600s; - - listen [::]:443 ssl; - listen 443 ssl; - - resolver 127.0.0.11 valid=10s; - -# # security headers -# #add_header X-Frame-Options "SAMEORIGIN" always; -# add_header X-XSS-Protection "1; mode=block" always; -# add_header X-Content-Type-Options "nosniff" always; -# add_header Referrer-Policy "no-referrer-when-downgrade" always; -# add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; -# -# # gzip -# gzip on; -# gzip_vary on; -# gzip_proxied any; -# gzip_comp_level 6; -# gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; - - -location ~ ^/models { - proxy_set_header Host $host; - set $upstreamName ow2-testar-decoder.xsalto.net:8090; - proxy_pass http://$upstreamName; -} - - location ~ ^/jupyter-lab/(.*)$ { - # NOTE important to also set base url of jupyterhub to /jupyter in its config - set $upstreamName jupyter-lab:8888; - proxy_pass http://$upstreamName; - - proxy_redirect off; - # proxy_buffering off; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - # websocket headers - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - #proxy_set_header Connection "upgrade"; - proxy_http_version 1.1; - proxy_set_header X-NginX-Proxy true; - proxy_hide_header Content-Security-Policy; - } - - # https://dev.to/danielkun/nginx-everything-about-proxypass-2ona - - location ^~ /pkm/ { - # https://stackoverflow.com/questions/28684300/nginx-pass-proxy-subdirectory-without-url-decoding/37584637#37584637 - set $upStream pkm:8080; - rewrite ^ $request_uri; - rewrite ^/pkm/(.*) $1 break; - return 400; #if the second rewrite won't match - - proxy_pass http://$upstream/$uri; - proxy_redirect off; - proxy_set_header Host $host; - # https://gitlab.ow2.org/decoder/frontend/-/issues/2 - client_max_body_size 100M; - } - - # constraint 1) static upstream name would prevent nginx to start if it's offline - # => need to use a variable - # constraint 2) when using a variable as upstream, the remain part of URI isn't included - # => need to capture the URI and include - # constraint 3) when using proxy_pass with a trailing slash, variable are URL-decoded... - - # This alternative does not preserve URL encoding - # location ~ ^/([\w-]+)/?(.*)$ { - # set $uriPrefix $1; - # if ($upstreamNameWithPortAndPrefix = noService) { - # return 444; - # } - # proxy_pass http://$upstreamNameWithPortAndPrefix/$2$is_args$args; - # proxy_redirect off; - # proxy_set_header Host $host; - # - # include /etc/nginx/cors.conf; - # } - - # # Possible workaround to preserve URL-encoded request and strip the prefix within the container - # # https://decoder-tool.ow2.org/srl/srl/foo/bar => http://upStream/srl/foo/bar - - location ~ ^/([\w-]+)/?(.*)$ { - include /etc/nginx/cors.conf; - set $uriPrefix $1; - if ($upstreamNameWithPortAndPrefix = noService) { - return 444; - } - rewrite ^ $request_uri; - rewrite ^/([\w-]+)/?(.*)$ /$2 break; - return 400; #if the second rewrite won't match and because the location apply after slash compression - - proxy_pass http://$upstreamNameWithPortAndPrefix$uri; - proxy_redirect off; - proxy_set_header Host $host; - } - - -} diff --git a/docker/frontend.conf.template b/docker/frontend.conf.template new file mode 100644 index 0000000000000000000000000000000000000000..5c6888515a4a78bf87169e47488523d27658325e --- /dev/null +++ b/docker/frontend.conf.template @@ -0,0 +1,22 @@ +server { + listen 80; + listen [::]:80; + server_name _; + + root /var/www/; + try_files $uri $uri/ /index.html; + + # security headers + # add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; + + # gzip + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; +}