This is an automated email from the ASF dual-hosted git repository.

shamrick 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 1f56100  Added SANs to Cert Page (#6282)
1f56100 is described below

commit 1f5610066c9191eeba29dcacb25182e6c676c82e
Author: mattjackson220 <[email protected]>
AuthorDate: Fri Oct 15 12:02:12 2021 -0600

    Added SANs to Cert Page (#6282)
    
    * Added SANs to Cert Page
    
    * updated changelog
    
    * updated per comment
---
 CHANGELOG.md                                       |  1 +
 .../v4/deliveryservices_xmlid_xmlid_sslkeys.rst    |  6 +-
 lib/go-tc/deliveryservice_ssl_keys.go              | 16 ++++-
 lib/go-util/str.go                                 | 11 ++++
 .../deliveryservice/autorenewcerts.go              |  2 +-
 .../traffic_ops_golang/deliveryservice/keys.go     | 69 ++++++++++++++--------
 traffic_ops/traffic_ops_golang/routing/routes.go   |  9 ++-
 .../FormDeliveryServiceSslKeysController.js        |  1 +
 .../form.deliveryServiceSslKeys.tpl.html           |  6 ++
 traffic_portal/app/src/scripts/config.js           |  2 +-
 10 files changed, 90 insertions(+), 33 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7286bf6..9624e01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#6034](https://github.com/apache/trafficcontrol/issues/6034) Added new 
query parameter `cdn` to the `GET /api/x/deliveryserviceserver` Traffic Ops API 
to filter by CDN name
 - Added a new Traffic Monitor configuration option -- 
`short_hostname_override` -- to traffic_monitor.cfg to allow overriding the 
system hostname that Traffic Monitor uses.
 - A new Traffic Portal server command-line option `-c` to specify a 
configuration file, and the ability to set `log: null` to log to stdout 
(consult documentation for details).
+- SANs information to the SSL key endpoint and Traffic Portal page.
 
 ### Fixed
 - Fixed Traffic Router crs/stats to prevent overflow and to correctly record 
the time used in averages.
diff --git a/docs/source/api/v4/deliveryservices_xmlid_xmlid_sslkeys.rst 
b/docs/source/api/v4/deliveryservices_xmlid_xmlid_sslkeys.rst
index efc2cb5..3130a23 100644
--- a/docs/source/api/v4/deliveryservices_xmlid_xmlid_sslkeys.rst
+++ b/docs/source/api/v4/deliveryservices_xmlid_xmlid_sslkeys.rst
@@ -71,6 +71,9 @@ Response Structure
 :state:           An optional field which, if present, contains the state 
entered by the user when generating certificate\ [1]_
 :version:         An integer that defines the "version" of the key - which may 
be thought of as the sequential generation; that is, the higher the number the 
more recent the key
 :expiration:      The expiration date of the certificate for the 
:term:`Delivery Service` in :rfc:`3339` format
+:sans:            The :abbr:`SANs (Subject Alternate Names)` from the SSL 
certificate.
+
+       .. versionadded:: 4.1
 
 .. code-block:: http
        :caption: Response Example
@@ -93,7 +96,8 @@ Response Structure
                "country": "US",
                "state": "Colorado",
                "version": "1",
-               "expiration": "2020-08-18T13:53:06Z"
+               "expiration": "2020-08-18T13:53:06Z",
+               "sans": ["*.foober.com", "*.foober2.com"]
        }}
 
 ``DELETE``
diff --git a/lib/go-tc/deliveryservice_ssl_keys.go 
b/lib/go-tc/deliveryservice_ssl_keys.go
index ec6dc4c..fd67722 100644
--- a/lib/go-tc/deliveryservice_ssl_keys.go
+++ b/lib/go-tc/deliveryservice_ssl_keys.go
@@ -65,6 +65,20 @@ type DeliveryServiceSSLKeys struct {
        Certificate     DeliveryServiceSSLKeysCertificate 
`json:"certificate,omitempty"`
 }
 
