You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/06/21 20:59:55 UTC

[GitHub] serDrem closed pull request #2422: new certificate chain analyzer test

serDrem closed pull request #2422: new certificate chain analyzer test
URL: https://github.com/apache/trafficcontrol/pull/2422
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/traffic_ops/traffic_ops_golang/deliveryservices_key_type_test.go b/traffic_ops/traffic_ops_golang/deliveryservices_key_type_test.go
new file mode 100644
index 000000000..1745f3133
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/deliveryservices_key_type_test.go
@@ -0,0 +1,148 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+
+	"time"
+	"fmt"
+	"github.com/apache/trafficcontrol/traffic_ops/client"
+	"sync"
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"strconv"
+	"testing"
+)
+
+const (
+	opsUrl         = "https://yourTO.net"
+	opsUser        = ""
+	opsPass        = ""
+)
+
+var to *client.Session
+
+func CreateToConnection(trafficOpsURL string, username string, password string) error {
+	toLocal, _, err := client.LoginWithAgent(trafficOpsURL, username, password, true, "cdn-bgp-consumer",
+		false, time.Second*time.Duration(30))
+	if err != nil {
+		fmt.Errorf("Unable to login to TO: %v", err)
+		return err
+	}
+	to = toLocal
+
+	return nil
+}
+
+//
+// go test -run TestCertificateType
+//
+func TestCertificateType(t *testing.T) {
+	CreateToConnection(opsUrl, opsUser, opsPass)
+
+	deliveryServices, _, err :=  to.GetDeliveryServices()
+
+	if err != nil {
+		fmt.Errorf("Unable to get delivery services: %v", err)
+		return
+	}
+
+	messages := make(chan string)
+	var wg sync.WaitGroup
+	totalSecDS := 0
+
+	for _, deliveryService := range deliveryServices {
+		if deliveryService.Protocol > 0 {
+			wg.Add(1)
+			totalSecDS += 1
+		}
+	}
+
+	certTypes := make(map[string]int)
+
+	fmt.Printf("Total DS: %d, ds with protocol != http_only: %d\n", len(deliveryServices), totalSecDS)
+	fmt.Printf("Getting DS certificates, need try multiple times for some DS\n")
+
+	errorsCount := 0
+	errorsString := ""
+
+	for _, deliveryService := range deliveryServices {
+		if deliveryService.Protocol == 0 {
+			continue
+		}
+		deliveryServiceCopy := tc.DeliveryService(deliveryService)
+
+		go func() {
+			defer wg.Done()
+			keepTrying := true
+
+			for keepTrying {
+
+				fmt.Print("Trying " + deliveryServiceCopy.XMLID + "\n")
+				// riak has trouble services too many requests at the same time
+				deliveryServiceSSLKeys, _, error := to.GetDeliveryServiceSSLKeysByID(deliveryServiceCopy.XMLID)
+
+				if error != nil {
+					fmt.Print("Could not get ssl key for " + deliveryServiceCopy.XMLID + ", trying again\n")
+					time.Sleep(time.Second)
+					continue
+				}
+
+				keepTrying = false
+
+				//messages <- spew.Sdump(deliveryServiceSSLKeys)
+
+				if certsChain, err := decodeCertificate(deliveryServiceSSLKeys.Certificate.Crt); err != nil {
+					errorStr := fmt.Sprintf("ERROR: could not decodeCertificate for %v, %v\n", deliveryServiceCopy.XMLID, err)
+					fmt.Print(errorStr)
+					errorsCount += 1
+					errorsString = errorsString + errorStr
+					return
+				} else {
+					certsChainStr := ""
+					for index, cert := range certsChain {
+						certsChainStr = certsChainStr + strconv.Itoa(index) + ". " + cert.SignatureAlgorithm.String() + "\n"
+					}
+					fmt.Print(deliveryServiceCopy.XMLID +": \n" + certsChainStr )
+					if _, ok := certTypes[certsChainStr]; !ok {
+						certTypes[certsChainStr] = 0
+					}
+					certTypes[certsChainStr] += 1
+				}
+			}
+		}()
+	}
+
+	go func() {
+		for message := range messages {
+			fmt.Print(message)
+		}
+	}()
+
+	wg.Wait()
+
+	fmt.Printf("\nTotal DS: %d, ds with protocol != http_only: %d\n\n", len(deliveryServices), totalSecDS)
+
+	for certType, num := range certTypes {
+		fmt.Printf("%d delivery services has sig:\n%s", num, certType)
+	}
+	fmt.Printf("Had %d errors:\n%s", errorsCount, errorsString)
+}
+
+
diff --git a/traffic_ops/traffic_ops_golang/deliveryservices_keys.go b/traffic_ops/traffic_ops_golang/deliveryservices_keys.go
index 50d4f5fdc..965661546 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservices_keys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservices_keys.go
@@ -154,6 +154,72 @@ func verifyAndEncodeCertificate(certificate string, rootCA string) (string, erro
 	return base64EncodedStr, nil
 }
 
