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 667b555 Add Per-DS HTTP/2 and TLS Versions Support (#5802)
667b555 is described below
commit 667b5552e5a184c08c5ef6ffb4cd2b5276db8f13
Author: Robert O Butts <[email protected]>
AuthorDate: Mon May 10 10:03:23 2021 -0600
Add Per-DS HTTP/2 and TLS Versions Support (#5802)
* Add t3c ssl_server_name.yaml
* Move docs DS Params to DS page
As requested in PR Review.
* Changed docs hyphens to match text length
As requested in PR Review.
* Change changelog to changed docs file
As requested in PR Review.
* Add docs profile overview link to ds params
As requested in PR Review.
---
CHANGELOG.md | 1 +
docs/source/overview/delivery_services.rst | 19 ++
docs/source/overview/profiles_and_parameters.rst | 3 +-
lib/go-atscfg/meta.go | 2 +
lib/go-atscfg/meta_test.go | 5 +
lib/go-atscfg/remapdotconfig.go | 150 +++++----
lib/go-atscfg/remapdotconfig_test.go | 10 +-
lib/go-atscfg/snidotyaml.go | 129 +++++++
lib/go-atscfg/sslservernamedotyaml.go | 383 +++++++++++++++++++++
lib/go-atscfg/sslservernamedotyaml_test.go | 411 +++++++++++++++++++++++
traffic_ops_ort/atstccfg/cfgfile/routing.go | 2 +
traffic_ops_ort/atstccfg/cfgfile/wrappers.go | 42 +++
traffic_ops_ort/atstccfg/config/config.go | 102 +++---
traffic_ops_ort/t3c/README.md | 76 +++--
traffic_ops_ort/t3c/config/config.go | 53 +--
traffic_ops_ort/t3c/torequest/torequest.go | 7 +-
16 files changed, 1225 insertions(+), 170 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9915938..16e01c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
- Added integration to use ACME to generate new SSL certificates.
- Add a Federation to the Ansible Dataset Loader
- Added asynchronous status to ACME certificate generation.
+- Added per Delivery Service HTTP/2 and TLS Versions support, via
ssl_server_name.yaml and sni.yaml. See overview/delivery_services and t3c docs.
- Added headers to Traffic Portal, Traffic Ops, and Traffic Monitor to opt out
of tracking users via Google FLoC.
- Add logging scope for logging.yaml generation for ATS 9 support
- `DELETE` request method for `deliveryservices/xmlId/{name}/urlkeys` and
`deliveryservices/{id}/urlkeys`.
diff --git a/docs/source/overview/delivery_services.rst
b/docs/source/overview/delivery_services.rst
index c2317ab..34d4c05 100644
--- a/docs/source/overview/delivery_services.rst
+++ b/docs/source/overview/delivery_services.rst
@@ -1023,3 +1023,22 @@ A text-based unique identifier for a Delivery Service.
Many :ref:`to-api` endpoi
.. [#cardinality] In source code and :ref:`to-api` responses, the "Long
Description" fields of a Delivery Service are "0-indexed" - hence the names
differing slightly from the ones displayed in user-friendly UIs.
.. [#dupOrigin] These Delivery Services Types are vulnerable to what this
writer likes to call the "Duplicate Origin Problem". This problem is tracked by
:issue:`3537`.
.. [#httpOnlyRegex] These regular expression types can only appear in the
Match List of HTTP-:ref:`Routed <ds-types>` Delivery Services.
+
+
+.. _ds-parameters:
+
+Delivery Service Parameters
+----------
+Features which are new, experimental, or not significant enough to be
first-class Delivery Service fields are often added as Parameters. To use
these, add a Profile to the Delivery Service, with the given Parameter assigned.
+
+parent.config
+'''''''''''''
+The following Parameters must have the Config File ``parent.config`` to take
effect.
+
+- ``try_all_primaries_before_secondary`` - on a Delivery Service Profile, if
this exists, try all primary parents before failing over to secondary parents,
which may be ideal if objects are unlikely to be in cache. The default behavior
is to immediately fail to a secondary, which is ideal if objects are likely to
be in cache, as the first consistent-hashed secondary parent will be the
primary parent in its own cachegroup and therefore receive requests for that
object from clients near it [...]
+- ``enable_h2`` - on a Delivery Service Profile, if this is ``true``, enable
HTTP/2 for client requests. Note ATS must also be listening for HTTP/2 in
records.config, or this will have no effect. Note this setting is not in the
parent.config config file, but either ssl_server_name.yaml in ATS 8 or sni.yaml
in ATS 9. The Parameter has the "parent.config" config file for consistency.
+- ``tls_versions`` - on a Delivery Service Profile, if this exists, enable the
given comma-delimited TLS versions for client requests. For example,
``1.1,1.2,1.3``. Note ATS must also be accepting those TLS versions in
records.config, or this will have no effect. Note this setting is not in the
parent.config config file, but either ssl_server_name.yaml in ATS 8 or sni.yaml
in ATS 9. The Parameter has the "parent.config" config file for consistency.
+
+Additionally, :term:`Delivery Service` :ref:`Profiles <ds-profile>` can have
special Parameters with the :ref:`parameter-name` "mso.parent_retry" to
:ref:`multi-site-origin-qht`.
+
+.. seealso:: To see how the :ref:`Values <parameter-value>` of these
Parameters are interpreted, refer to the `Apache Traffic Server documentation
on the parent.config configuration file
<https://docs.trafficserver.apache.org/en/7.1.x/admin-guide/files/parent.config.en.html>`_
diff --git a/docs/source/overview/profiles_and_parameters.rst
b/docs/source/overview/profiles_and_parameters.rst
index 8ed2b5b..160ba1a 100644
--- a/docs/source/overview/profiles_and_parameters.rst
+++ b/docs/source/overview/profiles_and_parameters.rst
@@ -21,6 +21,8 @@ Profiles and Parameters
***********************
:dfn:`Profiles` are a collection of configuration options, defined partially
by the Profile's Type_ (not to be confused with the more general ":term:`Type`"
used by many other things in Traffic Control) and partially by the
:dfn:`Parameters` set on them. Mainly, Profiles and Parameters are used to
configure :term:`cache servers`, but they can also be used to configure parts
of (nearly) any Traffic Control component, and can even be linked with more
abstract concepts like :ref:`Delivery S [...]
+.. seealso:: For Delivery Service Profile Parameters, see :ref:`ds-parameters`.
+
.. _profiles:
Profiles
@@ -490,7 +492,6 @@ This configuration file is generated entirely from
:term:`Cache Group` relations
- ``qstring``
- ``psel.qstring_handling``
- ``not_a_parent`` - unlike the other Parameters listed (which have a 1:1
correspondence with Apache Traffic Server configuration options), this
Parameter affects the generation of :term:`parent` relationships between
:term:`cache servers`. When a Parameter with this :ref:`parameter-name` and
Config File exists on a :ref:`Profile <profiles>` used by a :term:`cache
server`, it will not be added as a :term:`parent` of any other :term:`cache
server`, regardless of :term:`Cache Group` hierar [...]
-- ``try_all_primaries_before_secondary`` - on a Delivery Service Profile, if
this exists, try all primary parents before failing over to secondary parents,
which may be ideal if objects are unlikely to be in cache. The default behavior
is to immediately fail to a secondary, which is ideal if objects are likely to
be in cache, as the first consistent-hashed secondary parent will be the
primary parent in its own cachegroup and therefore receive requests for that
object from clients near it [...]
Additionally, :term:`Delivery Service` :ref:`Profiles <ds-profile>` can have
special Parameters with the :ref:`parameter-name` "mso.parent_retry" to
:ref:`multi-site-origin-qht`.
diff --git a/lib/go-atscfg/meta.go b/lib/go-atscfg/meta.go
index c7b7719..ec605df 100644
--- a/lib/go-atscfg/meta.go
+++ b/lib/go-atscfg/meta.go
@@ -437,6 +437,7 @@ func requiredFiles8() []string {
"plugin.config",
"records.config",
"remap.config",
+ "ssl_server_name.yaml",
"storage.config",
"volume.config",
}
@@ -454,6 +455,7 @@ func requiredFiles9() []string {
"plugin.config",
"records.config",
"remap.config",
+ "sni.yaml",
"storage.config",
"volume.config",
}
diff --git a/lib/go-atscfg/meta_test.go b/lib/go-atscfg/meta_test.go
index 70d791f..5d57249 100644
--- a/lib/go-atscfg/meta_test.go
+++ b/lib/go-atscfg/meta_test.go
@@ -167,6 +167,11 @@ func TestMakeMetaConfig(t *testing.T) {
t.Errorf("expected location '%v', actual '%v'",
expected, cf.Path)
}
},
+ "ssl_server_name.yaml": func(cf CfgMeta) {
+ if expected := cfgPath; cf.Path != expected {
+ t.Errorf("expected location '%v', actual '%v'",
expected, cf.Path)
+ }
+ },
}
for _, cfgFile := range cfg {
diff --git a/lib/go-atscfg/remapdotconfig.go b/lib/go-atscfg/remapdotconfig.go
index f2e448b..4ac9c9f 100644
--- a/lib/go-atscfg/remapdotconfig.go
+++ b/lib/go-atscfg/remapdotconfig.go
@@ -233,33 +233,39 @@ func getServerConfigRemapDotConfigForEdge(
textLines := []string{}
for _, ds := range dses {
- for _, dsRegex := range
dsRegexes[tc.DeliveryServiceName(*ds.XMLID)] {
- if
!hasRequiredCapabilities(serverCapabilities[*server.ID],
dsRequiredCapabilities[*ds.ID]) {
- continue
- }
+ if !hasRequiredCapabilities(serverCapabilities[*server.ID],
dsRequiredCapabilities[*ds.ID]) {
+ continue
+ }
- topology, hasTopology :=
nameTopologies[TopologyName(*ds.Topology)]
- if *ds.Topology != "" && hasTopology {
- topoIncludesServer, err :=
topologyIncludesServerNullable(topology, server)
- if err != nil {
- return "", warnings,
errors.New("getting topology server inclusion: " + err.Error())
- }
- if !topoIncludesServer {
- continue
- }
+ topology, hasTopology :=
nameTopologies[TopologyName(*ds.Topology)]
+ if *ds.Topology != "" && hasTopology {
+ topoIncludesServer, err :=
topologyIncludesServerNullable(topology, server)
+ if err != nil {
+ return "", warnings, errors.New("getting
topology server inclusion: " + err.Error())
}
- remapText := ""
- if *ds.Type == tc.DSTypeAnyMap {
- if ds.RemapText == nil {
- warnings = append(warnings, "ds
'"+*ds.XMLID+"' is ANY_MAP, but has no remap text - skipping")
- continue
- }
- remapText = *ds.RemapText + "\n"
- textLines = append(textLines, remapText)
+ if !topoIncludesServer {
continue
}
+ }
+ remapText := ""
+ if *ds.Type == tc.DSTypeAnyMap {
+ if ds.RemapText == nil {
+ warnings = append(warnings, "ds '"+*ds.XMLID+"'
is ANY_MAP, but has no remap text - skipping")
+ continue
+ }
+ remapText = *ds.RemapText + "\n"
+ textLines = append(textLines, remapText)
+ continue
+ }
+
+ requestFQDNs, err := getDSRequestFQDNs(&ds,
dsRegexes[tc.DeliveryServiceName(*ds.XMLID)], server, cdnDomain)
+ if err != nil {
+ warnings = append(warnings, "error getting ds
'"+*ds.XMLID+"' request fqdns, skipping! Error: "+err.Error())
+ continue
+ }
- remapLines, err := makeEdgeDSDataRemapLines(ds,
dsRegex, server, cdnDomain)
+ for _, requestFQDN := range requestFQDNs {
+ remapLines, err := makeEdgeDSDataRemapLines(ds,
requestFQDN, server, cdnDomain)
if err != nil {
warnings = append(warnings, "DS '"+*ds.XMLID+"'
- skipping! : "+err.Error())
continue
@@ -271,7 +277,7 @@ func getServerConfigRemapDotConfigForEdge(
profilecacheKeyConfigParams =
profilesCacheKeyConfigParams[*ds.ProfileID]
}
remapWarns := []string{}
- remapText, remapWarns, err =
buildEdgeRemapLine(cacheURLConfigParams, atsMajorVersion, server,
serverPackageParamData, remapText, ds, dsRegex, line.From, line.To,
profilecacheKeyConfigParams, cacheGroups, nameTopologies)
+ remapText, remapWarns, err =
buildEdgeRemapLine(cacheURLConfigParams, atsMajorVersion, server,
serverPackageParamData, remapText, ds, line.From, line.To,
profilecacheKeyConfigParams, cacheGroups, nameTopologies)
warnings = append(warnings, remapWarns...)
if err != nil {
return "", warnings, err
@@ -281,8 +287,8 @@ func getServerConfigRemapDotConfigForEdge(
}
remapText += "\n"
}
- textLines = append(textLines, remapText)
}
+ textLines = append(textLines, remapText)
}
text := header
@@ -301,7 +307,6 @@ func buildEdgeRemapLine(
pData map[string]string,
text string,
ds DeliveryService,
- dsRegex tc.DeliveryServiceRegex,
mapFrom string,
mapTo string,
cacheKeyConfigParams map[string]string,
@@ -441,56 +446,31 @@ type remapLine struct {
// Returns nil, if the given server and ds have no remap lines, i.e. the DS
match is not a host regex, or has no origin FQDN.
func makeEdgeDSDataRemapLines(
ds DeliveryService,
- dsRegex tc.DeliveryServiceRegex,
+ requestFQDN string,
+ // dsRegex tc.DeliveryServiceRegex,
server *Server,
cdnDomain string,
) ([]remapLine, error) {
- if tc.DSMatchType(dsRegex.Type) != tc.DSMatchTypeHostRegex ||
ds.OrgServerFQDN == nil || *ds.OrgServerFQDN == "" {
- return nil, nil
- }
- if dsRegex.Pattern == "" {
- return nil, errors.New("ds missing regex pattern")
- }
if ds.Protocol == nil {
- return nil, errors.New("ds missing protocol")
- }
- if cdnDomain == "" {
- return nil, errors.New("ds missing domain")
+ return nil, errors.New("ds had nil protocol")
}
remapLines := []remapLine{}
- hostRegex := dsRegex.Pattern
mapTo := *ds.OrgServerFQDN + "/"
- mapFromHTTP := "http://" + hostRegex + "/"
- mapFromHTTPS := "https://" + hostRegex + "/"
- if strings.HasSuffix(hostRegex, `.*`) {
- re := hostRegex
- re = strings.Replace(re, `\`, ``, -1)
- re = strings.Replace(re, `.*`, ``, -1)
-
- hName := "__http__"
- if ds.Type.IsDNS() {
- if ds.RoutingName == nil {
- return nil, errors.New("ds is dns, but missing
routing name")
- }
- hName = *ds.RoutingName
- }
-
- portStr := ""
- if hName == "__http__" && server.TCPPort != nil &&
*server.TCPPort > 0 && *server.TCPPort != 80 {
- portStr = ":" + strconv.Itoa(*server.TCPPort)
- }
-
- httpsPortStr := ""
- if hName == "__http__" && server.HTTPSPort != nil &&
*server.HTTPSPort > 0 && *server.HTTPSPort != 443 {
- httpsPortStr = ":" + strconv.Itoa(*server.HTTPSPort)
- }
+ portStr := ""
+ if !ds.Type.IsDNS() && server.TCPPort != nil && *server.TCPPort > 0 &&
*server.TCPPort != 80 {
+ portStr = ":" + strconv.Itoa(*server.TCPPort)
+ }
- mapFromHTTP = "http://" + hName + re + cdnDomain + portStr + "/"
- mapFromHTTPS = "https://" + hName + re + cdnDomain +
httpsPortStr + "/"
+ httpsPortStr := ""
+ if !ds.Type.IsDNS() && server.HTTPSPort != nil && *server.HTTPSPort > 0
&& *server.HTTPSPort != 443 {
+ httpsPortStr = ":" + strconv.Itoa(*server.HTTPSPort)
}
+ mapFromHTTP := "http://" + requestFQDN + portStr + "/"
+ mapFromHTTPS := "https://" + requestFQDN + httpsPortStr + "/"
+
if *ds.Protocol == tc.DSProtocolHTTP || *ds.Protocol ==
tc.DSProtocolHTTPAndHTTPS {
remapLines = append(remapLines, remapLine{From: mapFromHTTP,
To: mapTo})
}
@@ -715,3 +695,47 @@ func (ks keyVals) Less(i, j int) bool {
}
return ks[i].Val < ks[j].Val
}
+
+// getDSRequestFQDNs returns the FQDNs that clients will request from the edge.
+func getDSRequestFQDNs(ds *DeliveryService, regexes []tc.DeliveryServiceRegex,
server *Server, cdnDomain string) ([]string, error) {
+ if server.HostName == nil {
+ return nil, errors.New("server missing hostname")
+ }
+
+ fqdns := []string{}
+ for _, dsRegex := range regexes {
+ if tc.DSMatchType(dsRegex.Type) != tc.DSMatchTypeHostRegex ||
ds.OrgServerFQDN == nil || *ds.OrgServerFQDN == "" {
+ continue
+ }
+ if dsRegex.Pattern == "" {
+ return nil, errors.New("ds missing regex pattern")
+ }
+ if ds.Protocol == nil {
+ return nil, errors.New("ds missing protocol")
+ }
+ if cdnDomain == "" {
+ return nil, errors.New("ds missing domain")
+ }
+
+ hostRegex := dsRegex.Pattern
+ fqdn := hostRegex
+
+ if strings.HasSuffix(hostRegex, `.*`) {
+ re := hostRegex
+ re = strings.Replace(re, `\`, ``, -1)
+ re = strings.Replace(re, `.*`, ``, -1)
+
+ hName := *server.HostName
+ if ds.Type.IsDNS() {
+ if ds.RoutingName == nil {
+ return nil, errors.New("ds is dns, but
missing routing name")
+ }
+ hName = *ds.RoutingName
+ }
+
+ fqdn = hName + re + cdnDomain
+ }
+ fqdns = append(fqdns, fqdn)
+ }
+ return fqdns, nil
+}
diff --git a/lib/go-atscfg/remapdotconfig_test.go
b/lib/go-atscfg/remapdotconfig_test.go
index d110139..962a19f 100644
--- a/lib/go-atscfg/remapdotconfig_test.go
+++ b/lib/go-atscfg/remapdotconfig_test.go
@@ -1896,7 +1896,7 @@ func TestMakeRemapDotConfigEdgeMissingRemapData(t
*testing.T) {
tc.DeliveryServiceRegex{
Type:
string(tc.DSMatchTypeHeaderRegex),
SetNumber: 0,
- Pattern: "myregexpattern2",
+ Pattern: "myregexpattern3",
},
},
},
@@ -1906,7 +1906,7 @@ func TestMakeRemapDotConfigEdgeMissingRemapData(t
*testing.T) {
tc.DeliveryServiceRegex{
Type: "",
SetNumber: 0,
- Pattern: "myregexpattern2",
+ Pattern: "myregexpattern4",
},
},
},
@@ -1916,7 +1916,7 @@ func TestMakeRemapDotConfigEdgeMissingRemapData(t
*testing.T) {
tc.DeliveryServiceRegex{
Type: "nonexistenttype",
SetNumber: 0,
- Pattern: "myregexpattern2",
+ Pattern: "myregexpattern5",
},
},
},
@@ -1926,7 +1926,7 @@ func TestMakeRemapDotConfigEdgeMissingRemapData(t
*testing.T) {
tc.DeliveryServiceRegex{
Type:
string(tc.DSMatchTypeHostRegex),
SetNumber: 0,
- Pattern: "myregexpattern2",
+ Pattern: "myregexpattern6",
},
},
},
@@ -1936,7 +1936,7 @@ func TestMakeRemapDotConfigEdgeMissingRemapData(t
*testing.T) {
tc.DeliveryServiceRegex{
Type:
string(tc.DSMatchTypeHostRegex),
SetNumber: 0,
- Pattern: "myregexpattern2",
+ Pattern: "myregexpattern7",
},
},
},
diff --git a/lib/go-atscfg/snidotyaml.go b/lib/go-atscfg/snidotyaml.go
new file mode 100644
index 0000000..762ebde
--- /dev/null
+++ b/lib/go-atscfg/snidotyaml.go
@@ -0,0 +1,129 @@
+package atscfg
+
+/*
+ * 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 (
+ "strconv"
+ "strings"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+const SNIDotYAMLFileName = "sni.yaml"
+
+const ContentTypeSNIDotYAML = ContentTypeYAML
+const LineCommentSNIDotYAML = LineCommentYAML
+
+// SNIDotYAMLOpts contains settings to configure sni.yaml generation options.
+type SNIDotYAMLOpts struct {
+ // VerboseComments is whether to add informative comments to the
generated file, about what was generated and why.
+ // Note this does not include the header comment, which is configured
separately with HdrComment.
+ // These comments are human-readable and not guaranteed to be
consistent between versions. Automating anything based on them is strongly
discouraged.
+ VerboseComments bool
+
+ // HdrComment is the header comment to include at the beginning of the
file.
+ // This should be the text desired, without comment syntax (like # or
//). The file's comment syntax will be added.
+ // To omit the header comment, pass the empty string.
+ HdrComment string
+
+ // DefaultTLSVersions is the list of TLS versions to enable on delivery
services with no Parameter.
+ DefaultTLSVersions []TLSVersion
+
+ // DefaultEnableH2 is whether to disable H2 on delivery services with
no Parameter.
+ DefaultEnableH2 bool
+}
+
+func MakeSNIDotYAML(
+ server *Server,
+ dses []DeliveryService,
+ dss []tc.DeliveryServiceServer,
+ dsRegexArr []tc.DeliveryServiceRegexes,
+ tcParentConfigParams []tc.Parameter,
+ cdn *tc.CDN,
+ topologies []tc.Topology,
+ cacheGroupArr []tc.CacheGroupNullable,
+ serverCapabilities map[int]map[ServerCapability]struct{},
+ dsRequiredCapabilities map[int]map[ServerCapability]struct{},
+ opt SNIDotYAMLOpts,
+) (Cfg, error) {
+ if len(opt.DefaultTLSVersions) == 0 {
+ opt.DefaultTLSVersions = DefaultDefaultTLSVersions
+ }
+
+ sslDatas, warnings, err := GetServerSSLData(
+ server,
+ dses,
+ dss,
+ dsRegexArr,
+ tcParentConfigParams,
+ cdn,
+ topologies,
+ cacheGroupArr,
+ serverCapabilities,
+ dsRequiredCapabilities,
+ opt.DefaultTLSVersions,
+ opt.DefaultEnableH2,
+ )
+ if err != nil {
+ return Cfg{}, makeErr(warnings, "getting ssl data:
"+err.Error())
+ }
+
+ txt := ""
+ if opt.HdrComment != "" {
+ txt += makeHdrComment(opt.HdrComment)
+ }
+
+ txt += `sni:` + "\n"
+
+ seenFQDNs := map[string]struct{}{}
+
+ for _, sslData := range sslDatas {
+ tlsVersionsATS := []string{}
+ for _, tlsVersion := range sslData.TLSVersions {
+ tlsVersionsATS = append(tlsVersionsATS,
`'`+tlsVersionsToATS[tlsVersion]+`'`)
+ }
+
+ for _, requestFQDN := range sslData.RequestFQDNs {
+ // TODO let active DSes take precedence?
+ if _, ok := seenFQDNs[requestFQDN]; ok {
+ warnings = append(warnings, "ds
'"+sslData.DSName+"' had the same FQDN '"+requestFQDN+"' as some other delivery
service, skipping!")
+ continue
+ }
+ seenFQDNs[requestFQDN] = struct{}{}
+
+ dsTxt := "\n"
+ if opt.VerboseComments {
+ dsTxt += LineCommentYAML + ` ds '` +
sslData.DSName + `'` + "\n"
+ }
+ dsTxt += `- fqdn: '` + requestFQDN + `'`
+ dsTxt += "\n" + ` disable_h2: ` +
strconv.FormatBool(!sslData.EnableH2)
+ dsTxt += "\n" + ` valid_tls_versions_in: [` +
strings.Join(tlsVersionsATS, `,`) + `]`
+
+ txt += dsTxt + "\n"
+ }
+ }
+
+ return Cfg{
+ Text: txt,
+ ContentType: ContentTypeSNIDotYAML,
+ LineComment: LineCommentSNIDotYAML,
+ Warnings: warnings,
+ }, nil
+}
diff --git a/lib/go-atscfg/sslservernamedotyaml.go
b/lib/go-atscfg/sslservernamedotyaml.go
new file mode 100644
index 0000000..7286c80
--- /dev/null
+++ b/lib/go-atscfg/sslservernamedotyaml.go
@@ -0,0 +1,383 @@
+package atscfg
+
+/*
+ * 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 (
+ "errors"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+const ContentTypeYAML = "application/yaml; charset=us-ascii" // Note YAML has
no IANA standard mime type. This is one of several common usages, and is likely
to be the standardized value. If you're reading this, please check IANA to see
if YAML has been added, and change this to the IANA definition if so. Also note
we include 'charset=us-ascii' because YAML is commonly UTF-8, but ATS is likely
to be unable to handle UTF.
+const LineCommentYAML = LineCommentHash
+
+const SSLServerNameYAMLFileName = "ssl_server_name.yaml"
+
+const ContentTypeSSLServerNameYAML = ContentTypeYAML
+const LineCommentSSLServerNameYAML = LineCommentYAML
+
+// DefaultDefaultEnableH2 is whether Delivery Services will have HTTP/2
enabled by default if they don't have an explicit Parameter, and no Opt is
passed to the Make func.
+// We disable by default, to prevent potentially enabling broken clients.
+const DefaultDefaultEnableH2 = false
+
+type TLSVersion string
+
+const TLSVersion1p0 = TLSVersion("1.0")
+const TLSVersion1p1 = TLSVersion("1.1")
+const TLSVersion1p2 = TLSVersion("1.2")
+const TLSVersion1p3 = TLSVersion("1.3")
+const TLSVersionInvalid = TLSVersion("")
+
+// StringToTLSVersion returns the TLSVersion or TLSVersionInvalid if the
string is not a TLS Version enum.
+func StringToTLSVersion(st string) TLSVersion {
+ switch TLSVersion(st) {
+ case TLSVersion1p0:
+ return TLSVersion1p0
+ case TLSVersion1p1:
+ return TLSVersion1p1
+ case TLSVersion1p2:
+ return TLSVersion1p2
+ case TLSVersion1p3:
+ return TLSVersion1p3
+ }
+ return TLSVersionInvalid
+}
+
+// tlsVersionsToATS maps TLS version strings to the string used by ATS in
ssl_server_name.yaml.
+var tlsVersionsToATS = map[TLSVersion]string{
+ TLSVersion1p0: "TLSv1",
+ TLSVersion1p1: "TLSv1_1",
+ TLSVersion1p2: "TLSv1_2",
+ TLSVersion1p3: "TLSv1_3",
+}
+
+const SSLServerNameYAMLParamEnableH2 = "enable_h2"
+const SSLServerNameYAMLParamTLSVersions = "tls_versions"
+
+// DefaultDefaultTLSVersions is the list of TLS versions to enable by default,
if no Parameter exists and no Opt is passed to the Make func.
+// By default, we enable all, even insecure versions.
+// As a CDN, Traffic Control assumes it should not break clients, and it's the
client's responsibility to use secure protocols.
+// Note this enables certain downgrade attacks. Operators or tenants concerned
about these attacks should disable older TLS versions.
+var DefaultDefaultTLSVersions = []TLSVersion{
+ TLSVersion1p0,
+ TLSVersion1p1,
+ TLSVersion1p2,
+ TLSVersion1p3,
+}
+
+// SSLServerNameYAMLOpts contains settings to configure ssl_server_name.yaml
generation options.
+type SSLServerNameYAMLOpts struct {
+ // VerboseComments is whether to add informative comments to the
generated file, about what was generated and why.
+ // Note this does not include the header comment, which is configured
separately with HdrComment.
+ // These comments are human-readable and not guaranteed to be
consistent between versions. Automating anything based on them is strongly
discouraged.
+ VerboseComments bool
+
+ // HdrComment is the header comment to include at the beginning of the
file.
+ // This should be the text desired, without comment syntax (like # or
//). The file's comment syntax will be added.
+ // To omit the header comment, pass the empty string.
+ HdrComment string
+
+ // DefaultTLSVersions is the list of TLS versions to enable on delivery
services with no Parameter.
+ DefaultTLSVersions []TLSVersion
+
+ // DefaultEnableH2 is whether to disable H2 on delivery services with
no Parameter.
+ DefaultEnableH2 bool
+}
+
+func MakeSSLServerNameYAML(
+ server *Server,
+ dses []DeliveryService,
+ dss []tc.DeliveryServiceServer,
+ dsRegexArr []tc.DeliveryServiceRegexes,
+ tcParentConfigParams []tc.Parameter,
+ cdn *tc.CDN,
+ topologies []tc.Topology,
+ cacheGroupArr []tc.CacheGroupNullable,
+ serverCapabilities map[int]map[ServerCapability]struct{},
+ dsRequiredCapabilities map[int]map[ServerCapability]struct{},
+ opt SSLServerNameYAMLOpts,
+) (Cfg, error) {
+ if len(opt.DefaultTLSVersions) == 0 {
+ opt.DefaultTLSVersions = DefaultDefaultTLSVersions
+ }
+
+ sslDatas, warnings, err := GetServerSSLData(
+ server,
+ dses,
+ dss,
+ dsRegexArr,
+ tcParentConfigParams,
+ cdn,
+ topologies,
+ cacheGroupArr,
+ serverCapabilities,
+ dsRequiredCapabilities,
+ opt.DefaultTLSVersions,
+ opt.DefaultEnableH2,
+ )
+
+ if err != nil {
+ return Cfg{}, makeErr(warnings, "getting ssl data:
"+err.Error())
+ }
+
+ txt := ""
+ if opt.HdrComment != "" {
+ txt += makeHdrComment(opt.HdrComment)
+ }
+
+ seenFQDNs := map[string]struct{}{}
+
+ for _, sslData := range sslDatas {
+ tlsVersionsATS := []string{}
+ for _, tlsVersion := range sslData.TLSVersions {
+ tlsVersionsATS = append(tlsVersionsATS,
`'`+tlsVersionsToATS[tlsVersion]+`'`)
+ }
+
+ for _, requestFQDN := range sslData.RequestFQDNs {
+ // TODO let active DSes take precedence?
+ if _, ok := seenFQDNs[requestFQDN]; ok {
+ warnings = append(warnings, "ds
'"+sslData.DSName+"' had the same FQDN '"+requestFQDN+"' as some other delivery
service, skipping!")
+ continue
+ }
+ seenFQDNs[requestFQDN] = struct{}{}
+
+ dsTxt := "\n"
+ if opt.VerboseComments {
+ dsTxt += LineCommentYAML + ` ds '` +
sslData.DSName + `'` + "\n"
+ }
+ dsTxt += `- fqdn: '` + requestFQDN + `'`
+ dsTxt += "\n" + ` disable_h2: ` +
strconv.FormatBool(!sslData.EnableH2)
+ dsTxt += "\n" + ` valid_tls_versions_in: [` +
strings.Join(tlsVersionsATS, `,`) + `]`
+
+ txt += dsTxt + "\n"
+ }
+
+ }
+
+ return Cfg{
+ Text: txt,
+ ContentType: ContentTypeSSLServerNameYAML,
+ LineComment: LineCommentSSLServerNameYAML,
+ Warnings: warnings,
+ }, nil
+}
+
+// SSLData has the DS data needed for both sni.yaml (ATS 9+) and
ssl_server_name.yaml (ATS 8).
+type SSLData struct {
+ DSName string
+ RequestFQDNs []string
+ EnableH2 bool
+ TLSVersions []TLSVersion
+}
+
+// GetServerSSLData gets the SSLData for all Delivery Services assigned to the
given Server, any warnings, and any error.
+func GetServerSSLData(
+ server *Server,
+ dses []DeliveryService,
+ dss []tc.DeliveryServiceServer,
+ dsRegexArr []tc.DeliveryServiceRegexes,
+ tcParentConfigParams []tc.Parameter,
+ cdn *tc.CDN,
+ topologies []tc.Topology,
+ cacheGroupArr []tc.CacheGroupNullable,
+ serverCapabilities map[int]map[ServerCapability]struct{},
+ dsRequiredCapabilities map[int]map[ServerCapability]struct{},
+ defaultTLSVersions []TLSVersion,
+ defaultEnableH2 bool,
+) ([]SSLData, []string, error) {
+ warnings := []string{}
+
+ if server.Profile == nil {
+ return nil, warnings, errors.New("this server missing Profile")
+ }
+
+ dsRegexes := makeDSRegexMap(dsRegexArr)
+
+ parentConfigParamsWithProfiles, err :=
tcParamsToParamsWithProfiles(tcParentConfigParams)
+ if err != nil {
+ warnings = append(warnings, "error getting profiles from
Traffic Ops Parameters, Parameters will not be considered for generation! :
"+err.Error())
+ parentConfigParamsWithProfiles = []parameterWithProfiles{}
+ }
+
+ profileParentConfigParams := map[string]map[string]string{} //
map[profileName][paramName]paramVal
+ for _, param := range parentConfigParamsWithProfiles {
+ for _, profile := range param.ProfileNames {
+ if _, ok := profileParentConfigParams[profile]; !ok {
+ profileParentConfigParams[profile] =
map[string]string{}
+ }
+ profileParentConfigParams[profile][param.Name] =
param.Value
+ }
+ }
+
+ cacheGroups, err := makeCGMap(cacheGroupArr)
+ if err != nil {
+ return nil, warnings, errors.New("making cachegroup map: " +
err.Error())
+ }
+
+ nameTopologies := makeTopologyNameMap(topologies)
+
+ sort.Sort(dsesSortByName(dses))
+
+ sslDatas := []SSLData{}
+
+ for _, ds := range dses {
+ hasDS, err := dsUsesServer(&ds, server, dss, nameTopologies,
cacheGroups, serverCapabilities, dsRequiredCapabilities)
+ if err != nil {
+ warnings = append(warnings, "error checking if ds uses
this server, considering false! Error: "+err.Error())
+ continue
+ }
+ if !hasDS {
+ continue
+ }
+
+ dsParentConfigParams := map[string]string{}
+ if ds.ProfileName != nil {
+ dsParentConfigParams =
profileParentConfigParams[*ds.ProfileName]
+ }
+
+ requestFQDNs, err := getDSRequestFQDNs(&ds,
dsRegexes[tc.DeliveryServiceName(*ds.XMLID)], server, cdn.DomainName)
+ if err != nil {
+ warnings = append(warnings, "error getting ds
'"+*ds.XMLID+"' request fqdns, skipping! Error: "+err.Error())
+ continue
+ }
+
+ enableH2 := defaultEnableH2
+ tlsVersions := defaultTLSVersions
+
+ paramValEnableH2 :=
dsParentConfigParams[SSLServerNameYAMLParamEnableH2]
+ paramValEnableH2 = strings.TrimSpace(paramValEnableH2)
+ paramValEnableH2 = strings.ToLower(paramValEnableH2)
+
+ if paramValEnableH2 != "" {
+ enableH2 = strings.HasPrefix(paramValEnableH2, "t") ||
strings.HasPrefix(paramValEnableH2, "y")
+ }
+
+ paramValTLSVersions :=
dsParentConfigParams[SSLServerNameYAMLParamTLSVersions]
+ paramValTLSVersions = strings.Replace(paramValTLSVersions, " ",
"", -1)
+ paramValTLSVersions = strings.TrimSpace(paramValTLSVersions)
+
+ paramTLSVersions := []TLSVersion{}
+ if paramValTLSVersions != "" {
+ // Allow delimiting with commas, semicolons, spaces, or
newlines.
+ delim := ","
+ if !strings.Contains(paramValTLSVersions, delim) {
+ delim = ";"
+ }
+ if !strings.Contains(paramValTLSVersions, delim) {
+ delim = " "
+ }
+ if !strings.Contains(paramValTLSVersions, delim) {
+ delim = "\n"
+ }
+
+ tlsVersionsParamArr :=
strings.Split(paramValTLSVersions, delim)
+ for _, tlsVersion := range tlsVersionsParamArr {
+ if _, ok :=
tlsVersionsToATS[TLSVersion(tlsVersion)]; !ok {
+ warnings = append(warnings, "ds
'"+*ds.XMLID+"' had unknown "+SSLServerNameYAMLParamTLSVersions+" parameter
'"+tlsVersion+"' - ignoring!")
+ continue
+ }
+ paramTLSVersions = append(paramTLSVersions,
TLSVersion(tlsVersion))
+ }
+ }
+
+ if len(paramTLSVersions) != 0 {
+ tlsVersions = paramTLSVersions
+ }
+
+ sslDatas = append(sslDatas, SSLData{
+ DSName: *ds.XMLID,
+ RequestFQDNs: requestFQDNs,
+ EnableH2: enableH2,
+ TLSVersions: tlsVersions,
+ })
+ }
+
+ return sslDatas, warnings, nil
+}
+
+func dsUsesServer(
+ ds *DeliveryService,
+ server *Server,
+ dss []tc.DeliveryServiceServer,
+ nameTopologies map[TopologyName]tc.Topology,
+ cacheGroups map[tc.CacheGroupName]tc.CacheGroupNullable,
+ serverCapabilities map[int]map[ServerCapability]struct{},
+ dsRequiredCapabilities map[int]map[ServerCapability]struct{},
+) (bool, error) {
+ if ds.XMLID == nil || *ds.XMLID == "" {
+ return false, errors.New("ds missing xmlId")
+ } else if ds.ID == nil {
+ return false, errors.New("ds missing id")
+ } else if server.ID == nil {
+ return false, errors.New("server missing id")
+ } else if ds.Type == nil {
+ return false, errors.New("ds missing type")
+ }
+
+ if !hasRequiredCapabilities(serverCapabilities[*server.ID],
dsRequiredCapabilities[*ds.ID]) {
+ return false, nil
+ }
+
+ serverParentCGData, err := getParentCacheGroupData(server, cacheGroups)
+ if err != nil {
+ return false, errors.New("getting server parent cachegroup
data: " + err.Error())
+ }
+ cacheIsTopLevel := isTopLevelCache(serverParentCGData)
+
+ if !cacheIsTopLevel && (ds.Topology == nil || *ds.Topology == "") {
+ if !dsAssignedServer(*ds.ID, *server.ID, dss) {
+ return false, nil
+ }
+ }
+
+ if ds.Topology != nil && *ds.Topology != "" {
+ topology, ok := nameTopologies[TopologyName(*ds.Topology)]
+ if !ok {
+ return false, errors.New("ds topology '" + *ds.Topology
+ "' not found in topologies")
+ }
+
+ serverPlacement, err :=
getTopologyPlacement(tc.CacheGroupName(*server.Cachegroup), topology,
cacheGroups, ds)
+ if err != nil {
+ return false, errors.New("getting topology placement: "
+ err.Error())
+ }
+ if !serverPlacement.InTopology {
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
+
+// dsAssignedServer returns whether the Delivery Service Servers has an
assignment between the server and the DS.
+// Does not check Topologies, or parentage. Only useful for Edges and
pre-topology DSS.
+func dsAssignedServer(dsID int, serverID int, dsses
[]tc.DeliveryServiceServer) bool {
+ for _, dss := range dsses {
+ if dss.Server == nil || dss.DeliveryService == nil {
+ continue // TODO warn?
+ }
+ if *dss.Server == serverID && *dss.DeliveryService == dsID {
+ return true
+ }
+ }
+ return false
+}
diff --git a/lib/go-atscfg/sslservernamedotyaml_test.go
b/lib/go-atscfg/sslservernamedotyaml_test.go
new file mode 100644
index 0000000..4c0bcb7
--- /dev/null
+++ b/lib/go-atscfg/sslservernamedotyaml_test.go
@@ -0,0 +1,411 @@
+package atscfg
+
+/*
+ * 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 (
+ "strings"
+ "testing"
+
+ "github.com/apache/trafficcontrol/lib/go-tc"
+ "github.com/apache/trafficcontrol/lib/go-util"
+)
+
+func TestMakeSSLServerNameYAML(t *testing.T) {
+ opts := SSLServerNameYAMLOpts{VerboseComments: false, HdrComment:
"myHeaderComment"}
+
+ ds0 := makeParentDS()
+ ds0Type := tc.DSTypeHTTP
+ ds0.Type = &ds0Type
+ ds0.Protocol = util.IntPtr(int(tc.DSProtocolHTTPAndHTTPS))
+ ds0.QStringIgnore =
util.IntPtr(int(tc.QStringIgnoreUseInCacheKeyAndPassUp))
+ ds0.OrgServerFQDN = util.StrPtr("http://ds0.example.net")
+
+ ds1 := makeParentDS()
+ ds1.ID = util.IntPtr(43)
+ ds1Type := tc.DSTypeDNS
+ ds1.Type = &ds1Type
+ ds1.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreDrop))
+ ds1.OrgServerFQDN = util.StrPtr("http://ds1.example.net")
+
+ dses := []DeliveryService{*ds0, *ds1}
+
+ parentConfigParams := []tc.Parameter{
+ tc.Parameter{
+ Name: ParentConfigParamQStringHandling,
+ ConfigFile: "parent.config",
+ Value: "myQStringHandlingParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamAlgorithm,
+ ConfigFile: "parent.config",
+ Value: tc.AlgorithmConsistentHash,
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamQString,
+ ConfigFile: "parent.config",
+ Value: "myQstringParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ }
+
+ server := makeTestParentServer()
+
+ mid0 := makeTestParentServer()
+ mid0.Cachegroup = util.StrPtr("midCG")
+ mid0.HostName = util.StrPtr("mymid0")
+ mid0.ID = util.IntPtr(45)
+ setIP(mid0, "192.168.2.2")
+
+ mid1 := makeTestParentServer()
+ mid1.Cachegroup = util.StrPtr("midCG")
+ mid1.HostName = util.StrPtr("mymid1")
+ mid1.ID = util.IntPtr(46)
+ setIP(mid1, "192.168.2.3")
+
+ topologies := []tc.Topology{}
+ serverCapabilities := map[int]map[ServerCapability]struct{}{}
+ dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{}
+
+ eCG := &tc.CacheGroupNullable{}
+ eCG.Name = server.Cachegroup
+ eCG.ID = server.CachegroupID
+ eCG.ParentName = mid0.Cachegroup
+ eCG.ParentCachegroupID = mid0.CachegroupID
+ eCGType := tc.CacheGroupEdgeTypeName
+ eCG.Type = &eCGType
+
+ mCG := &tc.CacheGroupNullable{}
+ mCG.Name = mid0.Cachegroup
+ mCG.ID = mid0.CachegroupID
+ mCGType := tc.CacheGroupMidTypeName
+ mCG.Type = &mCGType
+
+ cgs := []tc.CacheGroupNullable{*eCG, *mCG}
+
+ dss := []tc.DeliveryServiceServer{
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds0.ID),
+ },
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds1.ID),
+ },
+ }
+ cdn := &tc.CDN{
+ DomainName: "cdndomain.example",
+ Name: "my-cdn-name",
+ }
+
+ dsr := []tc.DeliveryServiceRegexes{
+ tc.DeliveryServiceRegexes{
+ DSName: *ds0.XMLID,
+ Regexes: []tc.DeliveryServiceRegex{
+ tc.DeliveryServiceRegex{
+ Type:
string(tc.DSMatchTypeHostRegex),
+ SetNumber: 0,
+ Pattern: `.*\.ds0\..*`,
+ },
+ },
+ },
+ }
+
+ cfg, err := MakeSSLServerNameYAML(server, dses, dss, dsr,
parentConfigParams, cdn, topologies, cgs, serverCapabilities,
dsRequiredCapabilities, opts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ txt := cfg.Text
+
+ if !strings.Contains(txt, `fqdn: 'myserver.ds0.cdndomain.example'`) {
+ t.Errorf("expected ds0 fqdn, actual ''%+v'' warnings ''%+v''",
txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `disable_h2: true`) {
+ t.Errorf("expected h2 disabled for ds with no parameters,
actual ''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `['TLSv1','TLSv1_1','TLSv1_2','TLSv1_3']`) {
+ t.Errorf("expected all TLS versions for ds with no parameters,
actual ''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+}
+
+func TestMakeSSLServerNameYAMLParams(t *testing.T) {
+ opts := SSLServerNameYAMLOpts{VerboseComments: false, HdrComment:
"myHeaderComment"}
+
+ ds0 := makeParentDS()
+ ds0Type := tc.DSTypeHTTP
+ ds0.Type = &ds0Type
+ ds0.Protocol = util.IntPtr(int(tc.DSProtocolHTTPAndHTTPS))
+ ds0.ProfileName = util.StrPtr("ds0profile")
+ ds0.QStringIgnore =
util.IntPtr(int(tc.QStringIgnoreUseInCacheKeyAndPassUp))
+ ds0.OrgServerFQDN = util.StrPtr("http://ds0.example.net")
+
+ ds1 := makeParentDS()
+ ds1.ID = util.IntPtr(43)
+ ds1Type := tc.DSTypeDNS
+ ds1.Type = &ds1Type
+ ds1.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreDrop))
+ ds1.OrgServerFQDN = util.StrPtr("http://ds1.example.net")
+
+ dses := []DeliveryService{*ds0, *ds1}
+
+ parentConfigParams := []tc.Parameter{
+ tc.Parameter{
+ Name: ParentConfigParamQStringHandling,
+ ConfigFile: "parent.config",
+ Value: "myQStringHandlingParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamAlgorithm,
+ ConfigFile: "parent.config",
+ Value: tc.AlgorithmConsistentHash,
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamQString,
+ ConfigFile: "parent.config",
+ Value: "myQstringParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: SSLServerNameYAMLParamEnableH2,
+ ConfigFile: "parent.config",
+ Value: "true",
+ Profiles: []byte(`["ds0profile"]`),
+ },
+ tc.Parameter{
+ Name: SSLServerNameYAMLParamTLSVersions,
+ ConfigFile: "parent.config",
+ Value: "1.1,1.2",
+ Profiles: []byte(`["ds0profile"]`),
+ },
+ }
+
+ server := makeTestParentServer()
+
+ mid0 := makeTestParentServer()
+ mid0.Cachegroup = util.StrPtr("midCG")
+ mid0.HostName = util.StrPtr("mymid0")
+ mid0.ID = util.IntPtr(45)
+ setIP(mid0, "192.168.2.2")
+
+ mid1 := makeTestParentServer()
+ mid1.Cachegroup = util.StrPtr("midCG")
+ mid1.HostName = util.StrPtr("mymid1")
+ mid1.ID = util.IntPtr(46)
+ setIP(mid1, "192.168.2.3")
+
+ topologies := []tc.Topology{}
+ serverCapabilities := map[int]map[ServerCapability]struct{}{}
+ dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{}
+
+ eCG := &tc.CacheGroupNullable{}
+ eCG.Name = server.Cachegroup
+ eCG.ID = server.CachegroupID
+ eCG.ParentName = mid0.Cachegroup
+ eCG.ParentCachegroupID = mid0.CachegroupID
+ eCGType := tc.CacheGroupEdgeTypeName
+ eCG.Type = &eCGType
+
+ mCG := &tc.CacheGroupNullable{}
+ mCG.Name = mid0.Cachegroup
+ mCG.ID = mid0.CachegroupID
+ mCGType := tc.CacheGroupMidTypeName
+ mCG.Type = &mCGType
+
+ cgs := []tc.CacheGroupNullable{*eCG, *mCG}
+
+ dss := []tc.DeliveryServiceServer{
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds0.ID),
+ },
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds1.ID),
+ },
+ }
+ cdn := &tc.CDN{
+ DomainName: "cdndomain.example",
+ Name: "my-cdn-name",
+ }
+
+ dsr := []tc.DeliveryServiceRegexes{
+ tc.DeliveryServiceRegexes{
+ DSName: *ds0.XMLID,
+ Regexes: []tc.DeliveryServiceRegex{
+ tc.DeliveryServiceRegex{
+ Type:
string(tc.DSMatchTypeHostRegex),
+ SetNumber: 0,
+ Pattern: `.*\.ds0\..*`,
+ },
+ },
+ },
+ }
+
+ cfg, err := MakeSSLServerNameYAML(server, dses, dss, dsr,
parentConfigParams, cdn, topologies, cgs, serverCapabilities,
dsRequiredCapabilities, opts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ txt := cfg.Text
+
+ if !strings.Contains(txt, `fqdn: 'myserver.ds0.cdndomain.example'`) {
+ t.Errorf("expected ds0 fqdn, actual ''%+v'' warnings ''%+v''",
txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `disable_h2: false`) {
+ t.Errorf("expected h2 enabled for ds with parameter, actual
''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `['TLSv1_1','TLSv1_2']`) {
+ t.Errorf("expected TLS 1.1,1.2 for ds with parameters, actual
''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+}
+
+func TestMakeSSLServerNameYAMLParamInvalid(t *testing.T) {
+ opts := SSLServerNameYAMLOpts{VerboseComments: false, HdrComment:
"myHeaderComment"}
+
+ ds0 := makeParentDS()
+ ds0Type := tc.DSTypeHTTP
+ ds0.Type = &ds0Type
+ ds0.Protocol = util.IntPtr(int(tc.DSProtocolHTTPAndHTTPS))
+ ds0.ProfileName = util.StrPtr("ds0profile")
+ ds0.QStringIgnore =
util.IntPtr(int(tc.QStringIgnoreUseInCacheKeyAndPassUp))
+ ds0.OrgServerFQDN = util.StrPtr("http://ds0.example.net")
+
+ ds1 := makeParentDS()
+ ds1.ID = util.IntPtr(43)
+ ds1Type := tc.DSTypeDNS
+ ds1.Type = &ds1Type
+ ds1.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreDrop))
+ ds1.OrgServerFQDN = util.StrPtr("http://ds1.example.net")
+
+ dses := []DeliveryService{*ds0, *ds1}
+
+ parentConfigParams := []tc.Parameter{
+ tc.Parameter{
+ Name: ParentConfigParamQStringHandling,
+ ConfigFile: "parent.config",
+ Value: "myQStringHandlingParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamAlgorithm,
+ ConfigFile: "parent.config",
+ Value: tc.AlgorithmConsistentHash,
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: ParentConfigParamQString,
+ ConfigFile: "parent.config",
+ Value: "myQstringParam",
+ Profiles: []byte(`["serverprofile"]`),
+ },
+ tc.Parameter{
+ Name: SSLServerNameYAMLParamEnableH2,
+ ConfigFile: "parent.config",
+ Value: "true",
+ Profiles: []byte(`["ds0profile"]`),
+ },
+ tc.Parameter{
+ Name: SSLServerNameYAMLParamTLSVersions,
+ ConfigFile: "parent.config",
+ Value: "1.3,1.invalid,foo,bar,1.1", // invalid
params should warn and skip
+ Profiles: []byte(`["ds0profile"]`),
+ },
+ }
+
+ server := makeTestParentServer()
+
+ mid0 := makeTestParentServer()
+ mid0.Cachegroup = util.StrPtr("midCG")
+ mid0.HostName = util.StrPtr("mymid0")
+ mid0.ID = util.IntPtr(45)
+ setIP(mid0, "192.168.2.2")
+
+ mid1 := makeTestParentServer()
+ mid1.Cachegroup = util.StrPtr("midCG")
+ mid1.HostName = util.StrPtr("mymid1")
+ mid1.ID = util.IntPtr(46)
+ setIP(mid1, "192.168.2.3")
+
+ topologies := []tc.Topology{}
+ serverCapabilities := map[int]map[ServerCapability]struct{}{}
+ dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{}
+
+ eCG := &tc.CacheGroupNullable{}
+ eCG.Name = server.Cachegroup
+ eCG.ID = server.CachegroupID
+ eCG.ParentName = mid0.Cachegroup
+ eCG.ParentCachegroupID = mid0.CachegroupID
+ eCGType := tc.CacheGroupEdgeTypeName
+ eCG.Type = &eCGType
+
+ mCG := &tc.CacheGroupNullable{}
+ mCG.Name = mid0.Cachegroup
+ mCG.ID = mid0.CachegroupID
+ mCGType := tc.CacheGroupMidTypeName
+ mCG.Type = &mCGType
+
+ cgs := []tc.CacheGroupNullable{*eCG, *mCG}
+
+ dss := []tc.DeliveryServiceServer{
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds0.ID),
+ },
+ tc.DeliveryServiceServer{
+ Server: util.IntPtr(*server.ID),
+ DeliveryService: util.IntPtr(*ds1.ID),
+ },
+ }
+ cdn := &tc.CDN{
+ DomainName: "cdndomain.example",
+ Name: "my-cdn-name",
+ }
+
+ dsr := []tc.DeliveryServiceRegexes{
+ tc.DeliveryServiceRegexes{
+ DSName: *ds0.XMLID,
+ Regexes: []tc.DeliveryServiceRegex{
+ tc.DeliveryServiceRegex{
+ Type:
string(tc.DSMatchTypeHostRegex),
+ SetNumber: 0,
+ Pattern: `.*\.ds0\..*`,
+ },
+ },
+ },
+ }
+
+ cfg, err := MakeSSLServerNameYAML(server, dses, dss, dsr,
parentConfigParams, cdn, topologies, cgs, serverCapabilities,
dsRequiredCapabilities, opts)
+ if err != nil {
+ t.Fatal(err)
+ }
+ txt := cfg.Text
+
+ if !strings.Contains(txt, `fqdn: 'myserver.ds0.cdndomain.example'`) {
+ t.Errorf("expected ds0 fqdn, actual ''%+v'' warnings ''%+v''",
txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `disable_h2: false`) {
+ t.Errorf("expected h2 enabled for ds with parameter, actual
''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+ if !strings.Contains(txt, `['TLSv1_3','TLSv1_1']`) {
+ t.Errorf("expected TLS 1.3,1.1 for ds with valid and invalid
parameter, actual ''%+v'' warnings ''%+v''", txt, cfg.Warnings)
+ }
+}
diff --git a/traffic_ops_ort/atstccfg/cfgfile/routing.go
b/traffic_ops_ort/atstccfg/cfgfile/routing.go
index f21f18d..01ef2de 100644
--- a/traffic_ops_ort/atstccfg/cfgfile/routing.go
+++ b/traffic_ops_ort/atstccfg/cfgfile/routing.go
@@ -96,6 +96,8 @@ var configFileLiteralFuncs = []ConfigFileLiteralFunc{
{"regex_revalidate.config", MakeRegexRevalidateDotConfig},
{"remap.config", MakeRemapDotConfig},
{"ssl_multicert.config", MakeSSLMultiCertDotConfig},
+ {"ssl_server_name.yaml", MakeSSLServerNameYAML},
+ {"sni.yaml", MakeSNIDotYAML},
{"storage.config", MakeStorageDotConfig},
{"sysctl.conf", MakeSysCtlDotConf},
{"volume.config", MakeVolumeDotConfig},
diff --git a/traffic_ops_ort/atstccfg/cfgfile/wrappers.go
b/traffic_ops_ort/atstccfg/cfgfile/wrappers.go
index b21875d..6d99bc8 100644
--- a/traffic_ops_ort/atstccfg/cfgfile/wrappers.go
+++ b/traffic_ops_ort/atstccfg/cfgfile/wrappers.go
@@ -109,6 +109,48 @@ func MakeLoggingDotYAML(toData *config.TOData, fileName
string, hdrCommentTxt st
return atscfg.MakeLoggingDotYAML(toData.Server, toData.ServerParams,
hdrCommentTxt)
}
+func MakeSSLServerNameYAML(toData *config.TOData, fileName string,
hdrCommentTxt string, cfg config.TCCfg) (atscfg.Cfg, error) {
+ return atscfg.MakeSSLServerNameYAML(
+ toData.Server,
+ toData.DeliveryServices,
+ toData.DeliveryServiceServers,
+ toData.DeliveryServiceRegexes,
+ toData.ParentConfigParams,
+ toData.CDN,
+ toData.Topologies,
+ toData.CacheGroups,
+ toData.ServerCapabilities,
+ toData.DSRequiredCapabilities,
+ atscfg.SSLServerNameYAMLOpts{
+ HdrComment: hdrCommentTxt,
+ VerboseComments: true, // TODO add a CLI flag
+ DefaultTLSVersions: cfg.DefaultTLSVersions,
+ DefaultEnableH2: cfg.DefaultEnableH2,
+ },
+ )
+}
+
+func MakeSNIDotYAML(toData *config.TOData, fileName string, hdrCommentTxt
string, cfg config.TCCfg) (atscfg.Cfg, error) {
+ return atscfg.MakeSNIDotYAML(
+ toData.Server,
+ toData.DeliveryServices,
+ toData.DeliveryServiceServers,
+ toData.DeliveryServiceRegexes,
+ toData.ParentConfigParams,
+ toData.CDN,
+ toData.Topologies,
+ toData.CacheGroups,
+ toData.ServerCapabilities,
+ toData.DSRequiredCapabilities,
+ atscfg.SNIDotYAMLOpts{
+ HdrComment: hdrCommentTxt,
+ VerboseComments: true, // TODO add a CLI flag
+ DefaultTLSVersions: cfg.DefaultTLSVersions,
+ DefaultEnableH2: cfg.DefaultEnableH2,
+ },
+ )
+}
+
func MakeLogsXMLDotConfig(toData *config.TOData, fileName string,
hdrCommentTxt string, cfg config.TCCfg) (atscfg.Cfg, error) {
return atscfg.MakeLogsXMLDotConfig(toData.Server, toData.ServerParams,
hdrCommentTxt)
}
diff --git a/traffic_ops_ort/atstccfg/config/config.go
b/traffic_ops_ort/atstccfg/config/config.go
index 5db78c3..c8257d3 100644
--- a/traffic_ops_ort/atstccfg/config/config.go
+++ b/traffic_ops_ort/atstccfg/config/config.go
@@ -48,26 +48,28 @@ var ErrNotFound = errors.New("not found")
var ErrBadRequest = errors.New("bad request")
type Cfg struct {
- CacheHostName string
- DisableProxy bool
- GetData string
- ListPlugins bool
- LogLocationErr string
- LogLocationInfo string
- LogLocationWarn string
- NumRetries int
- RevalOnly bool
- SetQueueStatus string
- SetRevalStatus string
- TOInsecure bool
- TOPass string
- TOTimeout time.Duration
- TOURL *url.URL
- TOUser string
- Dir string
- ViaRelease bool
- SetDNSLocalBind bool
- ParentComments bool
+ CacheHostName string
+ DisableProxy bool
+ GetData string
+ ListPlugins bool
+ LogLocationErr string
+ LogLocationInfo string
+ LogLocationWarn string
+ NumRetries int
+ RevalOnly bool
+ SetQueueStatus string
+ SetRevalStatus string
+ TOInsecure bool
+ TOPass string
+ TOTimeout time.Duration
+ TOURL *url.URL
+ TOUser string
+ Dir string
+ ViaRelease bool
+ SetDNSLocalBind bool
+ ParentComments bool
+ DefaultEnableH2 bool
+ DefaultTLSVersions []atscfg.TLSVersion
}
type TCCfg struct {
@@ -105,6 +107,8 @@ func GetCfg() (Cfg, error) {
viaRelease := flag.BoolP("via-string-release", "", false, "Whether to
use the Release value from the RPM package as a replacement for the ATS version
specified in the build that is returned in the Via and Server headers from
ATS.")
dnsLocalBind := flag.BoolP("dns-local-bind", "", false, "Whether to use
the server's Service Addresses to set the ATS DNS local bind address.")
disableParentConfigComments :=
flag.BoolP("disable-parent-config-comments", "", false, "Disable adding a
comments to parent.config individual lines")
+ defaultEnableH2 := flag.BoolP("default-client-enable-h2", "", false,
"Whether to enable HTTP/2 on Delivery Services by default, if they have no
explicit Parameter. This is irrelevant if ATS records.config is not serving H2.
If omitted, H2 is disabled.")
+ defaultTLSVersionsStr := flag.StringP("default-client-tls-versions",
"", "", "Comma-delimited list of default TLS versions for Delivery Services
with no Parameter, e.g. '--default-tls-versions=1.1,1.2,1.3'. If omitted, all
versions are enabled.")
flag.Parse()
@@ -151,6 +155,22 @@ func GetCfg() (Cfg, error) {
return Cfg{}, errors.New("Missing required argument
--cache-host-name. " + usageStr)
}
+ defaultTLSVersions := atscfg.DefaultDefaultTLSVersions
+
+ *defaultTLSVersionsStr = strings.TrimSpace(*defaultTLSVersionsStr)
+ if len(*defaultTLSVersionsStr) > 0 {
+ defaultTLSVersionsStrs := strings.Split(*defaultTLSVersionsStr,
",")
+
+ defaultTLSVersions = []atscfg.TLSVersion{}
+ for _, tlsVersionStr := range defaultTLSVersionsStrs {
+ tlsVersion := atscfg.StringToTLSVersion(tlsVersionStr)
+ if tlsVersion == atscfg.TLSVersionInvalid {
+ return Cfg{}, errors.New("unknown TLS Version
'" + tlsVersionStr + "' in '" + *defaultTLSVersionsStr + "'")
+ }
+ defaultTLSVersions = append(defaultTLSVersions,
tlsVersion)
+ }
+ }
+
toURLParsed, err := url.Parse(*toURL)
if err != nil {
return Cfg{}, errors.New("parsing Traffic Ops URL from " +
urlSourceStr + " '" + *toURL + "': " + err.Error())
@@ -159,26 +179,28 @@ func GetCfg() (Cfg, error) {
}
cfg := Cfg{
- LogLocationErr: *logLocationErr,
- LogLocationWarn: *logLocationWarn,
- LogLocationInfo: *logLocationInfo,
- NumRetries: *numRetries,
- TOInsecure: *toInsecure,
- TOPass: *toPass,
- TOTimeout: time.Millisecond * time.Duration(*toTimeoutMS),
- TOURL: toURLParsed,
- TOUser: *toUser,
- ListPlugins: *listPlugins,
- CacheHostName: *cacheHostName,
- GetData: *getData,
- SetRevalStatus: *setRevalStatus,
- SetQueueStatus: *setQueueStatus,
- RevalOnly: *revalOnly,
- DisableProxy: *disableProxy,
- Dir: *dir,
- ViaRelease: *viaRelease,
- SetDNSLocalBind: *dnsLocalBind,
- ParentComments: !(*disableParentConfigComments),
+ LogLocationErr: *logLocationErr,
+ LogLocationWarn: *logLocationWarn,
+ LogLocationInfo: *logLocationInfo,
+ NumRetries: *numRetries,
+ TOInsecure: *toInsecure,
+ TOPass: *toPass,
+ TOTimeout: time.Millisecond *
time.Duration(*toTimeoutMS),
+ TOURL: toURLParsed,
+ TOUser: *toUser,
+ ListPlugins: *listPlugins,
+ CacheHostName: *cacheHostName,
+ GetData: *getData,
+ SetRevalStatus: *setRevalStatus,
+ SetQueueStatus: *setQueueStatus,
+ RevalOnly: *revalOnly,
+ DisableProxy: *disableProxy,
+ Dir: *dir,
+ ViaRelease: *viaRelease,
+ SetDNSLocalBind: *dnsLocalBind,
+ ParentComments: !(*disableParentConfigComments),
+ DefaultEnableH2: *defaultEnableH2,
+ DefaultTLSVersions: defaultTLSVersions,
}
if err := log.InitCfg(cfg); err != nil {
return Cfg{}, errors.New("Initializing loggers: " + err.Error()
+ "\n")
diff --git a/traffic_ops_ort/t3c/README.md b/traffic_ops_ort/t3c/README.md
index bc4af14..6a7a9e6 100644
--- a/traffic_ops_ort/t3c/README.md
+++ b/traffic_ops_ort/t3c/README.md
@@ -1,50 +1,52 @@
-# T3C
+# t3c
t3c is a transliteration of traffic_ops_ort.pl script to the go language.
It is designed to replace the traffic_ops_ort.pl perl script and it is used to
apply
configuration from Traffic Control, stored in Traffic Ops, to the cache.
-Typical usage is to install T3C on the cache machine, and then run it
periodically via a CRON job.
+Typical usage is to install `t3c` on the cache machine, and then run it
periodically via a CRON job.
-**NOTE** T3C requires and uses /opt/ort/atstccfg
+**NOTE** `t3c` requires and uses /opt/ort/atstccfg
## Options
-T3C has the following command-line options:
+The `t3c` app has the following command-line options:
long option | short | default | description
--------------------------------------- | ------| ------- |
------------------------------------------------------------------------------------
---cache-hostname=[hostname] | -H | "" | override the short
hostname of the OS for config generation.
---dispersion=[seconds] | -D | 300 | wait a random
number of seconds between 0 and [seconds] before starting.
---login-dispersion=[seconds] | -l | 0 | wait a random
number of seconds between 0 and [seconds] before login.
---log-location-debug=[value] | -d | stdout | Where to log
debugs. May be a file path, stdout, stderr, or null
---log-location-error=[value] | -e | stdout | Where to log
errors. May be a file path, stdout, stderr, or null
---log-location-info=[value] | -i | stdout | Where to log info
messages. May be a file path, stdout, stderr, or null
---log-location-warn=[value] | -w | stdout | Where to log
warning messages. May be a file path, stdout, stderr, or null
---num-retries=[number] | -r | 3 | retry connection
to Traffic Ops URL [number] times.
---rev-proxy-disable=['true' or 'false'] | -p | false | bypass the reverse
proxy even if one has been configured.
---reval-wait-time=[seconds] | -T | 60 | wait a random
number of seconds between 0 and [seconds] before revlidation
---run-mode=[mode] | -m | report | The mode of
operation, where mode is [badass|report|revalidate|syncds].
---skip-os-check=['true' or 'false'] | -s | false | bypass the check
for a supported CentOS version.
---traffic-ops-timeout-milliseconds=[ms] | -t | 30000 | The Traffic Ops
request timeout in milliseconds.
---traffic-ops-password=[password] | -P | "" | TrafficOps
password. Required if not set with the environment variable TO_PASS
---traffic-ops-url=[url] | -u | "" | TrafficOps URL.
Required if not set with the environment variable TO_URL
---traffic-ops-user=[username] | -U | "" | TrafficOps
username. Required if not set with the environment variable TO_USER
---trafficserver-home=[directory] | -R | "" | Used to specify an
alternate install location for ATS, otherwise its set from the RPM.
---dns-local-bind=['true' or 'false'] | -b | false | set the ATS config
to bind to the Server's Service Address in Traffic Ops for DNS.
---wait-for-parents=['true' or 'false'] | -W | true | do not update if
parent_pending = 1 in the update json.
---git=['yes' or 'no' or 'auto'] | -g | auto | track changes in
git. If yes, create and commit to a repo. If auto, commit if a repo exists.
+--cache-hostname=[hostname] | -H | "" | override
the short hostname of the OS for config generation.
+--dispersion=[seconds] | -D | 300 | wait a
random number of seconds between 0 and [seconds] before starting.
+--login-dispersion=[seconds] | -l | 0 | wait a
random number of seconds between 0 and [seconds] before login.
+--log-location-debug=[value] | -d | stdout | Where to
log debugs. May be a file path, stdout, stderr, or null
+--log-location-error=[value] | -e | stdout | Where to
log errors. May be a file path, stdout, stderr, or null
+--log-location-info=[value] | -i | stdout | Where to
log info messages. May be a file path, stdout, stderr, or null
+--log-location-warn=[value] | -w | stdout | Where to
log warning messages. May be a file path, stdout, stderr, or null
+--num-retries=[number] | -r | 3 | retry
connection to Traffic Ops URL [number] times.
+--rev-proxy-disable=['true' or 'false'] | -p | false | bypass the
reverse proxy even if one has been configured.
+--reval-wait-time=[seconds] | -T | 60 | wait a
random number of seconds between 0 and [seconds] before revlidation
+--run-mode=[mode] | -m | report | The mode of
operation, where mode is [badass|report|revalidate|syncds].
+--skip-os-check=['true' or 'false'] | -s | false | bypass the
check for a supported CentOS version.
+--traffic-ops-timeout-milliseconds=[ms] | -t | 30000 | The Traffic
Ops request timeout in milliseconds.
+--traffic-ops-password=[password] | -P | "" | TrafficOps
password. Required if not set with the environment variable TO_PASS
+--traffic-ops-url=[url] | -u | "" | TrafficOps
URL. Required if not set with the environment variable TO_URL
+--traffic-ops-user=[username] | -U | "" | TrafficOps
username. Required if not set with the environment variable TO_USER
+--trafficserver-home=[directory] | -R | "" | Used to
specify an alternate install location for ATS, otherwise its set from the RPM.
+--dns-local-bind=['true' or 'false'] | -b | false | set the ATS
config to bind to the Server's Service Address in Traffic Ops for DNS.
+--wait-for-parents=['true' or 'false'] | -W | true | do not
update if parent_pending = 1 in the update json.
+--git=['yes' or 'no' or 'auto'] | -g | auto | track
changes in git. If yes, create and commit to a repo. If auto, commit if a repo
exists.
+--default-client-enable-h2=['true' or 'false'] | -2 | false | Whether to
enable HTTP/2 on Delivery Services by default, if they have no explicit
Parameter.
+--default-client-tls-versions=[versions] | -v | "" |
Comma-delimited list of default TLS versions for Delivery Services with no
Parameter, e.g. '1.1,1.2,1.3'. If omitted, all versions are enabled.
# Modes
-T3C can be run in a number of modes.
+The `t3c` app can be run in a number of modes.
The syncds mode is the normal mode of operation, which should typically be run
periodically via cron or a similar tool.
-The badass mode is typically an emergency-fix mode, which will override and
replace all files with the configuration generated from the current Traffic Ops
data, regardless whether T3C (presumably incorrectly) thinks the files need
updating or not. It is recommended to run this mode when something goes wrong,
and the configuration on the cache is incorrect, and the data in Traffic Ops
and config generation is believed to be correct. It is not recommended to run
this in normal operation; [...]
+The badass mode is typically an emergency-fix mode, which will override and
replace all files with the configuration generated from the current Traffic Ops
data, regardless whether `t3c` (presumably incorrectly) thinks the files need
updating or not. It is recommended to run this mode when something goes wrong,
and the configuration on the cache is incorrect, and the data in Traffic Ops
and config generation is believed to be correct. It is not recommended to run
this in normal operation [...]
-The revalidate mode will apply Revalidations from Traffic Ops
(regex_revalidate.config) but no other configuration. This mode was intended to
quickly apply revalidations when T3C took a long time to run. It is less
relevant with T3C's current speed, but may still be useful on slow networks or
very large deployments.
+The revalidate mode will apply Revalidations from Traffic Ops
(regex_revalidate.config) but no other configuration. This mode was intended to
quickly apply revalidations when `t3c` took a long time to run. It is less
relevant with the current speed of `t3c` but may still be useful on slow
networks or very large deployments.
mode | description
------------| ---
@@ -55,7 +57,7 @@ revalidate | checks for updated revalidations in Traffic Ops
and applies them
# Behavior
-When T3C is run, it will:
+When `t3c` is run, it will:
1. Delete all of its temporary directories over a week old. Currently, the
base temp directory is hard-coded to /tmp/ort.
1. Determine if Updates have been Queued on the server (by checking the
Server's Update Pending or Revalidate Pending flag in Traffic Ops).
@@ -71,15 +73,15 @@ When T3C is run, it will:
1. **NOTE** the default profiles distributed by Traffic Control have an
ATS chkconfig with a runlevel before networking is enabled, which is likely
incorrect.
1. **NOTE** this is not used by CentOS 7+ and ATS 7+. SystemD does not use
chkconfig, and ATS 7+ uses a SystemD script not an init script.
1. Process each config file
- 1. If T3C is in revalidate mode, this will only be regex_revalidate.config
+ 1. If `t3c` is in revalidate mode, this will only be
regex_revalidate.config
1. Perform any special processing. See [Special
Processing](#special-processing).
1. If a file exists at the path of the file, load it from disk and compare
the two.
1. If there are no changes, don't apply the new file.
1. If there are changes, backup the existing file in the temp directory,
and write the new file.
1. If configuration was changed which requires an ATS reload to apply, perform
a service reload of ATS.
-1. If configuration was changed which requires an ATS restart to apply, and
T3C is in badass mode, perform a service restart of ATS.
-1. If a sysctl.conf config file was changed, and T3C is in badass mode, run
`sysctl -p`.
-1. If a ntpd.conf config file was changed, and T3C is in badass mode, perform
a service restart of ntpd.
+1. If configuration was changed which requires an ATS restart to apply, and
`t3c` is in badass mode, perform a service restart of ATS.
+1. If a sysctl.conf config file was changed, and `t3c` is in badass mode, run
`sysctl -p`.
+1. If a ntpd.conf config file was changed, and `t3c` is in badass mode,
perform a service restart of ntpd.
1. Update Traffic Ops to unset the Update Pending or Revalidate Pending flag
of this Server.
# Special Processing
@@ -88,7 +90,7 @@ Certain config files perform extra processing.
## Global replacements
-All config files have certain text directives replaced. This is done by the
atstccfg config generator before the file is returned to T3C.
+All config files have certain text directives replaced. This is done by the
atstccfg config generator before the file is returned to `t3c`.
* `__SERVER_TCP_PORT__` is replaced with the Server's Port from Traffic Ops;
unless the server's port is 80, 0, or null, in which case any occurrences
preceded by a colon are removed.
* `__CACHE_IPV4__` is replaced with the Server's IP address from Traffic Ops.
@@ -98,7 +100,7 @@ All config files have certain text directives replaced. This
is done by the atst
## remap.config
-T3C processes `##OVERRIDE##` directives in the remap.config file.
+The `t3c` app processes `##OVERRIDE##` directives in the remap.config file.
The ##OVERRIDE## template string allows the Delivery Service Raw Remap Text
field to override to fully override the Delivery Service’s line in the
remap.config ATS configuration file, generated by Traffic Ops. The end result
is the original, generated line commented out, prepended with ##OVERRIDDEN##
and the ##OVERRIDE## rule is activated in its place. This behavior is used to
incrementally deploy plugins used in this configuration file. Normally, this
entails cloning the Delivery Servic [...]
@@ -106,10 +108,10 @@ The ##OVERRIDE## template string allows the Delivery
Service Raw Remap Text fiel
This is presumed to be a udev file for devices which are block devices to be
used as disk storage by ATS.
-T3C verifies all devices in the file are owned by the owner listed in the
file, and logs errors otherwise.
+The `t3c` app verifies all devices in the file are owned by the owner listed
in the file, and logs errors otherwise.
-T3C verifies all devices in the file do not have filesystems. If any device
has a filesystem, T3C assumes it was a mistake to assign as an ATS storage
device, and logs a fatal error.
+The `t3c` app verifies all devices in the file do not have filesystems. If any
device has a filesystem, `t3c` assumes it was a mistake to assign as an ATS
storage device, and logs a fatal error.
# Trivia
-T3C stands for "TrafficOps Cache Control and Configuration.", 3 C's.
+The "t3c" stands for "Traffic Control Cache Config."
diff --git a/traffic_ops_ort/t3c/config/config.go
b/traffic_ops_ort/t3c/config/config.go
index c74f9b9..02d3a64 100644
--- a/traffic_ops_ort/t3c/config/config.go
+++ b/traffic_ops_ort/t3c/config/config.go
@@ -114,7 +114,9 @@ type Cfg struct {
// UseGit is whether to create and maintain a git repo of config
changes.
// Note this only applies to the ATS config directory inferred or set
via the flag.
// It does not do anything for config files generated outside that
location.
- UseGit UseGitFlag
+ UseGit UseGitFlag
+ DefaultClientEnableH2 *bool
+ DefaultClientTLSVersions *string
}
type UseGitFlag string
@@ -216,6 +218,9 @@ func GetCfg() (Cfg, error) {
dnsLocalBindPtr := getopt.BoolLong("dns-local-bind", 'b', "[true |
false] whether to use the server's Service Addresses to set the ATS DNS local
bind address")
helpPtr := getopt.BoolLong("help", 'h', "Print usage information and
exit")
useGitStr := getopt.StringLong("git", 'g', "auto", "Create and use a
git repo in the config directory. Options are yes, no, and auto. If yes, create
and use. If auto, use if it exist. Default is auto.")
+ defaultEnableH2 := getopt.BoolLong("default-client-enable-h2", '2',
"Whether to enable HTTP/2 on Delivery Services by default, if they have no
explicit Parameter. This is irrelevant if ATS records.config is not serving H2.
If omitted, H2 is disabled.")
+ defaultClientTLSVersions :=
getopt.StringLong("default-client-tls-versions", 'v', "", "Comma-delimited list
of default TLS versions for Delivery Services with no Parameter, e.g.
--default-tls-versions='1.1,1.2,1.3'. If omitted, all versions are enabled.")
+
getopt.Parse()
dispersion := time.Second * time.Duration(*dispersionPtr)
@@ -337,28 +342,30 @@ func GetCfg() (Cfg, error) {
yumOptions := os.Getenv("YUM_OPTIONS")
cfg := Cfg{
- Dispersion: dispersion,
- LogLocationDebug: logLocationDebug,
- LogLocationErr: logLocationError,
- LogLocationInfo: logLocationInfo,
- LogLocationWarn: logLocationWarn,
- LoginDispersion: loginDispersion,
- CacheHostName: cacheHostName,
- SvcManagement: svcManagement,
- Retries: retries,
- RevalWaitTime: revalWaitTime,
- ReverseProxyDisable: reverseProxyDisable,
- RunMode: runMode,
- SkipOSCheck: skipOsCheck,
- TOInsecure: toInsecure,
- TOTimeoutMS: toTimeoutMS,
- TOUser: toUser,
- TOPass: toPass,
- TOURL: toURL,
- DNSLocalBind: dnsLocalBind,
- WaitForParents: waitForParents,
- YumOptions: yumOptions,
- UseGit: useGit,
+ Dispersion: dispersion,
+ LogLocationDebug: logLocationDebug,
+ LogLocationErr: logLocationError,
+ LogLocationInfo: logLocationInfo,
+ LogLocationWarn: logLocationWarn,
+ LoginDispersion: loginDispersion,
+ CacheHostName: cacheHostName,
+ SvcManagement: svcManagement,
+ Retries: retries,
+ RevalWaitTime: revalWaitTime,
+ ReverseProxyDisable: reverseProxyDisable,
+ RunMode: runMode,
+ SkipOSCheck: skipOsCheck,
+ TOInsecure: toInsecure,
+ TOTimeoutMS: toTimeoutMS,
+ TOUser: toUser,
+ TOPass: toPass,
+ TOURL: toURL,
+ DNSLocalBind: dnsLocalBind,
+ WaitForParents: waitForParents,
+ YumOptions: yumOptions,
+ UseGit: useGit,
+ DefaultClientEnableH2: defaultEnableH2,
+ DefaultClientTLSVersions: defaultClientTLSVersions,
}
if err = log.InitCfg(cfg); err != nil {
diff --git a/traffic_ops_ort/t3c/torequest/torequest.go
b/traffic_ops_ort/t3c/torequest/torequest.go
index 0251fbf..67eb86c 100644
--- a/traffic_ops_ort/t3c/torequest/torequest.go
+++ b/traffic_ops_ort/t3c/torequest/torequest.go
@@ -227,10 +227,15 @@ func (r *TrafficOpsReq) atsTcExecCommand(cmdstr string,
queueState int, revalSta
if r.Cfg.TOInsecure == true {
args = append(args, "--traffic-ops-insecure")
}
-
if r.Cfg.DNSLocalBind {
args = append(args, "--dns-local-bind")
}
+ if r.Cfg.DefaultClientEnableH2 != nil {
+ args = append(args,
"--default-client-enable-h2="+strconv.FormatBool(*r.Cfg.DefaultClientEnableH2))
+ }
+ if r.Cfg.DefaultClientTLSVersions != nil {
+ args = append(args,
"--default-client-tls-versions="+*r.Cfg.DefaultClientTLSVersions+"")
+ }
switch cmdstr {
case "chkconfig":