From ee4f98ec293aed5f96bf1e0c778c4af7d7db9875 Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Thu, 14 Nov 2024 17:00:08 +0000 Subject: [PATCH] Customize connection, support for propert root CAs --- ca/AAPPNR_cert_sha256.pem | 41 ++++++++++++++++++++++++++++++++ ca/RAIZ2007_cert_sha256.pem | 34 ++++++++++++++++++++++++++ ca/SSLEV_cert_signing_1_2018.pem | 40 +++++++++++++++++++++++++++++++ ca/ca.go | 16 +++++++++++++ internal/gateways/araba.go | 2 -- internal/gateways/ebizkaia.go | 1 - internal/gateways/gateways.go | 27 +++++++++++++++++++++ internal/gateways/gipuzkoa.go | 2 -- ticketbai.go | 14 ++++------- 9 files changed, 162 insertions(+), 15 deletions(-) create mode 100644 ca/AAPPNR_cert_sha256.pem create mode 100644 ca/RAIZ2007_cert_sha256.pem create mode 100644 ca/SSLEV_cert_signing_1_2018.pem create mode 100644 ca/ca.go diff --git a/ca/AAPPNR_cert_sha256.pem b/ca/AAPPNR_cert_sha256.pem new file mode 100644 index 0000000..9512e34 --- /dev/null +++ b/ca/AAPPNR_cert_sha256.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL +MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu +cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV +BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0 +YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE +AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj +YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h +rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2 +To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU +ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD +PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr +PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn +soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM +8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL +MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg +jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk +3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb +KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w +gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO +MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0 +b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk +aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl +h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw +OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl +bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v +b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny +bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM +3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS +M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E +3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL +xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4 +VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR +0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK +b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi +1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS +FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM +5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw +k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7 +-----END CERTIFICATE----- diff --git a/ca/RAIZ2007_cert_sha256.pem b/ca/RAIZ2007_cert_sha256.pem new file mode 100644 index 0000000..7638321 --- /dev/null +++ b/ca/RAIZ2007_cert_sha256.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/ca/SSLEV_cert_signing_1_2018.pem b/ca/SSLEV_cert_signing_1_2018.pem new file mode 100644 index 0000000..f9d8118 --- /dev/null +++ b/ca/SSLEV_cert_signing_1_2018.pem @@ -0,0 +1,40 @@ +-----BEGIN CERTIFICATE----- +MIIHGjCCBQKgAwIBAgIQaH23FxdE2iNbP2Jac5P4pTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMTgwNzA2MTIzNjQxWhcNMjgwNzA2MTIzNjQxWjCBgTELMAkG +A1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTgwNgYDVQQLDC9CWiBaaXVy +dGFnaXJpIHB1Ymxpa29hIC0gQ2VydGlmaWNhZG8gcHVibGljbyBFVjEiMCAGA1UE +AwwZQ0EgZGUgQ2VydGlmaWNhZG9zIFNTTCBFVjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAN1INsruuFEV4Z9tcfhNC9neg6vTQYhJPNFJQmKGJVcELjn3 +Scf8kP0jJJOWlDKxYiP1dXjzV0FpK2colXDaV7gHXD912VoPVLmbRyK3UyV5YYTO +TGd84ErKtIceYLa7Hv38zsZnIkL+rfS98QoivMcZhpjRoLY3IUZ9U7j+DX/MkkJ5 +u6cXRe1vB8x9FwdWSwTkkLK4+lOhFOW0o5LDnt99Hs8ddi48KEflIbS7qYZty/Wy +SH6pvoi2ZqEAFL4eMIos4TMfV5Pdrd13HAB45Il/kdva0dq6GHfpy3absBZhsxVb +mvdAc1f66Ytr/qoLKSwBxRM/cCpQurnbS74HVgA2xBPEHM75J/YBa5uMgI/yxTzo +EiaGhExhTMUGG+9od8oqhXzDR1ecyxXqndVzf4RJB+zgd4LWnVXM3DJC0WBgmFES +Ucn0fqoyb09RPN5vFtjY/HeAuzm39p1RDclejAWWnQaDAHJrKUsk62zWKpJjuR3m +/WhLo9upz+oWO8hAofLIdxH7BOFPL+OOOsWJ8qqQPZpIZQZkwV02WBaxYufwMjgf +t4anyPrfRgujyIxFmUJxxTl6faL5XngYkZK1f4Ns2hOfn1qKZEX2C9UlCpBrSVQi +QMkM0Q3fnYOa7TBDB/f9yroxmrLmXUuG3VOCZ3rtN70DvcL7KbwiNlX0ld1RAgMB +AAGjggHUMIIB0DCBxwYDVR0RBIG/MIG8hhVodHRwOi8vd3d3Lml6ZW5wZS5jb22B +D2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBD +SUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgx +QzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAw +MTAxMCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwHQYDVR0OBBYEFMbt/nf7UVZN/KvV47EME6O/VOObMB8GA1UdIwQYMBaA +FB0cZQ6o8iV7tJHP5LGx5r1VdGwFMDoGA1UdIAQzMDEwLwYEVR0gADAnMCUGCCsG +AQUFBwIBFhlodHRwOi8vd3d3Lml6ZW5wZS5jb20vY3BzMDIGCCsGAQUFBwEBBCYw +JDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AuaXplbnBlLmNvbTAzBgNVHR8ELDAq +MCigJqAkhiJodHRwOi8vY3JsLml6ZW5wZS5jb20vY2dpLWJpbi9hcmwyMA0GCSqG +SIb3DQEBCwUAA4ICAQBYRlfC3xiMdbPZfP7j+5iHtfH1sCFGWfUF8PdWR5CGQHXq +9gybOYNDYBg8fQNIl3wKMZCI7WoXn+8e3eUUzKblhzU+009CNc2bPHIW4nCn8nak +JAcy3ZvDFO9G9K00aiu/aTgLDXnvR71crRx1vTOu30K2Lq9sJNzc8DeJWKmXY4Vu +J6C5AgwRsmtRlIBhudOyKTeXU72dRDEFejt8bGOt3gIuSEgrlPGEIP1LRnVVyAnR +RWfMOvDjwS5DQQs1j9/YIKS/w9pGB40QsCzUBsHd3N6VCtTi59ZDXky0DrA1c1ae +QtyXc90PfqYTwwEwYnQHsR6U0gk8SUB6xSn1nwUuWmHriJtmQGphGw4ax76sEJXN +k7XUJeclyKFCUK8gX6fYMb/l0hu2O93sEyfGJF9uIcqvduqEjRWQY36F/xO4r/ZH +ndVrI4vMlYN0Xiz/tPS61b3kkrWUVsknKfic8cuBiqGgop1ni0RNylpVk95UsROm +3Cfdcf1fdwVA6poiiYQiINhWb6mF0P7+DcfccC3llMYvxsfrx+11jt8YCQYI8FF6 +5FxPCt+YEBO2hnOnPMK3cA8Yvu5ol1fkE/5tcpcjPeRrvuPy/l+at2pj8hv8f4FW +MX6Gj8zt8+AoAprvXeQRaiEO4FL5alTv1Rqkv7i0HCGIpc+Ct2ApdcBtC4uSTA== +-----END CERTIFICATE----- diff --git a/ca/ca.go b/ca/ca.go new file mode 100644 index 0000000..7357641 --- /dev/null +++ b/ca/ca.go @@ -0,0 +1,16 @@ +// Package ca is used to provide the root certificates used by the TicketBAI +// services. Certificates where sourced from: +// +// - https://www.izenpe.eus/descarga-de-certificados/webize01-cndoctecnica/es/ +// +// And converted to PEM format: +// +// openssl x509 -in AAPPNR_cert_sha256.crt -outform PEM -out AAPPNR_cert_sha256.pem +package ca + +import "embed" + +//go:embed *.pem + +// Content contains the root certificates used by the TicketBAI services. +var Content embed.FS diff --git a/internal/gateways/araba.go b/internal/gateways/araba.go index f6c57d3..f68113a 100644 --- a/internal/gateways/araba.go +++ b/internal/gateways/araba.go @@ -65,8 +65,6 @@ func newAraba(env Environment, tlsConfig *tls.Config) *ArabaConn { c.client.SetBaseURL(arabaTestingBaseURL) } - tlsConfig.InsecureSkipVerify = true - tlsConfig.Renegotiation = tls.RenegotiateOnceAsClient c.client.SetTLSClientConfig(tlsConfig) c.client.SetDebug(os.Getenv("DEBUG") == "true") diff --git a/internal/gateways/ebizkaia.go b/internal/gateways/ebizkaia.go index 5b12668..3d17341 100644 --- a/internal/gateways/ebizkaia.go +++ b/internal/gateways/ebizkaia.go @@ -60,7 +60,6 @@ func newEbizkaia(env Environment, tlsConfig *tls.Config) *EBizkaiaConn { c.client.SetBaseURL(eBizkaiaTestingBaseURL) } - tlsConfig.InsecureSkipVerify = true c.client.SetTLSClientConfig(tlsConfig) c.client.SetDebug(os.Getenv("DEBUG") == "true") diff --git a/internal/gateways/gateways.go b/internal/gateways/gateways.go index b4d2ebe..f10dc00 100644 --- a/internal/gateways/gateways.go +++ b/internal/gateways/gateways.go @@ -4,10 +4,13 @@ package gateways import ( "context" + "crypto/tls" + "crypto/x509" "errors" "fmt" "strings" + "github.com/invopop/gobl.ticketbai/ca" "github.com/invopop/gobl.ticketbai/doc" "github.com/invopop/gobl/l10n" "github.com/invopop/xmldsig" @@ -121,6 +124,14 @@ func New(env Environment, zone l10n.Code, cert *xmldsig.Certificate) (Connection return nil, fmt.Errorf("preparing TLS config: %w", err) } + certs, err := rootCAPool() + if err != nil { + return nil, fmt.Errorf("preparing cert pool: %w", err) + } + + tlsConf.RootCAs = certs + tlsConf.Renegotiation = tls.RenegotiateOnceAsClient + switch zone { case doc.ZoneBI: return newEbizkaia(env, tlsConf), nil @@ -132,3 +143,19 @@ func New(env Environment, zone l10n.Code, cert *xmldsig.Certificate) (Connection return nil, fmt.Errorf("zone %s not supported", zone) } + +func rootCAPool() (*x509.CertPool, error) { + certs := x509.NewCertPool() + files, err := ca.Content.ReadDir(".") + if err != nil { + return nil, err + } + for _, f := range files { + data, err := ca.Content.ReadFile(f.Name()) + if err != nil { + return nil, err + } + certs.AppendCertsFromPEM(data) + } + return certs, nil +} diff --git a/internal/gateways/gipuzkoa.go b/internal/gateways/gipuzkoa.go index 7cd947f..4c7dacf 100644 --- a/internal/gateways/gipuzkoa.go +++ b/internal/gateways/gipuzkoa.go @@ -66,8 +66,6 @@ func newGipuzkoa(env Environment, tlsConfig *tls.Config) *GipuzkoaConn { c.client.SetBaseURL(gipuzkoaTestingBaseURL) } - tlsConfig.InsecureSkipVerify = true - tlsConfig.Renegotiation = tls.RenegotiateOnceAsClient c.client.SetTLSClientConfig(tlsConfig) c.client.SetDebug(os.Getenv("DEBUG") == "true") diff --git a/ticketbai.go b/ticketbai.go index 8690422..62ac5e7 100644 --- a/ticketbai.go +++ b/ticketbai.go @@ -50,19 +50,13 @@ func WithCurrentTime(curTime time.Time) Option { } } -/* -// WithGateway defines a new gateway connection to use for a specific zone. This -// option can be used multiple times to define multiple gateways. Useful for -// testing. -func WithGateway(code l10n.Code, conn gateways.Connection) Option { +// WithConenction defines a new gateway connection to use for the client. +// Useful for testing and mocking the connection responses. +func WithConnection(conn gateways.Connection) Option { return func(c *Client) { - if c.list == nil { - c.list = new(gateways.List) - } - c.list.Register(code, conn) + c.gw = conn } } -*/ // WithSupplierIssuer set the issuer type to supplier. To be used when the // invoice's supplier, using their own certificate, is issuing the document.