From 6a1fe4532a27576f707f51cec102b0c51fb0a0b9 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Mon, 28 Sep 2020 13:57:04 +0200 Subject: [PATCH 01/64] add sample shibboleth conf --- auth/shibboleth-conf/shibboleth2.xml | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 auth/shibboleth-conf/shibboleth2.xml diff --git a/auth/shibboleth-conf/shibboleth2.xml b/auth/shibboleth-conf/shibboleth2.xml new file mode 100644 index 00000000..342e057e --- /dev/null +++ b/auth/shibboleth-conf/shibboleth2.xml @@ -0,0 +1,37 @@ + + + + + +SAML2 + +SAML2 Local + + + + + + + + + + + + + + + + \ No newline at end of file -- GitLab From cdd1801bf29be506d819686520604c6cad126a1c Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Mon, 28 Sep 2020 14:10:17 +0200 Subject: [PATCH 02/64] add WIP auth folder structure --- auth/Dockerfile | 5 + auth/etc-httpd/conf.d/sp.conf | 15 +++ auth/index.html | 10 ++ auth/shibboleth-conf/attribute-map.xml | 5 + auth/shibboleth-conf/idp-metadata.xml | 122 +++++++++++++++++++++++++ auth/shibboleth-conf/shibd.logger | 76 +++++++++++++++ 6 files changed, 233 insertions(+) create mode 100644 auth/Dockerfile create mode 100644 auth/etc-httpd/conf.d/sp.conf create mode 100644 auth/index.html create mode 100644 auth/shibboleth-conf/attribute-map.xml create mode 100644 auth/shibboleth-conf/idp-metadata.xml create mode 100644 auth/shibboleth-conf/shibd.logger diff --git a/auth/Dockerfile b/auth/Dockerfile new file mode 100644 index 00000000..896601fb --- /dev/null +++ b/auth/Dockerfile @@ -0,0 +1,5 @@ +FROM unicon/shibboleth-sp:3.0.4 + +COPY shibboleth-conf /etc/shibboleth/ +COPY index.html /var/www/html/ +COPY etc-httpd/ /etc/httpd/ diff --git a/auth/etc-httpd/conf.d/sp.conf b/auth/etc-httpd/conf.d/sp.conf new file mode 100644 index 00000000..92bbe24a --- /dev/null +++ b/auth/etc-httpd/conf.d/sp.conf @@ -0,0 +1,15 @@ +ServerName idptestbed + + + ServerName https://idptestbed:443 + UseCanonicalName On + + DocumentRoot "/var/www/html" + + + AuthType shibboleth + ShibRequestSetting requireSession 1 + require shib-session + + + \ No newline at end of file diff --git a/auth/index.html b/auth/index.html new file mode 100644 index 00000000..7d20ce72 --- /dev/null +++ b/auth/index.html @@ -0,0 +1,10 @@ + + + + + APACHE TEST + + +

TESTING APACHE

