From 45c4a3d1d2245d278d7863e20cd7428c95a5e6bf Mon Sep 17 00:00:00 2001 From: Stefano Sinatti Date: Mon, 24 Jun 2024 15:40:39 +0200 Subject: [PATCH] First commit --- CHANGELOG.md | 42 + CONTAINER-SCAN-REPORT.md | 14 +- Dockerfile | 2 +- RELEASE-NOTES.md | 6 +- docker_build/certs/rer_ca.crt | 32 - docker_build/certs/rer_ca01.crt | 41 - docker_build/certs/rer_rootca.crt | 23 - docker_build/certs/rer_rootcat01.crt | 33 - pom.xml | 24 +- pom.xml.github | 694 +++++++++++++ .../core/bean/CommonsDataHttpClient.java | 964 ++++++++++++++++++ .../eidas/core/bean/CommonsDataLoaderExt.java | 49 +- .../eidas/core/bean/CustomDataLoaderExt.java | 106 ++ .../eidas/core/bean/OCSPDataLoaderExt.java | 47 +- .../parer/eidas/core/helper/EidasHelper.java | 42 +- .../CustomRemoteDocumentValidationImpl.java | 39 +- .../eidas/core/service/VerificaFirmaImpl.java | 6 +- .../eng/parer/eidas/core/util/Constants.java | 4 +- .../parer/eidas/web/config/AdviceHandler.java | 16 +- .../eidas/web/config/AppConfiguration.java | 2 +- .../parer/eidas/web/config/DSSBeanConfig.java | 241 +++-- .../parer/eidas/web/rest/VerificaFirmaWs.java | 9 + .../verifica-firma-eidas-template.yml | 2 - .../resources/policy/custom_constraint.xml | 2 +- 24 files changed, 2170 insertions(+), 270 deletions(-) delete mode 100644 docker_build/certs/rer_ca.crt delete mode 100644 docker_build/certs/rer_ca01.crt delete mode 100644 docker_build/certs/rer_rootca.crt delete mode 100644 docker_build/certs/rer_rootcat01.crt create mode 100644 pom.xml.github create mode 100644 src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java diff --git a/CHANGELOG.md b/CHANGELOG.md index a0cbe15..66081a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,50 @@ + +## 1.22.1 (24-06-2024) + +### Bugfix: 1 +- [#32811](https://parermine.regione.emilia-romagna.it/issues/32811) Correzione gestione "log level error" nei casi di errori "non previsti" da "gestiti in verifica firma digitale" + +## 1.22.0 (12-06-2024) + +### Novità: 1 +- [#32708](https://parermine.regione.emilia-romagna.it/issues/32708) Disattivazione PDF/PADES validation security checks (DSS) + +## 1.21.0 (10-06-2024) + +### Novità: 1 +- [#32690](https://parermine.regione.emilia-romagna.it/issues/32690) Introduzione di logica centralizzata per invocazione revocation URL via "single client instance" (DSS) + +## 1.20.0 (06-06-2024) + +### Novità: 1 +- [#32661](https://parermine.regione.emilia-romagna.it/issues/32661) Ottimizzazione/Re-factor apache client utilizzato per recupero documento da verificare e parametro per disattivazione verifica SSL + +## 1.19.0 (31-05-2024) + +### Novità: 1 +- [#32644](https://parermine.regione.emilia-romagna.it/issues/32644) Introduzione logging JSON body request + +## 1.18.0 (22-05-2024) + +### Novità: 1 +- [#32595](https://parermine.regione.emilia-romagna.it/issues/32595) Introduzione Apache basic client "no-retry" per recupero oggetto da object storage + +## 1.17.0 (10-04-2024) + +### Novità: 2 +- [#31808](https://parermine.regione.emilia-romagna.it/issues/31808) Rilassamento vincoli con verifica OCSP e data certificato antecedenete a quella del responder +- [#31709](https://parermine.regione.emilia-romagna.it/issues/31709) Gestione migliorata sorgenti revoche (cache / online) + ## 1.16.0 (14-03-2024) ### Novità: 1 - [#31419](https://parermine.regione.emilia-romagna.it/issues/31419) Attivazione statistiche per monitoraggio con prometheus +## 1.15.1 (16-02-2024) + +### Bugfix: 1 +- [#31275](https://parermine.regione.emilia-romagna.it/issues/31275) Correzione errore PKI su https://elektroninisparasas.lt/LT-TSL.xml + ## 1.15.0 (29-01-2024) ### Novità: 2 diff --git a/CONTAINER-SCAN-REPORT.md b/CONTAINER-SCAN-REPORT.md index dc16c7d..3926ec3 100644 --- a/CONTAINER-SCAN-REPORT.md +++ b/CONTAINER-SCAN-REPORT.md @@ -1,7 +1,15 @@ ## Container scan evidence CVE Image name: registry.ente.regione.emr.it/parer/okd/verifica-firma-eidas:sast -
Run date: Mon Jan 29 12:20:03 CET 2024 -
Produced by: Job -
CVE founded: 0 +
Run date: Mon Jun 24 11:42:47 CEST 2024 +
Produced by: Job +
CVE founded: 8 | CVE | Description | Severity | Solution | |:---:|:---|:---:|:---| +| [CVE-2024-2961](http://www.openwall.com/lists/oss-security/2024/04/17/9)|The iconv() function in the GNU C Library versions 2.39 and older may overflow the output buffer passed to it by up to 4 bytes when converting strings to the ISO-2022-CN-EXT character set, which may be used to crash an application or overwrite a neighbouring variable.|High|Upgrade glibc to 2.28-251.el8_10.1| +| [CVE-2024-33599](https://access.redhat.com/errata/RHSA-2024:3344)|nscd: Stack-based buffer overflow in netgroup cacheIf the Name Service Cache Daemon's (nscd) fixed size cache is exhaustedby client requests then a subsequent client request for netgroup datamay result in a stack-based buffer overflow. This flaw was introducedin glibc 2.15 when the cache was added to nscd.This vulnerability is only present in the nscd binary.|High|Upgrade glibc to 2.28-251.el8_10.2| +| [CVE-2024-2961](http://www.openwall.com/lists/oss-security/2024/04/17/9)|The iconv() function in the GNU C Library versions 2.39 and older may overflow the output buffer passed to it by up to 4 bytes when converting strings to the ISO-2022-CN-EXT character set, which may be used to crash an application or overwrite a neighbouring variable.|High|Upgrade glibc-common to 2.28-251.el8_10.1| +| [CVE-2024-33599](https://access.redhat.com/errata/RHSA-2024:3344)|nscd: Stack-based buffer overflow in netgroup cacheIf the Name Service Cache Daemon's (nscd) fixed size cache is exhaustedby client requests then a subsequent client request for netgroup datamay result in a stack-based buffer overflow. This flaw was introducedin glibc 2.15 when the cache was added to nscd.This vulnerability is only present in the nscd binary.|High|Upgrade glibc-common to 2.28-251.el8_10.2| +| [CVE-2024-2961](http://www.openwall.com/lists/oss-security/2024/04/17/9)|The iconv() function in the GNU C Library versions 2.39 and older may overflow the output buffer passed to it by up to 4 bytes when converting strings to the ISO-2022-CN-EXT character set, which may be used to crash an application or overwrite a neighbouring variable.|High|Upgrade glibc-minimal-langpack to 2.28-251.el8_10.1| +| [CVE-2024-33599](https://access.redhat.com/errata/RHSA-2024:3344)|nscd: Stack-based buffer overflow in netgroup cacheIf the Name Service Cache Daemon's (nscd) fixed size cache is exhaustedby client requests then a subsequent client request for netgroup datamay result in a stack-based buffer overflow. This flaw was introducedin glibc 2.15 when the cache was added to nscd.This vulnerability is only present in the nscd binary.|High|Upgrade glibc-minimal-langpack to 2.28-251.el8_10.2| +| [CVE-2023-6597](http://www.openwall.com/lists/oss-security/2024/03/20/5)|An issue was found in the CPython `tempfile.TemporaryDirectory` class affecting versions 3.12.1, 3.11.7, 3.10.13, 3.9.18, and 3.8.18 and prior.The tempfile.TemporaryDirectory class would dereference symlinks during cleanup of permissions-related errors. This means users which can run privileged programs are potentially able to modify permissions of files referenced by symlinks in some circumstances.|High|Upgrade platform-python to 3.6.8-62.el8_10| +| [CVE-2023-6597](http://www.openwall.com/lists/oss-security/2024/03/20/5)|An issue was found in the CPython `tempfile.TemporaryDirectory` class affecting versions 3.12.1, 3.11.7, 3.10.13, 3.9.18, and 3.8.18 and prior.The tempfile.TemporaryDirectory class would dereference symlinks during cleanup of permissions-related errors. This means users which can run privileged programs are potentially able to modify permissions of files referenced by symlinks in some circumstances.|High|Upgrade python3-libs to 3.6.8-62.el8_10| diff --git a/Dockerfile b/Dockerfile index 0697f21..ea6adcd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -77,7 +77,7 @@ # accessed directly. (example: "foo.example.com,bar.example.com") # ### -FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 +FROM registry.access.redhat.com/ubi8/openjdk-17:1.19 LABEL io.k8s.description="Microservizio verifica firma EIDAS (basato su immagine ubi RedHat)" \ io.k8s.display-name="Verifica firma EIDAS" \ diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 683c678..f02bf7a 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,4 +1,4 @@ -## 1.16.0 (14-03-2024) +## 1.22.1 (24-06-2024) -### Novità: 1 -- [#31419](https://parermine.regione.emilia-romagna.it/issues/31419) Attivazione statistiche per monitoraggio con prometheus +### Bugfix: 1 +- [#32811](https://parermine.regione.emilia-romagna.it/issues/32811) Correzione gestione "log level error" nei casi di errori "non previsti" da "gestiti in verifica firma digitale" diff --git a/docker_build/certs/rer_ca.crt b/docker_build/certs/rer_ca.crt deleted file mode 100644 index f7a6d76..0000000 --- a/docker_build/certs/rer_ca.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFjTCCBHWgAwIBAgIKcbpkygAAAAAABTANBgkqhkiG9w0BAQUFADCBgTESMBAG -CgmSJomT8ixkARkWAklUMRMwEQYKCZImiZPyLGQBGRYDRU1SMRcwFQYKCZImiZPy -LGQBGRYHUkVHSU9ORTEUMBIGCgmSJomT8ixkARkWBEVOVEUxJzAlBgNVBAMTHlJl -Z2lvbmUgRW1pbGlhLVJvbWFnbmEgUk9PVCBDQTAeFw0xNTAyMDUwOTIxNDJaFw0y -NTAyMDUwOTMxNDJaMHwxEjAQBgoJkiaJk/IsZAEZFgJpdDETMBEGCgmSJomT8ixk -ARkWA2VtcjEXMBUGCgmSJomT8ixkARkWB3JlZ2lvbmUxFDASBgoJkiaJk/IsZAEZ -FgRlbnRlMSIwIAYDVQQDExlSZWdpb25lIEVtaWxpYS1Sb21hZ25hIENBMIGfMA0G -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQdFPINsDDNr55JNSy8tCIOMBUOfdnzyEA -0RD7ydR/ihcehIaV1JCyiRw2g49HIk+06hcU4sXW6O5sztWUcZnSGHutnCxlMoOV -JjCtY0YL++1IZT7ov0q9HLafcFmTFLNVUtBGmXDFQD2ygzd/xTLvhEKSj+AJ7gQf -hgL1yPMagQIDAQABo4ICjTCCAokwEAYJKwYBBAGCNxUBBAMCAQEwIwYJKwYBBAGC -NxUCBBYEFJNy7NS5rDkZHjFOhRkJw4Cx9akuMB0GA1UdDgQWBBQonMbqQS1rvym7 -yXzQ8Ngt0ScB2zAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC -AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSBKCoY+RIG79+a5asQGWAJ -8yu1AjCB7wYDVR0fBIHnMIHkMIHhoIHeoIHbhoHYbGRhcDovLy9DTj1SZWdpb25l -JTIwRW1pbGlhLVJvbWFnbmElMjBST09UJTIwQ0EsQ049Q0FST09ULENOPUNEUCxD -Tj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1 -cmF0aW9uLERDPUVOVEUsREM9UkVHSU9ORSxEQz1FTVIsREM9SVQ/Y2VydGlmaWNh -dGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlv -blBvaW50MIHkBggrBgEFBQcBAQSB1zCB1DCB0QYIKwYBBQUHMAKGgcRsZGFwOi8v -L0NOPVJlZ2lvbmUlMjBFbWlsaWEtUm9tYWduYSUyMFJPT1QlMjBDQSxDTj1BSUEs -Q049UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmln -dXJhdGlvbixEQz1FTlRFLERDPVJFR0lPTkUsREM9RU1SLERDPUlUP2NBQ2VydGlm -aWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MA0G -CSqGSIb3DQEBBQUAA4IBAQCGqa+fPZUFeaDKLHBe/An/3U0v7nAfF6pbg9N0PpoN -L1DwDFw+FoZADZx/NCjc0Lb6uu7SGMe0qgKOwqvMDqxSs5NMC15U6lWocQi3okgV -5p+aWV727sqiYmra40eu8oHLVmWlszUKyf/P0iTjNgvHORVcve9clIfHrfdhfsnL -DlT7+YMkZC0PRFN6Owh61bUfxRROpudBxYbmc51txbqUs/hPjP3Phek+KP3pBhW5 -o+Z4mh7eF1mHsvfgtYXb3vvXRRJi9vdpSR14brMEuwAaOO7N7u6559fWJsV5v6Ad -FqP7cS4KfxSh3Ce33uEjg83HAM0xq1WCYTcRYMrmUTm9 ------END CERTIFICATE----- diff --git a/docker_build/certs/rer_ca01.crt b/docker_build/certs/rer_ca01.crt deleted file mode 100644 index de8639a..0000000 --- a/docker_build/certs/rer_ca01.crt +++ /dev/null @@ -1,41 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHSjCCBTKgAwIBAgITIAAAAAQjnDHJc/zNMgAAAAAABDANBgkqhkiG9w0BAQsF -ADArMSkwJwYDVQQDEyBSZWdpb25lIEVtaWxpYS1Sb21hZ25hIFJPT1QgQ0EwMTAe -Fw0xNzA1MDgxNTIxMjdaFw0yNzA1MDgxNTMxMjdaMH4xEjAQBgoJkiaJk/IsZAEZ -FgJpdDETMBEGCgmSJomT8ixkARkWA2VtcjEXMBUGCgmSJomT8ixkARkWB3JlZ2lv -bmUxFDASBgoJkiaJk/IsZAEZFgRlbnRlMSQwIgYDVQQDExtSZWdpb25lIEVtaWxp -YS1Sb21hZ25hIENBMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo -eIjHFymX4IXGLtSCnIYfRFV3ok0q+oq/nLi7R9QngOOsqXiWTLX83N73uha3szzE -k9ytn1W7+wab4zOP3DKD2Bx5DvMP+voK8QljahWpnOOgLPzD0bi0030cgJKGHtkZ -I/2fF25cuZ09hT4UZHb4RAjtgrpHGmhOIz+UIyP7Z+6aXiKDheSnS/YLxLu3c6GG -nBxCdJdTaXtw1jLDKmPHtgQ6ekeUhW2CDSEFB2zf6IlRSzy7o3DTXsEllMSIKhXj -X1I1NmwlHg9sqkZC9rDvmavEW007DSWSD0+XPOBx+SzWceKglrwe9jb17ZX8cTKW -w0Zrv8VenGvDwzEioOKFAgMBAAGjggMSMIIDDjAQBgkrBgEEAYI3FQEEAwIBATAj -BgkrBgEEAYI3FQIEFgQUTo2NUoDIXySFh91x8pshEISFbcUwHQYDVR0OBBYEFIpr -Wqcndg9DultgkfHAMgmtfshzMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsG -A1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFF3O4loUC2Lg -OBPDJAvjU2YUyjbbMIIBLQYDVR0fBIIBJDCCASAwggEcoIIBGKCCARSGgdxsZGFw -Oi8vL0NOPVJlZ2lvbmUlMjBFbWlsaWEtUm9tYWduYSUyMFJPT1QlMjBDQTAxLENO -PXZtNDU5c3J2LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1T -ZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUVOVEUsREM9UkVHSU9ORSxEQz1F -TVIsREM9SVQ/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENs -YXNzPWNSTERpc3RyaWJ1dGlvblBvaW50hjNodHRwOi8vY2VydGF1dGguZW50ZS5y -ZWdpb25lLmVtci5pdC9SRVJSb290Q0EwMS5jcmwwggEpBggrBgEFBQcBAQSCARsw -ggEXMIHTBggrBgEFBQcwAoaBxmxkYXA6Ly8vQ049UmVnaW9uZSUyMEVtaWxpYS1S -b21hZ25hJTIwUk9PVCUyMENBMDEsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNl -cnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9RU5URSxEQz1S -RUdJT05FLERDPUVNUixEQz1JVD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xh -c3M9Y2VydGlmaWNhdGlvbkF1dGhvcml0eTA/BggrBgEFBQcwAoYzaHR0cDovL2Nl -cnRhdXRoLmVudGUucmVnaW9uZS5lbXIuaXQvUkVSUm9vdENBMDEuY2VyMA0GCSqG -SIb3DQEBCwUAA4ICAQC6Q9Q8iQpRAOZuoMkRkNXnxwvlB3i0QJXPxOUwate5vFPM -uWlLXepINKBj2sF70hSbnCvXbPAyNBfG/8TMrNHC8WmeUZtNKE0I0p8lQBQMu6x7 -aFLFLoqzkLC++6DgwBxlFSB8/5Q03C09gEJSLJmRB7zRAmFD3GjxMcPEL+SILsfK -BRV/RtnGONRlFp/f7p6a9+A7U5srJwhJ6oWKI3KdzDvi8HtEo/6Plm1dfQSSkM5z -Z5b63ODjARmwvGwLgDJp3jrWkd9ctDQNJFXNuGWxxiyXkvT+06W6li+NRAucgMec -AiNziw5DGS0Bakow2ZC1Rw8PwIvlXSgx5zjzHlRGOWGyFtG59zaCOzvAp1a0vIhW -gvQH6LgeD0w2A5sn1POlnMibEezVuL+kLViU5bmC54L2+hzO6YSr+R5Sv52iw5bZ -Csbfn7c/2yj+Nw7i+vfEMWQ064RJR5PFGL/pZ8dmbql19mDnGu6HRgLy76TtzO5R -drTotwwsXnFQ6e8frz3FSVhWhwjMyVy/VtQNoFlSpyqIr8sa4ahcwPiGLreMxZon -UofmfknG15Y9CwJSsZvIPg0XPkDKPoJO2pENLIqm7bUCK6iWbWTl3CoChk40aj5U -NzLgLcXeJe9zqiKmPHFKVvVyp1p+I/XT06A50htVk31ylGBCVmYLpjbz5PB2eA== ------END CERTIFICATE----- diff --git a/docker_build/certs/rer_rootca.crt b/docker_build/certs/rer_rootca.crt deleted file mode 100644 index 6eb8710..0000000 --- a/docker_build/certs/rer_rootca.crt +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID3zCCAsegAwIBAgIQbH6Su1Vgr7pJAFxdtREKnjANBgkqhkiG9w0BAQUFADCB -gTESMBAGCgmSJomT8ixkARkWAklUMRMwEQYKCZImiZPyLGQBGRYDRU1SMRcwFQYK -CZImiZPyLGQBGRYHUkVHSU9ORTEUMBIGCgmSJomT8ixkARkWBEVOVEUxJzAlBgNV -BAMTHlJlZ2lvbmUgRW1pbGlhLVJvbWFnbmEgUk9PVCBDQTAeFw0wNjAxMjAxMDQ3 -MjhaFw0yNjAxMjAxMDU2MDFaMIGBMRIwEAYKCZImiZPyLGQBGRYCSVQxEzARBgoJ -kiaJk/IsZAEZFgNFTVIxFzAVBgoJkiaJk/IsZAEZFgdSRUdJT05FMRQwEgYKCZIm -iZPyLGQBGRYERU5URTEnMCUGA1UEAxMeUmVnaW9uZSBFbWlsaWEtUm9tYWduYSBS -T09UIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyiRjGV2siCpH -SVLc3+/fZAs/ke7Zqn8Pwwx+NeoQwySXmotCOk5DXvh5HOMhZ10xZYH57Iij/jgP -kN7E0IeBv0VvPxF6inpIBl7EINWzHu10F1vkxnz3W0Qd74pUOmdiWA98/ZFS4Nc0 -cTQZLpMFzzo5KIgVhkxXS9pbgj1TjWt1/BSRRNHwv4j8jxgxz7tPnaAWarlV96Fx -7X9xirrCIiSX/ZhI1OPblaaldXqybevexeQ7G9BGLH6dVk0H1fBMjZGT3mj04Nqe -29HUoAESKEepROSpqMiPC/d6aP726KFAf5Z8QkEJzmYJuiTrdwOyfghscd1qYDIq -FkI3yMrpgwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUgSgqGPkSBu/fmuWrEBlgCfMrtQIwEAYJKwYBBAGCNxUBBAMCAQAw -DQYJKoZIhvcNAQEFBQADggEBAHVqSoKEYHirW3+purLYKTC/lrGw0eJ4wMsVtaWd -yCeNhu2e3EgsEMVcCSIP5mK65xhFkS3zIaZX5XqnjyINgzjs51l9CX29xQoR7MTK -bzLm/fqwweJHM/s9ZLqRoffHuKsZyGe/f832ogGNsfpmYDBr6GjBHQfiCxTjd+WR -Xbj/lQ1dG/qV3+m8MqAWm+apetrLicTwCtO1m+2xETE4hxm8KtqcVFrsHlJo5U1O -DG6F8yXDUgtIuauIo0neXtbwEUGNTRH9d6Ki0rNpWgdgGDPJn3dBJy+6lSckZv7C -+q5JAsr90RxhOLzzBfaUXh0zmsqVmWGVRs3xs4NmqyVEqGA= ------END CERTIFICATE----- diff --git a/docker_build/certs/rer_rootcat01.crt b/docker_build/certs/rer_rootcat01.crt deleted file mode 100644 index 06ac05a..0000000 --- a/docker_build/certs/rer_rootcat01.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIQbYmupMHd/rRI3jvXBQnGaDANBgkqhkiG9w0BAQsFADAr -MSkwJwYDVQQDEyBSZWdpb25lIEVtaWxpYS1Sb21hZ25hIFJPT1QgQ0EwMTAeFw0x -NzA1MDMxMDMxMzhaFw00MjA1MDMxMDQxMzdaMCsxKTAnBgNVBAMTIFJlZ2lvbmUg -RW1pbGlhLVJvbWFnbmEgUk9PVCBDQTAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAvk9am77weaKgg42NzOhgz50ghK50msb4cZzRjZD1mLIkeGn/tb2K -14ouYZoVhLIdOC3omCU5mLzTURsYV15N2AiXwxFcDf42GJr19CVBihvNYkrt9KLe -tZt/55wBeVcUlOKO+VY0PwbBPOEqebTEJgUkDBi9ibpMCMBZIq7bc1FYhMaEE45u -4KYzYWOsrQkLMDcOvgTgs7lcDV6NAjCnAX6ELY8IZsISVnF37fI6uQHKgehtpAiR -6iXQwJCuXBpg3omADbL+QDAunZ3tW01AQGDG6JnHm1fZfr8E6tT4e4ISXNPHqaRy -Ll/UiZQXaL2YG+7miinYveHav5OUgysx5r8Z9a/P2LbLpa/NLTmmN0ZZUYYN4BP8 -D4qk3wh3yDgesPvCD/k2LGwOJMfQbtlpLe7O4oqMrV5SwHXtw2vO3OeLBgiGEqaC -dYYv3Po/8DJrzeqHvf0iL1MKGvzfX1swLIuWCf0W71a0KGKh3dO5rmYfxxnfl7k3 -Vl/HEfKO6e4aeEo7i9iKAoqsUtDOLMh9BLtobcfSxxFFh+/WyNaxIcnKaEt9+18R -XYVlcjVLZB6RmnqTG2OQ1p7Ybkgcg+LA9QuD2x4BWjkIc9CeeaUJ/HIJ/qGSt74E -iLmlKU5ouvhMUa7OqCGbbuVUgbp02pKXOyanb+g7h4ckwGu5NV3c7GMCAwEAAaOB -6TCB5jALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUXc7i -WhQLYuA4E8MkC+NTZhTKNtswRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NlcnRh -dXRoLmVudGUucmVnaW9uZS5lbXIuaXQvUkVSUm9vdENBMDEuY3JsMBAGCSsGAQQB -gjcVAQQDAgEAME8GCCsGAQUFBwEBBEMwQTA/BggrBgEFBQcwAoYzaHR0cDovL2Nl -cnRhdXRoLmVudGUucmVnaW9uZS5lbXIuaXQvUkVSUm9vdENBMDEuY2VyMA0GCSqG -SIb3DQEBCwUAA4ICAQCgJx95fgRaLtofYXI7KI3IGxTLdkHUP9RA22zy27oUzYDM -cLCgq4njqbPv2akadMV/kdScTsIrpGVDJrYyTYMafR2hFpHIX0NBaqf0QUu7nn6v -bNjtG2XQd/6t8MdL8O/p7ThiSdmgEToX5lMDGGTbDPFiV0Uh8kbUvmxY3kOI1BDJ -+k6Rp1lzYZnGIIxFB0dp7GqfhY/wNkjuU3XSloBmAC357mrpUiu1hDDXddzF2wYa -QvBbRpie7ApINL4UB8803bPrxGwYmH9YNAgV+XspZaFoGi7UkJSwFN4LZl2OQQ8U -El2KGehnkXEonn3aE5dz7aORWZa1VkSOAzYKptO7LsaeJ95xNco3QrTDmijL+UU7 -GplqojjVZOYO+6SIJwSCUNDD+YTwEf4z9YL3pbMD/U0qKGY+62jU/tK9cIWyXPAE -WS568FGaHqbT67Pyy1mvvl583DtoQ9pSw3P5QY6aYfR7dRHfcySMi4VVoJ/iaZ+S -LX+LWkiatCFoIt7H9KXQWXmjmq0V0eijXvLitZfvJ389sSRvUAM5cbVvdre/+KT5 -3qyG0Ms0gwq9hFSli6irN6mYVTho5cNyYb3NhU3Bhg88Hk3p028pAvTu5xoqpRmD -btvOyBxXvaBh8nT5vrXEKUWu9PpD7Qgwi7Uj4MCOOZQS9SgVstgRVy7Hq7eT4A== ------END CERTIFICATE----- diff --git a/pom.xml b/pom.xml index 8b0b0b5..9b00f07 100644 --- a/pom.xml +++ b/pom.xml @@ -2,15 +2,16 @@ 4.0.0 verifica-firma-eidas - 1.16.1-SNAPSHOT + 1.22.1 ${packaging.type} Verifica Firma EIDAS Progetto per effettuare firme e validazioni con librerie DSS (EIDAS) + https://nexus.ente.regione.emr.it/repository/parer-site/verifica-firma-eidas/${project.version}/ it.eng.parer parer-pom - 4.2.0 + 5.2.1 @@ -43,24 +44,17 @@ - scm:git:https://github.com/RegioneER/parer-verifica-firma-eidas.git - HEAD + scm:git:git@gitlab.ente.regione.emr.it:parer/okd/verifica-firma-eidas.git + verifica-firma-eidas-1.22.1 - - github - https://maven.pkg.github.com/RegioneER/parer-verifica-firma-eidas - + + site + dav:https://nexus.ente.regione.emr.it/repository/parer-site/verifica-firma-eidas/${project.version} + - - - github - https://maven.pkg.github.com/RegioneER/parer-framework-parerpom - - - diff --git a/pom.xml.github b/pom.xml.github new file mode 100644 index 0000000..8b0b0b5 --- /dev/null +++ b/pom.xml.github @@ -0,0 +1,694 @@ + + + 4.0.0 + verifica-firma-eidas + 1.16.1-SNAPSHOT + ${packaging.type} + Verifica Firma EIDAS + Progetto per effettuare firme e validazioni con librerie DSS (EIDAS) + + + it.eng.parer + parer-pom + 4.2.0 + + + + UTF-8 + UTF-8 + + true + + false + + 5.13 + 3.1.7 + 2.1.0 + 7.2 + 2.8.0 + 4.0.0 + 5.2.2 + 2.3.1 + 4.6.1 + 1.16.0 + 3.6.4 + 1.13.2 + 11.5.0 + 0.0.5 + 6.4.0 + 2.7 + + 1.9.0 + it.eng.parer.eidas.web.VerificaFirmaEidasApplication + + + + scm:git:https://github.com/RegioneER/parer-verifica-firma-eidas.git + HEAD + + + + + github + https://maven.pkg.github.com/RegioneER/parer-verifica-firma-eidas + + + + + + github + https://maven.pkg.github.com/RegioneER/parer-framework-parerpom + + + + + + + + eu.europa.ec.joinup.sd-dss + sd-dss + ${dss.version} + pom + import + + + it.eng.parer + verificafirma-eidas-beans + ${verificafirma-eidas-beans.version} + + + org.springframework.boot + spring-boot-dependencies + ${springboot.version} + pom + import + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc-openapi-starter-webmvc-ui.version} + + + org.apache.tika + tika-core + ${tika.version} + + + org.apache.tika + tika-parsers-standard-package + ${tika.version} + + + org.bouncycastle + bcprov-jdk18on + + + org.bouncycastle + bcmail-jdk18on + + + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder.version} + + + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind-api.version} + + + org.apache.httpcomponents.core5 + httpcore5 + ${httpcore5.version} + + + + + + + + + + eu.europa.ec.joinup.sd-dss + dss-document + + + eu.europa.ec.joinup.sd-dss + dss-cades + + + eu.europa.ec.joinup.sd-dss + dss-xades + + + eu.europa.ec.joinup.sd-dss + dss-utils-apache-commons + + + eu.europa.ec.joinup.sd-dss + dss-pades + + + eu.europa.ec.joinup.sd-dss + dss-pades-pdfbox + + + commons-logging + commons-logging + + + + + eu.europa.ec.joinup.sd-dss + dss-crl-parser-x509crl + + + eu.europa.ec.joinup.sd-dss + dss-token + compile + + + eu.europa.ec.joinup.sd-dss + dss-service + + + eu.europa.ec.joinup.sd-dss + dss-model + + + eu.europa.ec.joinup.sd-dss + dss-validation-dto + + + eu.europa.ec.joinup.sd-dss + dss-signature-rest + + + commons-logging + commons-logging + + + + + + eu.europa.ec.joinup.sd-dss + dss-validation-rest + compile + + + eu.europa.ec.joinup.sd-dss + dss-server-signing-rest + compile + + + eu.europa.ec.joinup.sd-dss + dss-tsl-validation + + + eu.europa.ec.joinup.sd-dss + dss-validation-soap + compile + + + + eu.europa.ec.joinup.sd-dss + dss-spi + + + eu.europa.ec.joinup.sd-dss + dss-crl-parser-stream + + + + it.eng.parer + verificafirma-eidas-beans + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity6 + + + org.springframework.ws + spring-ws-core + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-webflux + + + io.micrometer + micrometer-registry-prometheus + runtime + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + + + + net.logstash.logback + logstash-logback-encoder + + + + + + com.h2database + h2 + + + com.oracle.database.jdbc + ojdbc11 + + + + org.apache.taglibs + taglibs-standard-jstlel + ${taglibs-standard-jstlel.version} + + + org.apache.tika + tika-core + + + org.apache.tika + tika-parsers-standard-package + + + xerces + xercesImpl + + + xml-apis + xml-apis + + + org.bouncycastle + bcmail-jdk15on + + + org.bouncycastle + bcprov-jdk15on + + + org.apache.pdfbox + pdfbox + + + commons-logging + commons-logging + + + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + + + + + + + com.google.code.findbugs + annotations + 3.0.1 + provided + + + + org.webjars + bootstrap + ${bootstrap.version} + + + + org.webjars.npm + popper.js + ${popper.js.version} + + + org.webjars + jquery + ${jquery.version} + + + org.webjars + jquery-ui + ${jquery-ui.version} + + + + org.webjars + highlightjs + ${highlightjs.version} + + + org.webjars.npm + highlightjs-badgejs + ${highlightjs-badgejs.version} + + + org.webjars + font-awesome + ${font-awesome.version} + + + org.apache.xmlgraphics + fop + ${fop.version} + + + commons-logging + commons-logging + + + xalan + xalan + + + org.apache.pdfbox + fontbox + + + xml-apis + xml-apis + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + com.vaadin.external.google + android-json + + + + + + org.junit.platform + junit-platform-suite + test + + + org.junit.platform + junit-platform-suite-api + test + + + org.junit.platform + junit-platform-engine + test + + + org.junit.platform + junit-platform-commons + test + + + org.junit.platform + junit-platform-launcher + test + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${springboot.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + + + + org.jacoco + jacoco-maven-plugin + + + + prepare-agent + + + + + report + test + + report + + + + + jacoco-check + + check + + + + + BUNDLE + + + LINE + COVEREDRATIO + 0.35 + + + + + + + + + + + pl.project13.maven + git-commit-id-plugin + + true + false + false + + + + get-the-git-infos + + revision + + + + validate-the-git-infos + + validateRevision + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + build-info + + + + ${start-class} + + + ${java.version} + UTF-8 + UTF-8 + Verifica Firma EIDAS + ${dss.version} + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + false + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + none + + + + + + + + jar + + true + + + jar + + + + fatjar + + jar + + + ${project.artifactId} + + + src/main/resources + + application-oracle.yaml + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + package + + single + + + false + eidas + + src/standalone/assembly.xml + + + + + + + + + + + war + + war + + + + + ${basedir}/../profiles/war + + **/*.yaml + + + + src/main/resources + + application-oracle.yaml + + + + + + + + + suite + + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + it.eng.parer.eidas.client.IntegrationTestSuite + + + + + + + + + diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java new file mode 100644 index 0000000..62e52a1 --- /dev/null +++ b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataHttpClient.java @@ -0,0 +1,964 @@ +/* + * Engineering Ingegneria Informatica S.p.A. + * + * Copyright (C) 2023 Regione Emilia-Romagna + *

+ * This program is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + *

+ * You should have received a copy of the GNU Affero General Public License along with this program. + * If not, see . + */ + +package it.eng.parer.eidas.core.bean; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import javax.net.ssl.HostnameVerifier; + +import org.apache.hc.client5.http.HttpRequestRetryStrategy; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.Credentials; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.SocketConfig; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.ssl.TrustStrategy; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.europa.esig.dss.model.DSSDocument; +import eu.europa.esig.dss.service.http.commons.CommonsHttpClientResponseHandler; +import eu.europa.esig.dss.service.http.commons.HostConnection; +import eu.europa.esig.dss.service.http.commons.UserCredentials; +import eu.europa.esig.dss.spi.exception.DSSExternalResourceException; +import eu.europa.esig.dss.utils.Utils; + +public class CommonsDataHttpClient implements Serializable { + + private static final long serialVersionUID = 5684332248649660441L; + + private static final Logger LOG = LoggerFactory.getLogger(CommonsDataHttpClient.class); + + /** The default connection timeout (1 minute) */ + private static final Timeout TIMEOUT_CONNECTION = toTimeoutMilliseconds(60000); + + /** The default socket timeout (1 minute) */ + private static final Timeout TIMEOUT_SOCKET = toTimeoutMilliseconds(60000); + + /** The default value of maximum connections in time (20) */ + private static final int CONNECTIONS_MAX_TOTAL = 20; + + /** The default value of maximum connections per route (2) */ + private static final int CONNECTIONS_MAX_PER_ROUTE = 2; + + /** The default connection total time to live (TTL) (1 minute) */ + private static final TimeValue CONNECTION_TIME_TO_LIVE = toTimeValueMilliseconds(60000); + + /** The timeout connection */ + private Timeout timeoutConnection = TIMEOUT_CONNECTION; + + /** The connection request timeout */ + private Timeout timeoutConnectionRequest = TIMEOUT_CONNECTION; + + /** The server response timeout */ + private Timeout timeoutResponse = TIMEOUT_CONNECTION; + + /** The timeout socket */ + private Timeout timeoutSocket = TIMEOUT_SOCKET; + + /** Connection keep alive timeout */ + private TimeValue connectionKeepAlive = CONNECTION_TIME_TO_LIVE; + + /** Maximum connections number in time */ + private int connectionsMaxTotal = CONNECTIONS_MAX_TOTAL; + + /** Maximum connections number per route */ + private int connectionsMaxPerRoute = CONNECTIONS_MAX_PER_ROUTE; + + /** The finite connection total time to live (TTL) */ + private TimeValue connectionTimeToLive = CONNECTION_TIME_TO_LIVE; + + /** Defines if the redirection is enabled */ + private boolean redirectsEnabled = true; + + /** Defines if the default system network properties shall be used */ + private boolean useSystemProperties = false; + + /** Contains rules credentials for authentication to different resources */ + private Map authenticationMap; + + /** + * Used SSL protocol + */ + private String sslProtocol; + + /** + * Keystore for SSL. + */ + private DSSDocument sslKeystore; + + /** + * Keystore's type. + */ + private String sslKeystoreType = KeyStore.getDefaultType(); + + /** + * Keystore's password. + */ + private char[] sslKeystorePassword = new char[] {}; + + /** + * Defines if the keyStore shall be loaded as a trusted material + */ + private boolean loadKeyStoreAsTrustMaterial = false; + + /** + * TrustStore for SSL. + */ + private DSSDocument sslTruststore; + + /** + * Trust store's type + */ + private String sslTruststoreType = KeyStore.getDefaultType(); + + /** + * Truststore's password. + */ + private char[] sslTruststorePassword = new char[] {}; + + /** + * The trust strategy + */ + private transient TrustStrategy trustStrategy; + + /** + * Array of supported SSL protocols + */ + private String[] supportedSSLProtocols; + + /** + * Array of supported SSL Cipher Suites + */ + private String[] supportedSSLCipherSuites; + + /** + * The hostname verifier + */ + private transient HostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(); + + /** + * The connection retry strategy + */ + private transient HttpRequestRetryStrategy retryStrategy; + + /** + * Defines whether the preemptive basic authentication should be used + */ + private boolean preemptiveAuthentication; + + /** + * Processes the HTTP dataHttpClient response and returns byte array in case of success Default: + * {@code CommonsHttpClientResponseHandler} + */ + private transient HttpClientResponseHandler httpClientResponseHandler = new CommonsHttpClientResponseHandler(); + + /** + * Standard dataHttpClient + */ + private transient CloseableHttpClient client; + + /** + * The default constructor for CommonsDataLoader. + */ + public CommonsDataHttpClient() { + // empty + } + + /** + * init method + */ + public void init() { + if (client == null) { + client = createHttpClient(); + } + } + + /** + * destroy method + * + * @throws IOException + * generic exception + */ + public void destroy() throws IOException { + if (client != null) { + client.close(); + } + } + + /** + * Gets the connection timeout. + * + * @return the value (millis) + */ + public int getTimeoutConnection() { + return timeoutConnection.toMillisecondsIntBound(); + } + + /** + * Sets the connection timeout in milliseconds. + * + * A negative value is interpreted as undefined (use system default). + * + * @param timeoutConnection + * the value (millis) + */ + public void setTimeoutConnection(final int timeoutConnection) { + this.timeoutConnection = toTimeoutMilliseconds(timeoutConnection); + } + + /** + * Gets the connection request timeout. + * + * @return the value (millis) + */ + public int getTimeoutConnectionRequest() { + return timeoutConnectionRequest.toMillisecondsIntBound(); + } + + /** + * Sets the connection request in milliseconds. + * + * A negative value is interpreted as undefined (use system default). + * + * @param timeoutConnectionRequest + * the value (millis) + */ + public void setTimeoutConnectionRequest(int timeoutConnectionRequest) { + this.timeoutConnectionRequest = toTimeoutMilliseconds(timeoutConnectionRequest); + } + + /** + * Gets the server response timeout. + * + * @return the value (millis) + */ + public int getTimeoutResponse() { + return timeoutResponse.toMillisecondsIntBound(); + } + + /** + * Sets the server response timeout in milliseconds. + * + * A negative value is interpreted as undefined (use system default). + * + * @param timeoutResponse + * the value (millis) + */ + public void setTimeoutResponse(int timeoutResponse) { + this.timeoutResponse = toTimeoutMilliseconds(timeoutResponse); + } + + /** + * Gets the socket timeout. + * + * @return the value (millis) + */ + public int getTimeoutSocket() { + return timeoutSocket.toMillisecondsIntBound(); + } + + /** + * Sets the socket timeout in milliseconds. + * + * A negative value is interpreted as undefined (use system default). + * + * @param timeoutSocket + * the value (millis) + */ + public void setTimeoutSocket(final int timeoutSocket) { + this.timeoutSocket = toTimeoutMilliseconds(timeoutSocket); + } + + /** + * Gets the connection keep alive timeout. + * + * @return the value (millis) + */ + public int getConnectionKeepAlive() { + return connectionKeepAlive.toMillisecondsIntBound(); + } + + /** + * Sets the connection keep alive timeout in milliseconds. + * + * @param connectionKeepAlive + * the value (millis) + */ + public void setConnectionKeepAlive(int connectionKeepAlive) { + this.connectionKeepAlive = toTimeValueMilliseconds(connectionKeepAlive); + } + + /** + * Gets the maximum connections number. + * + * @return the value (millis) + */ + public int getConnectionsMaxTotal() { + return connectionsMaxTotal; + } + + /** + * Sets the maximum connections number. + * + * @param connectionsMaxTotal + * maximum number of connections + */ + public void setConnectionsMaxTotal(int connectionsMaxTotal) { + this.connectionsMaxTotal = connectionsMaxTotal; + } + + /** + * Gets the maximum connections number per route. + * + * @return maximum number of connections per one route + */ + public int getConnectionsMaxPerRoute() { + return connectionsMaxPerRoute; + } + + /** + * Sets the maximum connections number per route. + * + * @param connectionsMaxPerRoute + * maximum number of connections per one route + */ + public void setConnectionsMaxPerRoute(int connectionsMaxPerRoute) { + this.connectionsMaxPerRoute = connectionsMaxPerRoute; + } + + /** + * Gets the finite connection time to live. + * + * @return connection time to live (millis) + */ + public int getConnectionTimeToLive() { + return connectionTimeToLive.toMillisecondsIntBound(); + } + + /** + * Sets the finite connection total time to live (TTL) in milliseconds. + * + * @param connectionTimeToLive + * the finite connection time to live (millis) + */ + public void setConnectionTimeToLive(int connectionTimeToLive) { + this.connectionTimeToLive = toTimeValueMilliseconds(connectionTimeToLive); + } + + /** + * Gets if redirect is enabled. + * + * @return true if http redirects are allowed + */ + public boolean isRedirectsEnabled() { + return redirectsEnabled; + } + + /** + * Sets if redirect should be enabled. + * + * @param redirectsEnabled + * true if http redirects are allowed + */ + public void setRedirectsEnabled(boolean redirectsEnabled) { + this.redirectsEnabled = redirectsEnabled; + } + + /** + * Gets if the default system network properties shall be used + * + * @return TRUE if the default system network properties shall be used, FALSE otherwise + */ + public boolean isUseSystemProperties() { + return useSystemProperties; + } + + /** + * Sets if the default system network properties shall be used + * + * Default: FALSE (system properties are not used) + * + * NOTE: all other configured property may override the default behavior! + * + * @param useSystemProperties + * if the default system network properties shall be used + */ + public void setUseSystemProperties(boolean useSystemProperties) { + this.useSystemProperties = useSystemProperties; + } + + /** + * This method sets the SSL protocol to be used + * + * @param sslProtocol + * the ssl protocol to be used + */ + public void setSslProtocol(String sslProtocol) { + this.sslProtocol = sslProtocol; + } + + /** + * Sets the SSL KeyStore + * + * @param sslKeyStore + * {@link DSSDocument} + */ + public void setSslKeystore(DSSDocument sslKeyStore) { + this.sslKeystore = sslKeyStore; + } + + /** + * Sets if the KeyStore shall be considered as a trust material (used for SSL connection) + * + * @param loadKeyStoreAsTrustMaterial + * if the KeyStore shall be considered as a trust material + */ + public void setKeyStoreAsTrustMaterial(boolean loadKeyStoreAsTrustMaterial) { + this.loadKeyStoreAsTrustMaterial = loadKeyStoreAsTrustMaterial; + } + + /** + * Sets the SSL KeyStore type + * + * @param sslKeystoreType + * {@link String} + */ + public void setSslKeystoreType(String sslKeystoreType) { + this.sslKeystoreType = sslKeystoreType; + } + + /** + * Sets the KeyStore password. Please note that the password shall be the same for the keystore and the extraction + * of a corresponding key. + * + * @param sslKeystorePassword + * char array representing the password + */ + public void setSslKeystorePassword(char[] sslKeystorePassword) { + this.sslKeystorePassword = sslKeystorePassword; + } + + /** + * Sets the SSL trust store + * + * NOTE: different from KeyStore! + * + * @param sslTrustStore + * {@link DSSDocument} + */ + public void setSslTruststore(DSSDocument sslTrustStore) { + this.sslTruststore = sslTrustStore; + } + + /** + * Sets the password for SSL truststore + * + * @param sslTruststorePassword + * char array representing a password string + */ + public void setSslTruststorePassword(char[] sslTruststorePassword) { + this.sslTruststorePassword = sslTruststorePassword; + } + + /** + * Sets the SSL TrustStore type + * + * @param sslTruststoreType + * {@link String} + */ + public void setSslTruststoreType(String sslTruststoreType) { + this.sslTruststoreType = sslTruststoreType; + } + + /** + * Returns the current instance of the authentication map + * + * @return a map between {@link HostConnection} and {@link UserCredentials} + */ + public Map getAuthenticationMap() { + if (authenticationMap == null) { + authenticationMap = new HashMap<>(); + } + return authenticationMap; + } + + /** + * Sets the authentication map + * + * NOTE: this method overrides the current instance of {@code authenticationMap} + * + * @param authenticationMap + * a map between {@link HostConnection} and {@link UserCredentials} + */ + public void setAuthenticationMap(Map authenticationMap) { + this.authenticationMap = authenticationMap; + } + + /** + * Adds authentication credentials to the existing {@code authenticationMap} + * + * @param hostConnection + * host connection details + * @param userCredentials + * user login credentials + * + * @return this (for fluent addAuthentication) + */ + public CommonsDataHttpClient addAuthentication(HostConnection hostConnection, UserCredentials userCredentials) { + Map authenticationMap = getAuthenticationMap(); + authenticationMap.put(hostConnection, userCredentials); + return this; + } + + /** + * Sets whether the preemptive authentication should be used. When set to TRUE, the dataHttpClient sends + * authentication details (i.e. user credentials) within the initial request to the remote host, instead of sending + * the credentials only after a request from the host. Please note that the preemptive authentication should not be + * used over an insecure connection. Default : FALSE (preemptive authentication is not used) + * + * @param preemptiveAuthentication + * whether the preemptive authentication should be used + */ + public void setPreemptiveAuthentication(boolean preemptiveAuthentication) { + this.preemptiveAuthentication = preemptiveAuthentication; + } + + /** + * Adds authentication credentials to the existing {@code authenticationMap} + * + * @param host + * host + * @param port + * port + * @param scheme + * scheme + * @param login + * login + * @param password + * password + * + * @return this (for fluent addAuthentication) + */ + public CommonsDataHttpClient addAuthentication(final String host, final int port, final String scheme, + final String login, final char[] password) { + final HostConnection hostConnection = new HostConnection(host, port, scheme); + final UserCredentials userCredentials = new UserCredentials(login, password); + return addAuthentication(hostConnection, userCredentials); + } + + /** + * Sets a custom retry strategy + * + * @param retryStrategy + * {@link HttpRequestRetryStrategy} + */ + public void setRetryStrategy(final HttpRequestRetryStrategy retryStrategy) { + this.retryStrategy = retryStrategy; + } + + /** + * Gets supported SSL protocols + * + * @return an array if {@link String}s + */ + public String[] getSupportedSSLProtocols() { + return supportedSSLProtocols; + } + + /** + * Sets supported SSL protocols + * + * @param supportedSSLProtocols + * an array if {@link String}s + */ + public void setSupportedSSLProtocols(String[] supportedSSLProtocols) { + this.supportedSSLProtocols = supportedSSLProtocols; + } + + /** + * Gets supported SSL Cipher Suites + * + * @return an array if {@link String}s + */ + public String[] getSupportedSSLCipherSuites() { + return supportedSSLCipherSuites; + } + + /** + * Sets supported SSL Cipher Suites + * + * @param supportedSSLCipherSuites + * an array if {@link String}s + */ + public void setSupportedSSLCipherSuites(String[] supportedSSLCipherSuites) { + this.supportedSSLCipherSuites = supportedSSLCipherSuites; + } + + /** + * Gets the hostname verifier + * + * @return {@link HostnameVerifier} + */ + public HostnameVerifier getHostnameVerifier() { + return hostnameVerifier; + } + + /** + * Sets a custom {@code HostnameVerifier} + * + * @param hostnameVerifier + * {@link HostnameVerifier} + */ + public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { + this.hostnameVerifier = hostnameVerifier; + } + + /** + * Gets the TrustStrategy + * + * @return {@link TrustStrategy} + */ + public TrustStrategy getTrustStrategy() { + return trustStrategy; + } + + /** + * Sets the {@code TrustStrategy} + * + * @param trustStrategy + * {@link TrustStrategy} + */ + public void setTrustStrategy(TrustStrategy trustStrategy) { + this.trustStrategy = trustStrategy; + } + + /** + * Returns the {@code HttpClientResponseHandler} response handler + * + * @return {@link HttpClientResponseHandler} + */ + public HttpClientResponseHandler getHttpClientResponseHandler() { + return httpClientResponseHandler; + } + + /** + * Sets the {@code HttpClientResponseHandler} response handler performing a processing of an HTTP + * dataHttpClient response and returns a byte array in case of success. + * + * @param httpClientResponseHandler + * {@link HttpClientResponseHandler} + */ + public void setHttpClientResponseHandler(HttpClientResponseHandler httpClientResponseHandler) { + Objects.requireNonNull(httpClientResponseHandler, "HttpClientResponseHandler cannot be null!"); + this.httpClientResponseHandler = httpClientResponseHandler; + } + + /** + * Gets the {@code HttpHost} + * + * @param httpRequest + * {@link HttpUriRequest} + * + * @return {@link HttpHost} + */ + protected HttpHost getHttpHost(final HttpUriRequest httpRequest) { + try { + final URI uri = httpRequest.getUri(); + return new HttpHost(uri.getScheme(), uri.getHost(), uri.getPort()); + } catch (URISyntaxException e) { + throw new DSSExternalResourceException(String.format("Invalid URI : %s", e.getMessage()), e); + } + } + + /** + * Gets the {@code HttpContext} + * + * @param httpHost + * {@link HttpHost} + * + * @return {@link HttpContext} + */ + protected HttpContext getHttpContext(HttpHost httpHost) { + HttpClientContext localContext = HttpClientContext.create(); + localContext = configurePreemptiveAuthentication(localContext, httpHost); + return localContext; + } + + /** + * This method is used to configure preemptive authentication process for {@code HttpClientContext}, when required + * + * @param localContext + * {@link HttpClientContext} + * @param httpHost + * {@link HttpHost} + * + * @return {@link HttpClientContext} + */ + protected HttpClientContext configurePreemptiveAuthentication(HttpClientContext localContext, HttpHost httpHost) { + if (preemptiveAuthentication && Utils.isMapNotEmpty(getAuthenticationMap())) { + Credentials credentials = getCredentialsProvider().getCredentials(new AuthScope(httpHost), localContext); + BasicScheme basicScheme = new BasicScheme(); + basicScheme.initPreemptive(credentials); + localContext.resetAuthExchange(httpHost, basicScheme); + } + return localContext; + } + + /** + * Closes all the parameters quietly + * + * @param httpRequest + * {@link HttpUriRequestBase} + * @param client + * {@link CloseableHttpClient} + */ + protected void closeQuietly(HttpUriRequestBase httpRequest, CloseableHttpClient client) { + try { + if (httpRequest != null) { + httpRequest.cancel(); + } + } finally { + Utils.closeQuietly(client); + } + } + + private HttpClientConnectionManager getConnectionManager() { + final PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(getConnectionSocketFactoryHttps()).setDefaultSocketConfig(getSocketConfig()) + .setMaxConnTotal(getConnectionsMaxTotal()).setMaxConnPerRoute(getConnectionsMaxPerRoute()); + + final ConnectionConfig.Builder connectionConfigBuilder = ConnectionConfig.custom() + .setConnectTimeout(timeoutConnection).setTimeToLive(connectionTimeToLive); + + final PoolingHttpClientConnectionManager connectionManager = builder.build(); + connectionManager.setDefaultConnectionConfig(connectionConfigBuilder.build()); + + LOG.atDebug().log("PoolingHttpClientConnectionManager: max total: {}", connectionManager.getMaxTotal()); + LOG.atDebug().log("PoolingHttpClientConnectionManager: max per route: {}", + connectionManager.getDefaultMaxPerRoute()); + + return connectionManager; + } + + private SocketConfig getSocketConfig() { + SocketConfig.Builder socketConfigBuilder = SocketConfig.custom(); + socketConfigBuilder.setSoTimeout(timeoutSocket); + return socketConfigBuilder.build(); + } + + private SSLConnectionSocketFactory getConnectionSocketFactoryHttps() { + try { + SSLContextBuilder sslContextBuilder = SSLContextBuilder.create(); + sslContextBuilder.setProtocol(sslProtocol); + + final TrustStrategy trustStrategy = getTrustStrategy(); + if (trustStrategy != null) { + LOG.atDebug().log("Set the TrustStrategy"); + sslContextBuilder.loadTrustMaterial(null, trustStrategy); + } + + final KeyStore sslTrustStore = getSSLTrustStore(); + if (sslTrustStore != null) { + LOG.atDebug().log("Set the SSL trust store as trust materials"); + sslContextBuilder.loadTrustMaterial(sslTrustStore, trustStrategy); + } + + final KeyStore sslKeystore = getSSLKeyStore(); + if (sslKeystore != null) { + LOG.atDebug().log("Set the SSL keystore as key materials"); + sslContextBuilder.loadKeyMaterial(sslKeystore, sslKeystorePassword); + if (loadKeyStoreAsTrustMaterial) { + LOG.atDebug().log("Set the SSL keystore as trust materials"); + sslContextBuilder.loadTrustMaterial(sslKeystore, trustStrategy); + } + } + + SSLConnectionSocketFactoryBuilder sslConnectionSocketFactoryBuilder = new SSLConnectionSocketFactoryBuilder(); + return sslConnectionSocketFactoryBuilder.setSslContext(sslContextBuilder.build()) + .setTlsVersions(getSupportedSSLProtocols()).setCiphers(getSupportedSSLCipherSuites()) + .setHostnameVerifier(getHostnameVerifier()).build(); + + } catch (final Exception e) { + throw new IllegalArgumentException("Unable to configure the SSLContext/SSLConnectionSocketFactory", e); + } + } + + /** + * Gets the SSL KeyStore + * + * @return {@link KeyStore} + * + * @throws IOException + * if IOException occurs + * @throws GeneralSecurityException + * if GeneralSecurityException occurs + */ + protected KeyStore getSSLKeyStore() throws IOException, GeneralSecurityException { + return loadKeyStore(sslKeystore, sslKeystoreType, sslKeystorePassword); + } + + /** + * Gets the SSL Trusted KeyStore + * + * @return {@link KeyStore} + * + * @throws IOException + * if IOException occurs + * @throws GeneralSecurityException + * if GeneralSecurityException occurs + */ + protected KeyStore getSSLTrustStore() throws IOException, GeneralSecurityException { + return loadKeyStore(sslTruststore, sslTruststoreType, sslTruststorePassword); + } + + private KeyStore loadKeyStore(DSSDocument store, String type, char[] password) + throws IOException, GeneralSecurityException { + if (store != null) { + try (InputStream is = store.openStream()) { + KeyStore ks = KeyStore.getInstance(type); + ks.load(is, password); + return ks; + } + } else { + return null; + } + } + + /** + * Gets the {@code HttpClientBuilder} + * + * + * @return {@link HttpClientBuilder} + */ + protected HttpClientBuilder getHttpClientBuilder() { + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + + if (useSystemProperties) { + httpClientBuilder.useSystemProperties(); + } + + httpClientBuilder = configCredentials(httpClientBuilder); + + final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() + .setConnectionRequestTimeout(timeoutConnectionRequest).setResponseTimeout(timeoutResponse) + .setConnectionKeepAlive(connectionKeepAlive).setRedirectsEnabled(redirectsEnabled); + + httpClientBuilder.setConnectionManager(getConnectionManager()) + .setDefaultRequestConfig(requestConfigBuilder.build()).setRetryStrategy(retryStrategy); + + return httpClientBuilder; + } + + /** + * Create the HTTP dataHttpClient + * + * @return {@link CloseableHttpClient} + */ + protected CloseableHttpClient createHttpClient() { + return getHttpClientBuilder().build(); + } + + /** + * Defines the Credentials + * + * @param httpClientBuilder + * {@link HttpClientBuilder} + * @param url + * {@link String} + * + * @return {@link HttpClientBuilder} + */ + private HttpClientBuilder configCredentials(HttpClientBuilder httpClientBuilder) { + final BasicCredentialsProvider credentialsProvider = getCredentialsProvider(); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + return httpClientBuilder; + } + + /** + * Builds and returns a {@code BasicCredentialsProvider} configured with {@code authenticationMap} + * + * @return {@link BasicCredentialsProvider} + */ + protected BasicCredentialsProvider getCredentialsProvider() { + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + for (final Map.Entry entry : getAuthenticationMap().entrySet()) { + final HostConnection hostConnection = entry.getKey(); + final UserCredentials userCredentials = entry.getValue(); + final AuthScope authscope = new AuthScope(hostConnection.getProtocol(), hostConnection.getHost(), + hostConnection.getPort(), hostConnection.getRealm(), hostConnection.getScheme()); + + final UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials( + userCredentials.getUsername(), userCredentials.getPassword()); + credentialsProvider.setCredentials(authscope, usernamePasswordCredentials); + } + return credentialsProvider; + } + + private static Timeout toTimeoutMilliseconds(int millis) { + if (millis < 0) { + LOG.info("A negative timeout has been provided. Use system default."); + return null; + } + return Timeout.ofMilliseconds(millis); + } + + private static TimeValue toTimeValueMilliseconds(int millis) { + return TimeValue.ofMilliseconds(millis); + } + + /** + * Standard HTTP Apache Client + * + * @return dataHttpClient + */ + public CloseableHttpClient getHttpClient() { + return client; + } + +} diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java index 818bcb3..e51b55c 100644 --- a/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java +++ b/src/main/java/it/eng/parer/eidas/core/bean/CommonsDataLoaderExt.java @@ -17,14 +17,27 @@ package it.eng.parer.eidas.core.bean; +import java.io.IOException; + +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import eu.europa.esig.dss.service.http.commons.CommonsDataLoader; -import it.eng.parer.eidas.core.util.Constants; public class CommonsDataLoaderExt extends CommonsDataLoader implements CustomDataLoaderExt { private static final long serialVersionUID = -272512490031055464L; - private String ldapTimeoutConnection = Constants.TIMEOUT_LDAP_CONNECTION; + private static final Logger LOG = LoggerFactory.getLogger(CommonsDataLoaderExt.class); + + // ** LDAP + + private String ldapTimeoutConnection = TIMEOUT_LDAP_CONNECTION; + + /** The Commons HTTP dataHttpClient */ + private CommonsDataHttpClient dataHttpClient; /** * Sovrascritto il metodo del padre in quanto non implementava un TIMEOUT nelle chiamate LDAP @@ -51,4 +64,36 @@ public void setLdapTimeoutConnection(String ldapTimeoutConnection) { this.ldapTimeoutConnection = ldapTimeoutConnection; } + /* HTTP GET */ + @Override + protected byte[] httpGet(String url) { + return customHttpGet(url); + } + + /* HTTP POST */ + @Override + public byte[] post(String url, byte[] content) { + return customPost(url, content); + } + + @Override + public byte[] execute(CloseableHttpClient client, HttpUriRequest httpRequest) throws IOException { + return super.execute(client, httpRequest); + } + + @Override + public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient) { + this.dataHttpClient = dataHttpClient; + } + + @Override + public CommonsDataHttpClient getCommonsDataHttpClient() { + return dataHttpClient; + } + + @Override + public Logger logger() { + return LOG; + } + } diff --git a/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java index 3f59b73..e34cc51 100644 --- a/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java +++ b/src/main/java/it/eng/parer/eidas/core/bean/CustomDataLoaderExt.java @@ -17,6 +17,10 @@ package it.eng.parer.eidas.core.bean; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Hashtable; import java.util.StringTokenizer; @@ -26,13 +30,28 @@ import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.BufferedHttpEntity; +import org.apache.hc.core5.http.io.entity.InputStreamEntity; +import org.slf4j.Logger; + import eu.europa.esig.dss.model.DSSException; import eu.europa.esig.dss.service.http.commons.LdapURLUtils; +import eu.europa.esig.dss.spi.DSSUtils; import eu.europa.esig.dss.spi.exception.DSSExternalResourceException; import eu.europa.esig.dss.utils.Utils; public interface CustomDataLoaderExt { + static final String CONTENT_TYPE = "Content-Type"; + + static final String TIMEOUT_LDAP_CONNECTION = "6000"; + /** * Extendend OCSPDataLoader method, not implemented TIMEOUT on LDPA call * @@ -92,4 +111,91 @@ default byte[] customLdapGet(String urlString) { public String getLdapTimeoutConnection(); + /* CUSTOM DATA LOADING HTTP */ + + public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient); + + public CommonsDataHttpClient getCommonsDataHttpClient(); + + /* apache dataHttpClient management */ + + default byte[] customPost(String url, byte[] content) { + logger().atDebug().log("Fetching data via POST from url {}", url); + + HttpPost httpRequest = null; + // The length for the InputStreamEntity is needed, because some receivers (on + // the other side) + // need this information. + // To determine the length, we cannot read the content-stream up to the end and + // re-use it afterwards. + // This is because, it may not be possible to reset the stream (= go to position + // 0). + // So, the solution is to cache temporarily the complete content data (as we do + // not expect much here) in + // a byte-array. + try (final ByteArrayInputStream bis = new ByteArrayInputStream(content);) { + final URI uri = URI.create(Utils.trim(url)); + httpRequest = new HttpPost(uri); + + final HttpEntity httpEntity = new InputStreamEntity(bis, content.length, + toContentTypeExt(getContentType())); + final HttpEntity requestEntity = new BufferedHttpEntity(httpEntity); + httpRequest.setEntity(requestEntity); + + return execute(getCommonsDataHttpClient().getHttpClient(), httpRequest); + + } catch (IOException e) { + throw new DSSExternalResourceException( + String.format("Unable to process POST call for url [%s]. Reason : [%s]", url, e.getMessage()), e); + + } finally { + if (httpRequest != null) { + httpRequest.cancel(); + } + } + } + + default byte[] customHttpGet(String url) { + logger().atDebug().log("Fetching data via GET from url {}", url); + + HttpGet httpRequest = null; + + try { + httpRequest = customGetHttpRequest(url); + return execute(getCommonsDataHttpClient().getHttpClient(), httpRequest); + + } catch (URISyntaxException | IOException e) { + throw new DSSExternalResourceException(String.format( + "Unable to process GET call for url [%s]. Reason : [%s]", url, DSSUtils.getExceptionMessage(e)), e); + + } finally { + if (httpRequest != null) { + httpRequest.cancel(); + } + } + } + + default HttpGet customGetHttpRequest(String url) throws URISyntaxException { + final URI uri = new URI(Utils.trim(url)); + HttpGet httpRequest = new HttpGet(uri); + if (getContentType() != null) { + httpRequest.setHeader(CONTENT_TYPE, getContentType()); + } + return httpRequest; + } + + default ContentType toContentTypeExt(String contentTypeString) { + return Utils.isStringNotBlank(contentTypeString) ? ContentType.create(contentTypeString) : null; + } + + public Logger logger(); + + /* + * define standard getter & setter (inherit from {@link CommonsDataLoader}) + */ + + public byte[] execute(final CloseableHttpClient client, final HttpUriRequest httpRequest) throws IOException; + + public String getContentType(); + } diff --git a/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java b/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java index 0dee77c..10acb34 100644 --- a/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java +++ b/src/main/java/it/eng/parer/eidas/core/bean/OCSPDataLoaderExt.java @@ -17,8 +17,14 @@ package it.eng.parer.eidas.core.bean; +import java.io.IOException; + +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import eu.europa.esig.dss.service.http.commons.OCSPDataLoader; -import it.eng.parer.eidas.core.util.Constants; public class OCSPDataLoaderExt extends OCSPDataLoader implements CustomDataLoaderExt { @@ -27,7 +33,12 @@ public class OCSPDataLoaderExt extends OCSPDataLoader implements CustomDataLoade */ private static final long serialVersionUID = 2497778964600711396L; - private String ldapTimeoutConnection = Constants.TIMEOUT_LDAP_CONNECTION; + private static final Logger LOG = LoggerFactory.getLogger(OCSPDataLoaderExt.class); + + private String ldapTimeoutConnection = TIMEOUT_LDAP_CONNECTION; + + /** The Commons HTTP dataHttpClient */ + private CommonsDataHttpClient dataHttpClient; /** * Extendend OCSPDataLoader method, not implemented TIMEOUT on LDAP call @@ -55,4 +66,36 @@ public void setLdapTimeoutConnection(String ldapTimeoutConnection) { this.ldapTimeoutConnection = ldapTimeoutConnection; } + /* HTTP GET */ + @Override + protected byte[] httpGet(String url) { + return customHttpGet(url); + } + + /* HTTP POST */ + @Override + public byte[] post(String url, byte[] content) { + return customPost(url, content); + } + + @Override + public byte[] execute(CloseableHttpClient client, HttpUriRequest httpRequest) throws IOException { + return super.execute(client, httpRequest); + } + + @Override + public void setCommonsDataHttpClient(CommonsDataHttpClient dataHttpClient) { + this.dataHttpClient = dataHttpClient; + } + + @Override + public CommonsDataHttpClient getCommonsDataHttpClient() { + return dataHttpClient; + } + + @Override + public Logger logger() { + return LOG; + } + } diff --git a/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java b/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java index 6430d0f..95d024c 100644 --- a/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java +++ b/src/main/java/it/eng/parer/eidas/core/helper/EidasHelper.java @@ -37,7 +37,6 @@ import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; -import java.time.Duration; import java.util.List; import java.util.Set; @@ -47,7 +46,10 @@ import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.tika.config.TikaConfig; import org.apache.tika.detect.Detector; import org.apache.tika.io.TikaInputStream; @@ -56,23 +58,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.info.BuildProperties; import org.springframework.core.env.Environment; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; import eu.europa.esig.dss.enumerations.MimeTypeEnum; import eu.europa.esig.dss.model.DSSDocument; import eu.europa.esig.dss.spi.DSSUtils; +import it.eng.parer.eidas.core.bean.CommonsDataHttpClient; import it.eng.parer.eidas.model.EidasDataToValidateMetadata; import it.eng.parer.eidas.model.EidasRemoteDocument; import it.eng.parer.eidas.model.exception.EidasParerException; import it.eng.parer.eidas.model.exception.ParerError; -import reactor.core.publisher.Flux; -import reactor.util.retry.Retry; @Component public class EidasHelper { @@ -94,17 +91,8 @@ public class EidasHelper { @Autowired BuildProperties buildProperties; - // default 60 s - @Value("${parer.eidas.webclient.timeout:360}") - long webClientTimeout; - - // default 5 times - @Value("${parer.eidas.webclient.backoff:10}") - long webClientBackoff; - - // default 3 s - @Value("${parer.eidas.webclient.backofftime:3}") - long webClientBackoffTime; + @Autowired + CommonsDataHttpClient dataHttpClient; public String buildversion() { return env.getProperty(BUILD_VERSION); @@ -383,18 +371,12 @@ private Path readBase64EncodedFile(String prefix, InputStream is) throws IOExcep } public void getResourceFromURI(URI signedResource, Path localPath) throws IOException { - try { - // Attenzione, se al posto dell'uri viene utilizzata una stringa ci possono essere problemi di conversione - // dei - // caratteri - Flux dataBuffer = WebClient.create().get().uri(signedResource).retrieve() - .bodyToFlux(DataBuffer.class); - // scarica sul local path provando 5 volte aspettando almeno 3 secondi tra un prova e l'altra - DataBufferUtils.write(dataBuffer, localPath).timeout(Duration.ofSeconds(webClientTimeout)) - .retryWhen(Retry.backoff(webClientBackoff, Duration.ofSeconds(webClientBackoffTime))).share() - .block(); - } catch (Exception ex) { - throw new IOException("Impossibile recuperare il documento da URI", ex); + + try (ClassicHttpResponse response = dataHttpClient.getHttpClient().executeOpen(null, + new HttpGet(signedResource), null); FileOutputStream out = new FileOutputStream(localPath.toFile());) { + // + IOUtils.copyLarge(response.getEntity().getContent(), out); } } + } diff --git a/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java b/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java index 11fbd23..be1f4b9 100644 --- a/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java +++ b/src/main/java/it/eng/parer/eidas/core/service/CustomRemoteDocumentValidationImpl.java @@ -45,6 +45,11 @@ import eu.europa.esig.dss.model.DSSDocument; import eu.europa.esig.dss.model.FileDocument; import eu.europa.esig.dss.model.InMemoryDocument; +import eu.europa.esig.dss.pades.validation.PDFDocumentValidator; +import eu.europa.esig.dss.pdf.IPdfObjFactory; +import eu.europa.esig.dss.pdf.ServiceLoaderPdfObjFactory; +import eu.europa.esig.dss.pdf.modifications.DefaultPdfDifferencesFinder; +import eu.europa.esig.dss.pdf.modifications.DefaultPdfObjectModificationsFinder; import eu.europa.esig.dss.policy.ValidationPolicy; import eu.europa.esig.dss.policy.ValidationPolicyFacade; import eu.europa.esig.dss.policy.jaxb.Level; @@ -511,7 +516,7 @@ private EidasWSReportsDTOTree createRoot(DSSDocument signedDocument, Reports rep /** * Vedi issue https://gitlab.ente.regione.emr.it/parer/okd/verifica-firma-eidas/issues/7 * - * Per il momento il validation report non viene restituito al client + * Per il momento il validation report non viene restituito al dataHttpClient */ WSReportsDTO wsdto = new WSReportsDTO(reports.getDiagnosticDataJaxb(), reports.getSimpleReportJaxb(), reports.getDetailedReportJaxb()); @@ -636,6 +641,10 @@ private SignedDocumentValidator buildValidator(DSSDocument signedDocument, signedDocValidator.setIncludeSemantics(dataToValidateMetadata.isIncludeSemanticTokenValues()); // signedDocValidator.setCertificateVerifier(verifier); + + // + disablePDFComparisonsCheck(signedDocValidator); + log.atDebug().log("Signed Document Validator created class name: {}", signedDocValidator.getClass().getName()); return signedDocValidator; @@ -646,4 +655,32 @@ private SignedDocumentValidator buildValidator(DSSDocument signedDocument, } + /* + * PdfObjectModificationsFinder customization + * + * check : + * https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/doc/dss-documentation.html#DisablingPdfComparison + */ + private void disablePDFComparisonsCheck(SignedDocumentValidator signedDocValidator) { + if (signedDocValidator instanceof PDFDocumentValidator pdfDocumentValidator) { + // Create a IPdfObjFactory + IPdfObjFactory pdfObjFactory = new ServiceLoaderPdfObjFactory(); + + // Configure DefaultPdfDifferencesFinder responsible for visual document comparison + DefaultPdfDifferencesFinder pdfDifferencesFinder = new DefaultPdfDifferencesFinder(); + // NOTE: To skip the visual comparison '0' value should be set + pdfDifferencesFinder.setMaximalPagesAmountForVisualComparison(0); + pdfObjFactory.setPdfDifferencesFinder(pdfDifferencesFinder); + + // Configure DefaultPdfObjectModificationsFinder responsible for object comparison between PDF revisions + DefaultPdfObjectModificationsFinder pdfObjectModificationsFinder = new DefaultPdfObjectModificationsFinder(); + // NOTE: To skip the visual comparison '0' value should be set + pdfObjectModificationsFinder.setMaximumObjectVerificationDeepness(0); + pdfObjFactory.setPdfObjectModificationsFinder(pdfObjectModificationsFinder); + + // Set the factory to the DocumentValidator + pdfDocumentValidator.setPdfObjFactory(pdfObjFactory); + } + } + } diff --git a/src/main/java/it/eng/parer/eidas/core/service/VerificaFirmaImpl.java b/src/main/java/it/eng/parer/eidas/core/service/VerificaFirmaImpl.java index 05414aa..9586643 100644 --- a/src/main/java/it/eng/parer/eidas/core/service/VerificaFirmaImpl.java +++ b/src/main/java/it/eng/parer/eidas/core/service/VerificaFirmaImpl.java @@ -36,8 +36,8 @@ import it.eng.parer.eidas.core.helper.EidasHelper; import it.eng.parer.eidas.model.EidasDataToValidateMetadata; -import it.eng.parer.eidas.model.EidasWSReportsDTOTree; import it.eng.parer.eidas.model.EidasRemoteDocument; +import it.eng.parer.eidas.model.EidasWSReportsDTOTree; import it.eng.parer.eidas.model.exception.EidasParerException; import it.eng.parer.eidas.model.exception.ParerError; import jakarta.servlet.http.HttpServletRequest; @@ -205,12 +205,12 @@ private void elabValidateDtoExt(EidasDataToValidateMetadata dataToValidateDTO) { // set file path policyDocumentExt.setAbsolutePath(validationPolicyPath.toAbsolutePath().toString()); } - } catch (IOException ex) { + } catch (IOException ioex) { // clean from files helper.deleteTmpDocExtFiles(dataToValidateDTO.getRemoteSignedDocument(), dataToValidateDTO.getRemoteOriginalDocuments(), dataToValidateDTO.getPolicyExt()); - throw new EidasParerException(dataToValidateDTO, ex).withCode(ParerError.ErrorCode.IO_ERROR) + throw new EidasParerException(dataToValidateDTO, ioex).withCode(ParerError.ErrorCode.IO_ERROR) .withMessage("Errore durante elaborazione richiesta"); } } diff --git a/src/main/java/it/eng/parer/eidas/core/util/Constants.java b/src/main/java/it/eng/parer/eidas/core/util/Constants.java index f6308b5..d1f1e21 100644 --- a/src/main/java/it/eng/parer/eidas/core/util/Constants.java +++ b/src/main/java/it/eng/parer/eidas/core/util/Constants.java @@ -37,13 +37,11 @@ private Constants() { public static final String BUILD_TIME = "git.commit.time"; public static final String DSS_VERSION = "dss.version"; - /* default configuration */ - public static final String TIMEOUT_LDAP_CONNECTION = "6000"; - public static final String TMP_FILE_SUFFIX = "-eidasvf.tmp"; /* default error message on advice handler */ public static final String STD_MSG_APP_ERROR = "Errore applicativo"; + public static final String STD_MSG_APP_WARN = "Avviso errore"; public static final String STD_MSG_GENERIC_ERROR = "Errore generico"; public static final String STD_MSG_VALIDATION_ERROR = "Chiamata non valida"; diff --git a/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java b/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java index 467a38a..a5436d3 100644 --- a/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java +++ b/src/main/java/it/eng/parer/eidas/web/config/AdviceHandler.java @@ -18,8 +18,10 @@ package it.eng.parer.eidas.web.config; import static it.eng.parer.eidas.core.util.Constants.STD_MSG_APP_ERROR; +import static it.eng.parer.eidas.core.util.Constants.STD_MSG_APP_WARN; import static it.eng.parer.eidas.core.util.Constants.STD_MSG_GENERIC_ERROR; import static it.eng.parer.eidas.core.util.Constants.STD_MSG_VALIDATION_ERROR; +import static it.eng.parer.eidas.model.exception.ParerError.ErrorCode.EIDAS_ERROR; import java.util.Arrays; @@ -54,16 +56,22 @@ public class AdviceHandler { /* * Aggiunto log al fine di loggare i casi di generiche eccezioni ossia generate dopo l'esecuzione del servizio di - * verifica firma (o prima quando si valuta la risposta del client), ma che comunque in generale non sono gestite - * (EidasParerException) all'interno dell'implementazione dell'endpoint. + * verifica firma (o prima quando si valuta la risposta del dataHttpClient), ma che comunque in generale non sono + * gestite (EidasParerException) all'interno dell'implementazione dell'endpoint. */ private static final Logger log = LoggerFactory.getLogger(AdviceHandler.class); @ExceptionHandler(EidasParerException.class) public final ResponseEntity handleEidasParerException(EidasParerException ex, WebRequest request) { - // log error - log.atError().log(STD_MSG_APP_ERROR, ex); + // log code based + if (ex.getCode().equals(EIDAS_ERROR)) { + // log warn + log.atWarn().log(STD_MSG_APP_WARN, ex); + } else { + // log error + log.atError().log(STD_MSG_APP_ERROR, ex); + } HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return new ResponseEntity<>(RestUtil.buildParerResponseEntity(ex, request), headers, diff --git a/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java b/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java index a178a4d..184963d 100644 --- a/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java +++ b/src/main/java/it/eng/parer/eidas/web/config/AppConfiguration.java @@ -91,7 +91,7 @@ public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter( mapper); - // Aggiungo i media type text/plain per supportare client come jmeter + // Aggiungo i media type text/plain per supportare dataHttpClient come jmeter List supportedMediaTypes = new ArrayList<>( mappingJackson2HttpMessageConverter.getSupportedMediaTypes()); supportedMediaTypes.add(new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8)); diff --git a/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java b/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java index ab48aa5..28220ce 100644 --- a/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java +++ b/src/main/java/it/eng/parer/eidas/web/config/DSSBeanConfig.java @@ -20,9 +20,11 @@ import java.io.File; import java.io.IOException; import java.security.KeyStore.PasswordProtection; +import java.sql.SQLException; import javax.sql.DataSource; +import org.apache.commons.lang3.StringUtils; import org.apache.hc.client5.http.ssl.TrustAllStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,6 +63,8 @@ import eu.europa.esig.dss.spi.x509.KeyStoreCertificateSource; import eu.europa.esig.dss.spi.x509.aia.AIASource; import eu.europa.esig.dss.spi.x509.aia.DefaultAIASource; +import eu.europa.esig.dss.spi.x509.revocation.crl.CRLSource; +import eu.europa.esig.dss.spi.x509.revocation.ocsp.OCSPSource; import eu.europa.esig.dss.spi.x509.tsp.TSPSource; import eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection; import eu.europa.esig.dss.tsl.function.OfficialJournalSchemeInformationURI; @@ -74,6 +78,7 @@ import eu.europa.esig.dss.ws.signature.common.RemoteTrustedListSignatureServiceImpl; import eu.europa.esig.dss.ws.validation.common.RemoteDocumentValidationService; import eu.europa.esig.dss.xades.signature.XAdESService; +import it.eng.parer.eidas.core.bean.CommonsDataHttpClient; import it.eng.parer.eidas.core.bean.CommonsDataLoaderExt; import it.eng.parer.eidas.core.bean.OCSPDataLoaderExt; import it.eng.parer.eidas.core.service.CustomRemoteDocumentValidationImpl; @@ -122,7 +127,8 @@ public class DSSBeanConfig { @Value("${current.oj.url}") private String currentOjUrl; - @Autowired + /* custom DataSource possibile null in case DB is disable by configuration */ + @Autowired(required = false) private DataSource dataSource; @Autowired(required = false) @@ -144,38 +150,66 @@ public class DSSBeanConfig { @Value("${cache.ocsp.max.next.update:0}") private long ocspMaxNextUpdate; + /* from 5.13 */ + @Value("${cache.expiration:0}") + private long cacheExpiration; + /* custom */ - @Value("${revoke.data.loading.strategy.crl-first.enabled:true}") + @Value("${revoke.data.loading.strategy.crl-first.enabled:false}") private boolean revokeDataLoadingStratCrlFirst; @Value("${revoke.removeExpired.enabled:true}") private boolean revokeRemoveExpired; - @Value("${dataloader.timeoutconnection:60000}") + /* in ms (5m) */ + @Value("${dataloader.timeoutconnection:300000}") private int timeoutConnection; - @Value("${dataloader.timeoutsocket:60000}") + /* in ms (5m) */ + @Value("${dataloader.timeoutsocket:300000}") private int timeoutSocket; - @Value("${dataloader.connectionsmaxtotal:20}") + @Value("${dataloader.connectionsmaxtotal:40}") private int connectionsMaxTotal; - @Value("${dataloader.connectionsmaxperroute:2}") + @Value("${dataloader.connectionsmaxperroute:4}") private int connectionsMaxPerRoute; - @Value("${dataloader.ldaptimeoutconnection:30000}") + /* in ms (5m) */ + @Value("${dataloader.connectiontimetolive:300000}") + private int connectionTimeToLive; + + /* in ms (5m) */ + @Value("${dataloader.ldaptimeoutconnection:300000}") private String ldapTimeoutConnection; + @Value("${cache.enabled:true}") + private boolean cacheEnabled; + + // default empty + @Value("${cache.file.path:}") + private String cacheFilePath; + + /** CUSTOM HTTP CLIENT ! **/ + @Bean(initMethod = "init", destroyMethod = "destroy") + public CommonsDataHttpClient dataHttpClient() { + CommonsDataHttpClient dataClient = new CommonsDataHttpClient(); + // NOTA timeout impostabile (da configurazione!) + dataClient.setTimeoutConnection(timeoutConnection); + dataClient.setConnectionsMaxTotal(connectionsMaxTotal); + dataClient.setTimeoutSocket(timeoutSocket); + // + dataClient.setConnectionsMaxPerRoute(connectionsMaxPerRoute); + dataClient.setConnectionTimeToLive(connectionTimeToLive); + // + return dataClient; + } + @Bean public CommonsDataLoaderExt dataLoader() { CommonsDataLoaderExt dataLoader = new CommonsDataLoaderExt(); + dataLoader.setCommonsDataHttpClient(dataHttpClient()); dataLoader.setProxyConfig(proxyConfig); - // NOTA timeout impostabile (da configurazione!) - dataLoader.setTimeoutConnection(timeoutConnection); - dataLoader.setConnectionsMaxTotal(connectionsMaxTotal); - dataLoader.setTimeoutSocket(timeoutSocket); - // - dataLoader.setConnectionsMaxPerRoute(connectionsMaxPerRoute); // dataLoader.setLdapTimeoutConnection(ldapTimeoutConnection); return dataLoader; @@ -184,24 +218,28 @@ public CommonsDataLoaderExt dataLoader() { @Bean public OCSPDataLoaderExt ocspDataLoader() { OCSPDataLoaderExt ocspDataLoader = new OCSPDataLoaderExt(); + ocspDataLoader.setCommonsDataHttpClient(dataHttpClient()); ocspDataLoader.setProxyConfig(proxyConfig); - // NOTA timeout impostabile (da configurazione!) - ocspDataLoader.setTimeoutConnection(timeoutConnection); - ocspDataLoader.setConnectionsMaxTotal(connectionsMaxTotal); - ocspDataLoader.setTimeoutSocket(timeoutSocket); - // - ocspDataLoader.setConnectionsMaxPerRoute(connectionsMaxPerRoute); - // ocspDataLoader.setLdapTimeoutConnection(ldapTimeoutConnection); return ocspDataLoader; } + /* from 5.13 */ @Bean public FileCacheDataLoader fileCacheDataLoader() { + FileCacheDataLoader fileCacheDataLoader = initFileCacheDataLoader(); + fileCacheDataLoader.setCacheExpirationTime(cacheExpiration * 1000); // to millis + return fileCacheDataLoader; + } + + private FileCacheDataLoader initFileCacheDataLoader() { FileCacheDataLoader fileCacheDataLoader = new FileCacheDataLoader(); fileCacheDataLoader.setDataLoader(dataLoader()); // Per default uses "java.io.tmpdir" property // fileCacheDataLoader.setFileCacheDirectory(new File("/tmp")); + if (StringUtils.isNotBlank(cacheFilePath)) { + fileCacheDataLoader.setFileCacheDirectory(new File(cacheFilePath)); + } return fileCacheDataLoader; } @@ -213,55 +251,136 @@ public OnlineCRLSource onlineCRLSource() { } /* - * destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che vengano create le tabelle ma - * non si vuole dropparle non appena il processo viene interrotto + * initMethod = "initTable" esecuzione CREATE table gestita in fase di creazione del bean gestione logica doppio + * "source" JDBC vs FILE destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che + * vengano create le tabelle ma non si vuole dropparle non appena il processo viene interrotto + * + * Visit + * https://github.com/esig/dss-demonstrations/blob/master/dss-demo-webapp/src/main/java/eu/europa/esig/dss/web/ + * config/DSSBeanConfig.java + * */ // @Bean(initMethod = "initTable", destroyMethod = "destroyTable") - @Bean(initMethod = "initTable") - public JdbcCacheCRLSource cachedCRLSource() { - JdbcCacheCRLSource jdbcCacheCRLSource = new JdbcCacheCRLSource(); - jdbcCacheCRLSource.setJdbcCacheConnector(jdbcCacheConnector()); - jdbcCacheCRLSource.setProxySource(onlineCRLSource()); - jdbcCacheCRLSource.setDefaultNextUpdateDelay(crlDefaultNextUpdate); // 0 (get new one every time) - jdbcCacheCRLSource.setMaxNextUpdateDelay(crlMaxNextUpdate); // 0 (get new one every time) - // default = true - // questo permette di mantenere il dato su DB aggiornandolo se risulta *expired* - jdbcCacheCRLSource.setRemoveExpired(revokeRemoveExpired); - return jdbcCacheCRLSource; + @Bean + public CRLSource defineCRLSource() { + if (cacheEnabled) { + if (dataSource != null) { + JdbcCacheCRLSource jdbcCacheCRLSource = new JdbcCacheCRLSource(); + jdbcCacheCRLSource.setJdbcCacheConnector(jdbcCacheConnector()); + jdbcCacheCRLSource.setProxySource(onlineCRLSource()); + jdbcCacheCRLSource.setDefaultNextUpdateDelay(crlDefaultNextUpdate); // 0 (get new one every time) + jdbcCacheCRLSource.setMaxNextUpdateDelay(crlMaxNextUpdate); // 0 (get new one every time) + // default = true + // questo permette di mantenere il dato su DB aggiornandolo se risulta *expired* + jdbcCacheCRLSource.setRemoveExpired(revokeRemoveExpired); + // create table if not exits + try { + jdbcCacheCRLSource.initTable(); + } catch (SQLException e) { + throw new DSSException("Errore inizializzazione CRL JDBC cache", e); + } + return jdbcCacheCRLSource; + } + OnlineCRLSource onlineCRLSource = onlineCRLSource(); + FileCacheDataLoader fileCacheDataLoader = initFileCacheDataLoader(); + fileCacheDataLoader.setCacheExpirationTime(crlMaxNextUpdate * 1000); // to millis + onlineCRLSource.setDataLoader(fileCacheDataLoader); + return onlineCRLSource; + } else { + return onlineCRLSource(); + } + } @Bean - public OnlineOCSPSource onlineOcspSource() { + public OnlineOCSPSource onlineOCSPSource() { OnlineOCSPSource onlineOCSPSource = new OnlineOCSPSource(); onlineOCSPSource.setDataLoader(ocspDataLoader()); return onlineOCSPSource; } /* - * destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che vengano create le tabelle ma - * non si vuole dropparle non appena il processo viene interrotto + * initMethod = "initTable" esecuzione CREATE table gestita in fase di creazione del bean gestione logica doppio + * "source" JDBC vs FILE destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che + * vengano create le tabelle ma non si vuole dropparle non appena il processo viene interrotto + * + * Visit + * https://github.com/esig/dss-demonstrations/blob/master/dss-demo-webapp/src/main/java/eu/europa/esig/dss/web/ + * config/DSSBeanConfig.java + * + * */ - /* from 5.6 */ // @Bean(initMethod = "initTable", destroyMethod = "destroyTable") - @Bean(initMethod = "initTable") - public JdbcCacheOCSPSource cachedOCSPSource() { - JdbcCacheOCSPSource jdbcCacheOCSPSource = new JdbcCacheOCSPSource(); - jdbcCacheOCSPSource.setJdbcCacheConnector(jdbcCacheConnector()); - jdbcCacheOCSPSource.setProxySource(onlineOcspSource()); - jdbcCacheOCSPSource.setDefaultNextUpdateDelay(ocspDefaultNextUpdate); // 0 (get new one every time) - jdbcCacheOCSPSource.setMaxNextUpdateDelay(ocspMaxNextUpdate); // 0 (get new one every time) - // questo permette di mantenere il dato su DB aggiornandolo se risulta *expired* - jdbcCacheOCSPSource.setRemoveExpired(revokeRemoveExpired); - return jdbcCacheOCSPSource; + @Bean + public OCSPSource defineOCSPSource() { + if (cacheEnabled) { + if (dataSource != null) { + JdbcCacheOCSPSource jdbcCacheOCSPSource = new JdbcCacheOCSPSource(); + jdbcCacheOCSPSource.setJdbcCacheConnector(jdbcCacheConnector()); + jdbcCacheOCSPSource.setProxySource(onlineOCSPSource()); + jdbcCacheOCSPSource.setDefaultNextUpdateDelay(ocspDefaultNextUpdate); // 0 (get new one every time) + jdbcCacheOCSPSource.setMaxNextUpdateDelay(ocspMaxNextUpdate); // 0 (get new one every time) + // questo permette di mantenere il dato su DB aggiornandolo se risulta *expired* + jdbcCacheOCSPSource.setRemoveExpired(revokeRemoveExpired); + try { + jdbcCacheOCSPSource.initTable(); + } catch (SQLException e) { + throw new DSSException("Errore inizializzazione OCSP JDBC cache", e); + } + return jdbcCacheOCSPSource; + } + OnlineOCSPSource onlineOCSPSource = onlineOCSPSource(); + FileCacheDataLoader fileCacheDataLoader = initFileCacheDataLoader(); + fileCacheDataLoader.setDataLoader(ocspDataLoader()); + fileCacheDataLoader.setCacheExpirationTime(ocspMaxNextUpdate * 1000); // to millis + onlineOCSPSource.setDataLoader(fileCacheDataLoader); + return onlineOCSPSource; + } else { + return onlineOCSPSource(); + } + } + + /* + * initMethod = "initTable" esecuzione CREATE table gestita in fase di creazione del bean gestione logica doppio + * "source" JDBC vs FILE destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che + * vengano create le tabelle ma non si vuole dropparle non appena il processo viene interrotto + * + * + * Visit + * https://github.com/esig/dss-demonstrations/blob/master/dss-demo-webapp/src/main/java/eu/europa/esig/dss/web/ + * config/DSSBeanConfig.java + * + */ + // @Bean(initMethod = "initTable", destroyMethod = "destroyTable") + @Bean + public AIASource defineAIASource() { + if (cacheEnabled) { + if (dataSource != null) { + JdbcCacheAIASource jdbcCacheAIASource = new JdbcCacheAIASource(); + jdbcCacheAIASource.setJdbcCacheConnector(jdbcCacheConnector()); + jdbcCacheAIASource.setProxySource(onlineAIASource()); + return jdbcCacheAIASource; + } + FileCacheDataLoader fileCacheDataLoader = fileCacheDataLoader(); + return new DefaultAIASource(fileCacheDataLoader); + } else { + return onlineAIASource(); + } + } + + @Bean + public AIASource onlineAIASource() { + return new DefaultAIASource(dataLoader()); } /* from 5.8 */ @Bean public CertificateVerifier certificateVerifier() { CommonCertificateVerifier certificateVerifier = new CommonCertificateVerifier(); - certificateVerifier.setCrlSource(cachedCRLSource()); - certificateVerifier.setOcspSource(cachedOCSPSource()); - certificateVerifier.setAIASource(cachedAIASource()); + /* manage source */ + certificateVerifier.setCrlSource(defineCRLSource()); + certificateVerifier.setOcspSource(defineOCSPSource()); + certificateVerifier.setAIASource(defineAIASource()); certificateVerifier.setTrustedCertSources(trustedListSource()); // Default configs @@ -455,7 +574,8 @@ public TLValidationJob job() { /* from 5.8 */ @Bean public CommonsDataLoader trustAllDataLoader() { - CommonsDataLoader dataLoader = new CommonsDataLoader(); + CommonsDataLoaderExt dataLoader = new CommonsDataLoaderExt(); + dataLoader.setCommonsDataHttpClient(dataHttpClient()); dataLoader.setProxyConfig(proxyConfig); dataLoader.setTrustStrategy(new TrustAllStrategy()); return dataLoader; @@ -471,25 +591,6 @@ public SSLCertificateLoader sslCertificateLoader() { return sslCertificateLoader; } - /* - * destroyMethod = "destroyTable" = esecuzione DROP TABLE non desisedarata corretto che vengano create le tabelle ma - * non si vuole dropparle non appena il processo viene interrotto - */ - /* from 5.10.1 */ - // @Bean(initMethod = "initTable", destroyMethod = "destroyTable") - @Bean(initMethod = "initTable") - public JdbcCacheAIASource cachedAIASource() { - JdbcCacheAIASource jdbcCacheAIASource = new JdbcCacheAIASource(); - jdbcCacheAIASource.setJdbcCacheConnector(jdbcCacheConnector()); - jdbcCacheAIASource.setProxySource(onlineAIASource()); - return jdbcCacheAIASource; - } - - @Bean - public AIASource onlineAIASource() { - return new DefaultAIASource(dataLoader()); - } - @Bean public JdbcCacheConnector jdbcCacheConnector() { return new JdbcCacheConnector(dataSource); diff --git a/src/main/java/it/eng/parer/eidas/web/rest/VerificaFirmaWs.java b/src/main/java/it/eng/parer/eidas/web/rest/VerificaFirmaWs.java index 7e2f8eb..401406c 100644 --- a/src/main/java/it/eng/parer/eidas/web/rest/VerificaFirmaWs.java +++ b/src/main/java/it/eng/parer/eidas/web/rest/VerificaFirmaWs.java @@ -22,6 +22,9 @@ import java.util.Optional; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -59,6 +62,8 @@ @RequestMapping(URL_API_BASE) public class VerificaFirmaWs { + private static final Logger log = LoggerFactory.getLogger(VerificaFirmaWs.class); + /* constants */ private static final String ETAG = "RVv1.0"; @@ -99,6 +104,10 @@ public ResponseEntity validateJson( HttpServletRequest request) { // LOG UUID MDC.put(Constants.UUID_LOG_MDC, metadata.getUuid()); + // LOG BODY + if (log.isDebugEnabled()) { + log.atDebug().log("RequestBody {}", new JSONObject(metadata).toString()); + } EidasWSReportsDTOTree body = verificaFirma.validateSignatureOnJson(metadata, request); return ResponseEntity.ok().lastModified(body.getEndValidation().toInstant()).eTag(ETAG).body(body); } diff --git a/src/main/openshift/verifica-firma-eidas-template.yml b/src/main/openshift/verifica-firma-eidas-template.yml index 3c21811..82e7aeb 100644 --- a/src/main/openshift/verifica-firma-eidas-template.yml +++ b/src/main/openshift/verifica-firma-eidas-template.yml @@ -181,7 +181,6 @@ objects: labels: app: verificafirma-eidas group: it.eng.parer - registry: ${REGISTRY} gl_log_application: eidas gl_tags: ${AMBIENTE} name: verificafirma-eidas @@ -206,7 +205,6 @@ objects: labels: app: verificafirma-eidas group: it.eng.parer - registry: ${REGISTRY} gl_log_application: eidas gl_tags: ${AMBIENTE} spec: diff --git a/src/main/resources/policy/custom_constraint.xml b/src/main/resources/policy/custom_constraint.xml index ad01b75..0c7cfe8 100644 --- a/src/main/resources/policy/custom_constraint.xml +++ b/src/main/resources/policy/custom_constraint.xml @@ -105,7 +105,7 @@ - +