trafficcontrol-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dewr...@apache.org
Subject [trafficcontrol] 02/03: Fix TO Go cdn/dnssec/generate to accept strings
Date Tue, 21 Aug 2018 22:08:44 GMT
This is an automated email from the ASF dual-hosted git repository.

dewrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git

commit 1236dfe14751a1d61e0174051d39dca62d3a98cd
Author: Robert Butts <rob@apache.org>
AuthorDate: Tue Aug 21 11:28:17 2018 -0600

    Fix TO Go cdn/dnssec/generate to accept strings
    
    Fixes #2723
---
 lib/go-tc/deliveryservice_ssl_keys.go        | 45 +++++++++++--
 lib/go-tc/deliveryservicesslkeys_test.go     | 94 ++++++++++++++++++++++++++++
 traffic_ops/traffic_ops_golang/cdn/dnssec.go |  3 +-
 3 files changed, 135 insertions(+), 7 deletions(-)

diff --git a/lib/go-tc/deliveryservice_ssl_keys.go b/lib/go-tc/deliveryservice_ssl_keys.go
index a26d672..9687953 100644
--- a/lib/go-tc/deliveryservice_ssl_keys.go
+++ b/lib/go-tc/deliveryservice_ssl_keys.go
@@ -18,7 +18,9 @@ package tc
 import (
 	"database/sql"
 	"errors"
+	"strconv"
 	"strings"
+	"time"
 
 	"github.com/apache/trafficcontrol/lib/go-util"
 )
@@ -152,15 +154,48 @@ type DNSSECKeyDSRecord struct {
 	Digest     string `json:"digest"`
 }
 