+ + diff --git a/auth/shibboleth-conf/attribute-map.xml b/auth/shibboleth-conf/attribute-map.xml new file mode 100644 index 00000000..e9e9797a --- /dev/null +++ b/auth/shibboleth-conf/attribute-map.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/auth/shibboleth-conf/idp-metadata.xml b/auth/shibboleth-conf/idp-metadata.xml new file mode 100644 index 00000000..caa418c0 --- /dev/null +++ b/auth/shibboleth-conf/idp-metadata.xml @@ -0,0 +1,122 @@ + + + + + + + + + samltest.id + + + + SAMLtest IdP + A free and basic IdP for testing SAML deployments + https://samltest.id/saml/logo.png + + + + + + + +MIIDETCCAfmgAwIBAgIUZRpDhkNKl5eWtJqk0Bu1BgTTargwDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwHhcNMTgwODI0MjExNDEwWhcNMzgw +ODI0MjExNDEwWjAWMRQwEgYDVQQDDAtzYW1sdGVzdC5pZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAJrh9/PcDsiv3UeL8Iv9rf4WfLPxuOm9W6aCntEA +8l6c1LQ1Zyrz+Xa/40ZgP29ENf3oKKbPCzDcc6zooHMji2fBmgXp6Li3fQUzu7yd ++nIC2teejijVtrNLjn1WUTwmqjLtuzrKC/ePoZyIRjpoUxyEMJopAd4dJmAcCq/K +k2eYX9GYRlqvIjLFoGNgy2R4dWwAKwljyh6pdnPUgyO/WjRDrqUBRFrLQJorR2kD +c4seZUbmpZZfp4MjmWMDgyGM1ZnR0XvNLtYeWAyt0KkSvFoOMjZUeVK/4xR74F8e +8ToPqLmZEg9ZUx+4z2KjVK00LpdRkH9Uxhh03RQ0FabHW6UCAwEAAaNXMFUwHQYD +VR0OBBYEFJDbe6uSmYQScxpVJhmt7PsCG4IeMDQGA1UdEQQtMCuCC3NhbWx0ZXN0 +LmlkhhxodHRwczovL3NhbWx0ZXN0LmlkL3NhbWwvaWRwMA0GCSqGSIb3DQEBCwUA +A4IBAQBNcF3zkw/g51q26uxgyuy4gQwnSr01Mhvix3Dj/Gak4tc4XwvxUdLQq+jC +cxr2Pie96klWhY/v/JiHDU2FJo9/VWxmc/YOk83whvNd7mWaNMUsX3xGv6AlZtCO +L3JhCpHjiN+kBcMgS5jrtGgV1Lz3/1zpGxykdvS0B4sPnFOcaCwHe2B9SOCWbDAN +JXpTjz1DmJO4ImyWPJpN1xsYKtm67Pefxmn0ax0uE2uuzq25h0xbTkqIQgJzyoE/ +DPkBFK1vDkMfAW11dQ0BXatEnW7Gtkc0lh2/PIbHWj4AzxYMyBf5Gy6HSVOftwjC +voQR2qr2xJBixsg+MIORKtmKHLfU + + + + + + + + + +MIIDEjCCAfqgAwIBAgIVAMECQ1tjghafm5OxWDh9hwZfxthWMA0GCSqGSIb3DQEB +CwUAMBYxFDASBgNVBAMMC3NhbWx0ZXN0LmlkMB4XDTE4MDgyNDIxMTQwOVoXDTM4 +MDgyNDIxMTQwOVowFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC0Z4QX1NFKs71ufbQwoQoW7qkNAJRIANGA4iM0 +ThYghul3pC+FwrGv37aTxWXfA1UG9njKbbDreiDAZKngCgyjxj0uJ4lArgkr4AOE +jj5zXA81uGHARfUBctvQcsZpBIxDOvUUImAl+3NqLgMGF2fktxMG7kX3GEVNc1kl +bN3dfYsaw5dUrw25DheL9np7G/+28GwHPvLb4aptOiONbCaVvh9UMHEA9F7c0zfF +/cL5fOpdVa54wTI0u12CsFKt78h6lEGG5jUs/qX9clZncJM7EFkN3imPPy+0HC8n +spXiH/MZW8o2cqWRkrw3MzBZW3Ojk5nQj40V6NUbjb7kfejzAgMBAAGjVzBVMB0G +A1UdDgQWBBQT6Y9J3Tw/hOGc8PNV7JEE4k2ZNTA0BgNVHREELTArggtzYW1sdGVz +dC5pZIYcaHR0cHM6Ly9zYW1sdGVzdC5pZC9zYW1sL2lkcDANBgkqhkiG9w0BAQsF +AAOCAQEASk3guKfTkVhEaIVvxEPNR2w3vWt3fwmwJCccW98XXLWgNbu3YaMb2RSn +7Th4p3h+mfyk2don6au7Uyzc1Jd39RNv80TG5iQoxfCgphy1FYmmdaSfO8wvDtHT +TNiLArAxOYtzfYbzb5QrNNH/gQEN8RJaEf/g/1GTw9x/103dSMK0RXtl+fRs2nbl +D1JJKSQ3AdhxK/weP3aUPtLxVVJ9wMOQOfcy02l+hHMb6uAjsPOpOVKqi3M8XmcU +ZOpx4swtgGdeoSpeRyrtMvRwdcciNBp9UZome44qZAYH1iqrpmmjsfI9pJItsgWu +3kXPjhSfj1AJGR1l9JGvJrHki1iHTA== + + + + + + + + + +MIIDEjCCAfqgAwIBAgIVAPVbodo8Su7/BaHXUHykx0Pi5CFaMA0GCSqGSIb3DQEB +CwUAMBYxFDASBgNVBAMMC3NhbWx0ZXN0LmlkMB4XDTE4MDgyNDIxMTQwOVoXDTM4 +MDgyNDIxMTQwOVowFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCQb+1a7uDdTTBBFfwOUun3IQ9nEuKM98SmJDWa +MwM877elswKUTIBVh5gB2RIXAPZt7J/KGqypmgw9UNXFnoslpeZbA9fcAqqu28Z4 +sSb2YSajV1ZgEYPUKvXwQEmLWN6aDhkn8HnEZNrmeXihTFdyr7wjsLj0JpQ+VUlc +4/J+hNuU7rGYZ1rKY8AA34qDVd4DiJ+DXW2PESfOu8lJSOteEaNtbmnvH8KlwkDs +1NvPTsI0W/m4SK0UdXo6LLaV8saIpJfnkVC/FwpBolBrRC/Em64UlBsRZm2T89ca +uzDee2yPUvbBd5kLErw+sC7i4xXa2rGmsQLYcBPhsRwnmBmlAgMBAAGjVzBVMB0G +A1UdDgQWBBRZ3exEu6rCwRe5C7f5QrPcAKRPUjA0BgNVHREELTArggtzYW1sdGVz +dC5pZIYcaHR0cHM6Ly9zYW1sdGVzdC5pZC9zYW1sL2lkcDANBgkqhkiG9w0BAQsF +AAOCAQEABZDFRNtcbvIRmblnZItoWCFhVUlq81ceSQddLYs8DqK340//hWNAbYdj +WcP85HhIZnrw6NGCO4bUipxZXhiqTA/A9d1BUll0vYB8qckYDEdPDduYCOYemKkD +dmnHMQWs9Y6zWiYuNKEJ9mf3+1N8knN/PK0TYVjVjXAf2CnOETDbLtlj6Nqb8La3 +sQkYmU+aUdopbjd5JFFwbZRaj6KiHXHtnIRgu8sUXNPrgipUgZUOVhP0C0N5OfE4 +JW8ZBrKgQC/6vJ2rSa9TlzI6JAa5Ww7gMXMP9M+cJUNQklcq+SBnTK8G+uBHgPKR +zBDsMIEzRtQZm4GIoHJae4zmnCekkQ== + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/shibboleth-conf/shibd.logger b/auth/shibboleth-conf/shibd.logger new file mode 100644 index 00000000..e9526645 --- /dev/null +++ b/auth/shibboleth-conf/shibd.logger @@ -0,0 +1,76 @@ +# set overall behavior +log4j.rootCategory=INFO, shibd_log, warn_log + +# fairly verbose for DEBUG, so generally leave at INFO +log4j.category.XMLTooling.XMLObject=INFO +log4j.category.XMLTooling.KeyInfoResolver=INFO +log4j.category.Shibboleth.IPRange=INFO +log4j.category.Shibboleth.PropertySet=INFO + +# raise for low-level tracing of SOAP client HTTP/SSL behavior +log4j.category.XMLTooling.libcurl=INFO + +# useful categories to tune independently: +# +# tracing of SAML messages and security policies +#log4j.category.OpenSAML.MessageDecoder=DEBUG +#log4j.category.OpenSAML.MessageEncoder=DEBUG +#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG +#log4j.category.XMLTooling.SOAPClient=DEBUG +# interprocess message remoting +#log4j.category.Shibboleth.Listener=DEBUG +# mapping of requests to applicationId +#log4j.category.Shibboleth.RequestMapper=DEBUG +# high level session cache operations +#log4j.category.Shibboleth.SessionCache=DEBUG +# persistent storage and caching +#log4j.category.XMLTooling.StorageService=DEBUG + +# logs XML being signed or verified if set to DEBUG +log4j.category.XMLTooling.Signature.Debugger=INFO, sig_log +log4j.additivity.XMLTooling.Signature.Debugger=false +log4j.ownAppenders.XMLTooling.Signature.Debugger=true + +# the tran log blocks the "default" appender(s) at runtime +# Level should be left at INFO for this category +log4j.category.Shibboleth-TRANSACTION=INFO, tran_log +log4j.additivity.Shibboleth-TRANSACTION=false +log4j.ownAppenders.Shibboleth-TRANSACTION=true + +# uncomment to suppress particular event types +#log4j.category.Shibboleth-TRANSACTION.AuthnRequest=WARN +#log4j.category.Shibboleth-TRANSACTION.Login=WARN +#log4j.category.Shibboleth-TRANSACTION.Logout=WARN + +# define the appenders + +log4j.appender.shibd_log=org.apache.log4j.RollingFileAppender +log4j.appender.shibd_log.fileName=/dev/stdout +log4j.appender.shibd_log.maxFileSize=0 +log4j.appender.shibd_log.maxBackupIndex=0 +log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout +log4j.appender.shibd_log.layout.ConversionPattern=sp-shibd %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n + +#log4j.appender.warn_log=org.apache.log4j.RollingFileAppender +#log4j.appender.warn_log.fileName=/var/log/shibboleth/shibd_warn.log +#log4j.appender.warn_log.maxFileSize=0 +#log4j.appender.warn_log.maxBackupIndex=0 +#log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout +#log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n +#log4j.appender.warn_log.threshold=WARN + +log4j.appender.tran_log=org.apache.log4j.RollingFileAppender +log4j.appender.tran_log.fileName=/dev/stdout +log4j.appender.tran_log.maxFileSize=0 +log4j.appender.tran_log.maxBackupIndex=0 +log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout +log4j.appender.tran_log.layout.ConversionPattern=sp-transaction %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n + +log4j.appender.sig_log=org.apache.log4j.FileAppender +log4j.appender.sig_log.fileName=/dev/stdout +log4j.appender.sig_log.maxFileSize=0 +log4j.appender.sig_log.maxBackupIndex=0 +log4j.appender.sig_log.layout=org.apache.log4j.PatternLayout +log4j.appender.sig_log.layout.ConversionPattern=sp-signature %m + + -- GitLab From d37d1818f35d4fef86e6d746f3a8a5f2e37aabc6 Mon Sep 17 00:00:00 2001 From: Fabian Schindler Date: Mon, 28 Sep 2020 16:21:57 +0200 Subject: [PATCH 03/64] Adding auth forwarding in preparation of shibboleth auth --- docker-compose.dem.ops.yml | 12 ++++++++++++ docker-compose.emg.ops.yml | 12 ++++++++++++ docker-compose.vhr18.ops.yml | 16 ++++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index b1f09109..345ea97b 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -32,6 +32,10 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -74,6 +78,10 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" @@ -114,6 +122,10 @@ services: - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-client-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-client.loadbalancer.sticky=false" - "traefik.http.services.dem-client.loadbalancer.server.port=80" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index fcc054e6..34a0dc82 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -32,6 +32,10 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -74,6 +78,10 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" @@ -114,6 +122,10 @@ services: - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-client.loadbalancer.sticky=false" - "traefik.http.services.emg-client.loadbalancer.server.port=80" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index e8665d49..068238d2 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -33,6 +33,10 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -74,6 +78,10 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" @@ -97,7 +105,7 @@ services: replicas: 0 placement: constraints: - - node.labels.type == internal + - node.labels.type == internal client: configs: - source: client-ops @@ -114,6 +122,10 @@ services: - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" + # Auth forwarding + - "traefik.frontend.auth.forward.address=http://auth/auth" + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-client.loadbalancer.sticky=false" - "traefik.http.services.vhr18-client.loadbalancer.server.port=80" @@ -122,7 +134,7 @@ services: - "traefik.enable=true" placement: constraints: - - node.labels.type == external + - node.labels.type == external networks: - extnet preprocessor: -- GitLab From 3f73c73529e8bbcdc552b1f7a0e53d255459465b Mon Sep 17 00:00:00 2001 From: Fabian Schindler Date: Mon, 28 Sep 2020 18:04:30 +0200 Subject: [PATCH 04/64] Fixing auth forwarding using correct labels Setup of middleware in traefik-dynamic.yml --- docker-compose.dem.ops.yml | 18 +++--------------- docker-compose.emg.ops.yml | 18 +++--------------- docker-compose.vhr18.ops.yml | 18 +++--------------- traefik-dynamic.yml | 4 ++++ 4 files changed, 13 insertions(+), 45 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 345ea97b..57d7b33e 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.dem-renderer.tls=true" - "traefik.http.routers.dem-renderer.tls.certresolver=default" - "traefik.http.routers.dem-renderer.entrypoints=https" @@ -32,10 +32,6 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -60,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.dem-cache.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.dem-cache.tls=true" - "traefik.http.routers.dem-cache.tls.certresolver=default" - "traefik.http.routers.dem-cache.entrypoints=https" @@ -78,10 +74,6 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" @@ -114,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-client.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file,shibAuth@file" - "traefik.http.routers.dem-client.tls=true" - "traefik.http.routers.dem-client.tls.certresolver=default" - "traefik.http.routers.dem-client.entrypoints=https" @@ -122,10 +114,6 @@ services: - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-client-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.dem-client.loadbalancer.sticky=false" - "traefik.http.services.dem-client.loadbalancer.server.port=80" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 34a0dc82..46852d3f 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.emg-renderer.tls=true" - "traefik.http.routers.emg-renderer.tls.certresolver=default" - "traefik.http.routers.emg-renderer.entrypoints=https" @@ -32,10 +32,6 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -60,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.emg-cache.tls=true" - "traefik.http.routers.emg-cache.tls.certresolver=default" - "traefik.http.routers.emg-cache.entrypoints=https" @@ -78,10 +74,6 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" @@ -114,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file,shibAuth@file" - "traefik.http.routers.emg-client.tls=true" - "traefik.http.routers.emg-client.tls.certresolver=default" - "traefik.http.routers.emg-client.entrypoints=https" @@ -122,10 +114,6 @@ services: - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.emg-client.loadbalancer.sticky=false" - "traefik.http.services.emg-client.loadbalancer.server.port=80" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 068238d2..76a5948b 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -15,7 +15,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.vhr18-renderer.tls=true" - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - "traefik.http.routers.vhr18-renderer.entrypoints=https" @@ -33,10 +33,6 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -60,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" - "traefik.http.routers.vhr18-cache.tls=true" - "traefik.http.routers.vhr18-cache.tls.certresolver=default" - "traefik.http.routers.vhr18-cache.entrypoints=https" @@ -78,10 +74,6 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" @@ -114,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-client.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - - "traefik.http.routers.vhr18-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.vhr18-client.middlewares=auth@file,compress@file,shibAuth@file" - "traefik.http.routers.vhr18-client.tls=true" - "traefik.http.routers.vhr18-client.tls.certresolver=default" - "traefik.http.routers.vhr18-client.entrypoints=https" @@ -122,10 +114,6 @@ services: - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" - # Auth forwarding - - "traefik.frontend.auth.forward.address=http://auth/auth" - - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User - - traefik.frontend.auth.forward.trustForwardHeader=true # general - "traefik.http.services.vhr18-client.loadbalancer.sticky=false" - "traefik.http.services.vhr18-client.loadbalancer.server.port=80" diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 87f49816..0291f929 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -20,6 +20,10 @@ http: realm: "PRISM View Server (PVS)" users: - "***REMOVED***" + shibAuth: + forwardAuth: + address: http://auth/auth + trustForwardHeader: true compress: compress: {} redirect: -- GitLab From 762e143b7077b58f171cdc465843b5c465636ff7 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 11:08:10 +0200 Subject: [PATCH 05/64] rename folders --- auth/Dockerfile | 5 - auth/shibboleth-conf/shibboleth2.xml | 37 ------ shibauth/Dockerfile | 39 ++++++ {auth/etc-httpd => shibauth}/conf.d/sp.conf | 4 + {auth => shibauth}/index.html | 0 .../shibboleth-conf/attribute-map.xml | 0 .../shibboleth-conf/idp-metadata.xml | 0 shibauth/shibboleth-conf/shibboleth2.xml | 125 ++++++++++++++++++ .../shibboleth-conf/shibd.logger | 0 9 files changed, 168 insertions(+), 42 deletions(-) delete mode 100644 auth/Dockerfile delete mode 100644 auth/shibboleth-conf/shibboleth2.xml create mode 100644 shibauth/Dockerfile rename {auth/etc-httpd => shibauth}/conf.d/sp.conf (73%) rename {auth => shibauth}/index.html (100%) rename {auth => shibauth}/shibboleth-conf/attribute-map.xml (100%) rename {auth => shibauth}/shibboleth-conf/idp-metadata.xml (100%) create mode 100644 shibauth/shibboleth-conf/shibboleth2.xml rename {auth => shibauth}/shibboleth-conf/shibd.logger (100%) diff --git a/auth/Dockerfile b/auth/Dockerfile deleted file mode 100644 index 896601fb..00000000 --- a/auth/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM unicon/shibboleth-sp:3.0.4 - -COPY shibboleth-conf /etc/shibboleth/ -COPY index.html /var/www/html/ -COPY etc-httpd/ /etc/httpd/ diff --git a/auth/shibboleth-conf/shibboleth2.xml b/auth/shibboleth-conf/shibboleth2.xml deleted file mode 100644 index 342e057e..00000000 --- a/auth/shibboleth-conf/shibboleth2.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - -SAML2 - -SAML2 Local - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile new file mode 100644 index 00000000..a1c6d766 --- /dev/null +++ b/shibauth/Dockerfile @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Project: prism view server +# Authors: Stephan Meissl +# +#------------------------------------------------------------------------------ +# Copyright (C) 2020 EOX IT Services GmbH +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies of this Software or works derived from this Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +#----------------------------------------------------------------------------- + +FROM unicon/shibboleth-sp:3.0.4 + +MAINTAINER EOX +LABEL name="prism view server cache" \ + vendor="EOX IT Services GmbH " \ + license="MIT Copyright (C) 2019 EOX IT Services GmbH " \ + type="prism view server shibauth" \ + version="0.0.1" + +COPY shibboleth-conf /etc/shibboleth/ +COPY index.html /var/www/html/ +COPY conf.d /etc/httpd/etc-httpd/ diff --git a/auth/etc-httpd/conf.d/sp.conf b/shibauth/conf.d/sp.conf similarity index 73% rename from auth/etc-httpd/conf.d/sp.conf rename to shibauth/conf.d/sp.conf index 92bbe24a..091f85e9 100644 --- a/auth/etc-httpd/conf.d/sp.conf +++ b/shibauth/conf.d/sp.conf @@ -5,6 +5,10 @@ ServerName idptestbed UseCanonicalName On DocumentRoot "/var/www/html" + + Satisfy Any + Allow from all + AuthType shibboleth diff --git a/auth/index.html b/shibauth/index.html similarity index 100% rename from auth/index.html rename to shibauth/index.html diff --git a/auth/shibboleth-conf/attribute-map.xml b/shibauth/shibboleth-conf/attribute-map.xml similarity index 100% rename from auth/shibboleth-conf/attribute-map.xml rename to shibauth/shibboleth-conf/attribute-map.xml diff --git a/auth/shibboleth-conf/idp-metadata.xml b/shibauth/shibboleth-conf/idp-metadata.xml similarity index 100% rename from auth/shibboleth-conf/idp-metadata.xml rename to shibauth/shibboleth-conf/idp-metadata.xml diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml new file mode 100644 index 00000000..f890b39c --- /dev/null +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + SAML2 SAML1 + + + + SAML2 Local + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/shibboleth-conf/shibd.logger b/shibauth/shibboleth-conf/shibd.logger similarity index 100% rename from auth/shibboleth-conf/shibd.logger rename to shibauth/shibboleth-conf/shibd.logger -- GitLab From 70c6543feef529e295dd0698f9c8dda0343bac5e Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 13:25:29 +0200 Subject: [PATCH 06/64] add shib testing stack for now --- docker-compose.test.ops.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docker-compose.test.ops.yml diff --git a/docker-compose.test.ops.yml b/docker-compose.test.ops.yml new file mode 100644 index 00000000..69f4143b --- /dev/null +++ b/docker-compose.test.ops.yml @@ -0,0 +1,34 @@ +version: "3.6" +services: + shibauth: + image: testing-shibboleth + deploy: + placement: + constraints: [node.role == manager] + deploy: + labels: + # router for basic auth based access (https) + - "traefik.http.routers.emg-renderer.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file" + - "traefik.http.routers.emg-renderer.tls=true" + - "traefik.http.routers.emg-renderer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + # general + - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" + - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" + - "traefik.docker.network=shib-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + replicas: 1 + placement: + constraints: [node.role == manager] + networks: + - extnet +networks: + extnet: + name: shib-extnet + external: true -- GitLab From 5f1e9b004a836f5092d41dbb2168c0dc1a4593cf Mon Sep 17 00:00:00 2001 From: Fabian Schindler Date: Tue, 29 Sep 2020 16:35:47 +0200 Subject: [PATCH 07/64] Using {{slug}}-secure for shibboleth authed routes --- docker-compose.dem.ops.yml | 52 +++++++++++++++++++++++++++++++++++- docker-compose.emg.ops.yml | 50 ++++++++++++++++++++++++++++++++++ docker-compose.vhr18.ops.yml | 52 +++++++++++++++++++++++++++++++++++- 3 files changed, 152 insertions(+), 2 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 57d7b33e..a1f677ea 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file" - "traefik.http.routers.dem-renderer.tls=true" - "traefik.http.routers.dem-renderer.tls.certresolver=default" - "traefik.http.routers.dem-renderer.entrypoints=https" @@ -32,6 +32,26 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-renderer.tls=true" + - "traefik.http.routers.dem-renderer.tls.certresolver=default" + - "traefik.http.routers.dem-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.dem-renderer_referer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.dem-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.dem-renderer_referer.tls=true" + - "traefik.http.routers.dem-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.dem-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -74,6 +94,26 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-renderer.tls=true" + - "traefik.http.routers.dem-renderer.tls.certresolver=default" + - "traefik.http.routers.dem-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.dem-renderer_referer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.dem-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.dem-renderer_referer.tls=true" + - "traefik.http.routers.dem-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.dem-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" @@ -114,6 +154,16 @@ services: - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-client-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.dem-client.rule=Host(`dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`)" + - "traefik.http.routers.dem-client.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.dem-client.tls=true" + - "traefik.http.routers.dem-client.tls.certresolver=default" + - "traefik.http.routers.dem-client.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.dem-client-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`)" + - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-client-redirect.entrypoints=http" # general - "traefik.http.services.dem-client.loadbalancer.sticky=false" - "traefik.http.services.dem-client.loadbalancer.server.port=80" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 46852d3f..5d00a095 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -32,6 +32,26 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-renderer.tls=true" + - "traefik.http.routers.emg-renderer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.emg-renderer_referer.tls=true" + - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -74,6 +94,26 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-renderer.tls=true" + - "traefik.http.routers.emg-renderer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.emg-renderer_referer.tls=true" + - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" @@ -114,6 +154,16 @@ services: - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.emg-client.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.emg-client.tls=true" + - "traefik.http.routers.emg-client.tls.certresolver=default" + - "traefik.http.routers.emg-client.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-client-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-client-redirect.entrypoints=http" # general - "traefik.http.services.emg-client.loadbalancer.sticky=false" - "traefik.http.services.emg-client.loadbalancer.server.port=80" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 76a5948b..ee885d69 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -33,6 +33,26 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-renderer.tls=true" + - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.vhr18-renderer_referer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.vhr18-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer_referer.tls=true" + - "traefik.http.routers.vhr18-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -74,6 +94,26 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" + # router for shibboleth based auth based access (https) + - "traefik.http.routers.vhr18-cache-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-cache-renderer.tls=true" + - "traefik.http.routers.vhr18-cache-renderer.tls.certresolver=default" + - "traefik.http.routers.vhr18-cache-renderer.entrypoints=https" + # router for shibboleth shibboleth auth based access (http) + - "traefik.http.routers.vhr18-cache-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-cache-renderer-redirect.entrypoints=http" + # router for referrer shibboleth based access (https) + - "traefik.http.routers.vhr18-cache-renderer_referer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.vhr18-cache-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.vhr18-cache-renderer_referer.tls=true" + - "traefik.http.routers.vhr18-cache-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.vhr18-cache-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" + - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" @@ -106,7 +146,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-client.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - - "traefik.http.routers.vhr18-client.middlewares=auth@file,compress@file,shibAuth@file" + - "traefik.http.routers.vhr18-client.middlewares=auth@file,compress@file" - "traefik.http.routers.vhr18-client.tls=true" - "traefik.http.routers.vhr18-client.tls.certresolver=default" - "traefik.http.routers.vhr18-client.entrypoints=https" @@ -114,6 +154,16 @@ services: - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.vhr18-client.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.vhr18-client.tls=true" + - "traefik.http.routers.vhr18-client.tls.certresolver=default" + - "traefik.http.routers.vhr18-client.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-client.loadbalancer.sticky=false" - "traefik.http.services.vhr18-client.loadbalancer.server.port=80" -- GitLab From 9a613a3ed1e598d1f360e37da4d04c66f4e5a961 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 16:42:03 +0200 Subject: [PATCH 08/64] save temp --- shibauth/Dockerfile | 3 +- .../sp.conf => etc-httpd/conf.d/shib.conf} | 4 +- shibauth/shibboleth-conf/idp-metadata.xml | 24 --- shibauth/shibboleth-conf/shibboleth2.xml | 104 +------------ shibauth/shibboleth-conf/sp-metadata.xml | 141 ++++++++++++++++++ 5 files changed, 150 insertions(+), 126 deletions(-) rename shibauth/{conf.d/sp.conf => etc-httpd/conf.d/shib.conf} (78%) create mode 100644 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile index a1c6d766..986fbddc 100644 --- a/shibauth/Dockerfile +++ b/shibauth/Dockerfile @@ -35,5 +35,6 @@ LABEL name="prism view server cache" \ version="0.0.1" COPY shibboleth-conf /etc/shibboleth/ +COPY etc-httpd/ /etc/httpd/ COPY index.html /var/www/html/ -COPY conf.d /etc/httpd/etc-httpd/ + diff --git a/shibauth/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/shib.conf similarity index 78% rename from shibauth/conf.d/sp.conf rename to shibauth/etc-httpd/conf.d/shib.conf index 091f85e9..58a46d86 100644 --- a/shibauth/conf.d/sp.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -1,7 +1,7 @@ -ServerName idptestbed +ServerName shib-testing - ServerName https://idptestbed:443 + ServerName http://shib.pdas.prism.eox.at UseCanonicalName On DocumentRoot "/var/www/html" diff --git a/shibauth/shibboleth-conf/idp-metadata.xml b/shibauth/shibboleth-conf/idp-metadata.xml index caa418c0..6a91356a 100644 --- a/shibauth/shibboleth-conf/idp-metadata.xml +++ b/shibauth/shibboleth-conf/idp-metadata.xml @@ -1,18 +1,8 @@ - - - - samltest.id - - SAMLtest IdP A free and basic IdP for testing SAML deployments @@ -44,7 +34,6 @@ voQR2qr2xJBixsg+MIORKtmKHLfU - @@ -70,7 +59,6 @@ ZOpx4swtgGdeoSpeRyrtMvRwdcciNBp9UZome44qZAYH1iqrpmmjsfI9pJItsgWu - @@ -96,27 +84,15 @@ zBDsMIEzRtQZm4GIoHJae4zmnCekkQ== - - - - - - - - - - \ No newline at end of file diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index f890b39c..2769ec5f 100644 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -4,122 +4,28 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" clockSkew="180"> - - - - - - - - - - - SAML2 SAML1 - - SAML2 Local - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - + - - - - \ No newline at end of file diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml new file mode 100644 index 00000000..bfa4da80 --- /dev/null +++ b/shibauth/shibboleth-conf/sp-metadata.xml @@ -0,0 +1,141 @@ + + + + + + + +MIIHijCCBnKgAwIBAgIQPWbuJob/1pRBDBHQrAelKDANBgkqhkiG9w0BAQsFADB4 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJjAkBgNVBAMTHVN0YXJ0 +Q29tIENsYXNzIDMgT1YgU2VydmVyIENBMB4XDTE2MDUzMDIwMjAwNFoXDTE5MDUz +MDIwMjAwNFowZDELMAkGA1UEBhMCQVQxDTALBgNVBAgMBFdpZW4xDTALBgNVBAcM +BFdpZW4xHTAbBgNVBAoMFEVPWCBJVCBTZXJ2aWNlcyBHbWJIMRgwFgYDVQQDDA9l +c2EubWFwcy5lb3guYXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCX +GBReYwFVvkSrourZRd4zBBlo9apZHXxt+kk4bNbk1n70YNeFUaxJpwFQqkfwghrg +9tctD2B9HLDZl+LMnO6IXAzXkn8OHzt9vf4lVLDYOSHcC/oAt4aQjr98Anl1q822 +/FJ6csFtFAmEIg8P6NHByHlwaSM1yxcrc7ZgR+xph0/sQijh4jxOlcNfCGRy0VBt +lJE0rLSAmIN/LUX/hf1P4psbPlXNLl1U3Du6sh+pkgWV5gsKJBxAYJvptlahn9Ud +b6FBFngM/Z9rk/M4R692z5WWLwfxFScEw3/FfF9aH5ztCAM1u3L5QjqANcdbVl86 +x2kUXZh9A7EjUhnI25xu4aEVJBHTcq46rZQw88lW/+Xxavon03dHuaHhrZXMF5mD +rIGvumSlB1XzCz2lOQG4zrUnXtKw6rm7fr20Zn5KQEgiUD+d2Hs8lvkWmP0qKiP+ +EWdJrAfprv85tKqQMxldnrOK9FwH9TQh4TmhYlp+6vvsfZMZB4uDMlvKBtlI+7Yh +O61HKIDSsEqq6tdy312ENOjZVZsPsNkZCdOm6irTTymB9Id1LJ+3jv+lakPzluW/ +rTeq2S0UMMvByRsTGiI3ettxgOwo/jWAJiMTWb26ldpxHqyvOIX7b40Wvk+KRx9T +Vgx4kkuS5ycNi0YgUBs98imh8GXvBEufvpZCtcd5OQIDAQABo4IDIjCCAx4wDgYD +VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAJBgNV +HRMEAjAAMB0GA1UdDgQWBBRX3j8T9Ti5uurAxnFHSb/P6Q4Z9jAfBgNVHSMEGDAW +gBSxPxySe5KwWiWzOPucB6QmUDLjUTBvBggrBgEFBQcBAQRjMGEwJAYIKwYBBQUH +MAGGGGh0dHA6Ly9vY3NwLnN0YXJ0c3NsLmNvbTA5BggrBgEFBQcwAoYtaHR0cDov +L2FpYS5zdGFydHNzbC5jb20vY2VydHMvc2NhLnNlcnZlcjMuY3J0MDgGA1UdHwQx +MC8wLaAroCmGJ2h0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL3NjYS1zZXJ2ZXIzLmNy +bDB4BgNVHREEcTBvgg9lc2EubWFwcy5lb3guYXSCFXRpbGVzLmVzYS5tYXBzLmVv +eC5hdIIXKi50aWxlcy5lc2EubWFwcy5lb3guYXSCE29zbS5lc2EubWFwcy5lb3gu +YXSCF3N0YWdpbmcuZXNhLm1hcHMuZW94LmF0MCMGA1UdEgQcMBqGGGh0dHA6Ly93 +d3cuc3RhcnRzc2wuY29tLzBRBgNVHSAESjBIMAgGBmeBDAECAjA8BgsrBgEEAYG1 +NwECBTAtMCsGCCsGAQUFBwIBFh9odHRwczovL3d3dy5zdGFydHNzbC5jb20vcG9s +aWN5MIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYAaPaY+B9kgr46jO65KB1M/HFR +XWeT1ETRCmesu09P+8QAAAFVA3EKawAABAMARzBFAiAQMFKOGTFIZzbVuZ8R2C+u +4QgL0vnSOBT3ylGgjAf+AQIhAOHkMTkhr0APu8jaCkos4c9k8vrn5DWq0k8WXT12 +ip4fAHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFVA3EMcwAA +BAMARjBEAiASftiRTzUpe+IDonZidGHzHKlKwPZoaOE2zqsH1AW9jgIgM7Jmphm1 +rGkakcVooaUudEfCTN/fTJ7cs3kPiljWmkgwDQYJKoZIhvcNAQELBQADggEBAIp2 +QqqJ6+TRRr7cBeiMw+4MrQhbaf+Y0bAsPOF9KOnQ9JMavEki08JRLYLVSraqDW1+ +mrlk+mbvh9mEFkTIvwW5wt/S5tgbRE/fmDBTElRwLPVlvbwRNKNg/54lXhwgETM8 +oTOfxC+dK7bg+EFj3r71d7wf/qhPCBYmN9yk2z4tby1nYI6c+8xXVxnrKGIOOb/X +MAB1eHNvjMHHmhlSV33Z6nqrTzeUEDS5R6X1v3lCtP/058o6NDdLmJ/hTy/So5eB +8NwcilckyoYeI64QXg61KmH+9+scQ2bddWtuDJvnNo0NH1XPOuxl9HpaxBSzIflK +2Wfpr7x/2VCKeO7Mfpo= + + + + + + + + + + + + + + + + + + + + + + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + eox + EOX IT Services GmbH + http://eox.at + + -- GitLab From 46e407024f768335a05fafbf61a5738acfd02198 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 16:43:24 +0200 Subject: [PATCH 09/64] save temp --- shibauth/etc-httpd/conf.d/shib.conf | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf index 58a46d86..2c7d35d2 100644 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -1,19 +1,6 @@ -ServerName shib-testing - - - ServerName http://shib.pdas.prism.eox.at - UseCanonicalName On - - DocumentRoot "/var/www/html" - - Satisfy Any - Allow from all - - - - AuthType shibboleth - ShibRequestSetting requireSession 1 - require shib-session - - - \ No newline at end of file +ServerName shib.pdas.prism.eox.at +LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so + + SetHandler shib + +DocumentRoot "/var/www/html" \ No newline at end of file -- GitLab From e558d513682d3bd40ae303bacd819e25f23d0fc5 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 17:36:25 +0200 Subject: [PATCH 10/64] rename test routers, fix syntax compose --- docker-compose.test.ops.yml | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/docker-compose.test.ops.yml b/docker-compose.test.ops.yml index 69f4143b..df6bd812 100644 --- a/docker-compose.test.ops.yml +++ b/docker-compose.test.ops.yml @@ -2,24 +2,21 @@ version: "3.6" services: shibauth: image: testing-shibboleth - deploy: - placement: - constraints: [node.role == manager] deploy: labels: # router for basic auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`shib.pdas.prism.eox.at`)" - - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file" - - "traefik.http.routers.emg-renderer.tls=true" - - "traefik.http.routers.emg-renderer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer.entrypoints=https" + - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + - "traefik.http.routers.shibauth.tls=true" + - "traefik.http.routers.shibauth.tls.certresolver=default" + - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`shib.pdas.prism.eox.at`)" - - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general - - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" + - "traefik.http.services.shibauth.loadbalancer.sticky=false" + - "traefik.http.services.shibauth.loadbalancer.server.port=80" - "traefik.docker.network=shib-extnet" - "traefik.docker.lbswarm=true" - "traefik.enable=true" -- GitLab From a66a83f8630637692970a5e0bf8bc07a9a666c47 Mon Sep 17 00:00:00 2001 From: Fabian Schindler Date: Tue, 29 Sep 2020 17:51:08 +0200 Subject: [PATCH 11/64] Removing traefik rules for referrer based auth in URLs using shibboleth --- docker-compose.dem.ops.yml | 20 -------------------- docker-compose.emg.ops.yml | 20 -------------------- docker-compose.vhr18.ops.yml | 20 -------------------- 3 files changed, 60 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index a1f677ea..907564ca 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -42,16 +42,6 @@ services: - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.dem-renderer_referer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.dem-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.dem-renderer_referer.tls=true" - - "traefik.http.routers.dem-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.dem-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -104,16 +94,6 @@ services: - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.dem-renderer_referer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.dem-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.dem-renderer_referer.tls=true" - - "traefik.http.routers.dem-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.dem-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|dem-secure.pdas.prism.eox.at|dem-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 5d00a095..86fb801d 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -42,16 +42,6 @@ services: - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.emg-renderer_referer.tls=true" - - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -104,16 +94,6 @@ services: - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.emg-renderer_referer.tls=true" - - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg-secure.pdas.prism.eox.at|emg-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index ee885d69..4529ff57 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -43,16 +43,6 @@ services: - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.vhr18-renderer_referer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.vhr18-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.vhr18-renderer_referer.tls=true" - - "traefik.http.routers.vhr18-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.vhr18-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -104,16 +94,6 @@ services: - "traefik.http.routers.vhr18-cache-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-cache-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache-renderer-redirect.entrypoints=http" - # router for referrer shibboleth based access (https) - - "traefik.http.routers.vhr18-cache-renderer_referer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.vhr18-cache-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.vhr18-cache-renderer_referer.tls=true" - - "traefik.http.routers.vhr18-cache-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.vhr18-cache-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|vhr18-secure.pdas.prism.eox.at|vhr18-secure.pass.copernicus.eu)/?`)" - - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-cache-renderer_referer-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" -- GitLab From 0a384d51582e2e1134abe3b8887a7c3c37a433d0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 29 Sep 2020 20:49:09 +0200 Subject: [PATCH 12/64] update metadata to testing saml provider, still not working though --- shibauth/Dockerfile | 1 - shibauth/etc-httpd/conf.d/shib.conf | 6 ------ shibauth/etc-httpd/conf.d/sp.conf | 19 +++++++++++++++++++ shibauth/shibboleth-conf/shibboleth2.xml | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) delete mode 100644 shibauth/etc-httpd/conf.d/shib.conf create mode 100644 shibauth/etc-httpd/conf.d/sp.conf diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile index 986fbddc..3f278c26 100644 --- a/shibauth/Dockerfile +++ b/shibauth/Dockerfile @@ -37,4 +37,3 @@ LABEL name="prism view server cache" \ COPY shibboleth-conf /etc/shibboleth/ COPY etc-httpd/ /etc/httpd/ COPY index.html /var/www/html/ - diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf deleted file mode 100644 index 2c7d35d2..00000000 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ /dev/null @@ -1,6 +0,0 @@ -ServerName shib.pdas.prism.eox.at -LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so - - SetHandler shib - -DocumentRoot "/var/www/html" \ No newline at end of file diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf new file mode 100644 index 00000000..9de6cc7a --- /dev/null +++ b/shibauth/etc-httpd/conf.d/sp.conf @@ -0,0 +1,19 @@ +ServerName shib.pdas.prism.eox.at + + + ServerName https://shib.pdas.prism.eox.at:443 + UseCanonicalName On + + DocumentRoot "/var/www/html" + + + AuthType shibboleth + ShibRequestSetting requireSession 1 + require shib-session + + + + Satisfy Any + Allow from all + + \ No newline at end of file diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index 2769ec5f..8a916cfb 100644 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -8,7 +8,7 @@ REMOTE_USER="eppn uid persistent-id targeted-id"> - + SAML2 SAML1 SAML2 Local -- GitLab From c87648a08842d594521d683479306ddca04774fe Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 12:19:58 +0200 Subject: [PATCH 13/64] use http internally for handler, overwrite shib.conf completely, do not validate metadata --- shibauth/etc-httpd/conf.d/shib.conf | 13 +++++++++++++ shibauth/etc-httpd/conf.d/sp.conf | 19 ------------------- shibauth/shibboleth-conf/shibboleth2.xml | 10 +++++----- 3 files changed, 18 insertions(+), 24 deletions(-) create mode 100644 shibauth/etc-httpd/conf.d/shib.conf delete mode 100644 shibauth/etc-httpd/conf.d/sp.conf diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf new file mode 100644 index 00000000..758f387c --- /dev/null +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -0,0 +1,13 @@ +ServerName shib.pdas.prism.eox.at +LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so +ShibCompatValidUser Off +UseCanonicalName On + + SetHandler shib + + + + AuthType shibboleth + ShibRequestSetting requireSession 1 + require shib-session + diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf deleted file mode 100644 index 9de6cc7a..00000000 --- a/shibauth/etc-httpd/conf.d/sp.conf +++ /dev/null @@ -1,19 +0,0 @@ -ServerName shib.pdas.prism.eox.at - - - ServerName https://shib.pdas.prism.eox.at:443 - UseCanonicalName On - - DocumentRoot "/var/www/html" - - - AuthType shibboleth - ShibRequestSetting requireSession 1 - require shib-session - - - - Satisfy Any - Allow from all - - \ No newline at end of file diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index 8a916cfb..7bd47635 100644 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -4,22 +4,22 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" clockSkew="180"> - + checkAddress="false" handlerSSL="false" cookieProps="http"> - SAML2 SAML1 + SAML2 SAML2 Local - + - + -- GitLab From 26454276a31a90d2641b17e9d3a7ea1ef3183e4e Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 13:17:58 +0200 Subject: [PATCH 14/64] update config forwardauth url, remove not necessary files, add shibauth to base compose --- docker-compose.base.ops.yml | 28 +++++ shibauth/shibboleth-conf/shibd.logger | 76 ------------ shibauth/shibboleth-conf/sp-metadata.xml | 141 ----------------------- traefik-dynamic.yml | 2 +- 4 files changed, 29 insertions(+), 218 deletions(-) delete mode 100644 shibauth/shibboleth-conf/shibd.logger delete mode 100644 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index f29bcc7c..1aecaffa 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,6 +28,32 @@ services: - emg-extnet - dem-extnet - logging-extnet + - shibauth-extnet + shibauth: + image: testing-shibboleth + deploy: + # labels: + # # router for basic auth based access (https) + # - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" + # - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + # - "traefik.http.routers.shibauth.tls=true" + # - "traefik.http.routers.shibauth.tls.certresolver=default" + # - "traefik.http.routers.shibauth.entrypoints=https" + # # router for basic auth based access (http) + # - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" + # - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + # - "traefik.http.routers.shibauth-redirect.entrypoints=http" + # # general + # - "traefik.http.services.shibauth.loadbalancer.sticky=false" + # - "traefik.http.services.shibauth.loadbalancer.server.port=80" + # - "traefik.docker.network=shib-extnet" + # - "traefik.docker.lbswarm=true" + # - "traefik.enable=true" + replicas: 1 + placement: + constraints: [node.role == manager] + networks: + - shibauth-extnet volumes: traefik-data: networks: @@ -39,3 +65,5 @@ networks: name: dem-extnet logging-extnet: name: logging-extnet + shibauth-extnet: + name: shibauth-extnet diff --git a/shibauth/shibboleth-conf/shibd.logger b/shibauth/shibboleth-conf/shibd.logger deleted file mode 100644 index e9526645..00000000 --- a/shibauth/shibboleth-conf/shibd.logger +++ /dev/null @@ -1,76 +0,0 @@ -# set overall behavior -log4j.rootCategory=INFO, shibd_log, warn_log - -# fairly verbose for DEBUG, so generally leave at INFO -log4j.category.XMLTooling.XMLObject=INFO -log4j.category.XMLTooling.KeyInfoResolver=INFO -log4j.category.Shibboleth.IPRange=INFO -log4j.category.Shibboleth.PropertySet=INFO - -# raise for low-level tracing of SOAP client HTTP/SSL behavior -log4j.category.XMLTooling.libcurl=INFO - -# useful categories to tune independently: -# -# tracing of SAML messages and security policies -#log4j.category.OpenSAML.MessageDecoder=DEBUG -#log4j.category.OpenSAML.MessageEncoder=DEBUG -#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG -#log4j.category.XMLTooling.SOAPClient=DEBUG -# interprocess message remoting -#log4j.category.Shibboleth.Listener=DEBUG -# mapping of requests to applicationId -#log4j.category.Shibboleth.RequestMapper=DEBUG -# high level session cache operations -#log4j.category.Shibboleth.SessionCache=DEBUG -# persistent storage and caching -#log4j.category.XMLTooling.StorageService=DEBUG - -# logs XML being signed or verified if set to DEBUG -log4j.category.XMLTooling.Signature.Debugger=INFO, sig_log -log4j.additivity.XMLTooling.Signature.Debugger=false -log4j.ownAppenders.XMLTooling.Signature.Debugger=true - -# the tran log blocks the "default" appender(s) at runtime -# Level should be left at INFO for this category -log4j.category.Shibboleth-TRANSACTION=INFO, tran_log -log4j.additivity.Shibboleth-TRANSACTION=false -log4j.ownAppenders.Shibboleth-TRANSACTION=true - -# uncomment to suppress particular event types -#log4j.category.Shibboleth-TRANSACTION.AuthnRequest=WARN -#log4j.category.Shibboleth-TRANSACTION.Login=WARN -#log4j.category.Shibboleth-TRANSACTION.Logout=WARN - -# define the appenders - -log4j.appender.shibd_log=org.apache.log4j.RollingFileAppender -log4j.appender.shibd_log.fileName=/dev/stdout -log4j.appender.shibd_log.maxFileSize=0 -log4j.appender.shibd_log.maxBackupIndex=0 -log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout -log4j.appender.shibd_log.layout.ConversionPattern=sp-shibd %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n - -#log4j.appender.warn_log=org.apache.log4j.RollingFileAppender -#log4j.appender.warn_log.fileName=/var/log/shibboleth/shibd_warn.log -#log4j.appender.warn_log.maxFileSize=0 -#log4j.appender.warn_log.maxBackupIndex=0 -#log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout -#log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n -#log4j.appender.warn_log.threshold=WARN - -log4j.appender.tran_log=org.apache.log4j.RollingFileAppender -log4j.appender.tran_log.fileName=/dev/stdout -log4j.appender.tran_log.maxFileSize=0 -log4j.appender.tran_log.maxBackupIndex=0 -log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout -log4j.appender.tran_log.layout.ConversionPattern=sp-transaction %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n - -log4j.appender.sig_log=org.apache.log4j.FileAppender -log4j.appender.sig_log.fileName=/dev/stdout -log4j.appender.sig_log.maxFileSize=0 -log4j.appender.sig_log.maxBackupIndex=0 -log4j.appender.sig_log.layout=org.apache.log4j.PatternLayout -log4j.appender.sig_log.layout.ConversionPattern=sp-signature %m - - diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml deleted file mode 100644 index bfa4da80..00000000 --- a/shibauth/shibboleth-conf/sp-metadata.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - -MIIHijCCBnKgAwIBAgIQPWbuJob/1pRBDBHQrAelKDANBgkqhkiG9w0BAQsFADB4 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEpMCcGA1UECxMg -U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJjAkBgNVBAMTHVN0YXJ0 -Q29tIENsYXNzIDMgT1YgU2VydmVyIENBMB4XDTE2MDUzMDIwMjAwNFoXDTE5MDUz -MDIwMjAwNFowZDELMAkGA1UEBhMCQVQxDTALBgNVBAgMBFdpZW4xDTALBgNVBAcM -BFdpZW4xHTAbBgNVBAoMFEVPWCBJVCBTZXJ2aWNlcyBHbWJIMRgwFgYDVQQDDA9l -c2EubWFwcy5lb3guYXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCX -GBReYwFVvkSrourZRd4zBBlo9apZHXxt+kk4bNbk1n70YNeFUaxJpwFQqkfwghrg -9tctD2B9HLDZl+LMnO6IXAzXkn8OHzt9vf4lVLDYOSHcC/oAt4aQjr98Anl1q822 -/FJ6csFtFAmEIg8P6NHByHlwaSM1yxcrc7ZgR+xph0/sQijh4jxOlcNfCGRy0VBt -lJE0rLSAmIN/LUX/hf1P4psbPlXNLl1U3Du6sh+pkgWV5gsKJBxAYJvptlahn9Ud -b6FBFngM/Z9rk/M4R692z5WWLwfxFScEw3/FfF9aH5ztCAM1u3L5QjqANcdbVl86 -x2kUXZh9A7EjUhnI25xu4aEVJBHTcq46rZQw88lW/+Xxavon03dHuaHhrZXMF5mD -rIGvumSlB1XzCz2lOQG4zrUnXtKw6rm7fr20Zn5KQEgiUD+d2Hs8lvkWmP0qKiP+ -EWdJrAfprv85tKqQMxldnrOK9FwH9TQh4TmhYlp+6vvsfZMZB4uDMlvKBtlI+7Yh -O61HKIDSsEqq6tdy312ENOjZVZsPsNkZCdOm6irTTymB9Id1LJ+3jv+lakPzluW/ -rTeq2S0UMMvByRsTGiI3ettxgOwo/jWAJiMTWb26ldpxHqyvOIX7b40Wvk+KRx9T -Vgx4kkuS5ycNi0YgUBs98imh8GXvBEufvpZCtcd5OQIDAQABo4IDIjCCAx4wDgYD -VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAJBgNV -HRMEAjAAMB0GA1UdDgQWBBRX3j8T9Ti5uurAxnFHSb/P6Q4Z9jAfBgNVHSMEGDAW -gBSxPxySe5KwWiWzOPucB6QmUDLjUTBvBggrBgEFBQcBAQRjMGEwJAYIKwYBBQUH -MAGGGGh0dHA6Ly9vY3NwLnN0YXJ0c3NsLmNvbTA5BggrBgEFBQcwAoYtaHR0cDov -L2FpYS5zdGFydHNzbC5jb20vY2VydHMvc2NhLnNlcnZlcjMuY3J0MDgGA1UdHwQx -MC8wLaAroCmGJ2h0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL3NjYS1zZXJ2ZXIzLmNy -bDB4BgNVHREEcTBvgg9lc2EubWFwcy5lb3guYXSCFXRpbGVzLmVzYS5tYXBzLmVv -eC5hdIIXKi50aWxlcy5lc2EubWFwcy5lb3guYXSCE29zbS5lc2EubWFwcy5lb3gu -YXSCF3N0YWdpbmcuZXNhLm1hcHMuZW94LmF0MCMGA1UdEgQcMBqGGGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tLzBRBgNVHSAESjBIMAgGBmeBDAECAjA8BgsrBgEEAYG1 -NwECBTAtMCsGCCsGAQUFBwIBFh9odHRwczovL3d3dy5zdGFydHNzbC5jb20vcG9s -aWN5MIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYAaPaY+B9kgr46jO65KB1M/HFR -XWeT1ETRCmesu09P+8QAAAFVA3EKawAABAMARzBFAiAQMFKOGTFIZzbVuZ8R2C+u -4QgL0vnSOBT3ylGgjAf+AQIhAOHkMTkhr0APu8jaCkos4c9k8vrn5DWq0k8WXT12 -ip4fAHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFVA3EMcwAA -BAMARjBEAiASftiRTzUpe+IDonZidGHzHKlKwPZoaOE2zqsH1AW9jgIgM7Jmphm1 -rGkakcVooaUudEfCTN/fTJ7cs3kPiljWmkgwDQYJKoZIhvcNAQELBQADggEBAIp2 -QqqJ6+TRRr7cBeiMw+4MrQhbaf+Y0bAsPOF9KOnQ9JMavEki08JRLYLVSraqDW1+ -mrlk+mbvh9mEFkTIvwW5wt/S5tgbRE/fmDBTElRwLPVlvbwRNKNg/54lXhwgETM8 -oTOfxC+dK7bg+EFj3r71d7wf/qhPCBYmN9yk2z4tby1nYI6c+8xXVxnrKGIOOb/X -MAB1eHNvjMHHmhlSV33Z6nqrTzeUEDS5R6X1v3lCtP/058o6NDdLmJ/hTy/So5eB -8NwcilckyoYeI64QXg61KmH+9+scQ2bddWtuDJvnNo0NH1XPOuxl9HpaxBSzIflK -2Wfpr7x/2VCKeO7Mfpo= - - - - - - - - - - - - - - - - - - - - - - - - - - - urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - - - - eox - EOX IT Services GmbH - http://eox.at - - diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 0291f929..495ef4eb 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,7 +22,7 @@ http: - "***REMOVED***" shibAuth: forwardAuth: - address: http://auth/auth + address: http://shibauth/secure trustForwardHeader: true compress: compress: {} -- GitLab From 1dc82314529cc31453679294e7e4254d57565470 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 13:26:38 +0200 Subject: [PATCH 15/64] update pass copernicus shib urls for traefik --- docker-compose.dem.ops.yml | 4 ++-- docker-compose.emg.ops.yml | 8 ++++---- docker-compose.vhr18.ops.yml | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 907564ca..1f14e215 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -33,13 +33,13 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.dem-renderer.middlewares=compress@file,cors@file,shibAuth@file" - "traefik.http.routers.dem-renderer.tls=true" - "traefik.http.routers.dem-renderer.tls.certresolver=default" - "traefik.http.routers.dem-renderer.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" # general diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 86fb801d..019e638a 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -33,13 +33,13 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" - "traefik.http.routers.emg-renderer.tls=true" - "traefik.http.routers.emg-renderer.tls.certresolver=default" - "traefik.http.routers.emg-renderer.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" # general @@ -85,13 +85,13 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" - "traefik.http.routers.emg-renderer.tls=true" - "traefik.http.routers.emg-renderer.tls.certresolver=default" - "traefik.http.routers.emg-renderer.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" # general diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 4529ff57..22c58ea4 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -34,13 +34,13 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-renderer.middlewares=compress@file,cors@file,shibAuth@file" - "traefik.http.routers.vhr18-renderer.tls=true" - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - "traefik.http.routers.vhr18-renderer.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" # general @@ -85,13 +85,13 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-cache-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-cache-renderer.middlewares=compress@file,cors@file,shibAuth@file" - "traefik.http.routers.vhr18-cache-renderer.tls=true" - "traefik.http.routers.vhr18-cache-renderer.tls.certresolver=default" - "traefik.http.routers.vhr18-cache-renderer.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-cache-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - "traefik.http.routers.vhr18-cache-renderer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache-renderer-redirect.entrypoints=http" # general -- GitLab From 5d892ea5202811afbe7600e7d1901b3b08359e8d Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 13:29:20 +0200 Subject: [PATCH 16/64] rename shibextnet --- docker-compose.base.ops.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index 1aecaffa..a7b647cb 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -53,7 +53,7 @@ services: placement: constraints: [node.role == manager] networks: - - shibauth-extnet + - shib-extnet volumes: traefik-data: networks: @@ -65,5 +65,5 @@ networks: name: dem-extnet logging-extnet: name: logging-extnet - shibauth-extnet: - name: shibauth-extnet + shib-extnet: + name: shib-extnet -- GitLab From ba5d76ee29773ea09df31dc72a28642ba0093cb9 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 14:52:09 +0200 Subject: [PATCH 17/64] fix traefik labels to be unique --- docker-compose.dem.ops.yml | 32 ++++++++++++++++---------------- docker-compose.emg.ops.yml | 32 ++++++++++++++++---------------- docker-compose.vhr18.ops.yml | 32 ++++++++++++++++---------------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 1f14e215..46c6a135 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -33,15 +33,15 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.dem-renderer.tls=true" - - "traefik.http.routers.dem-renderer.tls.certresolver=default" - - "traefik.http.routers.dem-renderer.entrypoints=https" + - "traefik.http.routers.dem-renderer-shib.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-renderer-shib.tls=true" + - "traefik.http.routers.dem-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.dem-renderer-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" + - "traefik.http.routers.dem-renderer-shib-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -85,15 +85,15 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.dem-renderer.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.dem-renderer.tls=true" - - "traefik.http.routers.dem-renderer.tls.certresolver=default" - - "traefik.http.routers.dem-renderer.entrypoints=https" + - "traefik.http.routers.dem-cache-shib.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-cache-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-cache-shib.tls=true" + - "traefik.http.routers.dem-cache-shib.tls.certresolver=default" + - "traefik.http.routers.dem-cache-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" + - "traefik.http.routers.dem-cache-shib-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-cache-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-cache-shib-redirect.entrypoints=http" # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 019e638a..9054dbe2 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -33,15 +33,15 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.emg-renderer.tls=true" - - "traefik.http.routers.emg-renderer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer.entrypoints=https" + - "traefik.http.routers.emg-renderer-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-renderer-shib.tls=true" + - "traefik.http.routers.emg-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.emg-renderer-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + - "traefik.http.routers.emg-renderer-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -85,15 +85,15 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.emg-renderer.tls=true" - - "traefik.http.routers.emg-renderer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer.entrypoints=https" + - "traefik.http.routers.emg-cache-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-cache-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-cache-shib.tls=true" + - "traefik.http.routers.emg-cache-shib.tls.certresolver=default" + - "traefik.http.routers.emg-cache-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + - "traefik.http.routers.emg-cache-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-cache-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-cache-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 22c58ea4..443001b6 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -34,15 +34,15 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.vhr18-renderer.tls=true" - - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - - "traefik.http.routers.vhr18-renderer.entrypoints=https" + - "traefik.http.routers.vhr18-renderer-shib.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-renderer-shib.tls=true" + - "traefik.http.routers.vhr18-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" + - "traefik.http.routers.vhr18-renderer-shib-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -85,15 +85,15 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-cache-renderer.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-cache-renderer.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.vhr18-cache-renderer.tls=true" - - "traefik.http.routers.vhr18-cache-renderer.tls.certresolver=default" - - "traefik.http.routers.vhr18-cache-renderer.entrypoints=https" + - "traefik.http.routers.vhr18-cache-renderer-shib.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-cache-renderer-shib.tls=true" + - "traefik.http.routers.vhr18-cache-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.vhr18-cache-renderer-shib.entrypoints=https" # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-cache-renderer-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-cache-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-cache-renderer-redirect.entrypoints=http" + - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" -- GitLab From 4f6d22d4e00ae6d3f26c99ee0a11f094a2f51d41 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 14:54:27 +0200 Subject: [PATCH 18/64] fix typo --- docker-compose.base.ops.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index a7b647cb..bf6103e8 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,7 +28,7 @@ services: - emg-extnet - dem-extnet - logging-extnet - - shibauth-extnet + - shib-extnet shibauth: image: testing-shibboleth deploy: -- GitLab From 658e2e48d081f1c659ad57470d9800c8be5f3f69 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 15:22:38 +0200 Subject: [PATCH 19/64] intnet shib network --- docker-compose.base.ops.yml | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index bf6103e8..dbf099ee 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,32 +28,14 @@ services: - emg-extnet - dem-extnet - logging-extnet - - shib-extnet shibauth: image: testing-shibboleth deploy: - # labels: - # # router for basic auth based access (https) - # - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" - # - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - # - "traefik.http.routers.shibauth.tls=true" - # - "traefik.http.routers.shibauth.tls.certresolver=default" - # - "traefik.http.routers.shibauth.entrypoints=https" - # # router for basic auth based access (http) - # - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" - # - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - # - "traefik.http.routers.shibauth-redirect.entrypoints=http" - # # general - # - "traefik.http.services.shibauth.loadbalancer.sticky=false" - # - "traefik.http.services.shibauth.loadbalancer.server.port=80" - # - "traefik.docker.network=shib-extnet" - # - "traefik.docker.lbswarm=true" - # - "traefik.enable=true" replicas: 1 placement: constraints: [node.role == manager] networks: - - shib-extnet + - intnet volumes: traefik-data: networks: @@ -65,5 +47,4 @@ networks: name: dem-extnet logging-extnet: name: logging-extnet - shib-extnet: - name: shib-extnet + intnet: -- GitLab From 3fa843b0f64beca18fa7f9823c0975975a2e21bf Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 15:38:20 +0200 Subject: [PATCH 20/64] correct typo intnet traefik service --- docker-compose.base.ops.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index dbf099ee..d16ac8c4 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,6 +28,7 @@ services: - emg-extnet - dem-extnet - logging-extnet + - intnet shibauth: image: testing-shibboleth deploy: -- GitLab From de7a16c83e521c3a0a85d6a4eaf5c0231c62216b Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 30 Sep 2020 16:04:01 +0200 Subject: [PATCH 21/64] latest progress --- docker-compose.base.ops.yml | 29 ++++++++++++++++++++++++++--- traefik-dynamic.yml | 2 +- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index d16ac8c4..7ac26701 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,15 +28,37 @@ services: - emg-extnet - dem-extnet - logging-extnet - - intnet + - shib-extnet shibauth: image: testing-shibboleth deploy: replicas: 1 placement: constraints: [node.role == manager] + labels: + # router for basic auth based access (https) + - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + - "traefik.http.routers.shibauth.tls=true" + - "traefik.http.routers.shibauth.tls.certresolver=default" + - "traefik.http.routers.shibauth.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + - "traefik.http.routers.shibauth-redirect.entrypoints=http" + # general + - "traefik.http.services.shibauth.loadbalancer.sticky=false" + - "traefik.http.services.shibauth.loadbalancer.server.port=80" + - "traefik.docker.network=shib-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + # labels: + # - "traefik.enable=true" + # - "traefik.frontend.rule=Host:shib.pdas.prism.eox.at" + # - "traefik.port=80" + # - "traefik.frontend.passHostHeader=true" networks: - - intnet + - shib-extnet volumes: traefik-data: networks: @@ -48,4 +70,5 @@ networks: name: dem-extnet logging-extnet: name: logging-extnet - intnet: + shib-extnet: + name: shib-extnet diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 495ef4eb..9b51a489 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,7 +22,7 @@ http: - "***REMOVED***" shibAuth: forwardAuth: - address: http://shibauth/secure + address: http://shib.pdas.prism.eox.at/secure trustForwardHeader: true compress: compress: {} -- GitLab From 15a9e1176d6c116752706bbc3ab35508b8fb4322 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Mon, 5 Oct 2020 09:36:06 +0200 Subject: [PATCH 22/64] t --- docker-compose.base.ops.yml | 2 +- shibauth/Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index 7ac26701..807af599 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -51,7 +51,7 @@ services: - "traefik.http.services.shibauth.loadbalancer.server.port=80" - "traefik.docker.network=shib-extnet" - "traefik.docker.lbswarm=true" - - "traefik.enable=true" + - "traefik.enable=true" # labels: # - "traefik.enable=true" # - "traefik.frontend.rule=Host:shib.pdas.prism.eox.at" diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile index 3f278c26..88efe7cb 100644 --- a/shibauth/Dockerfile +++ b/shibauth/Dockerfile @@ -33,7 +33,7 @@ LABEL name="prism view server cache" \ license="MIT Copyright (C) 2019 EOX IT Services GmbH " \ type="prism view server shibauth" \ version="0.0.1" - +RUN mkdir -p /var/www/secure COPY shibboleth-conf /etc/shibboleth/ COPY etc-httpd/ /etc/httpd/ -COPY index.html /var/www/html/ +COPY index.html /var/www/html/secure -- GitLab From 43096bc9e05af7028da071517cfbd36e99c4c2bc Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 7 Oct 2020 16:05:55 +0200 Subject: [PATCH 23/64] update client deploy labels --- docker-compose.emg.ops.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 9054dbe2..88c5411b 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -135,15 +135,15 @@ services: - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" # router for basic auth based access (https) - - "traefik.http.routers.emg-client.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" - - "traefik.http.routers.emg-client.tls=true" - - "traefik.http.routers.emg-client.tls.certresolver=default" - - "traefik.http.routers.emg-client.entrypoints=https" + - "traefik.http.routers.emg-client-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-shib.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.emg-client-shib.tls=true" + - "traefik.http.routers.emg-client-shib.tls.certresolver=default" + - "traefik.http.routers.emg-client-shib.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.emg-client-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-client-redirect.entrypoints=http" + - "traefik.http.routers.emg-client-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-shib-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-client-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-client.loadbalancer.sticky=false" - "traefik.http.services.emg-client.loadbalancer.server.port=80" -- GitLab From 1233ece3dd7f9c08b7a60658b157c1452f4367cd Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 7 Oct 2020 16:06:05 +0200 Subject: [PATCH 24/64] fix shib internal url --- traefik-dynamic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 9b51a489..495ef4eb 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,7 +22,7 @@ http: - "***REMOVED***" shibAuth: forwardAuth: - address: http://shib.pdas.prism.eox.at/secure + address: http://shibauth/secure trustForwardHeader: true compress: compress: {} -- GitLab From 1e6900784570ebae24c2d33825cd5099ccc0a38e Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 09:18:54 +0200 Subject: [PATCH 25/64] fix traefik auth labels on basicauth access hosts --- docker-compose.dem.ops.yml | 4 ++-- docker-compose.emg.ops.yml | 6 +++--- docker-compose.vhr18.ops.yml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 46c6a135..af14f652 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -66,7 +66,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.dem-cache.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.dem-cache.tls=true" - "traefik.http.routers.dem-cache.tls.certresolver=default" - "traefik.http.routers.dem-cache.entrypoints=https" @@ -126,7 +126,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-client.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file,shibAuth@file" + - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file" - "traefik.http.routers.dem-client.tls=true" - "traefik.http.routers.dem-client.tls.certresolver=default" - "traefik.http.routers.dem-client.entrypoints=https" diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 88c5411b..909dab1b 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" - "traefik.http.routers.emg-renderer.tls=true" - "traefik.http.routers.emg-renderer.tls.certresolver=default" - "traefik.http.routers.emg-renderer.entrypoints=https" @@ -66,7 +66,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.emg-cache.tls=true" - "traefik.http.routers.emg-cache.tls.certresolver=default" - "traefik.http.routers.emg-cache.entrypoints=https" @@ -126,7 +126,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file,shibAuth@file" + - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file" - "traefik.http.routers.emg-client.tls=true" - "traefik.http.routers.emg-client.tls.certresolver=default" - "traefik.http.routers.emg-client.entrypoints=https" diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 443001b6..75e0c25a 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -15,7 +15,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" - "traefik.http.routers.vhr18-renderer.tls=true" - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - "traefik.http.routers.vhr18-renderer.entrypoints=https" @@ -66,7 +66,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file,shibAuth@file" + - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.vhr18-cache.tls=true" - "traefik.http.routers.vhr18-cache.tls.certresolver=default" - "traefik.http.routers.vhr18-cache.entrypoints=https" -- GitLab From 59c28d0cd1e25de365ba6d04015628e788839afd Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 16:27:24 +0200 Subject: [PATCH 26/64] testing emg.pdas.prism.eox.at directly --- docker-compose.base.ops.yml | 5 ----- docker-compose.emg.ops.yml | 12 +----------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index 807af599..421d65ce 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -52,11 +52,6 @@ services: - "traefik.docker.network=shib-extnet" - "traefik.docker.lbswarm=true" - "traefik.enable=true" - # labels: - # - "traefik.enable=true" - # - "traefik.frontend.rule=Host:shib.pdas.prism.eox.at" - # - "traefik.port=80" - # - "traefik.frontend.passHostHeader=true" networks: - shib-extnet volumes: diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 909dab1b..cd0cbafd 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -126,7 +126,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" - "traefik.http.routers.emg-client.tls=true" - "traefik.http.routers.emg-client.tls.certresolver=default" - "traefik.http.routers.emg-client.entrypoints=https" @@ -134,16 +134,6 @@ services: - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" - # router for basic auth based access (https) - - "traefik.http.routers.emg-client-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client-shib.middlewares=shibAuth@file,compress@file" - - "traefik.http.routers.emg-client-shib.tls=true" - - "traefik.http.routers.emg-client-shib.tls.certresolver=default" - - "traefik.http.routers.emg-client-shib.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-client-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-client-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-client.loadbalancer.sticky=false" - "traefik.http.services.emg-client.loadbalancer.server.port=80" -- GitLab From 9e879ebd007ec48af5e6396cefc54a9884fafa89 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 16:29:48 +0200 Subject: [PATCH 28/64] try https for shibAuth --- traefik-dynamic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 495ef4eb..896eaef8 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,7 +22,7 @@ http: - "***REMOVED***" shibAuth: forwardAuth: - address: http://shibauth/secure + address: https://shibauth/secure trustForwardHeader: true compress: compress: {} -- GitLab From 24c8bffd85469a2f2f36b1af2e9a550a921c2b55 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 16:55:34 +0200 Subject: [PATCH 29/64] new test --- docker-compose.emg.ops_test.yml | 147 ++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 docker-compose.emg.ops_test.yml diff --git a/docker-compose.emg.ops_test.yml b/docker-compose.emg.ops_test.yml new file mode 100644 index 00000000..7b66a1ea --- /dev/null +++ b/docker-compose.emg.ops_test.yml @@ -0,0 +1,147 @@ +version: "3.6" +services: + database: + volumes: + - type: tmpfs + target: /dev/shm + tmpfs: + size: 536870912 + renderer: + environment: + INSTALL_DIR: "/var/www/pvs/ops/" + INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" + deploy: + labels: + # router for basic auth based access (https) + - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.emg-renderer.tls=true" + - "traefik.http.routers.emg-renderer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + # router for referrer based access (https) + - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" + - "traefik.http.routers.emg-renderer_referer.tls=true" + - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" + # general + - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" + - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" + - "traefik.docker.network=emg-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + replicas: 0 + resources: + limits: + memory: 8G + placement: + constraints: + - node.labels.type == external + networks: + - extnet + cache: + configs: + - source: mapcache-ops + target: /mapcache-template.xml + deploy: + labels: + - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" + # router for basic auth based access (https) + - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache.tls=true" + - "traefik.http.routers.emg-cache.tls.certresolver=default" + - "traefik.http.routers.emg-cache.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-cache-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-cache-redirect.entrypoints=http" + # router for referrer based access (https) + - "traefik.http.routers.emg-cache_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-cache_referer.middlewares=cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache_referer.tls=true" + - "traefik.http.routers.emg-cache_referer.tls.certresolver=default" + - "traefik.http.routers.emg-cache_referer.entrypoints=https" + # router for referrer based access (http) + - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" + - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" + # general + - "traefik.http.services.emg-cache.loadbalancer.sticky=false" + - "traefik.http.services.emg-cache.loadbalancer.server.port=80" + - "traefik.docker.network=emg-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + replicas: 0 + resources: + limits: + memory: 8G + placement: + constraints: + - node.labels.type == external + networks: + - extnet + registrar: + environment: + INSTALL_DIR: "/var/www/pvs/ops/" + INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" + deploy: + replicas: 0 + placement: + constraints: + - node.labels.type == internal + client: + configs: + - source: client-ops + target: /usr/share/nginx/html/index.html + deploy: + labels: + # router for basic auth based access (https) + - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.emg-client.tls=true" + - "traefik.http.routers.emg-client.tls.certresolver=default" + - "traefik.http.routers.emg-client.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-client-redirect.entrypoints=http" + # general + - "traefik.http.services.emg-client.loadbalancer.sticky=false" + - "traefik.http.services.emg-client.loadbalancer.server.port=80" + - "traefik.docker.network=emg-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + placement: + constraints: + - node.labels.type == external + networks: + - extnet + preprocessor: + volumes: + - type: bind + source: /var/vhr + target: /tmp + deploy: + replicas: 0 + placement: + constraints: + - node.labels.type == internal + sftp: + deploy: + replicas: 0 + ingestor: + deploy: + replicas: 0 +networks: + extnet: + name: emg-extnet + external: true -- GitLab From 5529378266fe47f3537a9e81e0ecb65db99ad955 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 20:53:45 +0200 Subject: [PATCH 30/64] add sp-metadata.xml --- shibauth/shibboleth-conf/sp-metadata.xml | 84 ++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml new file mode 100644 index 00000000..ef565636 --- /dev/null +++ b/shibauth/shibboleth-conf/sp-metadata.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + https://https://shib.pdas.prism.eox.at/shibboleth + https://shib.pdas.prism.eox.at + + CN=https://shib.pdas.prism.eox.at + MIIEVDCCArygAwIBAgIJANYdDHsBg6ulMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNV +BAMTHmh0dHBzOi8vc2hpYi5wZGFzLnByaXNtLmVveC5hdDAeFw0yMDEwMDgxNDI2 +MjBaFw0zMDEwMDYxNDI2MjBaMCkxJzAlBgNVBAMTHmh0dHBzOi8vc2hpYi5wZGFz +LnByaXNtLmVveC5hdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMKW +psgoJpT33XXQDzFiWXPkTW8deYIjaRN4iXuVpMa9/RpuQsSTTPCxwFXhp31lgsay +3DA3WNK5KVCx5ccnLbb5CiuZBrzFFttfzK1LIgf0rieGtpFj0cTEQwfFGM+3T/5p +cdTi/CyT7xUCGOn6rzU9NjIpQ7Z0DrIkN4vcRbljExMALZwrfg0E00JB/rg7nUga +Tc5rkM8DuqsvOe9IfRv9ZOe2sDimido13jzhE/Y/NTHtq8qleVxeT42P/hiZlJX4 +rioMtigG7nXmz0/6nfBR3y2tnViWURNF3DXy+7BAKIfTUU5Dy8diFpPVolEuoF3r +7hK+TMrOjOm+XZ/oyM2AlxiDGHtMMVkVs/m92jewUnyZoOYawCs0O/Eysri302Ve +e1S7oj67NRB2X/x98iejBYP76Y4ssJvKyYn96M+Va3B+SOfrdMLJwTUZxTQmFMmk +iJsyCM9b7ZNb745mClkcoTy22HtA0qtcnd/sZJ6ljOCe8RxA9fhFYu+5oO9SHQID +AQABo38wfTBcBgNVHREEVTBTgh5odHRwczovL3NoaWIucGRhcy5wcmlzbS5lb3gu +YXSGMWh0dHBzOi8vaHR0cHM6Ly9zaGliLnBkYXMucHJpc20uZW94LmF0L3NoaWJi +b2xldGgwHQYDVR0OBBYEFOj3ABr8n1Af0GDfg5+aYtGAFM3kMA0GCSqGSIb3DQEB +CwUAA4IBgQC9jN3ZLU6z6UCngdY16vlPdyMjIdko3/bstXlNWGvAwx0lPmPnV4b5 +ej+4l1vd3S3OAFYUKPJJG8rTInHt2tyYNIjytjIzYnonksdnS/iSlrd38q1FdWH8 +3ny1gyegunJutXqaFLHlBw77oNau8swXSegs/60pgYNNH+eMJbrToeAAM8zGqN1z +wXh4KWcwHmmH2ozJ468DYnv6I4/U9WydBoXNdQa3cKDv6/g4xfiyS4ByorVmNvOW +0C6OrCYwucS1CYxbmHk1E9ygIFEeKv1Z29leTIJxUHZXljfg7BDst2I2EfhyQ+fT +vB7rAipb+M2xckJJrCZJe5skBWsvP5ZcM3FA/GctWnc+5P/CO+2CZkdNFan7NBIx +focLOwyc7q3iCpqDxBY+EIkVlmSeg8mZdU9B9y0SkJxIcsePwSX8CSaFj5ndBY/T +aFiImaHsFzO4bZDEdaA0AdeJ5PalOTopbbVYO2FLMfvaXdu+GjDS6PGi/HrSX+P0 +FDXpx00p+0g= + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- GitLab From 85d24a59d1d4624e3cbda0fbd950c46a1b50f338 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 8 Oct 2020 23:53:11 +0200 Subject: [PATCH 31/64] https --- shibauth/shibboleth-conf/shibboleth2.xml | 4 ++-- shibauth/shibboleth-conf/sp-metadata.xml | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index 7bd47635..568b8f4d 100644 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -7,9 +7,9 @@ + checkAddress="false" handlerSSL="true" cookieProps="https"> - SAML2 + SAML2 SAML2 Local diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml index ef565636..25280b3d 100644 --- a/shibauth/shibboleth-conf/sp-metadata.xml +++ b/shibauth/shibboleth-conf/sp-metadata.xml @@ -25,7 +25,7 @@ and do *NOT* provide it in real time to your partners. - + @@ -70,15 +70,15 @@ FDXpx00p+0g= - - - - - - - - - + + + + + + + + + \ No newline at end of file -- GitLab From c79249027b5b11bbf04edfb6f810294fadc8e228 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Fri, 9 Oct 2020 00:00:34 +0200 Subject: [PATCH 32/64] test --- shibauth/etc-httpd/conf.d/shib.conf | 6 ------ shibauth/etc-httpd/conf.d/sp.conf | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 shibauth/etc-httpd/conf.d/sp.conf diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf index 758f387c..191c4328 100644 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -5,9 +5,3 @@ UseCanonicalName On SetHandler shib - - - AuthType shibboleth - ShibRequestSetting requireSession 1 - require shib-session - diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf new file mode 100644 index 00000000..9749dc2b --- /dev/null +++ b/shibauth/etc-httpd/conf.d/sp.conf @@ -0,0 +1,13 @@ +ServerName shib.pdas.prism.eox.at + + + ServerName https://shib.pdas.prism.eox.at:443 + UseCanonicalName On + + DocumentRoot "/var/www/html" + + AuthType shibboleth + ShibRequestSetting requireSession 1 + require shib-session + + \ No newline at end of file -- GitLab From 884634f171f18b0dd24f96bb536a81e1d437d8e0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Fri, 9 Oct 2020 00:15:04 +0200 Subject: [PATCH 33/64] change modes for debugging --- shibauth/Dockerfile | 0 shibauth/etc-httpd/conf.d/shib.conf | 0 shibauth/etc-httpd/conf.d/sp.conf | 0 shibauth/index.html | 0 shibauth/shibboleth-conf/attribute-map.xml | 0 shibauth/shibboleth-conf/idp-metadata.xml | 0 shibauth/shibboleth-conf/shibboleth2.xml | 0 shibauth/shibboleth-conf/sp-metadata.xml | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 shibauth/Dockerfile mode change 100644 => 100755 shibauth/etc-httpd/conf.d/shib.conf mode change 100644 => 100755 shibauth/etc-httpd/conf.d/sp.conf mode change 100644 => 100755 shibauth/index.html mode change 100644 => 100755 shibauth/shibboleth-conf/attribute-map.xml mode change 100644 => 100755 shibauth/shibboleth-conf/idp-metadata.xml mode change 100644 => 100755 shibauth/shibboleth-conf/shibboleth2.xml mode change 100644 => 100755 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile old mode 100644 new mode 100755 diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf old mode 100644 new mode 100755 diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf old mode 100644 new mode 100755 diff --git a/shibauth/index.html b/shibauth/index.html old mode 100644 new mode 100755 diff --git a/shibauth/shibboleth-conf/attribute-map.xml b/shibauth/shibboleth-conf/attribute-map.xml old mode 100644 new mode 100755 diff --git a/shibauth/shibboleth-conf/idp-metadata.xml b/shibauth/shibboleth-conf/idp-metadata.xml old mode 100644 new mode 100755 diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml old mode 100644 new mode 100755 diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml old mode 100644 new mode 100755 -- GitLab From 0871f92585164a318b506aac331b275aecb3d242 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Fri, 9 Oct 2020 18:35:50 +0200 Subject: [PATCH 34/64] updating current progress --- docker-compose.base.ops.yml | 6 +++--- shibauth/etc-httpd/conf.d/shib.conf | 2 +- shibauth/etc-httpd/conf.d/sp.conf | 5 ++--- traefik-dynamic.yml | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index 421d65ce..56a2e14f 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -19,7 +19,7 @@ services: environment: HTTP_PROXY: "http://172.30.252.68:3128" HTTPS_PROXY: "http://172.30.252.68:3128" - NO_PROXY: "172.0.0.0/8,192.168.0.0/16,10.0.0.0/8" + NO_PROXY: "172.0.0.0/8,192.168.0.0/16,10.0.0.0/8,shibauth" deploy: placement: constraints: [node.role == manager] @@ -37,13 +37,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth.rule=Host(`emg.pdas.prism.eox.at`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`emg.pdas.prism.eox.at`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf index 191c4328..635aa462 100755 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -1,4 +1,4 @@ -ServerName shib.pdas.prism.eox.at +ServerName emg.pdas.prism.eox.at LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so ShibCompatValidUser Off UseCanonicalName On diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf index 9749dc2b..edfa7e84 100755 --- a/shibauth/etc-httpd/conf.d/sp.conf +++ b/shibauth/etc-httpd/conf.d/sp.conf @@ -1,7 +1,5 @@ -ServerName shib.pdas.prism.eox.at - - ServerName https://shib.pdas.prism.eox.at:443 + ServerName https://emg.pdas.prism.eox.at:443 UseCanonicalName On DocumentRoot "/var/www/html" @@ -9,5 +7,6 @@ ServerName shib.pdas.prism.eox.at AuthType shibboleth ShibRequestSetting requireSession 1 require shib-session + RequestHeader set Referer X-Forwarded-Uri env=X-Forwarded-Uri \ No newline at end of file diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index 896eaef8..495ef4eb 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,7 +22,7 @@ http: - "***REMOVED***" shibAuth: forwardAuth: - address: https://shibauth/secure + address: http://shibauth/secure trustForwardHeader: true compress: compress: {} -- GitLab From 239272ffad54e29c9dc199dc43cead751e70bba0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Fri, 9 Oct 2020 18:38:10 +0200 Subject: [PATCH 35/64] add debug loggers --- shibauth/shibboleth-conf/native.logger | 41 ++++++++++++++ shibauth/shibboleth-conf/shibd.logger | 75 ++++++++++++++++++++++++++ traefik.yml | 2 +- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 shibauth/shibboleth-conf/native.logger create mode 100644 shibauth/shibboleth-conf/shibd.logger diff --git a/shibauth/shibboleth-conf/native.logger b/shibauth/shibboleth-conf/native.logger new file mode 100644 index 00000000..d360b124 --- /dev/null +++ b/shibauth/shibboleth-conf/native.logger @@ -0,0 +1,41 @@ +# set overall behavior +log4j.rootCategory=DEBUG, native_log + +# fairly verbose for DEBUG, so generally leave at WARN/INFO +log4j.category.XMLTooling.XMLObject=WARN +log4j.category.XMLTooling.KeyInfoResolver=WARN +log4j.category.Shibboleth.IPRange=WARN +log4j.category.Shibboleth.PropertySet=WARN + +# raise for low-level tracing of SOAP client HTTP/SSL behavior +log4j.category.XMLTooling.libcurl=WARN + +# useful categories to tune independently: +# +# tracing of SAML messages and security policies +#log4j.category.OpenSAML.MessageDecoder=DEBUG +#log4j.category.OpenSAML.MessageEncoder=DEBUG +#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG +# interprocess message remoting +#log4j.category.Shibboleth.Listener=DEBUG +# mapping of requests to applicationId +#log4j.category.Shibboleth.RequestMapper=DEBUG +# high level session cache operations +#log4j.category.Shibboleth.SessionCache=DEBUG +# persistent storage and caching +#log4j.category.XMLTooling.StorageService=DEBUG + +# define the appender + +log4j.appender.native_log=org.apache.log4j.RollingFileAppender +log4j.appender.native_log.fileName=/dev/stdout +log4j.appender.native_log.maxFileSize=0 +log4j.appender.native_log.maxBackupIndex=0 +log4j.appender.native_log.layout=org.apache.log4j.PatternLayout +log4j.appender.native_log.layout.ConversionPattern=sp-native %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n + +#log4j.appender.warn_log=org.apache.log4j.RollingFileAppender +#log4j.appender.warn_log.fileName=/var/log/shibboleth-www/native_warn.log +#log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout +#log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n +#log4j.appender.warn_log.threshold=WARN diff --git a/shibauth/shibboleth-conf/shibd.logger b/shibauth/shibboleth-conf/shibd.logger new file mode 100644 index 00000000..c12b4089 --- /dev/null +++ b/shibauth/shibboleth-conf/shibd.logger @@ -0,0 +1,75 @@ +# set overall behavior +log4j.rootCategory=DEBUG, shibd_log, warn_log + +# fairly verbose for DEBUG, so generally leave at INFO +log4j.category.XMLTooling.XMLObject=INFO +log4j.category.XMLTooling.KeyInfoResolver=INFO +log4j.category.Shibboleth.IPRange=INFO +log4j.category.Shibboleth.PropertySet=INFO + +# raise for low-level tracing of SOAP client HTTP/SSL behavior +log4j.category.XMLTooling.libcurl=INFO + +# useful categories to tune independently: +# +# tracing of SAML messages and security policies +#log4j.category.OpenSAML.MessageDecoder=DEBUG +#log4j.category.OpenSAML.MessageEncoder=DEBUG +#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG +#log4j.category.XMLTooling.SOAPClient=DEBUG +# interprocess message remoting +#log4j.category.Shibboleth.Listener=DEBUG +# mapping of requests to applicationId +#log4j.category.Shibboleth.RequestMapper=DEBUG +# high level session cache operations +#log4j.category.Shibboleth.SessionCache=DEBUG +# persistent storage and caching +#log4j.category.XMLTooling.StorageService=DEBUG + +# logs XML being signed or verified if set to DEBUG +log4j.category.XMLTooling.Signature.Debugger=INFO, sig_log +log4j.additivity.XMLTooling.Signature.Debugger=false +log4j.ownAppenders.XMLTooling.Signature.Debugger=true + +# the tran log blocks the "default" appender(s) at runtime +# Level should be left at INFO for this category +log4j.category.Shibboleth-TRANSACTION=INFO, tran_log +log4j.additivity.Shibboleth-TRANSACTION=false +log4j.ownAppenders.Shibboleth-TRANSACTION=true + +# uncomment to suppress particular event types +#log4j.category.Shibboleth-TRANSACTION.AuthnRequest=WARN +#log4j.category.Shibboleth-TRANSACTION.Login=WARN +#log4j.category.Shibboleth-TRANSACTION.Logout=WARN + +# define the appenders + +log4j.appender.shibd_log=org.apache.log4j.RollingFileAppender +log4j.appender.shibd_log.fileName=/dev/stdout +log4j.appender.shibd_log.maxFileSize=0 +log4j.appender.shibd_log.maxBackupIndex=0 +log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout +log4j.appender.shibd_log.layout.ConversionPattern=sp-shibd %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n + +#log4j.appender.warn_log=org.apache.log4j.RollingFileAppender +#log4j.appender.warn_log.fileName=/var/log/shibboleth/shibd_warn.log +#log4j.appender.warn_log.maxFileSize=0 +#log4j.appender.warn_log.maxBackupIndex=0 +#log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout +#log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n +#log4j.appender.warn_log.threshold=WARN + +log4j.appender.tran_log=org.apache.log4j.RollingFileAppender +log4j.appender.tran_log.fileName=/dev/stdout +log4j.appender.tran_log.maxFileSize=0 +log4j.appender.tran_log.maxBackupIndex=0 +log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout +log4j.appender.tran_log.layout.ConversionPattern=sp-transaction %d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n + +log4j.appender.sig_log=org.apache.log4j.FileAppender +log4j.appender.sig_log.fileName=/dev/stdout +log4j.appender.sig_log.maxFileSize=0 +log4j.appender.sig_log.maxBackupIndex=0 +log4j.appender.sig_log.layout=org.apache.log4j.PatternLayout +log4j.appender.sig_log.layout.ConversionPattern=sp-signature %m + diff --git a/traefik.yml b/traefik.yml index 2986bbf2..4a4135d7 100644 --- a/traefik.yml +++ b/traefik.yml @@ -19,7 +19,7 @@ providers: api: dashboard: true log: - level: WARN + level: DEBUG accessLog: {} certificatesResolvers: default: -- GitLab From fd01235df8c84dbe106a0bf464e14ff190d58a66 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 14 Oct 2020 12:52:11 +0200 Subject: [PATCH 36/64] test change to esa sso --- .../shibboleth-conf/idp-metadata-esa-test.xml | 116 ++++++++++++++++++ ...metadata.xml => idp-metadata_samltest.xml} | 0 shibauth/shibboleth-conf/shibboleth2.xml | 4 +- 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 shibauth/shibboleth-conf/idp-metadata-esa-test.xml rename shibauth/shibboleth-conf/{idp-metadata.xml => idp-metadata_samltest.xml} (100%) diff --git a/shibauth/shibboleth-conf/idp-metadata-esa-test.xml b/shibauth/shibboleth-conf/idp-metadata-esa-test.xml new file mode 100644 index 00000000..647078b2 --- /dev/null +++ b/shibauth/shibboleth-conf/idp-metadata-esa-test.xml @@ -0,0 +1,116 @@ + + + + + + esa.int + + + + + + +MIIEQjCCAyqgAwIBAgIJAJw83mLahxpQMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV +BAYTAklUMQ4wDAYDVQQIEwVMYXppbzENMAsGA1UEBxMEUm9tZTEZMBcGA1UEChMQ +Q0RTVjMgQ29uc29ydGl1bTEOMAwGA1UECxMFU3BhY2UxGjAYBgNVBAMTEXVtc3Nv +aWRwLmNkc3YzLmV1MB4XDTE1MDQwMjE2Mzg1M1oXDTI1MDMzMDE2Mzg1M1owczEL +MAkGA1UEBhMCSVQxDjAMBgNVBAgTBUxhemlvMQ0wCwYDVQQHEwRSb21lMRkwFwYD +VQQKExBDRFNWMyBDb25zb3J0aXVtMQ4wDAYDVQQLEwVTcGFjZTEaMBgGA1UEAxMR +dW1zc29pZHAuY2RzdjMuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCrDTGZEQj7uMw347TnyMac0HnkLY046e/4V+boJBuQsP7Moxh6xHH2qcdS2UbW +xtSBOUuS/aAz92udzY8wBrKUUvvWKEnyh3v84+kfNYugBp4ZpW7pJbfUh9KjUvWh +G3LtZfyuRaCdyYF6TKh0K+96IRSpwe5wFXqRev7a6+8fDcTL73cFFBLjDaMFelIz +szskhsGalXAq5WP20aDog0eiEbf8oTa5NDPY1UZDnwDmF0lNDm4lsYGAv59h+8kU +ODGmmGVo5zrz7ujcU1sChc9iy9GlGEzekFAoEj6y9fbieyE4Wz6QW4nLeO1YZtjz +kvOi6yp2raNQSI4hwVEWNDK/AgMBAAGjgdgwgdUwHQYDVR0OBBYEFKXpmub0bNGS +gtwbyAUqu2kD1e8WMIGlBgNVHSMEgZ0wgZqAFKXpmub0bNGSgtwbyAUqu2kD1e8W +oXekdTBzMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFTGF6aW8xDTALBgNVBAcTBFJv +bWUxGTAXBgNVBAoTEENEU1YzIENvbnNvcnRpdW0xDjAMBgNVBAsTBVNwYWNlMRow +GAYDVQQDExF1bXNzb2lkcC5jZHN2My5ldYIJAJw83mLahxpQMAwGA1UdEwQFMAMB +Af8wDQYJKoZIhvcNAQEFBQADggEBAGMnf0UOmtKB2VF/TsjG1Lz7fJ48sySGC9R6 +TLy3lbUplogZsIBdt/cc+DP6O6l2z16hDb9B0X9QjJjO1qvM4oQPjlm8dZGCnyFV +EsstRM9EgOdnFIh16+q6x+u6c2XhnnLDdRsjsP7p53dT+iShgjI448voZDE3DLcs +b2eQu+iN5rmNfvg6DdaP/+2cvkoMvKL5dF+YRk5KNLn2vHi3Fti6uIpWAfgiICHr +dadCFX5qVlnadZP9Av35lM4VaDz+5eOFvjl1G+7+yEyaoi/m6gjrgrOI4Mqc1zcu +DhMOi9NqX4P9LSI1seXUf0feKA5wB+ei7MgqSSpooJc2PEnFyRg= + + + + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + + esa.int + + + + + + +MIIEQjCCAyqgAwIBAgIJAJw83mLahxpQMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV +BAYTAklUMQ4wDAYDVQQIEwVMYXppbzENMAsGA1UEBxMEUm9tZTEZMBcGA1UEChMQ +Q0RTVjMgQ29uc29ydGl1bTEOMAwGA1UECxMFU3BhY2UxGjAYBgNVBAMTEXVtc3Nv +aWRwLmNkc3YzLmV1MB4XDTE1MDQwMjE2Mzg1M1oXDTI1MDMzMDE2Mzg1M1owczEL +MAkGA1UEBhMCSVQxDjAMBgNVBAgTBUxhemlvMQ0wCwYDVQQHEwRSb21lMRkwFwYD +VQQKExBDRFNWMyBDb25zb3J0aXVtMQ4wDAYDVQQLEwVTcGFjZTEaMBgGA1UEAxMR +dW1zc29pZHAuY2RzdjMuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCrDTGZEQj7uMw347TnyMac0HnkLY046e/4V+boJBuQsP7Moxh6xHH2qcdS2UbW +xtSBOUuS/aAz92udzY8wBrKUUvvWKEnyh3v84+kfNYugBp4ZpW7pJbfUh9KjUvWh +G3LtZfyuRaCdyYF6TKh0K+96IRSpwe5wFXqRev7a6+8fDcTL73cFFBLjDaMFelIz +szskhsGalXAq5WP20aDog0eiEbf8oTa5NDPY1UZDnwDmF0lNDm4lsYGAv59h+8kU +ODGmmGVo5zrz7ujcU1sChc9iy9GlGEzekFAoEj6y9fbieyE4Wz6QW4nLeO1YZtjz +kvOi6yp2raNQSI4hwVEWNDK/AgMBAAGjgdgwgdUwHQYDVR0OBBYEFKXpmub0bNGS +gtwbyAUqu2kD1e8WMIGlBgNVHSMEgZ0wgZqAFKXpmub0bNGSgtwbyAUqu2kD1e8W +oXekdTBzMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFTGF6aW8xDTALBgNVBAcTBFJv +bWUxGTAXBgNVBAoTEENEU1YzIENvbnNvcnRpdW0xDjAMBgNVBAsTBVNwYWNlMRow +GAYDVQQDExF1bXNzb2lkcC5jZHN2My5ldYIJAJw83mLahxpQMAwGA1UdEwQFMAMB +Af8wDQYJKoZIhvcNAQEFBQADggEBAGMnf0UOmtKB2VF/TsjG1Lz7fJ48sySGC9R6 +TLy3lbUplogZsIBdt/cc+DP6O6l2z16hDb9B0X9QjJjO1qvM4oQPjlm8dZGCnyFV +EsstRM9EgOdnFIh16+q6x+u6c2XhnnLDdRsjsP7p53dT+iShgjI448voZDE3DLcs +b2eQu+iN5rmNfvg6DdaP/+2cvkoMvKL5dF+YRk5KNLn2vHi3Fti6uIpWAfgiICHr +dadCFX5qVlnadZP9Av35lM4VaDz+5eOFvjl1G+7+yEyaoi/m6gjrgrOI4Mqc1zcu +DhMOi9NqX4P9LSI1seXUf0feKA5wB+ei7MgqSSpooJc2PEnFyRg= + + + + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + diff --git a/shibauth/shibboleth-conf/idp-metadata.xml b/shibauth/shibboleth-conf/idp-metadata_samltest.xml similarity index 100% rename from shibauth/shibboleth-conf/idp-metadata.xml rename to shibauth/shibboleth-conf/idp-metadata_samltest.xml diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index 568b8f4d..424920c7 100755 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -8,7 +8,7 @@ REMOTE_USER="eppn uid persistent-id targeted-id"> - + SAML2 SAML2 Local @@ -19,7 +19,7 @@ - + -- GitLab From 289e44b31a7b7d27a348f56f593781269370a49a Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 14 Oct 2020 13:08:49 +0200 Subject: [PATCH 37/64] update certs with emg url as source --- shibauth/shibboleth-conf/shibboleth2.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index 424920c7..e3a18eaf 100755 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -4,7 +4,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" clockSkew="180"> - -- GitLab From 3c0266a6bcb2faf30b87987eb00f7542dc1eb398 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 14 Oct 2020 13:32:38 +0200 Subject: [PATCH 38/64] fix --- shibauth/shibboleth-conf/sp-metadata.xml | 76 ++++++++++++------------ 1 file changed, 38 insertions(+), 38 deletions(-) mode change 100755 => 100644 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml old mode 100755 new mode 100644 index 25280b3d..28a4e91f --- a/shibauth/shibboleth-conf/sp-metadata.xml +++ b/shibauth/shibboleth-conf/sp-metadata.xml @@ -2,7 +2,7 @@ This is example metadata only. Do *NOT* supply it as is without review, and do *NOT* provide it in real time to your partners. --> - + @@ -25,38 +25,38 @@ and do *NOT* provide it in real time to your partners. - + - https://https://shib.pdas.prism.eox.at/shibboleth - https://shib.pdas.prism.eox.at + https://emg.pdas.prism.eox.at + https://https://emg.pdas.prism.eox.at/shibboleth - CN=https://shib.pdas.prism.eox.at - MIIEVDCCArygAwIBAgIJANYdDHsBg6ulMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNV -BAMTHmh0dHBzOi8vc2hpYi5wZGFzLnByaXNtLmVveC5hdDAeFw0yMDEwMDgxNDI2 -MjBaFw0zMDEwMDYxNDI2MjBaMCkxJzAlBgNVBAMTHmh0dHBzOi8vc2hpYi5wZGFz -LnByaXNtLmVveC5hdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMKW -psgoJpT33XXQDzFiWXPkTW8deYIjaRN4iXuVpMa9/RpuQsSTTPCxwFXhp31lgsay -3DA3WNK5KVCx5ccnLbb5CiuZBrzFFttfzK1LIgf0rieGtpFj0cTEQwfFGM+3T/5p -cdTi/CyT7xUCGOn6rzU9NjIpQ7Z0DrIkN4vcRbljExMALZwrfg0E00JB/rg7nUga -Tc5rkM8DuqsvOe9IfRv9ZOe2sDimido13jzhE/Y/NTHtq8qleVxeT42P/hiZlJX4 -rioMtigG7nXmz0/6nfBR3y2tnViWURNF3DXy+7BAKIfTUU5Dy8diFpPVolEuoF3r -7hK+TMrOjOm+XZ/oyM2AlxiDGHtMMVkVs/m92jewUnyZoOYawCs0O/Eysri302Ve -e1S7oj67NRB2X/x98iejBYP76Y4ssJvKyYn96M+Va3B+SOfrdMLJwTUZxTQmFMmk -iJsyCM9b7ZNb745mClkcoTy22HtA0qtcnd/sZJ6ljOCe8RxA9fhFYu+5oO9SHQID -AQABo38wfTBcBgNVHREEVTBTgh5odHRwczovL3NoaWIucGRhcy5wcmlzbS5lb3gu -YXSGMWh0dHBzOi8vaHR0cHM6Ly9zaGliLnBkYXMucHJpc20uZW94LmF0L3NoaWJi -b2xldGgwHQYDVR0OBBYEFOj3ABr8n1Af0GDfg5+aYtGAFM3kMA0GCSqGSIb3DQEB -CwUAA4IBgQC9jN3ZLU6z6UCngdY16vlPdyMjIdko3/bstXlNWGvAwx0lPmPnV4b5 -ej+4l1vd3S3OAFYUKPJJG8rTInHt2tyYNIjytjIzYnonksdnS/iSlrd38q1FdWH8 -3ny1gyegunJutXqaFLHlBw77oNau8swXSegs/60pgYNNH+eMJbrToeAAM8zGqN1z -wXh4KWcwHmmH2ozJ468DYnv6I4/U9WydBoXNdQa3cKDv6/g4xfiyS4ByorVmNvOW -0C6OrCYwucS1CYxbmHk1E9ygIFEeKv1Z29leTIJxUHZXljfg7BDst2I2EfhyQ+fT -vB7rAipb+M2xckJJrCZJe5skBWsvP5ZcM3FA/GctWnc+5P/CO+2CZkdNFan7NBIx -focLOwyc7q3iCpqDxBY+EIkVlmSeg8mZdU9B9y0SkJxIcsePwSX8CSaFj5ndBY/T -aFiImaHsFzO4bZDEdaA0AdeJ5PalOTopbbVYO2FLMfvaXdu+GjDS6PGi/HrSX+P0 -FDXpx00p+0g= + CN=https://emg.pdas.prism.eox.at + MIIEUDCCArigAwIBAgIJAJtainQ0t+tRMA0GCSqGSIb3DQEBCwUAMCgxJjAkBgNV +BAMTHWh0dHBzOi8vZW1nLnBkYXMucHJpc20uZW94LmF0MB4XDTIwMTAxNDExMjcy +MFoXDTMwMTAxMjExMjcyMFowKDEmMCQGA1UEAxMdaHR0cHM6Ly9lbWcucGRhcy5w +cmlzbS5lb3guYXQwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDKkqzn +QsDnXSa+BHA10ZVkvw/PBfJVsby1C+zazCo32GpIHv5P+RFZj3FoC+N+gYatqijZ +57flt93krtqO/l/RrEosxwpWCXc54qXcFrPrlfXFr51dOW/BH6z1wpW9z67Pkr2M +v8Jqgs0t/k8BFlZ2jmiAZGrG+G+DrCefiy9JuKwBSiVh7Tg5P31fZv0qliNKwo5k +EbkeUuVrAvuNFV9NPdl35aevYZ0Mxy5N+/AbaaZScfmRnlTsRdHXL/k5anIceqk3 +k+qA1cHEXXqD7WtfQN4GQh9Oxqng//PBcH/9oe2h5axrkcw8YCC22YXp/OST4isk +lL1noCuRYPluvVDFqrh6z9S94QFuO3PdUckl7S7Gsty6X0MSYPYpBFZgivalIena +2vLC3sn5AGLrm3xmp4Io/iD0UtpnHHypCRghr8GE/yiZKPtq8bEk5d/NWMRgT5Ef +t77vZByeDxgN0Pl5gf8WtN0yKSPauxS3llNy9UFfoQP9OGV3FjzOo3DGuTUCAwEA +AaN9MHswWgYDVR0RBFMwUYIdaHR0cHM6Ly9lbWcucGRhcy5wcmlzbS5lb3guYXSG +MGh0dHBzOi8vaHR0cHM6Ly9lbWcucGRhcy5wcmlzbS5lb3guYXQvc2hpYmJvbGV0 +aDAdBgNVHQ4EFgQUzMF2sJVjzVscd6vLPMLWx2gD4uEwDQYJKoZIhvcNAQELBQAD +ggGBAIFFdjkcQyTWx30mwuJON4Bfi0IjBXyQ7YnbvB36sk9ohaPBz4uU1wKl5In+ +c/usuBgHS9JsBm2JIwnLKko6dS8h79pMnY8rDZxBxAPHkTUwTvzMraWHNXhblO9U +Oqp2NJqy4hyV1OzDWM5yYHiTSZIOewDS8inUvoDwUSYgQr9fSKljUmeI0In9f6wf +vvHA4hQQHVGYMNPO+rvpw8XeWZ8e+HdSxSM1RcL1m29s42HdycXTsmh4ghex4u16 +XvHNMGojW6ih0Oja69PKCraaLTUHPRjxwqx1ipaNbK/1pT7DPnLXHNGIOFW2JE9e +XIi3xy/d+C2Z/Ejwt4Xd+FVA9mhhbLkss7YI+SMJi73e31//sBiKOXBT1yBv8l0n +xTJsPmg2dbWQvNuJ89UIH8yPffcxdbT0xohgOiek+hBxZj0UU1ZSV5q2/X9aPKGZ +PMQ/PFgQJvdjegNZPupgBspcNlvYsdtln9vvyXWoNsNioSa6Uvntb8KEHnnh035S +VorGcA== @@ -70,15 +70,15 @@ FDXpx00p+0g= - - - - - - - - - + + + + + + + + + \ No newline at end of file -- GitLab From 933cd4c41181368677ed38ccb290d8c7f32d7fbc Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 27 Oct 2020 10:22:12 +0100 Subject: [PATCH 39/64] sample ac for emg, save work --- shibauth/etc-httpd/conf.d/sp.conf | 7 ++++--- shibauth/shibboleth-conf/attribute-map.xml | 5 ++--- shibauth/shibboleth-conf/pass-ac.xml | 9 +++++++++ 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 shibauth/shibboleth-conf/pass-ac.xml diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf index edfa7e84..ad617192 100755 --- a/shibauth/etc-httpd/conf.d/sp.conf +++ b/shibauth/etc-httpd/conf.d/sp.conf @@ -1,12 +1,13 @@ - ServerName https://emg.pdas.prism.eox.at:443 + ServerName PassEnv APACHE_SERVERNAME UseCanonicalName On DocumentRoot "/var/www/html" AuthType shibboleth ShibRequestSetting requireSession 1 - require shib-session - RequestHeader set Referer X-Forwarded-Uri env=X-Forwarded-Uri + ShibAccessControl /etc/shibboleth/pass-ac.xml + RequestHeader set Referer "%{X-Forwarded-Uri}e" + Header set Referer "%{X-Forwarded-Uri}e" \ No newline at end of file diff --git a/shibauth/shibboleth-conf/attribute-map.xml b/shibauth/shibboleth-conf/attribute-map.xml index e9e9797a..d20c5140 100755 --- a/shibauth/shibboleth-conf/attribute-map.xml +++ b/shibauth/shibboleth-conf/attribute-map.xml @@ -1,5 +1,4 @@ - - - + + diff --git a/shibauth/shibboleth-conf/pass-ac.xml b/shibauth/shibboleth-conf/pass-ac.xml new file mode 100644 index 00000000..13465660 --- /dev/null +++ b/shibauth/shibboleth-conf/pass-ac.xml @@ -0,0 +1,9 @@ + + + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + + .+ + + \ No newline at end of file -- GitLab From 9e0418378ec191c47a0a80947fa12b8d5e92f7a0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 27 Oct 2020 10:32:24 +0100 Subject: [PATCH 41/64] use certs as secrets --- docker-compose.base.ops.yml | 10 ++++++++++ shibauth/shibboleth-conf/shibboleth2.xml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index 56a2e14f..a307b9dd 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -31,6 +31,11 @@ services: - shib-extnet shibauth: image: testing-shibboleth + environment: + APACHE_SERVERNAME: "https://emg.pdas.prism.eox.at:443" + secrets: + - SHIB_CERT + - SHIB_KEY deploy: replicas: 1 placement: @@ -67,3 +72,8 @@ networks: name: logging-extnet shib-extnet: name: shib-extnet +secrets: + SHIB_CERT: + external: true + SHIB_KEY: + external: true diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/shibauth/shibboleth-conf/shibboleth2.xml index e3a18eaf..15399b0d 100755 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/shibauth/shibboleth-conf/shibboleth2.xml @@ -23,7 +23,7 @@ - + -- GitLab From 69620bed780dea094b6064d4151fb07b33151265 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 27 Oct 2020 19:11:38 +0100 Subject: [PATCH 42/64] fix apache config syntax --- shibauth/etc-httpd/conf.d/shib.conf | 2 +- shibauth/etc-httpd/conf.d/sp.conf | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf index 635aa462..cb82c34e 100755 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -1,7 +1,7 @@ -ServerName emg.pdas.prism.eox.at LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so ShibCompatValidUser Off UseCanonicalName On +DocumentRoot "/var/www/html" SetHandler shib diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf index ad617192..5186e84f 100755 --- a/shibauth/etc-httpd/conf.d/sp.conf +++ b/shibauth/etc-httpd/conf.d/sp.conf @@ -1,12 +1,10 @@ - ServerName PassEnv APACHE_SERVERNAME - UseCanonicalName On - - DocumentRoot "/var/www/html" + PassEnv APACHE_SERVERNAME + ServerName "${APACHE_SERVERNAME}" AuthType shibboleth ShibRequestSetting requireSession 1 - ShibAccessControl /etc/shibboleth/pass-ac.xml + Require shib-plugin /etc/shibboleth/pass-ac.xml RequestHeader set Referer "%{X-Forwarded-Uri}e" Header set Referer "%{X-Forwarded-Uri}e" -- GitLab From 405f1e216003122b9a8ad172b9bcbaa950c0de3d Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 28 Oct 2020 10:48:01 +0100 Subject: [PATCH 43/64] [shibauth] update docker compose files for other collections --- docker-compose.base.ops.yml | 37 ----------------------------- docker-compose.dem.ops.yml | 44 ++++++++++++++++++++++++++++++++++ docker-compose.emg.ops.yml | 44 ++++++++++++++++++++++++++++++++++ docker-compose.vhr18.ops.yml | 46 ++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 37 deletions(-) diff --git a/docker-compose.base.ops.yml b/docker-compose.base.ops.yml index d4a0eb35..002a236d 100644 --- a/docker-compose.base.ops.yml +++ b/docker-compose.base.ops.yml @@ -28,40 +28,9 @@ services: - emg-extnet - dem-extnet - logging-extnet - - shib-extnet secrets: - BASIC_AUTH_USERS_APIAUTH - BASIC_AUTH_USERS_AUTH - shibauth: - image: testing-shibboleth - environment: - APACHE_SERVERNAME: "https://emg.pdas.prism.eox.at:443" - secrets: - - SHIB_CERT - - SHIB_KEY - deploy: - replicas: 1 - placement: - constraints: [node.role == manager] - labels: - # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`emg.pdas.prism.eox.at`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - - "traefik.http.routers.shibauth.tls=true" - - "traefik.http.routers.shibauth.tls.certresolver=default" - - "traefik.http.routers.shibauth.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`emg.pdas.prism.eox.at`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - - "traefik.http.routers.shibauth-redirect.entrypoints=http" - # general - - "traefik.http.services.shibauth.loadbalancer.sticky=false" - - "traefik.http.services.shibauth.loadbalancer.server.port=80" - - "traefik.docker.network=shib-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" - networks: - - shib-extnet volumes: traefik-data: networks: @@ -73,13 +42,7 @@ networks: name: dem-extnet logging-extnet: name: logging-extnet - shib-extnet: - name: shib-extnet secrets: - SHIB_CERT: - external: true - SHIB_KEY: - external: true BASIC_AUTH_USERS_APIAUTH: external: true BASIC_AUTH_USERS_AUTH: diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index cb1223d8..72615fca 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -165,7 +165,51 @@ services: placement: constraints: - node.labels.type == internal + shibauth: + image: testing-shibboleth + environment: + APACHE_SERVERNAME: "https://dem-secure.pass.copernicus.eu:443" + secrets: + - SHIB_CERT + - SHIB_KEY + - BASIC_AUTH_USERS_AUTH + deploy: + replicas: 1 + placement: + constraints: [node.role == manager] + labels: + # router for basic auth based access (https) + - "traefik.http.routers.shibauth.rule=Host(`dem-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + - "traefik.http.routers.shibauth.tls=true" + - "traefik.http.routers.shibauth.tls.certresolver=default" + - "traefik.http.routers.shibauth.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.shibauth-redirect.rule=Host(`dem-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + - "traefik.http.routers.shibauth-redirect.entrypoints=http" + # general + - "traefik.http.services.shibauth.loadbalancer.sticky=false" + - "traefik.http.services.shibauth.loadbalancer.server.port=80" + - "traefik.docker.network=dem-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + networks: + - dem-extnet + configs: + - source: access-control-conf + target: /etc/shibboleth/pass-ac.xml networks: extnet: name: dem-extnet external: true +configs: + access-control-conf: + file: ./config/dem_pass-ac.xml +secrets: + SHIB_CERT: + external: true + SHIB_KEY: + external: true + BASIC_AUTH_USERS_AUTH: + external: true diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 4f344da8..30ab1f09 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -155,7 +155,51 @@ services: placement: constraints: - node.labels.type == internal + shibauth: + image: testing-shibboleth + environment: + APACHE_SERVERNAME: "https://emg-secure.pass.copernicus.eu:443" + secrets: + - SHIB_CERT + - SHIB_KEY + - BASIC_AUTH_USERS_AUTH + deploy: + replicas: 1 + placement: + constraints: [node.role == manager] + labels: + # router for basic auth based access (https) + - "traefik.http.routers.shibauth.rule=Host(`emg-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + - "traefik.http.routers.shibauth.tls=true" + - "traefik.http.routers.shibauth.tls.certresolver=default" + - "traefik.http.routers.shibauth.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.shibauth-redirect.rule=Host(`emg-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + - "traefik.http.routers.shibauth-redirect.entrypoints=http" + # general + - "traefik.http.services.shibauth.loadbalancer.sticky=false" + - "traefik.http.services.shibauth.loadbalancer.server.port=80" + - "traefik.docker.network=emg-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + networks: + - emg-extnet + configs: + - source: access-control-conf + target: /etc/shibboleth/pass-ac.xml networks: extnet: name: emg-extnet external: true +configs: + access-control-conf: + file: ./config/emg_pass-ac.xml +secrets: + SHIB_CERT: + external: true + SHIB_KEY: + external: true + BASIC_AUTH_USERS_AUTH: + external: true diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 738fc6f0..7ce490bc 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -165,7 +165,53 @@ services: placement: constraints: - node.labels.type == internal + shibauth: + image: testing-shibboleth + environment: + APACHE_SERVERNAME: "https://vhr18-secure.pass.copernicus.eu:443" + secrets: + - SHIB_CERT + - SHIB_KEY + - BASIC_AUTH_USERS_AUTH + deploy: + replicas: 1 + placement: + constraints: [node.role == manager] + labels: + # router for basic auth based access (https) + - "traefik.http.routers.shibauth.rule=Host(`vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" + - "traefik.http.routers.shibauth.tls=true" + - "traefik.http.routers.shibauth.tls.certresolver=default" + - "traefik.http.routers.shibauth.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.shibauth-redirect.rule=Host(`vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" + - "traefik.http.routers.shibauth-redirect.entrypoints=http" + # general + - "traefik.http.services.shibauth.loadbalancer.sticky=false" + - "traefik.http.services.shibauth.loadbalancer.server.port=80" + - "traefik.docker.network=vhr18-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + networks: + - vhr18-extnet + configs: + - source: access-control-conf + target: /etc/shibboleth/pass-ac.xml networks: extnet: name: vhr18-extnet external: true +configs: + access-control-conf: + file: ./config/vhr18_pass-ac.xml +secrets: + SHIB_CERT: + external: true + SHIB_KEY: + external: true + BASIC_AUTH_USERS_APIAUTH: + external: true + BASIC_AUTH_USERS_AUTH: + external: true -- GitLab From c2d3e07eb59009379a416c16e89438a72f96b09b Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 28 Oct 2020 12:15:42 +0100 Subject: [PATCH 44/64] access control as external config --- .../pass-ac.xml => config/dem_pass-ac.xml | 0 config/emg_pass-ac.xml | 9 +++++++++ config/vhr18_pass-ac.xml | 9 +++++++++ 3 files changed, 18 insertions(+) rename shibauth/shibboleth-conf/pass-ac.xml => config/dem_pass-ac.xml (100%) create mode 100644 config/emg_pass-ac.xml create mode 100644 config/vhr18_pass-ac.xml diff --git a/shibauth/shibboleth-conf/pass-ac.xml b/config/dem_pass-ac.xml similarity index 100% rename from shibauth/shibboleth-conf/pass-ac.xml rename to config/dem_pass-ac.xml diff --git a/config/emg_pass-ac.xml b/config/emg_pass-ac.xml new file mode 100644 index 00000000..13465660 --- /dev/null +++ b/config/emg_pass-ac.xml @@ -0,0 +1,9 @@ + + + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + + .+ + + \ No newline at end of file diff --git a/config/vhr18_pass-ac.xml b/config/vhr18_pass-ac.xml new file mode 100644 index 00000000..13465660 --- /dev/null +++ b/config/vhr18_pass-ac.xml @@ -0,0 +1,9 @@ + + + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + + .+ + + \ No newline at end of file -- GitLab From 934956e9730a602720e4255079efc96e43c07981 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 28 Oct 2020 12:16:12 +0100 Subject: [PATCH 45/64] enable basicAuth in apache using secret users file --- docker-compose.dem.ops.yml | 40 ++++------------------------- docker-compose.emg.ops.yml | 30 ++++------------------ docker-compose.test.ops.yml | 31 ---------------------- docker-compose.vhr18.ops.yml | 40 ++++------------------------- shibauth/etc-httpd/conf.d/shib.conf | 24 ++++++++++++++++- shibauth/etc-httpd/conf.d/sp.conf | 11 -------- 6 files changed, 38 insertions(+), 138 deletions(-) delete mode 100644 docker-compose.test.ops.yml delete mode 100755 shibauth/etc-httpd/conf.d/sp.conf diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 72615fca..283fc571 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.dem-renderer.middlewares=shibAuth@file,compress@file,cors@file" - "traefik.http.routers.dem-renderer.tls=true" - "traefik.http.routers.dem-renderer.tls.certresolver=default" - "traefik.http.routers.dem-renderer.entrypoints=https" @@ -32,16 +32,6 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.dem-renderer-shib.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.dem-renderer-shib.tls=true" - - "traefik.http.routers.dem-renderer-shib.tls.certresolver=default" - - "traefik.http.routers.dem-renderer-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.dem-renderer-shib-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`, `a.dem-secure.pass.copernicus.eu`, `b.dem-secure.pass.copernicus.eu`, `c.dem-secure.pass.copernicus.eu`, `d.dem-secure.pass.copernicus.eu`, `e.dem-secure.pass.copernicus.eu`, `f.dem-secure.pass.copernicus.eu`, `g.dem-secure.pass.copernicus.eu`, `h.dem-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -66,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.dem-cache.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.dem-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.dem-cache.tls=true" - "traefik.http.routers.dem-cache.tls.certresolver=default" - "traefik.http.routers.dem-cache.entrypoints=https" @@ -84,16 +74,6 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.dem-cache-shib.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-cache-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.dem-cache-shib.tls=true" - - "traefik.http.routers.dem-cache-shib.tls.certresolver=default" - - "traefik.http.routers.dem-cache-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.dem-cache-shib-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `a.dem-secure.pdas.prism.eox.at`, `b.dem-secure.pdas.prism.eox.at`, `c.dem-secure.pdas.prism.eox.at`, `d.dem-secure.pdas.prism.eox.at`, `e.dem-secure.pdas.prism.eox.at`, `f.dem-secure.pdas.prism.eox.at`, `g.dem-secure.pdas.prism.eox.at`, `h.dem-secure.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-cache-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-cache-shib-redirect.entrypoints=http" # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" @@ -134,16 +114,6 @@ services: - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-client-redirect.entrypoints=http" - # router for basic auth based access (https) - - "traefik.http.routers.dem-client.rule=Host(`dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client.middlewares=shibAuth@file,compress@file" - - "traefik.http.routers.dem-client.tls=true" - - "traefik.http.routers.dem-client.tls.certresolver=default" - - "traefik.http.routers.dem-client.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.dem-client-redirect.rule=Host(`dem-secure.pdas.prism.eox.at`, `dem-secure.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-client-redirect.entrypoints=http" # general - "traefik.http.services.dem-client.loadbalancer.sticky=false" - "traefik.http.services.dem-client.loadbalancer.server.port=80" @@ -168,7 +138,7 @@ services: shibauth: image: testing-shibboleth environment: - APACHE_SERVERNAME: "https://dem-secure.pass.copernicus.eu:443" + APACHE_SERVERNAME: "https://dem.pass.copernicus.eu:443" secrets: - SHIB_CERT - SHIB_KEY @@ -179,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`dem-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`dem-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 30ab1f09..17528ced 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.emg-renderer.middlewares=shibAuth@file,compress@file,cors@file" - "traefik.http.routers.emg-renderer.tls=true" - "traefik.http.routers.emg-renderer.tls.certresolver=default" - "traefik.http.routers.emg-renderer.entrypoints=https" @@ -32,16 +32,6 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-renderer-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.emg-renderer-shib.tls=true" - - "traefik.http.routers.emg-renderer-shib.tls.certresolver=default" - - "traefik.http.routers.emg-renderer-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-renderer-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -66,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.emg-cache.tls=true" - "traefik.http.routers.emg-cache.tls.certresolver=default" - "traefik.http.routers.emg-cache.entrypoints=https" @@ -84,16 +74,6 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.emg-cache-shib.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-cache-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.emg-cache-shib.tls=true" - - "traefik.http.routers.emg-cache-shib.tls.certresolver=default" - - "traefik.http.routers.emg-cache-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.emg-cache-shib-redirect.rule=Host(`emg-secure.pdas.prism.eox.at`, `a.emg-secure.pdas.prism.eox.at`, `b.emg-secure.pdas.prism.eox.at`, `c.emg-secure.pdas.prism.eox.at`, `d.emg-secure.pdas.prism.eox.at`, `e.emg-secure.pdas.prism.eox.at`, `f.emg-secure.pdas.prism.eox.at`, `g.emg-secure.pdas.prism.eox.at`, `h.emg-secure.pdas.prism.eox.at`, `emg-secure.pass.copernicus.eu`, `a.emg-secure.pass.copernicus.eu`, `b.emg-secure.pass.copernicus.eu`, `c.emg-secure.pass.copernicus.eu`, `d.emg-secure.pass.copernicus.eu`, `e.emg-secure.pass.copernicus.eu`, `f.emg-secure.pass.copernicus.eu`, `g.emg-secure.pass.copernicus.eu`, `h.emg-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-cache-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-cache-shib-redirect.entrypoints=http" # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" @@ -158,7 +138,7 @@ services: shibauth: image: testing-shibboleth environment: - APACHE_SERVERNAME: "https://emg-secure.pass.copernicus.eu:443" + APACHE_SERVERNAME: "https://emg.pass.copernicus.eu:443" secrets: - SHIB_CERT - SHIB_KEY @@ -169,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`emg-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`emg-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general diff --git a/docker-compose.test.ops.yml b/docker-compose.test.ops.yml deleted file mode 100644 index df6bd812..00000000 --- a/docker-compose.test.ops.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: "3.6" -services: - shibauth: - image: testing-shibboleth - deploy: - labels: - # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`shib.pdas.prism.eox.at`)" - - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - - "traefik.http.routers.shibauth.tls=true" - - "traefik.http.routers.shibauth.tls.certresolver=default" - - "traefik.http.routers.shibauth.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`shib.pdas.prism.eox.at`)" - - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - - "traefik.http.routers.shibauth-redirect.entrypoints=http" - # general - - "traefik.http.services.shibauth.loadbalancer.sticky=false" - - "traefik.http.services.shibauth.loadbalancer.server.port=80" - - "traefik.docker.network=shib-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" - replicas: 1 - placement: - constraints: [node.role == manager] - networks: - - extnet -networks: - extnet: - name: shib-extnet - external: true diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 7ce490bc..9466f7f4 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -15,7 +15,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer.middlewares=shibAuth@file,compress@file,cors@file" - "traefik.http.routers.vhr18-renderer.tls=true" - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - "traefik.http.routers.vhr18-renderer.entrypoints=https" @@ -33,16 +33,6 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-renderer-shib.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.vhr18-renderer-shib.tls=true" - - "traefik.http.routers.vhr18-renderer-shib.tls.certresolver=default" - - "traefik.http.routers.vhr18-renderer-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-renderer-shib-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -66,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.vhr18-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.vhr18-cache.tls=true" - "traefik.http.routers.vhr18-cache.tls.certresolver=default" - "traefik.http.routers.vhr18-cache.entrypoints=https" @@ -84,16 +74,6 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" - # router for shibboleth based auth based access (https) - - "traefik.http.routers.vhr18-cache-renderer-shib.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-cache-renderer-shib.middlewares=compress@file,cors@file,shibAuth@file" - - "traefik.http.routers.vhr18-cache-renderer-shib.tls=true" - - "traefik.http.routers.vhr18-cache-renderer-shib.tls.certresolver=default" - - "traefik.http.routers.vhr18-cache-renderer-shib.entrypoints=https" - # router for shibboleth shibboleth auth based access (http) - - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `a.vhr18-secure.pdas.prism.eox.at`, `b.vhr18-secure.pdas.prism.eox.at`, `c.vhr18-secure.pdas.prism.eox.at`, `d.vhr18-secure.pdas.prism.eox.at`, `e.vhr18-secure.pdas.prism.eox.at`, `f.vhr18-secure.pdas.prism.eox.at`, `g.vhr18-secure.pdas.prism.eox.at`, `h.vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`, `a.vhr18-secure.pass.copernicus.eu`, `b.vhr18-secure.pass.copernicus.eu`, `c.vhr18-secure.pass.copernicus.eu`, `d.vhr18-secure.pass.copernicus.eu`, `e.vhr18-secure.pass.copernicus.eu`, `f.vhr18-secure.pass.copernicus.eu`, `g.vhr18-secure.pass.copernicus.eu`, `h.vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-cache-renderer-shib-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" @@ -134,16 +114,6 @@ services: - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" - # router for basic auth based access (https) - - "traefik.http.routers.vhr18-client.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`)" - - "traefik.http.routers.vhr18-client.middlewares=shibAuth@file,compress@file" - - "traefik.http.routers.vhr18-client.tls=true" - - "traefik.http.routers.vhr18-client.tls.certresolver=default" - - "traefik.http.routers.vhr18-client.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18-secure.pdas.prism.eox.at`, `vhr18-secure.pass.copernicus.eu`)" - - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-client.loadbalancer.sticky=false" - "traefik.http.services.vhr18-client.loadbalancer.server.port=80" @@ -168,7 +138,7 @@ services: shibauth: image: testing-shibboleth environment: - APACHE_SERVERNAME: "https://vhr18-secure.pass.copernicus.eu:443" + APACHE_SERVERNAME: "https://vhr18.pass.copernicus.eu:443" secrets: - SHIB_CERT - SHIB_KEY @@ -179,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`vhr18-secure.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/shibauth/etc-httpd/conf.d/shib.conf index cb82c34e..91216960 100755 --- a/shibauth/etc-httpd/conf.d/shib.conf +++ b/shibauth/etc-httpd/conf.d/shib.conf @@ -1,7 +1,29 @@ LoadModule mod_shib /usr/lib64/shibboleth/mod_shib_24.so -ShibCompatValidUser Off +ShibCompatValidUser On UseCanonicalName On DocumentRoot "/var/www/html" + SetHandler shib + + + PassEnv APACHE_SERVERNAME + ServerName "${APACHE_SERVERNAME}" + + + Require valid-user + AuthType Basic + AuthBasicProvider file + AuthName "/secure" + AuthUserFile /run/secrets/BASIC_AUTH_USERS_AUTH + + + AuthType shibboleth + ShibRequestSetting requireSession 1 + Require shib-plugin /etc/shibboleth/pass-ac.xml + RequestHeader set Referer "%{X-Forwarded-Uri}e" + Header set Referer "%{X-Forwarded-Uri}e" + + + \ No newline at end of file diff --git a/shibauth/etc-httpd/conf.d/sp.conf b/shibauth/etc-httpd/conf.d/sp.conf deleted file mode 100755 index 5186e84f..00000000 --- a/shibauth/etc-httpd/conf.d/sp.conf +++ /dev/null @@ -1,11 +0,0 @@ - - PassEnv APACHE_SERVERNAME - ServerName "${APACHE_SERVERNAME}" - - AuthType shibboleth - ShibRequestSetting requireSession 1 - Require shib-plugin /etc/shibboleth/pass-ac.xml - RequestHeader set Referer "%{X-Forwarded-Uri}e" - Header set Referer "%{X-Forwarded-Uri}e" - - \ No newline at end of file -- GitLab From 6e64fafd17d94a437bd8192587e7b9160edb381e Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 28 Oct 2020 14:09:34 +0100 Subject: [PATCH 46/64] move shibboleth related files to config/shibboleth, use source image directly --- .../shibboleth}/attribute-map.xml | 0 config/{ => shibboleth}/dem_pass-ac.xml | 0 config/{ => shibboleth}/emg_pass-ac.xml | 0 {shibauth => config/shibboleth}/index.html | 0 .../shibboleth}/native.logger | 0 .../shibboleth/shib-apache.conf | 0 .../shibboleth}/shibboleth2.xml | 2 +- .../shibboleth}/shibd.logger | 0 config/{ => shibboleth}/vhr18_pass-ac.xml | 0 docker-compose.dem.ops.yml | 34 ++++- docker-compose.emg.ops.yml | 34 ++++- docker-compose.vhr18.ops.yml | 36 +++++- shibauth/Dockerfile | 39 ------ .../shibboleth-conf/idp-metadata-esa-test.xml | 116 ------------------ .../shibboleth-conf/idp-metadata_samltest.xml | 98 --------------- shibauth/shibboleth-conf/sp-metadata.xml | 84 ------------- 16 files changed, 94 insertions(+), 349 deletions(-) rename {shibauth/shibboleth-conf => config/shibboleth}/attribute-map.xml (100%) rename config/{ => shibboleth}/dem_pass-ac.xml (100%) rename config/{ => shibboleth}/emg_pass-ac.xml (100%) rename {shibauth => config/shibboleth}/index.html (100%) mode change 100755 => 100644 rename {shibauth/shibboleth-conf => config/shibboleth}/native.logger (100%) rename shibauth/etc-httpd/conf.d/shib.conf => config/shibboleth/shib-apache.conf (100%) rename {shibauth/shibboleth-conf => config/shibboleth}/shibboleth2.xml (98%) rename {shibauth/shibboleth-conf => config/shibboleth}/shibd.logger (100%) rename config/{ => shibboleth}/vhr18_pass-ac.xml (100%) delete mode 100755 shibauth/Dockerfile delete mode 100644 shibauth/shibboleth-conf/idp-metadata-esa-test.xml delete mode 100755 shibauth/shibboleth-conf/idp-metadata_samltest.xml delete mode 100644 shibauth/shibboleth-conf/sp-metadata.xml diff --git a/shibauth/shibboleth-conf/attribute-map.xml b/config/shibboleth/attribute-map.xml similarity index 100% rename from shibauth/shibboleth-conf/attribute-map.xml rename to config/shibboleth/attribute-map.xml diff --git a/config/dem_pass-ac.xml b/config/shibboleth/dem_pass-ac.xml similarity index 100% rename from config/dem_pass-ac.xml rename to config/shibboleth/dem_pass-ac.xml diff --git a/config/emg_pass-ac.xml b/config/shibboleth/emg_pass-ac.xml similarity index 100% rename from config/emg_pass-ac.xml rename to config/shibboleth/emg_pass-ac.xml diff --git a/shibauth/index.html b/config/shibboleth/index.html old mode 100755 new mode 100644 similarity index 100% rename from shibauth/index.html rename to config/shibboleth/index.html diff --git a/shibauth/shibboleth-conf/native.logger b/config/shibboleth/native.logger similarity index 100% rename from shibauth/shibboleth-conf/native.logger rename to config/shibboleth/native.logger diff --git a/shibauth/etc-httpd/conf.d/shib.conf b/config/shibboleth/shib-apache.conf similarity index 100% rename from shibauth/etc-httpd/conf.d/shib.conf rename to config/shibboleth/shib-apache.conf diff --git a/shibauth/shibboleth-conf/shibboleth2.xml b/config/shibboleth/shibboleth2.xml similarity index 98% rename from shibauth/shibboleth-conf/shibboleth2.xml rename to config/shibboleth/shibboleth2.xml index 15399b0d..2504a528 100755 --- a/shibauth/shibboleth-conf/shibboleth2.xml +++ b/config/shibboleth/shibboleth2.xml @@ -19,7 +19,7 @@ - + diff --git a/shibauth/shibboleth-conf/shibd.logger b/config/shibboleth/shibd.logger similarity index 100% rename from shibauth/shibboleth-conf/shibd.logger rename to config/shibboleth/shibd.logger diff --git a/config/vhr18_pass-ac.xml b/config/shibboleth/vhr18_pass-ac.xml similarity index 100% rename from config/vhr18_pass-ac.xml rename to config/shibboleth/vhr18_pass-ac.xml diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 283fc571..1459c1f1 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -136,7 +136,7 @@ services: constraints: - node.labels.type == internal shibauth: - image: testing-shibboleth + image: unicon/shibboleth-sp:3.0.4 environment: APACHE_SERVERNAME: "https://dem.pass.copernicus.eu:443" secrets: @@ -169,13 +169,41 @@ services: configs: - source: access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-shibboleth2 + target: /etc/shibboleth/shibboleth2.xml + - source: shib-apache + target: /etc/httpd/conf.d/shib.conf + - source: shib-attribute-map + target: /etc/shibboleth/attribute-map.xml + - source: idp-metadata + target: /etc/shibboleth/idp-metadata.xml + - source: shib-index + target: /var/www/html/secure/index.html + - source: shibd-logger + target: /etc/shibboleth/shibd.logger + - source: native-logger + target: /etc/shibboleth/native.logger networks: extnet: name: dem-extnet external: true configs: - access-control-conf: - file: ./config/dem_pass-ac.xml + shib-access-control-conf: + file: ./config/shibboleth/dem_pass-ac.xml + shib-shibboleth2: # this will vary for collections + file: ./config/shibboleth/shibboleth2.xml + shib-apache: + file: ./config/shibboleth/shib-apache.conf + shib-attribute-map: + file: ./config/shibboleth/attribute-map.xml + shib-index: + file: ./config/shibboleth/index.html + native-logger: + file: ./config/shibboleth/native.logger + shibd-logger: + file: ./config/shibboleth/shibd.logger + idp-metadata: + external: true secrets: SHIB_CERT: external: true diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 17528ced..0c4f9978 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -136,7 +136,7 @@ services: constraints: - node.labels.type == internal shibauth: - image: testing-shibboleth + image: unicon/shibboleth-sp:3.0.4 environment: APACHE_SERVERNAME: "https://emg.pass.copernicus.eu:443" secrets: @@ -169,13 +169,41 @@ services: configs: - source: access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-shibboleth2 + target: /etc/shibboleth/shibboleth2.xml + - source: shib-apache + target: /etc/httpd/conf.d/shib.conf + - source: shib-attribute-map + target: /etc/shibboleth/attribute-map.xml + - source: idp-metadata + target: /etc/shibboleth/idp-metadata.xml + - source: shib-index + target: /var/www/html/secure/index.html + - source: shibd-logger + target: /etc/shibboleth/shibd.logger + - source: native-logger + target: /etc/shibboleth/native.logger networks: extnet: name: emg-extnet external: true configs: - access-control-conf: - file: ./config/emg_pass-ac.xml + shib-access-control-conf: + file: ./config/shibboleth/emg_pass-ac.xml + shib-shibboleth2: # this will vary for collections + file: ./config/shibboleth/shibboleth2.xml + shib-apache: + file: ./config/shibboleth/shib-apache.conf + shib-attribute-map: + file: ./config/shibboleth/attribute-map.xml + shib-index: + file: ./config/shibboleth/index.html + native-logger: + file: ./config/shibboleth/native.logger + shibd-logger: + file: ./config/shibboleth/shibd.logger + idp-metadata: + external: true secrets: SHIB_CERT: external: true diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 9466f7f4..f82fd145 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -136,7 +136,7 @@ services: constraints: - node.labels.type == internal shibauth: - image: testing-shibboleth + image: unicon/shibboleth-sp:3.0.4 environment: APACHE_SERVERNAME: "https://vhr18.pass.copernicus.eu:443" secrets: @@ -169,19 +169,45 @@ services: configs: - source: access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-shibboleth2 + target: /etc/shibboleth/shibboleth2.xml + - source: shib-apache + target: /etc/httpd/conf.d/shib.conf + - source: shib-attribute-map + target: /etc/shibboleth/attribute-map.xml + - source: shib-idp-metadata + target: /etc/shibboleth/idp-metadata.xml + - source: shib-index + target: /var/www/html/secure/index.html + - source: shibd-logger + target: /etc/shibboleth/shibd.logger + - source: native-logger + target: /etc/shibboleth/native.logger networks: extnet: name: vhr18-extnet external: true configs: - access-control-conf: - file: ./config/vhr18_pass-ac.xml + shib-access-control-conf: + file: ./config/shibboleth/vhr18_pass-ac.xml + shib-shibboleth2: # this will vary for collections + file: ./config/shibboleth/shibboleth2.xml + shib-apache: + file: ./config/shibboleth/shib-apache.conf + shib-attribute-map: + file: ./config/shibboleth/attribute-map.xml + native-logger: + file: ./config/shibboleth/native.logger + shibd-logger: + file: ./config/shibboleth/shibd.logger + shib-index: + file: ./config/shibboleth/index.html + shib-idp-metadata: + external: true secrets: SHIB_CERT: external: true SHIB_KEY: external: true - BASIC_AUTH_USERS_APIAUTH: - external: true BASIC_AUTH_USERS_AUTH: external: true diff --git a/shibauth/Dockerfile b/shibauth/Dockerfile deleted file mode 100755 index 88efe7cb..00000000 --- a/shibauth/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -#------------------------------------------------------------------------------ -# -# Project: prism view server -# Authors: Stephan Meissl -# -#------------------------------------------------------------------------------ -# Copyright (C) 2020 EOX IT Services GmbH -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies of this Software or works derived from this Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -#----------------------------------------------------------------------------- - -FROM unicon/shibboleth-sp:3.0.4 - -MAINTAINER EOX -LABEL name="prism view server cache" \ - vendor="EOX IT Services GmbH " \ - license="MIT Copyright (C) 2019 EOX IT Services GmbH " \ - type="prism view server shibauth" \ - version="0.0.1" -RUN mkdir -p /var/www/secure -COPY shibboleth-conf /etc/shibboleth/ -COPY etc-httpd/ /etc/httpd/ -COPY index.html /var/www/html/secure diff --git a/shibauth/shibboleth-conf/idp-metadata-esa-test.xml b/shibauth/shibboleth-conf/idp-metadata-esa-test.xml deleted file mode 100644 index 647078b2..00000000 --- a/shibauth/shibboleth-conf/idp-metadata-esa-test.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - esa.int - - - - - - -MIIEQjCCAyqgAwIBAgIJAJw83mLahxpQMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV -BAYTAklUMQ4wDAYDVQQIEwVMYXppbzENMAsGA1UEBxMEUm9tZTEZMBcGA1UEChMQ -Q0RTVjMgQ29uc29ydGl1bTEOMAwGA1UECxMFU3BhY2UxGjAYBgNVBAMTEXVtc3Nv -aWRwLmNkc3YzLmV1MB4XDTE1MDQwMjE2Mzg1M1oXDTI1MDMzMDE2Mzg1M1owczEL -MAkGA1UEBhMCSVQxDjAMBgNVBAgTBUxhemlvMQ0wCwYDVQQHEwRSb21lMRkwFwYD -VQQKExBDRFNWMyBDb25zb3J0aXVtMQ4wDAYDVQQLEwVTcGFjZTEaMBgGA1UEAxMR -dW1zc29pZHAuY2RzdjMuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCrDTGZEQj7uMw347TnyMac0HnkLY046e/4V+boJBuQsP7Moxh6xHH2qcdS2UbW -xtSBOUuS/aAz92udzY8wBrKUUvvWKEnyh3v84+kfNYugBp4ZpW7pJbfUh9KjUvWh -G3LtZfyuRaCdyYF6TKh0K+96IRSpwe5wFXqRev7a6+8fDcTL73cFFBLjDaMFelIz -szskhsGalXAq5WP20aDog0eiEbf8oTa5NDPY1UZDnwDmF0lNDm4lsYGAv59h+8kU -ODGmmGVo5zrz7ujcU1sChc9iy9GlGEzekFAoEj6y9fbieyE4Wz6QW4nLeO1YZtjz -kvOi6yp2raNQSI4hwVEWNDK/AgMBAAGjgdgwgdUwHQYDVR0OBBYEFKXpmub0bNGS -gtwbyAUqu2kD1e8WMIGlBgNVHSMEgZ0wgZqAFKXpmub0bNGSgtwbyAUqu2kD1e8W -oXekdTBzMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFTGF6aW8xDTALBgNVBAcTBFJv -bWUxGTAXBgNVBAoTEENEU1YzIENvbnNvcnRpdW0xDjAMBgNVBAsTBVNwYWNlMRow -GAYDVQQDExF1bXNzb2lkcC5jZHN2My5ldYIJAJw83mLahxpQMAwGA1UdEwQFMAMB -Af8wDQYJKoZIhvcNAQEFBQADggEBAGMnf0UOmtKB2VF/TsjG1Lz7fJ48sySGC9R6 -TLy3lbUplogZsIBdt/cc+DP6O6l2z16hDb9B0X9QjJjO1qvM4oQPjlm8dZGCnyFV -EsstRM9EgOdnFIh16+q6x+u6c2XhnnLDdRsjsP7p53dT+iShgjI448voZDE3DLcs -b2eQu+iN5rmNfvg6DdaP/+2cvkoMvKL5dF+YRk5KNLn2vHi3Fti6uIpWAfgiICHr -dadCFX5qVlnadZP9Av35lM4VaDz+5eOFvjl1G+7+yEyaoi/m6gjrgrOI4Mqc1zcu -DhMOi9NqX4P9LSI1seXUf0feKA5wB+ei7MgqSSpooJc2PEnFyRg= - - - - - - - - - - urn:mace:shibboleth:1.0:nameIdentifier - urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - - - - - - - - - - - esa.int - - - - - - -MIIEQjCCAyqgAwIBAgIJAJw83mLahxpQMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV -BAYTAklUMQ4wDAYDVQQIEwVMYXppbzENMAsGA1UEBxMEUm9tZTEZMBcGA1UEChMQ -Q0RTVjMgQ29uc29ydGl1bTEOMAwGA1UECxMFU3BhY2UxGjAYBgNVBAMTEXVtc3Nv -aWRwLmNkc3YzLmV1MB4XDTE1MDQwMjE2Mzg1M1oXDTI1MDMzMDE2Mzg1M1owczEL -MAkGA1UEBhMCSVQxDjAMBgNVBAgTBUxhemlvMQ0wCwYDVQQHEwRSb21lMRkwFwYD -VQQKExBDRFNWMyBDb25zb3J0aXVtMQ4wDAYDVQQLEwVTcGFjZTEaMBgGA1UEAxMR -dW1zc29pZHAuY2RzdjMuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCrDTGZEQj7uMw347TnyMac0HnkLY046e/4V+boJBuQsP7Moxh6xHH2qcdS2UbW -xtSBOUuS/aAz92udzY8wBrKUUvvWKEnyh3v84+kfNYugBp4ZpW7pJbfUh9KjUvWh -G3LtZfyuRaCdyYF6TKh0K+96IRSpwe5wFXqRev7a6+8fDcTL73cFFBLjDaMFelIz -szskhsGalXAq5WP20aDog0eiEbf8oTa5NDPY1UZDnwDmF0lNDm4lsYGAv59h+8kU -ODGmmGVo5zrz7ujcU1sChc9iy9GlGEzekFAoEj6y9fbieyE4Wz6QW4nLeO1YZtjz -kvOi6yp2raNQSI4hwVEWNDK/AgMBAAGjgdgwgdUwHQYDVR0OBBYEFKXpmub0bNGS -gtwbyAUqu2kD1e8WMIGlBgNVHSMEgZ0wgZqAFKXpmub0bNGSgtwbyAUqu2kD1e8W -oXekdTBzMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFTGF6aW8xDTALBgNVBAcTBFJv -bWUxGTAXBgNVBAoTEENEU1YzIENvbnNvcnRpdW0xDjAMBgNVBAsTBVNwYWNlMRow -GAYDVQQDExF1bXNzb2lkcC5jZHN2My5ldYIJAJw83mLahxpQMAwGA1UdEwQFMAMB -Af8wDQYJKoZIhvcNAQEFBQADggEBAGMnf0UOmtKB2VF/TsjG1Lz7fJ48sySGC9R6 -TLy3lbUplogZsIBdt/cc+DP6O6l2z16hDb9B0X9QjJjO1qvM4oQPjlm8dZGCnyFV -EsstRM9EgOdnFIh16+q6x+u6c2XhnnLDdRsjsP7p53dT+iShgjI448voZDE3DLcs -b2eQu+iN5rmNfvg6DdaP/+2cvkoMvKL5dF+YRk5KNLn2vHi3Fti6uIpWAfgiICHr -dadCFX5qVlnadZP9Av35lM4VaDz+5eOFvjl1G+7+yEyaoi/m6gjrgrOI4Mqc1zcu -DhMOi9NqX4P9LSI1seXUf0feKA5wB+ei7MgqSSpooJc2PEnFyRg= - - - - - - - - - - urn:mace:shibboleth:1.0:nameIdentifier - urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - - - diff --git a/shibauth/shibboleth-conf/idp-metadata_samltest.xml b/shibauth/shibboleth-conf/idp-metadata_samltest.xml deleted file mode 100755 index 6a91356a..00000000 --- a/shibauth/shibboleth-conf/idp-metadata_samltest.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - samltest.id - - SAMLtest IdP - A free and basic IdP for testing SAML deployments - https://samltest.id/saml/logo.png - - - - - - - -MIIDETCCAfmgAwIBAgIUZRpDhkNKl5eWtJqk0Bu1BgTTargwDQYJKoZIhvcNAQEL -BQAwFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwHhcNMTgwODI0MjExNDEwWhcNMzgw -ODI0MjExNDEwWjAWMRQwEgYDVQQDDAtzYW1sdGVzdC5pZDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAJrh9/PcDsiv3UeL8Iv9rf4WfLPxuOm9W6aCntEA -8l6c1LQ1Zyrz+Xa/40ZgP29ENf3oKKbPCzDcc6zooHMji2fBmgXp6Li3fQUzu7yd -+nIC2teejijVtrNLjn1WUTwmqjLtuzrKC/ePoZyIRjpoUxyEMJopAd4dJmAcCq/K -k2eYX9GYRlqvIjLFoGNgy2R4dWwAKwljyh6pdnPUgyO/WjRDrqUBRFrLQJorR2kD -c4seZUbmpZZfp4MjmWMDgyGM1ZnR0XvNLtYeWAyt0KkSvFoOMjZUeVK/4xR74F8e -8ToPqLmZEg9ZUx+4z2KjVK00LpdRkH9Uxhh03RQ0FabHW6UCAwEAAaNXMFUwHQYD -VR0OBBYEFJDbe6uSmYQScxpVJhmt7PsCG4IeMDQGA1UdEQQtMCuCC3NhbWx0ZXN0 -LmlkhhxodHRwczovL3NhbWx0ZXN0LmlkL3NhbWwvaWRwMA0GCSqGSIb3DQEBCwUA -A4IBAQBNcF3zkw/g51q26uxgyuy4gQwnSr01Mhvix3Dj/Gak4tc4XwvxUdLQq+jC -cxr2Pie96klWhY/v/JiHDU2FJo9/VWxmc/YOk83whvNd7mWaNMUsX3xGv6AlZtCO -L3JhCpHjiN+kBcMgS5jrtGgV1Lz3/1zpGxykdvS0B4sPnFOcaCwHe2B9SOCWbDAN -JXpTjz1DmJO4ImyWPJpN1xsYKtm67Pefxmn0ax0uE2uuzq25h0xbTkqIQgJzyoE/ -DPkBFK1vDkMfAW11dQ0BXatEnW7Gtkc0lh2/PIbHWj4AzxYMyBf5Gy6HSVOftwjC -voQR2qr2xJBixsg+MIORKtmKHLfU - - - - - - - - -MIIDEjCCAfqgAwIBAgIVAMECQ1tjghafm5OxWDh9hwZfxthWMA0GCSqGSIb3DQEB -CwUAMBYxFDASBgNVBAMMC3NhbWx0ZXN0LmlkMB4XDTE4MDgyNDIxMTQwOVoXDTM4 -MDgyNDIxMTQwOVowFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQC0Z4QX1NFKs71ufbQwoQoW7qkNAJRIANGA4iM0 -ThYghul3pC+FwrGv37aTxWXfA1UG9njKbbDreiDAZKngCgyjxj0uJ4lArgkr4AOE -jj5zXA81uGHARfUBctvQcsZpBIxDOvUUImAl+3NqLgMGF2fktxMG7kX3GEVNc1kl -bN3dfYsaw5dUrw25DheL9np7G/+28GwHPvLb4aptOiONbCaVvh9UMHEA9F7c0zfF -/cL5fOpdVa54wTI0u12CsFKt78h6lEGG5jUs/qX9clZncJM7EFkN3imPPy+0HC8n -spXiH/MZW8o2cqWRkrw3MzBZW3Ojk5nQj40V6NUbjb7kfejzAgMBAAGjVzBVMB0G -A1UdDgQWBBQT6Y9J3Tw/hOGc8PNV7JEE4k2ZNTA0BgNVHREELTArggtzYW1sdGVz -dC5pZIYcaHR0cHM6Ly9zYW1sdGVzdC5pZC9zYW1sL2lkcDANBgkqhkiG9w0BAQsF -AAOCAQEASk3guKfTkVhEaIVvxEPNR2w3vWt3fwmwJCccW98XXLWgNbu3YaMb2RSn -7Th4p3h+mfyk2don6au7Uyzc1Jd39RNv80TG5iQoxfCgphy1FYmmdaSfO8wvDtHT -TNiLArAxOYtzfYbzb5QrNNH/gQEN8RJaEf/g/1GTw9x/103dSMK0RXtl+fRs2nbl -D1JJKSQ3AdhxK/weP3aUPtLxVVJ9wMOQOfcy02l+hHMb6uAjsPOpOVKqi3M8XmcU -ZOpx4swtgGdeoSpeRyrtMvRwdcciNBp9UZome44qZAYH1iqrpmmjsfI9pJItsgWu -3kXPjhSfj1AJGR1l9JGvJrHki1iHTA== - - - - - - - - -MIIDEjCCAfqgAwIBAgIVAPVbodo8Su7/BaHXUHykx0Pi5CFaMA0GCSqGSIb3DQEB -CwUAMBYxFDASBgNVBAMMC3NhbWx0ZXN0LmlkMB4XDTE4MDgyNDIxMTQwOVoXDTM4 -MDgyNDIxMTQwOVowFjEUMBIGA1UEAwwLc2FtbHRlc3QuaWQwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCQb+1a7uDdTTBBFfwOUun3IQ9nEuKM98SmJDWa -MwM877elswKUTIBVh5gB2RIXAPZt7J/KGqypmgw9UNXFnoslpeZbA9fcAqqu28Z4 -sSb2YSajV1ZgEYPUKvXwQEmLWN6aDhkn8HnEZNrmeXihTFdyr7wjsLj0JpQ+VUlc -4/J+hNuU7rGYZ1rKY8AA34qDVd4DiJ+DXW2PESfOu8lJSOteEaNtbmnvH8KlwkDs -1NvPTsI0W/m4SK0UdXo6LLaV8saIpJfnkVC/FwpBolBrRC/Em64UlBsRZm2T89ca -uzDee2yPUvbBd5kLErw+sC7i4xXa2rGmsQLYcBPhsRwnmBmlAgMBAAGjVzBVMB0G -A1UdDgQWBBRZ3exEu6rCwRe5C7f5QrPcAKRPUjA0BgNVHREELTArggtzYW1sdGVz -dC5pZIYcaHR0cHM6Ly9zYW1sdGVzdC5pZC9zYW1sL2lkcDANBgkqhkiG9w0BAQsF -AAOCAQEABZDFRNtcbvIRmblnZItoWCFhVUlq81ceSQddLYs8DqK340//hWNAbYdj -WcP85HhIZnrw6NGCO4bUipxZXhiqTA/A9d1BUll0vYB8qckYDEdPDduYCOYemKkD -dmnHMQWs9Y6zWiYuNKEJ9mf3+1N8knN/PK0TYVjVjXAf2CnOETDbLtlj6Nqb8La3 -sQkYmU+aUdopbjd5JFFwbZRaj6KiHXHtnIRgu8sUXNPrgipUgZUOVhP0C0N5OfE4 -JW8ZBrKgQC/6vJ2rSa9TlzI6JAa5Ww7gMXMP9M+cJUNQklcq+SBnTK8G+uBHgPKR -zBDsMIEzRtQZm4GIoHJae4zmnCekkQ== - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shibauth/shibboleth-conf/sp-metadata.xml b/shibauth/shibboleth-conf/sp-metadata.xml deleted file mode 100644 index 28a4e91f..00000000 --- a/shibauth/shibboleth-conf/sp-metadata.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - https://emg.pdas.prism.eox.at - https://https://emg.pdas.prism.eox.at/shibboleth - - CN=https://emg.pdas.prism.eox.at - MIIEUDCCArigAwIBAgIJAJtainQ0t+tRMA0GCSqGSIb3DQEBCwUAMCgxJjAkBgNV -BAMTHWh0dHBzOi8vZW1nLnBkYXMucHJpc20uZW94LmF0MB4XDTIwMTAxNDExMjcy -MFoXDTMwMTAxMjExMjcyMFowKDEmMCQGA1UEAxMdaHR0cHM6Ly9lbWcucGRhcy5w -cmlzbS5lb3guYXQwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDKkqzn -QsDnXSa+BHA10ZVkvw/PBfJVsby1C+zazCo32GpIHv5P+RFZj3FoC+N+gYatqijZ -57flt93krtqO/l/RrEosxwpWCXc54qXcFrPrlfXFr51dOW/BH6z1wpW9z67Pkr2M -v8Jqgs0t/k8BFlZ2jmiAZGrG+G+DrCefiy9JuKwBSiVh7Tg5P31fZv0qliNKwo5k -EbkeUuVrAvuNFV9NPdl35aevYZ0Mxy5N+/AbaaZScfmRnlTsRdHXL/k5anIceqk3 -k+qA1cHEXXqD7WtfQN4GQh9Oxqng//PBcH/9oe2h5axrkcw8YCC22YXp/OST4isk -lL1noCuRYPluvVDFqrh6z9S94QFuO3PdUckl7S7Gsty6X0MSYPYpBFZgivalIena -2vLC3sn5AGLrm3xmp4Io/iD0UtpnHHypCRghr8GE/yiZKPtq8bEk5d/NWMRgT5Ef -t77vZByeDxgN0Pl5gf8WtN0yKSPauxS3llNy9UFfoQP9OGV3FjzOo3DGuTUCAwEA -AaN9MHswWgYDVR0RBFMwUYIdaHR0cHM6Ly9lbWcucGRhcy5wcmlzbS5lb3guYXSG -MGh0dHBzOi8vaHR0cHM6Ly9lbWcucGRhcy5wcmlzbS5lb3guYXQvc2hpYmJvbGV0 -aDAdBgNVHQ4EFgQUzMF2sJVjzVscd6vLPMLWx2gD4uEwDQYJKoZIhvcNAQELBQAD -ggGBAIFFdjkcQyTWx30mwuJON4Bfi0IjBXyQ7YnbvB36sk9ohaPBz4uU1wKl5In+ -c/usuBgHS9JsBm2JIwnLKko6dS8h79pMnY8rDZxBxAPHkTUwTvzMraWHNXhblO9U -Oqp2NJqy4hyV1OzDWM5yYHiTSZIOewDS8inUvoDwUSYgQr9fSKljUmeI0In9f6wf -vvHA4hQQHVGYMNPO+rvpw8XeWZ8e+HdSxSM1RcL1m29s42HdycXTsmh4ghex4u16 -XvHNMGojW6ih0Oja69PKCraaLTUHPRjxwqx1ipaNbK/1pT7DPnLXHNGIOFW2JE9e -XIi3xy/d+C2Z/Ejwt4Xd+FVA9mhhbLkss7YI+SMJi73e31//sBiKOXBT1yBv8l0n -xTJsPmg2dbWQvNuJ89UIH8yPffcxdbT0xohgOiek+hBxZj0UU1ZSV5q2/X9aPKGZ -PMQ/PFgQJvdjegNZPupgBspcNlvYsdtln9vvyXWoNsNioSa6Uvntb8KEHnnh035S -VorGcA== - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- GitLab From 8f43fcc5ece65b104e86d6ba823749d12ddb25e0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 28 Oct 2020 17:43:38 +0100 Subject: [PATCH 47/64] minor updates --- config/shibboleth/attribute-map.xml | 2 +- config/shibboleth/dem_pass-ac.xml | 2 +- config/shibboleth/emg_pass-ac.xml | 2 +- config/shibboleth/shib-apache.conf | 2 -- config/shibboleth/vhr18_pass-ac.xml | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/config/shibboleth/attribute-map.xml b/config/shibboleth/attribute-map.xml index d20c5140..ddc1eeef 100755 --- a/config/shibboleth/attribute-map.xml +++ b/config/shibboleth/attribute-map.xml @@ -1,4 +1,4 @@ - + diff --git a/config/shibboleth/dem_pass-ac.xml b/config/shibboleth/dem_pass-ac.xml index 13465660..a93f5255 100644 --- a/config/shibboleth/dem_pass-ac.xml +++ b/config/shibboleth/dem_pass-ac.xml @@ -1,9 +1,9 @@ + .+ Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth - .+ \ No newline at end of file diff --git a/config/shibboleth/emg_pass-ac.xml b/config/shibboleth/emg_pass-ac.xml index 13465660..a93f5255 100644 --- a/config/shibboleth/emg_pass-ac.xml +++ b/config/shibboleth/emg_pass-ac.xml @@ -1,9 +1,9 @@ + .+ Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth - .+ \ No newline at end of file diff --git a/config/shibboleth/shib-apache.conf b/config/shibboleth/shib-apache.conf index 91216960..88f0a4ed 100755 --- a/config/shibboleth/shib-apache.conf +++ b/config/shibboleth/shib-apache.conf @@ -22,8 +22,6 @@ DocumentRoot "/var/www/html" AuthType shibboleth ShibRequestSetting requireSession 1 Require shib-plugin /etc/shibboleth/pass-ac.xml - RequestHeader set Referer "%{X-Forwarded-Uri}e" - Header set Referer "%{X-Forwarded-Uri}e" \ No newline at end of file diff --git a/config/shibboleth/vhr18_pass-ac.xml b/config/shibboleth/vhr18_pass-ac.xml index 13465660..a93f5255 100644 --- a/config/shibboleth/vhr18_pass-ac.xml +++ b/config/shibboleth/vhr18_pass-ac.xml @@ -1,9 +1,9 @@ + .+ Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth - .+ \ No newline at end of file -- GitLab From eaa3c2ccc1c2d9f1ff6a4edcd6859383534e85c1 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Thu, 29 Oct 2020 09:35:03 +0100 Subject: [PATCH 48/64] update AC for other collections now set on download+view, as separation is not easy now --- config/shibboleth/dem_pass-ac.xml | 2 +- config/shibboleth/vhr18_pass-ac.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/shibboleth/dem_pass-ac.xml b/config/shibboleth/dem_pass-ac.xml index a93f5255..08e4b9ba 100644 --- a/config/shibboleth/dem_pass-ac.xml +++ b/config/shibboleth/dem_pass-ac.xml @@ -3,7 +3,7 @@ type="edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"> .+ - Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space TP_Data_Providers Data_Access_Services Ops_Space_Inf_Services \ No newline at end of file diff --git a/config/shibboleth/vhr18_pass-ac.xml b/config/shibboleth/vhr18_pass-ac.xml index a93f5255..43130937 100644 --- a/config/shibboleth/vhr18_pass-ac.xml +++ b/config/shibboleth/vhr18_pass-ac.xml @@ -3,7 +3,7 @@ type="edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"> .+ - Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth Int_Org_NGO \ No newline at end of file -- GitLab From e3f032b5f457f5711d0117d280d270ee905aec5f Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 3 Nov 2020 17:38:01 +0100 Subject: [PATCH 49/64] create separate shib rules for cache, add shibAuthCache to client --- config/shibboleth/dem_pass-ac-cache.xml | 9 +++++++++ config/shibboleth/dem_pass-ac.xml | 2 +- config/shibboleth/emg_pass-ac-cache.xml | 9 +++++++++ config/shibboleth/emg_pass-ac.xml | 2 +- config/shibboleth/shib-apache.conf | 16 +++++++++++++++- config/shibboleth/vhr18_pass-ac-cache.xml | 9 +++++++++ config/shibboleth/vhr18_pass-ac.xml | 2 +- docker-compose.dem.ops.yml | 8 ++++++-- docker-compose.emg.ops.yml | 8 ++++++-- docker-compose.vhr18.ops.yml | 8 ++++++-- traefik-dynamic.yml | 4 ++++ 11 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 config/shibboleth/dem_pass-ac-cache.xml create mode 100644 config/shibboleth/emg_pass-ac-cache.xml create mode 100644 config/shibboleth/vhr18_pass-ac-cache.xml diff --git a/config/shibboleth/dem_pass-ac-cache.xml b/config/shibboleth/dem_pass-ac-cache.xml new file mode 100644 index 00000000..29cc048b --- /dev/null +++ b/config/shibboleth/dem_pass-ac-cache.xml @@ -0,0 +1,9 @@ + + + .+ + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space TP_Data_Providers Data_Access_Services Ops_Space_Inf_Services Public_Auth Int_Org_NGO + + + diff --git a/config/shibboleth/dem_pass-ac.xml b/config/shibboleth/dem_pass-ac.xml index 08e4b9ba..ef16ad42 100644 --- a/config/shibboleth/dem_pass-ac.xml +++ b/config/shibboleth/dem_pass-ac.xml @@ -6,4 +6,4 @@ type="edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"> Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space TP_Data_Providers Data_Access_Services Ops_Space_Inf_Services - \ No newline at end of file + diff --git a/config/shibboleth/emg_pass-ac-cache.xml b/config/shibboleth/emg_pass-ac-cache.xml new file mode 100644 index 00000000..91372acf --- /dev/null +++ b/config/shibboleth/emg_pass-ac-cache.xml @@ -0,0 +1,9 @@ + + + .+ + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth + + + diff --git a/config/shibboleth/emg_pass-ac.xml b/config/shibboleth/emg_pass-ac.xml index a93f5255..91372acf 100644 --- a/config/shibboleth/emg_pass-ac.xml +++ b/config/shibboleth/emg_pass-ac.xml @@ -6,4 +6,4 @@ type="edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"> Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth - \ No newline at end of file + diff --git a/config/shibboleth/shib-apache.conf b/config/shibboleth/shib-apache.conf index 88f0a4ed..8e5d486b 100755 --- a/config/shibboleth/shib-apache.conf +++ b/config/shibboleth/shib-apache.conf @@ -24,4 +24,18 @@ DocumentRoot "/var/www/html" Require shib-plugin /etc/shibboleth/pass-ac.xml - \ No newline at end of file + + + Require valid-user + AuthType Basic + AuthBasicProvider file + AuthName "/secure" + AuthUserFile /run/secrets/BASIC_AUTH_USERS_AUTH + + + AuthType shibboleth + ShibRequestSetting requireSession 1 + Require shib-plugin /etc/shibboleth/pass-ac-cache.xml + + + diff --git a/config/shibboleth/vhr18_pass-ac-cache.xml b/config/shibboleth/vhr18_pass-ac-cache.xml new file mode 100644 index 00000000..6a152812 --- /dev/null +++ b/config/shibboleth/vhr18_pass-ac-cache.xml @@ -0,0 +1,9 @@ + + + .+ + + Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth Int_Org_NGO Public + + + diff --git a/config/shibboleth/vhr18_pass-ac.xml b/config/shibboleth/vhr18_pass-ac.xml index 43130937..2a0fb352 100644 --- a/config/shibboleth/vhr18_pass-ac.xml +++ b/config/shibboleth/vhr18_pass-ac.xml @@ -6,4 +6,4 @@ type="edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl"> Copernicus_Services Union_Inst Union_Research_Projects_space Union_Research_Projects_non-space Public_Auth Int_Org_NGO - \ No newline at end of file + diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 1459c1f1..285d973c 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -14,7 +14,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=shibAuth@file,compress@file,cors@file" + - "traefik.http.routers.dem-renderer.middlewares=shibAuthCache@file,compress@file,cors@file" - "traefik.http.routers.dem-renderer.tls=true" - "traefik.http.routers.dem-renderer.tls.certresolver=default" - "traefik.http.routers.dem-renderer.entrypoints=https" @@ -167,8 +167,10 @@ services: networks: - dem-extnet configs: - - source: access-control-conf + - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-access-control-conf-cache + target: /etc/shibboleth/pass-ac-cache.xml - source: shib-shibboleth2 target: /etc/shibboleth/shibboleth2.xml - source: shib-apache @@ -190,6 +192,8 @@ networks: configs: shib-access-control-conf: file: ./config/shibboleth/dem_pass-ac.xml + shib-access-control-conf-cache: + file: ./config/shibboleth/dem_pass-ac-cache.xml shib-shibboleth2: # this will vary for collections file: ./config/shibboleth/shibboleth2.xml shib-apache: diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 0c4f9978..04c8beda 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -56,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.emg-cache.tls=true" - "traefik.http.routers.emg-cache.tls.certresolver=default" - "traefik.http.routers.emg-cache.entrypoints=https" @@ -167,8 +167,10 @@ services: networks: - emg-extnet configs: - - source: access-control-conf + - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-access-control-conf-cache + target: /etc/shibboleth/pass-ac-cache.xml - source: shib-shibboleth2 target: /etc/shibboleth/shibboleth2.xml - source: shib-apache @@ -190,6 +192,8 @@ networks: configs: shib-access-control-conf: file: ./config/shibboleth/emg_pass-ac.xml + shib-access-control-conf-cache: + file: ./config/shibboleth/emg_pass-ac-cache.xml shib-shibboleth2: # this will vary for collections file: ./config/shibboleth/shibboleth2.xml shib-apache: diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index f82fd145..6d517bc9 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -56,7 +56,7 @@ services: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" # router for basic auth based access (https) - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.vhr18-cache.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" - "traefik.http.routers.vhr18-cache.tls=true" - "traefik.http.routers.vhr18-cache.tls.certresolver=default" - "traefik.http.routers.vhr18-cache.entrypoints=https" @@ -167,8 +167,10 @@ services: networks: - vhr18-extnet configs: - - source: access-control-conf + - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml + - source: shib-access-control-conf-cache + target: /etc/shibboleth/pass-ac-cache.xml - source: shib-shibboleth2 target: /etc/shibboleth/shibboleth2.xml - source: shib-apache @@ -190,6 +192,8 @@ networks: configs: shib-access-control-conf: file: ./config/shibboleth/vhr18_pass-ac.xml + shib-access-control-conf-cache: + file: ./config/shibboleth/vhr18_pass-ac-cache.xml shib-shibboleth2: # this will vary for collections file: ./config/shibboleth/shibboleth2.xml shib-apache: diff --git a/traefik-dynamic.yml b/traefik-dynamic.yml index a04d0958..932dc5fc 100644 --- a/traefik-dynamic.yml +++ b/traefik-dynamic.yml @@ -22,6 +22,10 @@ http: forwardAuth: address: http://shibauth/secure trustForwardHeader: true + shibAuthCache: + forwardAuth: + address: http://shibauth/secure-cache + trustForwardHeader: true compress: compress: {} redirect: -- GitLab From cd3b7f8a6ad51804d8e432de0bc89717c8eea7de Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 4 Nov 2020 13:06:28 +0100 Subject: [PATCH 50/64] open /secure-cache endpoints, add index.html there too --- docker-compose.dem.ops.yml | 8 +++++--- docker-compose.emg.ops.yml | 8 +++++--- docker-compose.vhr18.ops.yml | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 285d973c..e891f57f 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -106,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.dem-client.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.dem-client.middlewares=shibAuthCache@file,compress@file" - "traefik.http.routers.dem-client.tls=true" - "traefik.http.routers.dem-client.tls.certresolver=default" - "traefik.http.routers.dem-client.entrypoints=https" @@ -149,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general @@ -181,6 +181,8 @@ services: target: /etc/shibboleth/idp-metadata.xml - source: shib-index target: /var/www/html/secure/index.html + - source: shib-index + target: /var/www/html/secure-cache/index.html - source: shibd-logger target: /etc/shibboleth/shibd.logger - source: native-logger diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 04c8beda..941b1f09 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -106,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" + - "traefik.http.routers.emg-client.middlewares=shibAuthCache@file,compress@file" - "traefik.http.routers.emg-client.tls=true" - "traefik.http.routers.emg-client.tls.certresolver=default" - "traefik.http.routers.emg-client.entrypoints=https" @@ -149,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general @@ -181,6 +181,8 @@ services: target: /etc/shibboleth/idp-metadata.xml - source: shib-index target: /var/www/html/secure/index.html + - source: shib-index + target: /var/www/html/secure-cache/index.html - source: shibd-logger target: /etc/shibboleth/shibd.logger - source: native-logger diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 6d517bc9..c17b88c9 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -106,7 +106,7 @@ services: labels: # router for basic auth based access (https) - "traefik.http.routers.vhr18-client.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" - - "traefik.http.routers.vhr18-client.middlewares=auth@file,compress@file" + - "traefik.http.routers.vhr18-client.middlewares=shibAuthCache@file,compress@file" - "traefik.http.routers.vhr18-client.tls=true" - "traefik.http.routers.vhr18-client.tls.certresolver=default" - "traefik.http.routers.vhr18-client.entrypoints=https" @@ -149,13 +149,13 @@ services: constraints: [node.role == manager] labels: # router for basic auth based access (https) - - "traefik.http.routers.shibauth.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth.middlewares=compress@file,cors@file" - "traefik.http.routers.shibauth.tls=true" - "traefik.http.routers.shibauth.tls.certresolver=default" - "traefik.http.routers.shibauth.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.shibauth-redirect.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + - "traefik.http.routers.shibauth-redirect.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/secure`, `/secure-cache`, `/Shibboleth.sso`)" - "traefik.http.routers.shibauth-redirect.middlewares=redirect@file" - "traefik.http.routers.shibauth-redirect.entrypoints=http" # general @@ -181,6 +181,8 @@ services: target: /etc/shibboleth/idp-metadata.xml - source: shib-index target: /var/www/html/secure/index.html + - source: shib-index + target: /var/www/html/secure-cache/index.html - source: shibd-logger target: /etc/shibboleth/shibd.logger - source: native-logger -- GitLab From b729deeb9057777c1680db2ce0afab3baf6bf5f5 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 4 Nov 2020 16:14:12 +0100 Subject: [PATCH 51/64] separate shib/basicauth traffic between pdas and pass --- docker-compose.dem.ops.yml | 76 ++++++++++++----- docker-compose.emg.ops.yml | 76 ++++++++++++----- docker-compose.emg.ops_test.yml | 147 -------------------------------- docker-compose.vhr18.ops.yml | 74 +++++++++++----- 4 files changed, 158 insertions(+), 215 deletions(-) delete mode 100644 docker-compose.emg.ops_test.yml diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index e891f57f..d6023b09 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -12,16 +12,16 @@ services: INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" deploy: labels: - # router for basic auth based access (https) - - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer.middlewares=shibAuthCache@file,compress@file,cors@file" - - "traefik.http.routers.dem-renderer.tls=true" - - "traefik.http.routers.dem-renderer.tls.certresolver=default" - - "traefik.http.routers.dem-renderer.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.dem-renderer-shib.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-shib.middlewares=shibAuth@file,compress@file,cors@file" + - "traefik.http.routers.dem-renderer-shib.tls=true" + - "traefik.http.routers.dem-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.dem-renderer-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.dem-renderer-redirect-shib.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.dem-renderer_referer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer.middlewares=compress@file,cors@file" @@ -32,6 +32,16 @@ services: - "traefik.http.routers.dem-renderer_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-renderer_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.dem-renderer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.dem-renderer.tls=true" + - "traefik.http.routers.dem-renderer.tls.certresolver=default" + - "traefik.http.routers.dem-renderer.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.dem-renderer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.dem-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-renderer-redirect.entrypoints=http" # general - "traefik.http.services.dem-renderer.loadbalancer.sticky=false" - "traefik.http.services.dem-renderer.loadbalancer.server.port=80" @@ -54,16 +64,16 @@ services: deploy: labels: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" - # router for basic auth based access (https) - - "traefik.http.routers.dem-cache.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.dem-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" - - "traefik.http.routers.dem-cache.tls=true" - - "traefik.http.routers.dem-cache.tls.certresolver=default" - - "traefik.http.routers.dem-cache.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.dem-cache-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.dem-cache-redirect.middlewares=redirect@file" - - "traefik.http.routers.dem-cache-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.dem-cache-shib.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.dem-cache-shib.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.dem-cache-shib.tls=true" + - "traefik.http.routers.dem-cache-shib.tls.certresolver=default" + - "traefik.http.routers.dem-cache-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.dem-cache-redirect-shib.rule=Host(`dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.dem-cache-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.dem-cache-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.dem-cache_referer.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer.middlewares=cache-stripprefix,compress@file,cors@file" @@ -74,6 +84,16 @@ services: - "traefik.http.routers.dem-cache_referer-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`, `a.dem.pass.copernicus.eu`, `b.dem.pass.copernicus.eu`, `c.dem.pass.copernicus.eu`, `d.dem.pass.copernicus.eu`, `e.dem.pass.copernicus.eu`, `f.dem.pass.copernicus.eu`, `g.dem.pass.copernicus.eu`, `h.dem.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|dem.pdas.prism.eox.at|dem.pass.copernicus.eu)/?`)" - "traefik.http.routers.dem-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-cache_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.dem-cache.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.dem-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.dem-cache.tls=true" + - "traefik.http.routers.dem-cache.tls.certresolver=default" + - "traefik.http.routers.dem-cache.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.dem-cache-redirect.rule=Host(`dem.pdas.prism.eox.at`, `a.dem.pdas.prism.eox.at`, `b.dem.pdas.prism.eox.at`, `c.dem.pdas.prism.eox.at`, `d.dem.pdas.prism.eox.at`, `e.dem.pdas.prism.eox.at`, `f.dem.pdas.prism.eox.at`, `g.dem.pdas.prism.eox.at`, `h.dem.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.dem-cache-redirect.middlewares=redirect@file" + - "traefik.http.routers.dem-cache-redirect.entrypoints=http" # general - "traefik.http.services.dem-cache.loadbalancer.sticky=false" - "traefik.http.services.dem-cache.loadbalancer.server.port=80" @@ -104,14 +124,24 @@ services: target: /usr/share/nginx/html/index.html deploy: labels: + # router for shib auth based access (https) + - "traefik.http.routers.dem-client-shib.rule=Host(`dem.pass.copernicus.eu`)" + - "traefik.http.routers.dem-client-shib.middlewares=shibAuthCache@file,compress@file" + - "traefik.http.routers.dem-client-shib.tls=true" + - "traefik.http.routers.dem-client-shib.tls.certresolver=default" + - "traefik.http.routers.dem-client-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.dem-client-redirect-shib.rule=Host(`dem.pass.copernicus.eu`)" + - "traefik.http.routers.dem-client-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.dem-client-redirect-shib.entrypoints=http" # router for basic auth based access (https) - - "traefik.http.routers.dem-client.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" - - "traefik.http.routers.dem-client.middlewares=shibAuthCache@file,compress@file" + - "traefik.http.routers.dem-client.rule=Host(`dem.pdas.prism.eox.at`)" + - "traefik.http.routers.dem-client.middlewares=auth@file,compress@file" - "traefik.http.routers.dem-client.tls=true" - "traefik.http.routers.dem-client.tls.certresolver=default" - "traefik.http.routers.dem-client.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`, `dem.pass.copernicus.eu`)" + - "traefik.http.routers.dem-client-redirect.rule=Host(`dem.pdas.prism.eox.at`)" - "traefik.http.routers.dem-client-redirect.middlewares=redirect@file" - "traefik.http.routers.dem-client-redirect.entrypoints=http" # general diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 941b1f09..86bea982 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -12,16 +12,16 @@ services: INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" deploy: labels: - # router for basic auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=shibAuth@file,compress@file,cors@file" - - "traefik.http.routers.emg-renderer.tls=true" - - "traefik.http.routers.emg-renderer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.emg-renderer-shib.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-shib.middlewares=shibAuth@file,compress@file,cors@file" + - "traefik.http.routers.emg-renderer-shib.tls=true" + - "traefik.http.routers.emg-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.emg-renderer-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.emg-renderer-redirect-shib.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" @@ -32,6 +32,16 @@ services: - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.emg-renderer.tls=true" + - "traefik.http.routers.emg-renderer.tls.certresolver=default" + - "traefik.http.routers.emg-renderer.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" # general - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" @@ -54,16 +64,16 @@ services: deploy: labels: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" - # router for basic auth based access (https) - - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" - - "traefik.http.routers.emg-cache.tls=true" - - "traefik.http.routers.emg-cache.tls.certresolver=default" - - "traefik.http.routers.emg-cache.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-cache-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-cache-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.emg-cache-shib.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache-shib.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache-shib.tls=true" + - "traefik.http.routers.emg-cache-shib.tls.certresolver=default" + - "traefik.http.routers.emg-cache-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.emg-cache-redirect-shib.rule=Host(`emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.emg-cache-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.emg-cache_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer.middlewares=cache-stripprefix,compress@file,cors@file" @@ -74,6 +84,16 @@ services: - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.emg-cache.tls=true" + - "traefik.http.routers.emg-cache.tls.certresolver=default" + - "traefik.http.routers.emg-cache.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.emg-cache-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.emg-cache-redirect.middlewares=redirect@file" + - "traefik.http.routers.emg-cache-redirect.entrypoints=http" # general - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - "traefik.http.services.emg-cache.loadbalancer.server.port=80" @@ -104,14 +124,24 @@ services: target: /usr/share/nginx/html/index.html deploy: labels: + # router for shib auth based access (https) + - "traefik.http.routers.emg-client-shib.rule=Host(`emg.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-shib.middlewares=shibAuthCache@file,compress@file" + - "traefik.http.routers.emg-client-shib.tls=true" + - "traefik.http.routers.emg-client-shib.tls.certresolver=default" + - "traefik.http.routers.emg-client-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.emg-client-redirect-shib.rule=Host(`emg.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.emg-client-redirect-shib.entrypoints=http" # router for basic auth based access (https) - - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=shibAuthCache@file,compress@file" + - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`)" + - "traefik.http.routers.emg-client.middlewares=auth@file,compress@file" - "traefik.http.routers.emg-client.tls=true" - "traefik.http.routers.emg-client.tls.certresolver=default" - "traefik.http.routers.emg-client.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" + - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`)" - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - "traefik.http.routers.emg-client-redirect.entrypoints=http" # general diff --git a/docker-compose.emg.ops_test.yml b/docker-compose.emg.ops_test.yml deleted file mode 100644 index 7b66a1ea..00000000 --- a/docker-compose.emg.ops_test.yml +++ /dev/null @@ -1,147 +0,0 @@ -version: "3.6" -services: - database: - volumes: - - type: tmpfs - target: /dev/shm - tmpfs: - size: 536870912 - renderer: - environment: - INSTALL_DIR: "/var/www/pvs/ops/" - INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" - deploy: - labels: - # router for basic auth based access (https) - - "traefik.http.routers.emg-renderer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer.middlewares=auth@file,compress@file,cors@file" - - "traefik.http.routers.emg-renderer.tls=true" - - "traefik.http.routers.emg-renderer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-renderer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.emg-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer-redirect.entrypoints=http" - # router for referrer based access (https) - - "traefik.http.routers.emg-renderer_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer.middlewares=compress@file,cors@file" - - "traefik.http.routers.emg-renderer_referer.tls=true" - - "traefik.http.routers.emg-renderer_referer.tls.certresolver=default" - - "traefik.http.routers.emg-renderer_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.emg-renderer_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-renderer_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-renderer_referer-redirect.entrypoints=http" - # general - - "traefik.http.services.emg-renderer.loadbalancer.sticky=false" - - "traefik.http.services.emg-renderer.loadbalancer.server.port=80" - - "traefik.docker.network=emg-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" - replicas: 0 - resources: - limits: - memory: 8G - placement: - constraints: - - node.labels.type == external - networks: - - extnet - cache: - configs: - - source: mapcache-ops - target: /mapcache-template.xml - deploy: - labels: - - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" - # router for basic auth based access (https) - - "traefik.http.routers.emg-cache.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache.middlewares=shibAuth@file,cache-stripprefix,compress@file,cors@file" - - "traefik.http.routers.emg-cache.tls=true" - - "traefik.http.routers.emg-cache.tls.certresolver=default" - - "traefik.http.routers.emg-cache.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-cache-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.emg-cache-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-cache-redirect.entrypoints=http" - # router for referrer based access (https) - - "traefik.http.routers.emg-cache_referer.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-cache_referer.middlewares=cache-stripprefix,compress@file,cors@file" - - "traefik.http.routers.emg-cache_referer.tls=true" - - "traefik.http.routers.emg-cache_referer.tls.certresolver=default" - - "traefik.http.routers.emg-cache_referer.entrypoints=https" - # router for referrer based access (http) - - "traefik.http.routers.emg-cache_referer-redirect.rule=Host(`emg.pdas.prism.eox.at`, `a.emg.pdas.prism.eox.at`, `b.emg.pdas.prism.eox.at`, `c.emg.pdas.prism.eox.at`, `d.emg.pdas.prism.eox.at`, `e.emg.pdas.prism.eox.at`, `f.emg.pdas.prism.eox.at`, `g.emg.pdas.prism.eox.at`, `h.emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`, `a.emg.pass.copernicus.eu`, `b.emg.pass.copernicus.eu`, `c.emg.pass.copernicus.eu`, `d.emg.pass.copernicus.eu`, `e.emg.pass.copernicus.eu`, `f.emg.pass.copernicus.eu`, `g.emg.pass.copernicus.eu`, `h.emg.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|emg.pdas.prism.eox.at|emg.pass.copernicus.eu)/?`)" - - "traefik.http.routers.emg-cache_referer-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-cache_referer-redirect.entrypoints=http" - # general - - "traefik.http.services.emg-cache.loadbalancer.sticky=false" - - "traefik.http.services.emg-cache.loadbalancer.server.port=80" - - "traefik.docker.network=emg-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" - replicas: 0 - resources: - limits: - memory: 8G - placement: - constraints: - - node.labels.type == external - networks: - - extnet - registrar: - environment: - INSTALL_DIR: "/var/www/pvs/ops/" - INSTANCE_DIR: "/var/www/pvs/ops/pvs_instance/" - deploy: - replicas: 0 - placement: - constraints: - - node.labels.type == internal - client: - configs: - - source: client-ops - target: /usr/share/nginx/html/index.html - deploy: - labels: - # router for basic auth based access (https) - - "traefik.http.routers.emg-client.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client.middlewares=shibAuth@file,compress@file" - - "traefik.http.routers.emg-client.tls=true" - - "traefik.http.routers.emg-client.tls.certresolver=default" - - "traefik.http.routers.emg-client.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.emg-client-redirect.rule=Host(`emg.pdas.prism.eox.at`, `emg.pass.copernicus.eu`)" - - "traefik.http.routers.emg-client-redirect.middlewares=redirect@file" - - "traefik.http.routers.emg-client-redirect.entrypoints=http" - # general - - "traefik.http.services.emg-client.loadbalancer.sticky=false" - - "traefik.http.services.emg-client.loadbalancer.server.port=80" - - "traefik.docker.network=emg-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" - placement: - constraints: - - node.labels.type == external - networks: - - extnet - preprocessor: - volumes: - - type: bind - source: /var/vhr - target: /tmp - deploy: - replicas: 0 - placement: - constraints: - - node.labels.type == internal - sftp: - deploy: - replicas: 0 - ingestor: - deploy: - replicas: 0 -networks: - extnet: - name: emg-extnet - external: true diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index c17b88c9..12a692eb 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -13,16 +13,16 @@ services: deploy: replicas: 3 labels: - # router for basic auth based access (https) - - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=shibAuth@file,compress@file,cors@file" - - "traefik.http.routers.vhr18-renderer.tls=true" - - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - - "traefik.http.routers.vhr18-renderer.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.vhr18-renderer-shib.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-shib.middlewares=shibAuth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer-shib.tls=true" + - "traefik.http.routers.vhr18-renderer-shib.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.vhr18-renderer-redirect-shib.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.vhr18-renderer-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.vhr18-renderer_referer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer.middlewares=compress@file,cors@file" @@ -33,6 +33,16 @@ services: - "traefik.http.routers.vhr18-renderer_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-renderer_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-renderer_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer.tls=true" + - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.vhr18-renderer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-renderer-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" @@ -54,16 +64,16 @@ services: deploy: labels: - "traefik.http.middlewares.cache-stripprefix.stripprefix.prefixes=/cache" - # router for basic auth based access (https) - - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" - - "traefik.http.routers.vhr18-cache.tls=true" - - "traefik.http.routers.vhr18-cache.tls.certresolver=default" - - "traefik.http.routers.vhr18-cache.entrypoints=https" - # router for basic auth based access (http) - - "traefik.http.routers.vhr18-cache-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" - - "traefik.http.routers.vhr18-cache-redirect.middlewares=redirect@file" - - "traefik.http.routers.vhr18-cache-redirect.entrypoints=http" + # router for shib auth based access (https) + - "traefik.http.routers.vhr18-cache-shib.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.vhr18-cache-shib.middlewares=shibAuthCache@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.vhr18-cache-shib.tls=true" + - "traefik.http.routers.vhr18-cache-shib.tls.certresolver=default" + - "traefik.http.routers.vhr18-cache-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.vhr18-cache-redirect-shib.rule=Host(`vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`)" + - "traefik.http.routers.vhr18-cache-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.vhr18-cache-redirect-shib.entrypoints=http" # router for referrer based access (https) - "traefik.http.routers.vhr18-cache_referer.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer.middlewares=cache-stripprefix,compress@file,cors@file" @@ -74,6 +84,16 @@ services: - "traefik.http.routers.vhr18-cache_referer-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`, `a.vhr18.pass.copernicus.eu`, `b.vhr18.pass.copernicus.eu`, `c.vhr18.pass.copernicus.eu`, `d.vhr18.pass.copernicus.eu`, `e.vhr18.pass.copernicus.eu`, `f.vhr18.pass.copernicus.eu`, `g.vhr18.pass.copernicus.eu`, `h.vhr18.pass.copernicus.eu`) && PathPrefix(`/cache`) && HeadersRegexp(`Referer`, `(https?://)?(panda.copernicus.eu|panda.cdsv3.eu|panda-demo.ondaprism.eu|panda-demo.copernicus.eu|cdsportal-demo.copernicus.eu|ocqc-demo.copernicus.eu|spdm-intservices.cds.esa.int|spdm-intservices-adm.cds.esa.int|vhr18.pdas.prism.eox.at|vhr18.pass.copernicus.eu)/?`)" - "traefik.http.routers.vhr18-cache_referer-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-cache_referer-redirect.entrypoints=http" + # router for basic auth based access (https) + - "traefik.http.routers.vhr18-cache.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.vhr18-cache.middlewares=auth@file,cache-stripprefix,compress@file,cors@file" + - "traefik.http.routers.vhr18-cache.tls=true" + - "traefik.http.routers.vhr18-cache.tls.certresolver=default" + - "traefik.http.routers.vhr18-cache.entrypoints=https" + # router for basic auth based access (http) + - "traefik.http.routers.vhr18-cache-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `a.vhr18.pdas.prism.eox.at`, `b.vhr18.pdas.prism.eox.at`, `c.vhr18.pdas.prism.eox.at`, `d.vhr18.pdas.prism.eox.at`, `e.vhr18.pdas.prism.eox.at`, `f.vhr18.pdas.prism.eox.at`, `g.vhr18.pdas.prism.eox.at`, `h.vhr18.pdas.prism.eox.at`) && PathPrefix(`/cache`)" + - "traefik.http.routers.vhr18-cache-redirect.middlewares=redirect@file" + - "traefik.http.routers.vhr18-cache-redirect.entrypoints=http" # general - "traefik.http.services.vhr18-cache.loadbalancer.sticky=false" - "traefik.http.services.vhr18-cache.loadbalancer.server.port=80" @@ -104,14 +124,24 @@ services: target: /usr/share/nginx/html/index.html deploy: labels: + # router for shib auth based access (https) + - "traefik.http.routers.vhr18-client-shib.rule=Host(`vhr18.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client-shib.middlewares=shibAuthCache@file,compress@file" + - "traefik.http.routers.vhr18-client-shib.tls=true" + - "traefik.http.routers.vhr18-client-shib.tls.certresolver=default" + - "traefik.http.routers.vhr18-client-shib.entrypoints=https" + # router for shib auth based access (http) + - "traefik.http.routers.vhr18-client-redirect-shib.rule=Host(`vhr18.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client-redirect-shib.middlewares=redirect@file" + - "traefik.http.routers.vhr18-client-redirect-shib.entrypoints=http" # router for basic auth based access (https) - - "traefik.http.routers.vhr18-client.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client.rule=Host(`vhr18.pdas.prism.eox.at`)" - "traefik.http.routers.vhr18-client.middlewares=shibAuthCache@file,compress@file" - "traefik.http.routers.vhr18-client.tls=true" - "traefik.http.routers.vhr18-client.tls.certresolver=default" - "traefik.http.routers.vhr18-client.entrypoints=https" # router for basic auth based access (http) - - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`, `vhr18.pass.copernicus.eu`)" + - "traefik.http.routers.vhr18-client-redirect.rule=Host(`vhr18.pdas.prism.eox.at`)" - "traefik.http.routers.vhr18-client-redirect.middlewares=redirect@file" - "traefik.http.routers.vhr18-client-redirect.entrypoints=http" # general -- GitLab From 4743176b273f90ae52235ff6ec89275719afad1d Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Mon, 9 Nov 2020 14:34:37 +0100 Subject: [PATCH 52/64] cleanup, separate shibboleth2.xml for collections --- README.md | 7 +++++ .../{shibboleth2.xml => dem-shibboleth2.xml} | 4 +-- config/shibboleth/emg-shibboleth2.xml | 31 +++++++++++++++++++ config/shibboleth/index.html | 5 +-- config/shibboleth/native.logger | 2 +- config/shibboleth/shibd.logger | 2 +- config/shibboleth/vhr18-shibboleth2.xml | 31 +++++++++++++++++++ docker-compose.dem.ops.yml | 12 +++---- docker-compose.emg.ops.yml | 12 +++---- docker-compose.vhr18.ops.yml | 12 +++---- traefik.yml | 2 +- 11 files changed, 95 insertions(+), 25 deletions(-) rename config/shibboleth/{shibboleth2.xml => dem-shibboleth2.xml} (88%) create mode 100644 config/shibboleth/emg-shibboleth2.xml create mode 100644 config/shibboleth/vhr18-shibboleth2.xml diff --git a/README.md b/README.md index ec20c42b..393f27a0 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,13 @@ The following services are defined via docker compose files. * provides the endpoint for external access * configured via docker labels +### shibauth + +* based on the external unicon/shibboleth-sp:3.0.4 Apache + Shibboleth image +* provides authentication and authorization via SAML2 +* docker configuration files set access control rules +* traefik labels determine which services are protected via Shib + ### database * based on external postgis:10 image diff --git a/config/shibboleth/shibboleth2.xml b/config/shibboleth/dem-shibboleth2.xml similarity index 88% rename from config/shibboleth/shibboleth2.xml rename to config/shibboleth/dem-shibboleth2.xml index 2504a528..2892d9ed 100755 --- a/config/shibboleth/shibboleth2.xml +++ b/config/shibboleth/dem-shibboleth2.xml @@ -4,7 +4,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" clockSkew="180"> - @@ -23,7 +23,7 @@ - + diff --git a/config/shibboleth/emg-shibboleth2.xml b/config/shibboleth/emg-shibboleth2.xml new file mode 100644 index 00000000..1f158494 --- /dev/null +++ b/config/shibboleth/emg-shibboleth2.xml @@ -0,0 +1,31 @@ + + + + + SAML2 + + SAML2 Local + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/shibboleth/index.html b/config/shibboleth/index.html index 7d20ce72..d1b18250 100644 --- a/config/shibboleth/index.html +++ b/config/shibboleth/index.html @@ -2,9 +2,10 @@ - APACHE TEST + Authentication Success -

