From 739510c151ffb963b7a2cfbe7d3bc1c4c38b1948 Mon Sep 17 00:00:00 2001 From: Bart Geesink Date: Tue, 16 Jan 2024 13:16:46 +0100 Subject: [PATCH] Dashboard: Add role to deploy dashboard using docker --- roles/dashboard/defaults/main.yml | 2 + roles/dashboard/handlers/main.yml | 5 + roles/dashboard/tasks/main.yml | 83 ++++++++++++++++ roles/dashboard/templates/dashboard.conf.j2 | 75 +++++++++++++++ roles/dashboard/templates/logback.xml.j2 | 29 ++++++ .../templates/serverapplication.yml.j2 | 95 +++++++++++++++++++ 6 files changed, 289 insertions(+) create mode 100644 roles/dashboard/defaults/main.yml create mode 100644 roles/dashboard/handlers/main.yml create mode 100644 roles/dashboard/tasks/main.yml create mode 100644 roles/dashboard/templates/dashboard.conf.j2 create mode 100644 roles/dashboard/templates/logback.xml.j2 create mode 100644 roles/dashboard/templates/serverapplication.yml.j2 diff --git a/roles/dashboard/defaults/main.yml b/roles/dashboard/defaults/main.yml new file mode 100644 index 000000000..1a2678d68 --- /dev/null +++ b/roles/dashboard/defaults/main.yml @@ -0,0 +1,2 @@ +dashboard_organization: SURFconext +dashboard_hide_tabs: none diff --git a/roles/dashboard/handlers/main.yml b/roles/dashboard/handlers/main.yml new file mode 100644 index 000000000..acc431504 --- /dev/null +++ b/roles/dashboard/handlers/main.yml @@ -0,0 +1,5 @@ +- name: restart dashboardserver + community.docker.docker_container: + name: dashboardserver + state: started + restart: true diff --git a/roles/dashboard/tasks/main.yml b/roles/dashboard/tasks/main.yml new file mode 100644 index 000000000..695e5a40d --- /dev/null +++ b/roles/dashboard/tasks/main.yml @@ -0,0 +1,83 @@ +--- +- name: Create directory to keep configfile + ansible.builtin.file: + dest: "/opt/openconext/dashboard" + state: directory + owner: root + group: root + mode: "0770" + +- name: Place the serverapplication configfiles + ansible.builtin.template: + src: "{{ item }}.j2" + dest: /opt/openconext/dashboard/{{ item }} + owner: root + group: root + mode: "0644" + with_items: + - serverapplication.yml + - logback.xml + - dashboard.conf + notify: restart dashboardserver + +- name: Create and start the server container + community.docker.docker_container: + name: dashboardserver + image: ghcr.io/openconext/openconext-dashboard/dashboard-server:{{ dashboard_server_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + mounts: + - source: /opt/openconext/dashboard/serverapplication.yml + target: /application.properties + type: bind + - source: /opt/openconext/dashboard/logback.xml + target: /logback.xml + type: bind + command: '--spring.config.location=./' + etc_hosts: + host.docker.internal: host-gateway + healthcheck: + test: ["CMD", "wget", "-no-verbose", "--tries=1", "--spider", "http://localhost:8080/internal/health" ] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + notify: restart dashboardserver + +- name: Create the gui container + community.docker.docker_container: + name: dashboardgui + image: ghcr.io/openconext/openconext-dashboard/dashboard-gui:{{ dashboard_gui_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + mounts: + - source: /opt/openconext/dashboard/dashboard.conf + target: /etc/apache2/sites-enabled/000-default.conf + type: bind + - source: /opt/openconext/dashboard/shibboleth2.xml + target: /etc/shibboleth/shibboleth2.xml + type: bind + labels: + traefik.http.routers.dashboardgui.rule: "Host(`dashboard.{{ base_domain }}`)" + traefik.http.routers.dashboardgui.tls: "true" + traefik.enable: "true" + healthcheck: + test: ["CMD", "curl", "--fail" , "http://localhost/internal/health" ] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + env: + HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" + OPENCONEXT_INSTANCENAME: "{{ instance_name }}" + OPENCONEXT_ENGINE_LOGOUT_URL: "https://engine.{{ base_domain }}/logout" + OPENCONEXT_HELP_EMAIL: "{{ support_email }}" + SHIB_ENTITYID: "https://dashboard.{{ base_domain }}/shibboleth" + SHIB_REMOTE_ENTITYID: "https://engine.{{ base_domain}}/authentication/idp/metadata" + SHIB_REMOTE_METADATA: "{{ shibboleth_metadata_sources.engine }}" diff --git a/roles/dashboard/templates/dashboard.conf.j2 b/roles/dashboard/templates/dashboard.conf.j2 new file mode 100644 index 000000000..048de7496 --- /dev/null +++ b/roles/dashboard/templates/dashboard.conf.j2 @@ -0,0 +1,75 @@ + # General setup for the virtual host, inherited from global configuration + ServerName https://dashboard.{{ base_domain }} + + ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-dashboard'" + CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-dashboard'" combined + + RewriteEngine on + + RewriteCond %{REQUEST_URI} !\.html$ + RewriteCond %{REQUEST_URI} !\.(js|css)(\.map)?$ + RewriteCond %{REQUEST_URI} !\.svg$ + RewriteCond %{REQUEST_URI} !\.png$ + RewriteCond %{REQUEST_URI} !\.ico$ + RewriteCond %{REQUEST_URI} !\.woff$ + RewriteCond %{REQUEST_URI} !\.woff2$ + RewriteCond %{REQUEST_URI} !\.ttf$ + RewriteCond %{REQUEST_URI} !\.eot$ + RewriteCond %{REQUEST_URI} !^/(asset-)?manifest.json$ + RewriteCond %{REQUEST_URI} !^/dashboard + RewriteCond %{REQUEST_URI} !^/spDashboard + RewriteCond %{REQUEST_URI} !^/health + RewriteCond %{REQUEST_URI} !^/info + RewriteCond %{REQUEST_URI} !^/internal + RewriteCond %{REQUEST_URI} !^/login + RewriteCond %{REQUEST_URI} !^/startSSO + RewriteCond %{REQUEST_URI} !^/fonts + RewriteRule (.*) /index.html [L] + + ProxyPreserveHost On + ProxyPass /Shibboleth.sso ! + ProxyPass /dashboard/api http://dashboardserver:8080/dashboard/api retry=0 + ProxyPassReverse /dashboard/api http://dashboardserver:8080/dashboard/api + + ProxyPass /health http://dashboardserver:8080/internal/health retry=0 + ProxyPass /info http://dashboardserver:8080/internal/info retry=0 + ProxyPass /login http://dashboardserver:8080/login retry=0 + ProxyPass /startSSO http://dashboardserver:8080/startSSO retry=0 + + ProxyPass /spDashboard/api http://dashboardserver:8080/spDashboard/api retry=0 + ProxyPassReverse /spDashboard/api http://dashboardserver:8080/spDashboard/api + + ProxyPass /internal http://dashboardserver:8080/internal retry=0 + ProxyPassReverse /internal http://dashboardserver:8080/internal + + + AuthType shibboleth + ShibUseHeaders On + ShibRequireSession On + ShibRequestSetting REMOTE_ADDR X-Forwarded-For + Require valid-user + + + DocumentRoot "/var/www/" + + + Require all granted + + + + Require all granted + + + + Require all granted + + + + Require all granted + + + Header always set X-Frame-Options "DENY" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set X-Content-Type-Options "nosniff" + + diff --git a/roles/dashboard/templates/logback.xml.j2 b/roles/dashboard/templates/logback.xml.j2 new file mode 100644 index 000000000..a73a85e17 --- /dev/null +++ b/roles/dashboard/templates/logback.xml.j2 @@ -0,0 +1,29 @@ +#jinja2:lstrip_blocks: True + + + + + + %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n + + + + + {{ smtp_server }} + {{ noreply_email }} + {{ error_mail_to }} + {{ error_subject_prefix }}Unexpected error dashboard + + + + ERROR + + + + + + + + + + diff --git a/roles/dashboard/templates/serverapplication.yml.j2 b/roles/dashboard/templates/serverapplication.yml.j2 new file mode 100644 index 000000000..90701e5ca --- /dev/null +++ b/roles/dashboard/templates/serverapplication.yml.j2 @@ -0,0 +1,95 @@ +logging.config=file:///logback.xml + +supported_language_codes={{ supported_language_codes }} +# Currently supported organizations: SURFconext, OpenConext and RCTSaai +organization={{ dashboard_organization }} + +# 8 hours +server.servlet.session.timeout=28800 + +# An empty value will be replaced with the default +server.server-header=no +server.servlet.session.cookie.secure=true + +# Team id that is used as definition of who is a 'dashboard_admin'. +dashboard.admin={{ dashboard.admin_team }} +# Team id that is used as definition of who is a 'dashboard.viewer'. +dashboard.viewer={{ dashboard.view_team }} +# Team id's comma separated that are used as definition of who is a 'dashboard_super_user'. +dashboard.super.user={{ dashboard.super_team }} + +dashboard.environment={{ env }} + +# SP Dashboard connection details +spDashboard.username={{ dashboard.sp_dashboard_user }} +spDashboard.password={{ dashboard_sp_dashboard_password }} + +# SAB connection details +sab.endpoint={{ dashboard.sab_endpoint }} +sab.username=cdk +sab.password={{ dashboard_sab_password }} + +sab-rest.endpoint={{ dashboard.sab_rest_endpoint }} +sab-rest.username=cdk +sab-rest.password={{ dashboard_sab_rest_password }} + +# SAB roles +admin.surfconext.idp.sabRole=SURFconextverantwoordelijke +viewer.surfconext.idp.sabRole=SURFconextbeheerder + +management.health.mail.enabled=true +management.endpoints.web.exposure.include=health,info +management.endpoints.web.base-path=/internal +management.endpoint.info.enabled=true +management.info.git.mode=full + +# SMTP server settings for notifications +spring.mail.host=host.docker.internal +spring.mail.port=25 + +coin-administrative-email={{ dashboard.administrative_mail }} +administration.email.enabled={{ dashboard.administration_email_enabled }} +mailBaseUrl=https://dashboard.{{ base_domain }} +systemEmail=SURFconext + +jiraBaseUrl={{ dashboard.jira_base_url }} +jiraUsername={{ dashboard.jira_username }} +jiraPassword={{ dashboard_jira_password }} +jiraProjectKey={{ dashboard.jira_project_key }} +jiraDueDateWeeks=1 +jiraEnvironment={{ dashboard.jira_environment }} + +manage.username={{ dashboard.manage_username }} +manage.password={{ manage_dashboard_secret }} +manage.manageBaseUrl={{ dashboard.manage_base_url }} + +statsUser={{ dashboard.stats_user }} +statsPassword={{ stats_dashboard_api_password }} +statsBaseUrl={{ dashboard.stats_url }} + +pdp.server={{ dashboard.pdp_server }} +pdp.username={{ dashboard.pdp_username }} +pdp.password={{ pdp_password }} + +dashboard.feature.shibboleth=true +dashboard.feature.sab={{ dashboard.feature_sab }} +dashboard.feature.manage=true +dashboard.feature.jira={{ dashboard.feature_jira }} +dashboard.feature.consent={{ dashboard.feature_consent }} +dashboard.feature.pdp=true +dashboard.feature.statistics=true +dashboard.feature.mail={{ dashboard.feature_mail }} +dashboard.feature.oidc={{ dashboard.feature_oidc }} +dashboard.feature.stepup={{ dashboard.feature_stepup }} +dashboard.feature.jiraDown={{ dashboard.feature_jiradown }} + +# Comma separated string of the entity-id of all guest Idp's +guestidp.entityids={{ dashboard.guestidp_entityids }} + +# tabs that can be hidden are: statistics,apps,policies,tickets,my_idp and user_invite +dashboard.hide_tabs={{ dashboard_hide_tabs }} + +default_loa_level={{ stepup_intrinsic_loa }} +loa_values_supported={{ stepup_loa_values_supported | join(",") }} + +authn_context_levels={{ mfa_values_supported | join(",") }}