diff --git a/environments/template/group_vars/template.yml b/environments/template/group_vars/template.yml index 6d7d3d93c..3478dce5c 100644 --- a/environments/template/group_vars/template.yml +++ b/environments/template/group_vars/template.yml @@ -1,5 +1,8 @@ --- env: "%env%" +mariadb_host: localhost +rsyslog_host: localhost +database_clients: [ "{{ mariadb_host }}" ] use_selfsigned_certs: true update_hosts_file: true use_welcome_role: true @@ -207,7 +210,7 @@ springboot_server_services: guest_qualifier: "urn:collab:org:{{ base_domain }}" engine_database_name: eb -engine_database_host: "{{ mysql_host }}" +engine_database_host: "{{ mariadb_host }}" engine_database_port: 3306 engine_database_user: ebrw engine_database_password: "{{ mysql_passwords.eb }}" @@ -254,20 +257,21 @@ shibboleth_apps: baseurl: "" shib: - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" shibboleth_database_backend: false teams: db_name: "teams" db_user: "teamsrw" db_password: "{{ mysql_passwords.teams }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" group_name_context: "urn:collab:group:{{ base_domain }}:" voot_api_user: "voot" spdashboard_api_user: "spdashboard" spdashboard_person_urn: "urn:collab:person:surfnet.nl:sp-dashboard-C133A36F-CFCA-4F3D-87CE-7ECE29773FE0" product_name: "OpenConext Teams" default_stem_name: "demo:openconext:org" + feature_invite_migration_on: False super_admins_team_urns: - "nl:surfnet:diensten:teams_super_users" - "nl:surfnet:diensten:teams_super_admin_users" @@ -329,7 +333,7 @@ pdp: password: "{{ pdp_password }}" db_user: pdp-serverrw db_password: "{{ mysql_passwords.pdp_server }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" db_name: pdp-server spring_profiles_active: test cache_policies: false @@ -344,7 +348,7 @@ aa: eb_password: "{{ aa_eb_password }}" db_user: aa-serverrw db_password: "{{ mysql_passwords.aa_server }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" db_name: aaserver authz_client_id: "aa.{{base_domain}}" authz_resource_server_id: aa @@ -359,6 +363,9 @@ aa: sab_username: coin-test sab_password: "{{ aa_sab_password }}" sab_endpoint: https://sab-ng.surfnet.nl/simplesaml/module.php/attributes/server.php + sab_rest_username: surfconexttest + sab_rest_password: "{{ aa_sab_rest_password }}" + sab_rest_endpoint: https://sab-ng.surfnet.nl surfmarket_url: https://example.org surfmarket_username: example@example.org surfmarket_password: "{{ aa_surfmarket_password }}" @@ -386,6 +393,7 @@ oidcng: key_rollover_cron_expression: "0 0 0 * * *" acr_values_supported: - https://eduid.nl/trust/validate-names + - https://eduid.nl/trust/validate-names-external - https://eduid.nl/trust/linked-institution - https://eduid.nl/trust/affiliation-student - https://refeds.org/profile/mfa @@ -405,11 +413,12 @@ myconext: mongo_password: "{{ mongo_passwords.myconext }}" rp_client_id: myconext.ala.eduid rs_client_id: myconext.rs - idp_external_validation_entity_id: http://mock-idp + verify_base_uri: "https://validate.test.eduid.nl" feature_webauthn: false feature_warning_educational_email_domain: false feature_show_connections: false - feature_use_external_validation: false + feature_id_verify: true + feature_remote_creation_api: true feature_deny_disposable_email_providers: true feature_create_eduid_institution_enabled: true feature_create_eduid_institution_landing: true @@ -441,7 +450,7 @@ manage: eb_db_user: "{{ engine_database_user }}" eb_db_password: "{{ mysql_passwords.eb }}" eb_db_name: "{{ engine_database_name }}" - eb_db_host: "{{ mysql_host }}" + eb_db_host: "{{ mariadb_host }}" mongo_port: "{{ mongo_port }}" mongo_user: managerw mongo_password: "{{ mongo_passwords.manage }}" @@ -481,6 +490,11 @@ manage: password: "{{ manage_invite_secret }}", scopes: ["READ"] } + - { + name: "sram", + password: "{{ manage_sram_secret }}", + scopes: ["READ", "WRITE_SP", "DELETE_SP"] + } - { name: "attribute-aggregation", password: "{{ aa_manage_password }}", diff --git a/environments/template/secrets/skeleton.yml b/environments/template/secrets/skeleton.yml index a112b13b1..5a68f80bb 100644 --- a/environments/template/secrets/skeleton.yml +++ b/environments/template/secrets/skeleton.yml @@ -1,10 +1,3 @@ -env: "%env%" - -mysql_host: localhost -rsyslog_host: localhost - -database_clients: [ "{{ mysql_host }}" ] - mysql_root_password: secret mysql_passwords: @@ -27,12 +20,15 @@ engine_api_metadata_push_password: secret oidcng_api_metadata_push_password: secret oidcng_api_tokens_profile_password: secret oidcng_api_tokens_eduid_password: secret -myconext_api_attribute_manipulation_password: secret +myconext_api_attribute_manipulation_password: "{noop}secret" myconext_oidcng_rs_client_secret: secret -myconext_api_attribute_aggregation_password: secret +myconext_api_attribute_aggregation_password: "{noop}secret" +myconext_api_studielink_password: "{noop}secret" myconext_client_secret: secret myconext_rs_client_secret: secret myconext_geo2lite_license_key: secret +myconext_verify_client_id: secret +myconext_verify_secret: secret engine_api_profile_password: secret engine_api_deprovision_password: secret engine_parameters_secret: secret @@ -63,6 +59,7 @@ pdp_sab_password: secret aa_eb_password: secret aa_authz_client_secret: secret aa_sab_password: secret +aa_sab_rest_password: secret aa_idin_client_secret: secret aa_orcid_password: secret aa_surfmarket_password: secret @@ -99,6 +96,7 @@ pdp_push_endpoint_secret: secret manage_sp_dashboard_secret: secret manage_sysadmin_secret: secret manage_invite_secret: secret +manage_sram_secret: secret lifecycle_symfony_secret: secret lifecycle_api_password: secret @@ -138,11 +136,12 @@ myconext_private_key: | invite_oidc_secret: secretsecret invite_rs_secret: secretsecret -invite_voot_secret: secret -invite_teams_secret: secret -invite_attribute_aggregation_secret: secret +invite_voot_secret: "{noop}secret" +invite_teams_secret: "{noop}secret" +invite_attribute_aggregation_secret: "{noop}secret" invite_manage_secret: secret -invite_lifecycle_secret: secret +invite_lifecycle_secret: "{noop}secret" +invite_profile_secret: "{noop}secret" invite_private_key_pkcs8: | -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCfpYYMgKYDICkp diff --git a/environments/vm/group_vars/vm.yml b/environments/vm/group_vars/vm.yml index f0e19510e..fa884bb2d 100644 --- a/environments/vm/group_vars/vm.yml +++ b/environments/vm/group_vars/vm.yml @@ -1,5 +1,11 @@ --- env: vm + +base_domain: "{{ env }}.openconext.org" + +rsyslog_host: localhost +mariadb_host: localhost +database_clients: [ "{{ mariadb_host }}" ] use_selfsigned_certs: true update_hosts_file: true use_welcome_role: true @@ -150,13 +156,14 @@ teams: db_name: "teams" db_user: "teamsrw" db_password: "{{ mysql_passwords.teams }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" group_name_context: "urn:collab:group:{{ base_domain }}:" voot_api_user: "voot" spdashboard_api_user: "spdashboard" spdashboard_person_urn: "urn:collab:person:surfnet.nl:sp-dashboard-C133A36F-CFCA-4F3D-87CE-7ECE29773FE0" product_name: "OpenConext Teams" default_stem_name: "demo:openconext:org" + feature_invite_migration_on: False super_admins_team_urns: - "nl:surfnet:diensten:teams_super_users" - "nl:surfnet:diensten:teams_super_admin_users" @@ -220,7 +227,7 @@ pdp: password: "{{ pdp_password }}" db_user: pdp-serverrw db_password: "{{ mysql_passwords.pdp_server }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" db_name: pdp-server spring_profiles_active: test cache_policies: false @@ -234,7 +241,7 @@ aa: eb_password: "{{ aa_eb_password }}" db_user: aa-serverrw db_password: "{{ mysql_passwords.aa_server }}" - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" db_name: aaserver authz_client_id: "aa.{{ base_domain }}" authz_resource_server_id: aa @@ -249,6 +256,9 @@ aa: sab_username: coin-test sab_password: "{{ aa_sab_password }}" sab_endpoint: https://sab-ng.surfnet.nl/simplesaml/module.php/attributes/server.php + sab_rest_username: surfconexttest + sab_rest_password: "{{ aa_sab_rest_password }}" + sab_rest_endpoint: https://sab-ng.surfnet.nl surfmarket_url: https://example.org surfmarket_username: example@example.org surfmarket_password: "{{ aa_surfmarket_password }}" @@ -276,6 +286,7 @@ oidcng: key_rollover_cron_expression: "0 0 0 * * *" acr_values_supported: - https://eduid.nl/trust/validate-names + - https://eduid.nl/trust/validate-names-external - https://eduid.nl/trust/linked-institution - https://eduid.nl/trust/affiliation-student - https://refeds.org/profile/mfa @@ -294,10 +305,11 @@ myconext: mongo_password: "{{ mongo_passwords.myconext }}" rp_client_id: myconext.ala.eduid rs_client_id: myconext.rs - idp_external_validation_entity_id: http://mock-idp + verify_base_uri: "https://validate.test.eduid.nl" feature_webauthn: false feature_warning_educational_email_domain: false - feature_use_external_validation: false + feature_id_verify: true + feature_remote_creation_api: true feature_deny_disposable_email_providers: true feature_create_eduid_institution_enabled: true feature_create_eduid_institution_landing: true @@ -328,7 +340,7 @@ manage: eb_db_user: "{{ engine_database_user }}" eb_db_password: "{{ mysql_passwords.eb }}" eb_db_name: "{{ engine_database_name }}" - eb_db_host: "{{ mysql_host }}" + eb_db_host: "{{ mariadb_host }}" mongo_port: "{{ mongo_port }}" mongo_user: "{{ manage_mongo_user }}" mongo_password: "{{ mongo_passwords.manage }}" @@ -359,13 +371,18 @@ manage: - { name: "sp-dashboard", password: "{{ manage_sp_dashboard_secret }}", - scopes: [ "READ", "WRITE_SP", "CHANGE_REQUEST_SP", "PUSH"] + scopes: [ "READ", "WRITE_SP", "DELETE_SP", "CHANGE_REQUEST_SP", "PUSH"] } - { name: "invite", password: "{{ manage_invite_secret }}", scopes: ["READ"] } + - { + name: "sram", + password: "{{ manage_sram_secret }}", + scopes: ["READ", "WRITE_SP", "DELETE_SP"] + } - { name: "sysadmin", password: "{{ manage_sysadmin_secret }}", @@ -385,6 +402,7 @@ manage: manage_show_oidc_rp_tab: true manage_exclude_oidc_rp_imports_in_push: false +manage_exclude_sram_imports_in_push: false manage_mongo_db: metadata manage_mongo_user: managerw diff --git a/environments/vm/secrets/vm.yml b/environments/vm/secrets/vm.yml index a20f93595..566ee0718 100644 --- a/environments/vm/secrets/vm.yml +++ b/environments/vm/secrets/vm.yml @@ -1,11 +1,3 @@ -env: vm -base_domain: "{{ env }}.openconext.org" - -mysql_host: localhost -rsyslog_host: localhost - -database_clients: [ "{{ mysql_host }}" ] - mysql_root_password: secret galera_clustercheck_password: secret @@ -37,12 +29,15 @@ engine_api_metadata_push_password: secret oidcng_api_metadata_push_password: secret oidcng_api_tokens_profile_password: secret oidcng_api_tokens_eduid_password: secret -myconext_api_attribute_manipulation_password: secret +myconext_api_attribute_manipulation_password: "{noop}secret" myconext_oidcng_rs_client_secret: secret -myconext_api_attribute_aggregation_password: secret +myconext_api_attribute_aggregation_password: "{noop}secret" +myconext_api_studielink_password: "{noop}secret" myconext_client_secret: secret myconext_rs_client_secret: secret myconext_geo2lite_license_key: secret +myconext_verify_client_id: secret +myconext_verify_secret: secret engine_api_profile_password: secret engine_api_deprovision_password: secret @@ -66,6 +61,7 @@ pdp_sab_password: secret aa_eb_password: secret aa_authz_client_secret: secretsecret aa_sab_password: secret +aa_sab_rest_password: secret aa_idin_client_secret: secret aa_orcid_password: secret aa_surfmarket_password: secret @@ -91,6 +87,7 @@ manage_sp_dashboard_secret: secret manage_sysadmin_secret: secret manage_stats_api_password: secret manage_invite_secret: secret +manage_sram_secret: secret manage_prod_sp_dashboard_secret: secret spdashboard_symfony_secret: secret @@ -285,11 +282,12 @@ myconext_private_key: | invite_oidc_secret: secretsecret invite_rs_secret: secretsecret -invite_voot_secret: secret -invite_teams_secret: secret -invite_attribute_aggregation_secret: secret +invite_voot_secret: "{noop}secret" +invite_teams_secret: "{noop}secret" +invite_attribute_aggregation_secret: "{noop}secret" invite_manage_secret: secret -invite_lifecycle_secret: secret +invite_lifecycle_secret: "{noop}secret" +invite_profile_secret: "{noop}secret" invite_private_key_pkcs8: | -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCfpYYMgKYDICkp diff --git a/group_vars/all.yml b/group_vars/all.yml index b2d2e3669..0fc312cc4 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -32,11 +32,11 @@ environment_ribbon_colour: "" httpd_csp: lenient: "default-src 'self'; object-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" - lenient_with_static_img: "default-src 'self'; object-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https://{{ static_vhost }} data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" - lenient_with_static_img_with_oidcng: "default-src 'self'; object-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://{{ oidcng_vhost }}; img-src 'self' https://{{ static_vhost }} data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" + lenient_with_static_img: "default-src 'self'; object-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https://{{ static_vhost }} http://localhost:* data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" + lenient_with_static_img_with_oidcng: "default-src 'self'; object-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://{{ oidcng_vhost }}; img-src 'self' https://{{ static_vhost }} http://localhost:* data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" strict: "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'; img-src 'self' data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" - strict_with_static_img: "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'; img-src 'self' https://{{ static_vhost }} data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" - lenient_with_static_img_for_idp: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self' https://{{ oidcng_vhost }}; img-src 'self' https://{{ static_vhost }} data:; form-action 'self' https://*.{{ base_domain }}; frame-ancestors 'none'; base-uri 'none'" + strict_with_static_img: "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'; img-src 'self' https://{{ static_vhost }} http://localhost:* data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'" + lenient_with_static_img_for_idp: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self' https://{{ oidcng_vhost }}; img-src 'self' https://{{ static_vhost }} http://localhost:* data:; form-action 'self' https://*.{{ base_domain }}; frame-ancestors 'none'; base-uri 'none'" nothing: "default-src 'none'; frame-ancestors 'none'; form-action 'none'; base-uri 'none'" error_subject_prefix: "[{{ ansible_hostname }}] " diff --git a/library/haproxy_commands.py b/library/haproxy_commands.py deleted file mode 100644 index 83e932c8e..000000000 --- a/library/haproxy_commands.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/env python -from ansible.module_utils.basic import * - - -def _haproxy_weight(host, weight, app_name): - return { - "host": host, "weight": str(weight) + "%", "backend": app_name + "_be" - } - - -def _haproxy_state(host, state, app_name): - return { - "host": host, "state": state, "backend": app_name + "_be", - "wait": "yes" - } - - -if __name__ == "__main__": - fields = { - "java_blauwrood_servers": {"java_blauwrood_servers": True, "type": "list"}, - "php_blauwrood_servers": {"php_blauwrood_servers": True, "type": "list"}, - "static_blauwrood_servers": {"static_blauwrood_servers": True, "type": "list"}, - "stepup_blauwrood_servers": {"stepup_blauwrood_servers": True, "type": "list"}, - "docker_blauwrood_servers": {"docker_blauwrood_servers": True, "type": "list"}, - "weight": {"type": "str"}, - "color": {"required": True, "type": "str"}, - "app_name": {"required": True, "type": "str"}, - "app_type": {"required": True, "type": "str"}, - "state": {"type": "str"} - } - module = AnsibleModule(argument_spec=fields) - java_servers = [s["label"] for s in module.params["java_blauwrood_servers"]] - php_servers = [s["label"] for s in module.params["php_blauwrood_servers"]] - static_servers = [s["label"] for s in module.params["static_blauwrood_servers"]] - stepup_servers = [s["label"] for s in module.params["stepup_blauwrood_servers"]] - docker_servers = [s["label"] for s in module.params["docker_blauwrood_servers"]] - app_name = module.params["app_name"].lower() - app_type = module.params["app_type"].lower() - - weight = module.params["weight"] - color = module.params["color"] - - state = module.params["state"] - - if app_type == "java": - servers = java_servers - elif app_type == "php": - servers = php_servers - elif app_type == "static": - servers = static_servers - elif app_type == "stepup": - servers = stepup_servers - elif app_type == "docker": - servers = docker_servers - - red_servers = [s for s in servers if s.upper().endswith("ROOD")] - blue_servers = [s for s in servers if s.upper().endswith("BLAUW")] - if color == "rood": - state_servers = red_servers - elif color == "blauw": - state_servers = blue_servers - - if state: - haproxy_items = [_haproxy_state(s, state, app_name) for s in state_servers] - module.exit_json(haproxy_items=haproxy_items) - else: - weight = int(weight[:-1]) if weight.endswith("%") else int(weight) - other_weight = 100 - weight - color = color.lower() - - red_weight = weight if color == "rood" else other_weight - blue_weight = weight if color == "blauw" else other_weight - - red_items = [_haproxy_weight(s, red_weight, app_name) for s in red_servers] - blue_items = [_haproxy_weight(s, blue_weight, app_name) for s in blue_servers] - module.exit_json(haproxy_items=red_items + blue_items) diff --git a/provision.yml b/provision.yml index 248c4f380..5a21697c3 100644 --- a/provision.yml +++ b/provision.yml @@ -162,11 +162,11 @@ roles: - { role: stepupwebauthn, tags: ['stepupwebauthn','stepup' ] } - { role: stepupazuremfa, tags: ['stepupazuremfa', 'stepup'] } - - { role: stepuptiqr, tags: ['stepuptiqr' , 'stepup'] } - { role: stepupmiddleware, tags: ['stepupmiddleware' , 'stepup'] } - { role: stepupgateway, tags: ['stepupgateway' , 'stepup'] } - { role: stepupselfservice, tags: ['stepupselfservice' , 'stepup'] } - { role: stepupra , tags: ['stepupra' , 'stepup'] } + - { role: stepupgateway , tags: ['stepupgateway' , 'stepup'] } - hosts: docker become: true @@ -177,10 +177,17 @@ - { role: teams, tags: ["teams"] } - { role: pdp, tags: ["pdp"] } - { role: voot, tags: ["voot"] } - - { role: attribute-aggregation, tags: ["aa"] } + - { role: attribute-aggregation, tags: ["aa", "attribute-aggregation"] } - { role: mujina-idp, tags: ["mujina-idp"] } - { role: oidc-playground, tags: ["oidc-playground"] } + - { role: myconext, tags: ["myconext"] } + - { role: manage, tags: ["manage"] } + - { role: oidcng, tags: ["oidcng"] } - { role: stats, tags: ["stats"] } + - { role: diyidp, tags: ["diyidp"] } + - { role: profile, tags: ["profile"] } + - { role: lifecycle, tags: ["lifecycle"] } + - { role: stepuptiqr, tags: ['stepuptiqr' , 'stepup'] } - import_playbook: "{{ environment_dir }}/playbook.yml" diff --git a/roles/attribute-aggregation/tasks/main.yml b/roles/attribute-aggregation/tasks/main.yml index 852c08a07..c1f52d97d 100644 --- a/roles/attribute-aggregation/tasks/main.yml +++ b/roles/attribute-aggregation/tasks/main.yml @@ -18,6 +18,7 @@ - serverapplication.yml - logback.xml - attributeAuthorities.yml + - apachelink.conf notify: restart attribute-aggregationserver - name: Create and start the server container @@ -50,7 +51,7 @@ "-no-verbose", "--tries=1", "--spider", - "http://localhost:8080/internal/health", + "http://localhost:8080/aa/api/internal/health", ] interval: 10s timeout: 10s @@ -78,6 +79,13 @@ retries: 3 start_period: 10s hostname: attribute-aggregation + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind env: HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" HTTPD_SERVERNAME: "aa.{{ base_domain }}" @@ -87,3 +95,43 @@ SHIB_ENTITYID: "https://aa.{{ base_domain }}/shibboleth" SHIB_REMOTE_ENTITYID: "https://engine.{{ base_domain }}/authentication/idp/metadata" SHIB_REMOTE_METADATA: "{{ shibboleth_metadata_sources.engine }}" + +- name: Create the gui link container + community.docker.docker_container: + name: aalink + image: ghcr.io/openconext/openconext-basecontainers/apache2-shibboleth:latest + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.attribute-aggregationlink.rule: "Host(`link.{{ base_domain }}`)" + traefik.http.routers.attribute-aggregationlink.tls: "true" + traefik.enable: "true" + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost/internal/health"] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + mounts: + - source: /opt/openconext/attribute-aggregation/apachelink.conf + target: /etc/apache2/sites-enabled/000-default.conf + type: bind + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind + hostname: attribute-link + env: + HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" + HTTPD_SERVERNAME: "link.{{ base_domain }}" + OPENCONEXT_INSTANCENAME: "{{ instance_name }}" + OPENCONEXT_ENGINE_LOGOUT_URL: "https://engine.{{ base_domain }}/logout" + OPENCONEXT_HELP_EMAIL: "{{ support_email }}" + SHIB_ENTITYID: "https://link.{{ base_domain }}/shibboleth" + SHIB_REMOTE_ENTITYID: "https://engine.{{ base_domain }}/authentication/idp/metadata" + SHIB_REMOTE_METADATA: "{{ shibboleth_metadata_sources.engine }}" diff --git a/roles/attribute-aggregation/templates/apachelink.conf.j2 b/roles/attribute-aggregation/templates/apachelink.conf.j2 new file mode 100644 index 000000000..a73b32d13 --- /dev/null +++ b/roles/attribute-aggregation/templates/apachelink.conf.j2 @@ -0,0 +1,41 @@ +ServerName https://${HTTPD_SERVERNAME} +RewriteEngine on +RewriteCond %{REQUEST_URI} !\.html$ +RewriteCond %{REQUEST_URI} !^/aa/ +RewriteCond %{REQUEST_URI} !^/internal/ +RewriteCond %{REQUEST_URI} !^/redirect +RewriteCond %{REQUEST_URI} !^/fonts/ +RewriteCond %{REQUEST_URI} !^/orcid +RewriteRule (.*) /index.html [L] + +Redirect /orcid https://link.{{ base_domain }}/aa/api/client/information.html +ProxyPass /Shibboleth.sso ! + +ProxyPass /redirect http://aaserver:8080/aa/api/redirect +ProxyPass /internal/health http://aaserver:8080/aa/api/internal/health +ProxyPass /internal/info http://aaserver:8080/aa/api/internal/info + +ProxyPass /aa/api http://aaserver:8080/aa/api +ProxyPassReverse /aa/api http://aaserver:8080/aa/api +ProxyPassReverse /aa/api/client http://aaserver:8080/aa/api/client + + + + AuthType shibboleth + ShibUseHeaders On + ShibRequireSession On + Require valid-user + + + +Require all granted + + +# The EB endpoints are secured with basic auth + + 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/attribute-aggregation/templates/attributeAuthorities.yml.j2 b/roles/attribute-aggregation/templates/attributeAuthorities.yml.j2 index e98342b8b..ed26c3778 100644 --- a/roles/attribute-aggregation/templates/attributeAuthorities.yml.j2 +++ b/roles/attribute-aggregation/templates/attributeAuthorities.yml.j2 @@ -175,3 +175,37 @@ authorities: ], validationRegExp: "^urn:(collab:group|mace:surf.nl):.*$" } + - { + id: "sabrest", + description: "SURF Autorisatie Beheer - REST", + endpoint: "{{ aa.sab_rest_endpoint }}", + user: "{{ aa.sab_rest_username }}", + password: "{{ aa.sab_rest_password }}", + timeOut: 1000, + timeOut: 1000, + attributes: [ + { + name: "urn:mace:dir:attribute-def:eduPersonEntitlement", + description: "URI (either URN or URL) that indicates a set of rights to specific resources.", + type: "string", + example: "urn:mace:surfnet.nl:surfnet.nl:sab:role:Instellingsbevoegde" + }, + { + name: "urn:mace:surf.nl:attribute-def:surf-autorisaties", + description: "URI (either URN or URL) that indicates a set of rights to specific resources.", + type: "string", + example: "urn:mace:surfnet.nl:surfnet.nl:sab:role:Instellingsbevoegde" + } + + ], + requiredInputAttributes: [ + { + name: "urn:mace:dir:attribute-def:uid", + }, + { + name: "urn:mace:terena.org:attribute-def:schacHomeOrganization", + } + + ], + validationRegExp: "^urn:mace:surfnet.nl:(surfnet\\.nl|surf\\.nl):sab:(role|organizationCode|organizationGUID|mobile):[A-Z0-9_+-]+$" + } diff --git a/roles/attribute-aggregation/templates/serverapplication.yml.j2 b/roles/attribute-aggregation/templates/serverapplication.yml.j2 index 5b3138cad..7929fab4b 100644 --- a/roles/attribute-aggregation/templates/serverapplication.yml.j2 +++ b/roles/attribute-aggregation/templates/serverapplication.yml.j2 @@ -34,7 +34,7 @@ security: api: lifecycle: username: {{ attribute_aggregator_api_lifecycle_username }} - password: {{ attribute_aggregator_api_lifecycle_password }} + password: "{{ attribute_aggregator_api_lifecycle_password }}" pseudo: mail_postfix: {{ attribute_aggregation_pseudo_mail_postfix }} diff --git a/roles/dashboard/tasks/main.yml b/roles/dashboard/tasks/main.yml index 0c701dfb4..c9f2def95 100644 --- a/roles/dashboard/tasks/main.yml +++ b/roles/dashboard/tasks/main.yml @@ -23,6 +23,8 @@ - name: Create and start the server container community.docker.docker_container: name: dashboardserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-dashboard/dashboard-server:{{ dashboard_server_version }} pull: true restart_policy: "always" @@ -75,6 +77,13 @@ retries: 3 start_period: 10s hostname: dashboard + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind env: HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" HTTPD_SERVERNAME: "dashboard.{{ base_domain }}" diff --git a/roles/dashboard/templates/serverapplication.yml.j2 b/roles/dashboard/templates/serverapplication.yml.j2 index b56aa5ada..11576ef72 100644 --- a/roles/dashboard/templates/serverapplication.yml.j2 +++ b/roles/dashboard/templates/serverapplication.yml.j2 @@ -6,6 +6,7 @@ organization={{ dashboard_organization }} # 8 hours server.servlet.session.timeout=28800 +server.servlet.session.cookie.secure=true # An empty value will be replaced with the default server.server-header=no @@ -48,7 +49,6 @@ 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 @@ -60,6 +60,8 @@ jiraDueDateWeeks=1 jiraEnvironment={{ dashboard.jira_environment }} jiraApikey={{ dashboard_jira_apikey }} jiraUseApiKey={{ dashboard.jira_use_api_key }} +# Timeout in milliseconds +jiraConnectionTimeout=10000 manage.username={{ dashboard.manage_username }} manage.password={{ manage_dashboard_secret }} @@ -76,10 +78,11 @@ pdp.password={{ pdp_password }} dashboard.feature.shibboleth=true dashboard.feature.sab={{ dashboard.feature_sab }} dashboard.feature.manage=true +# If feature.jira is set to false, then emails are send out when questions are asked or an entity is linked / unlinked dashboard.feature.jira={{ dashboard.feature_jira }} dashboard.feature.consent={{ dashboard.feature_consent }} # Valid choices are 'MOCK', 'PDP' or 'MANAGE', 'MOCK' is for local development -dashboard.feature.pdpSource=MANAGE +dashboard.feature.pdpSource={{ dashboard.pdp_source }} dashboard.feature.statistics=true dashboard.feature.mail={{ dashboard.feature_mail }} dashboard.feature.oidc={{ dashboard.feature_oidc }} diff --git a/roles/diyidp/defaults/main.yml b/roles/diyidp/defaults/main.yml index 6d240c194..5fe652520 100644 --- a/roles/diyidp/defaults/main.yml +++ b/roles/diyidp/defaults/main.yml @@ -1,18 +1,16 @@ --- -diyidp_fpm_user: diyidp -simplesamlphp_version: 1.19.5 -diyidp_current_release_symlink: "{{ openconext_releases_dir }}/OpenConext-diyidp" -diyidp_domain: diyidp."{{ base_domain }}" +diyidp_domain: "diyidp.{{ base_domain }}" diyidp_cert: "diyidp.crt" -diyidp_welcome_text: | - "Congratulations<\/strong>, you have successfully installed SimpleSAMLphp. This is the start page of your installation, where you will find links to test examples, diagnostics, metadata and even links to relevant documentation." diyidp: - db_host: "{{ mysql_host }}" + db_host: "{{ mariadb_host }}" db_name: diyidp db_user: diyidprw - dp_password: "{{ mysql_passwords.diyidp }}" + db_password: "{{ mysql_passwords.diyidp }}" + secretsalt: "{{ diyidp_secret_salt }} " + admin_password: "{{ diyidp_secret }}" +diyidp_secret_salt: secretsecret +diyidp_secret: secret diyidp_remotesp: - name: "{{ instance_name }} SP metadata" metadataurl: "https://engine.{{ base_domain }}/authentication/sp/metadata" acslocation: "https://engine.{{ base_domain }}/authentication/sp/consume-assertion" - diff --git a/roles/diyidp/handlers/main.yml b/roles/diyidp/handlers/main.yml index 7c4a7364e..1ef1d0ed4 100644 --- a/roles/diyidp/handlers/main.yml +++ b/roles/diyidp/handlers/main.yml @@ -1,5 +1,3 @@ --- -- name: restart apache - service: - name: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}" - state: restarted +- name: restart diyidp + command: docker restart diyidp diff --git a/roles/diyidp/tasks/main.yml b/roles/diyidp/tasks/main.yml index 74f936337..0688ddfe7 100644 --- a/roles/diyidp/tasks/main.yml +++ b/roles/diyidp/tasks/main.yml @@ -1,127 +1,108 @@ --- -- name: Add group {{ diyidp_fpm_user }} - group: - name: "{{ diyidp_fpm_user }}" - state: present - -- name: Add user {{ diyidp_fpm_user }} - user: - name: "{{ diyidp_fpm_user }}" - group: "{{ diyidp_fpm_user }}" - createhome: no - state: present - -- name: Create directory for vhosts to store PHP sessions - file: - path: "{{ php_session_dir}}/diyidp" - state: directory - owner: "{{ diyidp_fpm_user }}" - group: root - mode: 0770 - -- name: Download and unarchive the latest release - unarchive: - src: "https://github.com/simplesamlphp/simplesamlphp/releases/download/v{{ simplesamlphp_version }}/simplesamlphp-{{ simplesamlphp_version }}.tar.gz" - dest: "{{ openconext_releases_dir }}" - creates: "/opt/openconext/simplesamlphp-{{ simplesamlphp_version }}" - remote_src: yes - -- name: Install Apache vhost - template: - src: "{{ item }}.j2" - dest: "/etc/httpd/conf.d/{{ item }}" - with_items: - - diyidp.conf - notify: - - "restart httpd" - -- name: Clean up old php-fpm 5.6 config - file: - path: "/etc/php-fpm.d/diyidp-pool.conf" - state: absent - -- name: php-fpm 72 config - template: - src: "{{ item }}.j2" - dest: "/etc/opt/remi/php72/php-fpm.d/{{ item }}" - with_items: - - diyidp-pool-72.conf - notify: - - "restart php72-fpm" - -- name: Activate new DIY IDP release - file: - src: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}" - dest: "{{ diyidp_current_release_symlink }}" - state: link - notify: - - "restart httpd" - +- debug: + msg: "{{ diyidp }}" - name: Create directories - file: - path: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/{{ item }}" + ansible.builtin.file: + path: "/opt/openconext/diyidp/{{ item }}" state: directory owner: root group: root - mode: 0775 + mode: "0775" with_items: - - config + - www - metadata - - data - cert - name: Put metadata certificate in place - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/{{ diyidp_cert }}" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/cert/server.crt" + dest: "/opt/openconext/diyidp/cert/server.crt" + owner: root + group: root + mode: "0644" - name: Put metadata key in place - copy: + ansible.builtin.copy: content: "{{ diyidp_private_key }}" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/cert/server.key" - owner: "{{ diyidp_fpm_user }}" - mode: 0400 + dest: "/opt/openconext/diyidp/cert/server.key" + owner: root + group: root + mode: "0444" + notify: restart diyidp - name: Copy simplesamlphp configuration files - template: + ansible.builtin.template: src: "{{ item }}.j2" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/config/{{ item }}" + dest: "/opt/openconext/diyidp/{{ item }}" + mode: "0644" with_items: - - config.php + - config-override.php - authsources.php + notify: restart diyidp - name: Copy simplesamlphp metadata files - template: + ansible.builtin.template: src: "{{ item }}.j2" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/metadata/{{ item }}" + dest: "/opt/openconext/diyidp/metadata/{{ item }}" + mode: "0644" with_items: - saml20-idp-hosted.php - saml20-sp-remote.php + notify: restart diyidp - name: Copy showusers php script - template: + ansible.builtin.template: src: "showusers.php.j2" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/www/showusers.php" + dest: "/opt/openconext/diyidp/www/showusers.php" owner: root - mode: 0644 + mode: "0644" + notify: restart diyidp -- name: Copy frontpage definitions - template: - src: "frontpage.definition.json.j2" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/modules/core/dictionaries/frontpage.definition.json" - -- name: Copy login page definition - template: - src: "login.definition.json.j2" - dest: "{{ openconext_releases_dir }}/simplesamlphp-{{ simplesamlphp_version }}/dictionaries/login.definition.json" - -- name: Copy the database dump file - copy: - src: diyidp.sql - dest: "{{ openconext_releases_dir }}/builds/" - register: copy_diyidp_script - -- name: Import the database - shell: mysql -u {{ diyidp.db_user }} -p{{ diyidp.db_password }} -h {{ diyidp.db_host }} -D {{ diyidp.db_name }} < {{ openconext_releases_dir }}/builds/diyidp.sql - args: - creates: /var/lib/mysql/{{diyidp.db_name}}/users.frm +- name: Copy the apache config + ansible.builtin.template: + src: "000-default.conf.j2" + dest: "/opt/openconext/diyidp/000-default.conf" + owner: root + group: root + mode: "0644" + notify: restart diyidp + +- name: Create the container + community.docker.docker_container: + name: diyidp + image: cirrusid/simplesamlphp:v2.2.2 + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.diyidp.rule: "Host(`{{ diyidp_domain }}`)" + traefik.http.routers.diyidp.tls: "true" + traefik.enable: "true" + hostname: diyidp + mounts: + - source: /opt/openconext/diyidp/config-override.php + target: /var/simplesamlphp/config/config-override.php + type: bind + - source: /opt/openconext/diyidp/authsources.php + target: /var/simplesamlphp/config/authsources.php + type: bind + - source: /opt/openconext/diyidp/metadata + target: /var/simplesamlphp/config/metadata + type: bind + - source: /opt/openconext/diyidp/cert + target: /var/simplesamlphp/config/cert + type: bind + - source: /opt/openconext/diyidp/www/showusers.php + target: /var/simplesamlphp/public/showusers.php + type: bind + - source: /opt/openconext/diyidp/000-default.conf + target: /etc/apache2/sites-enabled/000-default.conf + type: bind + env: + SSP_ENABLED_MODULES: "sqlauth themesurf" + SSP_LOG_HANDLER: stderr + COMPOSER_REQUIRE: "simplesamlphp/simplesamlphp-module-sqlauth surfnet/simplesamlphp-module-themesurf:dev-main" + SSP_ENABLE_IDP: "true" + SSP_SECRET_SALT: "{{ diyidp.secretsalt }}" diff --git a/roles/diyidp/tasks/main_config.yml b/roles/diyidp/tasks/main_config.yml deleted file mode 100644 index b87f280b7..000000000 --- a/roles/diyidp/tasks/main_config.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- - -- name: Copy default config - shell: cp -r {{ simplesamlphp_dir }}/config-templates {{ simplesamlphp_dir }}/config - -- name: Copy default metadata - shell: cp -r {{ simplesamlphp_dir }}/metadata-templates {{ simplesamlphp_dir }}/metadata - -- name: Generate secretsalt - shell: tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' /dev/null;echo - register: secretsalt_raw - -- name: Getting hash of the secretsalt - set_fact: simplesamlphp_secretsalt={{ secretsalt_raw.stdout }} - -- template: - src: simplesaml_config_php.conf - dest: "{{ simplesamlphp_dir }}/config/config.php" diff --git a/roles/diyidp/tasks/vhost.yml b/roles/diyidp/tasks/vhost.yml deleted file mode 100644 index 218822bda..000000000 --- a/roles/diyidp/tasks/vhost.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- template: - src: simplesamlphp.conf - dest: /etc/apache2/sites-available/simplesamlphp.conf - backup: true - when: ansible_os_family == 'Debian' - -- template: - src: simplesamlphp.conf - dest: /etc/httpd/conf.d/simplesamlphp.conf - backup: true - when: ansible_os_family == 'RedHat' - notify: restart apache - -- command: a2ensite simplesamlphp.conf - when: ansible_os_family == 'Debian' - notify: restart apache diff --git a/roles/diyidp/templates/000-default.conf.j2 b/roles/diyidp/templates/000-default.conf.j2 new file mode 100644 index 000000000..84fa26b05 --- /dev/null +++ b/roles/diyidp/templates/000-default.conf.j2 @@ -0,0 +1,7 @@ + + DocumentRoot /var/simplesamlphp/public + + + Require all granted + + diff --git a/roles/diyidp/templates/authsources.php.j2 b/roles/diyidp/templates/authsources.php.j2 index f89d144dd..769b4939d 100644 --- a/roles/diyidp/templates/authsources.php.j2 +++ b/roles/diyidp/templates/authsources.php.j2 @@ -12,6 +12,9 @@ $config = array( 'sql_user' => array( + 'core:loginpage_links' => [ + 'users' => ['href' => '/showusers.php', 'text' => 'List of available users'], + ], 'sqlauth:SQL', 'dsn' => 'mysql:host={{ diyidp.db_host}};port=3306;dbname={{ diyidp.db_name }}', 'username' => '{{ diyidp.db_user}}', diff --git a/roles/diyidp/templates/config-override.php.j2 b/roles/diyidp/templates/config-override.php.j2 new file mode 100644 index 000000000..7418d5bfa --- /dev/null +++ b/roles/diyidp/templates/config-override.php.j2 @@ -0,0 +1,6 @@ + '/', - 'certdir' => 'cert/', - 'loggingdir' => 'log/', - 'datadir' => 'data/', - - /* - * A directory where simpleSAMLphp can save temporary files. - * - * SimpleSAMLphp will attempt to create this directory if it doesn't exist. - */ - 'tempdir' => '/tmp/simplesaml', - - - /* - * If you enable this option, simpleSAMLphp will log all sent and received messages - * to the log file. - * - * This option also enables logging of the messages that are encrypted and decrypted. - * - * Note: The messages are logged with the DEBUG log level, so you also need to set - * the 'logging.level' option to LOG_DEBUG. - */ - 'debug' => FALSE, - - - 'showerrors' => TRUE, - - /** - * Custom error show function called from SimpleSAML_Error_Error::show. - * See docs/simplesamlphp-errorhandling.txt for function code example. - * - * Example: - * 'errors.show_function' => 'sspmod_exmaple_Error_Show::show', - */ - - /** - * This option allows you to enable validation of XML data against its - * schemas. A warning will be written to the log if validation fails. - */ - 'debug.validatexml' => FALSE, - - /** - * This password must be kept secret, and modified from the default value 123. - * This password will give access to the installation page of simpleSAMLphp with - * metadata listing and diagnostics pages. - */ - 'auth.adminpassword' => '{{ diyidp_secret }}', - 'admin.protectindexpage' => true, - 'admin.protectmetadata' => false, - - /** - * This is a secret salt used by simpleSAMLphp when it needs to generate a secure hash - * of a value. It must be changed from its default value to a secret value. The value of - * 'secretsalt' can be any valid string of any length. - * - * A possible way to generate a random salt is by running the following command from a unix shell: - * tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' /dev/null;echo - */ - 'secretsalt' => '{{ diyidp_secret_salt }}', - - /* - * Some information about the technical persons running this installation. - * The email address will be used as the recipient address for error reports, and - * also as the technical contact in generated metadata. - */ - 'technicalcontact_name' => '{{ instance_name }} Administrator', - 'technicalcontact_email' => '{{ admin_email }}', - - /* - * The timezone of the server. This option should be set to the timezone you want - * simpleSAMLphp to report the time in. The default is to guess the timezone based - * on your system timezone. - * - * See this page for a list of valid timezones: http://php.net/manual/en/timezones.php - */ - 'timezone' => '{{ timezone }}', - - /* - * Logging. - * - * define the minimum log level to log - * LOG_ERR No statistics, only errors - * LOG_WARNING No statistics, only warnings/errors - * LOG_NOTICE Statistics and errors - * LOG_INFO Verbose logs - * LOG_DEBUG Full debug logs - not reccomended for production - * - * Choose logging handler. - * - * Options: [syslog,file,errorlog] - * - */ - 'logging.level' => LOG_NOTICE, - 'logging.handler' => 'syslog', - - /* - * Choose which facility should be used when logging with syslog. - * - * These can be used for filtering the syslog output from simpleSAMLphp into its - * own file by configuring the syslog daemon. - * - * See the documentation for openlog (http://php.net/manual/en/function.openlog.php) for available - * facilities. Note that only LOG_USER is valid on windows. - * - * The default is to use LOG_LOCAL5 if available, and fall back to LOG_USER if not. - */ - 'logging.facility' => defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER, - - /* - * The process name that should be used when logging to syslog. - * The value is also written out by the other logging handlers. - */ - 'logging.processname' => 'simplesamlphp', - - /* Logging: file - Logfilename in the loggingdir from above. - */ - 'logging.logfile' => 'simplesamlphp.log', - - - - /* - * Enable - * - * Which functionality in simpleSAMLphp do you want to enable. Normally you would enable only - * one of the functionalities below, but in some cases you could run multiple functionalities. - * In example when you are setting up a federation bridge. - */ - 'enable.saml20-idp' => true, - 'enable.shib13-idp' => false, - 'enable.adfs-idp' => false, - 'enable.wsfed-sp' => false, - 'enable.authmemcookie' => false, - - /* - * This value is the duration of the session in seconds. Make sure that the time duration of - * cookies both at the SP and the IdP exceeds this duration. - */ - 'session.duration' => 8 * (60*60), // 8 hours. - 'session.requestcache' => 4 * (60*60), // 4 hours - - /* - * Sets the duration, in seconds, data should be stored in the datastore. As the datastore is used for - * login and logout requests, thid option will control the maximum time these operations can take. - * The default is 4 hours (4*60*60) seconds, which should be more than enough for these operations. - */ - 'session.datastore.timeout' => (4*60*60), // 4 hours - - - /* - * Expiration time for the session cookie, in seconds. - * - * Defaults to 0, which means that the cookie expires when the browser is closed. - * - * Example: - * 'session.cookie.lifetime' => 30*60, - */ - 'session.cookie.lifetime' => 0, - - /* - * Limit the path of the cookies. - * - * Can be used to limit the path of the cookies to a specific subdirectory. - * - * Example: - * 'session.cookie.path' => '/simplesaml/', - */ - 'session.cookie.path' => '/', - - /* - * Cookie domain. - * - * Can be used to make the session cookie available to several domains. - * - * Example: - * 'session.cookie.domain' => '.example.org', - */ - 'session.cookie.domain' => NULL, - - /* - * Set the secure flag in the cookie. - * - * Set this to TRUE if the user only accesses your service - * through https. If the user can access the service through - * both http and https, this must be set to FALSE. - */ - 'session.cookie.secure' => TRUE, - - /* - * Options to override the default settings for php sessions. - */ - 'session.phpsession.cookiename' => null, - 'session.phpsession.savepath' => null, - 'session.phpsession.httponly' => true, - - /* - * Languages available and what language is default - */ - 'language.available' => array('en'), - 'language.default' => 'en', - - /* - * Extra dictionary for attribute names. - * This can be used to define local attributes. - * - * The format of the parameter is a string with :. - * - * Specifying this option will cause us to look for modules//dictionaries/.definition.json - * The dictionary should look something like: - * - * { - * "firstattribute": { - * "en": "English name", - * "no": "Norwegian name" - * }, - * "secondattribute": { - * "en": "English name", - * "no": "Norwegian name" - * } - * } - * - * Note that all attribute names in the dictionary must in lowercase. - * - * Example: 'attributes.extradictionary' => 'ourmodule:ourattributes', - */ - 'attributes.extradictionary' => NULL, - - /* - * Which theme directory should be used? - */ - //'theme.use' => 'default', - 'theme.use' => 'surfconext-diy:diytheme', - - /* - * Default IdP for WS-Fed. - */ - 'default-wsfed-idp' => 'urn:federation:pingfederate:localhost', - - /* - * Whether the discovery service should allow the user to save his choice of IdP. - */ - 'idpdisco.enableremember' => TRUE, - 'idpdisco.rememberchecked' => TRUE, - - // Disco service only accepts entities it knows. - 'idpdisco.validate' => TRUE, - - 'idpdisco.extDiscoveryStorage' => NULL, - - /* - * IdP Discovery service look configuration. - * Wether to display a list of idp or to display a dropdown box. For many IdP' a dropdown box - * gives the best use experience. - * - * When using dropdown box a cookie is used to highlight the previously chosen IdP in the dropdown. - * This makes it easier for the user to choose the IdP - * - * Options: [links,dropdown] - * - */ - 'idpdisco.layout' => 'links', - - /* - * Whether simpleSAMLphp should sign the response or the assertion in SAML 1.1 authentication - * responses. - * - * The default is to sign the assertion element, but that can be overridden by setting this - * option to TRUE. It can also be overridden on a pr. SP basis by adding an option with the - * same name to the metadata of the SP. - */ - 'shib13.signresponse' => TRUE, - - - - /* - * Authentication processing filters that will be executed for all IdPs - * Both Shibboleth and SAML 2.0 - */ - 'authproc.idp' => array( - /* Enable the authproc filter below to add URN Prefixces to all attributes - 10 => array( - 'class' => 'core:AttributeMap', 'addurnprefix' - ), */ - /* Enable the authproc filter below to automatically generated eduPersonTargetedID. - 20 => 'core:TargetedID', - */ - - // Adopts language from attribute to use in UI - 30 => 'core:LanguageAdaptor', - - /* Add a realm attribute from edupersonprincipalname - 40 => 'core:AttributeRealm', - */ - 45 => array( - 'class' => 'core:StatisticsWithAttribute', - 'attributename' => 'realm', - 'type' => 'saml20-idp-SSO', - ), - - /* When called without parameters, it will fallback to filter attributes ‹the old way› - * by checking the 'attributes' parameter in metadata on IdP hosted and SP remote. - */ - 50 => 'core:AttributeLimit', - - /* - * Search attribute "distinguishedName" for pattern and replaces if found - - 60 => array( - 'class' => 'core:AttributeAlter', - 'pattern' => '/OU=studerende/', - 'replacement' => 'Student', - 'subject' => 'distinguishedName', - '%replace', - ), - */ - - /* - * Consent module is enabled (with no permanent storage, using cookies). - - 90 => array( - 'class' => 'consent:Consent', - 'store' => 'consent:Cookie', - 'focus' => 'yes', - 'checked' => TRUE - ), - */ - // If language is set in Consent module it will be added as an attribute. - 98 => 'core:LanguageAdaptor', - ), - /* - * Authentication processing filters that will be executed for all IdPs - * Both Shibboleth and SAML 2.0 - */ - 'authproc.sp' => array( - /* - 10 => array( - 'class' => 'core:AttributeMap', 'removeurnprefix' - ), - */ - - /* When called without parameters, it will fallback to filter attributes ‹the old way› - * by checking the 'attributes' parameter in metadata on SP hosted and IdP remote. - */ - 50 => 'core:AttributeLimit', - - /* - * Generate the 'group' attribute populated from other variables, including eduPersonAffiliation. - */ - 60 => array('class' => 'core:GenerateGroups', 'eduPersonAffiliation'), - // All users will be members of 'users' and 'members' - 61 => array('class' => 'core:AttributeAdd', 'groups' => array('users', 'members')), - - // Adopts language from attribute to use in UI - 90 => 'core:LanguageAdaptor', - - - ), - - - /* - * This option configures the metadata sources. The metadata sources is given as an array with - * different metadata sources. When searching for metadata, simpleSAMPphp will search through - * the array from start to end. - * - * Each element in the array is an associative array which configures the metadata source. - * The type of the metadata source is given by the 'type' element. For each type we have - * different configuration options. - * - * Flat file metadata handler: - * - 'type': This is always 'flatfile'. - * - 'directory': The directory we will load the metadata files from. The default value for - * this option is the value of the 'metadatadir' configuration option, or - * 'metadata/' if that option is unset. - * - * XML metadata handler: - * This metadata handler parses an XML file with either an EntityDescriptor element or an - * EntitiesDescriptor element. The XML file may be stored locally, or (for debugging) on a remote - * web server. - * The XML hetadata handler defines the following options: - * - 'type': This is always 'xml'. - * - 'file': Path to the XML file with the metadata. - * - 'url': The url to fetch metadata from. THIS IS ONLY FOR DEBUGGING - THERE IS NO CACHING OF THE RESPONSE. - * - * - * Examples: - * - * This example defines two flatfile sources. One is the default metadata directory, the other - * is a metadata directory with autogenerated metadata files. - * - * 'metadata.sources' => array( - * array('type' => 'flatfile'), - * array('type' => 'flatfile', 'directory' => 'metadata-generated'), - * ), - * - * This example defines a flatfile source and an XML source. - * 'metadata.sources' => array( - * array('type' => 'flatfile'), - * array('type' => 'xml', 'file' => 'idp.example.org-idpMeta.xml'), - * ), - * - * - * Default: - * 'metadata.sources' => array( - * array('type' => 'flatfile') - * ), - */ - 'metadata.sources' => array( - array('type' => 'flatfile'), - ), - - - /* - * Configure the datastore for simpleSAMLphp. - * - * - 'phpsession': Limited datastore, which uses the PHP session. - * - 'memcache': Key-value datastore, based on memcache. - * - 'sql': SQL datastore, using PDO. - * - * The default datastore is 'phpsession'. - * - * (This option replaces the old 'session.handler'-option.) - */ - 'store.type' => 'phpsession', - - - /* - * The DSN the sql datastore should connect to. - * - * See http://www.php.net/manual/en/pdo.drivers.php for the various - * syntaxes. - */ - 'store.sql.dsn' => 'sqlite:/path/to/sqlitedatabase.sq3', - - /* - * The username and password to use when connecting to the database. - */ - 'store.sql.username' => NULL, - 'store.sql.password' => NULL, - - /* - * The prefix we should use on our tables. - */ - 'store.sql.prefix' => 'simpleSAMLphp', - - - /* - * Configuration for the MemcacheStore class. This allows you to store - * multiple redudant copies of sessions on different memcache servers. - * - * 'memcache_store.servers' is an array of server groups. Every data - * item will be mirrored in every server group. - * - * Each server group is an array of servers. The data items will be - * load-balanced between all servers in each server group. - * - * Each server is an array of parameters for the server. The following - * options are available: - * - 'hostname': This is the hostname or ip address where the - * memcache server runs. This is the only required option. - * - 'port': This is the port number of the memcache server. If this - * option isn't set, then we will use the 'memcache.default_port' - * ini setting. This is 11211 by default. - * - 'weight': This sets the weight of this server in this server - * group. http://php.net/manual/en/function.Memcache-addServer.php - * contains more information about the weight option. - * - 'timeout': The timeout for this server. By default, the timeout - * is 3 seconds. - * - * Example of redudant configuration with load balancing: - * This configuration makes it possible to lose both servers in the - * a-group or both servers in the b-group without losing any sessions. - * Note that sessions will be lost if one server is lost from both the - * a-group and the b-group. - * - * 'memcache_store.servers' => array( - * array( - * array('hostname' => 'mc_a1'), - * array('hostname' => 'mc_a2'), - * ), - * array( - * array('hostname' => 'mc_b1'), - * array('hostname' => 'mc_b2'), - * ), - * ), - * - * Example of simple configuration with only one memcache server, - * running on the same computer as the web server: - * Note that all sessions will be lost if the memcache server crashes. - * - * 'memcache_store.servers' => array( - * array( - * array('hostname' => 'localhost'), - * ), - * ), - * - */ - 'memcache_store.servers' => array( - array( - array('hostname' => 'localhost'), - ), - ), - - - /* - * This value is the duration data should be stored in memcache. Data - * will be dropped from the memcache servers when this time expires. - * The time will be reset every time the data is written to the - * memcache servers. - * - * This value should always be larger than the 'session.duration' - * option. Not doing this may result in the session being deleted from - * the memcache servers while it is still in use. - * - * Set this value to 0 if you don't want data to expire. - * - * Note: The oldest data will always be deleted if the memcache server - * runs out of storage space. - */ - 'memcache_store.expires' => 36 * (60*60), // 36 hours. - - - /* - * Should signing of generated metadata be enabled by default. - * - * Metadata signing can also be enabled for a individual SP or IdP by setting the - * same option in the metadata for the SP or IdP. - */ - 'metadata.sign.enable' => FALSE, - - /* - * The default key & certificate which should be used to sign generated metadata. These - * are files stored in the cert dir. - * These values can be overridden by the options with the same names in the SP or - * IdP metadata. - * - * If these aren't specified here or in the metadata for the SP or IdP, then - * the 'certificate' and 'privatekey' option in the metadata will be used. - * if those aren't set, signing of metadata will fail. - */ - 'metadata.sign.privatekey' => NULL, - 'metadata.sign.privatekey_pass' => NULL, - 'metadata.sign.certificate' => NULL, - - - /* - * Proxy to use for retrieving URLs. - * - * Example: - * 'proxy' => 'tcp://proxy.example.com:5100' - */ - 'proxy' => NULL, - - 'trusted.url.domains' => array(), - 'module.enable' => [ - 'sqlauth' => true, - ], - -); diff --git a/roles/diyidp/templates/diyidp-pool-72.conf.j2 b/roles/diyidp/templates/diyidp-pool-72.conf.j2 deleted file mode 100644 index 33da0c132..000000000 --- a/roles/diyidp/templates/diyidp-pool-72.conf.j2 +++ /dev/null @@ -1,225 +0,0 @@ -; Create a new pool named diyidp. -[diyidp] - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses on a -; specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. - -; Use unix socket -listen = /var/run/php-fpm/diyidp-pool-72.sock -; Set listen(2) backlog. A value of '-1' means unlimited. -; Default Value: -1 -;listen.backlog = -1 - -; List of ipv4 addresses of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -listen.allowed_clients = 127.0.0.1 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0666 -listen.owner = apache -listen.group = apache -listen.mode = 0640 - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = {{ diyidp_fpm_user }} -group = {{ diyidp_fpm_user }} - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives: -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; Note: This value is mandatory. -pm = ondemand - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes to be created when pm is set to 'dynamic'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. -; Note: Used when pm is set to either 'static' or 'dynamic' -; Note: This value is mandatory. -pm.max_children = 20 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -;pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.max_spare_servers = 5 - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -pm.max_requests = 300 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. By default, the status page shows the following -; information: -; accepted conn - the number of request accepted by the pool; -; pool - the name of the pool; -; process manager - static or dynamic; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes. -; The values of 'idle processes', 'active processes' and 'total processes' are -; updated each second. The value of 'accepted conn' is updated in real time. -; Example output: -; accepted conn: 12073 -; pool: www -; process manager: static -; idle processes: 35 -; active processes: 65 -; total processes: 100 -; By default the status page output is formatted as text/plain. Passing either -; 'html' or 'json' as a query string will return the corresponding output -; syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_terminate_timeout = 0 - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -slowlog = /var/log/php-fpm/www-slow.log - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. This value must be an absolute path. -; Default Value: current directory or / when chroot -;chdir = /var/www - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Default Value: no -;catch_workers_output = yes - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; exectute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -php_admin_value[error_log] = /var/log/php-fpm/diyidp-error.log -php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 128M - -; Set session path to a directory owned by process user -php_value[session.save_handler] = files -php_value[session.save_path] = {{ php_session_dir }}/diyidp -php_value[disable_functions] = {{ php_disabled_functions }} diff --git a/roles/diyidp/templates/diyidp.conf.j2 b/roles/diyidp/templates/diyidp.conf.j2 deleted file mode 100644 index c055f3b82..000000000 --- a/roles/diyidp/templates/diyidp.conf.j2 +++ /dev/null @@ -1,30 +0,0 @@ -Listen {{ apache_app_listen_address.diyidp }}:{{ loadbalancing.diyidp.port }} - - ServerName https://{{ diyidp_domain }} - ServerAdmin {{ admin_email }} - DirectoryIndex index.php - DocumentRoot {{ diyidp_current_release_symlink }}/www - - SetEnv HTTPS on - Alias /simplesaml "{{ diyidp_current_release_symlink }}/www" - - Require all granted - - Options -MultiViews - RewriteEngine On - - - Redirect permanent /simplesaml/showusers.php /showusers.php - - # Proxy the requests to FPM - ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php-fpm/diyidp-pool-72.sock|fcgi://localhost/{{ diyidp_current_release_symlink }}/www/$1 - {% if haproxy_backend_tls %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/backend.{{ base_domain }}.pem - SSLCertificateKeyFile {{ tls.cert_private_path }}/backend.{{ base_domain }}.key - Include ssl_backend.conf - {% endif %} - - ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-DIYIDP'" - CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-DIYIDP'" combined - diff --git a/roles/diyidp/templates/frontpage.definition.json.j2 b/roles/diyidp/templates/frontpage.definition.json.j2 deleted file mode 100644 index b42c6eb6f..000000000 --- a/roles/diyidp/templates/frontpage.definition.json.j2 +++ /dev/null @@ -1,146 +0,0 @@ -{ - "page_title": { - "en": "SimpleSAMLphp installation page" - }, - "intro": { - "en": {{ diyidp_welcome_text }} - }, - "useful_links_header": { - "en": "Useful links for your installation" - }, - "metadata_header": { - "en": "Metadata" - }, - "doc_header": { - "en": "Documentation" - }, - "checkphp": { - "en": "Checking your PHP installation" - }, - "about_header": { - "en": "About SimpleSAMLphp" - }, - "about_text": { - "en": "This SimpleSAMLphp thing is pretty cool, where can I read more about it? You can find more information about it at the SimpleSAMLphp web page <\/a> over at UNINETT<\/a>." - }, - "required": { - "en": "Required" - }, - "required_ldap": { - "en": "Required for LDAP" - }, - "required_radius": { - "en": "Required for Radius" - }, - "optional": { - "en": "Optional" - }, - "reccomended": { - "en": "Recommended" - }, - "warnings": { - "en": "Warnings" - }, - "warnings_https": { - "en": "You are not using HTTPS<\/strong> - encrypted communication with the user. HTTP works fine for test purposes, but in a production environment, you should use HTTPS. [ Read more about SimpleSAMLphp maintenance<\/a> ]" - }, - "warnings_secretsalt": { - "en": "The configuration uses the default secret salt - make sure you modify the default 'secretsalt' option in the simpleSAML configuration in production environments. [Read more about SimpleSAMLphp configuration<\/a> ]" - }, - "warnings_suhosin_url_length": { - "en": "The length of query parameters is limited by the PHP Suhosin extension. Please increase the suhosin.get.max_value_length option to at least 2048 bytes." - }, - "link_saml2example": { - "en": "SAML 2.0 SP example - test logging in through your IdP" - }, - "link_shib13example": { - "en": "Shibboleth 1.3 SP example - test logging in through your Shib IdP" - }, - "link_openidprovider": { - "en": "OpenID Provider site - Alpha version (test code)" - }, - "link_diagnostics": { - "en": "Diagnostics on hostname, port and protocol" - }, - "link_phpinfo": { - "en": "PHP info" - }, - "link_meta_overview": { - "en": "Metadata overview for your installation. Diagnose your metadata files" - }, - "link_meta_saml2sphosted": { - "en": "Hosted SAML 2.0 Service Provider Metadata (automatically generated)" - }, - "link_meta_saml2idphosted": { - "en": "Hosted SAML 2.0 Identity Provider Metadata (automatically generated)" - }, - "link_meta_shib13sphosted": { - "en": "Hosted Shibboleth 1.3 Service Provider Metadata (automatically generated)" - }, - "link_meta_shib13idphosted": { - "en": "Hosted Shibboleth 1.3 Identity Provider Metadata (automatically generated)" - }, - "link_xmlconvert": { - "en": "XML to SimpleSAMLphp metadata converter" - }, - "link_doc_install": { - "en": "Installing SimpleSAMLphp" - }, - "link_doc_sp": { - "en": "Using SimpleSAMLphp as a Service Provider" - }, - "link_doc_idp": { - "en": "Using SimpleSAMLphp as an Identity Provider" - }, - "link_doc_shibsp": { - "en": "Configure Shibboleth 1.3 SP to work with SimpleSAMLphp IdP" - }, - "link_doc_googleapps": { - "en": "SimpleSAMLphp as an IdP for Google Apps for Education" - }, - "link_doc_advanced": { - "en": "SimpleSAMLphp Advanced Features" - }, - "link_doc_maintenance": { - "en": "SimpleSAMLphp Maintenance and Configuration" - }, - "link_configcheck": { - "en": "SimpleSAMLphp configuration check" - }, - "link_cleardiscochoices": { - "en": "Delete my choices of IdP in the IdP discovery services" - }, - "welcome": { - "en": "Welcome" - }, - "configuration": { - "en": "Configuration" - }, - "metadata": { - "en": "Metadata" - }, - "tools": { - "en": "Tools" - }, - "show_metadata": { - "en": "Show metadata" - }, - "login_as_admin": { - "en": "Login as administrator" - }, - "loggedin_as_admin": { - "en": "You are logged in as administrator" - }, - "auth": { - "en": "Authentication" - }, - "federation": { - "en": "Federation" - }, - "authtest": { - "en": "Test configured authentication sources " - }, - "deprecated": { - "en": "Deprecated" - } -} diff --git a/roles/diyidp/templates/login.definition.json.j2 b/roles/diyidp/templates/login.definition.json.j2 deleted file mode 100644 index a7c0969e9..000000000 --- a/roles/diyidp/templates/login.definition.json.j2 +++ /dev/null @@ -1,68 +0,0 @@ -{ - "error_header": { - "en": "Error" - }, - "user_pass_header": { - "en": "Enter your username and password" - }, - "user_pass_text": { - "en": "A service has requested you to authenticate yourself. Please enter your username and password in the form below.

The list of known users and their attributes is available here.

" - }, - "login_button": { - "en": "Login" - }, - "processing": { - "en": "Processing..." - }, - "username": { - "en": "Username" - }, - "organization": { - "en": "Organization" - }, - "password": { - "en": "Password" - }, - "help_header": { - "en": "Help! I don't remember my password." - }, - "help_text": { - "en": "Too bad! - Without your username and password you cannot authenticate yourself for access to the service. There may be someone that can help you. Consult the help desk at your organization!" - }, - "error_nopassword": { - "en": "You sent something to the login page, but for some reason the password was not sent. Try again please." - }, - "error_wrongpassword": { - "en": "Incorrect username or password." - }, - "select_home_org": { - "en": "Choose your home organization" - }, - "next": { - "en": "Next" - }, - "change_home_org_title": { - "en": "Change your home organization" - }, - "change_home_org_text": { - "en": "You have chosen %HOMEORG%<\/b> as your home organization. If this is wrong you may choose another one." - }, - "change_home_org_button": { - "en": "Choose home organization" - }, - "help_desk_link": { - "en": "Help desk homepage" - }, - "help_desk_email": { - "en": "Send e-mail to help desk" - }, - "contact_info": { - "en": "Contact information:" - }, - "remember_username": { - "en": "Remember my username" - }, - "remember_me": { - "en": "Remember me" - } -} diff --git a/roles/diyidp/templates/saml20-idp-hosted.php.j2 b/roles/diyidp/templates/saml20-idp-hosted.php.j2 index 22cfaff44..6b8577f55 100644 --- a/roles/diyidp/templates/saml20-idp-hosted.php.j2 +++ b/roles/diyidp/templates/saml20-idp-hosted.php.j2 @@ -5,7 +5,7 @@ * See: https://rnd.feide.no/content/idp-hosted-metadata-reference */ -$metadata['__DYNAMIC:1__'] = array( +$metadata['https://diyidp.{{ base_domain}}'] = array( /* * The hostname of the server (VHOST) that will use this SAML entity. * @@ -49,23 +49,6 @@ $metadata['__DYNAMIC:1__'] = array( // Convert LDAP names to oids. 100 => array('class' => 'core:AttributeMap', 'name2oid'), 200 => array('class' => 'core:AttributeMap', 'name2urn'), - 300 => array('class' => 'saml:PersistentNameID', 'attribute' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6' ), + 300 => array('class' => 'saml:PersistentNameID', 'identifyingAttribute' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6' ), ), - - /* - * Uncomment the following to specify the registration information in the - * exported metadata. Refer to: - * http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/cs01/saml-metadata-rpi-v1.0-cs01.html - * for more information. - */ - /* - 'RegistrationInfo' => array( - 'authority' => 'urn:mace:example.org', - 'instant' => '2008-01-17T11:28:03Z', - 'policies' => array( - 'en' => 'http://example.org/policy', - 'es' => 'http://example.org/politica', - ), - ), - */ ); diff --git a/roles/diyidp/templates/showusers.php.j2 b/roles/diyidp/templates/showusers.php.j2 index 8aa11b589..ad13e89b0 100644 --- a/roles/diyidp/templates/showusers.php.j2 +++ b/roles/diyidp/templates/showusers.php.j2 @@ -4,17 +4,30 @@ $dbuser = "{{ diyidp.db_user }}"; $dbpass = "{{ diyidp.db_password }}"; $dbhost = "{{ diyidp.db_host }}"; - -function doQuery($qryString, $dbuser, $dbpass, $dbhost) { - - // Make a MySQL Connection - mysql_connect($dbhost, $dbuser, $dbpass) or die(mysql_error()); - - // Retrieve the data - $setUTF8 = mysql_query("SET NAMES utf8"); - $result = mysql_query($qryString) or die(mysql_error()); - - return $result; +$dbname = "{{ diyidp.db_name }}"; + +function doQuery($qryString, $dbuser, $dbpass, $dbhost, $dbname) { + try { + // Create a new PDO connection + $dsn = "mysql:host=$dbhost;dbname=$dbname;charset=utf8"; + $pdo = new PDO($dsn, $dbuser, $dbpass); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Prepare and execute the query + $stmt = $pdo->prepare($qryString); + $stmt->execute(); + // Return the rows + $rows = []; + while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) { + $rows[] = $r; + } + + return $rows; + + } + catch (PDOException $e) { + die("PDO Error: " . $e->getMessage()); + } } /** @@ -206,14 +219,7 @@ GROUP BY diy.uid ORDER BY LPAD(lower(username), 2,0), LPAD(lower(username), 10,0)"; // Run the query - $qryrset = doQuery($sqlString, $dbuser, $dbpass, $dbhost); - - //var_dump($qryrset); - - $rows = array(); - while($r = mysql_fetch_assoc($qryrset)) { - $rows[] = $r; - } + $rows = doQuery($sqlString, $dbuser, $dbpass, $dbhost, $dbname); $htmlTable = array2table($rows); print_r($htmlTable); diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 144c89f1c..70892703d 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -130,3 +130,25 @@ service: iptablesdocker.service enabled: true state: started + +- name: Create OpenConext common files dir + ansible.builtin.file: + state: directory + path: "/opt/openconext/common/" + owner: root + mode: "0755" + +- name: Check if a favicon exists + ansible.builtin.stat: + path: "{{ inventory_dir }}/files/favicon.ico" + delegate_to: localhost + register: favicon_present + become: false + +- name: Place the favicon file + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/favicon.ico" + dest: /opt/openconext/common/favicon.ico + owner: root + group: root + mode: "0644" diff --git a/roles/docker/templates/traefik.yaml.j2 b/roles/docker/templates/traefik.yaml.j2 index e303744ca..43230fcf2 100644 --- a/roles/docker/templates/traefik.yaml.j2 +++ b/roles/docker/templates/traefik.yaml.j2 @@ -10,11 +10,13 @@ providers: entryPoints: websecure: address: ":443" +{% if engine_trusted_proxy_ips is defined %} forwardedHeaders: trustedIPs: {% for engine_trusted_proxy_ip in engine_trusted_proxy_ips %} - {{ engine_trusted_proxy_ip }} {% endfor %} +{% endif %} # Server transport configuration serversTransport: insecureSkipVerify: true diff --git a/roles/haproxy/templates/haproxy_frontend.cfg.j2 b/roles/haproxy/templates/haproxy_frontend.cfg.j2 index 1857784c1..6082e9c03 100644 --- a/roles/haproxy/templates/haproxy_frontend.cfg.j2 +++ b/roles/haproxy/templates/haproxy_frontend.cfg.j2 @@ -198,5 +198,6 @@ frontend localhost_restricted acl securitytxt path /.well-known/security.txt http-request redirect location {{ haproxy_securitytxt_target_url }} if securitytxt {% endif %} + http-request redirect location %[base,map_reg(/etc/haproxy/maps/redirects.map)] if { base,map_reg(/etc/haproxy/maps/redirects.map) -m found } {% endif %} diff --git a/roles/haproxy/templates/validvhostsunrestricted.acl.j2 b/roles/haproxy/templates/validvhostsunrestricted.acl.j2 index 52ea259f5..b62774518 100644 --- a/roles/haproxy/templates/validvhostsunrestricted.acl.j2 +++ b/roles/haproxy/templates/validvhostsunrestricted.acl.j2 @@ -9,4 +9,4 @@ {{ application.hostname }} {% endif %} {% endfor %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/roles/haproxy_mgnt/tasks/main.yml b/roles/haproxy_mgnt/tasks/main.yml index 5babeb3f3..86eacf6ba 100644 --- a/roles/haproxy_mgnt/tasks/main.yml +++ b/roles/haproxy_mgnt/tasks/main.yml @@ -1,74 +1,59 @@ --- -- name: Check if the patchproces is running, except when called from the patchproces - stat: - path: /tmp/patchprocesstarted - register: patch_process_started +- name: Extract list of application names + ansible.builtin.set_fact: + app_names: "{{ haproxy_applications | map(attribute='name') | list }}" -- block: - - name: End the play if the patchprocess is running - debug: - msg: "The patchprocess is running. No loadbalancer management allowed" - - meta: end_play - when: patch_process_started.stat.exists and skip_patch_check is not defined +- name: Check if dynamic_input exists in haproxy_applications + ansible.builtin.set_fact: + app_exists: "{{ app_name in app_names }}" -- name: get new weight for haproxy hosts - haproxy_commands: - java_blauwrood_servers: "{{ java_blauwrood_servers }}" - php_blauwrood_servers: "{{ php_blauwrood_servers }}" - static_blauwrood_servers: "{{ static_blauwrood_servers }}" - stepup_blauwrood_servers: "{{ stepup_blauwrood_servers }}" - docker_blauwrood_servers: "{{ docker_blauwrood_servers }}" - weight: "{{ weight }}" - color: "{{ color }}" - app_name: "{{ app_name }}" - app_type: "{{ app_type }}" - when: weight is defined - register: haproxy_weights +- name: Fail if dynamic_input does not exist in haproxy_applications + ansible.builtin.fail: + msg: "The application '{{ app_name }}' does not exist in haproxy_applications. Available applications are: {{ app_names | join(', ') }}" + when: not app_exists -- name: get new state for haproxy hosts - haproxy_commands: - java_blauwrood_servers: "{{ java_blauwrood_servers }}" - php_blauwrood_servers: "{{ php_blauwrood_servers }}" - static_blauwrood_servers: "{{ static_blauwrood_servers }}" - stepup_blauwrood_servers: "{{ stepup_blauwrood_servers }}" - docker_blauwrood_servers: "{{ docker_blauwrood_servers }}" - color: "{{ color }}" - state: "{{ state }}" - app_name: "{{ app_name }}" - app_type: "{{ app_type }}" - when: state is defined - register: haproxy_states +- name: Set the complementing weight + ansible.builtin.set_fact: + weight_complementing: "{{ 100 - weight | int }}" -- name: dump weight output - debug: - msg: '{{ haproxy_weights.haproxy_items }}' - when: weight is defined +- name: Get the server list from the servers configured in haproxy_applications + ansible.builtin.set_fact: + selected_servers: "{{ (haproxy_applications | selectattr('name', 'equalto', app_name) | map(attribute='servers') | first) }}" -- name: dump state output - debug: - msg: '{{ haproxy_states.haproxy_items }}' - when: state is defined +- name: Check if the patchproces is running, except when called from the patchproces + ansible.builtin.stat: + path: /tmp/patchprocesstarted + register: patch_process_started -- name: set weights for haproxy hosts - haproxy: +- block: + - name: End the play if the patchprocess is running + ansible.builtin.debug: + msg: "The patchprocess is running. No loadbalancer management allowed" + - ansible.builtin.meta: end_play + when: patch_process_started.stat.exists and skip_patch_check is not defined + +- name: Create an empty list + ansible.builtin.set_fact: + server_labels_with_weights: [] + +- name: Create list with labels and weights as dictionaries + ansible.builtin.set_fact: + server_labels_with_weights: "{{ server_labels_with_weights + [{ 'label': item.label, 'weight': (weight if item[app_filter] == app_filtervalue else weight_complementing) }] }}" + loop: "{{ selected_servers }}" + +- name: Show the created list + ansible.builtin.debug: + msg: "{{ server_labels_with_weights }}" + +- name: Set weights for haproxy hosts + community.general.haproxy: state: enabled - host: "{{ item.host }}" - fail_on_not_found: yes - socket: /var/lib/haproxy/haproxy.stats - weight: "{{ item.weight }}" - backend: "{{ item.backend }}" - with_items: "{{ haproxy_weights.haproxy_items }}" - when: weight is defined - -- name: set state for haproxy hosts - haproxy: - state: "{{ item.state }}" - host: "{{ item.host }}" - fail_on_not_found: yes + host: "{{ item.label }}" + fail_on_not_found: true socket: /var/lib/haproxy/haproxy.stats - backend: "{{ item.backend }}" - with_items: "{{ haproxy_states.haproxy_items }}" - when: state is defined + weight: "{{ item.weight }}%" + backend: "{{ app_name }}_be" + with_items: "{{ server_labels_with_weights }}" - name: Write the state to the correct state file - shell: echo "show servers state" | socat /var/lib/haproxy/haproxy.stats - > /var/lib/haproxy/state + ansible.builtin.shell: echo "show servers state" | socat /var/lib/haproxy/haproxy.stats - > /var/lib/haproxy/state diff --git a/roles/invite/defaults/main.yml b/roles/invite/defaults/main.yml index 8d54ac551..60e35df36 100644 --- a/roles/invite/defaults/main.yml +++ b/roles/invite/defaults/main.yml @@ -2,7 +2,7 @@ invite_manage_provision_oidcrp_client_id: "{{ invite.oidc_client_id }}" invite_manage_provision_oidcrp_name_en: "{{ instance_name }} invite" invite_manage_provision_oidcrp_description_en: "{{ instance_name }} invite" invite_manage_provision_oidcrp_secret: "{{ invite.oidc_secret }}" -invite_manage_provision_oidcrp_redirecturls: "https://invite.{{ base_domain }}/login/oauth2/code/oidcng" +invite_manage_provision_oidcrp_redirecturls: "https://invite.{{ base_domain }}/login/oauth2/code/oidcng" invite_manage_provision_oidcrp_grants: "authorization_code" invite_manage_provision_oidcrp_allowed_resource_servers: '{"name": "{{ invite.resource_server_id }}"}' invite_manage_provision_oidcrp_is_public_client: false @@ -13,3 +13,5 @@ invite_manage_provision_oauth_rs_client_id: "{{ invite.resource_server_id }}" invite_manage_provision_oauth_rs_rp_secret: "{{ invite.resource_server_secret }}" invite_manage_provision_oauth_rs_scopes: "openid" invite_mock_install: false +# Override is in the dockerX.env host_var files +invite_cronjobmaster: true diff --git a/roles/invite/tasks/main.yml b/roles/invite/tasks/main.yml index 66c605da9..de22eca9c 100644 --- a/roles/invite/tasks/main.yml +++ b/roles/invite/tasks/main.yml @@ -51,6 +51,8 @@ - name: Create and start the server container community.docker.docker_container: name: inviteserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-invite/inviteserver:{{ invite_server_version }} pull: true restart_policy: "always" @@ -76,7 +78,6 @@ timeout: 10s retries: 3 start_period: 10s - notify: restart inviteserver - name: Create the client container community.docker.docker_container: @@ -97,6 +98,10 @@ timeout: 10s retries: 3 start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind env: HTTPD_CSP: "{{ httpd_csp.strict_with_static_img }}" @@ -119,6 +124,10 @@ timeout: 10s retries: 3 start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind env: HTTPD_CSP: "{{ httpd_csp.strict_with_static_img }}" @@ -134,6 +143,9 @@ - source: /opt/openconext/invite/mockapplication.yml target: /application.yml type: bind + - source: /etc/localtime + target: /etc/localtime + type: bind networks: - name: "loadbalancer" labels: @@ -148,7 +160,6 @@ retries: 3 start_period: 10s when: invite_mock_install - notify: restart inviteprovisioningmock - name: Include the role manage_provision_entities to provision invite client to Manage ansible.builtin.include_role: diff --git a/roles/invite/templates/mockapplication.yml.j2 b/roles/invite/templates/mockapplication.yml.j2 index fe1e6c390..621fffe8b 100644 --- a/roles/invite/templates/mockapplication.yml.j2 +++ b/roles/invite/templates/mockapplication.yml.j2 @@ -18,7 +18,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://{{ invite.db_host }}/invite username: {{ invite.db_user }} - password: {{ invite.db_secret }} + password: "{{ invite.db_secret }}" server: port: 8081 diff --git a/roles/invite/templates/serverapplication.yml.j2 b/roles/invite/templates/serverapplication.yml.j2 index 33de0fafe..d8567077e 100644 --- a/roles/invite/templates/serverapplication.yml.j2 +++ b/roles/invite/templates/serverapplication.yml.j2 @@ -12,7 +12,7 @@ server: error: path: "/error" include-message: always - forward-headers-strategy: framework + forward-headers-strategy: native servlet: session: cookie: @@ -24,6 +24,11 @@ spring: session: jdbc: initialize-schema: always +{% if invite_cronjobmaster is defined and invite_cronjobmaster == false %} + cleanup-cron: "-" +{% else %} + cleanup-cron: "0 */5 * * * *" +{% endif %} store-type: jdbc timeout: 8h mvc: @@ -61,14 +66,14 @@ spring: locations: classpath:db/{vendor}/migration fail-on-missing-locations: true mail: - host: {{ smtp_host }} + host: {{ smtp_server }} crypto: development-mode: False private-key-location: file:///private_key_pkcs8.pem cron: - node-cron-job-responsible: true + node-cron-job-responsible: {{ invite_cronjobmaster }} user-cleaner-expression: "0 0/30 * * * *" last-activity-duration-days: 1000 role-expiration-notifier-expression: "0 0/30 * * * *" @@ -107,24 +112,38 @@ config: past-date-allowed: {{ invite.past_date_allowed }} eduid-idp-schac-home-organization: {{ invite.eduid_idp_schac_home_organization }} +# We don't encode in-memory passwords, so we need to prefix them with {noop} +external-api-configuration: + remote-users: + - + username: {{ invite.vootuser }} + password: "{{ invite.vootsecret }}" + scopes: + - voot + - + username: {{ invite.teamsuser}} + password: "{{ invite.teamssecret }}" + scopes: + - teams + - + username: {{ aa.invite_username }} + password: "{{ invite_attribute_aggregation_secret }}" + scopes: + - attribute_aggregation + - + username: {{ invite.lifecycle_user }} + password: "{{ invite.lifecycle_secret }}" + scopes: + - lifecycle + - + username: {{ invite.profile_user }} + password: "{{ invite.profile_secret }}" + scopes: + - profile + voot: - user: {{ invite.vootuser }} - password: {{ invite.vootsecret }} group_urn_domain: "{{ invite.group_urn_domain }}" -teams: - user: {{ invite.teamsuser}} - password: {{ invite.teamssecret }} - group-name-context: "{{ invite.group_name_context }}" - -attribute-aggregation: - user: {{ aa.invite_username }} - password: "{{ invite_attribute_aggregation_secret }}" - -lifecycle: - user: {{ invite.lifecycle_user }} - password: {{ invite.lifecycle_secret }} - email: from: "{{ noreply_email }}" contactEmail: "{{ support_email }}" diff --git a/roles/lifecycle/defaults/main.yml b/roles/lifecycle/defaults/main.yml index b22afc29e..1338bd91c 100644 --- a/roles/lifecycle/defaults/main.yml +++ b/roles/lifecycle/defaults/main.yml @@ -1,23 +1,13 @@ --- -# +appname: lifecycle lifecycle_version: '' -# Lifecycle installer specific variables -lifecycle_version_dir: "{{ lifecycle_version | replace('/', '-') }}" -lifecycle_branch_dir: "{{ openconext_builds_dir }}/OpenConext-user-lifecycle-{{ lifecycle_branch | replace('/', '-') }}" -lifecycle_release_dir: "{{ openconext_releases_dir }}/OpenConext-user-lifecycle-{{ lifecycle_version_dir }}" -lifecycle_build_path: "{{ openconext_builds_dir }}/OpenConext-user-lifecycle-{{ lifecycle_version_dir }}.tar.gz" -lifecycle_download_url: "https://github.com/OpenConext/OpenConext-user-lifecycle/releases/download/{{ lifecycle_version }}/OpenConext-user-lifecycle-{{ lifecycle_version_dir }}.tar.gz" -lifecycle_current_release_symlink: "{{ openconext_releases_dir }}/OpenConext-user-lifecycle" - lifecycle_user: lifecycle -lifecycle_data_dir: /opt/openconext/OpenConext-lifecycle lifecycle_symfony_env: prod -lifecycle_apache_symfony_environment: prod lifecycle_eb_logins_db: eb_logins lifecycle_db_host: localhost lifecycle_user_quota: 1500 -lifecycle_inactivity_period: 37 +lifecycle_inactivity_period: 38 lifecycle_api_enabled: true lifecycle_api_password: secret lifecycle_api_username: lifecycle - +current_release_config_dir_name: /opt/openconext/{{ appname }} diff --git a/roles/lifecycle/handlers/main.yml b/roles/lifecycle/handlers/main.yml new file mode 100644 index 000000000..8c65fdb80 --- /dev/null +++ b/roles/lifecycle/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: restart lifecycle + community.docker.docker_container: + name: lifecycle + state: started + restart: true diff --git a/roles/lifecycle/tasks/install-branch.yml b/roles/lifecycle/tasks/install-branch.yml deleted file mode 100644 index c3c7dfaca..000000000 --- a/roles/lifecycle/tasks/install-branch.yml +++ /dev/null @@ -1,45 +0,0 @@ ---- -- name: Check if target dir exists - stat: - path: "{{ lifecycle_release_dir }}" - register: lifecycle_dir - -- name: Create build dir - file: - path: "{{ lifecycle_branch_dir }}" - state: directory - - #- name: Checkout lifecycle branch - #git: - # repo: https://github.com/OpenConext/OpenConext-lifecycle-user.git - # dest: "{{ lifecycle_branch_dir }}" - # version: "{{ lifecycle_branch }}" - # force: yes - #register: lifecycle_gitclone -- name: Copy makerelease.sh - template: - src: "makeRelease.sh.j2" - dest: "{{lifecycle_branch_dir}}/makeRelease.sh" - mode: 0770 - -- name: Make release - command: "./makeRelease.sh {{ lifecycle_branch }}" - environment: - HOME: "{{ openconext_builds_dir }}" - args: - chdir: "{{ lifecycle_branch_dir }}" - -- name: Unpack current version - unarchive: - src: "{{ openconext_builds_dir }}/Releases/OpenConext-user-lifecycle-{{ lifecycle_branch | replace('/', '_') }}.tar.gz" - dest: "{{ openconext_releases_dir }}" - copy: no - -- name: Activate new lifecycle branch - file: - src: "{{ openconext_releases_dir }}/OpenConext-user-lifecycle-{{ lifecycle_branch | replace('/', '_') }}" - dest: "{{ lifecycle_current_release_symlink }}" - state: link - notify: - - "restart httpd" - - "restart php72-fpm" diff --git a/roles/lifecycle/tasks/install-release.yml b/roles/lifecycle/tasks/install-release.yml deleted file mode 100644 index cd6820db6..000000000 --- a/roles/lifecycle/tasks/install-release.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -- name: Check if target dir exists - stat: - path: "{{ lifecycle_current_release_symlink }}" - follow: no - register: lifecycle_dir - -- name: Download current version - get_url: - url: "{{ lifecycle_download_url }}" - dest: "{{ lifecycle_build_path }}" - register: lifecycle_download - -- name: Unpack current version - unarchive: - src: "{{ lifecycle_build_path }}" - dest: "{{ openconext_releases_dir }}" - copy: no - when: - - lifecycle_download.changed or lifecycle_dir.stat.lnk_source != lifecycle_release_dir - -- name: Activate new Lifecycle release - file: - src: "{{ lifecycle_release_dir }}" - dest: "{{ lifecycle_current_release_symlink }}" - state: link - notify: - - "restart httpd" - - "restart php72-fpm" - when: - - lifecycle_download.changed or lifecycle_dir.stat.lnk_source != lifecycle_release_dir - diff --git a/roles/lifecycle/tasks/main.yml b/roles/lifecycle/tasks/main.yml index ed09c7bf7..2c5c99e3b 100644 --- a/roles/lifecycle/tasks/main.yml +++ b/roles/lifecycle/tasks/main.yml @@ -1,108 +1,67 @@ - name: Add group {{ lifecycle_user }} - group: + ansible.builtin.group: name: "{{ lifecycle_user }}" state: present + register: lifecycle_guid - name: Add user {{ lifecycle_user }} - user: + ansible.builtin.user: name: "{{ lifecycle_user }}" group: "{{ lifecycle_user }}" - createhome: yes + createhome: true state: present + register: lifecycle_uid -- name: Create php session dir for lifecycle - file: - path: "{{ php_session_dir }}/lifecycle" +- name: Create config dirs sajsdjasjaksa + ansible.builtin.file: state: directory - owner: "{{ lifecycle_user }}" + dest: "{{ item }}" + owner: root group: root - mode: 0770 - -- name: Install Apache vhost - template: - src: lifecycle.conf.j2 - dest: /etc/httpd/conf.d/lifecycle.conf - notify: "reload httpd" - -- name: Clean up old php-fpm 5.6 config - file: - path: "/etc/php-fpm.d/lifecycle-pool.conf" - state: absent - -- name: php-fpm 72 config - template: - src: "{{ item }}.j2" - dest: "/etc/opt/remi/php72/php-fpm.d/{{ item }}" + mode: "0755" with_items: - - lifecycle-pool-72.conf - notify: - - "restart php72-php-fpm" + - "{{ current_release_config_dir_name }}" -- name: Include install-branch.yml - include_tasks: install-branch.yml - when: lifecycle_branch is defined and lifecycle_branch != '' - -- name: Include install-release.yml - include_tasks: install-release.yml - when: lifecycle_branch is not defined or lifecycle_branch == '' - -- name: Place parameters.yml - template: - src: "{{ item }}.j2" - dest: "{{ lifecycle_current_release_symlink }}/config/legacy/{{ item }}" - mode: 0644 +- name: Put parameters YAML config + ansible.builtin.template: + src: "{{ item }}.yml.j2" + dest: "{{ current_release_config_dir_name }}/{{ item }}.yaml" + mode: "0640" + group: "{{ appname }}" with_items: - - parameters.yml + - parameters notify: - - "restart php72-fpm" - -- name: Place .envl file - copy: - src: env - dest: "{{ lifecycle_current_release_symlink }}/.env" - mode: 0644 - -- name: Create the symfony cache - command: "/usr/bin/php72 bin/console cache:clear --env={{ lifecycle_apache_symfony_environment }} --no-debug" - args: - chdir: "{{ lifecycle_current_release_symlink }}/" - when: - - not develop - changed_when: false - -- name: Make sure cache dir has correct permissions - file: - path: "{{ lifecycle_current_release_symlink }}/var/cache" - owner: "{{ lifecycle_user }}" - group: "{{ lifecycle_user }}" - recurse: yes - changed_when: false - -- name: Make sure log dir has correct permissions - file: - path: "{{ lifecycle_current_release_symlink }}/var/logs" - owner: "{{ lifecycle_user }}" - group: "{{ lifecycle_user }}" - recurse: yes - changed_when: false - - # Remove all dirs, but keep the current version and from the rest the most recent one. -- name: Clean up old releases - shell: ls -td {{ openconext_releases_dir }}/OpenConext-user-lifecycle-* | grep -v $(readlink {{ lifecycle_current_release_symlink }}) | tail -n +2 | xargs --no-run-if-empty rm -rv - register: clean_releases - changed_when: '"removed" in clean_releases.stdout' + - restart {{ appname }} -# Remove all tarballs, but keep the current version and from the rest the most recent one. -- name: Clean up old builds - shell: ls -td {{ openconext_builds_dir }}/OpenConext-user-lifecycle-* {{ openconext_builds_dir }}/Releases/ | grep -v {{ lifecycle_build_path }} | tail -n +2 | xargs --no-run-if-empty rm -rv - register: clean_builds - changed_when: '"removed" in clean_builds.stdout' +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/openconext-user-lifecycle/user-lifecycle:{{ lifecycle_version }} + etc_hosts: + host.docker.internal: host-gateway + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.lifecycle.rule: "Host(`lifecycle.{{ base_domain }}`)" + traefik.http.routers.lifecycle.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ lifecycle_uid.uid }}" + APACHE_GUID: "#{{ lifecycle_guid.gid }}" + APP_ENV: prod + HTTPD_CSP: "{{ httpd_csp.strict }}" + mounts: + - source: /opt/openconext/lifecycle + target: /var/www/html/config/openconext + type: bind -- name: Create daily cronjob - cron: - name: lifecycle run - minute: "8" - hour: "01" - user: "{{ lifecycle_user }}" - job: "/usr/bin/php72 {{ lifecycle_current_release_symlink }}/userlifecycle deprovision" - cron_file: user_lifecycle +#- name: Create daily cronjob + # cron: + # name: lifecycle run + # minute: "8" + # hour: "01" + # user: "{{ lifecycle_user }}" + # job: "/usr/bin/php72 {{ lifecycle_current_release_symlink }}/userlifecycle deprovision" + # cron_file: user_lifecycle diff --git a/roles/lifecycle/templates/lifecycle-pool-72.conf.j2 b/roles/lifecycle/templates/lifecycle-pool-72.conf.j2 deleted file mode 100644 index ef2217ba1..000000000 --- a/roles/lifecycle/templates/lifecycle-pool-72.conf.j2 +++ /dev/null @@ -1,225 +0,0 @@ -; Create a new pool named lifecycle. -[lifecycle] - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses on a -; specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. - -; Use unix socket -listen = /var/run/php-fpm/lifecycle-pool-72.sock -; Set listen(2) backlog. A value of '-1' means unlimited. -; Default Value: -1 -;listen.backlog = -1 - -; List of ipv4 addresses of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -listen.allowed_clients = 127.0.0.1 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0666 -listen.owner = apache -listen.group = apache -listen.mode = 0640 - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = {{ lifecycle_user }} -group = {{ lifecycle_user }} - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives: -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; Note: This value is mandatory. -pm = ondemand - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes to be created when pm is set to 'dynamic'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. -; Note: Used when pm is set to either 'static' or 'dynamic' -; Note: This value is mandatory. -pm.max_children = 20 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -;pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.max_spare_servers = 5 - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -pm.max_requests = 300 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. By default, the status page shows the following -; information: -; accepted conn - the number of request accepted by the pool; -; pool - the name of the pool; -; process manager - static or dynamic; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes. -; The values of 'idle processes', 'active processes' and 'total processes' are -; updated each second. The value of 'accepted conn' is updated in real time. -; Example output: -; accepted conn: 12073 -; pool: www -; process manager: static -; idle processes: 35 -; active processes: 65 -; total processes: 100 -; By default the status page output is formatted as text/plain. Passing either -; 'html' or 'json' as a query string will return the corresponding output -; syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_terminate_timeout = 0 - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -slowlog = /var/log/php-fpm/www-slow.log - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. This value must be an absolute path. -; Default Value: current directory or / when chroot -;chdir = /var/www - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Default Value: no -;catch_workers_output = yes - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; exectute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -php_admin_value[error_log] = /var/log/php-fpm/lifecycle-error.log -php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 128M - -; Set session path to a directory owned by process user -php_value[session.save_handler] = files -php_value[session.save_path] = {{ php_session_dir }}/lifecycle -php_value[disable_functions] = {{ php_disabled_functions }} diff --git a/roles/lifecycle/templates/lifecycle.conf.j2 b/roles/lifecycle/templates/lifecycle.conf.j2 deleted file mode 100644 index a2252c132..000000000 --- a/roles/lifecycle/templates/lifecycle.conf.j2 +++ /dev/null @@ -1,35 +0,0 @@ -{% if apache_app_listen_address.lifecycle is defined %} -Listen {{ apache_app_listen_address.lifecycle }}:{{ loadbalancing.lifecycle.port }} - -{% else %} - -{% endif %} - ServerAdmin {{ admin_email }} - DocumentRoot "{{ lifecycle_current_release_symlink }}/public" - SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 - - Require all granted - Options -MultiViews - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php [QSA,L] - - ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php-fpm/lifecycle-pool-72.sock|fcgi://localhost{{ lifecycle_current_release_symlink }}/public/$1 - ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-LIFECYCLE'" - CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-LIFECYCLE'" combined - - {% if haproxy_backend_tls %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/backend.{{ base_domain }}.pem - SSLCertificateKeyFile {{ tls.cert_private_path }}/backend.{{ base_domain }}.key - Include ssl_backend.conf - {% endif %} - - {% if apache_app_listen_address.all is defined %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/{{ tls_star_cert }} - SSLCertificateKeyFile {{ tls.cert_private_path }}/{{ tls_star_cert_key }} - SSLCertificateChainFile {{ tls.cert_path_ca }}/{{ tls_ca }} - Include ssl_backend.conf - {% endif %} - diff --git a/roles/lifecycle/templates/makeRelease.sh.j2 b/roles/lifecycle/templates/makeRelease.sh.j2 deleted file mode 100644 index d9384ee70..000000000 --- a/roles/lifecycle/templates/makeRelease.sh.j2 +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh -# Copy of SP Dashboard makeRelease.sh file. Please review everything carefully! - -PREVIOUS_SF_ENV=${SYMFONY_ENV} -export SYMFONY_ENV="{{ lifecycle_symfony_env }}" - -RELEASE_DIR=${HOME}/Releases -GITHUB_USER=OpenConext -PROJECT_NAME=OpenConext-user-lifecycle - -if [ -z "$1" ] -then - -cat << EOF -Please specify the tag or branch to make a release of. - -Examples: - - sh makeRelease.sh 0.1.0 - sh makeRelease.sh master - sh makeRelease.sh develop - -If you want to GPG sign the release, you can specify the "sign" parameter, this will -invoke the gpg command line tool to sign it. - - sh makeRelease 0.1.0 sign - -EOF -exit 1 -else - TAG=$1 -fi - -PROJECT_DIR_NAME=${PROJECT_NAME}-${TAG//\//_} && -PROJECT_DIR=${RELEASE_DIR}/${PROJECT_DIR_NAME} && - -echo "Preparing environment" && -mkdir -p ${RELEASE_DIR} && -rm -rf ${PROJECT_DIR} && -cd ${RELEASE_DIR} -git clone https://github.com/${GITHUB_USER}/${PROJECT_NAME}.git ${PROJECT_DIR_NAME} && - -cd ${PROJECT_DIR} && -git checkout ${TAG} && -echo "Running Composer Install"; -curl -sS https://getcomposer.org/installer | php -php ./composer.phar install -n --prefer-dist -o --ignore-platform-reqs&& - -echo "Tagging the release in RELEASE file" && -COMMITHASH=`git rev-parse HEAD` && -echo "Tag: ${TAG}" > ${PROJECT_DIR}/RELEASE && -echo "Commit: ${COMMITHASH}" >> ${PROJECT_DIR}/RELEASE && - -echo "Cleaning build of dev files" && -rm -rf ${PROJECT_DIR}/.idea && -rm -rf ${PROJECT_DIR}/.git && -rm -f ${PROJECT_DIR}/.gitignore && -rm -f ${PROJECT_DIR}/makeRelease.sh && -rm -f ${PROJECT_DIR}/bin/composer.phar && -rm -rf ${PROJECT_DIR}/features && -rm -rf ${PROJECT_DIR}/behat.yml && -rm -rf ${PROJECT_DIR}/build.xml && -rm -rf ${PROJECT_DIR}/tests && -rm -rf ${PROJECT_DIR}/ci && -rm -rf ${PROJECT_DIR}/.travis.yml && -rm -rf ${PROJECT_DIR}/ansible && -rm -rf ${PROJECT_DIR}/Vagrantfile && - -echo "Create tarball" && -cd ${RELEASE_DIR} && -tar -czf ${PROJECT_DIR_NAME}.tar.gz ${PROJECT_DIR_NAME} - - -echo "Create checksum file" && -cd ${RELEASE_DIR} && -if hash sha1sum 2>/dev/null; then - sha1sum ${PROJECT_DIR_NAME}.tar.gz > ${PROJECT_DIR_NAME}.sha -else - shasum ${PROJECT_DIR_NAME}.tar.gz > ${PROJECT_DIR_NAME}.sha -fi - -if [ -n "$2" ] -then - if [ "$2" == "sign" ] - then - echo "Signing build" - cd ${RELEASE_DIR} - gpg -o ${PROJECT_DIR_NAME}.sha.gpg --clearsign ${PROJECT_DIR_NAME}.sha - fi -fi - -export SYMFONY_ENV=${PREVIOUS_SF_ENV} diff --git a/roles/lifecycle/templates/parameters.yml.j2 b/roles/lifecycle/templates/parameters.yml.j2 index 4e69bca28..20c2f5ceb 100644 --- a/roles/lifecycle/templates/parameters.yml.j2 +++ b/roles/lifecycle/templates/parameters.yml.j2 @@ -1,4 +1,7 @@ parameters: + app_env: prod + app_debug: false + app_secret: {{ lifecycle_symfony_secret }} database_host: {{ lifecycle_db_host }} database_port: 3306 database_name: {{ lifecycle_eb_logins_db }} diff --git a/roles/lifecycle/vars/main.yml b/roles/lifecycle/vars/main.yml new file mode 100644 index 000000000..0eb9d3835 --- /dev/null +++ b/roles/lifecycle/vars/main.yml @@ -0,0 +1,13 @@ +--- +appname: lifecycle +lifecycle_version: '' +lifecycle_user: lifecycle +lifecycle_symfony_env: prod +lifecycle_eb_logins_db: eb_logins +lifecycle_db_host: localhost +lifecycle_user_quota: 1500 +lifecycle_inactivity_period: 37 +lifecycle_api_enabled: true +lifecycle_api_password: secret +lifecycle_api_username: lifecycle +current_release_config_dir_name: /opt/openconext/{{ appname }} diff --git a/roles/manage-gui/defaults/main.yml b/roles/manage-gui/defaults/main.yml deleted file mode 100644 index d7916b32a..000000000 --- a/roles/manage-gui/defaults/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -manage_gui_version: '' -manage_gui_snapshot_timestamp: '' diff --git a/roles/manage-gui/meta/main.yml b/roles/manage-gui/meta/main.yml deleted file mode 100644 index ed97d539c..000000000 --- a/roles/manage-gui/meta/main.yml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/roles/manage-gui/tasks/main.yml b/roles/manage-gui/tasks/main.yml deleted file mode 100644 index d2cd0c5b3..000000000 --- a/roles/manage-gui/tasks/main.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: copy Apache config - template: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - with_items: - - src: "manage.conf.j2" - dest: "/etc/httpd/conf.d/manage.conf" - notify: - - "restart httpd" diff --git a/roles/manage-gui/templates/manage.conf.j2 b/roles/manage-gui/templates/manage.conf.j2 deleted file mode 100644 index 0e2a92723..000000000 --- a/roles/manage-gui/templates/manage.conf.j2 +++ /dev/null @@ -1,107 +0,0 @@ -{% if apache_app_listen_address.manage is defined %} -Listen {{ apache_app_listen_address.manage }}:{{ loadbalancing.manage.port }} - -{% else %} - -{% endif %} - # General setup for the virtual host, inherited from global configuration - ServerName https://manage.{{ base_domain }} - - ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-Manage'" - CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-Manage'" 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} !^/manage - RewriteCond %{REQUEST_URI} !^/internal - RewriteCond %{REQUEST_URI} !^/fonts - RewriteRule (.*) /index.html [L] - - ProxyPass /Shibboleth.sso ! - ProxyPass /manage/api/health http://localhost:{{ springapp_tcpport }}/internal/health retry=0 - ProxyPass /manage/api/info http://localhost:{{ springapp_tcpport }}/internal/info retry=0 - - ProxyPass /internal/health http://localhost:{{ springapp_tcpport }}/internal/health retry=0 - ProxyPass /internal/info http://localhost:{{ springapp_tcpport }}/internal/info retry=0 - - ProxyPass /manage/api http://localhost:{{ springapp_tcpport }} retry=0 - ProxyPassReverse /manage/api http://localhost:{{ springapp_tcpport }} - -########################################################################### -# Backdoor instructions # -# ------------------------------------------------------------------------# -# Manage offers the ability to use basic authentication to login # -# In order to activate it, remove the block below # -# and restart httpd # -# The username and password can be found in the manage application.yml # -# ######################################################################### - - - AuthType shibboleth - ShibUseHeaders On - ShibRequestSetting applicationId manage - ShibRequireSession On - ShibRequestSetting REMOTE_ADDR X-Forwarded-For - Require valid-user - - - DocumentRoot "{{ _springapp_dir }}/current" - - - Require all granted - Options -Indexes - - - # Enable shibboleth for all other URLs, but the health check and info endpoint - - Require all granted - - - - Require all granted - - - # The internal API is secured with basic auth - - Require all granted - - - - Require all granted - - - - Require all granted - - - Header always set Content-Security-Policy "{{ httpd_csp.lenient_with_static_img }}" - Header always set X-Frame-Options "DENY" - Header always set Referrer-Policy "same-origin" - Header always set X-Content-Type-Options "nosniff" - - {% if haproxy_backend_tls %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/backend.{{ base_domain }}.pem - SSLCertificateKeyFile {{ tls.cert_private_path }}/backend.{{ base_domain }}.key - Include ssl_backend.conf - {% endif %} - - {% if apache_app_listen_address.all is defined %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/{{ tls_star_cert }} - SSLCertificateKeyFile {{ tls.cert_private_path }}/{{ tls_star_cert_key }} - SSLCertificateChainFile {{ tls.cert_path_ca }}/{{ tls_ca }} - Include ssl_backend.conf - {% endif %} - - diff --git a/roles/manage-gui/vars/main.yml b/roles/manage-gui/vars/main.yml deleted file mode 100644 index 1ad255d5d..000000000 --- a/roles/manage-gui/vars/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -springapp_tcpport: "{{ manage_springapp_tcpport }}" -springapp_artifact_id: manage-gui -springapp_version: "{{ manage_gui_version }}" diff --git a/roles/manage-server/handlers/main.yml b/roles/manage-server/handlers/main.yml deleted file mode 100644 index 08e3264b3..000000000 --- a/roles/manage-server/handlers/main.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: restart manage - systemd: - name: manage - state: restarted - daemon_reload: yes - -- name: update_ca_trust - command: update-ca-trust diff --git a/roles/manage-server/meta/main.yml b/roles/manage-server/meta/main.yml deleted file mode 100644 index ed97d539c..000000000 --- a/roles/manage-server/meta/main.yml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/roles/manage-server/tasks/main.yml b/roles/manage-server/tasks/main.yml deleted file mode 100644 index c58a5d64b..000000000 --- a/roles/manage-server/tasks/main.yml +++ /dev/null @@ -1,83 +0,0 @@ ---- -- name: Import the mongo CA file - copy: - src: "{{ inventory_dir }}/secrets/mongo/mongoca.pem" - dest: "{{ tls.cert_path_ca }}/" - owner: root - mode: "0644" - -- name: Update the ca trust store - command: /bin/update-ca-trust - changed_when: False - -- name: Create metadata {{ manage_dir }} directories - file: - path: "{{ item }}" - state: directory - owner: manage - group: manage - mode: 0740 - with_items: - - "{{ manage_dir }}/metadata_configuration" - - "{{ manage_dir }}/metadata_templates" - -- name: copy application config - template: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: manage - group: manage - mode: 0740 - with_items: - - src: "logback.xml.j2" - dest: "{{ manage_dir }}/logback.xml" - - src: "application.yml.j2" - dest: "{{ manage_dir }}/application.yml" - - src: "manage-api-users.yml.j2" - dest: "{{ manage_dir }}/manage-api-users.yml" - notify: - - "restart manage" - -- name: copy metadata configuration - template: - src: "metadata_configuration/{{ item }}.schema.json.j2" - dest: "{{ manage_dir }}/metadata_configuration/{{ item }}.schema.json" - owner: manage - group: manage - mode: "0640" - with_items: - - "{{ manage_tabs_enabled }}" - notify: - - "restart manage" - -- name: copy metadata templates - copy: - src: "metadata_templates/{{ item }}.template.json" - dest: "{{ manage_dir }}/metadata_templates/{{ item }}.template.json" - owner: manage - group: manage - mode: "0640" - with_items: - - "{{ manage_tabs_enabled }}" - notify: - - "restart manage" - -- name: copy / create certificate - copy: - src: "{{ inventory_dir }}/files/certs/invite/public_key.pem" - dest: "{{ manage_dir }}/public_invite_key.pem" - owner: manage - group: manage - mode: "0740" - notify: - - "restart manage" - - -- meta: flush_handlers - -- name: Include the role manage_provision_entities to provision the Manage sp to Manage - include_role: - name: manage_provision_entities - vars: - entity_type: saml20_sp - diff --git a/roles/manage-server/templates/logback.xml.j2 b/roles/manage-server/templates/logback.xml.j2 deleted file mode 100644 index d8150441d..000000000 --- a/roles/manage-server/templates/logback.xml.j2 +++ /dev/null @@ -1,44 +0,0 @@ -#jinja2:lstrip_blocks: True - - - - - /var/log/manage/manage.log - - - /var/log/manage/manage-%d{yyyy-MM-dd}.log.gz - {{ logback_max_history }} - - - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - - - - {{ rsyslog_host }} - DAEMON - manage: [%thread] %logger %msg - - - - {{ smtp_server }} - {{ noreply_email }} - {{ error_mail_to }} - {{ error_subject_prefix }}Unexpected error manage - - - - ERROR - - - - - - - - - - - - - diff --git a/roles/manage-server/vars/main.yml b/roles/manage-server/vars/main.yml deleted file mode 100644 index b395680e5..000000000 --- a/roles/manage-server/vars/main.yml +++ /dev/null @@ -1,18 +0,0 @@ -springapp_artifact_id: manage-server -springapp_artifact_type: jar -springapp_artifact_group_dir: org.openconext -springapp_version: "{{ manage_server_version }}" -springapp_dir: "{{ manage_dir }}" -springapp_user: manage -springapp_service_name: manage -springapp_jar: "{{ manage_jar }}" -springapp_tcpport: "{{ manage_springapp_tcpport }}" -springapp_random_source: "file:///dev/urandom" -manage_provision_samlsp_client_id: "{{ manage_manage_provision_samlsp_client_id }}" -manage_provision_samlsp_name_en: "{{ manage_manage_provision_samlsp_name_en }}" -manage_provision_samlsp_description_en: "{{ manage_manage_provision_samlsp_description_en }}" -manage_provision_samlsp_acs_location: "{{ manage_manage_provision_samlsp_acs_location }}" -manage_provision_samlsp_metadata_url: "{{ manage_manage_provision_samlsp_metadata_url }}" -manage_provision_samlsp_sp_cert: "{{ manage_manage_provision_samlsp_sp_cert }}" -manage_provision_samlsp_trusted_proxy: "{{ manage_manage_provision_samlsp_trusted_proxy }}" -manage_provision_samlsp_sign: "{{ manage_manage_provision_samlsp_sign }}" diff --git a/roles/manage-server/defaults/main.yml b/roles/manage/defaults/main.yml similarity index 95% rename from roles/manage-server/defaults/main.yml rename to roles/manage/defaults/main.yml index 1341fc496..b44c6f2ed 100644 --- a/roles/manage-server/defaults/main.yml +++ b/roles/manage/defaults/main.yml @@ -1,5 +1,5 @@ --- -manage_dir: /opt/manage +manage_dir: /config/ manage_snapshot_timestamp: '' manage_jar: manage-current.jar manage_random_source: 'file:///dev/urandom' @@ -8,6 +8,7 @@ manage_disclaimer_background_color: "{{ environment_ribbon_colour }}" manage_disclaimer_content: "{{ environment_shortname }}" manage_service_provider_feed_url: "http://mds.edugain.org/edugain-v2.xml" manage_exclude_edugain_imports_in_push: true +manage_exclude_sram_imports_in_push: true manage_show_oidc_rp_tab: false manage_exclude_oidc_rp_imports_in_push: false manage_metadata_refresh_cron_schedule: "-" diff --git a/roles/manage-server/files/metadata_templates/oauth20_rs.template.json b/roles/manage/files/metadata_templates/oauth20_rs.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/oauth20_rs.template.json rename to roles/manage/files/metadata_templates/oauth20_rs.template.json diff --git a/roles/manage-server/files/metadata_templates/oidc10_rp.template.json b/roles/manage/files/metadata_templates/oidc10_rp.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/oidc10_rp.template.json rename to roles/manage/files/metadata_templates/oidc10_rp.template.json diff --git a/roles/manage-server/files/metadata_templates/policy.template.json b/roles/manage/files/metadata_templates/policy.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/policy.template.json rename to roles/manage/files/metadata_templates/policy.template.json diff --git a/roles/manage-server/files/metadata_templates/provisioning.template.json b/roles/manage/files/metadata_templates/provisioning.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/provisioning.template.json rename to roles/manage/files/metadata_templates/provisioning.template.json diff --git a/roles/manage-server/files/metadata_templates/saml20_idp.template.json b/roles/manage/files/metadata_templates/saml20_idp.template.json similarity index 89% rename from roles/manage-server/files/metadata_templates/saml20_idp.template.json rename to roles/manage/files/metadata_templates/saml20_idp.template.json index 856b82f27..8698863f2 100644 --- a/roles/manage-server/files/metadata_templates/saml20_idp.template.json +++ b/roles/manage/files/metadata_templates/saml20_idp.template.json @@ -12,8 +12,8 @@ "SingleSignOnService:0:Location": "" }, "autoRefresh": { - "enabled": false, - "allowAll": false, + "enabled": true, + "allowAll": true, "fields": { } } diff --git a/roles/manage-server/files/metadata_templates/saml20_sp.template.json b/roles/manage/files/metadata_templates/saml20_sp.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/saml20_sp.template.json rename to roles/manage/files/metadata_templates/saml20_sp.template.json diff --git a/roles/manage-server/files/metadata_templates/single_tenant_template.template.json b/roles/manage/files/metadata_templates/single_tenant_template.template.json similarity index 100% rename from roles/manage-server/files/metadata_templates/single_tenant_template.template.json rename to roles/manage/files/metadata_templates/single_tenant_template.template.json diff --git a/roles/manage/files/metadata_templates/sram.template.json b/roles/manage/files/metadata_templates/sram.template.json new file mode 100644 index 000000000..0dc3f5616 --- /dev/null +++ b/roles/manage/files/metadata_templates/sram.template.json @@ -0,0 +1,28 @@ +{ + "entityid": "", + "state": "testaccepted", + "allowedall": true, + "arp": { + "enabled": false, + "attributes": {} + }, + "metaDataFields": { + "name:en": "", + "OrganizationName:en": "", + "AssertionConsumerService:0:Binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + "AssertionConsumerService:0:Location": "https://trusted.proxy.acs.location.rules", + "NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "coin:signature_method": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + "connection_type": "oidc_rp", + "secret": "", + "redirectUrls": [], + "grants": ["authorization_code"] + }, + "allowedEntities": [], + "autoRefresh": { + "enabled": false, + "allowAll": false, + "fields": { + } + } +} \ No newline at end of file diff --git a/roles/manage/handlers/main.yml b/roles/manage/handlers/main.yml new file mode 100644 index 000000000..5ec9e9c09 --- /dev/null +++ b/roles/manage/handlers/main.yml @@ -0,0 +1,5 @@ +- name: restart manageserver + community.docker.docker_container: + name: manageserver + state: started + restart: true diff --git a/roles/manage/tasks/main.yml b/roles/manage/tasks/main.yml new file mode 100644 index 000000000..1d19bef6d --- /dev/null +++ b/roles/manage/tasks/main.yml @@ -0,0 +1,141 @@ +--- +- name: Create metadata directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: root + group: root + mode: 0750 + with_items: + - "/opt/openconext/manage/metadata_configuration" + - "/opt/openconext/manage/metadata_templates" + +- name: Import the mongo CA file + ansible.builtin.copy: + src: "{{ inventory_dir }}/secrets/mongo/mongoca.pem" + dest: "/opt/openconext/manage" + owner: root + mode: "0644" + +- name: copy invite certificate + copy: + src: "{{ inventory_dir }}/files/certs/invite/public_key.pem" + dest: "/opt/openconext/manage/public_invite_key.pem" + owner: root + group: root + mode: "0640" + notify: + - "restart manageserver" + +- name: Place the serverapplication configfiles + ansible.builtin.template: + src: "{{ item }}.j2" + dest: /opt/openconext/manage/{{ item }} + owner: root + group: root + mode: "0644" + with_items: + - application.yml + - logback.xml + - manage-api-users.yml + notify: restart manageserver + +- name: copy metadata configuration + ansible.builtin.template: + src: "metadata_configuration/{{ item }}.schema.json.j2" + dest: "/opt/openconext/manage/metadata_configuration/{{ item }}.schema.json" + owner: root + group: root + mode: "0640" + with_items: + - "{{ manage_tabs_enabled }}" + notify: + - "restart manageserver" + +- name: copy metadata templates + copy: + src: "metadata_templates/{{ item }}.template.json" + dest: "/opt/openconext/manage/metadata_templates/{{ item }}.template.json" + owner: root + group: root + mode: "0640" + with_items: + - "{{ manage_tabs_enabled }}" + notify: + - "restart manageserver" + +- name: Create and start the server container + community.docker.docker_container: + name: manageserver + image: ghcr.io/openconext/openconext-manage/manage-server:{{ manage_server_version }} + entrypoint: /__cacert_entrypoint.sh + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + mounts: + - source: /opt/openconext/manage/ + target: /config/ + type: bind + - source: /opt/openconext/manage/mongoca.pem + target: /certificates/mongoca.crt + type: bind + command: "java -jar /app.jar -Xmx512m --spring.config.location=./config/" + etc_hosts: + host.docker.internal: host-gateway + env: + USE_SYSTEM_CA_CERTS: "true" + TZ: "{{ timezone }}" + hostname: manage + healthcheck: + test: + [ + "CMD", + "wget", + "-no-verbose", + "--tries=1", + "--spider", + "http://localhost:8080/internal/health", + ] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + +- name: Create the gui container + community.docker.docker_container: + name: managegui + image: ghcr.io/openconext/openconext-manage/manage-gui:{{ manage_gui_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.managegui.rule: "Host(`manage.{{ base_domain }}`)" + traefik.http.routers.managegui.tls: "true" + traefik.enable: "true" + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost/internal/health"] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + hostname: managegui + env: + HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" + HTTPD_SERVERNAME: "manage.{{ base_domain }}" + OPENCONEXT_INSTANCENAME: "{{ instance_name }}" + OPENCONEXT_ENGINE_LOGOUT_URL: "https://engine.{{ base_domain }}/logout" + OPENCONEXT_HELP_EMAIL: "{{ support_email }}" + SHIB_ENTITYID: "https://manage.{{ base_domain }}/shibboleth" + SHIB_REMOTE_ENTITYID: "https://engine.{{ base_domain }}/authentication/idp/metadata" + SHIB_REMOTE_METADATA: "{{ shibboleth_metadata_sources.engine }}" + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind diff --git a/roles/manage-server/templates/application.yml.j2 b/roles/manage/templates/application.yml.j2 similarity index 86% rename from roles/manage-server/templates/application.yml.j2 rename to roles/manage/templates/application.yml.j2 index 7150ce8a1..1923b83ca 100644 --- a/roles/manage-server/templates/application.yml.j2 +++ b/roles/manage/templates/application.yml.j2 @@ -13,7 +13,7 @@ environment: {{ manage.environment }} server: # The port to where this Spring Boot application listens to. - port: {{ springapp_tcpport }} + port: 8080 error: path: "/error" server-header: @@ -35,11 +35,12 @@ push: name: {{ instance_name }} EngineBlock exclude_edugain_imports: {{ manage_exclude_edugain_imports_in_push }} exclude_oidc_rp: {{ manage_exclude_oidc_rp_imports_in_push }} + exclude_sram: {{ manage_exclude_sram_imports_in_push }} oidc: url: https://connect.{{ base_domain }}/manage/connections user: manage name: {{ manage.oidcng_name }} - password: {{ oidcng_api_metadata_push_password }} + password: "{{ oidcng_api_metadata_push_password }}" enabled: {{ manage.oidc_push_enabled }} pdp: url: https://pdp.{{ base_domain }}/pdp/api/manage/push @@ -47,7 +48,7 @@ push: decide_url: https://pdp.{{ base_domain }}/pdp/api/manage/decide name: {{ manage.pdp_name }} user: {{ pdp.username }} - password: {{ pdp.password }} + password: "{{ pdp.password }}" product: name: Manage @@ -58,10 +59,11 @@ product: metadata_configuration_path: file://{{ manage_dir }}/metadata_configuration metadata_templates_path: file://{{ manage_dir }}/metadata_templates +metadata_export_path: classpath:/metadata_export security: backdoor_user_name: {{ manage.backdoor_api_user }} - backdoor_password: {{ manage_backdoor_api_password }} + backdoor_password: "{{ manage_backdoor_api_password }}" api_users_config_path: file://{{ manage_dir }}/manage-api-users.yml super_user_team_names: {{ manage.super_user_team_names }} @@ -71,7 +73,7 @@ crypto: spring: mail: - host: localhost + host: {{ smtp_server }} port: 25 data: mongodb: @@ -79,10 +81,12 @@ spring: datasource: url: jdbc:mysql://{{ pdp.db_host }}/{{ pdp.db_name }}?permitMysqlScheme username: {{ pdp.db_user }} - password: {{ pdp.db_password }} + password: "{{ pdp.db_password }}" driverClassName: org.mariadb.jdbc.Driver main: banner-mode: "off" + jpa: + open-in-view: false gui: disclaimer: @@ -113,3 +117,5 @@ management: info: git: mode: full + +loa_levels: "http://localhost/assurance/loa1.5,http://localhost/assurance/loa2,http://localhost/assurance/loa3" diff --git a/roles/manage/templates/logback.xml.j2 b/roles/manage/templates/logback.xml.j2 new file mode 100644 index 000000000..f5ca6c7cb --- /dev/null +++ b/roles/manage/templates/logback.xml.j2 @@ -0,0 +1,31 @@ +#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 manage + + + + ERROR + + + + + + + + + + + + diff --git a/roles/manage-server/templates/manage-api-users.yml.j2 b/roles/manage/templates/manage-api-users.yml.j2 similarity index 100% rename from roles/manage-server/templates/manage-api-users.yml.j2 rename to roles/manage/templates/manage-api-users.yml.j2 diff --git a/roles/manage-server/templates/metadata_configuration/oauth20_rs.schema.json.j2 b/roles/manage/templates/metadata_configuration/oauth20_rs.schema.json.j2 similarity index 99% rename from roles/manage-server/templates/metadata_configuration/oauth20_rs.schema.json.j2 rename to roles/manage/templates/metadata_configuration/oauth20_rs.schema.json.j2 index af3cf014a..6ef93ce5c 100644 --- a/roles/manage-server/templates/metadata_configuration/oauth20_rs.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/oauth20_rs.schema.json.j2 @@ -190,7 +190,7 @@ "patternProperties": { "^name:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", - "info": "Set the name of the service. Format: 'Service Name | Supplier'" + "info": "Set the name of the service. Format: 'Service Name'" }, "^description:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", diff --git a/roles/manage-server/templates/metadata_configuration/oidc10_rp.schema.json.j2 b/roles/manage/templates/metadata_configuration/oidc10_rp.schema.json.j2 similarity index 98% rename from roles/manage-server/templates/metadata_configuration/oidc10_rp.schema.json.j2 rename to roles/manage/templates/metadata_configuration/oidc10_rp.schema.json.j2 index 4dc3e694b..494bde510 100644 --- a/roles/manage-server/templates/metadata_configuration/oidc10_rp.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/oidc10_rp.schema.json.j2 @@ -23,8 +23,18 @@ }, "value": { "type": "string" + }, + "motivation": { + "type": "string" + }, + "release_as": { + "type": "string" + }, + "use_as_nameid": { + "type": "boolean" } - } + }, + "additionalProperties": false } } }, @@ -298,6 +308,11 @@ "format": "url", "info": "Enter the URL that is allowed to use for this RP to host a JWT containing request parameters (when doing a request using a signed jwt)." }, + "oidc:state_parameter_decoding_disabled": { + "type": "boolean", + "info": "Select this option to disable the default decoding of the state parameter in the authorization request.", + "default": false + }, "logo:0:url": { "type": "string", "format": "url", @@ -564,7 +579,7 @@ "patternProperties": { "^name:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", - "info": "Set the name of the service. Format: 'Service Name | Supplier'" + "info": "Set the name of the service. Format: 'Service Name'" }, "^displayName:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", diff --git a/roles/manage-server/templates/metadata_configuration/policy.schema.json.j2 b/roles/manage/templates/metadata_configuration/policy.schema.json.j2 similarity index 100% rename from roles/manage-server/templates/metadata_configuration/policy.schema.json.j2 rename to roles/manage/templates/metadata_configuration/policy.schema.json.j2 diff --git a/roles/manage-server/templates/metadata_configuration/provisioning.schema.json.j2 b/roles/manage/templates/metadata_configuration/provisioning.schema.json.j2 similarity index 87% rename from roles/manage-server/templates/metadata_configuration/provisioning.schema.json.j2 rename to roles/manage/templates/metadata_configuration/provisioning.schema.json.j2 index 2b8694ff0..9cd5741f3 100644 --- a/roles/manage-server/templates/metadata_configuration/provisioning.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/provisioning.schema.json.j2 @@ -83,13 +83,26 @@ }, "scim_password": { "type": "string", - "info": "The password of the SCIM endpoint." + "info": "The password of the SCIM endpoint. Will be stored symmetrically encrypted." }, "scim_update_role_put_method": { "type": "boolean", "default": false, "info": "If checked then we use the PUT method for Group updates thus sending all information (e.g. all members), otherwise PATCH with only the added or removed member." }, + "scim_user_identifier": { + "type": "string", + "enum": [ + "subject_id", + "eduperson_principal_name", + "uids", + "email", + "eduID" + ], + "default": "eduperson_principal_name", + "info": "From the pull down, select the scim identifier used for the user provisioning.", + "disabledAfterPersisted": true + }, "eva_url": { "type": "string", "format": "url", diff --git a/roles/manage-server/templates/metadata_configuration/saml20_idp.schema.json.j2 b/roles/manage/templates/metadata_configuration/saml20_idp.schema.json.j2 similarity index 98% rename from roles/manage-server/templates/metadata_configuration/saml20_idp.schema.json.j2 rename to roles/manage/templates/metadata_configuration/saml20_idp.schema.json.j2 index 0dcaa22e4..538d8431e 100644 --- a/roles/manage-server/templates/metadata_configuration/saml20_idp.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/saml20_idp.schema.json.j2 @@ -312,6 +312,11 @@ "type": "string", "info": "The defined client code. Generally an abbreviation of the name of the client." }, + "coin:institution_brin": { + "type": "string", + "format": "brin", + "info": "Official BRIN code as assigned to this IdP's institution by Dienst uitvoering Onderwijs (DUO)." + }, "coin:institution_guid": { "type": "string", "format": "uuid", @@ -351,10 +356,6 @@ "type": "boolean", "info": "Set to make the IdP hidden in the dashboard when the IdP is not connected to a service." }, - "coin:ss:allow_scb_admin_rights": { - "type": "boolean", - "info": "Set to grant SAB SURFconext beheerders for this IdP the SURFconext verantwoordelijke rights." - }, "coin:signature_method": { "type": "string", "format": "url", diff --git a/roles/manage-server/templates/metadata_configuration/saml20_sp.schema.json.j2 b/roles/manage/templates/metadata_configuration/saml20_sp.schema.json.j2 similarity index 99% rename from roles/manage-server/templates/metadata_configuration/saml20_sp.schema.json.j2 rename to roles/manage/templates/metadata_configuration/saml20_sp.schema.json.j2 index 8c54765fa..c8f30aa3d 100644 --- a/roles/manage-server/templates/metadata_configuration/saml20_sp.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/saml20_sp.schema.json.j2 @@ -51,8 +51,18 @@ }, "value": { "type": "string" + }, + "motivation": { + "type": "string" + }, + "release_as": { + "type": "string" + }, + "use_as_nameid": { + "type": "boolean" } - } + }, + "additionalProperties": false } } }, @@ -637,7 +647,7 @@ "patternProperties": { "^name:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", - "info": "Set the name of the service. Format: 'Service Name | Supplier'" + "info": "Set the name of the service. Format: 'Service Name'" }, "^displayName:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", diff --git a/roles/manage-server/templates/metadata_configuration/single_tenant_template.schema.json.j2 b/roles/manage/templates/metadata_configuration/single_tenant_template.schema.json.j2 similarity index 98% rename from roles/manage-server/templates/metadata_configuration/single_tenant_template.schema.json.j2 rename to roles/manage/templates/metadata_configuration/single_tenant_template.schema.json.j2 index 0772b2549..6d17cfe51 100644 --- a/roles/manage-server/templates/metadata_configuration/single_tenant_template.schema.json.j2 +++ b/roles/manage/templates/metadata_configuration/single_tenant_template.schema.json.j2 @@ -37,8 +37,18 @@ }, "value": { "type": "string" + }, + "motivation": { + "type": "string" + }, + "release_as": { + "type": "string" + }, + "use_as_nameid": { + "type": "boolean" } - } + }, + "additionalProperties": false } } }, @@ -516,7 +526,7 @@ "patternProperties": { "^name:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", - "info": "Set the name of the service. Format: 'Service Name | Supplier'" + "info": "Set the name of the service. Format: 'Service Name'" }, "^displayName:({{ supported_language_codes | replace(',','|') }})$": { "type": "string", diff --git a/roles/manage/templates/metadata_configuration/sram.schema.json.j2 b/roles/manage/templates/metadata_configuration/sram.schema.json.j2 new file mode 100644 index 000000000..5cacf51eb --- /dev/null +++ b/roles/manage/templates/metadata_configuration/sram.schema.json.j2 @@ -0,0 +1,501 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "sram", + "order": 8, + "definitions": { + "AssertionConsumerService_Binding": { + "type": "string", + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ], + "default": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + "info": "Select the binding the SP claims support for. A binding specifies the technical method of a connection." + }, + "NameIDFormat": { + "type": "string", + "enum": [ + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" + ], + "default": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "info": "This indicates whether the nameID is set to something random or the same every time the user logs in. Use transient if user does not need to be identified in a new session." + }, + "ArpAttribute": { + "type": "array", + "items": { + "type": "object", + "properties": { + "source": { + "type": "string" + }, + "value": { + "type": "string" + }, + "motivation": { + "type": "string" + }, + "release_as": { + "type": "string" + }, + "use_as_nameid": { + "type": "boolean" + } + }, + "additionalProperties": false + } + } + }, + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "eid": { + "type": "number" + }, + "entityid": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "sram" + ] + }, + "revisionid": { + "type": "number" + }, + "state": { + "type": "string", + "enum": [ + "prodaccepted", + "testaccepted" + ] + }, + "metadataurl": { + "type": [ + "string", + "null" + ] + }, + "allowedall": { + "type": "boolean" + }, + "manipulation": { + "type": [ + "string", + "null" + ] + }, + "manipulationNotes": { + "type": [ + "string", + "null" + ] + }, + "user": { + "type": "string" + }, + "created": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "revisionnote": { + "type": "string" + }, + "active": { + "type": "boolean" + }, + "allowedEntities": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + }, + "autoRefresh": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "allowAll": { + "type": "boolean" + }, + "fields": { + "properties": { + "certData": { + "type": "boolean" + }, + "certData2": { + "type": "boolean" + }, + "certData3": { + "type": "boolean" + } + }, + "additionalProperties": false + } + } + }, + "arp": { + "type": "object", + "sources": [ + "ala", + "eduid", + "idp", + "manage", + "orcid", + "pseudo_email", + "sab", + "invite", + "voot" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "attributes": { + "type": "object", + "properties": { + "urn:mace:dir:attribute-def:eduPersonTargetedID": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.10" + }, + "urn:mace:dir:attribute-def:eduPersonPrincipalName": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.6" + }, + "urn:mace:dir:attribute-def:displayName": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:2.16.840.1.113730.3.1.241" + }, + "urn:mace:dir:attribute-def:cn": { + "$ref": "#/definitions/ArpAttribute", + "description": "common name", + "alias": "urn:oid:2.5.4.3" + }, + "urn:mace:dir:attribute-def:givenName": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:2.5.4.42" + }, + "urn:mace:dir:attribute-def:sn": { + "$ref": "#/definitions/ArpAttribute", + "description": "surname", + "alias": "urn:oid:2.5.4.4" + }, + "urn:mace:dir:attribute-def:mail": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:0.9.2342.19200300.100.1.3" + }, + "urn:mace:terena.org:attribute-def:schacHomeOrganization": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.25178.1.2.9" + }, + "urn:mace:terena.org:attribute-def:schacHomeOrganizationType": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.25178.1.2.10" + }, + "urn:schac:attribute-def:schacPersonalUniqueCode": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.25178.1.2.14", + "multiplicity": true + }, + "urn:mace:dir:attribute-def:eduPersonAffiliation": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.1", + "multiplicity": true + }, + "urn:mace:dir:attribute-def:eduPersonScopedAffiliation": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.9", + "multiplicity": true + }, + "urn:mace:dir:attribute-def:eduPersonEntitlement": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.7", + "multiplicity": true + }, + "urn:mace:dir:attribute-def:eduPersonOrcid": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.16" + }, + "urn:mace:dir:attribute-def:eduPersonAssurance": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.1.1.11" + }, + "urn:mace:surf.nl:attribute-def:eckid": { + "$ref": "#/definitions/ArpAttribute" + }, + "urn:mace:eduid.nl:1.1": { + "$ref": "#/definitions/ArpAttribute", + "description": "eduid", + "display": "eduid" + }, + "urn:mace:surf.nl:attribute-def:surf-crm-id": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.1076.20.100.10.50.2" + }, + "urn:mace:dir:attribute-def:isMemberOf": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.5923.1.5.1.1", + "multiplicity": true + }, + "urn:mace:dir:attribute-def:uid": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:0.9.2342.19200300.100.1.1" + }, + "urn:mace:dir:attribute-def:preferredLanguage": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:2.16.840.1.113730.3.1.39" + }, + "urn:mace:surffederatie.nl:attribute-def:nlEduPersonOrgUnit": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.1076.20.40.20.10.1", + "deprecated": true, + "multiplicity": true + }, + "urn:mace:surffederatie.nl:attribute-def:nlEduPersonStudyBranch": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.1076.20.40.20.10", + "deprecated": true, + "multiplicity": true + }, + "urn:mace:surffederatie.nl:attribute-def:nlStudielinkNummer": { + "$ref": "#/definitions/ArpAttribute", + "alias": "urn:oid:1.3.6.1.4.1.1076.20.40.20.10.3", + "deprecated": true + } + } + } + }, + "required": [ + "enabled", + "attributes" + ] + }, + "notes": { + "type": [ + "string", + "null" + ] + }, + "metaDataFields": { + "type": "object", + "properties": { + "NameIDFormat": { + "$ref": "#/definitions/NameIDFormat" + }, + "certData": { + "type": "string", + "format": "certificate", + "info": "The supplied public certificate of the service. This must be a PEM encoded certificate. DER, CRT or CER are not supported." + }, + "logo:0:url": { + "type": "string", + "format": "url", + "info": "Enter the URL to the logo used for this service. e.g. https://static.example-logo.nl/media/sp/logo.png." + }, + "logo:0:width": { + "type": "number", + "info": "The width of the logo found at logo:0:url in pixels." + }, + "logo:0:height": { + "type": "number", + "info": "The height of the logo found at logo:0:url in pixels." + }, + "redirect.sign": { + "type": "boolean", + "info": "Whether authentication request, logout requests and logout responses should be signed. The default is FALSE. This is generally set for trusted proxies like OpenID Connect Gateway or Stepup authentication gateway." + }, + "coin:institution_guid": { + "type": "string", + "format": "uuid", + "info": "This is a 128 bit number also known as a globally unique identifier (GUID or UUID) for this service." + }, + "coin:no_consent_required": { + "type": "boolean", + "info": "Select this option to skip the consent for a user.", + "default": true + }, + "coin:application_url": { + "type": "string", + "format": "url", + "info": "The URL of the service used to log on." + }, + "coin:policy_enforcement_decision_required": { + "type": "boolean", + "info": "Set to activate the user policy engine (PDP)." + }, + "coin:privacy:privacy_policy": { + "type": "boolean", + "info": "Does the SP publish an applicable privacy policy on a web page?" + }, + "coin:privacy:privacy_policy_url": { + "type": "string", + "format": "url", + "info": "The URL to the applicable privacy policy. " + }, + "coin:signature_method": { + "type": "string", + "format": "url", + "enum": [ + "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" + ], + "default": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + "info": "Select the Secure Hash Algorithm (SHA) to use for assertions sent by Engineblock to this service provider." + }, + "connection_type": { + "type": "string", + "enum": [ + "oidc_rp", + "saml_sp" + ], + "default": "oidc_rp", + "info": "Select the protocol of the service.", + "disabledAfterPersisted": true + }, + "secret": { + "type": "string", + "format": "password", + "info": "The secret of this Relying Party for authentication purposes - minimal length 12 characters." + }, + "isPublicClient": { + "type": "boolean", + "default": false, + "info": "Must be set for this Relying Party to be marked as a Public Client to explicitly allow the Proof Key for Code Exchange (PKCE) flow." + }, + "accessTokenValidity": { + "type": "number", + "default": 3600, + "info": "The number of seconds that a new access token is valid for this Relying Party." + }, + "refreshTokenValidity": { + "type": "number", + "default": 3600, + "info": "The number of seconds that a new refresh token is valid for this Relying Party." + }, + "redirectUrls": { + "type": "array", + "items": { + "type": "string", + "format": "{{ manage.oidc_rp_redirect_url_format }}" + }, + "info": "The redirect URI's of this Relying Party." + }, + "grants": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "authorization_code", + "implicit", + "refresh_token", + "client_credentials" + ] + }, + "info": "The authorisation grant type's of this Relying Party." + } + }, + "patternProperties": { + "^name:({{ supported_language_codes | replace(',','|') }})$": { + "type": "string", + "info": "Set the name of the service. Format: 'Service Name'" + }, + "^description:({{ supported_language_codes | replace(',','|') }})$": { + "type": "string", + "info": "The description of the service." + }, + "^AssertionConsumerService:([0-3]{0,1}[0-9]{1}):Binding$": { + "$ref": "#/definitions/AssertionConsumerService_Binding", + "multiplicity": 30, + "info": "An Assertion Consumer Service (or ACS) the location at a ServiceProvider that accepts messages. The type of binding for this location can be selected from the pull-down." + }, + "^AssertionConsumerService:([0-3]{0,1}[0-9]{1}):Location$": { + "type": "string", + "format": "url", + "multiplicity": 30, + "info": "An Assertion Consumer Service (or ACS) is the location at a ServiceProvider that accepts messages. A typical ACS location for an SP might look like this: https://data.example-service.nl/saml/saml2_acs/" + }, + "^AssertionConsumerService:([0-3]{0,1}[0-9]{1}):index$": { + "type": "number", + "multiplicity": 30, + "info": "An Assertion Consumer Service (or ACS) is the location at a ServiceProvider that accepts messages. With the index you can include additional elements in the SAML 2.0 SP metadata with the same binding, each with its own unique index." + }, + "^NameIDFormats:([0-2]{1})$": { + "$ref": "#/definitions/NameIDFormat", + "multiplicity": 3, + "info": "The NameIDFormat(s) this service provider supports. This can be transient, persistent or unspecified." + }, + "^contacts:([0-3]{1}):surName$": { + "type": "string", + "multiplicity": 4, + "sibblingIndependent": true, + "info": "The surname of the contact. e.g. for 'John Doe', 'Doe' is the surname." + }, + "^contacts:([0-3]{1}):givenName$": { + "type": "string", + "multiplicity": 4, + "sibblingIndependent": true, + "info": "The given name of the contact. e.g. for 'John Doe', 'John' is the given name." + }, + "^contacts:([0-3]{1}):emailAddress$": { + "type": "string", + "format": "local-email", + "multiplicity": 4, + "sibblingIndependent": true, + "info": "The e-mail address; syntax in accordance with RFC 5322. e.g. m.l.vermeegen@university.example.org." + }, + "^contacts:([0-3]{1}):telephoneNumber$": { + "type": "string", + "multiplicity": 4, + "sibblingIndependent": true, + "info": "The telephone number of the contact." + }, + "^contacts:([0-3]{1}):contactType$": { + "type": "string", + "enum": [ + "technical", + "support", + "administrative", + "billing", + "other" + ], + "multiplicity": 4, + "sibblingIndependent": true, + "info": "From the pull down, select the type of contact." + }, + "^OrganizationName:({{ supported_language_codes | replace(',','|') }})$": { + "type": "string", + "info": "The formal name of the organization. e.g. Service by University of Harderwijk." + }, + "^url:({{ supported_language_codes | replace(',','|') }})$": { + "type": "string", + "format": "url", + "info": "The URL to the support site of the service." + } + }, + "required": [ + "name:en", + "connection_type", + "OrganizationName:en", + "AssertionConsumerService:0:Binding", + "AssertionConsumerService:0:Location" + ], + "additionalProperties": false + } + }, + "required": [ + "entityid", + "state", + "allowedall", + "metaDataFields" + ], + "additionalProperties": false, + "indexes": [] +} diff --git a/roles/metadata/templates/metadata.conf.j2 b/roles/metadata/templates/metadata.conf.j2 index 2d7eaea3d..292e9ed32 100644 --- a/roles/metadata/templates/metadata.conf.j2 +++ b/roles/metadata/templates/metadata.conf.j2 @@ -18,8 +18,9 @@ Listen {{ apache_app_listen_address.metadata }}:{{ loadbalancing.metadata.port } Header always set X-XSS-Protection "1; mode=block" AddType application/x-pem-file .pem + AddType application/samlmetadata+xml .xml - ForceType text/xml + ForceType application/samlmetadata+xml ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-METADATA'" diff --git a/roles/mujina-idp/tasks/docker.yml b/roles/mujina-idp/tasks/docker.yml index 82ff22c0d..e8438e8fa 100644 --- a/roles/mujina-idp/tasks/docker.yml +++ b/roles/mujina-idp/tasks/docker.yml @@ -30,6 +30,8 @@ pull: true restart_policy: "always" state: started + env: + TZ: "{{ timezone }}" networks: - name: "loadbalancer" mounts: diff --git a/roles/myconext-gui/defaults/main.yml b/roles/myconext-gui/defaults/main.yml deleted file mode 100644 index 136cbd6a7..000000000 --- a/roles/myconext-gui/defaults/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -myconext_gui_version: '' -myconext_gui_snapshot_timestamp: '' -myconext_install: true -myconext_skip_wayf: true diff --git a/roles/myconext-gui/meta/main.yml b/roles/myconext-gui/meta/main.yml deleted file mode 100644 index ed97d539c..000000000 --- a/roles/myconext-gui/meta/main.yml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/roles/myconext-gui/tasks/main.yml b/roles/myconext-gui/tasks/main.yml deleted file mode 100644 index 50cdcf59e..000000000 --- a/roles/myconext-gui/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: copy virtual host config - template: - src: myconext.conf.j2 - dest: /etc/httpd/conf.d/myconext.conf - notify: restart httpd diff --git a/roles/myconext-gui/templates/myconext.conf.j2 b/roles/myconext-gui/templates/myconext.conf.j2 deleted file mode 100644 index c85c686de..000000000 --- a/roles/myconext-gui/templates/myconext.conf.j2 +++ /dev/null @@ -1,130 +0,0 @@ -{% if apache_app_listen_address.myconext is defined %} -Listen {{ apache_app_listen_address.myconext }}:{{ loadbalancing.myconext.port }} - -{% else %} - -{% endif %} - # General setup for the virtual host, inherited from global configuration - ServerName https://mijn.{{ myconext_base_domain }} - - ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-myconext'" - CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-myconext'" combined - - RewriteEngine on - - {% for links in myconext.links %} - RewriteRule "^/{{ links.name }}(/|$)" "{{ links.url }}" [R,L] - {% endfor %} - - 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} !^/myconext - RewriteCond %{REQUEST_URI} !^/tiqr - RewriteCond %{REQUEST_URI} !^/actuator - RewriteCond %{REQUEST_URI} !^/internal - RewriteCond %{REQUEST_URI} !^/config - RewriteCond %{REQUEST_URI} !^/login - RewriteCond %{REQUEST_URI} !^/startSSO - RewriteCond %{REQUEST_URI} !^/fonts - RewriteCond %{REQUEST_URI} !^/.well-known - RewriteRule (.*) /index.html [L] - - ProxyPreserveHost On - ProxyPass /Shibboleth.sso ! - - ProxyPass /myconext/api http://localhost:{{ springapp_tcpport }}/myconext/api retry=0 - ProxyPassReverse /myconext/api http://localhost:{{ springapp_tcpport }}/myconext/api - - ProxyPass /tiqr http://localhost:{{ springapp_tcpport }}/tiqr retry=0 - ProxyPassReverse /tiqr http://localhost:{{ springapp_tcpport }}/tiqr - - ProxyPass /internal http://localhost:{{ springapp_tcpport }}/internal retry=0 - ProxyPass /actuator http://localhost:{{ springapp_tcpport }}/internal retry=0 - ProxyPass /login http://localhost:{{ springapp_tcpport }}/login retry=0 - ProxyPass /startSSO http://localhost:{{ springapp_tcpport }}/startSSO retry=0 - ProxyPass /config http://localhost:{{ springapp_tcpport }}/config retry=0 - - - AuthType shibboleth - ShibUseHeaders On - ShibRequestSetting applicationId myconext - {% if myconext_skip_wayf is defined and myconext_skip_wayf %} - ShibRequestSetting entityID https://login.{{ myconext_base_domain }} - {% endif %} - ShibRequireSession On - Require valid-user - - - DocumentRoot "{{ _springapp_dir }}/current" - - - Require all granted - Options -Indexes - - - # Public endpoints - - Require all granted - - - # After logout / delete - - Require all granted - - - {% if myconext.feature_create_eduid_institution_enabled %} - - Require all granted - - {% endif %} - - # The Spring Boot endpoints - - Require all granted - - - Require all granted - - - # Svelte resources - - Require all granted - - - - Require all granted - - - - Require all granted - - - Header always set Content-Security-Policy "{{ httpd_csp.lenient_with_static_img }}" - Header always set X-Frame-Options "DENY" - Header always set Referrer-Policy "same-origin" - Header always set X-Content-Type-Options "nosniff" - - {% if haproxy_backend_tls %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/backend.{{ base_domain }}.pem - SSLCertificateKeyFile {{ tls.cert_private_path }}/backend.{{ base_domain }}.key - Include ssl_backend.conf - {% endif %} - - {% if apache_app_listen_address.all is defined %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/{{ tls_star_cert }} - SSLCertificateKeyFile {{ tls.cert_private_path }}/{{ tls_star_cert_key }} - SSLCertificateChainFile {{ tls.cert_path_ca }}/{{ tls_ca }} - Include ssl_backend.conf - {% endif %} - - diff --git a/roles/myconext-gui/vars/main.yml b/roles/myconext-gui/vars/main.yml deleted file mode 100644 index 51cb36e6d..000000000 --- a/roles/myconext-gui/vars/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -springapp_tcpport: 9189 -springapp_artifact_id: myconext-gui -springapp_version: "{{ myconext_gui_version }}" diff --git a/roles/myconext-server/defaults/main.yml b/roles/myconext-server/defaults/main.yml deleted file mode 100644 index a8a628f00..000000000 --- a/roles/myconext-server/defaults/main.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -myconext_dir: /opt/myconext -myconext_snapshot_timestamp: '' -myconext_jar: myconext-current.jar -myconext_random_source: 'file:///dev/urandom' -myconext_install: true -myconext_cronjobmaster: true diff --git a/roles/myconext-server/handlers/main.yml b/roles/myconext-server/handlers/main.yml deleted file mode 100644 index 3d20a5b33..000000000 --- a/roles/myconext-server/handlers/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: restart myconext - service: - name: myconext - state: restarted - daemon_reload: yes diff --git a/roles/myconext-server/meta/main.yml b/roles/myconext-server/meta/main.yml deleted file mode 100644 index ed97d539c..000000000 --- a/roles/myconext-server/meta/main.yml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/roles/myconext-server/tasks/main.yml b/roles/myconext-server/tasks/main.yml deleted file mode 100644 index 9dc1a2767..000000000 --- a/roles/myconext-server/tasks/main.yml +++ /dev/null @@ -1,65 +0,0 @@ ---- - -- name: copy config - template: - src: "{{ item }}.j2" - dest: "{{ myconext_dir }}/{{ item }}" - owner: myconext - group: myconext - mode: 0740 - with_items: - - logback.xml - - application.yml - - tiqr.configuration.yml - notify: - - "restart myconext" - -- name: copy / create GCM config - copy: - src: "{{ inventory_dir }}/files/myconext/firebase.json" - dest: "{{ myconext_dir }}/firebase.json" - owner: "root" - group: "myconext" - mode: 0740 - notify: - - "restart myconext" - -- name: copy / create APNS certificate - copy: - content: "{{ myconext_apns }}" - dest: "{{ myconext_dir }}/apns.p8" - owner: "root" - group: "myconext" - mode: 0740 - notify: - - "restart myconext" - -- name: copy / create private key - copy: - content: "{{ myconext_private_key }}" - dest: "{{ myconext_dir }}/myconext_saml.key" - owner: "root" - group: "myconext" - mode: 0740 - notify: - - "restart myconext" - -- name: copy / create certificate - copy: - src: "{{ inventory_dir }}/files/certs/myconext/myconext_saml.crt" - dest: "{{ myconext_dir }}/myconext_saml.crt" - owner: "root" - group: "myconext" - mode: 0740 - notify: - - "restart myconext" - -- name: create geo download directory - file: - path: "{{ myconext_dir }}/geo2lite" - state: directory - owner: "{{ _springapp_user }}" - group: "{{ _springapp_user }}" - mode: 0760 - -- meta: flush_handlers diff --git a/roles/myconext-server/templates/logback.xml.j2 b/roles/myconext-server/templates/logback.xml.j2 deleted file mode 100644 index 1f3b85483..000000000 --- a/roles/myconext-server/templates/logback.xml.j2 +++ /dev/null @@ -1,62 +0,0 @@ -#jinja2:lstrip_blocks: True - - - - - /var/log/myconext/myconext.log - - - /var/log/myconext/myconext-%d{yyyy-MM-dd}.log.gz - {{ logback_max_history }} - - - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - - - - {{ ansible_fqdn }} - 514 - {"app":"myconext"} - - [ignore] - [ignore] - [ignore] - - - myconextjson: - - - - - {{ rsyslog_host }} - DAEMON - myconext: [%thread] %logger %msg - - - - {{ smtp_server }} - {{ noreply_email }} - {{ error_mail_to }} - {{ error_subject_prefix }}Unexpected error myconext - - - - myconext.exceptions.ExpiredAuthenticationException - myconext.exceptions.UserNotFoundException - ERROR - - - - - - - - - - - - - - - diff --git a/roles/myconext-server/vars/main.yml b/roles/myconext-server/vars/main.yml deleted file mode 100644 index 6fe920066..000000000 --- a/roles/myconext-server/vars/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -springapp_artifact_id: myconext-server -springapp_artifact_type: jar -springapp_artifact_group_dir: org.openconext -springapp_version: "{{ myconext_server_version }}" -springapp_dir: "{{ myconext_dir }}" -springapp_user: myconext -springapp_service_name: myconext -springapp_jar: "{{ myconext_jar }}" -springapp_tcpport: 9189 -springapp_random_source: "file:///dev/urandom" diff --git a/roles/myconext/defaults/main.yml b/roles/myconext/defaults/main.yml new file mode 100644 index 000000000..2fa088e32 --- /dev/null +++ b/roles/myconext/defaults/main.yml @@ -0,0 +1,2 @@ +--- +myconext_cronjobmaster: true diff --git a/roles/myconext/handlers/main.yml b/roles/myconext/handlers/main.yml new file mode 100644 index 000000000..f0285c7e7 --- /dev/null +++ b/roles/myconext/handlers/main.yml @@ -0,0 +1,5 @@ +- name: restart myconextserver + community.docker.docker_container: + name: myconextserver + state: started + restart: true diff --git a/roles/myconext/tasks/main.yml b/roles/myconext/tasks/main.yml new file mode 100644 index 000000000..3bb0cc2d6 --- /dev/null +++ b/roles/myconext/tasks/main.yml @@ -0,0 +1,184 @@ +--- +- name: Create common certs directory + ansible.builtin.file: + dest: /opt/openconext/certs/ + state: directory + owner: root + group: root + mode: "0755" + +- name: Install the Mongo CA certificate + ansible.builtin.copy: + src: "{{ inventory_dir }}/secrets/mongo/mongoca.pem" + dest: /opt/openconext/certs/mongoca.crt + owner: root + group: root + mode: "0644" + +- name: Create directory to keep configfiles + ansible.builtin.file: + dest: "/opt/openconext/myconext" + state: directory + owner: root + group: root + mode: "0770" + +- name: Place the serverapplication configfiles + ansible.builtin.template: + src: "{{ item }}.j2" + dest: /opt/openconext/myconext/{{ item }} + owner: root + group: root + mode: "0644" + with_items: + - application.yml + - logback.xml + - tiqr.configuration.yml + notify: restart myconextserver + +- name: Copy / create GCM config + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/myconext/firebase.json" + dest: "/opt/openconext/myconext/firebase.json" + owner: "root" + group: "root" + mode: "0640" + notify: + - "restart myconextserver" + +- name: Copy / create APNS certificate + ansible.builtin.copy: + content: "{{ myconext_apns }}" + dest: "/opt/openconext/myconext/apns.p8" + owner: "root" + group: "root" + mode: "0740" + notify: + - "restart myconextserver" + +- name: copy / create private key + ansible.builtin.copy: + content: "{{ myconext_private_key }}" + dest: "/opt/openconext/myconext/myconext_saml.key" + owner: "root" + group: "root" + mode: "0640" + notify: + - "restart myconextserver" + +- name: copy / create certificate + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/certs/myconext/myconext_saml.crt" + dest: "/opt/openconext/myconext/myconext_saml.crt" + owner: "root" + group: "root" + mode: "0740" + notify: + - "restart myconextserver" + +- name: Create geo download directory + ansible.builtin.file: + path: "/opt/openconext/myconext/geo2lite" + state: directory + owner: "root" + group: "root" + mode: "0750" + +- name: Create and start the server container + community.docker.docker_container: + name: myconextserver + image: ghcr.io/openconext/openconext-myconext/myconext-server:{{ myconext_server_version }} + pull: true + restart_policy: "always" + state: started + env: + USE_SYSTEM_CA_CERTS: "true" + TZ: "{{ timezone }}" + networks: + - name: "loadbalancer" + mounts: + - source: /opt/openconext/myconext/ + target: /config/ + type: bind + - source: /opt/openconext/certs/mongoca.crt + target: /certificates/mongoca.crt + type: bind + entrypoint: /__cacert_entrypoint.sh + command: 'java -jar /app.jar -Xmx256M --spring.config.location=./config/' + 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 myconextserver + +- name: Create the client container + community.docker.docker_container: + name: myconextgui + image: ghcr.io/openconext/openconext-myconext/myconext-gui:{{ myconext_gui_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.myconextgui.rule: "Host(`mijn.{{ myconext_base_domain }}`)" + traefik.http.routers.myconextgui.tls: "true" + traefik.enable: "true" + healthcheck: + test: ["CMD", "curl", "--fail" , "http://localhost" ] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind + env: + HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img }}" + HTTPD_SERVERNAME: "mijn.{{ myconext_base_domain }}" + OPENCONEXT_INSTANCENAME: "{{ instance_name }}" + OPENCONEXT_ENGINE_LOGOUT_URL: "https://engine.{{ base_domain }}/logout" + OPENCONEXT_HELP_EMAIL: "{{ support_email }}" + SHIB_ENTITYID: "https://mijn.{{ myconext_base_domain }}/shibboleth" + SHIB_REMOTE_ENTITYID: "https://engine.{{ base_domain }}/authentication/idp/metadata" + SHIB_REMOTE_METADATA: "{{ shibboleth_metadata_sources.engine }}" + +- name: Create the account gui + community.docker.docker_container: + name: accountgui + image: ghcr.io/openconext/openconext-myconext/account-gui:{{ account_gui_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.accountgui.rule: "Host(`login.{{ myconext_base_domain }}`)" + traefik.http.routers.accountgui.tls: "true" + traefik.enable: "true" + healthcheck: + test: ["CMD", "curl", "--fail" , "http://localhost"] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind + + env: + HTTPD_CSP: "{{ httpd_csp.lenient_with_static_img_for_idp }}" + HTTPD_SERVERNAME: "login.{{ myconext_base_domain }}" + diff --git a/roles/myconext-server/templates/application.yml.j2 b/roles/myconext/templates/application.yml.j2 similarity index 72% rename from roles/myconext-server/templates/application.yml.j2 rename to roles/myconext/templates/application.yml.j2 index 3422965c3..eacbbf223 100644 --- a/roles/myconext-server/templates/application.yml.j2 +++ b/roles/myconext/templates/application.yml.j2 @@ -1,5 +1,5 @@ logging: - config: file://{{ myconext_dir }}/logback.xml + config: file:///config/logback.xml level: org.springframework.data.mongodb: INFO org.springframework.data.convert: INFO @@ -7,7 +7,7 @@ logging: server: # The port to where this Spring Boot application listens to. - port: {{ springapp_tcpport }} + port: 8080 error: path: "/error" server-header: @@ -21,12 +21,15 @@ server: max-http-header-size: 20000 springdoc: - pathsToMatch: "/mobile/**" + pathsToMatch: + - "/api/remote-creation/**" + - "/mobile/**" api-docs: - path: "/myconext/api/mobile/api-docs" + path: "/myconext/api/api-docs" enabled: true + # resolves to https://login.test2.eduid.nl/myconext/api/swagger-ui/index.html swagger-ui: - path: "/myconext/api/mobile/api-ui.html" + path: "/myconext/api/" operationsSorter: method enabled: true @@ -35,6 +38,7 @@ email: magic-link-url: https://login.{{ myconext_base_domain }}/saml/guest-idp/magic my-surfconext-url: https://mijn.{{ myconext_base_domain }} idp-surfconext-url: https://login.{{ myconext_base_domain }} + mail-templates-directory: classpath:mail_templates identity-provider-meta-data: single_sign_on_service_uri: "https://login.{{ myconext_base_domain }}/saml/guest-idp/SSO" @@ -47,19 +51,14 @@ schac_home_organization: eduid.nl cron: node-cron-job-responsible: {{ myconext_cronjobmaster }} token-cleaner-expression: "0 0/15 * * * *" - service-name-resolver-initial-delay-milliseconds: 120_000 - service-name-resolver-fixed-rate-milliseconds: 43_200_000 - metadata-resolver-initial-delay-milliseconds: 1 - metadata-resolver-fixed-rate-milliseconds: 86_400_000 - metadata-resolver-url: "https://metadata.surfconext.nl/idps-metadata.xml" + manage-initial-delay-milliseconds: 15000 + manage-fixed-rate-milliseconds: 300_000 manage: username: myconext password: "{{ manage_myconext_secret }}" base_url: "https://manage.{{ base_domain }}" enabled: True - # Can also be a https url - fallback_url: "classpath:metadata/sp-names.json" base_domain: {{ myconext_base_domain }} saml_metadata_base_path: https://login.{{ myconext_base_domain }} @@ -71,7 +70,7 @@ rp_origin: https://login.{{ myconext_base_domain }} sp_redirect_url: https://mijn.{{ myconext_base_domain }} sp_entity_id: {{ myconext.sp_entity_id }} sp_entity_metadata_url: {{ myconext.sp_entity_metadata_url }} -guest_idp_entity_id: https://login.{{ myconext_base_domain }} +guest_idp_entity_id: https://engine.{{ base_domain }}/authentication/idp/metadata my_conext_url: https://mijn.{{ myconext_base_domain }} domain: {{ myconext_base_domain }} mijn_eduid_entity_id: https://mijn.{{ myconext_base_domain }}/shibboleth @@ -83,8 +82,6 @@ feature: webauthn: {{ myconext.feature_webauthn }} warning_educational_email_domain: {{ myconext.feature_warning_educational_email_domain }} connections: {{ myconext.feature_show_connections }} - # Do we allow the account linking to take place with the accounting IdP, e.g. add extra button in IdP link screen - use_external_validation: {{ myconext.feature_use_external_validation }} # Do we deny emails that are known Disposable Email Providers deny_disposable_email_providers: {{ myconext.feature_deny_disposable_email_providers }} use_deny_allow_list: @@ -98,12 +95,16 @@ feature: default_remember_me: True # Does the SAMLIdpService expects authn requests to be signed requires_signed_authn_request: False + # Do we support ID verify + id_verify: {{ myconext.feature_id_verify}} + # Do we support the remote creation API (e.g. for studielink) + remote_creation_api: {{ myconext.feature_remote_creation_api }} secure_cookie: true idp_entity_id: https://login.{{ myconext_base_domain }} -private_key_path: file://{{ myconext_dir }}/myconext_saml.key -certificate_path: file://{{ myconext_dir }}/myconext_saml.crt +private_key_path: file:///config/myconext_saml.key +certificate_path: file:///config/myconext_saml.crt tiqr_hash_secret: "{{ myconext_tiqr_hash_secret }}" remember_me_max_age_seconds: 15_768_000 @@ -117,21 +118,34 @@ sms: url: "{{ myconext.sms_api_url}}" bearer: "{{ myconext_sms_bearer }}" -tiqr_configuration: "file://{{ myconext_dir }}/tiqr.configuration.yml" - - -attribute_aggregation: - user: aa - password: {{ myconext_api_attribute_aggregation_password }} - -attribute_manipulation: - user: oidcng - password: {{ myconext_api_attribute_manipulation_password }} +tiqr_configuration: "file:///config/tiqr.configuration.yml" + +# We don't encode in-memory passwords, so we need to prefix them with {noop} +external-api-configuration: + remote-users: + - + username: aa + password: "{{ myconext_api_attribute_aggregation_password }}" + scopes: + - attribute-aggregation + - system + - + username: oidcng + password: "{{ myconext_api_attribute_manipulation_password }}" + scopes: + - attribute-manipulation + - + username: studielink + password: "{{ myconext_api_studielink_password }}" + scopes: + - remote-creation + institutionGUID: ec9d6d75-0d11-e511-80d0-005056956c1a + schac_home: studielink.nl oidc-token-api: token-url: https://connect.{{ base_domain }}/tokens user: eduid - password: {{ oidcng_api_tokens_eduid_password }} + password: "{{ oidcng_api_tokens_eduid_password }}" enabled: {{ oidcng.token_api_enabled }} oidc: @@ -153,11 +167,11 @@ linked_accounts: account_linking_context_class_ref: linked_institution: https://eduid.nl/trust/linked-institution validate_names: https://eduid.nl/trust/validate-names + validate_names_external: https://eduid.nl/trust/validate-names-external affiliation_student: https://eduid.nl/trust/affiliation-student profile_mfa: https://refeds.org/profile/mfa account_linking: - idp_external_validation_entity_id: {{ myconext.idp_external_validation_entity_id }} myconext_sp_entity_id: https://mijn.{{ myconext_base_domain }}/shibboleth eduid_api: @@ -170,7 +184,17 @@ eduid_api: geo_location: license_key: {{ myconext_geo2lite_license_key }} external_url: "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key={license_key}&suffix=tar.gz" - download_directory: "{{ myconext_dir }}/geo2lite" + download_directory: "/config/geo2lite" + +# Signicat configuration +verify: + client_id: {{ myconext_verify_client_id }} + secret: {{ myconext_verify_secret }} + base_uri: {{ myconext.verify_base_uri }} + sp_verify_redirect_url: https://mijn.{{ myconext_base_domain }}/myconext/api/sp/verify/redirect + idp_verify_redirect_url: https://login.{{ myconext_base_domain }}/myconext/api/idp/verify/redirect + mobile_verify_redirect_url: https://mijn.{{ myconext_base_domain }}/myconext/api/mobile/verify/redirect + issuers_path: "classpath:idin/issuers.json" spring: data: @@ -178,7 +202,7 @@ spring: uri: mongodb://{{ myconext.mongo_user }}:{{ myconext.mongo_password }}@{% for host in groups['mongo_servers'] %}{{ hostvars[host]['inventory_hostname'] }}:{{ myconext.mongo_port }}{% if not loop.last %},{% endif %}{% endfor %}/{{ myconext.mongo_database }}?ssl=true mail: - host: localhost + host: {{ smtp_server }} port: 25 main: banner-mode: "off" @@ -188,12 +212,14 @@ management: health: mail: enabled: true + show-details: always + info: + enabled: true + git: + mode: full # We disable all endpoints except health for the load-balancer and info for git information. endpoints: - enabled: false - health: - enabled: true - info: - enabled: true - git: - mode: full + web: + exposure: + include: "health,info,mappings,metrics" + base-path: "/internal" diff --git a/roles/myconext/templates/logback.xml.j2 b/roles/myconext/templates/logback.xml.j2 new file mode 100644 index 000000000..57b0ab15f --- /dev/null +++ b/roles/myconext/templates/logback.xml.j2 @@ -0,0 +1,20 @@ +#jinja2:lstrip_blocks: True + + + + + + %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n + + + + + + + + + + + + + diff --git a/roles/myconext-server/templates/tiqr.configuration.yml.j2 b/roles/myconext/templates/tiqr.configuration.yml.j2 similarity index 85% rename from roles/myconext-server/templates/tiqr.configuration.yml.j2 rename to roles/myconext/templates/tiqr.configuration.yml.j2 index 79954e093..e09df4e49 100644 --- a/roles/myconext-server/templates/tiqr.configuration.yml.j2 +++ b/roles/myconext/templates/tiqr.configuration.yml.j2 @@ -13,7 +13,7 @@ rateLimitResetMinutes: 30 apns: serverHost: "api.push.apple.com" port: 443 - signingKey: "file://{{ myconext_dir }}/apns.p8" + signingKey: "file:///config/apns.p8" # Leave empty for non-local development serverCertificateChain: "" topic: "nl.eduid" @@ -21,5 +21,5 @@ apns: keyId: "{{ myconext.apns_keyid }}" gcm: - firebaseServiceAccount: "file://{{ myconext_dir }}/firebase.json" + firebaseServiceAccount: "file:///config/firebase.json" appName: "tiqr" diff --git a/roles/mysql/tasks/main.yml b/roles/mysql/tasks/main.yml index 52b37f35b..0f9eb3e05 100644 --- a/roles/mysql/tasks/main.yml +++ b/roles/mysql/tasks/main.yml @@ -47,7 +47,7 @@ user: "" state: absent login_user: root - host: "{{ mysql_host }}" + host: "{{ mariadb_host }}" login_password: "{{ mysql_root_password }}" tags: - mysql @@ -57,7 +57,7 @@ user: "" state: absent login_user: root - host: "{{ mysql_host }}" + host: "{{ mariadb_host }}" login_password: "{{ mysql_root_password }}" tags: - mysql diff --git a/roles/oidc-playground/tasks/main.yml b/roles/oidc-playground/tasks/main.yml index 83286f4b8..fd4b0d0f7 100644 --- a/roles/oidc-playground/tasks/main.yml +++ b/roles/oidc-playground/tasks/main.yml @@ -23,6 +23,8 @@ - name: Create and start the server container community.docker.docker_container: name: oidcplaygroundserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-oidc-playground/oidc-playground-server:{{ oidc_playground_server_version }} pull: true restart_policy: "always" @@ -73,6 +75,13 @@ timeout: 10s retries: 3 start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/html/favicon.ico + type: bind env: HTTPD_CSP: "{{ httpd_csp.lenient }}" diff --git a/roles/oidc-playground/templates/serverapplication.yml.j2 b/roles/oidc-playground/templates/serverapplication.yml.j2 index ea3261872..9edc8219b 100644 --- a/roles/oidc-playground/templates/serverapplication.yml.j2 +++ b/roles/oidc-playground/templates/serverapplication.yml.j2 @@ -13,6 +13,8 @@ server: max-http-header-size: 10000000 tomcat: max-http-post-size: 10000000 + forward-headers-strategy: native + management: health: diff --git a/roles/oidcng/defaults/main.yml b/roles/oidcng/defaults/main.yml index c8441fa86..23d6def24 100644 --- a/roles/oidcng/defaults/main.yml +++ b/roles/oidcng/defaults/main.yml @@ -1,15 +1,13 @@ --- -oidcng_dir: /opt/oidcng +oidcng_dir: /opt/openconext/oidcng +oidcng_config_dir: /config oidcng_version: '' oidcng_snapshot_timestamp: '' -oidcng_jar: oidcng-current.jar -oidcng_random_source: 'file:///dev/urandom' oidcng_cronjobmaster: true oidcng_saml_sp_entityid: https://connect.{{ base_domain }} oidcng_idp_metadata_url: https://engine.{{ base_domain }}/authentication/idp/metadata oidcng_base_hostname: connect.{{ base_domain }} oidcng_logback_email: true -oidcng_logback_file: true oidcng_logback_json: true oidcng_idp_sso_location: https://engine.{{ base_domain }}/authentication/idp/single-sign-on oidcng_manage_provision_samlsp_client_id: "https://connect.{{ base_domain }}" diff --git a/roles/oidcng/handlers/main.yml b/roles/oidcng/handlers/main.yml index 9d3fdc354..c180bf02b 100644 --- a/roles/oidcng/handlers/main.yml +++ b/roles/oidcng/handlers/main.yml @@ -1,7 +1,6 @@ --- - name: "restart oidcng" - systemd: - name: oidcng - state: restarted - daemon-reload: yes - + community.docker.docker_container: + name: dashboardserver + state: started + restart: true diff --git a/roles/oidcng/tasks/main.yml b/roles/oidcng/tasks/main.yml index 597561cb3..d1e2ce47b 100644 --- a/roles/oidcng/tasks/main.yml +++ b/roles/oidcng/tasks/main.yml @@ -1,84 +1,135 @@ --- +- name: Create config dir + ansible.builtin.file: + path: "{{ oidcng_dir }}" + state: directory + owner: root + group: root + mode: "0750" -- name: copy config - template: +- name: Copy config + ansible.builtin.template: src: "{{ item }}.j2" dest: "{{ oidcng_dir }}/{{ item }}" owner: root - group: oidcng - mode: 0740 + group: root + mode: "0640" with_items: - logback.xml - application.yml notify: - "restart oidcng" -- name: copy oidcng secret keyset configuration - template: +- name: Copy oidcng secret keyset configuration + ansible.builtin.template: src: "secret_keyset.json.j2" dest: "{{ oidcng_dir }}/secret_keyset.json" + owner: root + group: root + mode: "0640" notify: - "restart oidcng" -- name: copy oidcng well-known discovery configuration - template: +- name: Copy oidcng well-known discovery configuration + ansible.builtin.template: src: "openid-configuration.json.j2" dest: "{{ oidcng_dir }}/openid-configuration.json" + owner: root + group: root + mode: "0640" notify: - "restart oidcng" -- name: copy oidc saml mapping - copy: +- name: Copy oidc saml mapping + ansible.builtin.copy: src: oidc_saml_mapping.json dest: "{{ oidcng_dir }}" owner: "root" - group: "oidcng" - mode: 0740 + group: "root" + mode: "0640" notify: - "restart oidcng" -- name: copy / create private key - copy: +- name: Copy / create SAML private key + ansible.builtin.copy: content: "{{ oidcng_private_key }}" dest: "{{ oidcng_dir }}/oidcsaml.key" owner: "root" - group: "oidcng" - mode: 0740 + group: "root" + mode: "0640" notify: - "restart oidcng" -- name: copy / create certificate - copy: +- name: Copy / create SAML certificate + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/oidc/oidcsaml.crt" dest: "{{ oidcng_dir }}/oidcsaml.crt" owner: "root" - group: "oidcng" - mode: 0740 + group: "root" + mode: "0640" notify: - "restart oidcng" -- name: copy / create metatdata signing certificate - copy: +- name: Copy engineblock signing certificate + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/oidcng/SURFconext-metadata-signer.pem" dest: "{{ oidcng_dir }}/SURFconext-metadata-signer.pem" owner: "root" - group: "oidcng" - mode: 0740 + group: "root" + mode: "0640" notify: - "restart oidcng" -- name: copy apache config - template: - src: "oidcng.conf.j2" - dest: "/etc/httpd/conf.d/oidcng.conf" - notify: - - "reload httpd" +- name: Create and start the server container + community.docker.docker_container: + name: oidcngserver + image: ghcr.io/openconext/openconext-oidcng/oidcng:{{ oidcng_version }} + entrypoint: /__cacert_entrypoint.sh + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + mounts: + - source: "{{ oidcng_dir }}" + target: /config/ + type: bind + - source: /opt/openconext/manage/mongoca.pem + target: /certificates/mongoca.crt + type: bind + command: "java -jar /app.jar -Xmx512m --spring.config.location=./config/" + etc_hosts: + host.docker.internal: host-gateway + env: + USE_SYSTEM_CA_CERTS: "true" + TZ: "{{ timezone }}" + healthcheck: + test: + [ + "CMD", + "wget", + "-no-verbose", + "--tries=1", + "--spider", + "http://localhost:8080/internal/health", + ] + interval: 10s + timeout: 10s + retries: 3 + start_period: 10s + labels: + traefik.enable: "true" + traefik.http.services.oidcng.loadbalancer.server.port: "8080" + traefik.http.routers.oidcng.rule: "Host(`connect.{{ base_domain }}`)" + traefik.http.routers.oidcng.tls: "true" + traefik.http.routers.oidcng.middlewares: oidcngmw@docker + traefik.http.middlewares.oidcngmw.replacepathregex.regex: "^/.well-known/openid-configuration" + traefik.http.middlewares.oidcngmw.replacepathregex.replacement: "/oidc/.well-known/openid-configuration" -- meta: flush_handlers -- name: Include the role manage_provision_entities to provision oidncg to Manage - include_role: - name: manage_provision_entities - vars: - entity_type: saml20_sp +#- name: Include the role manage_provision_entities to provision oidncg to Manage +# ansible.builtin.include_role: +# name: manage_provision_entities +# vars: +# entity_type: saml20_sp diff --git a/roles/oidcng/templates/application.yml.j2 b/roles/oidcng/templates/application.yml.j2 index 24a4b068c..4615094b4 100644 --- a/roles/oidcng/templates/application.yml.j2 +++ b/roles/oidcng/templates/application.yml.j2 @@ -1,6 +1,6 @@ # The logging configuration. logging: - config: file://{{ oidcng_dir }}/logback.xml + config: file://{{ oidcng_config_dir }}/logback.xml level: org.springframework: WARN oidc: WARN @@ -14,10 +14,16 @@ cron: key-rollover-expression: {{ oidcng.key_rollover_cron_expression }} consent-expiry-duration-days: 90 +keys-cache: + # The max-age cache control for signing keys in seconds + cache-duration-seconds: 3600 + # The time in seconds where new signing keys are published, but not used + idle-time-seconds: 7200 server: # The port to where this Spring Boot application listens to. - port: {{ springapp_tcpport }} + port: 8080 + forward-headers-strategy: native error: path: "/error" server-header: @@ -34,13 +40,13 @@ server: max-swallow-size: 10000000 mongodb_db: {{ oidcng.mongo_database }} -oidc_saml_mapping_path: file://{{ oidcng_dir }}/oidc_saml_mapping.json -openid_configuration_path: file://{{ oidcng_dir }}/openid-configuration.json -secret_key_set_path: file://{{ oidcng_dir }}/secret_keyset.json +oidc_saml_mapping_path: file://{{ oidcng_config_dir }}/oidc_saml_mapping.json +openid_configuration_path: file://{{ oidcng_config_dir }}/openid-configuration.json +secret_key_set_path: file://{{ oidcng_config_dir }}/secret_keyset.json associated_data: {{ oidcng_associated_data }} access_token_one_way_hash_salt: {{ oidcng_access_token_one_way_hash_salt }} -private_key_path: file://{{ oidcng_dir }}/oidcsaml.key -certificate_path: file://{{ oidcng_dir }}/oidcsaml.crt +private_key_path: file://{{ oidcng_config_dir }}/oidcsaml.key +certificate_path: file://{{ oidcng_config_dir }}/oidcsaml.crt default_acr_value: {{ oidcng.default_acr_value }} secure_cookie: true oidc_token_endpoint: https://connect.{{ base_domain }}/oidc/token @@ -62,7 +68,7 @@ sp: idp: entity_id: https://engine.{{ base_domain }}/authentication/idp/metadata sso_location: {{ oidcng_idp_sso_location }} - saml_assertion_signing_key: file://{{ oidcng_dir }}/SURFconext-metadata-signer.pem + saml_assertion_signing_key: file://{{ oidcng_config_dir }}/SURFconext-metadata-signer.pem spring: data: @@ -74,18 +80,43 @@ spring: manage: user: manage - password: {{ oidcng_api_metadata_push_password }} + password: "{{ oidcng_api_metadata_push_password }}" token-api: enabled: {{ oidcng.token_api_enabled }} users: - user: eduid - password: {{ oidcng_api_tokens_eduid_password }} + password: "{{ oidcng_api_tokens_eduid_password }}" - user: profile - password: {{ oidcng_api_tokens_profile_password }} + password: "{{ oidcng_api_tokens_profile_password }}" eduid: user: oidcng - password: {{ myconext_api_attribute_manipulation_password }} - uri: https://login.{{ myconext_base_domain }}/myconext/api/attribute-manipulation + password: "{{ myconext_api_attribute_manipulation_password }}" + uri: "https://login.{{ myconext_base_domain }}/myconext/api/attribute-manipulation" enabled: {{ oidcng.eduid_attribute_manipulation_enabled }} + + +management: + health: + mail: + enabled: false + endpoints: + web: + exposure: + include: "health,info,mappings" + base-path: "/internal" + endpoint: + info: + enabled: true + mappings: + enabled: true + info: + git: + mode: full + +# used by the git plugin +info: + build: + artifact: "@project.artifactId@" + version: "@project.version@" diff --git a/roles/oidcng/templates/logback.xml.j2 b/roles/oidcng/templates/logback.xml.j2 index 767ba7aa3..21422750c 100644 --- a/roles/oidcng/templates/logback.xml.j2 +++ b/roles/oidcng/templates/logback.xml.j2 @@ -2,24 +2,12 @@ - - /var/log/oidcng/oidcng.log - - - /var/log/oidcng/oidcng-%d{yyyy-MM-dd}.log.gz - {{ logback_max_history }} - - + + %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n - - {{ rsyslog_host }} - DAEMON - oidcng: [%thread] %logger %msg - - {{ ansible_fqdn }} 514 @@ -55,13 +43,10 @@ -{%if oidcng_logback_file |bool %} - -{%endif%} {%if oidcng_logback_email |bool %} {%endif%} - + {%if oidcng_logback_json |bool %} {%endif%} diff --git a/roles/oidcng/templates/oidcng.conf.j2 b/roles/oidcng/templates/oidcng.conf.j2 index e054d7958..40b7cfad8 100644 --- a/roles/oidcng/templates/oidcng.conf.j2 +++ b/roles/oidcng/templates/oidcng.conf.j2 @@ -9,7 +9,7 @@ Listen {{ apache_app_listen_address.oidcng }}:{{ loadbalancing.oidcng.port }} ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-oidcng'" CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-oidcng'" combined - + LimitRequestFieldSize 16384 ProxyPass /.well-known/openid-configuration http://localhost:{{ springapp_tcpport}}/oidc/.well-known/openid-configuration retry=0 ProxyPass /actuator http://localhost:{{ springapp_tcpport}}/internal retry=0 diff --git a/roles/pdp/tasks/main.yml b/roles/pdp/tasks/main.yml index 03675c46e..ee4661c43 100644 --- a/roles/pdp/tasks/main.yml +++ b/roles/pdp/tasks/main.yml @@ -23,6 +23,8 @@ - name: Create and start the server container community.docker.docker_container: name: pdpserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-pdp/pdp-server:{{ pdp_server_version }} pull: true restart_policy: "always" @@ -77,6 +79,13 @@ timeout: 10s retries: 3 start_period: 10s + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/html/favicon.ico + type: bind hostname: pdp env: HTTPD_CSP: "{{ httpd_csp.lenient }}" diff --git a/roles/pdp/templates/logback.xml.j2 b/roles/pdp/templates/logback.xml.j2 index b2991351c..403776189 100644 --- a/roles/pdp/templates/logback.xml.j2 +++ b/roles/pdp/templates/logback.xml.j2 @@ -7,7 +7,7 @@ - %d{ISO8601} %5p [%t] %logger{40}:%L - %m%n + %logger{40}:%L %d{ISO8601} %5p [%t] - %m%n diff --git a/roles/pdp/templates/serverapplication.properties.j2 b/roles/pdp/templates/serverapplication.properties.j2 index 00e9d7da4..e8b91bf17 100644 --- a/roles/pdp/templates/serverapplication.properties.j2 +++ b/roles/pdp/templates/serverapplication.properties.j2 @@ -27,7 +27,7 @@ spring.flyway.enabled={{ pdp_spring_flyway_enabled }} spring.mvc.dispatch-options-request=true spring.flyway.validate-on-migrate=false spring.flyway.table=schema_version -spring.mail.host={{ smtp_host }} +spring.mail.host={{ smtp_server }} spring.mail.port=25 email.base_url=https://pdp.{{ base_domain }}/conflicts diff --git a/roles/profile/defaults/main.yml b/roles/profile/defaults/main.yml index 208687a05..ad0c115d0 100644 --- a/roles/profile/defaults/main.yml +++ b/roles/profile/defaults/main.yml @@ -1,42 +1,21 @@ # Default variables used to configure Profile # These can be overwritten via group or extra vars -# Version of Profile that is installable by this role -# E.g. profile_version: x.y.z -profile_version: '' - -# Profile installer specific variables -profile_version_dir: "{{ profile_version | replace('/', '-') }}" -profile_branch_dir: "{{ openconext_builds_dir }}/OpenConext-profile-{{ profile_branch | replace('/', '-') }}" -profile_release_dir: "{{ openconext_releases_dir }}/OpenConext-profile-{{ profile_version_dir }}" -profile_build_path: "{{ openconext_builds_dir }}/OpenConext-profile-{{ profile_version_dir }}.tar.gz" -profile_download_url: "https://github.com/OpenConext/OpenConext-profile/releases/download/{{ profile_version }}/OpenConext-profile-{{ profile_version_dir }}.tar.gz" -profile_current_release_symlink: "{{ openconext_releases_dir }}/OpenConext-profile" - -# Domain under which profile can be found -profile_domain: profile.{{ base_domain }} - -# Cache and log paths -profile_symfony_cache_path: "/tmp/profile/symfony-cache/" -profile_symfony_log_path: "/var/log/profile" - # Secret used by application for adding entropy to security related operations profile_secret: secret - +engine_api_verify_ssl: true +profile_vhost_name: "profile.{{ base_domain }}" # Language code for user locale to be set by default # E.g. profile_default_locale: en profile_default_locale: en -# IP-address and domain of Engine API to enable Profile to send API calls -engine_api_verify_ssl: true - # Paths of public and private key used for sending SAML AuthnRequests -profile_saml_sp_publickey: ../vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_publickey.cer -profile_saml_sp_privatekey: ../vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_privatekey.pem +profile_saml_sp_publickey: /var/www/html/vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_publickey.cer +profile_saml_sp_privatekey: /var/www/html/vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_privatekey.pem # Paths of public and private key used for signing metadata -profile_saml_metadata_publickey: ../vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_publickey.cer -profile_saml_metadata_privatekey: ../vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_privatekey.pem +profile_saml_metadata_publickey: /var/www/html/vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_publickey.cer +profile_saml_metadata_privatekey: /var/www/html/vendor/surfnet/stepup-saml-bundle/src/Resources/keys/development_privatekey.pem # Domain under which EngineBlock can be found engine_domain: engine.{{ base_domain }} @@ -46,10 +25,8 @@ engine_profile_idp_entityid: https://{{ engine_domain }}/authentication/idp/meta # URL for remote identity provider's single sign on engine_profile_idp_sso_url: https://{{ engine_domain }}/authentication/idp/single-sign-on - -profile_fpm_user: profile -profile_fpm_port: 802 - +# Certificate containting the public SAML signing key of the reomote IDP +engine_profile_idp_certificate: "/var/www/html/config/openconext/certs/{{ profile_eb_saml_public_key }}" profile_info_request_email: "{{ support_email }}" profile_lifecycle_enabled: false @@ -63,4 +40,3 @@ profile_manage_provision_samlsp_metadata_url: "https://profile.{{ base_domain }} profile_manage_provision_samlsp_sp_cert: "" profile_manage_provision_samlsp_trusted_proxy: false profile_manage_provision_samlsp_sign: false - diff --git a/roles/profile/handlers/main.yml b/roles/profile/handlers/main.yml index 8a2235003..0e6bf345f 100644 --- a/roles/profile/handlers/main.yml +++ b/roles/profile/handlers/main.yml @@ -1,5 +1,6 @@ --- -- name: restart php72-fpm - service: - name: php72-php-fpm - state: restarted +- name: restart profile + community.docker.docker_container: + name: profile + state: started + restart: true diff --git a/roles/profile/tasks/install-branch.yml b/roles/profile/tasks/install-branch.yml deleted file mode 100644 index ab28a4c84..000000000 --- a/roles/profile/tasks/install-branch.yml +++ /dev/null @@ -1,39 +0,0 @@ ---- -- name: Check if target dir exists - stat: - path: "{{ profile_release_dir }}" - register: profile_dir - -- name: Checkout profile branch - git: - repo: https://github.com/OpenConext/OpenConext-profile.git - dest: "{{ profile_branch_dir }}" - version: "{{ profile_branch }}" - force: yes - register: profile_gitclone - -- name: Make release - command: "./makeRelease.sh {{ profile_branch }}" - environment: - HOME: "{{ openconext_builds_dir }}" - args: - chdir: "{{ profile_branch_dir }}" - when: - - profile_gitclone.changed or not profile_dir.stat.exists - -- name: Unpack current version - unarchive: - src: "{{ openconext_builds_dir }}/Releases/OpenConext-profile-{{ profile_branch | replace('/', '_') }}.tar.gz" - dest: "{{ openconext_releases_dir }}" - copy: no - when: - - profile_gitclone.changed or not profile_dir.stat.exists - -- name: Activate new Profile branch - file: - src: "{{ openconext_releases_dir }}/OpenConext-profile-{{ profile_branch | replace('/', '_') }}" - dest: "{{ profile_current_release_symlink }}" - state: link - notify: - - "restart httpd" - - "restart php72-fpm" diff --git a/roles/profile/tasks/install-release.yml b/roles/profile/tasks/install-release.yml deleted file mode 100644 index 9aa5a7f5a..000000000 --- a/roles/profile/tasks/install-release.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: Check if target dir exists - stat: - path: "{{ profile_current_release_symlink }}" - follow: no - register: profile_dir - -- name: Download current version - get_url: - url: "{{ profile_download_url }}" - dest: "{{ profile_build_path }}" - register: profile_download - -- name: Unpack current version - unarchive: - src: "{{ profile_build_path }}" - dest: "{{ openconext_releases_dir }}" - copy: no - when: - - profile_download.changed or profile_dir.stat.lnk_source != profile_release_dir - -- name: Activate new Profile release - file: - src: "{{ profile_release_dir }}" - dest: "{{ profile_current_release_symlink }}" - state: link - notify: - - "restart httpd" - - "restart php72-fpm" - when: - - profile_download.changed or profile_dir.stat.lnk_source != profile_release_dir diff --git a/roles/profile/tasks/main.yml b/roles/profile/tasks/main.yml index 5401b873b..872d653fa 100644 --- a/roles/profile/tasks/main.yml +++ b/roles/profile/tasks/main.yml @@ -1,170 +1,117 @@ --- -- name: Add group {{ profile_fpm_user }} - group: - name: "{{ profile_fpm_user }}" +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" state: present + register: profile_guid -- name: Add user {{ profile_fpm_user }} - user: - name: "{{ profile_fpm_user }}" - group: "{{ profile_fpm_user }}" - createhome: no +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: false state: present + register: profile_uid -- name: Create directory for vhosts to store PHP sessions - file: - path: "{{ php_session_dir}}/profile" +- name: Create some dirs + ansible.builtin.file: state: directory - owner: "{{ profile_fpm_user }}" + dest: "{{ item }}" + owner: root group: root - mode: 0770 - -- name: Include install-release.yml - include_tasks: install-release.yml - when: profile_branch is not defined or profile_branch == '' - -- name: Include install-branch.yml - include_tasks: install-branch.yml - when: profile_branch is defined and profile_branch != '' - -- name: Create the cache dir for Symfony - file: - path: "{{ profile_symfony_cache_path }}" - state: directory - owner: "{{ profile_fpm_user }}" - group: "{{ profile_fpm_user }}" - recurse: yes - -- name: Create the log dir for Symfony - file: - path: "{{ profile_symfony_log_path }}" - state: directory - owner: "{{ profile_fpm_user }}" - group: '{{ profile_fpm_user }}' - recurse: yes - -- name: Place parameters.yaml - template: - src: "{{ item }}.j2" - dest: "{{ profile_current_release_symlink }}/config/legacy/{{ item }}" - mode: 0644 + mode: "0755" with_items: - - parameters.yaml + - "{{ current_release_config_dir_name }}" + - "{{ current_release_config_dir_name }}/certs" + - "{{ current_release_config_dir_name }}/translationoverrides" + +- name: Put parameters YAML config + ansible.builtin.template: + src: "{{ item }}.yml.j2" + dest: "{{ current_release_config_dir_name }}/{{ item }}.yaml" + mode: "0640" + group: "{{ appname }}" + with_items: + - parameters + - global_view_parameters notify: - - "restart php72-fpm" - -- name: Instantiate global_view_parameters.yml.dist - command: mv global_view_parameters.yaml.dist global_view_parameters.yaml - args: - chdir: "{{ profile_current_release_symlink }}/config/legacy/" - creates: "{{ profile_current_release_symlink }}/config/legacy/global_view_parameters.yaml" + - restart {{ appname }} + +- name: Install the engineblock certificate + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/certs/{{ profile_eb_saml_public_key }}" + dest: "{{ current_release_config_dir_name }}/certs/{{ profile_eb_saml_public_key }}" + mode: "0644" + owner: root + group: root - name: Check presence of language specific overrides - local_action: stat path="{{ inventory_dir }}/files/profile/overrides/" + ansible.builtin.stat: + path: "{{ inventory_dir }}/files/profile/overrides/" + delegate_to: localhost register: overrides_present become: false -# Can be removed after 2022-01-01 -- name: Check for wrongly created overrides file (not dir) - stat: - path: "{{ profile_current_release_symlink }}/translations/overrides" - register: overridesisfile - -# Can be removed after 2022-01-01 -- name: Clean up wrongly created overrides file (not dir) - file: - path: "{{ profile_current_release_symlink }}/translations/overrides" - state: absent - when: overrides_present.stat.exists and overridesisfile.stat.exists and overridesisfile.stat.isdir == False - - name: Copy language specific overrides - template: + ansible.builtin.template: src: "{{ item }}" - dest: "{{ profile_current_release_symlink }}/translations/overrides/" + dest: "{{ current_release_config_dir_name }}/translationoverrides/" when: overrides_present.stat.exists with_fileglob: - "{{ inventory_dir }}/files/profile/overrides/*" notify: - - "restart php72-fpm" + - "restart {{ appname }}" - name: Check if we have a custom favicon - local_action: stat path="{{ inventory_dir }}/files/favicon.ico" + ansible.builtin.stat: + path: "{{ inventory_dir }}/files/favicon.ico" + delegate_to: localhost register: customfavicon become: false - name: Install environment specific favicon - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/favicon.ico" - dest: "{{ profile_current_release_symlink }}/public/" + dest: "{{ current_release_config_dir_name }}/images/" + owner: root + group: root + mode: "0644" when: customfavicon.stat.exists -- name: Create the symfony cache - command: php72 bin/console cache:clear --env={{ profile_apache_symfony_environment }} --no-debug - args: - chdir: "{{ profile_current_release_symlink }}/" - when: - - not develop - changed_when: false - -- name: Make sure cache dir has correct permissions - file: - path: "{{ profile_current_release_symlink }}/var/cache" - owner: "{{ profile_fpm_user }}" - group: "{{ profile_fpm_user }}" - recurse: yes - changed_when: false - -- name: Make sure log dir has correct permissions - file: - path: "{{ profile_current_release_symlink }}/var/log" - owner: "{{ profile_fpm_user }}" - group: "{{ profile_fpm_user }}" - recurse: yes - changed_when: false - -- name: Install Apache vhost - template: - src: "{{ item }}.j2" - dest: "/etc/httpd/conf.d/{{ item }}" - with_items: - - profile.conf - notify: - - "restart httpd" - -- name: clean up old php-fpm 5.6 config - file: - path: "/etc/php-fpm.d/profile-pool.conf" - state: absent - -- name: php-fpm 72 config - template: - src: "{{ item }}.j2" - dest: "/etc/opt/remi/php72/php-fpm.d/{{ item }}" - with_items: - - profile-pool-72.conf - notify: - - "restart php72-fpm" - -- name: clean up profile <3.0 config - file: - path: "/etc/openconext/profile.yml" - state: absent +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/openconext-profile/profile:{{ profile_version }} + etc_hosts: + host.docker.internal: host-gateway + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.profile.rule: "Host(`{{ profile_vhost_name }}`)" + traefik.http.routers.profile.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ profile_uid.uid }}" + APACHE_GUID: "#{{ profile_guid.gid }}" + APP_ENV: prod + HTTPD_CSP: "{{ httpd_csp.strict_with_static_img }}" + mounts: + - source: /opt/openconext/profile + target: /var/www/html/config/openconext + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/html/public/favicon.ico + type: bind + - source: /etc/localtime + target: /etc/localtime + type: bind + - name: Include the role manage_provision_entities to provision profile to Manage - include_role: + ansible.builtin.include_role: name: manage_provision_entities - vars: + vars: entity_type: saml20_sp - -# Remove all dirs, but keep the current version and from the rest the most recent one. -- name: Clean up old releases - shell: ls -td {{ openconext_releases_dir }}/OpenConext-profile-* | grep -v $(readlink {{ profile_current_release_symlink }}) | tail -n +2 | xargs --no-run-if-empty rm -rv - register: clean_releases - changed_when: '"removed" in clean_releases.stdout' - -# Remove all tarballs, but keep the current version and from the rest the most recent one. -- name: Clean up old builds - shell: ls -td {{ openconext_builds_dir }}/OpenConext-profile-* {{ openconext_builds_dir }}/Releases/ | grep -v {{ profile_build_path }} | tail -n +2 | xargs --no-run-if-empty rm -rv - register: clean_builds - changed_when: '"removed" in clean_builds.stdout' diff --git a/roles/profile/templates/global_view_parameters.yml.j2 b/roles/profile/templates/global_view_parameters.yml.j2 new file mode 100644 index 000000000..f39839b42 --- /dev/null +++ b/roles/profile/templates/global_view_parameters.yml.j2 @@ -0,0 +1,26 @@ +# This file is auto-generated during the composer install +parameters: + help_url: + en: 'https://support.surfconext.nl/help-profile-en' + nl: 'https://support.surfconext.nl/help-profile-nl' + pt: 'https://support.surfconext.nl/help-profile-en' + privacy_url: + en: 'https://support.surfconext.nl/privacy-en' + nl: 'https://support.surfconext.nl/privacy-nl' + pt: 'https://support.surfconext.nl/privacy-en' + terms_of_service_url: + en: 'https://support.surfconext.nl/terms-en' + nl: 'https://support.surfconext.nl/terms-nl' + pt: 'https://support.surfconext.nl/terms-en' + platform_url: + en: 'https://www.surfconext.nl/en' + nl: 'https://www.surfconext.nl' + pt: 'https://www.surfconext.nl/en' + profile_explanation_image_path: + en: build/images/profile_home_en.png + nl: build/images/profile_home_nl.png + pt: build/images/profile_home_pt.png + attribute_information_url: + en: 'https://support.surfconext.nl/attributes-en' + nl: 'https://support.surfconext.nl/attributes-nl' + pt: 'https://support.surfconext.nl/attributes-en' diff --git a/roles/profile/templates/parameters.yaml.j2 b/roles/profile/templates/parameters.yml.j2 similarity index 92% rename from roles/profile/templates/parameters.yaml.j2 rename to roles/profile/templates/parameters.yml.j2 index 8459f9e2c..35baf6e56 100644 --- a/roles/profile/templates/parameters.yaml.j2 +++ b/roles/profile/templates/parameters.yml.j2 @@ -1,5 +1,8 @@ parameters: - secret: '{{ profile_secret }}' + app_env: prod + app_debug: false + app_secret: {{ profile_secret }} + locales: [en, nl] default_locale: {{ profile_default_locale }} open_conext_locale_cookie_key: lang @@ -38,7 +41,7 @@ parameters: attribute_aggregation_orcid_logo_path: 'build/images/orcid.png' attribute_aggregation_orcid_connect_url: 'https://link.{{ base_domain }}/orcid?redirectUrl=https://profile.{{ base_domain }}/my-connections' - mailer_url: 'smtp://localhost:25' + mailer_url: 'smtp://{{ smtp_server }}:25' attribute_support_email_from: '{{ noreply_email }}' attribute_support_email_to: '{{ engine_idp_debugging_email_address }}' @@ -55,3 +58,6 @@ parameters: session_handler: ~ # Database settings when using a db to store sessions. Unused in the default setup dsn: mysql://profilerw:secret@localhost/profile?serverVersion=5.7 + + # which context class ref is used for the saml bundle + authentication_context_class_ref: ~ diff --git a/roles/profile/templates/profile-pool-72.conf.j2 b/roles/profile/templates/profile-pool-72.conf.j2 deleted file mode 100644 index f8d7690a9..000000000 --- a/roles/profile/templates/profile-pool-72.conf.j2 +++ /dev/null @@ -1,225 +0,0 @@ -; Create a new pool named profile. -[profile] - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses on a -; specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. - -; Use unix socket -listen = /var/run/php-fpm/profile-pool-72.sock -; Set listen(2) backlog. A value of '-1' means unlimited. -; Default Value: -1 -;listen.backlog = -1 - -; List of ipv4 addresses of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -listen.allowed_clients = 127.0.0.1 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0666 -listen.owner = apache -listen.group = apache -listen.mode = 0640 - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = {{ profile_fpm_user }} -group = {{ profile_fpm_user }} - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives: -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; Note: This value is mandatory. -pm = ondemand - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes to be created when pm is set to 'dynamic'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. -; Note: Used when pm is set to either 'static' or 'dynamic' -; Note: This value is mandatory. -pm.max_children = 20 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -;pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -;pm.max_spare_servers = 5 - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -pm.max_requests = 300 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. By default, the status page shows the following -; information: -; accepted conn - the number of request accepted by the pool; -; pool - the name of the pool; -; process manager - static or dynamic; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes. -; The values of 'idle processes', 'active processes' and 'total processes' are -; updated each second. The value of 'accepted conn' is updated in real time. -; Example output: -; accepted conn: 12073 -; pool: www -; process manager: static -; idle processes: 35 -; active processes: 65 -; total processes: 100 -; By default the status page output is formatted as text/plain. Passing either -; 'html' or 'json' as a query string will return the corresponding output -; syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_terminate_timeout = 0 - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -slowlog = /var/log/php-fpm/www-slow.log - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. This value must be an absolute path. -; Default Value: current directory or / when chroot -;chdir = /var/www - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Default Value: no -;catch_workers_output = yes - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; exectute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -php_admin_value[error_log] = /var/log/php-fpm/profile-error.log -php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 128M - -; Set session path to a directory owned by process user -php_value[session.save_handler] = files -php_value[session.save_path] = {{ php_session_dir }}/profile -php_value[disable_functions] = {{ php_disabled_functions }} diff --git a/roles/profile/templates/profile.conf.j2 b/roles/profile/templates/profile.conf.j2 deleted file mode 100644 index dece65bc8..000000000 --- a/roles/profile/templates/profile.conf.j2 +++ /dev/null @@ -1,53 +0,0 @@ -{% if apache_app_listen_address.profile is defined %} -Listen {{ apache_app_listen_address.profile }}:{{ loadbalancing.profile.port }} - -{% else %} - -{% endif %} - ServerName {{ profile_domain }} - ServerAdmin {{ admin_email }} - - DocumentRoot {{ profile_current_release_symlink }}/public - - SetEnv APP_ENV {{ profile_apache_symfony_environment }} - SetEnv HTTPS on - - - Require all granted - - Options -MultiViews - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php [QSA,L] - - - Header always set Referrer-Policy "strict-origin-when-cross-origin" - Header always set Content-Security-Policy "{{ httpd_csp.strict_with_static_img }}" - - # Proxy the requests to FPM - ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php-fpm/profile-pool-72.sock|fcgi://localhost/{{ profile_current_release_symlink }}/public/$1 - - ErrorLog "|/usr/bin/logger -S 32k -p local3.err -t 'Apache-PROFILE'" - CustomLog "|/usr/bin/logger -S 32k -p local3.info -t 'Apache-PROFILE'" combined - {% if haproxy_backend_tls %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/backend.{{ base_domain }}.pem - SSLCertificateKeyFile {{ tls.cert_private_path }}/backend.{{ base_domain }}.key - Include ssl_backend.conf - {% endif %} - - {% if apache_app_listen_address.all is defined %} - SSLEngine on - SSLCertificateFile {{ tls.cert_path }}/{{ tls_star_cert }} - SSLCertificateKeyFile {{ tls.cert_private_path }}/{{ tls_star_cert_key }} - SSLCertificateChainFile {{ tls.cert_path_ca }}/{{ tls_ca }} - Include ssl_backend.conf - {% endif %} - - ExpiresActive on - ExpiresByType font/* "access plus 1 year" - ExpiresByType image/* "access plus 6 months" - ExpiresByType text/css "access plus 1 year" - ExpiresByType text/js "access plus 1 year" - - diff --git a/roles/profile/vars/main.yml b/roles/profile/vars/main.yml index fcd768a4f..96e501593 100644 --- a/roles/profile/vars/main.yml +++ b/roles/profile/vars/main.yml @@ -1,8 +1,11 @@ +appname: "profile" +current_release_config_dir_name: "/opt/openconext/{{ appname }}" + manage_provision_samlsp_client_id: "{{ profile_manage_provision_samlsp_client_id }}" -manage_provision_samlsp_name_en: "{{ profile_manage_provision_samlsp_name_en }}" -manage_provision_samlsp_description_en: "{{ profile_manage_provision_samlsp_description_en }}" -manage_provision_samlsp_acs_location: "{{ profile_manage_provision_samlsp_acs_location }}" -manage_provision_samlsp_metadata_url: "{{ profile_manage_provision_samlsp_metadata_url }}" +manage_provision_samlsp_name_en: "{{ profile_manage_provision_samlsp_name_en }}" +manage_provision_samlsp_description_en: "{{ profile_manage_provision_samlsp_description_en }}" +manage_provision_samlsp_acs_location: "{{ profile_manage_provision_samlsp_acs_location }}" +manage_provision_samlsp_metadata_url: "{{ profile_manage_provision_samlsp_metadata_url }}" manage_provision_samlsp_sp_cert: "{{ profile_manage_provision_samlsp_sp_cert }}" manage_provision_samlsp_trusted_proxy: "{{ profile_manage_provision_samlsp_trusted_proxy }}" manage_provision_samlsp_sign: "{{ profile_manage_provision_samlsp_sign }}" diff --git a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 b/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 index 931329a9a..4196c526e 100644 --- a/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 +++ b/roles/rsyslog/templates/rsyslog_onlyforward.conf.j2 @@ -2,11 +2,6 @@ module(load="imuxsock") module(load="imklog") # provides kernel logging support module(load="immark" interval="600" ) # provides --MARK-- message capability -module(load="imjournal" - PersistStateInterval="100" - StateFile="/var/spool/rsyslog/imjournal.state" - ratelimit.interval="30" - ratelimit.burst="20000" ) # Reads journald logs $PreserveFQDN on diff --git a/roles/rsyslog/templates/sc_ruleset.conf.j2 b/roles/rsyslog/templates/sc_ruleset.conf.j2 index 7fd172960..d3fc5d0ad 100644 --- a/roles/rsyslog/templates/sc_ruleset.conf.j2 +++ b/roles/rsyslog/templates/sc_ruleset.conf.j2 @@ -4,23 +4,22 @@ $RuleSet {{ item.name }} :programname, isequal, "Apache-EB" { action(type="omfile" DynaFile="apache-eb-{{ item.name }}") stop } :programname, isequal, "EBAUTH" { action(type="omfile" DynaFile="ebauth-{{ item.name }}") stop } :programname, isequal, "haproxy" { action(type="omfile" DynaFile="haproxy-{{ item.name }}") stop } -:programname, isequal, "aa" { action(type="omfile" DynaFile="aa-{{ item.name }}") stop } -:programname, isequal, "Apache-AA" { action(type="omfile" DynaFile="apache-aa-{{ item.name }}") stop } -:programname, isequal, "Apache-AAlink" { action(type="omfile" DynaFile="apache-aalink-{{ item.name }}") stop } +:programname, isequal, "aaserver" { action(type="omfile" DynaFile="aa-{{ item.name }}") stop } +:programname, isequal, "aagui" { action(type="omfile" DynaFile="apache-aa-{{ item.name }}") stop } +:programname, isequal, "aalink" { action(type="omfile" DynaFile="apache-aa-{{ item.name }}") stop } :programname, isequal, "dashboardgui" { action(type="omfile" DynaFile="apache-dashboard-{{ item.name }}") stop } :programname, isequal, "dashboardserver" { action(type="omfile" DynaFile="dashboard-{{ item.name }}") stop } :programname, isequal, "Apache-EBAPI" { action(type="omfile" DynaFile="apache-eb-api-{{ item.name }}") stop } :programname, isequal, "manage" { action(type="omfile" DynaFile="manage-{{ item.name }}") stop } :programname, isequal, "Apache-Manage" { action(type="omfile" DynaFile="apache-manage-{{ item.name }}") stop } -:programname, isequal, "PDPMAIN" { action(type="omfile" DynaFile="pdp-{{ item.name }}") stop } :programname, isequal, "PDPANALYTICS" { action(type="omfile" DynaFile="pdpanalytics-{{ item.name }}") stop } -:programname, isequal, "Apache-PDP" { action(type="omfile" DynaFile="apache-pdp-{{ item.name }}") stop } -:programname, isequal, "openconext-profile" { action(type="omfile" DynaFile="profile-{{ item.name }}") stop } -:programname, isequal, "Apache-PROFILE" { action(type="omfile" DynaFile="apache-profile-{{ item.name }}") stop } -:programname, isequal, "teams" { action(type="omfile" DynaFile="teams-{{ item.name }}") stop } -:programname, isequal, "Apache-teams" { action(type="omfile" DynaFile="apache-teams-{{ item.name }}") stop } -:programname, isequal, "VOOTMAIN" { action(type="omfile" DynaFile="voot-{{ item.name }}") stop } -:programname, isequal, "Apache-VOOT" { action(type="omfile" DynaFile="apache-voot-{{ item.name }}") stop } +:programname, isequal, "pdpserver" { action(type="omfile" DynaFile="pdp-{{ item.name }}") stop } +:programname, isequal, "pdpgui" { action(type="omfile" DynaFile="apache-pdp-{{ item.name }}") stop } +if $programname == "profile" and $msg startswith " {" then { action(type="omfile" DynaFile="profile-{{ item.name }}") stop } +:programname, isequal, "profile" { action(type="omfile" DynaFile="apache-profile-{{ item.name }}") stop } +:programname, isequal, "teamsserver" { action(type="omfile" DynaFile="teams-{{ item.name }}") stop } +:programname, isequal, "teamsgui" { action(type="omfile" DynaFile="apache-teams-{{ item.name }}") stop } +:programname, isequal, "vootserver" { action(type="omfile" DynaFile="voot-{{ item.name }}") stop } :programname, isequal, "mariadbd" { action(type="omfile" DynaFile="galera-{{ item.name }}") stop } :programname, isequal, "garb-systemd" { action(type="omfile" DynaFile="haproxy-{{ item.name }}") stop } :programname, isequal, "Keepalived_vrrp" { action(type="omfile" DynaFile="keepalived-{{ item.name }}") stop } @@ -31,21 +30,23 @@ $RuleSet {{ item.name }} :programname, isequal, "Apache-oidcng" { action(type="omfile" DynaFile="apache-oidcng-{{ item.name }}") stop } :programname, isequal, "oidcplaygroundserver" { action(type="omfile" DynaFile="oidc-playground-{{ item.name }}") stop } :programname, isequal, "oidcplaygroundgui" { action(type="omfile" DynaFile="apache-oidcplayground-{{item.name }}") stop } -:programname, isequal, "myconext" { action(type="omfile" DynaFile="myconext-{{ item.name }}") stop } +:programname, isequal, "myconextserver" { action(type="omfile" DynaFile="myconext-{{ item.name }}") stop } :programname, isequal, "myconextjson" { action(type="omfile" DynaFile="myconextjson-{{ item.name }}") stop } -:programname, isequal, "Apache-myconext" { action(type="omfile" DynaFile="apache-myconext-{{item.name }}") stop } -:programname, isequal, "Apache-account" { action(type="omfile" DynaFile="apache-account-{{item.name }}") stop } -:programname, isequal, "Apache-eduid" { action(type="omfile" DynaFile="apache-eduid-{{item.name }}") stop } -:programname, isequal, "spdashboard_php-fpm" { action(type="omfile" DynaFile="spdashboard-{{ item.name }}") stop } -:programname, isequal, "spdashboard_web" { action(type="omfile" DynaFile="apache-spdashboard-{{ item.name }}") stop } +:programname, isequal, "myconextgui" { action(type="omfile" DynaFile="apache-myconext-{{item.name }}") stop } +:programname, isequal, "accountgui" { action(type="omfile" DynaFile="apache-account-{{item.name }}") stop } :programname, startswith, "inviteclient" { action(type="omfile" DynaFile="inviteclient-{{ item.name }}") stop } :programname, startswith, "invitewelcome" { action(type="omfile" DynaFile="invitewelcome-{{ item.name }}") stop } :programname, startswith, "inviteserver" { action(type="omfile" DynaFile="inviteserver-{{ item.name }}") stop } :programname, startswith, "inviteprovisioningmock" { action(type="omfile" DynaFile="inviteprovisioningmock-{{ item.name }}") stop } :programname, startswith, "loadbalancer" { action(type="omfile" DynaFile="loadbalancer-{{ item.name }}") stop } +if $programname == "gateway" and $msg startswith ' {"message":"Second Factor Authenticated"' then { action(type="omfile" DynaFile="stepup-authentication-{{ item.name }}") stop } +if $programname == "gateway" and $msg startswith ' {"message":"Intrinsic Loa Requested"' then { action(type="omfile" DynaFile="stepup-authentication-{{ item.name }}") stop } + {% for stepupapp in stepupapps %} :programname, isequal, "stepup-{{ stepupapp }}" { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } +if $programname == "{{ stepupapp }}" and $msg startswith " {{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } +:programname, isequal, "{{ stepupapp }}" { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } :programname, isequal, "Apache-{{ stepupapp }}" { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } if $programname == "{{ stepupapp }}" and $msg startswith " {{ stepupapp }}" then { action(type="omfile" DynaFile="apache-{{ stepupapp }}-{{item.name }}") stop } :programname, isequal, "{{ stepupapp }}" { action(type="omfile" DynaFile="stepup-{{ stepupapp }}-{{item.name }}") stop } diff --git a/roles/stats/defaults/main.yml b/roles/stats/defaults/main.yml index 9bdfb26b5..9822b2a2c 100644 --- a/roles/stats/defaults/main.yml +++ b/roles/stats/defaults/main.yml @@ -5,3 +5,4 @@ stats_manage_api_user: stats stats_base_domain: stats.{{ base_domain }} stats_oidc_metadata_url: "https://connect.{{ base_domain }}/.well-known/openid-configuration" stats_oidc_client_id: "stats.{{ base_domain }}" +stats_domain: "stats.{{ base_domain }}" diff --git a/roles/stats/tasks/main.yml b/roles/stats/tasks/main.yml index 816654491..9a5d5d965 100644 --- a/roles/stats/tasks/main.yml +++ b/roles/stats/tasks/main.yml @@ -54,7 +54,7 @@ restart_policy: "always" state: started labels: - traefik.http.routers.statsgui.rule: "Host(`stats.{{ base_domain }}`)" + traefik.http.routers.statsgui.rule: "Host(`{{ stats_domain }}`)" traefik.http.routers.statsgui.tls: "true" traefik.enable: "true" networks: diff --git a/roles/stepupapp/tasks/copyspcerts.yml b/roles/stepupapp/tasks/copyspcerts.yml index 7f944e1f3..0ca8b6322 100644 --- a/roles/stepupapp/tasks/copyspcerts.yml +++ b/roles/stepupapp/tasks/copyspcerts.yml @@ -5,11 +5,11 @@ dest: "{{ current_release_config_file_dir_name }}/sp.key" owner: "{{ appname}}" group: "{{ appname }}" - mode: 400 + mode: "0440" - name: Write SP certificate | {{ appname }} copy: src: "{{ inventory_dir }}/files/certs/stepup/{{ appname }}_saml_sp.crt" dest: "{{ current_release_config_file_dir_name }}/sp.crt" group: "{{ appname }}" - mode: 400 + mode: "0440" diff --git a/roles/stepupazuremfa/handlers/main.yml b/roles/stepupazuremfa/handlers/main.yml index 40eef830c..6e76d3748 100644 --- a/roles/stepupazuremfa/handlers/main.yml +++ b/roles/stepupazuremfa/handlers/main.yml @@ -6,3 +6,9 @@ service: name: php72-php-fpm state: reloaded + +- name: restart azuremfa + community.docker.docker_container: + name: azuremfa + state: started + restart: true diff --git a/roles/stepupazuremfa/tasks/main.yml b/roles/stepupazuremfa/tasks/main.yml index d76f1035f..a7935e775 100644 --- a/roles/stepupazuremfa/tasks/main.yml +++ b/roles/stepupazuremfa/tasks/main.yml @@ -1,62 +1,78 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm +- name: Include docker vars + ansible.builtin.include_vars: docker.yml -- name: Install the symfony app - include_role: - name: stepupapp +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: azuremfa_guid + +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: azuremfa_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" - name: Install images - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyimages - name: Install the GSSP certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copygsspidpcerts - name: Place parameters.yml - template: + ansible.builtin.template: src: parameters.yaml.j2 dest: "{{ current_release_config_dir_name }}/parameters.yaml" - mode: 0640 + mode: "0640" owner: root group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} + notify: restart azuremfa - name: Put institutions.yaml from environment - template: + ansible.builtin.template: src: "{{ inventory_dir }}/files/stepup-azuremfa/institutions.yaml.j2" dest: "{{ current_release_config_dir_name }}/institutions.yaml" - mode: 0640 - group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Place .env file - template: - src: env.j2 - dest: "{{ current_release_appdir }}/.env.local" - mode: 0640 + mode: "0640" owner: root group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}/" - dest: "{{ current_release_symlink }}" - state: link + notify: restart azuremfa -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-azuremfa/stepup-azuremfa:{{ azuremfa_version }} + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.azuremfa.rule: "Host(`azuremfa.{{ base_domain }}`)" + traefik.http.routers.azuremfa.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ azuremfa_uid.uid }}" + APACHE_GUID: "#{{ azuremfa_guid.gid }}" + mounts: + - source: /opt/openconext/azuremfa/public/images/header-logo.png + target: /var/www/html/public/build/images/header-logo.png + type: bind + - source: /opt/openconext/azuremfa + target: /var/www/html/config/openconext + type: bind diff --git a/roles/stepupazuremfa/templates/parameters.yaml.j2 b/roles/stepupazuremfa/templates/parameters.yaml.j2 index ff19a47eb..61a49ef5e 100644 --- a/roles/stepupazuremfa/templates/parameters.yaml.j2 +++ b/roles/stepupazuremfa/templates/parameters.yaml.j2 @@ -1,16 +1,21 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ azuremfa_secret }} +{% endif %} # All locales supported by the application locales: [{{ enabled_locales | join(",") }}] # SAML configuration - saml_idp_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_idp_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_idp_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_idp_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' # NOTE: same key used for metadata and response/assertion signing - saml_metadata_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_metadata_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_metadata_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_metadata_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' saml_remote_sp_entity_id: 'https://{{ gateway_vhost_name }}/gssp/azuremfa/metadata' - saml_remote_sp_certificate: '{{ current_release_config_file_dir_name }}/gateway.crt' + saml_remote_sp_certificate: '{{ current_release_config_file_dir_name_in_config }}/gateway.crt' saml_remote_sp_acs: 'https://{{ gateway_vhost_name }}/gssp/azuremfa/consume-assertion' # View parameters diff --git a/roles/stepupazuremfa/vars/docker.yml b/roles/stepupazuremfa/vars/docker.yml new file mode 100644 index 000000000..764009ac0 --- /dev/null +++ b/roles/stepupazuremfa/vars/docker.yml @@ -0,0 +1,4 @@ +current_release_appdir: /opt/openconext/azuremfa +current_release_config_file_dir_name: /opt/openconext/azuremfa +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/azuremfa diff --git a/roles/stepupazuremfa/vars/main.yml b/roles/stepupazuremfa/vars/main.yml index 9ef9ade0f..fbadef306 100644 --- a/roles/stepupazuremfa/vars/main.yml +++ b/roles/stepupazuremfa/vars/main.yml @@ -7,6 +7,7 @@ stepup_gh_appname: "Azure-MFA" current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" +#current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" current_release_config_dir_name: "{{ current_release_appdir }}/config/packages" gssp_idp_private_key: "{{ lookup('file', inventory_dir+'/files/certs/stepup/azuremfa_idp.key') }}" fpmmemory: 128M diff --git a/roles/stepupgateway/handlers/main.yml b/roles/stepupgateway/handlers/main.yml index 40eef830c..b0afaa370 100644 --- a/roles/stepupgateway/handlers/main.yml +++ b/roles/stepupgateway/handlers/main.yml @@ -6,3 +6,6 @@ service: name: php72-php-fpm state: reloaded + +- name: restart gateway + command: docker restart gateway diff --git a/roles/stepupgateway/tasks/main.yml b/roles/stepupgateway/tasks/main.yml index 52f24b95a..c4d604fec 100644 --- a/roles/stepupgateway/tasks/main.yml +++ b/roles/stepupgateway/tasks/main.yml @@ -1,26 +1,47 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm - -- name: Install the symfony app - include_role: - name: stepupapp +--- +- name: Include docker vars + ansible.builtin.include_vars: docker.yml + +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: gateway_guid + +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: gateway_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" - name: Install images - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyimages - name: Install second factor images - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copysfimages - name: Place config parameterfiles - template: + ansible.builtin.template: src: "{{ item }}.yml.j2" dest: "{{ current_release_config_dir_name }}/{{ item }}.yaml" - mode: 0640 + mode: "0640" owner: root group: "{{ appname }}" with_items: @@ -29,97 +50,86 @@ - samlstepupproviders_parameters - global_view_parameters notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Place .env file - template: - src: env.j2 - dest: "{{ current_release_appdir }}/.env.local" - mode: 0640 - owner: root - group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} + - restart {{ appname }} -# Writing all the SAML keys and certificates. Since the gateway is special no need to include it from other roles + # Writing all the SAML keys and certificates. Since the gateway is special no need to include it from other roles - name: Write GateWay SAML SP private key - copy: + ansible.builtin.copy: content: "{{ gateway_saml_sp_privatekey }}" dest: "{{ current_release_config_file_dir_name }}/sp.key" owner: "{{ appname }}" - mode: 0400 + mode: "0400" - name: Write SAML SP certificate - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/stepup/gateway_saml_sp.crt" dest: "{{ current_release_config_file_dir_name }}/sp.crt" group: "{{ appname }}" - mode: 0640 + mode: "0640" - name: Write GSSP SP private key - copy: + ansible.builtin.copy: content: "{{ gateway_gssp_sp_privatekey }}" dest: "{{ current_release_config_file_dir_name }}/sp_gssp.key" owner: "{{ appname }}" - mode: 0400 + mode: "0400" - name: Write GSSP SP certificate - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/stepup/gateway_gssp_sp.crt" dest: "{{ current_release_config_file_dir_name }}/sp_gssp.crt" group: "{{ appname }}" - mode: 0640 + mode: "0640" - name: Write SAML IdP private key - copy: + ansible.builtin.copy: content: "{{ gateway_saml_idp_privatekey }}" dest: "{{ current_release_config_file_dir_name }}/idp.key" owner: "{{ appname }}" - mode: 0400 + mode: "0400" - name: Write SAML IdP public key - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/stepup/gateway_saml_idp.crt" dest: "{{ current_release_config_file_dir_name }}/idp.crt" group: "{{ appname }}" - mode: 0640 + mode: "0640" - name: Write GSSP IdP cert - copy: + ansible.builtin.copy: src: "{{ inventory_dir }}/files/certs/stepup/gateway_gssp_idp.crt" dest: "{{ current_release_config_file_dir_name }}/idp_gssp.crt" owner: "{{ appname }}" - mode: 0600 + mode: "0600" - name: Write GSSP IdP key - copy: + ansible.builtin.copy: content: "{{ gateway_gssp_idp_privatekey }}" dest: "{{ current_release_config_file_dir_name }}/idp_gssp.key" owner: "{{ appname }}" - mode: 0600 - -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}/" - dest: "{{ current_release_symlink }}" - state: link - -- name: Remove gateway database db_migrate script from /root/ - file: - path: "/root/01-gateway-db_migrate.sh" - state: absent - -- name: Put logout.php in public - template: - src: "logout.php.j2" - dest: "{{ current_release_appdir }}/public/logout.php" - mode: "444" - -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall + mode: "0600" + +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-gateway/stepup-gateway:{{ gateway_version }} + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.gateway.rule: "Host(`{{ gateway_vhost_name }}`)" + traefik.http.routers.gateway.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ gateway_uid.uid }}" + APACHE_GUID: "#{{ gateway_guid.gid }}" + APP_ENV: prod + HTTPD_CSP: "" + mounts: + - source: /opt/openconext/gateway/public/images/header-logo.png + target: /var/www/html/public/images/header-logo.png + type: bind + - source: /opt/openconext/gateway/ + target: /var/www/html/config/openconext + type: bind diff --git a/roles/stepupgateway/templates/parameters.yml.j2 b/roles/stepupgateway/templates/parameters.yml.j2 index 021a4e9af..82de2e54a 100644 --- a/roles/stepupgateway/templates/parameters.yml.j2 +++ b/roles/stepupgateway/templates/parameters.yml.j2 @@ -1,8 +1,14 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ gateway_secret }} +{% endif %} + trusted_proxies: [ 127.0.0.1 ] database_driver: pdo_mysql - database_host: {{ database_lb_address }} + database_host: {{ dbcluster_ip }} database_port: 3306 database_gateway_name: {{ database_gateway_name }} database_gateway_user: {{ database_gateway_user }} @@ -57,21 +63,21 @@ parameters: # The private key and certificate that are used by the Gateway SP to sign SAML AuthnRequests # Filename of the PEM CERTIFICATE - saml_sp_publickey: {{ current_release_config_file_dir_name }}/sp.crt + saml_sp_publickey: {{ current_release_config_file_dir_name_in_config }}/sp.crt # Filename of the PEM RSA PRIVATE KEY - saml_sp_privatekey: {{ current_release_config_file_dir_name }}/sp.key + saml_sp_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp.key # The private key and certificate that are used by the Gateway IdP to sign SAML Responses/Assertions # Filename of the PEM CERTIFICATE - saml_idp_publickey: {{ current_release_config_file_dir_name }}/idp.crt + saml_idp_publickey: {{ current_release_config_file_dir_name_in_config }}/idp.crt # Filename of the PEM RSA PRIVATE KEY - saml_idp_privatekey: {{ current_release_config_file_dir_name }}/idp.key + saml_idp_privatekey: {{ current_release_config_file_dir_name_in_config }}/idp.key # The certificate and private key that are used by the Gateway to sign the metadata that it publishes # Filename of the PEM CERTIFICATE - saml_metadata_publickey: {{ current_release_config_file_dir_name }}/idp.crt + saml_metadata_publickey: {{ current_release_config_file_dir_name_in_config }}/idp.crt # Filename of the PEM RSA PRIVATE KEY - saml_metadata_privatekey: {{ current_release_config_file_dir_name }}/idp.key + saml_metadata_privatekey: {{ current_release_config_file_dir_name_in_config }}/idp.key # The remote IdP (i.e. not the local IdP that is part of the Gateway) is the IdP that provides the first # factor authentication of users to the Gateway. @@ -104,8 +110,6 @@ parameters: second_factor_only: {{ gateway_second_factor_only | default(false) }} - asset_version: {{ appversion_sha }} - enabled_second_factors: [ {{ stepup_enabled_factors }} ] enabled_generic_second_factors: diff --git a/roles/stepupgateway/templates/samlstepupproviders_parameters.yml.j2 b/roles/stepupgateway/templates/samlstepupproviders_parameters.yml.j2 index 86c5e267c..10ef19e7d 100644 --- a/roles/stepupgateway/templates/samlstepupproviders_parameters.yml.j2 +++ b/roles/stepupgateway/templates/samlstepupproviders_parameters.yml.j2 @@ -15,16 +15,16 @@ parameters: # Metadata URL: https:///gssp/{{ key }}/metadata # GSSP SP Proxy for authenticating with the real (i.e. external) GSSP IdP - gssp_{{ key }}_sp_publickey: {{ current_release_config_file_dir_name }}/sp_gssp.crt - gssp_{{ key }}_sp_privatekey: {{ current_release_config_file_dir_name }}/sp_gssp.key + gssp_{{ key }}_sp_publickey: {{ current_release_config_file_dir_name_in_config }}/sp_gssp.crt + gssp_{{ key }}_sp_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp_gssp.key # Certificate and private key of GSSP IdP Proxy for use by RA and SS - gssp_{{ key }}_idp_publickey: {{ current_release_config_file_dir_name }}/idp_gssp.crt - gssp_{{ key }}_idp_privatekey: {{ current_release_config_file_dir_name }}/idp_gssp.key + gssp_{{ key }}_idp_publickey: {{ current_release_config_file_dir_name_in_config }}/idp_gssp.crt + gssp_{{ key }}_idp_privatekey: {{ current_release_config_file_dir_name_in_config }}/idp_gssp.key # Metadata signing cert and key for tiqr SP/IdP proxy - gssp_{{ key }}_metadata_publickey: {{ current_release_config_file_dir_name }}/idp_gssp.crt - gssp_{{ key }}_metadata_privatekey: {{ current_release_config_file_dir_name }}/idp_gssp.key + gssp_{{ key }}_metadata_publickey: {{ current_release_config_file_dir_name_in_config }}/idp_gssp.crt + gssp_{{ key }}_metadata_privatekey: {{ current_release_config_file_dir_name_in_config }}/idp_gssp.key # Real (i.e. external) GSSP IdP gssp_{{ key }}_remote_entity_id: '{{ hostvars[inventory_hostname]['gateway_' + key + '_remote_entity_id'] }}' diff --git a/roles/stepupgateway/vars/docker.yml b/roles/stepupgateway/vars/docker.yml new file mode 100644 index 000000000..3c9ed88fd --- /dev/null +++ b/roles/stepupgateway/vars/docker.yml @@ -0,0 +1,5 @@ +current_release_appdir: /opt/openconext/gateway +current_release_config_file_dir_name: /opt/openconext/gateway +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/gateway/ + diff --git a/roles/stepupgateway/vars/main.yml b/roles/stepupgateway/vars/main.yml index 8f8ba95df..ca601a1d6 100644 --- a/roles/stepupgateway/vars/main.yml +++ b/roles/stepupgateway/vars/main.yml @@ -7,7 +7,8 @@ stepup_gh_appname: "Gateway" current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" -current_release_config_dir_name: "{{ current_release_appdir }}/config/legacy" +current_release_config_dir_name: "{{ current_release_appdir }}/config/openconext" +current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" gateway_saml_sp_privatekey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/gateway_saml_sp.key') }}" gateway_gssp_sp_privatekey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/gateway_gssp_sp.key') }}" gateway_gssp_idp_privatekey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/gateway_gssp_idp.key') }}" diff --git a/roles/stepupmiddleware/tasks/docker.yml b/roles/stepupmiddleware/tasks/docker.yml new file mode 100644 index 000000000..44861f4b1 --- /dev/null +++ b/roles/stepupmiddleware/tasks/docker.yml @@ -0,0 +1,3 @@ +--- +- name: Exiting since there is no docker support yet + meta: end_play diff --git a/roles/stepupmiddleware/tasks/main.yml b/roles/stepupmiddleware/tasks/main.yml index ceab80cb6..19d999980 100644 --- a/roles/stepupmiddleware/tasks/main.yml +++ b/roles/stepupmiddleware/tasks/main.yml @@ -1,133 +1,7 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm +- name: Include docker tasks when running docker + import_tasks: docker.yml + when: "'docker' in group_names" -- name: Install the symfony app - include_role: - name: stepupapp - -- name: Place parameters.yml - template: - src: parameters.yaml.j2 - dest: "{{ current_release_config_dir_name }}/parameters.yaml" - mode: 0640 - owner: root - group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}" - dest: "{{ current_release_symlink }}" - state: link - -- name: Put middleware configuration scripts in /root/ - template: - src: "{{ item }}.j2" - dest: "/root/{{ item }}" - group: "root" - owner: "root" - mode: "0500" - with_items: - - "01-middleware-db_migrate.sh" - - "06-middleware-bootstrap-sraa-users.sh" - -- name: Create /opt/scripts - file: - path: /opt/scripts - state: directory - owner: root - group: root - mode: 0750 - -- name: Put middleware config from environment in /opt/scripts - template: - src: "{{ inventory_dir }}/templates/middleware/{{ item }}.j2" - dest: "/opt/scripts/{{ item }}" - group: "{{ appname }}" - owner: "{{ appname }}" - mode: "0400" - with_items: - - "middleware-config.json" - - "middleware-whitelist.json" - - "middleware-institution.json" - tags: - - push_mw_config - - push_mw_institution - - push_mw_whitelist - -- name: Put middleware configuration scripts in /opt/scripts - template: - src: "{{ item}}.j2" - dest: "/opt/scripts/{{ item }}" - group: "{{ appname }}" - owner: root - mode: "0550" - with_items: - - "middleware-push-config.sh" - - "middleware-push-whitelist.sh" - - "middleware-push-institution.sh" - -- name: Create symlinks to middleware configuration scripts in /root - file: - src: "/opt/scripts/{{ item.key }}" - dest: "/root/{{ item.value }}" - group: "{{ appname }}" - owner: root - state: link - force: true - with_dict: - "middleware-push-config.sh": "02-middleware-config.sh" - "middleware-push-whitelist.sh": "04-middleware-whitelist.sh" - "middleware-push-institution.sh": "05-middleware-institution.sh" - -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall - -# The following push scripts have an additional conditional check on the presence of -# a tag, so these are only ran when explicitly called. - -- name: Push middleware configuration - command: /opt/scripts/middleware-push-config.sh - run_once: true - when: - - "'push_mw_config' in ansible_run_tags" - tags: - - push_mw_config - -- name: Push middleware whitelist - command: /opt/scripts/middleware-push-whitelist.sh - run_once: True - when: - - "'push_mw_whitelist' in ansible_run_tags" - tags: - - push_mw_whitelist - -- name: Push middleware institution configuration - command: /opt/scripts/middleware-push-institution.sh - run_once: True - when: - - "'push_mw_institution' in ansible_run_tags" - tags: - - push_mw_institution - - -# Middleware migrate identities from CSV - -- name: Migrate middleware identities from CSV - include_tasks: migrate_identities.yml - args: - apply: - tags: - - mw_migrate_identities - run_once: True - when: - - "'mw_migrate_identities' in ansible_run_tags" - tags: - - mw_migrate_identities +- name: Include vm tasks when running on a vm + import_tasks: vm.yml + when: "'docker' not in group_names" diff --git a/roles/stepupmiddleware/tasks/vm.yml b/roles/stepupmiddleware/tasks/vm.yml new file mode 100644 index 000000000..ceab80cb6 --- /dev/null +++ b/roles/stepupmiddleware/tasks/vm.yml @@ -0,0 +1,133 @@ +- name: Install Apache and FPM config + include_role: + name: apachefpm + +- name: Install the symfony app + include_role: + name: stepupapp + +- name: Place parameters.yml + template: + src: parameters.yaml.j2 + dest: "{{ current_release_config_dir_name }}/parameters.yaml" + mode: 0640 + owner: root + group: "{{ appname }}" + notify: + - clear cache {{ appname }} + - reload php72-fpm {{ appname }} + +- name: Activate the symlink + file: + src: "{{ current_release_appdir }}" + dest: "{{ current_release_symlink }}" + state: link + +- name: Put middleware configuration scripts in /root/ + template: + src: "{{ item }}.j2" + dest: "/root/{{ item }}" + group: "root" + owner: "root" + mode: "0500" + with_items: + - "01-middleware-db_migrate.sh" + - "06-middleware-bootstrap-sraa-users.sh" + +- name: Create /opt/scripts + file: + path: /opt/scripts + state: directory + owner: root + group: root + mode: 0750 + +- name: Put middleware config from environment in /opt/scripts + template: + src: "{{ inventory_dir }}/templates/middleware/{{ item }}.j2" + dest: "/opt/scripts/{{ item }}" + group: "{{ appname }}" + owner: "{{ appname }}" + mode: "0400" + with_items: + - "middleware-config.json" + - "middleware-whitelist.json" + - "middleware-institution.json" + tags: + - push_mw_config + - push_mw_institution + - push_mw_whitelist + +- name: Put middleware configuration scripts in /opt/scripts + template: + src: "{{ item}}.j2" + dest: "/opt/scripts/{{ item }}" + group: "{{ appname }}" + owner: root + mode: "0550" + with_items: + - "middleware-push-config.sh" + - "middleware-push-whitelist.sh" + - "middleware-push-institution.sh" + +- name: Create symlinks to middleware configuration scripts in /root + file: + src: "/opt/scripts/{{ item.key }}" + dest: "/root/{{ item.value }}" + group: "{{ appname }}" + owner: root + state: link + force: true + with_dict: + "middleware-push-config.sh": "02-middleware-config.sh" + "middleware-push-whitelist.sh": "04-middleware-whitelist.sh" + "middleware-push-institution.sh": "05-middleware-institution.sh" + +- meta: flush_handlers + +- name: Include post installation tasks + include_role: + name: stepupapp + tasks_from: postinstall + +# The following push scripts have an additional conditional check on the presence of +# a tag, so these are only ran when explicitly called. + +- name: Push middleware configuration + command: /opt/scripts/middleware-push-config.sh + run_once: true + when: + - "'push_mw_config' in ansible_run_tags" + tags: + - push_mw_config + +- name: Push middleware whitelist + command: /opt/scripts/middleware-push-whitelist.sh + run_once: True + when: + - "'push_mw_whitelist' in ansible_run_tags" + tags: + - push_mw_whitelist + +- name: Push middleware institution configuration + command: /opt/scripts/middleware-push-institution.sh + run_once: True + when: + - "'push_mw_institution' in ansible_run_tags" + tags: + - push_mw_institution + + +# Middleware migrate identities from CSV + +- name: Migrate middleware identities from CSV + include_tasks: migrate_identities.yml + args: + apply: + tags: + - mw_migrate_identities + run_once: True + when: + - "'mw_migrate_identities' in ansible_run_tags" + tags: + - mw_migrate_identities diff --git a/roles/stepupmiddleware/templates/parameters.yaml.j2 b/roles/stepupmiddleware/templates/parameters.yaml.j2 index f48510944..ab6883576 100644 --- a/roles/stepupmiddleware/templates/parameters.yaml.j2 +++ b/roles/stepupmiddleware/templates/parameters.yaml.j2 @@ -5,7 +5,7 @@ parameters: database_driver: pdo_mysql - database_host: {{ database_lb_address }} + database_host: {{ dbcluster_ip }} database_port: 3306 # Enabling the STRICT_ALL_TABLES SQL mode. To prevent 'magic' truncation problems where string # values like the identity name id would be truncated after 255 characters without notice. Enabling diff --git a/roles/stepupra/handlers/main.yml b/roles/stepupra/handlers/main.yml index 40eef830c..1139c576b 100644 --- a/roles/stepupra/handlers/main.yml +++ b/roles/stepupra/handlers/main.yml @@ -6,3 +6,9 @@ service: name: php72-php-fpm state: reloaded + +- name: restart ra + community.docker.docker_container: + name: ra + state: started + restart: true diff --git a/roles/stepupra/tasks/main.yml b/roles/stepupra/tasks/main.yml index e3e4e242d..db580ef93 100644 --- a/roles/stepupra/tasks/main.yml +++ b/roles/stepupra/tasks/main.yml @@ -1,36 +1,52 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm +--- +- name: Include docker vars + ansible.builtin.include_vars: docker.yml -- name: Install the symfony app - include_role: +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: ra_guid + +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: ra_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" + +- name: Install images + ansible.builtin.include_role: name: stepupapp + tasks_from: copyimages - name: Install GSSP SP key and certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copygsspspcerts - name: Install SAML SP key and certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyspcerts -- name: Install images - include_role: - name: stepupapp - tasks_from: copyimages - -- name: Install second factor images - include_role: - name: stepupapp - tasks_from: copysfimages - - name: Put parameters, samlstepupproviders, samlstepupproviders_parameters and global_view_parameters YAML config - template: + ansible.builtin.template: src: "{{ item }}.yml.j2" dest: "{{ current_release_config_dir_name }}/{{ item }}.yaml" - mode: 0640 + mode: "0640" group: "{{ appname }}" with_items: - parameters @@ -38,18 +54,28 @@ - samlstepupproviders_parameters - global_view_parameters notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}/" - dest: "{{ current_release_symlink }}" - state: link + - restart {{ appname }} -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-ra/stepup-ra:{{ ra_version }} + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.ra.rule: "Host(`{{ ra_vhost_name }}`)" + traefik.http.routers.ra.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ ra_uid.uid }}" + APACHE_GUID: "#{{ ra_guid.gid }}" + APP_ENV: prod + mounts: + - source: /opt/openconext/ra/public/images/header-logo.png + target: /var/www/html/public/build/images/header-logo.png + type: bind + - source: /opt/openconext/ra + target: /var/www/html/config/openconext + type: bind diff --git a/roles/stepupra/templates/parameters.yml.j2 b/roles/stepupra/templates/parameters.yml.j2 index 7df5fb0e2..7814f4b62 100644 --- a/roles/stepupra/templates/parameters.yml.j2 +++ b/roles/stepupra/templates/parameters.yml.j2 @@ -1,4 +1,10 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ ra_secret }} +{% endif %} + trusted_proxies: [ {{ engine_trusted_proxy_ips|join(',') }} ] mailer_transport: smtp @@ -34,26 +40,24 @@ parameters: sms_otp_expiry_interval: {{ sms_otp_expiry_interval }} sms_maximum_otp_requests: {{ sms_maximum_otp_requests }} - saml_sp_publickey: {{ current_release_config_file_dir_name }}/sp.crt - saml_sp_privatekey: {{ current_release_config_file_dir_name }}/sp.key + saml_sp_publickey: {{ current_release_config_file_dir_name_in_config }}/sp.crt + saml_sp_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp.key - saml_metadata_publickey: {{ current_release_config_file_dir_name }}/sp.crt - saml_metadata_privatekey: {{ current_release_config_file_dir_name }}/sp.key + saml_metadata_publickey: {{ current_release_config_file_dir_name_in_config }}/sp.crt + saml_metadata_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp.key saml_remote_idp_entity_id: https://{{ gateway_vhost_name }}/authentication/metadata saml_remote_idp_sso_url: https://{{ gateway_vhost_name }}/authentication/single-sign-on saml_remote_idp_certificate: {{ gateway_saml_idp_publickey | depem }} # Minimum LoA required for login to the RA interface - loa_required_for_login: '{{ stepup_uri_loa3 }}' + authentication_context_class_ref: '{{ stepup_uri_loa3 }}' stepup_loa_loa1: '{{ stepup_uri_loa1 }}' stepup_loa_loa2: '{{ stepup_uri_loa2 }}' stepup_loa_loa3: '{{ stepup_uri_loa3 }}' stepup_loa_self_asserted: '{{ stepup_uri_self_asserted }}' - asset_version: {{ appversion_sha }} - logout_redirect_url: {% for key, value in ra_logout_redirect_url.items() %} {{ key }}: {{ value }} diff --git a/roles/stepupra/templates/samlstepupproviders_parameters.yml.j2 b/roles/stepupra/templates/samlstepupproviders_parameters.yml.j2 index 9ad205457..cda9e80d5 100644 --- a/roles/stepupra/templates/samlstepupproviders_parameters.yml.j2 +++ b/roles/stepupra/templates/samlstepupproviders_parameters.yml.j2 @@ -5,12 +5,12 @@ parameters: {% for key, value in stepup_enabled_generic_second_factors.items() %} # GSSP Proxy SP used to authenticate to the Real GSSP IdP though GSSP IdP proxy in the gateway - gssp_{{ key }}_sp_publickey: '{{ current_release_config_file_dir_name }}/sp_gssp.crt' - gssp_{{ key }}_sp_privatekey: '{{ current_release_config_file_dir_name }}/sp_gssp.key' + gssp_{{ key }}_sp_publickey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.crt' + gssp_{{ key }}_sp_privatekey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.key' # Certificate used to sign metadata of the GSSP Proxy SP on the gateway - gssp_{{ key }}_metadata_publickey: '{{ current_release_config_file_dir_name }}/sp_gssp.crt' - gssp_{{ key }}_metadata_privatekey: '{{ current_release_config_file_dir_name }}/sp_gssp.key' + gssp_{{ key }}_metadata_publickey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.crt' + gssp_{{ key }}_metadata_privatekey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.key' # EntityID and SSO Location of the GSSP IdP Proxy on the Gateway gssp_{{ key }}_remote_entity_id: 'https://{{ gateway_vhost_name }}/gssp/{{ key }}/metadata' diff --git a/roles/stepupra/vars/docker.yml b/roles/stepupra/vars/docker.yml new file mode 100644 index 000000000..e035e8149 --- /dev/null +++ b/roles/stepupra/vars/docker.yml @@ -0,0 +1,4 @@ +current_release_appdir: /opt/openconext/ra +current_release_config_file_dir_name: /opt/openconext/ra +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/ra diff --git a/roles/stepupra/vars/main.yml b/roles/stepupra/vars/main.yml index 2fbc04ce4..996a4ff2c 100644 --- a/roles/stepupra/vars/main.yml +++ b/roles/stepupra/vars/main.yml @@ -9,6 +9,7 @@ current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{ current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" current_release_config_dir_name: "{{ current_release_appdir }}/config/legacy" +current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" gssp_sp_private_key: "{{ lookup('file', inventory_dir+'/files/certs/stepup/ra_gssp_sp.key') }}" stepup_saml_sp_privatekey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/ra_saml_sp.key') }}" gateway_saml_idp_publickey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/gateway_saml_idp.crt') }}" diff --git a/roles/stepupselfservice/handlers/main.yml b/roles/stepupselfservice/handlers/main.yml index 40eef830c..007b0fc07 100644 --- a/roles/stepupselfservice/handlers/main.yml +++ b/roles/stepupselfservice/handlers/main.yml @@ -6,3 +6,9 @@ service: name: php72-php-fpm state: reloaded + +- name: restart selfservice + community.docker.docker_container: + name: selfservice + state: started + restart: true diff --git a/roles/stepupselfservice/tasks/main.yml b/roles/stepupselfservice/tasks/main.yml index c8f38280f..77855882c 100644 --- a/roles/stepupselfservice/tasks/main.yml +++ b/roles/stepupselfservice/tasks/main.yml @@ -1,36 +1,52 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm +--- +- name: Include docker vars + ansible.builtin.include_vars: docker.yml -- name: Install the symfony app - include_role: +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: selfservice_guid + +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: selfservice_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" + +- name: Install images + ansible.builtin.include_role: name: stepupapp + tasks_from: copyimages - name: Install GSSP SP key and certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copygsspspcerts - name: Install SAML SP key and certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyspcerts -- name: Install images - include_role: - name: stepupapp - tasks_from: copyimages - -- name: Install images - include_role: - name: stepupapp - tasks_from: copysfimages - - name: Put parameters, samlstepupproviders, samlstepupproviders_parameters and global_view_parameters YAML config - template: + ansible.builtin.template: src: "{{ item }}.yml.j2" dest: "{{ current_release_config_dir_name }}/{{ item }}.yaml" - mode: 0640 + mode: "0640" group: "{{ appname }}" with_items: - parameters @@ -38,18 +54,30 @@ - samlstepupproviders_parameters - global_view_parameters notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}/" - dest: "{{ current_release_symlink }}" - state: link + - restart {{ appname }} -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-selfservice/stepup-selfservice:{{ selfservice_version }} + etc_hosts: + host.docker.internal: host-gateway + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.selfservice.rule: "Host(`{{ selfservice_vhost_name }}`)" + traefik.http.routers.selfservice.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ selfservice_uid.uid }}" + APACHE_GUID: "#{{ selfservice_guid.gid }}" + APP_ENV: prod + mounts: + - source: /opt/openconext/selfservice/public/images/header-logo.png + target: /var/www/html/public/build/images/logo/header-logo.png + type: bind + - source: /opt/openconext/selfservice + target: /var/www/html/config/openconext + type: bind diff --git a/roles/stepupselfservice/templates/parameters.yml.j2 b/roles/stepupselfservice/templates/parameters.yml.j2 index 846847ec4..cb2f25759 100644 --- a/roles/stepupselfservice/templates/parameters.yml.j2 +++ b/roles/stepupselfservice/templates/parameters.yml.j2 @@ -1,8 +1,14 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ selfservice_secret }} +{% endif %} + trusted_proxies: [ {{ engine_trusted_proxy_ips|join(',') }} ] mailer_transport: smtp - mailer_host: 127.0.0.1 + mailer_host: host.docker.internal mailer_user: ~ mailer_password: ~ @@ -32,13 +38,13 @@ parameters: sms_otp_expiry_interval: {{ sms_otp_expiry_interval }} sms_maximum_otp_requests: {{ sms_maximum_otp_requests }} - saml_sp_publickey: {{ current_release_config_file_dir_name }}/sp.crt + saml_sp_publickey: {{ current_release_config_file_dir_name_in_config }}/sp.crt - saml_sp_privatekey: {{ current_release_config_file_dir_name }}/sp.key + saml_sp_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp.key - saml_metadata_publickey: {{ current_release_config_file_dir_name }}/sp.crt + saml_metadata_publickey: {{ current_release_config_file_dir_name_in_config }}/sp.crt - saml_metadata_privatekey: {{ current_release_config_file_dir_name }}/sp.key + saml_metadata_privatekey: {{ current_release_config_file_dir_name_in_config }}/sp.key # Connect to remote IdP through Stepup Gateway saml_remote_idp_entity_id: https://{{ gateway_vhost_name }}/authentication/metadata @@ -56,8 +62,6 @@ parameters: second_factor_test_idp_sso_url: https://{{ gateway_vhost_name }}/authentication/single-sign-on second_factor_test_idp_certificate: {{ gateway_saml_idp_publickey | depem }} - asset_version: {{ appversion_sha }} - stepup_loa_loa1: {{ stepup_uri_loa1 }} stepup_loa_loa2: {{ stepup_uri_loa2 }} stepup_loa_loa3: {{ stepup_uri_loa3 }} @@ -91,3 +95,12 @@ parameters: # Self-asserted token registration process. recovery_method_sms_enabled: true recovery_method_safe_store_code_enabled: true + + # SAML Bundle SamlAuthenticator configuration + # The acs location that the SAML response must be posted to (used in SamlAuthenticator::supports) + acs_location_route_name: selfservice_serviceprovider_consume_assertion + # The relay state values that will cause the SamlAuthenticator from not handling the SAML response. + # Used for test and self asserted token registration authentications + rejected_relay_states: ['isTestRequest', 'isSatRequest', 'isGssfRequest'] + + authentication_context_class_ref: {{ stepup_uri_loa1 }} diff --git a/roles/stepupselfservice/templates/samlstepupproviders_parameters.yml.j2 b/roles/stepupselfservice/templates/samlstepupproviders_parameters.yml.j2 index 71702288e..b2005c26b 100644 --- a/roles/stepupselfservice/templates/samlstepupproviders_parameters.yml.j2 +++ b/roles/stepupselfservice/templates/samlstepupproviders_parameters.yml.j2 @@ -5,12 +5,12 @@ parameters: {% for key, value in stepup_enabled_generic_second_factors.items() %} # GSSP Proxy SP used to authenticate to the Real GSSP IdP though GSSP IdP proxy in the gateway - gssp_{{ key }}_sp_publickey: '{{ current_release_config_file_dir_name }}/sp_gssp.crt' - gssp_{{ key }}_sp_privatekey: '{{ current_release_config_file_dir_name }}/sp_gssp.key' + gssp_{{ key }}_sp_publickey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.crt' + gssp_{{ key }}_sp_privatekey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.key' # Certificate used to sign metadata of the GSSP Proxy SP on the gateway - gssp_{{ key }}_metadata_publickey: '{{ current_release_config_file_dir_name }}/sp_gssp.crt' - gssp_{{ key }}_metadata_privatekey: '{{ current_release_config_file_dir_name }}/sp_gssp.key' + gssp_{{ key }}_metadata_publickey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.crt' + gssp_{{ key }}_metadata_privatekey: '{{ current_release_config_file_dir_name_in_config }}/sp_gssp.key' # EntityID and SSO Location of the GSSP IdP Proxy on the Gateway gssp_{{ key }}_remote_entity_id: 'https://{{ gateway_vhost_name }}/gssp/{{ key }}/metadata' diff --git a/roles/stepupselfservice/vars/docker.yml b/roles/stepupselfservice/vars/docker.yml new file mode 100644 index 000000000..008c03990 --- /dev/null +++ b/roles/stepupselfservice/vars/docker.yml @@ -0,0 +1,4 @@ +current_release_appdir: /opt/openconext/selfservice +current_release_config_file_dir_name: /opt/openconext/selfservice +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/selfservice diff --git a/roles/stepupselfservice/vars/main.yml b/roles/stepupselfservice/vars/main.yml index ac19de1ea..828ec6de1 100644 --- a/roles/stepupselfservice/vars/main.yml +++ b/roles/stepupselfservice/vars/main.yml @@ -9,6 +9,7 @@ current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{ current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" current_release_config_dir_name: "{{ current_release_appdir }}/config/legacy" +current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" gssp_sp_private_key: "{{ lookup('file', inventory_dir+'/files/certs/stepup/selfservice_gssp_sp.key') }}" stepup_saml_sp_privatekey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/selfservice_saml_sp.key') }}" gateway_saml_idp_publickey: "{{ lookup('file', inventory_dir+'/files/certs/stepup/gateway_saml_idp.crt') }}" diff --git a/roles/stepuptiqr/handlers/main.yml b/roles/stepuptiqr/handlers/main.yml index 40eef830c..ab79436f4 100644 --- a/roles/stepuptiqr/handlers/main.yml +++ b/roles/stepuptiqr/handlers/main.yml @@ -6,3 +6,10 @@ service: name: php72-php-fpm state: reloaded + +- name: restart tiqr + community.docker.docker_container: + name: tiqr + state: started + restart: true + diff --git a/roles/stepuptiqr/tasks/main.yml b/roles/stepuptiqr/tasks/main.yml index 81c222dfc..867585085 100644 --- a/roles/stepuptiqr/tasks/main.yml +++ b/roles/stepuptiqr/tasks/main.yml @@ -1,93 +1,87 @@ -- debug: - msg: "{{ tiqr_statestorage }}" +- name: Include docker vars + ansible.builtin.include_vars: docker.yml -- name: Install Apache and FPM config - include_role: - name: apachefpm +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: tiqr_guid -- name: Install the symfony app - include_role: - name: stepupapp +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: tiqr_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" - name: Install images - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyimages -- name: Install the GSSP certificates - include_role: +- name: Install GSSP IdP key and certificates + ansible.builtin.include_role: name: stepupapp tasks_from: copygsspidpcerts - name: Write tiqr APNS certificate - copy: + ansible.builtin.copy: content: "{{ tiqr_apns_pemfile }}" dest: "{{ current_release_config_file_dir_name }}/apns.pem" owner: "{{ appname }}" - mode: 0400 + mode: "0400" when: tiqr_apns_pemfile is defined - name: Write tiqr Firebase service json copy: - src: "{{ inventory_dir }}/secrets/tiqr-demo.json" + src: "{{ inventory_dir }}/secrets/stepup/tiqr-demo.json" dest: "{{ current_release_config_file_dir_name }}/tiqr-demo.json" owner: "{{ appname }}" mode: 0400 when: tiqr_firebase_credentialsfile is defined - name: Place parameters.yml - template: + ansible.builtin.template: src: parameters.yaml.j2 dest: "{{ current_release_config_dir_name }}/parameters.yaml" - mode: 0640 + mode: "0640" owner: root group: "{{ appname }}" notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Place .env file - template: - src: env.j2 - dest: "{{ current_release_appdir }}/.env.local" - mode: 0640 - owner: root - group: "{{ appname }}" - notify: clear cache {{ appname }} - -- name: Install assets - command: php72 {{ current_release_appdir }}/bin/console assets:install + - restart tiqr -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}" - dest: "{{ current_release_symlink }}" - state: link - -- name: Put tiqr configuration script in /root/ - template: - src: "{{ item }}.j2" - dest: "/root/{{ item }}" - group: root - owner: root - mode: "0500" - with_items: - - "01-tiqr-db_init.sh" - -- name: Put tiqr keyserver migration script in /root/ - template: - src: "{{ item }}.j2" - dest: "/root/{{ item }}" - group: root - owner: root - mode: "500" - with_items: - - "02-tiqr-migrate-to-keyserver.php" - when: keyserver_consumerkey is defined - -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-tiqr/stepup-tiqr:{{ tiqr_version }} + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.tiqr.rule: "Host(`tiqr.{{ base_domain }}`)" + traefik.http.routers.tiqr.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ tiqr_uid.uid }}" + APACHE_GUID: "#{{ tiqr_guid.gid }}" + APP_ENV: prod + mounts: + - source: /opt/openconext/tiqr/public/images/header-logo.png + target: /var/www/html/public/build/images/logo/header-logo.png + type: bind + - source: /opt/openconext/tiqr + target: /var/www/html/config/openconext + type: bind \ No newline at end of file diff --git a/roles/stepuptiqr/templates/parameters.yaml.j2 b/roles/stepuptiqr/templates/parameters.yaml.j2 index 52c0b5b4e..c6a79571c 100644 --- a/roles/stepuptiqr/templates/parameters.yaml.j2 +++ b/roles/stepuptiqr/templates/parameters.yaml.j2 @@ -1,16 +1,22 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ tiqr_secret }} +{% endif %} + # All locales supported by the application locales: [{{ enabled_locales | join(",") }}] # SAML configuration - saml_idp_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_idp_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_idp_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_idp_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' # NOTE: same key used for metadata and response/assertion signing - saml_metadata_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_metadata_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_metadata_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_metadata_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' saml_remote_sp_entity_id: 'https://{{ gateway_vhost_name }}/gssp/tiqr/metadata' - saml_remote_sp_certificate: '{{ current_release_config_file_dir_name }}/gateway.crt' + saml_remote_sp_certificate: '{{ current_release_config_file_dir_name_in_config }}/gateway.crt' saml_remote_sp_acs: 'https://{{ gateway_vhost_name }}/gssp/tiqr/consume-assertion' base_url: 'https://{{ vhost_name }}' @@ -40,23 +46,16 @@ parameters: logoUrl: '%base_url%/images/header-logo.png' infoUrl: '{{ tiqr_info_url }}' library: -{% if tiqr_gcm_apikey is defined %} gcm: apikey: '{{ tiqr_gcm_apikey }}' application: 'nl.surfnet.authenticator' -{% endif %} -{% if tiqr_firebase_apikey is defined %} - firebase: - apikey: '{{ tiqr_firebase_apikey }}' -{% endif %} -{% if tiqr_firebase_credentialsFile is defined %} firebase: projectId: '{{ tiqr_firebase_projectid }}' - credentialsFile: '{{ tiqr_firebase_credentialsfile }}' - cacheTokens: '{{ tiqr_firebase_cachetokens }}' -{% endif %} + credentialsFile: '{{ current_release_config_file_dir_name_in_config }}/{{ tiqr_firebase_credentialsfile }}' + cacheTokens: {{ tiqr_firebase_cachetokens }} + tokenCacheDir: '/tmp' apns: - certificate: '{{ current_release_config_file_dir_name }}/apns.pem' + certificate: '{{ current_release_config_file_dir_name_in_config }}/apns.pem' environment: production accountblocking: maxAttempts: 5 @@ -106,4 +105,4 @@ parameters: dsn: 'mysql:host={{ tiqr_db_host }};dbname={{ database_tiqr_name }}' username: '{{ database_tiqr_user }}' password: '{{ mysql_passwords.tiqr }}' -{% endif %} +{% endif %} \ No newline at end of file diff --git a/roles/stepuptiqr/vars/docker.yml b/roles/stepuptiqr/vars/docker.yml new file mode 100644 index 000000000..f42194f3d --- /dev/null +++ b/roles/stepuptiqr/vars/docker.yml @@ -0,0 +1,5 @@ + +current_release_appdir: /opt/openconext/tiqr +current_release_config_file_dir_name: /opt/openconext/tiqr +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/tiqr diff --git a/roles/stepuptiqr/vars/main.yml b/roles/stepuptiqr/vars/main.yml index 23f1e5917..18fed7cfb 100644 --- a/roles/stepuptiqr/vars/main.yml +++ b/roles/stepuptiqr/vars/main.yml @@ -9,6 +9,7 @@ current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{ current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" current_release_config_dir_name: "{{ current_release_appdir }}/config/legacy" +current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" gssp_idp_private_key: "{{ lookup('file', inventory_dir+'/files/certs/stepup/tiqr_idp.key') }}" database_tiqr_user: tiqrrw database_tiqr_deploy_user: tiqrdeploy diff --git a/roles/stepupwebauthn/handlers/main.yml b/roles/stepupwebauthn/handlers/main.yml index 40eef830c..e118b593e 100644 --- a/roles/stepupwebauthn/handlers/main.yml +++ b/roles/stepupwebauthn/handlers/main.yml @@ -6,3 +6,9 @@ service: name: php72-php-fpm state: reloaded + +- name: restart webauthn + community.docker.docker_container: + name: webauthn + state: started + restart: true diff --git a/roles/stepupwebauthn/tasks/main.yml b/roles/stepupwebauthn/tasks/main.yml index cd4e8e993..ec04bc7d6 100644 --- a/roles/stepupwebauthn/tasks/main.yml +++ b/roles/stepupwebauthn/tasks/main.yml @@ -1,77 +1,121 @@ -- name: Install Apache and FPM config - include_role: - name: apachefpm +- name: Include docker vars + ansible.builtin.include_vars: docker.yml -- name: Install the symfony app - include_role: - name: stepupapp +- name: Add group {{ appname }} + ansible.builtin.group: + name: "{{ appname }}" + state: present + register: webauthn_guid + +- name: Add user {{ appname }} + ansible.builtin.user: + name: "{{ appname }}" + group: "{{ appname }}" + createhome: no + state: present + register: webauthn_uid + +- name: Create some dirs + ansible.builtin.file: + state: directory + dest: "{{ item }}" + owner: root + group: root + mode: "0755" + with_items: + - "{{ current_release_config_dir_name }}" + - "{{ current_release_appdir }}/public/images" - name: Install images - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copyimages - name: Install the GSSP certificates - include_role: + ansible.builtin.include_role: name: stepupapp tasks_from: copygsspidpcerts -- name: Create the trusted certificate dir - file: +- name: Create the metadata service dir + ansible.builtin.file: state: directory dest: "{{ item }}" + owner: root + mode: "0755" with_items: - - "{{ current_release_config_file_dir_name }}/trusted_certificates" + - "{{ current_release_config_file_dir_name }}/mds" -- name: Place parameters.yml - template: - src: parameters.yml.j2 - dest: "{{ current_release_config_dir_name }}/parameters.yml" - mode: 0640 +- name: Create and empty the metadata service cache dir + ansible.builtin.file: + state: "{{ item }}" + path: "{{ current_release_config_file_dir_name }}/var/mds/" owner: root group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} + mode: "0774" + with_items: + - absent + - directory + +- name: Download metadata service blob + ansible.builtin.get_url: + url: https://mds3.fidoalliance.org/ + dest: "{{ current_release_config_file_dir_name }}/mds/blob.jwt" + mode: '0744' + force: true -- name: Place .env file - template: - src: env.j2 - dest: "{{ current_release_appdir }}/.env.local" - mode: 0640 +- name: Download metadata service signing certificate + ansible.builtin.get_url: + url: http://secure.globalsign.com/cacert/root-r3.crt + dest: "{{ current_release_config_file_dir_name }}/mds/fido2-mds.cer" + mode: '0744' + force: true + +- name: Place parameters.yml + ansible.builtin.template: + src: parameters.yml.j2 + dest: "{{ current_release_config_dir_name }}/parameters.yaml" + mode: "0640" owner: root group: "{{ appname }}" - notify: - - clear cache {{ appname }} - - reload php72-fpm {{ appname }} - -- name: Copy trusted certificates - copy: - src: "{{ item }}" - dest: "{{ current_release_config_file_dir_name }}/trusted_certificates/" - mode: "444" - with_fileglob: - - "{{ inventory_dir }}/files/stepup-webauthn/trusted_certificates/*" + notify: restart webauthn -- name: Activate the symlink - file: - src: "{{ current_release_appdir }}" - dest: "{{ current_release_symlink }}" - state: link +# - name: Copy trusted certificates +# ansible.builtin.copy: +# src: "{{ item }}" +# dest: "{{ current_release_config_file_dir_name }}/trusted_certificates/" +# mode: "444" +# with_fileglob: +# - "{{ inventory_dir }}/files/stepup-webauthn/trusted_certificates/*" - name: Put webauthn configuration script in /root/ - template: + ansible.builtin.template: src: "{{ item }}.j2" dest: "/root/{{ item }}" - group: root - owner: root + group: root + owner: root mode: "0500" with_items: - - "01-webauthn-db_init.sh" + - "01-webauthn-db_init.sh" -- meta: flush_handlers - -- name: Include post installation tasks - include_role: - name: stepupapp - tasks_from: postinstall +- name: Create the container + community.docker.docker_container: + name: "{{ appname }}" + image: ghcr.io/openconext/stepup-webauthn/stepup-webauthn:{{ webauthn_version }} + pull: true + restart_policy: "always" + networks: + - name: "loadbalancer" + labels: + traefik.http.routers.webauthn.rule: "Host(`webauthn.{{ base_domain }}`)" + traefik.http.routers.webauthn.tls: "true" + traefik.enable: "true" + env: + APACHE_UID: "#{{ webauthn_uid.uid }}" + APACHE_GUID: "#{{ webauthn_guid.gid }}" + mounts: + - source: /opt/openconext/webauthn/public/images/header-logo.png + target: /var/www/html/public/build/images/logo/header-logo.png + type: bind + - source: /opt/openconext/webauthn + target: /var/www/html/config/openconext + type: bind diff --git a/roles/stepupwebauthn/templates/parameters.yml.j2 b/roles/stepupwebauthn/templates/parameters.yml.j2 index 221402c9e..a0a4e6cce 100644 --- a/roles/stepupwebauthn/templates/parameters.yml.j2 +++ b/roles/stepupwebauthn/templates/parameters.yml.j2 @@ -1,16 +1,22 @@ parameters: +{% if 'docker' in group_names %} + app_env: prod + app_debug: false + app_secret: {{ webauthn_secret }} + database_url: mysql://{{ database_webauthn_user }}:{{ mysql_passwords.webauthn }}@{{ webauthn_db_host }}:3306/{{ database_webauthn_name }} +{% endif %} # All locales supported by the application locales: [{{ enabled_locales | join(",") }}] # SAML configuration - saml_idp_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_idp_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_idp_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_idp_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' # NOTE: same key used for metadata and response/assertion signing - saml_metadata_publickey: '{{ current_release_config_file_dir_name }}/cert.pem' - saml_metadata_privatekey: '{{ current_release_config_file_dir_name }}/key.pem' + saml_metadata_publickey: '{{ current_release_config_file_dir_name_in_config }}/cert.pem' + saml_metadata_privatekey: '{{ current_release_config_file_dir_name_in_config }}/key.pem' saml_remote_sp_entity_id: 'https://{{ gateway_vhost_name }}/gssp/webauthn/metadata' - saml_remote_sp_certificate: '{{ current_release_config_file_dir_name }}/gateway.crt' + saml_remote_sp_certificate: '{{ current_release_config_file_dir_name_in_config }}/gateway.crt' saml_remote_sp_acs: 'https://{{ gateway_vhost_name }}/gssp/webauthn/consume-assertion' # View parameters @@ -24,4 +30,7 @@ parameters: webauthn_name: '{{ webauthn_user_display_name }}' webauthn_logo: 'https://{{ webauthn_vhost_name }}/images/header-logo.png' - trusted_certificates_directory: '{{ current_release_config_file_dir_name }}/trusted_certificates' + trusted_certificates_directory: '{{ current_release_config_file_dir_name_in_config }}/trusted_certificates' + fido2_jwt_mds_blob_file_name: '{{ current_release_config_file_dir_name_in_config }}/mds/blob.jwt' + fido2_jwt_mds_root_certificate_file_name: '{{ current_release_config_file_dir_name_in_config }}/mds/fido2-mds.cer' + fido2_mds_cache_dir: '{{ current_release_config_file_dir_name_in_config }}/var/mds/' diff --git a/roles/stepupwebauthn/vars/docker.yml b/roles/stepupwebauthn/vars/docker.yml new file mode 100644 index 000000000..c765aafa4 --- /dev/null +++ b/roles/stepupwebauthn/vars/docker.yml @@ -0,0 +1,4 @@ +current_release_appdir: /opt/openconext/webauthn +current_release_config_file_dir_name: /opt/openconext/webauthn +current_release_config_file_dir_name_in_config: /var/www/html/config/openconext +current_release_config_dir_name: /opt/openconext/webauthn diff --git a/roles/stepupwebauthn/vars/main.yml b/roles/stepupwebauthn/vars/main.yml index e16b790b8..d24106cf0 100644 --- a/roles/stepupwebauthn/vars/main.yml +++ b/roles/stepupwebauthn/vars/main.yml @@ -8,6 +8,7 @@ stepup_gh_appname: Webauthn current_release_symlink: "/opt/openconext/OpenConext-{{ appname }}" current_release_appdir: "{{ current_release_symlink }}-{{ appversion }}" current_release_config_file_dir_name: "{{ current_release_appdir }}/app/files" +current_release_config_file_dir_name_in_config: "{{ current_release_config_file_dir_name }}" current_release_config_dir_name: "{{ current_release_appdir }}/config/packages" gssp_idp_private_key: "{{ lookup('file', inventory_dir+'/files/certs/stepup/webauthn_idp.key') }}" database_webauthn_user: webauthnrw diff --git a/roles/teams/tasks/main.yml b/roles/teams/tasks/main.yml index 4baa22064..8326a466a 100644 --- a/roles/teams/tasks/main.yml +++ b/roles/teams/tasks/main.yml @@ -22,6 +22,8 @@ - name: Create and start the server container community.docker.docker_container: name: teamsserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-teams-ng/teams-server:{{ teams_server_version }} pull: true restart_policy: "always" @@ -74,6 +76,13 @@ retries: 3 start_period: 10s hostname: teams + mounts: + - source: /etc/localtime + target: /etc/localtime + type: bind + - source: /opt/openconext/common/favicon.ico + target: /var/www/favicon.ico + type: bind env: HTTPD_CSP: "{{ httpd_csp.strict_with_static_img }}" HTTPD_SERVERNAME: "teams.{{ base_domain }}" diff --git a/roles/teams/templates/serverapplication.yml.j2 b/roles/teams/templates/serverapplication.yml.j2 index ba667352a..b9dc23489 100644 --- a/roles/teams/templates/serverapplication.yml.j2 +++ b/roles/teams/templates/serverapplication.yml.j2 @@ -7,7 +7,7 @@ logging: api: lifecycle: username: {{ teams_api_lifecycle_username }} - password: {{ teams_api_lifecycle_password }} + password: "{{ teams_api_lifecycle_password }}" secure_cookie: true @@ -22,10 +22,6 @@ server: secure: true server-header: no -feature-toggles: - expiry-date-membership: false - person-email-picker: false - config: support-email: {{ support_email }} help-link-en: {{ teams_help_link_en }} @@ -39,14 +35,17 @@ config: sponsor: {{ sponsor_name }} supported_language_codes: {{ supported_language_codes }} +features: + invite-migration-on: {{ teams.feature_invite_migration_on }} + security: user: - name: {{ teams.voot_api_user }} - password: {{ external_group_provider_secrets.teams }} + name: "{{ teams.voot_api_user }}" + password: "{{ external_group_provider_secrets.teams }}" sp_dashboard: - user-name: {{ teams.spdashboard_api_user }} - password: {{ teams_api_spdashboard_password }} + user-name: "{{ teams.spdashboard_api_user }}" + password: "{{ teams_api_spdashboard_password }}" person-urn: "{{ teams.spdashboard_person_urn }}" name: "SP Dashboard" email: "{{ support_email }}" @@ -76,9 +75,9 @@ voot: scopes: "{{ teams_manage_provision_oidcrp_scopes }}" invite: - url: https://invite.{{ base_domain }}/api/teams - user: {{ invite.teamsuser}} - password: {{ invite.teamssecret }} + url: "https://invite.{{ base_domain }}/api/teams" + user: "{{ invite.teamsuser}}" + password: "{{ invite.teamssecret }}" spring: session: @@ -97,9 +96,9 @@ spring: driver-class-name: org.mariadb.jdbc.Driver url: jdbc:mysql://{{ teams.db_host }}/{{ teams.db_name }}?useMysqlMetadata=true username: {{ teams.db_user }} - password: {{ teams.db_password }} + password: "{{ teams.db_password }}" mail: - host: {{ smtp_host }} + host: {{ smtp_server }} port: 25 main: banner-mode: "off" diff --git a/roles/voot/tasks/main.yml b/roles/voot/tasks/main.yml index 845fb246d..15403e587 100644 --- a/roles/voot/tasks/main.yml +++ b/roles/voot/tasks/main.yml @@ -23,6 +23,8 @@ - name: Create and start the server container community.docker.docker_container: name: vootserver + env: + TZ: "{{ timezone }}" image: ghcr.io/openconext/openconext-voot/voot:{{ voot_version }} pull: true restart_policy: "always" @@ -63,7 +65,7 @@ notify: restart vootserver - name: Include the role manage_provision_entities to provision the client_credentials client - include_role: + ansible.builtin.include_role: name: manage_provision_entities - vars: + vars: entity_type: oauth20_rs diff --git a/tests/github.yml b/tests/github.yml index 206d217c2..4a3e08b15 100644 --- a/tests/github.yml +++ b/tests/github.yml @@ -9,4 +9,5 @@ dashboard_install: False update_hosts_file: False manage_show_oidc_rp_tab: true manage_exclude_oidc_rp_imports_in_push: true +manage_exclude_sram_imports_in_push: true mongo_tls_host_altname_dnsorip: DNS