TESTING APACHE

+

Your login was successful and you were granted access to the service. + Please access the URL, which you originally requested. Proper redirection is not implemented yet.

diff --git a/config/shibboleth/native.logger b/config/shibboleth/native.logger index d360b124..1a854391 100644 --- a/config/shibboleth/native.logger +++ b/config/shibboleth/native.logger @@ -1,5 +1,5 @@ # set overall behavior -log4j.rootCategory=DEBUG, native_log +log4j.rootCategory=INFO, native_log # fairly verbose for DEBUG, so generally leave at WARN/INFO log4j.category.XMLTooling.XMLObject=WARN diff --git a/config/shibboleth/shibd.logger b/config/shibboleth/shibd.logger index c12b4089..909609df 100644 --- a/config/shibboleth/shibd.logger +++ b/config/shibboleth/shibd.logger @@ -1,5 +1,5 @@ # set overall behavior -log4j.rootCategory=DEBUG, shibd_log, warn_log +log4j.rootCategory=INFO, shibd_log, warn_log # fairly verbose for DEBUG, so generally leave at INFO log4j.category.XMLTooling.XMLObject=INFO diff --git a/config/shibboleth/vhr18-shibboleth2.xml b/config/shibboleth/vhr18-shibboleth2.xml new file mode 100644 index 00000000..d18baeff --- /dev/null +++ b/config/shibboleth/vhr18-shibboleth2.xml @@ -0,0 +1,31 @@ + + + + + SAML2 + + SAML2 Local + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index d6023b09..76fd6746 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -170,8 +170,8 @@ services: environment: APACHE_SERVERNAME: "https://dem.pass.copernicus.eu:443" secrets: - - SHIB_CERT - - SHIB_KEY + - DEM_SHIB_CERT + - DEM_SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 @@ -226,8 +226,8 @@ configs: file: ./config/shibboleth/dem_pass-ac.xml shib-access-control-conf-cache: file: ./config/shibboleth/dem_pass-ac-cache.xml - shib-shibboleth2: # this will vary for collections - file: ./config/shibboleth/shibboleth2.xml + shib-shibboleth2: + file: ./config/shibboleth/dem-shibboleth2.xml shib-apache: file: ./config/shibboleth/shib-apache.conf shib-attribute-map: @@ -241,9 +241,9 @@ configs: idp-metadata: external: true secrets: - SHIB_CERT: + DEM_SHIB_CERT: external: true - SHIB_KEY: + DEM_SHIB_KEY: external: true BASIC_AUTH_USERS_AUTH: external: true diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 86bea982..9e9a9c8c 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -170,8 +170,8 @@ services: environment: APACHE_SERVERNAME: "https://emg.pass.copernicus.eu:443" secrets: - - SHIB_CERT - - SHIB_KEY + - EMG_SHIB_CERT + - EMG_SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 @@ -226,8 +226,8 @@ configs: file: ./config/shibboleth/emg_pass-ac.xml shib-access-control-conf-cache: file: ./config/shibboleth/emg_pass-ac-cache.xml - shib-shibboleth2: # this will vary for collections - file: ./config/shibboleth/shibboleth2.xml + shib-shibboleth2: + file: ./config/shibboleth/emg-shibboleth2.xml shib-apache: file: ./config/shibboleth/shib-apache.conf shib-attribute-map: @@ -241,9 +241,9 @@ configs: idp-metadata: external: true secrets: - SHIB_CERT: + EMG_SHIB_CERT: external: true - SHIB_KEY: + EMG_SHIB_KEY: external: true BASIC_AUTH_USERS_AUTH: external: true diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 12a692eb..8c529ad5 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -170,8 +170,8 @@ services: environment: APACHE_SERVERNAME: "https://vhr18.pass.copernicus.eu:443" secrets: - - SHIB_CERT - - SHIB_KEY + - VHR18_SHIB_CERT + - VHR18_SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 @@ -226,8 +226,8 @@ configs: file: ./config/shibboleth/vhr18_pass-ac.xml shib-access-control-conf-cache: file: ./config/shibboleth/vhr18_pass-ac-cache.xml - shib-shibboleth2: # this will vary for collections - file: ./config/shibboleth/shibboleth2.xml + shib-shibboleth2: + file: ./config/shibboleth/vhr18-shibboleth2.xml shib-apache: file: ./config/shibboleth/shib-apache.conf shib-attribute-map: @@ -241,9 +241,9 @@ configs: shib-idp-metadata: external: true secrets: - SHIB_CERT: + VHR18_SHIB_CERT: external: true - SHIB_KEY: + VHR18_SHIB_KEY: external: true BASIC_AUTH_USERS_AUTH: external: true diff --git a/traefik.yml b/traefik.yml index 4a4135d7..39a93c19 100644 --- a/traefik.yml +++ b/traefik.yml @@ -19,7 +19,7 @@ providers: api: dashboard: true log: - level: DEBUG + level: INFO accessLog: {} certificatesResolvers: default: -- GitLab From 40bf5cfa50e362b87780c194d5ec3a49c3cce426 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 12:35:09 +0100 Subject: [PATCH 53/64] operators guide additions --- .../operator-guide/configuration.rst | 2 +- documentation/operator-guide/ingestion.rst | 30 ++++++++++++++--- documentation/operator-guide/management.rst | 32 +++++++++++++++---- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/documentation/operator-guide/configuration.rst b/documentation/operator-guide/configuration.rst index 27b245cd..72de645c 100644 --- a/documentation/operator-guide/configuration.rst +++ b/documentation/operator-guide/configuration.rst @@ -397,7 +397,7 @@ preprocessing force_north_up - TODO + Circumvents the naming of corner names and assumes a north-up orientation of the image. tps diff --git a/documentation/operator-guide/ingestion.rst b/documentation/operator-guide/ingestion.rst index 16be9b8c..8efdac75 100644 --- a/documentation/operator-guide/ingestion.rst +++ b/documentation/operator-guide/ingestion.rst @@ -162,12 +162,23 @@ it is passed as a command line argument, which is then processed normally. .. code-block:: bash - python3 /preprocessor.py \ - --mode standard \ - --replace \ - --tar-object-path /data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar + preprocess \ + --config-file /preprocessor_config.yml \ + --validate \ + --use-dir /tmp \ + data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar -In this mode, the item will not be placed in the resulting set +In order to preprocess a ngEO Ingest Browse Report, an additonal ``--browse-report`` parameter needs to be added: + +.. code-block:: bash + + preprocess \ + --config-file /preprocessor_config.yml \ + --browse-report \ + --use-dir /tmp \ + browse_report_test1.json + +In this "one-off" mode, the item will not be placed in the resulting set (``preprocessing_set``, ``preprocess-success_set``, and ``preprocess-failure_set``). @@ -273,3 +284,12 @@ Deregistration .. code-block:: bash manage.py coverage deregister "${product_id}_coverage" + +Preprocessing vs registration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The preprocessing step aims to ensure that cloud optimized GeoTIFF (COG) files are created in order to significantly speed up the viewing of large amount of data in lower zooms. There are several cases, where such preprocessing is not necessary or wanted. + +- If data are already in COGs and in favorable projection, which will be presented to the user for most of the times, direct registration should be used. This means, paths to individual products will be pushed directly to the register queues. + +- Also for cases, where preprocessing step would take too much time, direct registration allowing access to the metadata and catalog functions, while justifying slower rendering times can be preferred. \ No newline at end of file diff --git a/documentation/operator-guide/management.rst b/documentation/operator-guide/management.rst index d453d28c..9ba0fec6 100644 --- a/documentation/operator-guide/management.rst +++ b/documentation/operator-guide/management.rst @@ -62,9 +62,9 @@ shutting down of the stack and new deployment. Inspecting reports ------------------ -Once registered, a xml report containes wcs and wms getcapabilities of the registered product is generated and can be accessed by connecting to the `SFTP` image +Once registered, a xml report containing wcs and wms getcapabilities of the registered product is generated and can be accessed by connecting to the `SFTP` image via the sftp protocol. -In order to log into the logging folders through port 2222 on the hosting ip (e.g. localhost if you are running the dev stack ) The following command can be used: +In order to log into the logging folders through port 2222 on the hosting ip (e.g. localhost if you are running the dev stack) The following command can be used: .. code-block:: bash @@ -74,8 +74,8 @@ this will direct the user into `/home//data` directory which contains .. Note:: The mounted directory that the user is directed into is *`/home/user`*, where `user` is the username, hence when changing the username in the `.conf` file, the `sftp` mounted volumes path in `docker-compose..yml` must be changed respectively. -Inspecting logs ---------------- +Inspecting logs in development +------------------------------ All service components are running inside docker containers and it is therefore possible to inspect the logs for anomalies via standard docker logs calls redirected for example to less command to allow paging through them. @@ -95,8 +95,24 @@ It is possible to show logs of all containers belonging to a service from a mast docker service logs _ -t 2>&1 | sort -k 1 2>&1 | tail -n 2>&1 | less -The docker service logs is intended as a quick way to view the latest log entries of all tasks of a service, but should not be used as a main way to collect these logs. For that it would be appropriate to use a logging driver, and extract the logs from the nodes to a central log aggregator. -The docker service logs is intended as a quick way to view the latest log entries of all tasks of a service, but should not be used as a main way to collect these logs. For that it would be appropriate to use a logging driver, and extract the logs from the nodes to a central log aggregator. +The docker service logs is intended as a quick way to view the latest log entries of all tasks of a service, but should not be used as a main way to collect these logs. For that, on production setup, an additional EFK (Elasticsearch, Fluentd, Kibana) stack is deployed. + +Inspecting logs in production +----------------------------- + +Fluentd is configured as main logging driver of the Docker daemon on Virtual machine level. Therefore for other services to run, Fluentd service must be running too. To access the logs, interactive and multi-purpose Kibana interface is available and exposed externally by traefik. + +For simple listing of the filtered time-sorted logs as an equivalent to `docker service logs` command, a basic ``Discover`` app can be used. The main panel to interact with the logs is the ``Search`` bar, allowing filtered field-data and free-text searches, modyfing time range etc. The individual log results will then appear in the ``Document table`` panel in the bottom of the page. + +For specific help, please consult `Kibana official documentation `_ + +Kibana discover image here. + +Kibana also allows to aggregate log data based on a search query in two modes of operation: + +- ``Bucketing``, + +- ``Metrics``, keeping track of computed metrics over a set of documents (buckets). Increasing logging level ------------------------ @@ -112,7 +128,9 @@ A restart of respective service for the change to be applied is also necessary. cd ${INSTALL_DIR}/pvs_instance sed -i 's/DEBUG = False/DEBUG = True/g' settings.py -In order to increase logging level of registrar and preprocessor services to `debug`, the respective Python scripts need to be run with an optional parameter **-v 4**. +In order to increase logging level of registrar and preprocessor services to `DEBUG`, the respective Python commands need to be run with an optional parameter **--debug**. + +Ingestor service by default logs its messages in DEBUG mode. The cache services internally uses a Mapcache software, which usually incorporates an Apache 2 HTTP Server. Due to that, logging level is shared throughout the whole service and is based on Apache `.conf` file, which is stored in $APACHE_CONF environment variable. To change the logging level, edit this file, by setting a **LogLevel debug** and then gracefully restart the Apache component (this way, the cache service itself will not restart and renew default configuration). -- GitLab From 65a4330bcb56ae8d650c266007d68606246090c4 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 13:12:17 +0100 Subject: [PATCH 54/64] add some info + images on kibana op guide --- .../operator-guide/images/kibana_1.png | Bin 0 -> 33557 bytes .../operator-guide/images/kibana_2.png | Bin 0 -> 265421 bytes documentation/operator-guide/management.rst | 21 +++++++++++++----- 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 documentation/operator-guide/images/kibana_1.png create mode 100644 documentation/operator-guide/images/kibana_2.png diff --git a/documentation/operator-guide/images/kibana_1.png b/documentation/operator-guide/images/kibana_1.png new file mode 100644 index 0000000000000000000000000000000000000000..40efe5567ff541250adc10f91d1a23a1c96223b0 GIT binary patch literal 33557 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 z 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 literal 0 HcmV?d00001 diff --git a/documentation/operator-guide/images/kibana_2.png b/documentation/operator-guide/images/kibana_2.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc60b5b3958778a3770c201d543dfc152b3cdd6 GIT binary patch literal 265421 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�kxxk62$*pWuJr`tZJCQU;lD$Y<`!`3&1aRnT(3~DY~H{gCvuS zihid;eW4=P^q#&^Wn&M%)Rp#-au9^UTDObsM-k*XT=6E8+j9!~1maD96UAw;-1A2) zQoF;t`|9mPSU!WU1lyZ)@7>Y-fwrhx_{W2)$a1)Tsw2N4MuCkDdhO3oqNI2R}}5u^@9Y%(Vuj|j2zB-VUg8W$B`w! z$w*g#W|DBZhCA>n!sXiM6SPJ*a8EMrSm+g(-0p07PX73t_6>(Z(Bt4rqR7K}MXmQ9 zm=={5h%jDwo@*U*CtkC($~k5`547!C$S#|9rcx<><%vnmf?FrFJ9E zwdG$eRzYriSq~w&l%DJJ;5mBkg~EKK<>xfwMv2=~LWiR?6VTj{Og!3*|Dsv^R{hHXcIaEoMD6K!0#>K(@!#x1mEBZURfV_} zh7OKYvtRB+J_D@YPru3bveITaprozO2tTkB2?F8T{-v*OUNhqxk`e66B41{N)m-a{ zhuczj4!17YZ$5aW2*jUeGZAh3N1*73;>q2_Azy!|c9dBVpB2oMnB;BNy{U2LalnmL za&7OeKpQ(H?ocD=~YvirrM|8_?uQqG$U|ssixO(=2;?mVc{0L~Nkx_r}*^W}8Y@5u8 zB0>p6t4&V>XfI4hi$v5a9twlaSeyB~MXvLVE)YyOm)_{sKUHDlz|Gnd&oZhk20?B* zKyeU{eP+1WYLZOoRvxSwRE2ZIS}7F4d9 zZs_u0p7kgVCZ58|{s=y_%q<@wb$vO_-y2jY3l&w!SW_Jd2cQDRJ2BhQSo?5a-oJu4 z9jPewY24F2#^43`6m0Iybt4Jn^u+S)qo`Nj5_fb{zn6zGp%`Y(zyUh4_gFLKYwgvA zWVIsRrH6Yr@4=@lIbdpJdzo`=J-xjMmhCwT8gMY?IV_@vRZNElh2vT|DhM$Sj$@3o zvIZY$4{%JrsE6!)B`K;i_X{7uG_3H?10%aoUos@;y-y3-J*+hDiJ^W^G&?V2gqrW} zCZ$&-G2~Bjry{z$!@pKb#2mm`Cmxq<7oqKrA?|t&Zyl(fn&Z3!k;1bMnd8~eqj;}3 zHSsWzkn^(A{B@auN=Fr-wT8PwHvnO7b#OihGMy{}^UxMP72({wZ4C0k_{%?9lDUxy zFI3#{g0b8~xQsxd>$g-$iBgSp#X4~hiw>8{W@sNOk3L�E-Ua&hOhatk+xw6}D%= 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%0DUQjppyf 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 literal 0 HcmV?d00001 diff --git a/documentation/operator-guide/management.rst b/documentation/operator-guide/management.rst index 9ba0fec6..565c8a30 100644 --- a/documentation/operator-guide/management.rst +++ b/documentation/operator-guide/management.rst @@ -104,15 +104,26 @@ Fluentd is configured as main logging driver of the Docker daemon on Virtual mac For simple listing of the filtered time-sorted logs as an equivalent to `docker service logs` command, a basic ``Discover`` app can be used. The main panel to interact with the logs is the ``Search`` bar, allowing filtered field-data and free-text searches, modyfing time range etc. The individual log results will then appear in the ``Document table`` panel in the bottom of the page. -For specific help, please consult `Kibana official documentation `_ -Kibana discover image here. +.. _fig_kibana_discover: +.. figure:: images/kibana_2.* + :alt: Kibana discover -Kibana also allows to aggregate log data based on a search query in two modes of operation: + *Kibana discover panel* + +For specific help with ``Discover`` panel, please consult `Kibana official documentation `_ -- ``Bucketing``, +In order to select any other option from the Kibana toolkit, click the horizontal lines selection on the top left and pick a tool. -- ``Metrics``, keeping track of computed metrics over a set of documents (buckets). +.. _fig_kibana_menu: +.. figure:: images/kibana_1.* + :alt: Kibana menu + + *Kibana menu* + +Kibana also allows to aggregate log data based on a search query in two modes of operation: ``Bucketing`` and ``Metrics`` being applied on all buckets. + +These aggregations then are used in ``Visualisations`` with various chart modes like vertical bar chart, horizontal line chart. Using saved searches improves the performance of the charts due to limiting the results list. Increasing logging level ------------------------ -- GitLab From ce68ef55c44c33f2fc96899d78aa06ef23e84a02 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 14:40:05 +0100 Subject: [PATCH 55/64] correct small typos in compose files --- docker-compose.dem.ops.yml | 2 +- docker-compose.emg.ops.yml | 2 +- docker-compose.vhr18.ops.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 1def60fa..ce82c2dc 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -201,7 +201,7 @@ services: - "traefik.docker.lbswarm=true" - "traefik.enable=true" networks: - - dem-extnet + - extnet configs: - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 992ac805..0729c43a 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -201,7 +201,7 @@ services: - "traefik.docker.lbswarm=true" - "traefik.enable=true" networks: - - emg-extnet + - extnet configs: - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index c34e9994..173e27b2 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -201,7 +201,7 @@ services: - "traefik.docker.lbswarm=true" - "traefik.enable=true" networks: - - vhr18-extnet + - extnet configs: - source: shib-access-control-conf target: /etc/shibboleth/pass-ac.xml @@ -213,7 +213,7 @@ services: target: /etc/httpd/conf.d/shib.conf - source: shib-attribute-map target: /etc/shibboleth/attribute-map.xml - - source: shib-idp-metadata + - source: idp-metadata target: /etc/shibboleth/idp-metadata.xml - source: shib-index target: /var/www/html/secure/index.html @@ -246,7 +246,7 @@ configs: file: ./config/shibboleth/shibd.logger shib-index: file: ./config/shibboleth/index.html - shib-idp-metadata: + idp-metadata: external: true secrets: VHR18_SHIB_CERT: -- GitLab From 7568bf8d84523f5cf50384a0828f9bb304797886 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 14:40:58 +0100 Subject: [PATCH 56/64] add shibauth necessary steps in readme, add keygen.sh for pem+cert --- README.md | 12 +++++++ config/keygen.sh | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100755 config/keygen.sh diff --git a/README.md b/README.md index 92a8373e..6747a87d 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,18 @@ docker secret create BASIC_AUTH_USERS_AUTH auth_list.txt docker secret create BASIC_AUTH_USERS_APIAUTH auth_list_api.txt ``` +In case **shibauth** service will be used, for production deployment, two more secrets need to be created for each stack, where **shibauth** is deployed. These ensure that the SP is recognized and its identity confirmed by the IDP. They are configured as **stack-name-capitalized_SHIB_KEY** and **stack-name-capitalized_SHIB_CERT**. In order to create them, use the attached **keygen.sh** command-line tool in */config* folder. +```bash +SPURL="https://emg.pass.copernicus.eu" # service initial access point made accessible by traefik +./config/keygen.sh -h $SPURL -y 20 -e https://$SPURL/shibboleth -n sp-signing -f +docker secret create EMG_SHIB_CERT sp-signing-cert.pem +docker secret create EMG_SHIB_KEY sp-signing-key.pem +``` +Additionally a docker config `idp-metadata` containing the metadata of the used IDP needs to be added: +```bash +docker config create idp_metadata idp-metadata-received.xml +``` + Deploy the stack in dev environment: ``` docker stack deploy -c docker-compose.vhr18.yml -c docker-compose.vhr18.dev.yml -c docker-compose.logging.yml -c docker-compose.logging.dev.yml vhr18-pvs # start VHR_IMAGE_2018 stack in dev mode, for example to use local sources diff --git a/config/keygen.sh b/config/keygen.sh new file mode 100755 index 00000000..b5378fd3 --- /dev/null +++ b/config/keygen.sh @@ -0,0 +1,91 @@ +#! /bin/sh + +while getopts n:h:u:g:o:e:y:bf c + do + case $c in + u) USER=$OPTARG;; + g) GROUP=$OPTARG;; + o) OUT=$OPTARG;; + b) BATCH=1;; + f) FORCE=1;; + h) FQDN=$OPTARG;; + e) ENTITYID=$OPTARG;; + y) YEARS=$OPTARG;; + n) PREFIX=$OPTARG;; + \?) echo "keygen [-o output directory (default .)] [-u username to own keypair] [-g owning groupname] [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert] [-n filename prefix (default 'sp')]" + exit 1;; + esac + done + +if [ -z "$OUT" ] ; then + OUT=. +fi + +if [ -z "$PREFIX" ]; then + PREFIX="sp" +fi + +if [ -n "$FORCE" ] ; then + rm $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem +fi + +if [ -s $OUT/${PREFIX}-key.pem -o -s $OUT/${PREFIX}-cert.pem ] ; then + if [ -z "$BATCH" ] ; then + echo The files $OUT/${PREFIX}-key.pem and/or $OUT/${PREFIX}-cert.pem already exist! + echo Use -f option to force recreation of keypair. + exit 2 + fi + exit 0 +fi + +if [ -z "$FQDN" ] ; then + FQDN=`hostname` +fi + +if [ -z "$YEARS" ] ; then + YEARS=10 +fi + +DAYS=`expr $YEARS \* 365` + +if [ -z "$ENTITYID" ] ; then + ALTNAME=DNS:$FQDN +else + ALTNAME=DNS:$FQDN,URI:$ENTITYID +fi + +SSLCNF=$OUT/${PREFIX}-cert.cnf +cat >$SSLCNF < /dev/null +fi +rm $SSLCNF + +if [ -s $OUT/${PREFIX}-key.pem -a -n "$USER" ] ; then + chown $USER $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem +fi + +if [ -s $OUT/${PREFIX}-key.pem -a -n "$GROUP" ] ; then + chgrp $GROUP $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem +fi -- GitLab From 58e1f4118500eac9508661366c0e02d99d8fabc0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 16:18:03 +0100 Subject: [PATCH 57/64] saving progress of access part of operator guide --- README.md | 2 +- documentation/operator-guide/index.rst | 1 + documentation/operator-guide/ingestion.rst | 4 +++- documentation/operator-guide/intro.rst | 21 +++++++++++++-------- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6747a87d..734ddd8a 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The following services are defined via docker compose files. ### shibauth -* based on the external unicon/shibboleth-sp:3.0.4 Apache + Shibboleth image +* based on the external unicon/shibboleth-sp:3.0.4 Apache + Shibboleth SP3 image * provides authentication and authorization via SAML2 * docker configuration files set access control rules * traefik labels determine which services are protected via Shib diff --git a/documentation/operator-guide/index.rst b/documentation/operator-guide/index.rst index 249dfe69..4aa4e923 100644 --- a/documentation/operator-guide/index.rst +++ b/documentation/operator-guide/index.rst @@ -12,6 +12,7 @@ View Server - Operator Guide configuration management ingestion + access .. Indices and tables diff --git a/documentation/operator-guide/ingestion.rst b/documentation/operator-guide/ingestion.rst index 8efdac75..f81dfee0 100644 --- a/documentation/operator-guide/ingestion.rst +++ b/documentation/operator-guide/ingestion.rst @@ -292,4 +292,6 @@ The preprocessing step aims to ensure that cloud optimized GeoTIFF (COG) files a - If data are already in COGs and in favorable projection, which will be presented to the user for most of the times, direct registration should be used. This means, paths to individual products will be pushed directly to the register queues. -- Also for cases, where preprocessing step would take too much time, direct registration allowing access to the metadata and catalog functions, while justifying slower rendering times can be preferred. \ No newline at end of file +- Also for cases, where preprocessing step would take too much time, direct registration allowing access to the metadata and catalog functions, while justifying slower rendering times can be preferred. + +Next chapter :ref:`access` describes used authorization and authentication concepts and lines out how the external access to individual components and service as such is configured. \ No newline at end of file diff --git a/documentation/operator-guide/intro.rst b/documentation/operator-guide/intro.rst index 3ee54989..6e818495 100644 --- a/documentation/operator-guide/intro.rst +++ b/documentation/operator-guide/intro.rst @@ -32,6 +32,9 @@ respective Docker image in parenthesis): - Database (postgis) - Queue Manager (redis) - Log collector (fluentd) +- Kibana (kibana) +- Elasticsearch (elasticsearch) +- Shibboleth SP3 (unicon/shibboleth-sp) These services are bundled and managed together in a Docker Swarm via Docker Compose configuration files. @@ -50,15 +53,17 @@ the used images: - mdillon/postgis:10 - redis -- traefik:2.1 -- elasticsearch:7.9.0 -- kibana:7.9.0 +- traefik +- elasticsearch +- kibana +- unicon/shibboleth-sp - atmoz/sftp -- registry.gitlab.eox.at/esa/prism/vs/fluentd:latest -- registry.gitlab.eox.at/esa/prism/vs/pvs_core:latest -- registry.gitlab.eox.at/esa/prism/vs/pvs_cache:latest -- registry.gitlab.eox.at/esa/prism/vs/pvs_preprocessor:latest -- registry.gitlab.eox.at/esa/prism/vs/pvs_client:latest +- registry.gitlab.eox.at/esa/prism/vs/fluentd +- registry.gitlab.eox.at/esa/prism/vs/pvs_core +- registry.gitlab.eox.at/esa/prism/vs/pvs_cache +- registry.gitlab.eox.at/esa/prism/vs/pvs_preprocessor +- registry.gitlab.eox.at/esa/prism/vs/pvs_client +- registry.gitlab.eox.at/esa/prism/vs/pvs_ingestor Configuration Files ------------------- -- GitLab From e201148131d36bd4f3c5b3bc3c2ecf8d761de970 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 17:04:49 +0100 Subject: [PATCH 58/64] wait until renderer is initialized too before registrar test --- testing/preprocessor_test.sh | 1 + testing/registrar_test.sh | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/testing/preprocessor_test.sh b/testing/preprocessor_test.sh index 60334fb9..c86f3e84 100755 --- a/testing/preprocessor_test.sh +++ b/testing/preprocessor_test.sh @@ -1,5 +1,6 @@ #!/bin/bash product_list_file=$1 +echo "Starting preprocessor test" while read product; do echo $product diff --git a/testing/registrar_test.sh b/testing/registrar_test.sh index 0e0b6ea8..7659f177 100755 --- a/testing/registrar_test.sh +++ b/testing/registrar_test.sh @@ -1,11 +1,12 @@ #!/bin/bash product_list_file=$1 -echo "inside registrar_test" +echo "Starting registrar test" OS_PASSWORD=$(docker exec -i $(docker ps -qf "name=emg-pvs_registrar") cat /run/secrets/OS_PASSWORD) IFS="," docker exec -i $(docker ps -qf "name=emg-pvs_registrar") /wait-initialized.sh +docker exec -i $(docker ps -qf "name=emg-pvs_renderer") /wait-initialized.sh while read product; do docker exec -e OS_PASSWORD=$OS_PASSWORD -i $(docker ps -qf "name=emg-pvs_registrar") \ python3 /registrar.py \ -- GitLab From 038b27602d1900863ab46e48f446ca82f6f0ad78 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 17:39:04 +0100 Subject: [PATCH 59/64] wip access part added into operator guide --- documentation/operator-guide/access.rst | 74 +++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 documentation/operator-guide/access.rst diff --git a/documentation/operator-guide/access.rst b/documentation/operator-guide/access.rst new file mode 100644 index 00000000..bc633f46 --- /dev/null +++ b/documentation/operator-guide/access.rst @@ -0,0 +1,74 @@ +.. _access: + +Access +====== +This chapter describes general concepts of how external access to each component is provided and how authentication and authorization layer based on `Shibboleth SP3 `_. is configured. + +General overview +~~~~~~~~~~~~~~~~ +Each individual docker **stack** has its own internal network ``intnet`` where services can communicate between each other. This network is not exposed to the public and provides most of the necessary communication. Additionally external user access to some services (client, renderer, cache) is provided via external network ``extnet`` and reverse-proxy (traefik) with load balancer. + +These services can have a set of authentication and authorization rules applied both on traefik level and Shibboleth SP level. Kibana and Traefik dashboard are also accessible externally, but through a different set of default credentials. + + +Routing with traefik +~~~~~~~~~~~~~~~~~~~~ +``Reverse-proxy`` service in base stack provides central access endpoint to the VS. It exposes ports 80 and 443 for HTTP and HTTPS access. Configuration of the reverse-proxy is done on three places. + +First two are static and dynamic configuration files ``traefik.yml`` and ``traefik-dynamic.yml``. Static configuration sets up connections to providers and define the entrypoints that Traefik will listen to. Dynamic configuration defines how the requests are handled. This configuration can change and is seamlessly hot-reloaded, without any request interruption or connection loss. Third part are docker ``labels`` on individual services which Traefik provides access to. + +For example following configuration snippet enables access to certain paths of ``renderer`` service under a given hostname. It also sets externally set basic authentication and other rules via ``@file`` identifier, which references configurations from ``traefik-dynamic.yml``. + +.. code-block:: yaml + + renderer: + deploy: + labels: + # router for basic auth based access (https) + - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer.tls=true" + - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer.entrypoints=https" + # general rules + - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" + - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" + - "traefik.docker.network=vhr18-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" + +An example of such auth@file configuration from ``traefik-dynamic.yml`` would be following snippet, where ``BASIC_AUTH_USERS_AUTH`` is referencing a docker secret configured earlier: + +.. code-block:: yaml + + http: + middlewares: + auth: + basicAuth: + realm: "PRISM View Server (PVS)" + usersFile: "/run/secrets/BASIC_AUTH_USERS_AUTH" + +Unsecured HTTP access is configured to be redirected to the HTTPS endpoint but inside the swarm among the services, only HTTP is used internally. Traefik also needs access to each external network, that he will be servicing. + +Authentication and Authorization +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Authentication of access to external parts of VS is made up of two options: + +- Traefik provided basic authentication - configured as ``file@auth`` and ``file@apiAuth`` + +Here, access on such endpoint requires basic authentication credentials (username, password) to be inserted, while web browsers are usually prompted for input. After inserting valid credentials, access is granted. + +- Shibboleth Service Provider 3 + Apache 2 instance, to which request is forwarded by `Traefik ForwardAuth middleware `_. + +Middleware delegates the authentication to Shibboleth. If Shibboleth response code is 2XX, access is granted and the original request is performed. Otherwise, the response from the Shibboleth is returned. + +Shibboleth can automatically establish a session whenever a particular URL is accessed. This means that any user accessing that resource must be able to authenticate at an IdP trusted by the SP. + +In order to authenticate with Shibboleth, a user must log in with valid credentials on the side of Identity Provider (IDP), if doing so, the IDP informs the SP about successful login, accompanied by relevant user attributes. SP then saves the information about a created session into a cookie and based on user attributes can authorize access to the services. + +Currently setting individual authorization rules on a ``Collection`` and ``Service`` level is possible with current approach. It is yet not clearly possible to separate viewing and download, as both of these parts are handled by ``renderer`` service. + +Configuration +~~~~~~~~~~~~~ + +Several parts of the SP need to be configured. -- GitLab From bd912877bc616e4556124a267433e24e85df3c74 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 18:46:21 +0100 Subject: [PATCH 60/64] remove one variable part in shibboleth2.xml config --- config/shibboleth/dem-shibboleth2.xml | 2 +- config/shibboleth/emg-shibboleth2.xml | 2 +- config/shibboleth/vhr18-shibboleth2.xml | 2 +- docker-compose.dem.ops.yml | 6 ++++-- docker-compose.emg.ops.yml | 6 ++++-- docker-compose.vhr18.ops.yml | 6 ++++-- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/config/shibboleth/dem-shibboleth2.xml b/config/shibboleth/dem-shibboleth2.xml index 2892d9ed..80564fad 100755 --- a/config/shibboleth/dem-shibboleth2.xml +++ b/config/shibboleth/dem-shibboleth2.xml @@ -23,7 +23,7 @@ - + diff --git a/config/shibboleth/emg-shibboleth2.xml b/config/shibboleth/emg-shibboleth2.xml index 1f158494..a659df73 100644 --- a/config/shibboleth/emg-shibboleth2.xml +++ b/config/shibboleth/emg-shibboleth2.xml @@ -23,7 +23,7 @@ - + diff --git a/config/shibboleth/vhr18-shibboleth2.xml b/config/shibboleth/vhr18-shibboleth2.xml index d18baeff..c063012b 100644 --- a/config/shibboleth/vhr18-shibboleth2.xml +++ b/config/shibboleth/vhr18-shibboleth2.xml @@ -23,7 +23,7 @@ - + diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index ce82c2dc..1c29b09a 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -176,8 +176,10 @@ services: environment: APACHE_SERVERNAME: "https://dem.pass.copernicus.eu:443" secrets: - - DEM_SHIB_CERT - - DEM_SHIB_KEY + - source: DEM_SHIB_CERT + target: SHIB_CERT + - source: DEM_SHIB_KEY + target: SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 0729c43a..61f2b860 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -176,8 +176,10 @@ services: environment: APACHE_SERVERNAME: "https://emg.pass.copernicus.eu:443" secrets: - - EMG_SHIB_CERT - - EMG_SHIB_KEY + - source: EMG_SHIB_CERT + target: SHIB_CERT + - source: EMG_SHIB_KEY + target: SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index 173e27b2..fe819375 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -176,8 +176,10 @@ services: environment: APACHE_SERVERNAME: "https://vhr18.pass.copernicus.eu:443" secrets: - - VHR18_SHIB_CERT - - VHR18_SHIB_KEY + - source: VHR18_SHIB_CERT + target: SHIB_CERT + - source: VHR18_SHIB_KEY + target: SHIB_KEY - BASIC_AUTH_USERS_AUTH deploy: replicas: 1 -- GitLab From d0bc419fb5c7bbcdab128af85864793e61b29546 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Tue, 10 Nov 2020 21:30:05 +0100 Subject: [PATCH 61/64] update access part, still wip --- config/{ => shibboleth}/keygen.sh | 0 documentation/operator-guide/access.rst | 85 +++++++++++++++++-------- 2 files changed, 58 insertions(+), 27 deletions(-) rename config/{ => shibboleth}/keygen.sh (100%) diff --git a/config/keygen.sh b/config/shibboleth/keygen.sh similarity index 100% rename from config/keygen.sh rename to config/shibboleth/keygen.sh diff --git a/documentation/operator-guide/access.rst b/documentation/operator-guide/access.rst index bc633f46..bcd09ae1 100644 --- a/documentation/operator-guide/access.rst +++ b/documentation/operator-guide/access.rst @@ -21,34 +21,34 @@ For example following configuration snippet enables access to certain paths of ` .. code-block:: yaml - renderer: - deploy: - labels: - # router for basic auth based access (https) - - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" - - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" - - "traefik.http.routers.vhr18-renderer.tls=true" - - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" - - "traefik.http.routers.vhr18-renderer.entrypoints=https" - # general rules - - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" - - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" - - "traefik.docker.network=vhr18-extnet" - - "traefik.docker.lbswarm=true" - - "traefik.enable=true" + renderer: + deploy: + labels: + # router for basic auth based access (https) + - "traefik.http.routers.vhr18-renderer.rule=Host(`vhr18.pdas.prism.eox.at`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.vhr18-renderer.middlewares=auth@file,compress@file,cors@file" + - "traefik.http.routers.vhr18-renderer.tls=true" + - "traefik.http.routers.vhr18-renderer.tls.certresolver=default" + - "traefik.http.routers.vhr18-renderer.entrypoints=https" + # general rules + - "traefik.http.services.vhr18-renderer.loadbalancer.sticky=false" + - "traefik.http.services.vhr18-renderer.loadbalancer.server.port=80" + - "traefik.docker.network=vhr18-extnet" + - "traefik.docker.lbswarm=true" + - "traefik.enable=true" An example of such auth@file configuration from ``traefik-dynamic.yml`` would be following snippet, where ``BASIC_AUTH_USERS_AUTH`` is referencing a docker secret configured earlier: .. code-block:: yaml - http: - middlewares: - auth: - basicAuth: - realm: "PRISM View Server (PVS)" - usersFile: "/run/secrets/BASIC_AUTH_USERS_AUTH" + http: + middlewares: + auth: + basicAuth: + realm: "PRISM View Server (PVS)" + usersFile: "/run/secrets/BASIC_AUTH_USERS_AUTH" -Unsecured HTTP access is configured to be redirected to the HTTPS endpoint but inside the swarm among the services, only HTTP is used internally. Traefik also needs access to each external network, that he will be servicing. +Unsecured HTTP access is configured to be redirected to the HTTPS endpoint but inside the swarm among the services, only HTTP is used internally. Authentication and Authorization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -58,17 +58,48 @@ Authentication of access to external parts of VS is made up of two options: Here, access on such endpoint requires basic authentication credentials (username, password) to be inserted, while web browsers are usually prompted for input. After inserting valid credentials, access is granted. -- Shibboleth Service Provider 3 + Apache 2 instance, to which request is forwarded by `Traefik ForwardAuth middleware `_. +- Shibboleth Service Provider 3 + Apache 2 instance, to which requests are forwarded by `Traefik ForwardAuth middleware `_. Middleware delegates the authentication to Shibboleth. If Shibboleth response code is 2XX, access is granted and the original request is performed. Otherwise, the response from the Shibboleth is returned. -Shibboleth can automatically establish a session whenever a particular URL is accessed. This means that any user accessing that resource must be able to authenticate at an IdP trusted by the SP. - -In order to authenticate with Shibboleth, a user must log in with valid credentials on the side of Identity Provider (IDP), if doing so, the IDP informs the SP about successful login, accompanied by relevant user attributes. SP then saves the information about a created session into a cookie and based on user attributes can authorize access to the services. +In order to authenticate with Shibboleth, a user must log in with valid credentials on the side of Identity Provider (IdP), if doing so, the IdP informs the SP about successful login, accompanied by relevant user attributes and a session is created for the user. SP then saves the information about a created session into a cookie and based on user attributes can authorize access to the services. If the user was already logged in, he is automatically Currently setting individual authorization rules on a ``Collection`` and ``Service`` level is possible with current approach. It is yet not clearly possible to separate viewing and download, as both of these parts are handled by ``renderer`` service. Configuration ~~~~~~~~~~~~~ +For correct configuration of Shibboleth SP3 on a new stack, several steps need to be done. +Briefly summarized, SP and IdP need to exchange metadata and certificates to trust each other, SP needs to know which attributes the IdP will be sending about the logged-in user and respective access-control rules are configured based on those attributes. Most of the configurations are done via docker configs defined in the docker compose + +- Create a pair of key, certificate using attached Shibboleth ``config/shibboleth/keygen.sh`` in the cloned vs repository and save them as respective docker secrets. + +.. code-block:: bash + + SPURL="https://emg.pass.copernicus.eu" # service initial access point made accessible by traefik + ./config/shibboleth/keygen.sh -h $SPURL -y 20 -e https://$SPURL/shibboleth -n sp-signing -f + docker secret create EMG_SHIB_CERT sp-signing-cert.pem + docker secret create _SHIB_KEY sp-signing-key.pem + +- Get IDP metadata and save it as a docker config. Also read the entityID of the IdP for further use in referencing it in your ``shibboleth2.xml`` configuration. +.. code-block:: bash + + docker config create idp-metadata idp-metadata-received.xml + +- Configure Apache ServerName used inside the ``shibauth`` service by modifying ``APACHE_SERVERNAME`` environment variable of corresponding ``shibauth`` service in ``docker-compose..ops.yml``. This URL should resolve to the actual service URL. + +- Modify shibboleth2.xml content by setting your "entityID" in Additionally edit the "entityID" value inside ``SSO`` element to match the IdP "entityID". Note that "entityID" does not need to resolve to an actual service URL. +.. code-block:: xml + + + SAML2 + + +- Deploy your shibauth service and exchange your SP metadata with the IdP provider and have them recognize your SP. Necessary metadata needs to be downloaded from url ``/Shibboleth.sso/Metadata``. + +- Get information about attributes provided by IdP and update ``config/shibboleth/attribute-map.xml`` by adding individual entries mapping ``name`` provided by IdP to ``id`` used by SP internally. -Several parts of the SP need to be configured. +- Create access-rules based on these attributes in Date: Wed, 11 Nov 2020 09:33:28 +0100 Subject: [PATCH 62/64] rename ac files to enable templating --- config/shibboleth/{dem_pass-ac-cache.xml => dem-ac-cache.xml} | 0 config/shibboleth/{dem_pass-ac.xml => dem-ac.xml} | 0 config/shibboleth/{emg_pass-ac-cache.xml => emg-ac-cache.xml} | 0 config/shibboleth/{emg_pass-ac.xml => emg-ac.xml} | 0 .../{vhr18_pass-ac-cache.xml => vhr18-ac-cache.xml} | 0 config/shibboleth/{vhr18_pass-ac.xml => vhr18-ac.xml} | 0 docker-compose.dem.ops.yml | 4 ++-- docker-compose.emg.ops.yml | 4 ++-- docker-compose.vhr18.ops.yml | 4 ++-- 9 files changed, 6 insertions(+), 6 deletions(-) rename config/shibboleth/{dem_pass-ac-cache.xml => dem-ac-cache.xml} (100%) rename config/shibboleth/{dem_pass-ac.xml => dem-ac.xml} (100%) rename config/shibboleth/{emg_pass-ac-cache.xml => emg-ac-cache.xml} (100%) rename config/shibboleth/{emg_pass-ac.xml => emg-ac.xml} (100%) rename config/shibboleth/{vhr18_pass-ac-cache.xml => vhr18-ac-cache.xml} (100%) rename config/shibboleth/{vhr18_pass-ac.xml => vhr18-ac.xml} (100%) diff --git a/config/shibboleth/dem_pass-ac-cache.xml b/config/shibboleth/dem-ac-cache.xml similarity index 100% rename from config/shibboleth/dem_pass-ac-cache.xml rename to config/shibboleth/dem-ac-cache.xml diff --git a/config/shibboleth/dem_pass-ac.xml b/config/shibboleth/dem-ac.xml similarity index 100% rename from config/shibboleth/dem_pass-ac.xml rename to config/shibboleth/dem-ac.xml diff --git a/config/shibboleth/emg_pass-ac-cache.xml b/config/shibboleth/emg-ac-cache.xml similarity index 100% rename from config/shibboleth/emg_pass-ac-cache.xml rename to config/shibboleth/emg-ac-cache.xml diff --git a/config/shibboleth/emg_pass-ac.xml b/config/shibboleth/emg-ac.xml similarity index 100% rename from config/shibboleth/emg_pass-ac.xml rename to config/shibboleth/emg-ac.xml diff --git a/config/shibboleth/vhr18_pass-ac-cache.xml b/config/shibboleth/vhr18-ac-cache.xml similarity index 100% rename from config/shibboleth/vhr18_pass-ac-cache.xml rename to config/shibboleth/vhr18-ac-cache.xml diff --git a/config/shibboleth/vhr18_pass-ac.xml b/config/shibboleth/vhr18-ac.xml similarity index 100% rename from config/shibboleth/vhr18_pass-ac.xml rename to config/shibboleth/vhr18-ac.xml diff --git a/docker-compose.dem.ops.yml b/docker-compose.dem.ops.yml index 1c29b09a..0fa2a23e 100644 --- a/docker-compose.dem.ops.yml +++ b/docker-compose.dem.ops.yml @@ -233,9 +233,9 @@ networks: external: true configs: shib-access-control-conf: - file: ./config/shibboleth/dem_pass-ac.xml + file: ./config/shibboleth/dem-ac.xml shib-access-control-conf-cache: - file: ./config/shibboleth/dem_pass-ac-cache.xml + file: ./config/shibboleth/dem-ac-cache.xml shib-shibboleth2: file: ./config/shibboleth/dem-shibboleth2.xml shib-apache: diff --git a/docker-compose.emg.ops.yml b/docker-compose.emg.ops.yml index 61f2b860..98a5ba55 100644 --- a/docker-compose.emg.ops.yml +++ b/docker-compose.emg.ops.yml @@ -233,9 +233,9 @@ networks: external: true configs: shib-access-control-conf: - file: ./config/shibboleth/emg_pass-ac.xml + file: ./config/shibboleth/emg-ac.xml shib-access-control-conf-cache: - file: ./config/shibboleth/emg_pass-ac-cache.xml + file: ./config/shibboleth/emg-ac-cache.xml shib-shibboleth2: file: ./config/shibboleth/emg-shibboleth2.xml shib-apache: diff --git a/docker-compose.vhr18.ops.yml b/docker-compose.vhr18.ops.yml index fe819375..1c8a5f4c 100644 --- a/docker-compose.vhr18.ops.yml +++ b/docker-compose.vhr18.ops.yml @@ -233,9 +233,9 @@ networks: external: true configs: shib-access-control-conf: - file: ./config/shibboleth/vhr18_pass-ac.xml + file: ./config/shibboleth/vhr18-ac.xml shib-access-control-conf-cache: - file: ./config/shibboleth/vhr18_pass-ac-cache.xml + file: ./config/shibboleth/vhr18-ac-cache.xml shib-shibboleth2: file: ./config/shibboleth/vhr18-shibboleth2.xml shib-apache: -- GitLab From bd5d090c967954b17a37dca831d76555c0cea3f0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 11 Nov 2020 10:10:57 +0100 Subject: [PATCH 63/64] finish access part of op guide --- documentation/operator-guide/access.rst | 82 +++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/documentation/operator-guide/access.rst b/documentation/operator-guide/access.rst index bcd09ae1..b96c281e 100644 --- a/documentation/operator-guide/access.rst +++ b/documentation/operator-guide/access.rst @@ -68,7 +68,7 @@ Currently setting individual authorization rules on a ``Collection`` and ``Servi Configuration ~~~~~~~~~~~~~ -For correct configuration of Shibboleth SP3 on a new stack, several steps need to be done. +For correct configuration of Shibboleth SP3 on a new stack, several steps need to be done. Most of these configurations are usually done in the :ref:`_initialization` step using ``pvs_starter`` tool. Still, it is advised to check following steps, understand them and change if necessary. Briefly summarized, SP and IdP need to exchange metadata and certificates to trust each other, SP needs to know which attributes the IdP will be sending about the logged-in user and respective access-control rules are configured based on those attributes. Most of the configurations are done via docker configs defined in the docker compose - Create a pair of key, certificate using attached Shibboleth ``config/shibboleth/keygen.sh`` in the cloned vs repository and save them as respective docker secrets. @@ -98,8 +98,80 @@ Briefly summarized, SP and IdP need to exchange metadata and certificates to tru - Deploy your shibauth service and exchange your SP metadata with the IdP provider and have them recognize your SP. Necessary metadata needs to be downloaded from url ``/Shibboleth.sso/Metadata``. -- Get information about attributes provided by IdP and update ``config/shibboleth/attribute-map.xml`` by adding individual entries mapping ``name`` provided by IdP to ``id`` used by SP internally. +- Get information about attributes provided by IdP and update ``config/shibboleth/attribute-map.xml`` by adding individual entries mapping ``name`` provided by IdP to ``id`` used by SP internally. Example configuration: -- Create access-rules based on these attributes in + + + + +- Create custom access rules based on these attributes and map these access controls to different internal apache routes to which Traefik ForwardAuth middleware will point. Access rules are created in ``config/shibboleth/-ac.xml``. +Example of external Access control rules configuration: + +.. code-block:: xml + + + + .+ + + Privileged_Access Public_Access + + + + +- Check configured link between Apache configuration for ``shibauth`` service, access rules, Traefik ForwardAuth middleware and per-service Traefik labels. Following simplified examples show the links in more detail: + +``APACHE_SERVERNAME`` environment variable needs to be set and same as the hostname, that Traefik will be serving as main entry point. Part of docker compose of shibauth service in ``docker-compose.emg.ops.yml``: + +.. code-block:: yaml + + services: + shibauth: + environment: + APACHE_SERVERNAME: "https://emg.pass.copernicus.eu:443" + deploy: + labels: + - "traefik.http.routers.shibauth.rule=Host(`emg.pass.copernicus.eu`) && PathPrefix(`/secure`, `/Shibboleth.sso`)" + ... + +Relevant Apache configuration in ``config/shibboleth/shib-apache.conf``, enabling Shibboleth authentication and authorization of the ``/secure`` endpoint. + +.. code-block:: apacheconf + + + SetHandler shib + + + PassEnv APACHE_SERVERNAME + ServerName "${APACHE_SERVERNAME}" + + AuthType shibboleth + ShibRequestSetting requireSession 1 + Require shib-plugin /etc/shibboleth/pass-ac.xml + + ... + +Part of Traefik ForwardAuth middleware configuration from ``traefik-dynamic.yml``, defining the internal address pointing to the ``shibauth`` service and ``/secure`` endpoint in it: + +.. code-block:: yaml + + http: + middlewares: + shibAuth: + forwardAuth: + address: http://shibauth/secure + trustForwardHeader: true + +Part of renderer service Traefik labels from ``docker-compose.emg.ops.yml``, where access through the middleware is configured. + +.. code-block:: yaml + + services: + renderer: + deploy: + labels: + # router for shib auth based access (https) + - "traefik.http.routers.emg-renderer-shib.rule=Host(`emg.pass.copernicus.eu`) && PathPrefix(`/ows`, `/opensearch`, `/admin`)" + - "traefik.http.routers.emg-renderer-shib.middlewares=shibAuth@file" -- GitLab From c9a8be2cd327b6238df5d83495aaa515a9dae4b0 Mon Sep 17 00:00:00 2001 From: Lubomir Bucek Date: Wed, 11 Nov 2020 11:04:32 +0100 Subject: [PATCH 64/64] docs finalize ingestion part --- .../operator-guide/configuration.rst | 4 +++ documentation/operator-guide/ingestion.rst | 31 ++++++++++++++++--- documentation/operator-guide/management.rst | 3 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/documentation/operator-guide/configuration.rst b/documentation/operator-guide/configuration.rst index 72de645c..47c1ea10 100644 --- a/documentation/operator-guide/configuration.rst +++ b/documentation/operator-guide/configuration.rst @@ -277,6 +277,8 @@ source/target Here, the source file storage and the target file storage are configured. This can either be a local directory or an OpenStack Swift object storage. + If Swift is used for source, download container can be left unset. In that case, + container can be inferred from the given path in format /. workdir @@ -531,5 +533,7 @@ An example of creating ``BASIC_AUTH_USERS_AUTH`` secret: htpasswd -nb user2 YyuN9bYRvBUUU6COx7itWw5qyyARus >> auth_list.txt docker secret create BASIC_AUTH_USERS_AUTH auth_list.txt +For configuration of the ``shibauth`` service, please consult a separate chapter :ref:`access`. + The next section :ref:`management` describes how an operator interacts with a deployed VS stack. diff --git a/documentation/operator-guide/ingestion.rst b/documentation/operator-guide/ingestion.rst index f81dfee0..456d9ca7 100644 --- a/documentation/operator-guide/ingestion.rst +++ b/documentation/operator-guide/ingestion.rst @@ -82,7 +82,7 @@ For a more concrete example the following command executes a .. code-block:: bash - redis-cli lpush preprocess_queue "/data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar" + redis-cli lpush preprocess_queue "data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar" Usually, with a preprocessor service running and no other items in the ``preprocess_queue`` this value will be immediately popped from the list and @@ -92,7 +92,7 @@ of the ``preprocess_queue``: .. code-block:: bash $ redis-cli lrange preprocess_queue 0 -1 - /data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar + data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar Now that the product is being preprocessed, it should be visible in the ``preprocessing_set``. As the name indicates, this is using the ``Set`` @@ -101,7 +101,7 @@ datatype, thus requiring the ``SMEMBERS`` subcommand to list: .. code-block:: bash $ redis-cli smembers preprocessing_set 0 -1 - /data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar + data25/OA/PL00/1.0/00/urn:eop:DOVE:MULTISPECTRAL_4m:20180811_081455_1054_3be7/0001/PL00_DOV_MS_L3A_20180811T081455_20180811T081455_TOU_1234_3be7.DIMA.tar Once the preprocessing of the product is finished, the preprocessor will remove the currently worked on path from the ``preprocessing_set`` and add it either @@ -130,6 +130,27 @@ added to the ``registering_set``, afterwards the path is placed to either the sets can be inspected by the ``LRANGE`` or ``SMEMBERS`` subcommands respectively. +Ingestor and sftp +~~~~~~~~~~~~~~~~~ +Triggering preprocessing and registration via pushing to the redis queues is very convenient for single ingestion campaigns, but not optimal for continuous ingestion of new products from "live" sources. +``Ingestor`` service, together optionally with ``sftp`` service allow data ingestion to be initiated by external means. + +``Ingestor`` can work in two modes: + +- Default: Exposing a simple ``/`` endpoint, and listening for ``POST`` requests containing ``data`` with either a Browse Report JSON or a string with path to the object storage with product to be ingested. It then parses this informatio and internally puts it into configured redis queue (preprocess or register). +- Alternative: Listening for newly added Browse Report files on a configured path on a file system via ``inotify``. +These Browse Report files need to be in an agreed XML schema to be correctly handled. +``Sftp`` service enables a secure access to a configured folder via sftp, while this folder can be mounted to other vs services. This way, ``Ingestor`` can listen for newly created files by the sftp access. +If the filedaemon alternative mode should be used, ``INOTIFY_WATCH_DIR`` environment variable needs to be set and a ``command`` used in the docker-compose..ops.yml for ``ingestor`` service needs to be set to ``python3 filedaemon.py``: + +.. code-block:: yaml + + ingestor: + environment: + REDIS_PREPROCESS_MD_QUEUE_KEY: "preprocess_queue" # to override md_queue (json) and instead use (string) + command: + ["python3", "/filedaemon.py"] + Direct Data Management ---------------------- @@ -288,9 +309,9 @@ Deregistration Preprocessing vs registration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The preprocessing step aims to ensure that cloud optimized GeoTIFF (COG) files are created in order to significantly speed up the viewing of large amount of data in lower zooms. There are several cases, where such preprocessing is not necessary or wanted. +The preprocessing step aims to ensure that cloud optimized GeoTIFF (COG) files are created in order to significantly speed up the viewing of large amount of data in lower zoom levels. There are several cases, where such preprocessing is not necessary or wanted. -- If data are already in COGs and in favorable projection, which will be presented to the user for most of the times, direct registration should be used. This means, paths to individual products will be pushed directly to the register queues. +- If data are already in COGs and in favorable projection, which will be presented to the user for most of the times, direct registration should be used. This means, paths to individual products will be pushed directly to the register-queue. - Also for cases, where preprocessing step would take too much time, direct registration allowing access to the metadata and catalog functions, while justifying slower rendering times can be preferred. diff --git a/documentation/operator-guide/management.rst b/documentation/operator-guide/management.rst index 565c8a30..bbb33703 100644 --- a/documentation/operator-guide/management.rst +++ b/documentation/operator-guide/management.rst @@ -62,8 +62,7 @@ shutting down of the stack and new deployment. Inspecting reports ------------------ -Once registered, a xml report containing wcs and wms getcapabilities of the registered product is generated and can be accessed by connecting to the `SFTP` image -via the sftp protocol. +Once a product is registered, a xml report containing wcs and wms getcapabilities of the registered product is generated and can be accessed by connecting to the `SFTP` service via the sftp protocol. In order to log into the logging folders through port 2222 on the hosting ip (e.g. localhost if you are running the dev stack) The following command can be used: .. code-block:: bash -- GitLab