@ -19,16 +19,23 @@ package cmd
import (
import (
"bufio"
"bufio"
"bytes"
"bytes"
"crypto/ecdsa"
"crypto/hmac"
"crypto/hmac"
crand "crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha1"
"crypto/tls"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/base64"
"encoding/hex"
"encoding/hex"
"encoding/json"
"encoding/json"
"encoding/pem"
"errors"
"errors"
"fmt"
"fmt"
"io"
"io"
"io/ioutil"
"io/ioutil"
"math/big"
"math/rand"
"math/rand"
"net"
"net"
"net/http"
"net/http"
@ -233,66 +240,68 @@ func UnstartedTestServer(t TestErrHandler, instanceType string) TestServer {
}
}
// Starts the test server and returns the TestServer with TLS configured instance.
// testServerCertPEM and testServerKeyPEM are generated by
func StartTestTLSServer ( t TestErrHandler , instanceType string ) TestServer {
// https://golang.org/src/crypto/tls/generate_cert.go
serverKey := [ ] byte ( ` -- -- - BEGIN RSA PRIVATE KEY -- -- -
// $ go run generate_cert.go -ca --host 127.0.0.1
MIIEpAIBAAKCAQEAwD0kEmvtaHx + M0qJAY8zFEn6UpCIbZshNIoXOOr2S3XBEar9
// The generated certificate contains IP SAN, that way we don't need
gtvTGpL73rPJroVcaTJxavsQJx6iD8E38t85rTsrlxEomAk5eKVK3WyplcUuqBgm
// to enable InsecureSkipVerify in TLS config
+ KMYyyWxMXgYA3 + AumEHiDg1SMIgrWFka2x + dSsqRb64tzWtD3LLy / Amq4cdiO1v
/ v1rNEdqj + 9 G7G8leZSd8TNWZqebOwBPA4JiVtDDubemk4Qr4qYt3ChwNQiwq7Bt
var testServerCertPEM = [ ] byte ( ` -- -- - BEGIN CERTIFICATE -- -- -
RFR7EokO2an9XfT1NS71evikmGduhBLz3T + 3 QinxZDwb6SmNouYJkdqy6oPcWt0z
MIIC9zCCAd + gAwIBAgIQV9ukx5ZahXeFygLXnR1WJTANBgkqhkiG9w0BAQsFADAS
OXDgSPmY1NVlrujJ5JhtQTQxOs6mFVZ / 82 mn7wIDAQABAoIBAQCWiIoRntAGLM5J
MRAwDgYDVQQKEwdBY21lIENvMB4XDTE2MTExNTE1MDQxNFoXDTE3MTExNTE1MDQx
7 cjBHthZv + Az / RfH9F0ZHjU3Dc6VonzwD9x6NxbkzUpLxq9caPPHMIfdxQGOEI / J
NFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
FH1yQtiQTTBCGF6YR0jor06jey6EqCZz3I3Pzy9gDIDnguoS + ynbSJW0VodrFRCv
AQoCggEBALLDXunOVIipgtvPVpQxIBTzUpceUtLYrNKTCtYfLtvFCNSPAa2W2EAi
k / 8 lm4yexZFRkhpk5LRCz5rEdKZjU4kBgTBzeD6P1JbYKfAs49A99x9L42hExwfv
mW2WgtU + Wd + jFN2leG + lvyEp2n1YzBN12oOzAZMf39K2j05aO6vN68Pf / 3 w / h2qz
ppX / 7 ECbdMTQRVgDytOJpQR + mrrEHq30lxNZg0XngGm / 4 Rby8Ga6cfxmQbUrj5of
PDYFWbWBMS1vC6RosfaQc4VFZCkz89M1aonwj0K8FjOHG4pu7rKnVkluC0c4 + Xpu
uA9TsQ6CAmTy6OqagLK4Rr9tSd4cjbBm2MCs2bDMYhzkhsveoFidsF1A9S3zSo / z
8 rB652chx / h6wFZwscVqFZIarTte8Z1tcbRhbvpdkOV749Wn5i2umlrKpBgsBv22
VJlqFtXpAoGBAP2ewImNRpaa0D1TWk / 559 XZJ64MMd4J0VK4cGzXPeBZ8WGVJxqF
8 jn115BK7E2mN0rlCYPuN312bFFSSE85NaSdOp06TjD + 2 Rv9jPKizvnFN + 2 ADEje
PLl74AXG7 / Iu18EWMHqTuMxlrkTKpF6KF9G5RCmAFi + UzVVspj9uvAk8SrFUA5P7
nlCaYe3VRybKPZLrxPcqFQoCQsO + 8 ZsCAwEAAaNJMEcwDgYDVR0PAQH / BAQDAgKk
c7Ahnmz44isD7OJ6sHUOP1d88dehODQdRAp5hX0h + rsTH3L6g3QRnEEdAoGBAMIK
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB / wQFMAMBAf8wDwYDVR0RBAgw
8 DJMsl2dmuuV4WPrgoqdnDnSmuC5YqxibJPJnZpgp19IxlIYRYtuUZjHIYx7OM / r
BocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAsmNCixmx + srB93 + Jz5t90zzCJN4O
1 X / dIvNqpFbvTnT9XFHWSyYMqal1 + OY1Sg9i9E6YKuPAW2wccf3svhzehc98vJ0j
5 RDWh7X7D54xtRRZ / t9HLLLFKW9EqhAM17xee3C4eNCicOqHP / htEvLwt3BWFmya
d7S81UpfKKWY + uD / wvOJdV1Pw7SoSvs5pmbFuKt7AoGAUY7ClblDsNy6CG6MhVl0
djvIUQYfymx4GtBTfMH4eC5vYGdxSuTVNe7JGHMpJjArNe4vIlUHyj2n12aGDHUf
7 zT06KhtRNzdXn + HT8jr0gC6ecnwGDwuaetnABSYRsY / hY0wK8rjS3 + LSf3sW6aG
NKEiTR2m + 6 hiKEyym74vhxGnl208OFa4tAMv3J7BjEObE37oy / vH / getE0HwG / EL
wF + Whs301HpCiaz1zUI737BuyJWezPC4pDQ7cQmcGX8apz4TDqF1Rxob316t5zxe
feE4D2Pp9XqeMCg / sPZPoQgBuq3QsL2RdL8DQywb / HrApdLyfmN0avV5tmbrm0cL
DAxGHBZYPd6JZ30d1q5vFBUCgYEAvnaOHlE6Irm4ftW3TqS0lerulbMrYrmVKS / S
/ 0 NUqCWjJIIKF0XxZbqlkQsYK5zpDJ36MFXO65aF3QGOMP1rlBD3d0S6kw ==
851 KnWWR4 + 1 C / QHmAV5fqV6Mh5 / LvAr4nXEqBVP / y3VJxXuLSqjVSpvTTQsHLK / R
-- -- - END CERTIFICATE -- -- - ` )
6 hhvRVYHg1YkZpHlMiFW2m9xWKBPYs6ViUpw8XdGJoVqe7 + QVAvwr47DwmgOcVm9
A9O / 2 FECgYAgttnwo3gBxY0DJdfXBuqZCAa1MMErIxCaKw2Gm9JccnQW0fcuUcb3
var testServerKeyPEM = [ ] byte ( ` -- -- - BEGIN RSA PRIVATE KEY -- -- -
WSHJPyJ74ktk / QZGEmtKzAxVZ73t14dwHNNDid5CN2FyTIMCeWG5b2vM5NJe8KuQ
MIIEowIBAAKCAQEAssNe6c5UiKmC289WlDEgFPNSlx5S0tis0pMK1h8u28UI1I8B
6 cJePZj7ZkSvm2tkREdR37Oh2eZqGtaIbj6VTplvKUByWa / TEozMpQ ==
rZbYQCKZbZaC1T5Z36MU3aV4b6W / ISnafVjME3Xag7MBkx / f0raPTlo7q83rw9 //
fD + HarM8NgVZtYExLW8LpGix9pBzhUVkKTPz0zVqifCPQrwWM4cbim7usqdWSW4L
Rzj5em7ysHrnZyHH + HrAVnCxxWoVkhqtO17xnW1xtGFu + l2Q5Xvj1afmLa6aWsqk
GCwG / bbyOfXXkErsTaY3SuUJg + 43 fXZsUVJITzk1pJ06nTpOMP7ZG / 2 M8qLO + cU3
7 YAMSN6eUJph7dVHJso9kuvE9yoVCgJCw77xmwIDAQABAoIBAEE6CmLTd4LaHzZn
RBcUibk7Q5KCbQQkLYM0Rgr1G9ry3RL6D0mwtb1JIqSa + 6 gldROl5NIvM2 / Bkajf
JasBAI3FPfM6GMP / KGMxW77iK823eGRjUkyavaWQOtMXRrF0r2X9k8jsrqrh8FTb
if2CyF / zqKkmTo + yI4Ovs7viWFR1IFBUHRwfYTTKnXA2q4S39knExALe1wWUkc4L
oOidewQ5IVCU3OQLWXP / beKoV / jw6 + dOs5CYjXFsww6tdOsh + WkA9d3 / rKPPtLdP
tDQiZtmI6FCYy / PdYqmzY0xg6dipGTDRfENUEx5SJu6HeSoUQUwEpQqnRxIu0iZl
FJ2ZziECgYEAzpdbIrFltGlSh7DIJfnQG86QeOw / nGluFTED9AweRAIzOYnUQCV3
XCKMhFqmzsNpibEC1Cok92ZJk7bfsmPlx + qzL7BFpynA / gezxgc2wNZlWs8btPHi
s9h8hwL5If1FgAMD4E2iJtNgI / Kn5j8SDo / A5hAP1CXv12JRTB + pzlECgYEA3YQ6
e2MLQYLDIcD5RoCrXOc9qo / l46uzo5laIuCKtd / IoOlip95kdgzpQC0 / eenDLV9y
KLqAOZxZe + TVKtSOzVGy58FyD6L1oBJgfwuBku1x5ADRsIblq2uIOumDygRU0hMg
0 tM3orIFGLyJU5hv6vC0x1ZdIGit0wP4ULhgKisCgYARJs3BLps0BD5 + 13 V2eawG
cvrZnzuUv8gM6FncrBjjKo + YKlI91R54vsGNx3zr05tyfAixFqKlC4 / 2 PIuL4vFT
zK99uRO / Uh8cuAT73uNz1RjrFiDFwANDTSjhiKSoZr + bZiSvPaLFuGzV7zJzUi8s
mFC6iQDXayLjbd00BbjyUQKBgHJD2R74sj + ywhFRR8S0brDXn5mx7LYKRfnoCvTe
uu6iZw2KFhfdwhibBF7UeF / c048 + ItcbjTUqj4Y3PjZ / usHymMSvprSmLOnLUPd3
6 fjufsdMHN5gV2ybZYRuHEtC / LX4o //ccGB+T964smXqxiB81ePViuhC1xd4fsi0
svZNAoGBALJOOR8ebtgATqc6jpnFxdqNmlwzAf / dH / jMZ6FZrttqIWiwxKvWaWPK
eHJtMmEPMustw / sv1GhDzwWmvgNFPzwEitPKW31m4EdbUCZFxPZ69 / BtHTjXD3q3
dP9W + omFXKQ36bVCB6xKmZH / ZVH5iQW0pdkD2JRnUPsDMNBeqmd6
-- -- - END RSA PRIVATE KEY -- -- - ` )
-- -- - END RSA PRIVATE KEY -- -- - ` )
serverPem := [ ] byte ( ` -- -- - BEGIN CERTIFICATE -- -- -
// Starts the test server and returns the TestServer with TLS configured instance.
MIID2zCCAsOgAwIBAgIJALPniQGEq3KtMA0GCSqGSIb3DQEBCwUAMIGDMQswCQYD
func StartTestTLSServer ( t TestErrHandler , instanceType string , cert , key [ ] byte ) TestServer {
VQQGEwJJTjESMBAGA1UECAwJS2FybmF0YWthMRIwEAYDVQQHDAlCZW5nYWx1cnUx
FzAVBgNVBAoMDk1pbmlvVW5pdFRlc3RzMREwDwYDVQQLDAhTU0xUZXN0czEgMB4G
CSqGSIb3DQEJARYRc3NsdGVzdHNAbWluaW8uaW8wHhcNMTYxMDI0MDk1ODQzWhcN
MjYxMDIyMDk1ODQzWjCBgzELMAkGA1UEBhMCSU4xEjAQBgNVBAgMCUthcm5hdGFr
YTESMBAGA1UEBwwJQmVuZ2FsdXJ1MRcwFQYDVQQKDA5NaW5pb1VuaXRUZXN0czER
MA8GA1UECwwIU1NMVGVzdHMxIDAeBgkqhkiG9w0BCQEWEXNzbHRlc3RzQG1pbmlv
LmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwD0kEmvtaHx + M0qJ
AY8zFEn6UpCIbZshNIoXOOr2S3XBEar9gtvTGpL73rPJroVcaTJxavsQJx6iD8E3
8 t85rTsrlxEomAk5eKVK3WyplcUuqBgm + KMYyyWxMXgYA3 + AumEHiDg1SMIgrWFk
a2x + dSsqRb64tzWtD3LLy / Amq4cdiO1v / v1rNEdqj + 9 G7G8leZSd8TNWZqebOwBP
A4JiVtDDubemk4Qr4qYt3ChwNQiwq7BtRFR7EokO2an9XfT1NS71evikmGduhBLz
3 T + 3 QinxZDwb6SmNouYJkdqy6oPcWt0zOXDgSPmY1NVlrujJ5JhtQTQxOs6mFVZ /
82 mn7wIDAQABo1AwTjAdBgNVHQ4EFgQUv ++ gaIEUL0sboDER + 4 KPpiU27FMwHwYD
VR0jBBgwFoAUv ++ gaIEUL0sboDER + 4 KPpiU27FMwDAYDVR0TBAUwAwEB / zANBgkq
hkiG9w0BAQsFAAOCAQEAHumbrFEBhN0EWsjZZB / VkArE / owBg7djvNetYE / rEWSV
/ dwysQgkTpGrCyfmzSwhsX ++ gr5a5qh + HAF0Ygufd5OIk / kn9X3pz66Kaq4TYdFO
hc / DUD7wwY3 / Mfi9lhT6lKSfMu69D3FuiI + xtUJ7CU8Fhr2ua6UB7e / 2i nYzsJDN
WYMzrkLMasQNzNWiz3Tditxj1WuuRe9mgXbbBHT03udUyuLi + 4 ZiOuw6CiJL4Pfk
PAKMo7QWaxAectHZsxvcfH9uYOIuv1AwDUQBA + jhADvLh55epFq0DdJ057 + QKItL
vtKIzIB9HcGDFfBvIq + WlxYlQPSIkeq2z1iZaTl11g ==
-- -- - END CERTIFICATE -- -- - ` )
// Fetch TLS key and pem files from test-data/ directory.
// Fetch TLS key and pem files from test-data/ directory.
// dir, _ := os.Getwd()
// dir, _ := os.Getwd()
// testDataDir := filepath.Join(filepath.Dir(dir), "test-data")
// testDataDir := filepath.Join(filepath.Dir(dir), "test-data")
//
//
// pemFile := filepath.Join(testDataDir, "server.pem")
// pemFile := filepath.Join(testDataDir, "server.pem")
// keyFile := filepath.Join(testDataDir, "server.key")
// keyFile := filepath.Join(testDataDir, "server.key")
cer , err := tls . X509KeyPair ( serverPem , serverK ey)
cer , err := tls . X509KeyPair ( cert , key )
if err != nil {
if err != nil {
t . Fatalf ( "Failed to load certificate: %v" , err )
t . Fatalf ( "Failed to load certificate: %v" , err )
}
}
@ -2115,3 +2124,97 @@ func StartTestS3PeerRPCServer(t TestErrHandler) (TestServer, []string) {
testRPCServer . Server = httptest . NewServer ( muxRouter )
testRPCServer . Server = httptest . NewServer ( muxRouter )
return testRPCServer , fsDirs
return testRPCServer , fsDirs
}
}
// generateTLSCertKey creates valid key/cert with registered DNS or IP address
// depending on the passed parameter. That way, we can use tls config without
// passing InsecureSkipVerify flag. This code is a simplified version of
// https://golang.org/src/crypto/tls/generate_cert.go
func generateTLSCertKey ( host string ) ( [ ] byte , [ ] byte , error ) {
validFor := 365 * 24 * time . Hour
rsaBits := 2048
if len ( host ) == 0 {
return nil , nil , fmt . Errorf ( "Missing host parameter" )
}
publicKey := func ( priv interface { } ) interface { } {
switch k := priv . ( type ) {
case * rsa . PrivateKey :
return & k . PublicKey
case * ecdsa . PrivateKey :
return & k . PublicKey
default :
return nil
}
}
pemBlockForKey := func ( priv interface { } ) * pem . Block {
switch k := priv . ( type ) {
case * rsa . PrivateKey :
return & pem . Block { Type : "RSA PRIVATE KEY" , Bytes : x509 . MarshalPKCS1PrivateKey ( k ) }
case * ecdsa . PrivateKey :
b , err := x509 . MarshalECPrivateKey ( k )
if err != nil {
fmt . Fprintf ( os . Stderr , "Unable to marshal ECDSA private key: %v" , err )
os . Exit ( 2 )
}
return & pem . Block { Type : "EC PRIVATE KEY" , Bytes : b }
default :
return nil
}
}
var priv interface { }
var err error
priv , err = rsa . GenerateKey ( crand . Reader , rsaBits )
if err != nil {
return nil , nil , fmt . Errorf ( "failed to generate private key: %s" , err )
}
notBefore := time . Now ( )
notAfter := notBefore . Add ( validFor )
serialNumberLimit := new ( big . Int ) . Lsh ( big . NewInt ( 1 ) , 128 )
serialNumber , err := crand . Int ( crand . Reader , serialNumberLimit )
if err != nil {
return nil , nil , fmt . Errorf ( "failed to generate serial number: %s" , err )
}
template := x509 . Certificate {
SerialNumber : serialNumber ,
Subject : pkix . Name {
Organization : [ ] string { "Acme Co" } ,
} ,
NotBefore : notBefore ,
NotAfter : notAfter ,
KeyUsage : x509 . KeyUsageKeyEncipherment | x509 . KeyUsageDigitalSignature ,
ExtKeyUsage : [ ] x509 . ExtKeyUsage { x509 . ExtKeyUsageServerAuth } ,
BasicConstraintsValid : true ,
}
hosts := strings . Split ( host , "," )
for _ , h := range hosts {
if ip := net . ParseIP ( h ) ; ip != nil {
template . IPAddresses = append ( template . IPAddresses , ip )
} else {
template . DNSNames = append ( template . DNSNames , h )
}
}
template . IsCA = true
template . KeyUsage |= x509 . KeyUsageCertSign
derBytes , err := x509 . CreateCertificate ( crand . Reader , & template , & template , publicKey ( priv ) , priv )
if err != nil {
return nil , nil , fmt . Errorf ( "Failed to create certificate: %s" , err )
}
certOut := bytes . NewBuffer ( [ ] byte { } )
pem . Encode ( certOut , & pem . Block { Type : "CERTIFICATE" , Bytes : derBytes } )
keyOut := bytes . NewBuffer ( [ ] byte { } )
pem . Encode ( keyOut , pemBlockForKey ( priv ) )
return certOut . Bytes ( ) , keyOut . Bytes ( ) , nil
}