You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ne...@apache.org on 2018/12/07 20:49:12 UTC
[trafficcontrol] branch master updated: Emit warning when adding
self-signed certs using the API (#3072)
This is an automated email from the ASF dual-hosted git repository.
neuman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new e4b07c8 Emit warning when adding self-signed certs using the API (#3072)
e4b07c8 is described below
commit e4b07c8401345475089d1ffb22e30b6b2cdbe2ac
Author: Rawlin Peters <Ra...@gmail.com>
AuthorDate: Fri Dec 7 13:49:08 2018 -0700
Emit warning when adding self-signed certs using the API (#3072)
Rather than prohibit adding self-signed certs via the API, emit a
warning to indicate that self-signed certs were detected and might not
be completely valid.
---
lib/go-tc/constants.go | 2 +-
.../traffic_ops_golang/deliveryservice/keys.go | 31 ++++++++++++++--------
.../deliveryservice/keys_test.go | 19 +++++++++----
.../common/api/DeliveryServiceSslKeysService.js | 2 +-
4 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/lib/go-tc/constants.go b/lib/go-tc/constants.go
index a72aefb..9f7cee8 100644
--- a/lib/go-tc/constants.go
+++ b/lib/go-tc/constants.go
@@ -42,7 +42,7 @@ const (
ErrorLevel
)
-var alertLevels = [4]string{"success", "info", "warn", "error"}
+var alertLevels = [4]string{"success", "info", "warning", "error"}
func (a AlertLevel) String() string {
return alertLevels[a]
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
index 0c5a1a9..3dd2577 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
@@ -60,7 +60,7 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
return
}
- certChain, err := verifyCertificate(req.Certificate.Crt, "")
+ certChain, isUnknownAuth, err := verifyCertificate(req.Certificate.Crt, "")
if err != nil {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil)
return
@@ -83,6 +83,10 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("adding SSL keys to delivery service '"+*req.DeliveryService+"': "+err.Error()))
return
}
+ if isUnknownAuth {
+ api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the certificate is signed by an unknown authority and may be invalid")
+ return
+ }
api.WriteResp(w, r, "Successfully added ssl keys for "+*req.DeliveryService)
}
@@ -268,24 +272,26 @@ WHERE r.pattern = $2
// verify the server certificate chain and return the
// certificate and its chain in the proper order. Returns a verified
// and ordered certificate and CA chain.
-func verifyCertificate(certificate string, rootCA string) (string, error) {
+// If the cert verification returns UnknownAuthorityError, return true to
+// indicate that the certs are signed by an unknown authority (e.g. self-signed).
+func verifyCertificate(certificate string, rootCA string) (string, bool, error) {
// decode, verify, and order certs for storage
certs := strings.SplitAfter(certificate, PemCertEndMarker)
if len(certs) <= 1 {
- return "", errors.New("no certificate chain to verify")
+ return "", false, errors.New("no certificate chain to verify")
}
// decode and verify the server certificate
block, _ := pem.Decode([]byte(certs[0]))
if block == nil {
- return "", errors.New("could not decode pem-encoded server certificate")
+ return "", false, errors.New("could not decode pem-encoded server certificate")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
- return "", errors.New("could not parse the server certificate: " + err.Error())
+ return "", false, errors.New("could not parse the server certificate: " + err.Error())
}
if !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) {
- return "", errors.New("no key encipherment usage for the server certificate")
+ return "", false, errors.New("no key encipherment usage for the server certificate")
}
bundle := ""
for i := 0; i < len(certs)-1; i++ {
@@ -294,7 +300,7 @@ func verifyCertificate(certificate string, rootCA string) (string, error) {
intermediatePool := x509.NewCertPool()
if !intermediatePool.AppendCertsFromPEM([]byte(bundle)) {
- return "", errors.New("certificate CA bundle is empty")
+ return "", false, errors.New("certificate CA bundle is empty")
}
opts := x509.VerifyOptions{
@@ -304,17 +310,20 @@ func verifyCertificate(certificate string, rootCA string) (string, error) {
// verify the certificate chain.
rootPool := x509.NewCertPool()
if !rootPool.AppendCertsFromPEM([]byte(rootCA)) {
- return "", errors.New("unable to parse root CA certificate")
+ return "", false, errors.New("unable to parse root CA certificate")
}
opts.Roots = rootPool
}
chain, err := cert.Verify(opts)
if err != nil {
- return "", errors.New("could not verify the certificate chain: " + err.Error())
+ if _, ok := err.(x509.UnknownAuthorityError); ok {
+ return certificate, true, nil
+ }
+ return "", false, errors.New("could not verify the certificate chain: " + err.Error())
}
if len(chain) < 1 {
- return "", errors.New("can't find valid chain for cert in file in request")
+ return "", false, errors.New("can't find valid chain for cert in file in request")
}
pemEncodedChain := ""
for _, link := range chain[0] {
@@ -325,5 +334,5 @@ func verifyCertificate(certificate string, rootCA string) (string, error) {
}
}
- return pemEncodedChain, nil
+ return pemEncodedChain, false, nil
}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go
index 14b30a3..1bc2bd2 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go
@@ -27,7 +27,7 @@ import (
const (
BadData = "This is bad data and it is not pem encoded"
- SelfSigneCertOnly = `
+ SelfSignedCertOnly = `
-----BEGIN CERTIFICATE-----
MIIDkjCCAnoCCQCfwd219JKpUDANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC
VVMxETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxEDAOBgNVBAoM
@@ -199,19 +199,28 @@ OEUjfakK71+V/HbQt477zR4k7cRbiA==
func TestVerifyAndEncodeCertificate(t *testing.T) {
// should fail bad base64 data
- dat, err := verifyCertificate(BadData, "")
+ dat, _, err := verifyCertificate(BadData, "")
if err == nil {
t.Errorf("Unexpected result, there should have been a base64 decoding failure")
}
- // should fail, can't verify self signed cert
- dat, err = verifyCertificate(SelfSigneCertOnly, rootCA)
+ // should fail, can't verify self signed cert against this rootCA
+ dat, _, err = verifyCertificate(SelfSignedCertOnly, rootCA)
if err == nil {
t.Errorf("Unexpected result, a certificate verification error should have occured")
}
+ // should pass, unknown authority is just a warning not an error
+ dat, unknownAuth, err := verifyCertificate(GoodTLSKeys, "")
+ if err != nil {
+ t.Errorf("Test failure: %s", err)
+ }
+ if !unknownAuth {
+ t.Errorf("Unexpected result, certificate verification should have detected unknown authority")
+ }
+
// should pass
- dat, err = verifyCertificate(GoodTLSKeys, rootCA)
+ dat, _, err = verifyCertificate(GoodTLSKeys, rootCA)
if err != nil {
t.Errorf("Test failure: %s", err)
}
diff --git a/traffic_portal/app/src/common/api/DeliveryServiceSslKeysService.js b/traffic_portal/app/src/common/api/DeliveryServiceSslKeysService.js
index 46a8ec0..31f1631 100644
--- a/traffic_portal/app/src/common/api/DeliveryServiceSslKeysService.js
+++ b/traffic_portal/app/src/common/api/DeliveryServiceSslKeysService.js
@@ -60,7 +60,7 @@ var DeliveryServiceSslKeysService = function($http, $q, locationUtils, messageMo
$http.post(ENV.api['root'] + "deliveryservices/sslkeys/add", sslKeys)
.then(
function(result) {
- messageModel.setMessages([ { level: 'success', text: 'SSL Keys updated for ' + deliveryService.xmlId } ], false);
+ messageModel.setMessages(result.data.alerts, false);
request.resolve(result.data.response);
},
function(fault) {