From be4027045a8cfbc38df434c51bc7653d80928fb0 Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Thu, 28 Apr 2022 18:19:20 +0200 Subject: [PATCH] Riscritti per essere usati in una VM. --- shinyproxy/ansible_vars/nginx.yml | 49 ++++ shinyproxy/nginx.conf.j2 | 45 ---- shinyproxy/nginx.default.conf.j2 | 73 ----- shinyproxy/nginx_pep.conf.j2 | 9 + shinyproxy/nginx_virtualhost.conf.j2 | 382 +++++++++++++++++++++++++++ shinyproxy/pep-swarm.yml.j2 | 37 --- shinyproxy/pep.js.j2 | 6 +- 7 files changed, 441 insertions(+), 160 deletions(-) create mode 100644 shinyproxy/ansible_vars/nginx.yml delete mode 100644 shinyproxy/nginx.conf.j2 delete mode 100644 shinyproxy/nginx.default.conf.j2 create mode 100644 shinyproxy/nginx_pep.conf.j2 create mode 100644 shinyproxy/nginx_virtualhost.conf.j2 delete mode 100644 shinyproxy/pep-swarm.yml.j2 diff --git a/shinyproxy/ansible_vars/nginx.yml b/shinyproxy/ansible_vars/nginx.yml new file mode 100644 index 0000000..a90b160 --- /dev/null +++ b/shinyproxy/ansible_vars/nginx.yml @@ -0,0 +1,49 @@ +--- +nginx_set_frame_origin: True +nginx_x_frame_options: '' +nginx_virthosts: + - virthost_name: 'shinyproxy-test.d4science.org' + server_name: 'shinyproxy-test.d4science.org' + upstream_backends: + - name: shinyproxy_test + servers: + - '{{ docker_garr_swarm1_ip }}:8080' + - '{{ docker_garr_swarm2_ip }}:8080' + - '{{ docker_garr_swarm3_ip }}:8080' + ssl_enabled: True + ssl_only: True + ssl_letsencrypt_certs: '{{ nginx_letsencrypt_managed }}' + root: '{{ nginx_webroot }}' + server_tokens: 'off' + proxy_standard_setup: True + include_global_proxy_conf: True + websockets: True + locations: + - location: / + other_opts: + - 'js_content pep.enforce' + - location: /jwt_verify_request + target: 'https://{{ keycloak_auth_server }}/auth/realms/d4science/protocol/openid-connect/token/introspect' + other_opts: + - 'internal' + - 'proxy_method POST' + - 'gunzip on' + - 'proxy_set_header Authorization {{ keycloak_auth_credentials_prod }}' + - 'proxy_set_header Content-Type "application/x-www-form-urlencoded"' + - 'proxy_cache' + - 'proxy_cache_key $source_auth' + - 'proxy_cache_lock on' + - 'proxy_cache_valid 200 10s' + - 'proxy_ignore_headers Cache-Control Expires Set-Cookie' + - location: /_backend + - 'internal' + - 'resolver 146.48.122.10' + - 'proxy_set_header Authorization "$auth_token"' + target: 'http://shinyproxy_test$request_uri' + - location: /_accounting + target: 'https://accounting-service.d4science.org/accounting-service/record' + other_opts: + - 'internal' + - 'proxy_method POST' + - 'proxy_set_header Authorization "$auth_token"' + - 'proxy_set_header Content-Type "application/json"' diff --git a/shinyproxy/nginx.conf.j2 b/shinyproxy/nginx.conf.j2 deleted file mode 100644 index b079900..0000000 --- a/shinyproxy/nginx.conf.j2 +++ /dev/null @@ -1,45 +0,0 @@ -# Added to load njs module -load_module modules/ngx_http_js_module.so; - -user nginx; -worker_processes auto; - -error_log /var/log/nginx/error.log notice; -pid /var/run/nginx.pid; - - -events { - worker_connections 1024; -} - - -http { - - # added to import pep script - js_import pep.js; - - # added to bind enforce function - js_set $authorization pep.enforce; - - # added to create cache for tokens and auth calls - proxy_cache_path /var/cache/nginx/pep keys_zone=token_responses:1m max_size=2m; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - include /etc/nginx/conf.d/*.conf; -} - diff --git a/shinyproxy/nginx.default.conf.j2 b/shinyproxy/nginx.default.conf.j2 deleted file mode 100644 index 3f6a56a..0000000 --- a/shinyproxy/nginx.default.conf.j2 +++ /dev/null @@ -1,73 +0,0 @@ -upstream service { - ip_hash; - #server {{ shinyproxy_docker_stack_name }}_{{ shinyproxy_docker_service_server_name }}:{{ shinyproxy_service_port }}; -} - -# added to import pep script -js_import pep.js; - -# added to bind enforce function -js_set $authorization pep.enforce; - -# variables computed by njs and which may possibly be passed among locations -js_var $auth_token; -js_var $account_record; - -proxy_cache_path /tmp levels=1:2 keys_zone=social_cache:10m max_size=10g inactive=60m use_temp_path=off; - -server { - - listen *:80; - listen [::]:80; - - server_name {{ shinyproxy_service_host }}; - - subrequest_output_buffer_size 200k; - - location /health { - add_header Content-Length 0; - add_header Content-Type "text/plain"; - return 200; - } - - location / { - proxy_read_timeout 300; - proxy_send_timeout 300; - js_content pep.enforce; - } - - location /jwt_verify_request { - internal; - gunzip on; - proxy_method POST; - proxy_http_version 1.1; - proxy_set_header Authorization {{ keycloak_auth_credentials_prod }}; - proxy_set_header Content-Type "application/x-www-form-urlencoded"; - proxy_pass https://{{ keycloak_auth_server }}/auth/realms/d4science/protocol/openid-connect/token/introspect; - proxy_cache token_responses; # Enable caching - proxy_cache_key $source_auth; # Cache for each source authentication - proxy_cache_lock on; # Duplicate tokens must wait - proxy_cache_valid 200 10s; # How long to use each response - proxy_ignore_headers Cache-Control Expires Set-Cookie; - } - - - location /_backend { - internal; - proxy_read_timeout 300; - proxy_send_timeout 300; - resolver 146.48.122.10; - proxy_http_version 1.1; - proxy_set_header Authorization "$auth_token"; - proxy_pass http://service$request_uri; - } - - location /_accounting { - internal; - proxy_method POST; - proxy_http_version 1.1; - proxy_set_header Authorization $auth_token - proxy_set_header Content-Type "application/json"; - proxy_pass https://accounting-service.d4science.org/accounting-service/record; - } -} diff --git a/shinyproxy/nginx_pep.conf.j2 b/shinyproxy/nginx_pep.conf.j2 new file mode 100644 index 0000000..200bb36 --- /dev/null +++ b/shinyproxy/nginx_pep.conf.j2 @@ -0,0 +1,9 @@ +# variables computed by njs and which may possibly be passed among locations +js_var $auth_token; +js_var $account_record; + +proxy_cache_path /tmp levels=1:2 keys_zone=social_cache:10m max_size=10g inactive=60m use_temp_path=off; + +js_import /etc/nginx/conf.d/pep.js; +# added to bind enforce function +js_set $authorization pep.enforce; diff --git a/shinyproxy/nginx_virtualhost.conf.j2 b/shinyproxy/nginx_virtualhost.conf.j2 new file mode 100644 index 0000000..0ff6603 --- /dev/null +++ b/shinyproxy/nginx_virtualhost.conf.j2 @@ -0,0 +1,382 @@ +{% if nginx_websockets_support is defined and nginx_websockets_support %} +include /etc/nginx/snippets/nginx-websockets.conf; +{% else %} +{% if item.websockets is defined and item.websockets %} +include /etc/nginx/snippets/nginx-websockets.conf; +{% endif %} +{% endif %} + +{% if item.upstream_backends is defined %} +{% for u_bk in item.upstream_backends %} +upstream {{ u_bk.name }} { + {% for srv in u_bk.servers %} + server {{ srv }}; + {% endfor %} +} + +{% endfor %} +{% endif %} + +# variables computed by njs and which may possibly be passed among locations +js_var $auth_token; +js_var $account_record; + +proxy_cache_path /tmp levels=1:2 keys_zone=social_cache:10m max_size=10g inactive=60m use_temp_path=off; + +server { + listen {{ item.http_port | default ('80') }}; + server_name {{ item.server_name }} {% if item.serveraliases is defined %}{{ item.serveraliases }}{% endif %}; +{% if nginx_block_dotfiles %} + location ~ /\.(?!well-known).* { + deny all; + access_log off; + log_not_found off; + return 404; + } +{% endif %} + +{% if letsencrypt_acme_install %} + include /etc/nginx/snippets/letsencrypt-proxy.conf; +{% endif %} + + {% if item.access_log is defined %} + access_log {{ item.access_log }}; + {% else %} + access_log /var/log/nginx/{{ item.server_name }}_access.log; + {% endif %} + + {% if item.error_log is defined %} + error_log {{ item.error_log }}; + {% else %} + error_log /var/log/nginx/{{ item.server_name }}_error.log; + {% endif %} + + {% if nginx_set_xss_protection %} + proxy_hide_header X-XSS-Protection; + add_header X-XSS-Protection "1; mode=block;"; + {% endif %} + {% if nginx_set_frame_origin %} + proxy_hide_header X-Frame-Options; + add_header X-Frame-Options "{{ nginx_x_frame_options }}"; + {% endif %} + {% if nginx_set_content_security_options %} + proxy_hide_header Content-Security-Policy; + add_header Content-Security-Policy "frame-src{% for s in nginx_content_security_src_acl %} {{ s }}{% endfor %}; frame-ancestors{% for l in nginx_content_security_ancestor_acl %} {{ l }}{% endfor %};"; + {% endif %} + server_tokens {{ item.server_tokens | default('off') }}; + +{% if item.ssl_enabled and item.ssl_only %} + location / { + return 301 https://{{ item.server_name }}$request_uri; + } +{% else %} + root {{ item.root | default('/usr/share/nginx/html/') }}; + index {{ item.index | default('index.html index.htm') }}; + error_page 500 502 503 504 {{ item.error_page | default('/50x.html') }}; + location = /50x.html { + root {{ item.error_path | default('/usr/share/nginx/html') }}; + } + location = /favicon.ico { + log_not_found off; + access_log off; + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + {% if haproxy_ips is defined %} + # We are behind haproxy + {% for ip in haproxy_ips %} + set_real_ip_from {{ ip }}; + {% endfor %} + real_ip_header X-Forwarded-For; + {% endif %} + + {% if item.max_body is defined %} + client_max_body_size {{ item.max_body }}; + {% else %} + client_max_body_size {{ nginx_client_max_body_size }}; + {% endif %} + + {% if item.body_timeout is defined %} + client_body_timeout {{ item.body_timeout }}; + {% else %} + client_body_timeout {{ nginx_client_body_timeout }}; + {% endif %} + + {% if nginx_cors_enabled %} + {% if nginx_cors_global %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + + {% if item.additional_options is defined %} + {% for add_opt in item.additional_options %} + {{ add_opt }}; + {% endfor %} + {% endif %} + + {% if item.http_acls is defined %} + {% for acl in item.http_acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if nginx_websockets_support is defined and nginx_websockets_support %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% else %} + {% if item.websockets is defined and item.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% endif %} + {% endif %} + + {% if item.proxy_standard_setup is defined and item.proxy_standard_setup %} + + # Proxy stuff + {% if item.include_global_proxy_conf is defined and not item.include_global_proxy_conf %} + {% else %} + include /etc/nginx/snippets/nginx-proxy-params.conf; + {% endif %} + + {% if item.proxy_additional_options is defined %} + {% for popt in item.proxy_additional_options %} + {{ popt }}; + {% endfor %} + {% endif %} + + {% if item.locations is defined %} + {% for location in item.locations -%} + + location {{ location.location }} { + + {% if nginx_cors_enabled %} + {% if not nginx_cors_global %} + {% if location.cors is defined and location.cors %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + {% endif %} + + {% if location.target is defined %} + proxy_pass {{ location.target }}; + {% elif location.php_target is defined %} + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass {% if phpfpm_listen_on_socket is defined and phpfpm_listen_on_socket %}unix:{% endif %}{{ location.php_target }}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REMOTE_ADDR $http_x_forwarded_for; + #fastcgi_param REMOTE_ADDR $remote_addr; + include fastcgi_params; + {% endif %} + + {% if location.websockets is defined and location.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + {% endif %} + + {% if location.extra_conf is defined %} + {{ location.extra_conf }} + {% endif %} + + {% if location.acls is defined %} + {% for acl in location.acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if location.other_opts is defined %} + {% for opt in location.other_opts %} + {{ opt }}; + {% endfor %} + {% endif %} + } + {% endfor %} + {% endif %} + {% endif %} + + {% if item.extra_parameters is defined %} + {{ item.extra_parameters }} + {% endif %} + +{% endif %} + +} + +{% if item.ssl_enabled %} +server { + listen {% if item.https_port is defined %} {{ item.https_port }} {% else %} {{ https_port | default('443') }} {% endif %} ssl {% if ansible_distribution_release != "trusty" %} http2{% endif %}; + server_name {{ item.server_name }} {% if item.serveraliases is defined %}{{ item.serveraliases }}{% endif %}; + + {% if item.access_log is defined %} + access_log {{ item.access_log }}; + {% else %} + access_log /var/log/nginx/{{ item.server_name }}_ssl_access.log; + {% endif %} + + {% if item.error_log is defined %} + error_log {{ item.error_log }}; + {% else %} + error_log /var/log/nginx/{{ item.server_name }}_ssl_error.log; + {% endif %} + + root {{ item.root | default('/usr/share/nginx/html/') }}; + index {{ item.index | default('index.html index.htm') }}; + error_page 500 502 503 504 {{ item.error_page | default('/50x.html') }}; + location = /50x.html { + root {{ item.error_path | default('/usr/share/nginx/html') }}; + } + location = /favicon.ico { + log_not_found off; + access_log off; + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } +{% if nginx_block_dotfiles %} + location ~ /\.(?!well-known).* { + deny all; + access_log off; + log_not_found off; + return 404; + } +{% endif %} + + {% if haproxy_ips is defined %} + # We are behind haproxy + {% for ip in haproxy_ips %} + set_real_ip_from {{ ip }}; + {% endfor %} + real_ip_header X-Forwarded-For; + {% endif %} + + {% if item.max_body is defined %} + client_max_body_size {{ item.max_body }}; + {% else %} + client_max_body_size {{ nginx_client_max_body_size }}; + {% endif %} + {% if item.body_timeout is defined %} + client_body_timeout {{ item.body_timeout }}; + {% else %} + client_body_timeout {{ nginx_client_body_timeout }}; + {% endif %} + + include /etc/nginx/snippets/nginx-server-ssl.conf; + + {% if nginx_set_xss_protection %} + proxy_hide_header X-XSS-Protection; + add_header X-XSS-Protection "1; mode=block;"; + {% endif %} + {% if nginx_set_frame_origin %} + proxy_hide_header X-Frame-Options; + add_header X-Frame-Options "{{ nginx_x_frame_options }}"; + {% endif %} + {% if nginx_set_content_security_options %} + proxy_hide_header Content-Security-Policy; + add_header Content-Security-Policy "frame-src{% for s in nginx_content_security_src_acl %} {{ s }}{% endfor %}; frame-ancestors{% for l in nginx_content_security_ancestor_acl %} {{ l }}{% endfor %};"; + {% endif %} + server_tokens {{ item.server_tokens | default('off') }}; + + {% if nginx_cors_enabled %} + {% if nginx_cors_global %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + + {% if nginx_websockets_support is defined and nginx_websockets_support %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% else %} + {% if item.websockets is defined and item.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + {% endif %} + {% endif %} + + {% if item.additional_options is defined %} + {% for add_opt in item.additional_options %} + {{ add_opt }}; + {% endfor %} + {% endif %} + + {% if item.https_acls is defined %} + {% for acl in item.https_acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if item.proxy_standard_setup is defined and item.proxy_standard_setup %} + + # Proxy stuff + {% if item.include_global_proxy_conf is defined and not item.include_global_proxy_conf %} + {% else %} + include /etc/nginx/snippets/nginx-proxy-params.conf; + {% endif %} + + {% if item.proxy_additional_options is defined %} + {% for popt in item.proxy_additional_options %} + {{ popt }} + {% endfor %} + {% endif %} + + {% if item.locations is defined %} + {% for location in item.locations -%} + location {{ location.location }} { + + {% if nginx_cors_enabled %} + {% if not nginx_cors_global %} + {% if location.cors is defined and location.cors %} + include /etc/nginx/snippets/nginx-cors.conf; + {% endif %} + {% endif %} + {% endif %} + + {% if location.target is defined %} + proxy_pass {{ location.target }}; + {% elif location.php_target is defined %} + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass {% if phpfpm_listen_on_socket is defined and phpfpm_listen_on_socket %}unix:{% endif %}{{ location.php_target }}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param REMOTE_ADDR $http_x_forwarded_for; + #fastcgi_param REMOTE_ADDR $remote_addr; + include fastcgi_params; + {% endif %} + + {% if location.websockets is defined and location.websockets %} + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + {% endif %} + + {% if location.extra_conf is defined %} + {{ location.extra_conf }} + {% endif %} + + {% if location.acls is defined %} + {% for acl in location.acls %} + {{ acl }}; + {% endfor %} + {% endif %} + + {% if location.other_opts is defined %} + {% for opt in location.other_opts %} + {{ opt }}; + {% endfor %} + {% endif %} + } + {% endfor %} + {% endif %} + {% endif %} + + {% if item.extra_parameters is defined %} + {{ item.extra_parameters }} + {% endif %} +} + +{% endif %} diff --git a/shinyproxy/pep-swarm.yml.j2 b/shinyproxy/pep-swarm.yml.j2 deleted file mode 100644 index d3a6c83..0000000 --- a/shinyproxy/pep-swarm.yml.j2 +++ /dev/null @@ -1,37 +0,0 @@ -version: '3.6' - -services: - pep-rel: - image: nginx:stable-alpine - networks: - - {{ shinyproxy_docker_network }} - - haproxy-public - deploy: - replicas: 1 - placement: - constraints: [node.role == worker] - endpoint_mode: dnsrr - restart_policy: - condition: on-failure - delay: 10s - window: 120s - configs: - - source: nginxconf - target: /etc/nginx/templates/default.conf.template - - source: nginxbaseconf - target: /etc/nginx/nginx.conf - - source: pep - target: /etc/nginx/pep.js - -networks: - {{ shinyproxy_docker_network }}: - haproxy-public: - external: true - -configs: - nginxconf: - file: ./nginx.default.conf - nginxbaseconf: - file: ./nginx.conf - pep: - file: ./pep.js diff --git a/shinyproxy/pep.js.j2 b/shinyproxy/pep.js.j2 index d2dbb18..0be3f5a 100644 --- a/shinyproxy/pep.js.j2 +++ b/shinyproxy/pep.js.j2 @@ -32,16 +32,12 @@ function enforce(r) { } context.userinfo = { username : jwt.preferred_username } return Promise.resolve(context) - } else { - debug(context, "[PEP] failed " + reply.status + ":" + reply.responseBody) - throw new Error("Unauthorized") - } }).then(ctx => { debug(context, "[HOMESERV] creating home for username " + context.userinfo.username) return context.request.subrequest("/_homeserv", {"body" : "user=" + context.userinfo.username }) }).then(reply => { if(reply.status !== 200){ - throw new Error("Unauthorized: Unable to create home for user") + throw new Error("Unauthorized: Unable to create home for user") } context.record = buildAccountingRecord(context) return context.request.subrequest("/_backend", { method : context.request.method, args : context.request.args, headers : context.request.headersIn})