diff --git a/cache-config/t3c-apply/t3c-apply.go b/cache-config/t3c-apply/t3c-apply.go index 75876f129a..905cc1a6f1 100644 --- a/cache-config/t3c-apply/t3c-apply.go +++ b/cache-config/t3c-apply/t3c-apply.go @@ -334,6 +334,25 @@ func Main() int { } } + if trops.HitchReload { + svcStatus, _, err := util.GetServiceStatus("hitch") + cmd := "start" + running := false + if err != nil { + log.Errorf("not starting 'hitch', error getting 'hitch' run status: %s\n", err) + } else if svcStatus != util.SvcNotRunning { + cmd = "reload" + } + running, err = util.ServiceStart("hitch", cmd) + if err != nil { + log.Errorf("'hitch' was not %sed: %s\n", cmd, err) + } else if running { + log.Infof("service 'hitch' %sed", cmd) + } else { + log.Infoln("service 'hitch' already running") + } + } + // reload sysctl if trops.SysCtlReload == true { runSysctl(cfg) diff --git a/cache-config/t3c-apply/torequest/torequest.go b/cache-config/t3c-apply/torequest/torequest.go index 990b71c852..ba9b443682 100644 --- a/cache-config/t3c-apply/torequest/torequest.go +++ b/cache-config/t3c-apply/torequest/torequest.go @@ -90,6 +90,7 @@ type RestartData struct { TeakdRestart bool // a restart of teakd is required TrafficServerRestart bool // a trafficserver restart is required RemapConfigReload bool // remap.config should be reloaded + HitchReload bool // hitch should be reloaded } type ConfigFile struct { @@ -520,6 +521,7 @@ func (r *TrafficOpsReq) replaceCfgFile(cfg *ConfigFile) (*FileRestartData, error trafficServerRestart := cfg.Name == "plugin.config" ntpdRestart := cfg.Name == "ntpd.conf" sysCtlReload := cfg.Name == "sysctl.conf" + hitchReload := cfg.Name == "hitch.conf" log.Debugf("Reload state after %s: remap.config: %t reload: %t restart: %t ntpd: %t sysctl: %t", cfg.Name, remapConfigReload, trafficCtlReload, trafficServerRestart, ntpdRestart, sysCtlReload) @@ -532,6 +534,7 @@ func (r *TrafficOpsReq) replaceCfgFile(cfg *ConfigFile) (*FileRestartData, error NtpdRestart: ntpdRestart, TrafficServerRestart: trafficServerRestart, RemapConfigReload: remapConfigReload, + HitchReload: hitchReload, }, }, nil } @@ -810,6 +813,7 @@ func (r *TrafficOpsReq) CheckReloadRestart(data []FileRestartData) RestartData { rd.TeakdRestart = rd.TeakdRestart || changedFile.TeakdRestart rd.TrafficServerRestart = rd.TrafficServerRestart || changedFile.TrafficServerRestart rd.RemapConfigReload = rd.RemapConfigReload || changedFile.RemapConfigReload + rd.HitchReload = rd.HitchReload || changedFile.HitchReload } return rd } diff --git a/cache-config/t3c-generate/cfgfile/varnish.go b/cache-config/t3c-generate/cfgfile/varnish.go index 060445a75a..07a33273e0 100644 --- a/cache-config/t3c-generate/cfgfile/varnish.go +++ b/cache-config/t3c-generate/cfgfile/varnish.go @@ -20,6 +20,9 @@ package cfgfile */ import ( + "errors" + "path/filepath" + "github.com/apache/trafficcontrol/cache-config/t3c-generate/config" "github.com/apache/trafficcontrol/cache-config/t3cutil" "github.com/apache/trafficcontrol/lib/varnishcfg" @@ -42,5 +45,29 @@ func GetVarnishConfigs(toData *t3cutil.ConfigData, cfg config.Cfg) ([]t3cutil.AT LineComment: "//", Secure: false, }) - return configs, err + txt, hitchWarnings := varnishcfg.GetHitchConfig(toData.DeliveryServices, filepath.Join(cfg.Dir, "ssl/")) + warnings = append(warnings, hitchWarnings...) + logWarnings("Generating hitch configuration files: ", hitchWarnings) + + configs = append(configs, t3cutil.ATSConfigFile{ + Name: "hitch.conf", + Text: txt, + Path: cfg.Dir, + ContentType: "text/plain; charset=us-ascii", + LineComment: "//", + Secure: false, + }) + + sslConfigs, err := GetSSLCertsAndKeyFiles(toData) + if err != nil { + return nil, errors.New("getting ssl key and cert config files: " + err.Error()) + } + for i := range sslConfigs { + // path changed manually because GetSSLCertsAndKeyFiles hardcodes the directory certs and keys are written to. + // will be removed once GetSSLCertsAndKeyFiles uses proxy.config.ssl.server.cert.path parameter. + sslConfigs[i].Path = filepath.Join(cfg.Dir, "ssl/") + } + configs = append(configs, sslConfigs...) + + return configs, nil } diff --git a/infrastructure/cdn-in-a-box/varnish/Dockerfile b/infrastructure/cdn-in-a-box/varnish/Dockerfile index a67e1724b3..9b5840d7b5 100644 --- a/infrastructure/cdn-in-a-box/varnish/Dockerfile +++ b/infrastructure/cdn-in-a-box/varnish/Dockerfile @@ -28,6 +28,8 @@ RUN curl -s https://packagecloud.io/install/repositories/varnishcache/varnish73/ RUN yum install varnish-7.3.0 -y +RUN yum install -y hitch-1.5.2 + RUN dnf install -y bind-utils kyotocabinet-libs initscripts iproute net-tools nmap-ncat gettext autoconf automake libtool gcc-c++ cronie glibc-devel openssl-devel git perl && \ dnf install -y jq logrotate findutils && \ dnf clean all diff --git a/infrastructure/cdn-in-a-box/varnish/systemctl.sh b/infrastructure/cdn-in-a-box/varnish/systemctl.sh index cfe2a55c24..7184d78194 100755 --- a/infrastructure/cdn-in-a-box/varnish/systemctl.sh +++ b/infrastructure/cdn-in-a-box/varnish/systemctl.sh @@ -18,6 +18,7 @@ # under the License. VARNISHD_EXECUTABLE="/usr/sbin/varnishd" +HITCH_EXECUTABLE="/usr/sbin/hitch" is_varnishd_running() { pgrep -x "$(basename "$VARNISHD_EXECUTABLE")" >/dev/null @@ -28,7 +29,7 @@ start_varnishd() { echo "varnishd is already running." else echo "Starting varnishd..." - "$VARNISHD_EXECUTABLE" -f /opt/cache/etc/varnish/default.vcl + "$VARNISHD_EXECUTABLE" -f /opt/cache/etc/varnish/default.vcl -a :80 -a :6081,PROXY echo "varnishd is now running." fi } @@ -67,28 +68,90 @@ restart_varnishd() { start_varnishd } -case "$1" in - enable) - exit 0 - ;; - start) - start_varnishd - ;; - stop) - stop_varnishd - ;; - restart) - restart_varnishd - ;; - status) - if is_varnishd_running; then - exit 0 - fi - exit 3 - ;; - *) - echo "Usage: $0 {start|stop|restart|enable|status}" +is_hitch_running() { + pgrep -x "$(basename "$HITCH_EXECUTABLE")" >/dev/null +} + + +start_hitch() { + if is_hitch_running; then + echo "hitch is already running." + else + echo "Starting hitch..." + "$HITCH_EXECUTABLE" --config /opt/cache/etc/varnish/hitch.conf --daemon + echo "hitch is now running." + fi + +} + +reload_hitch() { + if is_hitch_running; then + pkill -HUP "$(basename "$HITCH_EXECUTABLE")" + else + echo "hitch is not running" exit 1 -esac + fi +} + +handle_varnish_service() { + case "$1" in + enable) + exit 0 + ;; + start) + start_varnishd + ;; + stop) + stop_varnishd + ;; + restart) + restart_varnishd + ;; + status) + if is_varnishd_running; then + # t3c-apply looks for this specific string + echo "Active: active" + exit 0 + fi + exit 3 + ;; + *) + echo "Usage: $0 {start|stop|restart|enable|status}" + exit 1 + esac +} + +handle_hitch_service() { + case "$1" in + enable) + exit 0 + ;; + start) + start_hitch + ;; + reload) + reload_hitch + ;; + status) + if is_hitch_running; then + # t3c-apply looks for this specific string + echo "Active: active" + exit 0 + fi + exit 3 + ;; + *) + echo "Usage: $0 {start|stop|restart|reload|enable|status}" + exit 1 + esac +} + +if [[ $2 == "varnish.service" ]] +then + handle_varnish_service $1 +elif [[ $2 == "hitch.service" ]] +then + handle_hitch_service $1 +fi exit 0 diff --git a/lib/varnishcfg/hitch.go b/lib/varnishcfg/hitch.go new file mode 100644 index 0000000000..2727feb96e --- /dev/null +++ b/lib/varnishcfg/hitch.go @@ -0,0 +1,61 @@ +package varnishcfg + +/* + * 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 ( + "path/filepath" + "strings" + + "github.com/apache/trafficcontrol/lib/go-atscfg" +) + +// GetHitchConfig returns Hitch config using TO data +func GetHitchConfig(deliveryServices []atscfg.DeliveryService, sslDir string) (string, []string) { + warnings := make([]string, 0) + lines := []string{ + `frontend = {`, + ` host = "*"`, + ` port = "443"`, + `}`, + `backend = "[127.0.0.1]:6081"`, + `write-proxy-v2 = on`, + // TODO: change root user + `user = "root"`, + } + + dses, dsWarns := atscfg.DeliveryServicesToSSLMultiCertDSes(deliveryServices) + warnings = append(warnings, dsWarns...) + + dses = atscfg.GetSSLMultiCertDotConfigDeliveryServices(dses) + + for dsName, ds := range dses { + cerName, keyName := atscfg.GetSSLMultiCertDotConfigCertAndKeyName(dsName, ds) + lines = append(lines, []string{ + `pem-file = {`, + ` cert = "` + filepath.Join(sslDir, cerName) + `"`, + ` private-key = "` + filepath.Join(sslDir, keyName) + `"`, + `}`, + }...) + } + + txt := strings.Join(lines, "\n") + txt += "\n" + return txt, warnings +} diff --git a/lib/varnishcfg/hitch_test.go b/lib/varnishcfg/hitch_test.go new file mode 100644 index 0000000000..b9a6699579 --- /dev/null +++ b/lib/varnishcfg/hitch_test.go @@ -0,0 +1,60 @@ +package varnishcfg + +/* + * 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-atscfg" + "github.com/apache/trafficcontrol/lib/go-tc" + "github.com/apache/trafficcontrol/lib/go-util" +) + +func TestGetHitchConfig(t *testing.T) { + ds1 := &atscfg.DeliveryService{} + ds1.XMLID = util.StrPtr("ds1") + ds1.Protocol = util.IntPtr(1) + ds1Type := tc.DSTypeHTTP + ds1.Type = &ds1Type + ds1.ExampleURLs = []string{"https://ds1.example.org"} + deliveryServices := []atscfg.DeliveryService{*ds1} + txt, warnings := GetHitchConfig(deliveryServices, "/ssl") + expectedTxt := strings.Join([]string{ + `frontend = {`, + ` host = "*"`, + ` port = "443"`, + `}`, + `backend = "[127.0.0.1]:6081"`, + `write-proxy-v2 = on`, + `user = "root"`, + `pem-file = {`, + ` cert = "/ssl/ds1_example_org_cert.cer"`, + ` private-key = "/ssl/ds1.example.org.key"`, + `}`, + }, "\n") + expectedTxt += "\n" + if len(warnings) != 0 { + t.Errorf("expected no warnings got %v", warnings) + } + if txt != expectedTxt { + t.Errorf("expected: %s got: %s", expectedTxt, txt) + } +}