2016-03-30 10 views
4

Ich arbeite mit AWS API Gateway und einem Go-Back-Ende. Um sicherzustellen, dass alle Verbindungen über das API-Gateway laufen, muss ich die TLS-Client-Authentifizierung verwenden (auch bekannt als Zwei-Wege-Authentifizierung, gegenseitige Authentifizierung).Wie kann ich Go dazu bringen, ein selbstsigniertes Zertifikat für die TLS-Client-Authentifizierung zu akzeptieren?

Im Prinzip funktioniert das mit so etwas wie:

func enableClientAuth(server *http.Server, clientCertFile string) error { 
    clientCert, err := ioutil.ReadFile(clientCertFile) 
    if err != nil { 
     return err 
    } 
    caCertPool := x509.NewCertPool() 
    caCertPool.AppendCertsFromPEM(clientCert) 

    tlsConfig := &tls.Config{ 
     ClientAuth: tls.RequireAndVerifyClientCert, 
     ClientCAs: caCertPool, 
    } 
    tlsConfig.BuildNameToCertificate() 
    server.TLSConfig = tlsConfig 
    return nil 
} 

Das Problem, das ich habe, ist dieser Fehler:

tls: failed to verify client's certificate: x509: certificate signed by unknown authority (possibly because of "x509: invalid signature: parent certificate cannot sign this kind of certificate" while trying to verify candidate authority certificate "ApiGateway")

Dieses Zertifikat, weil der Client zu sein scheint selbst signiert, Es handelt sich jedoch nicht um ein CA-Zertifikat. Go akzeptiert die Signatur nicht. (Unterbindet dies nicht den Zweck eines selbstsignierten Zertifikats? Die meisten selbstsignierten Zertifikate, die ich gesehen habe, sind keine CA-Zertifikate.) Ich habe leider keine Kontrolle darüber, wie das Client-Zertifikat generiert oder gesendet wird. Alles wird von AWS erledigt. Kann ich etwas tun, um ein Zertifikat im ClientCas-Zertifikatspool zu erhalten, das Go dazu veranlasst, das API Gateway-Clientzertifikat zu akzeptieren?

Beispiel Client-Zertifikat:

-----BEGIN CERTIFICATE----- 
MIIC6DCCAdCgAwIBAgIISIIYdm+rIgMwDQYJKoZIhvcNAQELBQAwNDELMAkGA1UE 
BhMCVVMxEDAOBgNVBAcTB1NlYXR0bGUxEzARBgNVBAMTCkFwaUdhdGV3YXkwHhcN 
MTYwMzMwMTgxNTE4WhcNMTcwMzMwMTgxNTE4WjA0MQswCQYDVQQGEwJVUzEQMA4G 
A1UEBxMHU2VhdHRsZTETMBEGA1UEAxMKQXBpR2F0ZXdheTCCASIwDQYJKoZIhvcN 
AQEBBQADggEPADCCAQoCggEBALVVG0Ng8IbDy0tdw2yp2GHXYV8jDPJxsRXAstZ+ 
5N4ngG/ySPyv1i2OOvzKqUNzyKptsUbgtG/0XDWRI0qDATrsxXH6xy8lBeRZHNi4 
ko6EP9BevyxB5YtoKqEoXbKAn4/hNWmac8tnENkLww0qFpPOhtxb0B2DHv+lkqZo 
qBBBBZQ5Dal95h0cpUwoLRr5w3HsYzPcX1OUtQ/5cH0M0p/XvkB4jrZxsh1aQGsf 
B9+temIJJtKvmmZ0C/dZ+neJhA+I526eUENeqmm5R1irM7sj4FDaU4bLR+L/+R6s 
KtDLT4jPqf5vFYfMuEmyk4b5TBATJxAA47Y+gRFRe6Aon0ECAwEAATANBgkqhkiG 
9w0BAQsFAAOCAQEAmFdXuy5Y6zdrIZHd7XCt/Q6jsU3hFGaEGRbDEFBwh6ixz58e 
1egiUnIeUWZTFSzjQSY3IhYE7dvW+BVkjdLybhB3rim29Fb67AkBtRmQOLnHz426 
bflOG46BSwNTvIEytOr0O6ds49bD34UrHELUCGmHJqIhBSrVCFOCwlf/Mksw9jxD 
xo/YmJe2R4xNklvxWiFHOXrnGwrJ9yaWeQnCkRZBzfFLSZ26/fBnbkYUGn0lmtoB 
e/rg/rgpwufbkhXA6CFX7adnLUKWqZgbmL5dpvLu9vB34ebfo4vE+o7AsgdloHBV 
obcSyrLbZp25k/SlbOhSAqjjW1NaF+YypTxHFA== 
-----END CERTIFICATE----- 
+3

Haben Sie Ihr selbst signiertes Zertifikat laden und markieren Sie ihn als 'IsCA', wie http://stackoverflow.com/questions/22666163/golang-tls-with-selfsigned- Zertifikat –

+0

Ist das Zertifikat vom Client das Stammzertifikat oder das Kind? – Griffin

+2

Dieser Schlüssel * kann * nicht von sich aus verifiziert werden: aus dem [RFC] (https://tools.ietf.org/html/rfc5280#section-4.2.1.9) "Wenn die Erweiterung der Basisbedingungen in einer Version nicht vorhanden ist 3 Zertifikat, oder die Erweiterung ist vorhanden, aber die cA boolean wird nicht geltend gemacht, dann darf der zertifizierte öffentliche Schlüssel nicht verwendet werden, um Zertifikatsignaturen zu überprüfen " – JimB

Antwort

4

@ JohnWeldon Kommentar führte mich zu der Lösung, die ist, dass ich die Client-Zertifikat-Struktur ändern müssen, nachdem ich es laden. Dies erfordert die Decodierung der PEM und das Zerlegen des Zertifikats. Für das API-Gateway-Client-Zertifikat musste ich BasicConstraintsValid und IsCA auf True und KeyUsage auf KeyUsageCertSign setzen; für mein lokal generiertes cert brauchte ich nur die letzten beiden. Ändern der enableClientAuth() func in meiner Frage:

func enableClientAuth(server *http.Server, clientCertFile string) error { 
    pemBytes, err := ioutil.ReadFile(clientCertFile) 
    if err != nil { 
     return err 
    } 

    pemBlock, _ := pem.Decode(pemBytes) 
    clientCert, err := x509.ParseCertificate(pemBlock.Bytes) 
    if err != nil { 
     return err 
    } 

    clientCert.BasicConstraintsValid = true 
    clientCert.IsCA = true 
    clientCert.KeyUsage = x509.KeyUsageCertSign 

    caCertPool := x509.NewCertPool() 
    caCertPool.AddCert(clientCert) 

    tlsConfig := &tls.Config{ 
     ClientAuth: tls.RequireAndVerifyClientCert, 
     ClientCAs: caCertPool, 
    } 
    tlsConfig.BuildNameToCertificate() 
    server.TLSConfig = tlsConfig 
    return nil 
}