diff --git a/provision.yml b/provision.yml index be6d8fbf0..9ec706183 100644 --- a/provision.yml +++ b/provision.yml @@ -126,6 +126,7 @@ - { role: lifecycle, tags: ["lifecycle"] } - { role: stepuptiqr, tags: ['stepuptiqr' , 'stepup'] } - { role: openaccess, tags: ['openaccess' ] } + - { role: midproxy, tags: ['midproxy', 'myaccessid' ] } - hosts: docker_apps2 become: true diff --git a/roles/midproxy/defaults/main.yml b/roles/midproxy/defaults/main.yml new file mode 100644 index 000000000..3522fcb47 --- /dev/null +++ b/roles/midproxy/defaults/main.yml @@ -0,0 +1,8 @@ +--- +midproxy: + satosa_version: 8 + state_encryption_key: 'secret' + issuer: 'issuer' + client_id: 'client' + client_secret: 'secret' + sp_metadata: 'eb-metadata.xml' diff --git a/roles/midproxy/files/internal_attributes.yaml b/roles/midproxy/files/internal_attributes.yaml new file mode 100644 index 000000000..f03873371 --- /dev/null +++ b/roles/midproxy/files/internal_attributes.yaml @@ -0,0 +1,27 @@ +attributes: + displayname: + openid: [name] + saml: [displayName] + edupersontargetedid: + openid: [sub] + saml: [eduPersonTargetedID] + givenname: + openid: [given_name] + saml: [givenName] + mail: + openid: [email] + saml: [email, emailAddress, mail] + name: + openid: [name] + saml: [cn] + surname: + openid: [family_name] + saml: [sn, surname] + uid: + openid: [sub] + saml: [uid] + schachomeorganization: + openid: [schac_home_organization] + saml: [schacHomeOrganization] +user_id_from_attrs: [edupersontargetedid] +user_id_to_attr: edupersontargetedid diff --git a/roles/midproxy/files/plugins/backends/openid_backend.yaml b/roles/midproxy/files/plugins/backends/openid_backend.yaml new file mode 100644 index 000000000..cb78fcccd --- /dev/null +++ b/roles/midproxy/files/plugins/backends/openid_backend.yaml @@ -0,0 +1,14 @@ +module: satosa.backends.openid_connect.OpenIDConnectBackend +name: myaccessid +config: + provider_metadata: + issuer: !ENV SATOSA_ISSUER + client: + verify_ssl: yes + auth_req_params: + response_type: code + scope: [openid, profile, email, schac_home_organization] + client_metadata: + client_id: !ENV SATOSA_CLIENT_ID + client_secret: !ENV SATOSA_CLIENT_SECRET + redirect_uris: [/] diff --git a/roles/midproxy/files/plugins/backends/saml2_backend.yaml b/roles/midproxy/files/plugins/backends/saml2_backend.yaml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/roles/midproxy/files/plugins/backends/saml2_backend.yaml @@ -0,0 +1 @@ +--- diff --git a/roles/midproxy/files/plugins/frontends/ping_frontend.yaml b/roles/midproxy/files/plugins/frontends/ping_frontend.yaml new file mode 100644 index 000000000..c09b218b6 --- /dev/null +++ b/roles/midproxy/files/plugins/frontends/ping_frontend.yaml @@ -0,0 +1,3 @@ +module: satosa.frontends.ping.PingFrontend +name: ping +config: null diff --git a/roles/midproxy/files/plugins/frontends/saml2_frontend.yaml b/roles/midproxy/files/plugins/frontends/saml2_frontend.yaml new file mode 100644 index 000000000..059b5bc60 --- /dev/null +++ b/roles/midproxy/files/plugins/frontends/saml2_frontend.yaml @@ -0,0 +1,63 @@ +module: satosa.frontends.saml2.SAMLFrontend +name: idp +config: + #acr_mapping: + # "": "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" + # "https://accounts.google.com": "http://eidas.europa.eu/LoA/low" + + endpoints: + single_sign_on_service: + 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST': sso/post + 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect': sso/redirect + + # If configured and not false or empty the common domain cookie _saml_idp will be set + # with or have appended the IdP used for authentication. The default is not to set the + # cookie. If the value is a dictionary with key 'domain' then the domain for the cookie + # will be set to the value for the 'domain' key. If no 'domain' is set then the domain + # from the BASE defined for the proxy will be used. + #common_domain_cookie: + # domain: .example.com + + entityid_endpoint: true + enable_metadata_reload: no + + idp_config: + organization: {display_name: SURF, name: SURF, url: 'https://www.surf.nl/'} + contact_person: + - {contact_type: technical, email_address: 'mailto:sram-beheer@surf.nl', given_name: Technical} + - {contact_type: support, email_address: 'mailto:sram-beheer@surf.nl', given_name: Support} + - {contact_type: other, email_address: 'mailto:sram-beheer@surf.nl', given_name: Security, extension_attributes: {'xmlns:remd': 'http://refeds.org/metadata', 'remd:contactType': 'http://refeds.org/metadata/contactType/security'}} + key_file: frontend.key + cert_file: frontend.crt + metadata: + # remote: + # - url: https://engine.test2.surfconext.nl/authentication/sp/metadata + # cert: null + local: [!ENV SATOSA_SP_METADATA] + entityid: //proxy.xml + accepted_time_diff: 60 + # attribute_map_dir: plugins/attribute-maps + service: + idp: + endpoints: + single_sign_on_service: [] + name: Proxy IdP + ui_info: + display_name: + - lang: en + text: "MyAccessID proxy" + description: + - lang: en + text: "MyAccessID proxy" + keywords: + - lang: en + text: ["MyAccessID", "proxy"] + name_id_format: ['urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'] + policy: + default: + fail_on_missing_requested: false + # name_form: urn:oasis:names:tc:SAML:2.0:attrname-format:basic + # attribute_restrictions: null + # lifetime: {minutes: 15} + # encrypt_assertion: false + # encrypted_advice_attributes: false diff --git a/roles/midproxy/files/plugins/microservices/static_attributes.yaml b/roles/midproxy/files/plugins/microservices/static_attributes.yaml new file mode 100644 index 000000000..72e25bb58 --- /dev/null +++ b/roles/midproxy/files/plugins/microservices/static_attributes.yaml @@ -0,0 +1,5 @@ +module: satosa.micro_services.attribute_modifications.AddStaticAttributes +name: AddAttributes +config: + static_attributes: + schachomeorganization: 'myaccessid.org' diff --git a/roles/midproxy/files/proxy_conf.yaml b/roles/midproxy/files/proxy_conf.yaml new file mode 100644 index 000000000..49594d6aa --- /dev/null +++ b/roles/midproxy/files/proxy_conf.yaml @@ -0,0 +1,73 @@ +# BASE: https://example.com +BASE: !ENV SATOSA_BASE + +COOKIE_STATE_NAME: "SATOSA_STATE" +CONTEXT_STATE_DELETE: yes +#STATE_ENCRYPTION_KEY: "asdASD123" + +cookies_samesite_compat: + - ["SATOSA_STATE", "SATOSA_STATE_LEGACY"] + +INTERNAL_ATTRIBUTES: "internal_attributes.yaml" + +BACKEND_MODULES: + - "plugins/backends/openid_backend.yaml" + +FRONTEND_MODULES: + - "plugins/frontends/saml2_frontend.yaml" + - "plugins/frontends/ping_frontend.yaml" + +MICRO_SERVICES: + - "plugins/microservices/static_attributes.yaml" + +LOGGING: + version: 1 + formatters: + simple: + format: "[%(asctime)s] [%(levelname)s] [%(name)s.%(funcName)s] %(message)s" + handlers: + stdout: + class: logging.StreamHandler + stream: "ext://sys.stdout" + level: INFO + formatter: simple + syslog: + class: logging.handlers.SysLogHandler + address: "/dev/log" + level: INFO + formatter: simple + debug_file: + class: logging.FileHandler + filename: satosa-debug.log + encoding: utf8 + level: INFO + formatter: simple + error_file: + class: logging.FileHandler + filename: satosa-error.log + encoding: utf8 + level: ERROR + formatter: simple + info_file: + class: logging.handlers.RotatingFileHandler + filename: satosa-info.log + encoding: utf8 + maxBytes: 10485760 # 10MB + backupCount: 20 + level: INFO + formatter: simple + loggers: + satosa: + level: INFO + saml2: + level: INFO + oidcendpoint: + level: INFO + pyop: + level: INFO + oic: + level: INFO + root: + level: INFO + handlers: + - stdout diff --git a/roles/midproxy/tasks/main.yml b/roles/midproxy/tasks/main.yml new file mode 100644 index 000000000..346f56e6e --- /dev/null +++ b/roles/midproxy/tasks/main.yml @@ -0,0 +1,58 @@ +--- +- name: Create directory to keep configfile + ansible.builtin.file: + dest: "/opt/sram/midproxy" + state: directory + owner: 1000 + group: 1000 + mode: "0770" + +- name: Copy EB SP metadata + ansible.builtin.copy: + src: "{{ inventory_dir }}/files/midproxy/{{ midproxy.sp_metadata }}" + dest: "/opt/sram/midproxy/{{ midproxy.sp_metadata }}" + owner: 1000 + group: 1000 + mode: "0740" + +- name: Copy SATOSA conf files + ansible.builtin.copy: + src: "{{ item }}" + dest: "/opt/sram/midproxy/{{ item }}" + owner: 1000 + group: 1000 + with_items: + - internal_attributes.yaml + - proxy_conf.yaml + - plugins/ + +- name: Create the SATOSA container + community.docker.docker_container: + name: midproxy + image: satosa:{{ midproxy.satosa_version }} + pull: true + restart_policy: "always" + state: started + networks: + - name: "loadbalancer" + env: + SATOSA_BASE: 'https://midproxy.{{ openconextaccess_base_domain }}' + SATOSA_STATE_ENCRYPTION_KEY: '{{ midproxy_state_encryption_key }}' + SATOSA_SP_METADATA: '{{ midproxy.sp_metadata }}' + SATOSA_ISSUER: '{{ midproxy.issuer }}' + SATOSA_CLIENT_ID: '{{ midproxy_client_id }}' + SATOSA_CLIENT_SECRET: '{{ midproxy_client_secret }}' + volumes: + - /opt/sram/midproxy:/etc/satosa + labels: + traefik.http.routers.midproxy.rule: "Host(`midproxy.{{ openconextaccess_base_domain }}`)" + traefik.http.routers.midproxy.tls: "true" + traefik.enable: "true" + # curl is not availavble in the minimized satosa image + # so this healthcheck won't work + # healthcheck: + # test: ["CMD", "curl", "--fail" , "http://localhost" ] + # interval: 10s + # timeout: 10s + # retries: 3 + # start_period: 10s