+// CDNDNSSECGenerateReqDate is the date accepted by CDNDNSSECGenerateReq.
+// This will unmarshal a UNIX epoch integer, a RFC3339 string, the old format string used
by Perl '2018-08-21+14:26:06', and the old format string sent by the Portal '2018-08-21 14:14:42'.
+// This exists to fix a critical bug, see https://github.com/apache/trafficcontrol/issues/2723
- it SHOULD NOT be used by any other endpoint.
+type CDNDNSSECGenerateReqDate int64
+
+func (i *CDNDNSSECGenerateReqDate) UnmarshalJSON(d []byte) error {
+	const oldPortalDateFormat = `2006-01-02 15:04:05`
+	const oldPerlUIDateFormat = `2006-01-02+15:04:05`
+	if len(d) == 0 {
+		return errors.New("empty object")
+	}
+	if d[0] == '"' {
+		d = d[1 : len(d)-1] // strip JSON quotes, to accept the UNIX epoch as a string or number
+	}
+	if di, err := strconv.ParseInt(string(d), 10, 64); err == nil {
+		*i = CDNDNSSECGenerateReqDate(di)
+		return nil
+	}
+	if t, err := time.Parse(time.RFC3339, string(d)); err == nil {
+		*i = CDNDNSSECGenerateReqDate(t.Unix())
+		return nil
+	}
+	if t, err := time.Parse(oldPortalDateFormat, string(d)); err == nil {
+		*i = CDNDNSSECGenerateReqDate(t.Unix())
+		return nil
+	}
+	if t, err := time.Parse(oldPerlUIDateFormat, string(d)); err == nil {
+		*i = CDNDNSSECGenerateReqDate(t.Unix())
+		return nil
+	}
+	return errors.New("invalid date")
+}
+
 type CDNDNSSECGenerateReq struct {
 	// Key is the CDN name, as documented in the API documentation.
 	Key *string `json:"key"`
 	// Name is the CDN domain, as documented in the API documentation.
-	Name              *string          `json:"name"`
-	TTL               *util.JSONIntStr `json:"ttl"`
-	KSKExpirationDays *util.JSONIntStr `json:"kskExpirationDays"`
-	ZSKExpirationDays *util.JSONIntStr `json:"zskExpirationDays"`
-	EffectiveDateUnix *util.JSONIntStr `json:"effectiveDate"`
+	Name              *string                   `json:"name"`
+	TTL               *util.JSONIntStr          `json:"ttl"`
+	KSKExpirationDays *util.JSONIntStr          `json:"kskExpirationDays"`
+	ZSKExpirationDays *util.JSONIntStr          `json:"zskExpirationDays"`
+	EffectiveDateUnix *CDNDNSSECGenerateReqDate `json:"effectiveDate"`
 }
 
 func (r CDNDNSSECGenerateReq) Validate(tx *sql.Tx) error {
diff --git a/lib/go-tc/deliveryservicesslkeys_test.go b/lib/go-tc/deliveryservicesslkeys_test.go
new file mode 100644
index 0000000..31039bf
--- /dev/null
+++ b/lib/go-tc/deliveryservicesslkeys_test.go
@@ -0,0 +1,94 @@
+package tc
+
+/*
+ * 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 (
+	"encoding/json"
+	"testing"
+)
+
+// - Perl: 2018-08-21+14:26:06
+// - Portal: 2018-08-21 14:14:42
+// - RFC3339
+
+func TestCDNDNSSECGenerateReqDateUnmarshalJSON(t *testing.T) {
+	type T struct {
+		D CDNDNSSECGenerateReqDate `json:"d"`
+	}
+	obj := T{}
+
+	// epoch
+	s := `{"d": 1534869508}`
+	if err := json.Unmarshal([]byte(s), &obj); err != nil {
+		t.Fatalf("unmarshalling epoch CDNDNSSECGenerateReqDate: error expected nil, actual:  %+v",
err)
+	}
+	if st := int64(1534869508); int64(obj.D) != st {
+		t.Fatalf("unmarshalling epoch CDNDNSSECGenerateReqDate: error expected %+v, actual:  %+v",
st, int64(obj.D))
+	}
+
+	// RFC3339
+	s = `{"d": "2018-08-21T10:58:56-06:00"}`
+	if err := json.Unmarshal([]byte(s), &obj); err != nil {
+		t.Fatalf("unmarshalling RFC3339 CDNDNSSECGenerateReqDate: error expected nil, actual: 
%+v", err)
+	}
+	if st := int64(1534870736); int64(obj.D) != st {
+		t.Fatalf("unmarshalling RFC3339 CDNDNSSECGenerateReqDate: error expected %+v, actual: 
%+v", st, int64(obj.D))
+	}
+
+	// old Portal date format
+	s = `{"d": "2018-10-31 1:12:06"}`
+	if err := json.Unmarshal([]byte(s), &obj); err != nil {
+		t.Fatalf("unmarshalling old Portal CDNDNSSECGenerateReqDate: error expected nil, actual:
 %+v", err)
+	}
+	if st := int64(1540948326); int64(obj.D) != st {
+		t.Fatalf("unmarshalling old Portal CDNDNSSECGenerateReqDate: error expected %+v, actual:
 %+v", st, int64(obj.D))
+	}
+
+	// old Perl date format
+	s = `{"d": "2018-04-19+02:04:05"}`
+	if err := json.Unmarshal([]byte(s), &obj); err != nil {
+		t.Fatalf("unmarshalling old Perl CDNDNSSECGenerateReqDate: error expected nil, actual:
 %+v", err)
+	}
+	if st := int64(1524103445); int64(obj.D) != st {
+		t.Fatalf("unmarshalling old Perl CDNDNSSECGenerateReqDate: error expected %+v, actual:
 %+v", st, int64(obj.D))
+	}
+
+	// invalid date format
+	s = `{"d": "Mon Jan 12 15:04:05 -0700 MST 2018"}`
+	if err := json.Unmarshal([]byte(s), &obj); err == nil {
+		t.Fatalf("unmarshalling invalid CDNDNSSECGenerateReqDate: error expected, actual nil")
+	}
+	s = `{"d": "01-25-2018"}`
+	if err := json.Unmarshal([]byte(s), &obj); err == nil {
+		t.Fatalf("unmarshalling invalid format CDNDNSSECGenerateReqDate: error expected, actual
nil")
+	}
+	s = `{"d": "foo"}`
+	if err := json.Unmarshal([]byte(s), &obj); err == nil {
+		t.Fatalf("unmarshalling invalid string CDNDNSSECGenerateReqDate: error expected, actual
nil")
+	}
+	s = `{"d": "42.0"}`
+	if err := json.Unmarshal([]byte(s), &obj); err == nil {
+		t.Fatalf("unmarshalling invalid float string CDNDNSSECGenerateReqDate: error expected,
actual nil")
+	}
+	s = `{"d": 42.0}`
+	if err := json.Unmarshal([]byte(s), &obj); err == nil {
+		t.Fatalf("unmarshalling invalid float CDNDNSSECGenerateReqDate: error expected, actual
nil")
+	}
+}
diff --git a/traffic_ops/traffic_ops_golang/cdn/dnssec.go b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
index 3456620..b44ba7b 100644
--- a/traffic_ops/traffic_ops_golang/cdn/dnssec.go
+++ b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
@@ -27,7 +27,6 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
-	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice"
@@ -51,7 +50,7 @@ func CreateDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	if req.EffectiveDateUnix == nil {
-		now := util.JSONIntStr(time.Now().Unix())
+		now := tc.CDNDNSSECGenerateReqDate(time.Now().Unix())
 		req.EffectiveDateUnix = &now
 	}
 	cdnName := *req.Key


Mime
View raw message