+// DeliveryServiceSSLKeysV4 is the representation of a DeliveryServiceSSLKeys 
in the latest minor version of
+// version 4 of the Traffic Ops API.
+type DeliveryServiceSSLKeysV4 = DeliveryServiceSSLKeysV41
+
+// DeliveryServiceSSLKeysV41 structures contain information about an SSL key
+// certificate pair used by a Delivery Service.
+//
+// "V41" is used because this structure was first introduced in version 4.1 of
+// the Traffic Ops API.
+type DeliveryServiceSSLKeysV41 struct {
+       DeliveryServiceSSLKeysV15
+       Sans []string `json:"sans,omitempty"`
+}
+
 // DeliveryServiceSSLKeysV15 structures contain information about an SSL key
 // certificate pair used by a Delivery Service.
 //
@@ -73,7 +87,7 @@ type DeliveryServiceSSLKeys struct {
 //
 // This is, ostensibly, an updated version of DeliveryServiceSSLKeys, but
 // beware that this may not be completely accurate as the predecessor structure
-// appears to be used in many more contexts than this this structure.
+// appears to be used in many more contexts than this structure.
 type DeliveryServiceSSLKeysV15 struct {
        DeliveryServiceSSLKeys
        Expiration time.Time `json:"expiration,omitempty"`
diff --git a/lib/go-util/str.go b/lib/go-util/str.go
index 842def7..755fc8c 100644
--- a/lib/go-util/str.go
+++ b/lib/go-util/str.go
@@ -49,6 +49,17 @@ func StrInArray(strs []string, s string) bool {
        return false
 }
 
+// RemoveStrFromArray removes a specific string from a string slice.
+func RemoveStrFromArray(strs []string, s string) []string {
+       newStrArray := []string{}
+       for _, str := range strs {
+               if str != s {
+                       newStrArray = append(newStrArray, str)
+               }
+       }
+       return newStrArray
+}
+
 func ContainsStr(a []string, x string) bool {
        for _, n := range a {
                if x == n {
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
index 05327d2..84be21f 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
@@ -208,7 +208,7 @@ func RunAutorenewal(existingCerts []ExistingCerts, cfg 
*config.Config, ctx conte
                        continue
                }
 
-               expiration, err := 
parseExpirationFromCert([]byte(keyObj.Certificate.Crt))
+               expiration, _, err := 
parseExpirationAndSansFromCert([]byte(keyObj.Certificate.Crt), keyObj.Hostname)
                if err != nil {
                        log.Errorf("cert autorenewal: %s: %s", ds.XmlId, 
err.Error())
                        dsExpInfo.XmlId = ds.XmlId
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
index 79fcd69..b4d1502 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
@@ -21,6 +21,7 @@ package deliveryservice
 
 import (
        "bytes"
+       "context"
        "crypto/ecdsa"
        "crypto/rsa"
        "crypto/x509"
@@ -135,8 +136,8 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
        api.WriteResp(w, r, "Successfully added ssl keys for 
"+*req.DeliveryService)
 }
 
-// GetSSLKeysByXMLIDV15 fetches the deliveryservice ssl keys by the specified 
xmlID. V15 includes expiration date.
-func GetSSLKeysByXMLIDV15(w http.ResponseWriter, r *http.Request) {
+// GetSSLKeysByXMLID fetches the deliveryservice ssl keys by the specified 
xmlID. V15 includes expiration date.
+func GetSSLKeysByXMLID(w http.ResponseWriter, r *http.Request) {
        inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"xmlid"}, nil)
        if userErr != nil || sysErr != nil {
                api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
@@ -149,67 +150,83 @@ func GetSSLKeysByXMLIDV15(w http.ResponseWriter, r 
*http.Request) {
        }
        xmlID := inf.Params["xmlid"]
        alerts := tc.Alerts{}
-       version := inf.Params["version"]
-       decode := inf.Params["decode"]
        if userErr, sysErr, errCode := tenant.Check(inf.User, xmlID, 
inf.Tx.Tx); userErr != nil || sysErr != nil {
                userErr = api.LogErr(r, errCode, userErr, sysErr)
                alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
                api.WriteAlerts(w, r, errCode, alerts)
                return
        }
-       keyObj, ok, err := inf.Vault.GetDeliveryServiceSSLKeys(xmlID, version, 
inf.Tx.Tx, r.Context())
+
+       keyObjV4, err := getSslKeys(inf, r.Context())
        if err != nil {
-               userErr := api.LogErr(r, http.StatusInternalServerError, nil, 
errors.New("getting ssl keys: "+err.Error()))
+               userErr := api.LogErr(r, http.StatusInternalServerError, nil, 
err)
                alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
                api.WriteAlerts(w, r, http.StatusInternalServerError, alerts)
                return
        }
-       if !ok {
-               keyObj = tc.DeliveryServiceSSLKeysV15{}
+
+       var keyObj interface{}
+       if inf.Version.Major < 4 || (inf.Version.Major == 4 && 
inf.Version.Minor < 1) {
+               keyObj = keyObjV4.DeliveryServiceSSLKeysV15
        } else {
+               keyObj = keyObjV4
+       }
+
+       if len(alerts.Alerts) == 0 {
+               api.WriteResp(w, r, keyObj)
+       } else {
+               api.WriteAlertsObj(w, r, http.StatusOK, alerts, keyObj)
+       }
+}
+
+func getSslKeys(inf *api.APIInfo, ctx context.Context) 
(tc.DeliveryServiceSSLKeysV4, error) {
+       xmlID := inf.Params["xmlid"]
+       version := inf.Params["version"]
+       decode := inf.Params["decode"]
+
+       keyObjFromTv, ok, err := inf.Vault.GetDeliveryServiceSSLKeys(xmlID, 
version, inf.Tx.Tx, ctx)
+       if err != nil {
+               return tc.DeliveryServiceSSLKeysV4{}, errors.New("getting ssl 
keys: " + err.Error())
+       }
+       keyObj := tc.DeliveryServiceSSLKeysV4{}
+       if ok {
+               keyObj.DeliveryServiceSSLKeysV15 = keyObjFromTv
                parsedCert := keyObj.Certificate
                err = Base64DecodeCertificate(&parsedCert)
                if err != nil {
-                       userErr := api.LogErr(r, 
http.StatusInternalServerError, nil, errors.New("getting SSL keys for XMLID 
'"+xmlID+"': "+err.Error()))
-                       alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
-                       api.WriteAlerts(w, r, http.StatusInternalServerError, 
alerts)
-                       return
+                       return tc.DeliveryServiceSSLKeysV4{}, 
errors.New("getting SSL keys for XMLID '" + xmlID + "': " + err.Error())
                }
                if decode != "" && decode != "0" { // the Perl version checked 
the decode string as: if ( $decode )
                        keyObj.Certificate = parsedCert
                }
 
                if keyObj.Certificate.Crt != "" && keyObj.Expiration.IsZero() {
-                       exp, err := 
parseExpirationFromCert([]byte(parsedCert.Crt))
+                       exp, sans, err := 
parseExpirationAndSansFromCert([]byte(parsedCert.Crt), keyObj.Hostname)
                        if err != nil {
-                               userErr := api.LogErr(r, 
http.StatusInternalServerError, nil, errors.New(xmlID+": "+err.Error()))
-                               alerts.AddNewAlert(tc.ErrorLevel, 
userErr.Error())
-                               api.WriteAlerts(w, r, 
http.StatusInternalServerError, alerts)
-                               return
+                               return tc.DeliveryServiceSSLKeysV4{}, 
errors.New(xmlID + ": " + err.Error())
                        }
                        keyObj.Expiration = exp
+                       keyObj.Sans = sans
                }
        }
 
-       if len(alerts.Alerts) == 0 {
-               api.WriteResp(w, r, keyObj)
-       } else {
-               api.WriteAlertsObj(w, r, http.StatusOK, alerts, keyObj)
-       }
+       return keyObj, nil
 }
 
-func parseExpirationFromCert(cert []byte) (time.Time, error) {
+func parseExpirationAndSansFromCert(cert []byte, commonName string) 
(time.Time, []string, error) {
        block, _ := pem.Decode(cert)
        if block == nil {
-               return time.Time{}, errors.New("Error decoding cert to parse 
expiration")
+               return time.Time{}, []string{}, errors.New("Error decoding cert 
to parse expiration")
        }
 
        x509cert, err := x509.ParseCertificate(block.Bytes)
        if err != nil {
-               return time.Time{}, errors.New("Error parsing cert to get 
expiration - " + err.Error())
+               return time.Time{}, []string{}, errors.New("Error parsing cert 
to get expiration - " + err.Error())
        }
 
-       return x509cert.NotAfter, nil
+       dnsNames := util.RemoveStrFromArray(x509cert.DNSNames, commonName)
+
+       return x509cert.NotAfter, dnsNames, nil
 }
 
 func Base64DecodeCertificate(cert *tc.DeliveryServiceSSLKeysCertificate) error 
{
diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go 
b/traffic_ops/traffic_ops_golang/routing/routes.go
index b8a3fc6..8c3ccf0 100644
--- a/traffic_ops/traffic_ops_golang/routing/routes.go
+++ b/traffic_ops/traffic_ops_golang/routing/routes.go
@@ -130,6 +130,9 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                 * 4.x API
                 */
 
+               // SSL Keys
+               {api.Version{Major: 4, Minor: 1}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.GetSSLKeysByXMLID, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 41357729074},
+
                // CDN lock
                {api.Version{Major: 4, Minor: 0}, http.MethodGet, 
`cdn_locks/?$`, cdn_lock.Read, auth.PrivLevelReadOnly, nil, Authenticated, nil, 
4134390561},
                {api.Version{Major: 4, Minor: 0}, http.MethodPost, 
`cdn_locks/?$`, cdn_lock.Create, auth.PrivLevelOperations, nil, Authenticated, 
nil, 4134390562},
@@ -484,7 +487,7 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {api.Version{Major: 4, Minor: 0}, http.MethodDelete, 
`deliveryservices/{id}/?$`, 
api.DeleteHandler(&deliveryservice.TODeliveryService{}), 
auth.PrivLevelOperations, nil, Authenticated, nil, 4226420743},
                {api.Version{Major: 4, Minor: 0}, http.MethodGet, 
`deliveryservices/{id}/servers/eligible/?$`, 
deliveryservice.GetServersEligible, auth.PrivLevelReadOnly, nil, Authenticated, 
nil, 4747615843},
 
-               {api.Version{Major: 4, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, 
deliveryservice.GetSSLKeysByXMLIDV15, auth.PrivLevelAdmin, nil, Authenticated, 
nil, 41357729073},
+               {api.Version{Major: 4, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.GetSSLKeysByXMLID, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 41357729073},
                {api.Version{Major: 4, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/add$`, deliveryservice.AddSSLKeys, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 48728785833},
                {api.Version{Major: 4, Minor: 0}, http.MethodDelete, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.DeleteSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 49267343},
                {api.Version{Major: 4, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/generate/?$`, deliveryservice.GenerateSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 4534390513},
@@ -872,7 +875,7 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {api.Version{Major: 3, Minor: 0}, http.MethodDelete, 
`deliveryservices/{id}/?$`, 
api.DeleteHandler(&deliveryservice.TODeliveryService{}), 
auth.PrivLevelOperations, nil, Authenticated, nil, 2226420743},
                {api.Version{Major: 3, Minor: 0}, http.MethodGet, 
`deliveryservices/{id}/servers/eligible/?$`, 
deliveryservice.GetServersEligible, auth.PrivLevelReadOnly, nil, Authenticated, 
nil, 2747615843},
 
-               {api.Version{Major: 3, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, 
deliveryservice.GetSSLKeysByXMLIDV15, auth.PrivLevelAdmin, nil, Authenticated, 
nil, 21357729073},
+               {api.Version{Major: 3, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.GetSSLKeysByXMLID, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 21357729073},
                {api.Version{Major: 3, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/add$`, deliveryservice.AddSSLKeys, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 28728785833},
                {api.Version{Major: 3, Minor: 0}, http.MethodDelete, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.DeleteSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 29267343},
                {api.Version{Major: 3, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/generate/?$`, deliveryservice.GenerateSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 2534390513},
@@ -1236,7 +1239,7 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {api.Version{Major: 2, Minor: 0}, http.MethodDelete, 
`deliveryservices/{id}/?$`, 
api.DeleteHandler(&deliveryservice.TODeliveryService{}), 
auth.PrivLevelOperations, nil, Authenticated, nil, 222642074},
                {api.Version{Major: 2, Minor: 0}, http.MethodGet, 
`deliveryservices/{id}/servers/eligible/?$`, 
deliveryservice.GetServersEligible, auth.PrivLevelReadOnly, nil, Authenticated, 
nil, 274761584},
 
-               {api.Version{Major: 2, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, 
deliveryservice.GetSSLKeysByXMLIDV15, auth.PrivLevelAdmin, nil, Authenticated, 
nil, 2135772907},
+               {api.Version{Major: 2, Minor: 0}, http.MethodGet, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.GetSSLKeysByXMLID, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 2135772907},
                {api.Version{Major: 2, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/add$`, deliveryservice.AddSSLKeys, 
auth.PrivLevelAdmin, nil, Authenticated, nil, 2872878583},
                {api.Version{Major: 2, Minor: 0}, http.MethodDelete, 
`deliveryservices/xmlId/{xmlid}/sslkeys$`, deliveryservice.DeleteSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 2926734},
                {api.Version{Major: 2, Minor: 0}, http.MethodPost, 
`deliveryservices/sslkeys/generate/?$`, deliveryservice.GenerateSSLKeys, 
auth.PrivLevelOperations, nil, Authenticated, nil, 253439051},
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/FormDeliveryServiceSslKeysController.js
 
b/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/FormDeliveryServiceSslKeysController.js
index 59596af..205b303 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/FormDeliveryServiceSslKeysController.js
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/FormDeliveryServiceSslKeysController.js
@@ -65,6 +65,7 @@ var FormDeliveryServiceSslKeysController = 
function(deliveryService, sslKeys, $s
        $scope.navigateToPath = locationUtils.navigateToPath;
 
        $scope.formattedExpiration = $scope.sslKeys.expiration !== undefined ? 
$filter('date')($scope.sslKeys.expiration, 'MM/dd/yyyy') : undefined;
+       $scope.sans = $scope.sslKeys.sans !== undefined ? sslKeys.sans.join(', 
') : ""
 
        $scope.generateKeys = function() {
                locationUtils.navigateToPath('/delivery-services/' + 
deliveryService.id + '/ssl-keys/generate');
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/form.deliveryServiceSslKeys.tpl.html
 
b/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/form.deliveryServiceSslKeys.tpl.html
index 6f0bf3a..4894918 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/form.deliveryServiceSslKeys.tpl.html
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryServiceSslKeys/form.deliveryServiceSslKeys.tpl.html
@@ -61,6 +61,12 @@ under the License.
                                        <output name="expiration" 
class="form-control">{{formattedExpiration}}</output>
                                </div>
                        </div>
+            <div class="form-group">
+                <label for="sans" class="control-label col-md-2 col-sm-2 
col-xs-12">SANs</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <output name="sans" class="form-control">{{sans}}</output>
+                </div>
+            </div>
                        <div class="form-group" ng-class="{'has-error': 
hasError(dsSslKeyForm.authType), 'has-feedback': 
hasError(dsSslKeyForm.authType)}">
                                <label for="authType" class="control-label 
col-md-2 col-sm-2 col-xs-12">Certificate Source (Self Signed, CA, etc) *</label>
                                <div class="col-md-10 col-sm-10 col-xs-12">
diff --git a/traffic_portal/app/src/scripts/config.js 
b/traffic_portal/app/src/scripts/config.js
index 52e5f0c..3973a15 100644
--- a/traffic_portal/app/src/scripts/config.js
+++ b/traffic_portal/app/src/scripts/config.js
@@ -23,4 +23,4 @@
 
 angular.module('config', [])
 
-.constant('ENV', { api: { root:'/api/4.0/', stable: "/api/3.1/" } });
+.constant('ENV', { api: { root:'/api/4.1/', stable: "/api/3.1/" } });

Reply via email to