+// verify the server certificate chain and return the
+// certificate and its chain in the proper order. Returns an
+// ordered certificate chain, including self signed certificates.
+func decodeCertificate(certificate string) ([]*x509.Certificate, error) {
+	var b64crt string
+
+	// strip newlines from encoded crt and decode it from base64.
+	crtArr := strings.Split(certificate, "\\n")
+	for i := 0; i < len(crtArr); i++ {
+		b64crt += crtArr[i]
+	}
+	pemCerts := make([]byte, base64.StdEncoding.EncodedLen(len(b64crt)))
+	_, err := base64.StdEncoding.Decode(pemCerts, []byte(b64crt))
+	if err != nil {
+		return nil, fmt.Errorf("could not base64 decode the certificate %v", err)
+	}
+
+	// decode, verify, and order certs
+	var bundle string
+	certs := strings.SplitAfter(string(pemCerts), "-----END CERTIFICATE-----")
+	if len(certs) > 1 {
+		// decode and verify the server certificate
+		block, _ := pem.Decode([]byte(certs[0]))
+		cert, err := x509.ParseCertificate(block.Bytes)
+		if err != nil {
+			return nil, fmt.Errorf("could not parse the server certificate %v", err)
+		}
+		if !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) {
+			return nil, fmt.Errorf("no key encipherment usage for the server certificate")
+		}
+		for i := 0; i < len(certs)-1; i++ {
+			bundle += certs[i]
+		}
+
+		var opts x509.VerifyOptions
+
+		intermediatePool := x509.NewCertPool()
+		if !intermediatePool.AppendCertsFromPEM([]byte(bundle)) {
+			return nil, fmt.Errorf("certificate CA bundle is empty, %v", err)
+		}
+
+		opts = x509.VerifyOptions{
+			Intermediates: intermediatePool,
+		}
+
+		chain, err := cert.Verify(opts)
+		if err != nil {
+			return nil, fmt.Errorf("could not verify the certificate chain, %v", err)
+		}
+		var certChain []*x509.Certificate
+		if len(chain) > 0 {
+			for _, link := range chain[0] {
+				// Only print non-self signed elements of the chain
+				//if link.AuthorityKeyId != nil && !bytes.Equal(link.AuthorityKeyId, link.SubjectKeyId) {
+				certChain = append(certChain, link)
+				//}
+			}
+			return certChain, nil
+		} else {
+			return nil, fmt.Errorf("can't find valid chain for cert in file in request")
+		}
+	} else {
+		return nil, fmt.Errorf("no certificate chain to decode")
+	}
+}
+
 func addDeliveryServiceSSLKeysHandler(w http.ResponseWriter, r *http.Request) {
 	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
 	if userErr != nil || sysErr != nil {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services