diff --git a/CHANGELOG.md b/CHANGELOG.md index d95858ad44..18cd9ba6e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - New `pkg` script options, `-h`, `-s`, `-S`, and `-L`. - Added `Invalidation Type` (REFRESH or REFETCH) for invalidating content to Traffic Portal. - IMS warnings to Content Invalidation requests in Traffic Portal and documentation. +- [#6032](https://github.com/apache/trafficcontrol/issues/6032) Add t3c setting mode 0600 for secure files ### Fixed - [#6197](https://github.com/apache/trafficcontrol/issues/6197) - TO `/deliveryservices/:id/routing` makes requests to all TRs instead of by CDN. diff --git a/cache-config/t3c-apply/torequest/cmd.go b/cache-config/t3c-apply/torequest/cmd.go index 53fa7ece6b..c9e48046e2 100644 --- a/cache-config/t3c-apply/torequest/cmd.go +++ b/cache-config/t3c-apply/torequest/cmd.go @@ -257,17 +257,22 @@ func sendUpdate(cfg config.Cfg, updateStatus bool, revalStatus bool) error { // diff calls t3c-diff to diff the given new file and the file on disk. Returns whether they're different. // Logs the difference. // If the file on disk doesn't exist, returns true and logs the entire file as a diff. -func diff(cfg config.Cfg, newFile []byte, fileLocation string, reportOnly bool) (bool, error) { +func diff(cfg config.Cfg, newFile []byte, fileLocation string, reportOnly bool, perm os.FileMode) (bool, error) { diffMsg := "" + args := []string{ + "--file-a=stdin", + "--file-b=" + fileLocation, + "--file-mode=" + fmt.Sprintf("%#o", perm), + } - stdOut, stdErr, code := t3cutil.DoInput(newFile, `t3c-diff`, `stdin`, fileLocation) + stdOut, stdErr, code := t3cutil.DoInput(newFile, `t3c-diff`, args...) if code > 1 { return false, fmt.Errorf("t3c-diff returned error code %v stdout '%v' stderr '%v'", code, string(stdOut), string(stdErr)) } logSubApp(`t3c-diff`, stdErr) if code == 0 { - diffMsg += fmt.Sprintf("All lines match TrOps for config file: %s\n", fileLocation) + diffMsg += fmt.Sprintf("All lines and file permissions match TrOps for config file: %s\n", fileLocation) return false, nil // 0 is only returned if there's no diff } // code 1 means a diff, difference text will be on stdout @@ -332,10 +337,49 @@ func checkRefs(cfg config.Cfg, cfgFile []byte, filesAdding []string) error { func checkReload(pluginPackagesInstalled []string, changedConfigFiles []string) (t3cutil.ServiceNeeds, error) { log.Infof("t3c-check-reload calling with pluginPackagesInstalled '%v' changedConfigFiles '%v'\n", pluginPackagesInstalled, changedConfigFiles) - stdOut, stdErr, code := t3cutil.Do(`t3c`, `check`, `reload`, - "--plugin-packages-installed="+strings.Join(pluginPackagesInstalled, ","), - "--changed-config-paths="+strings.Join(changedConfigFiles, ","), - ) + changedFiles := []byte(strings.Join(changedConfigFiles, ",")) + installedPlugins := []byte(strings.Join(pluginPackagesInstalled, ",")) + + cmd := exec.Command(`t3c-check-reload`) + outBuf := bytes.Buffer{} + errBuf := bytes.Buffer{} + cmd.Stdout = &outBuf + cmd.Stderr = &errBuf + + stdinPipe, err := cmd.StdinPipe() + if err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("getting command pipe: " + err.Error()) + } + + if err := cmd.Start(); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("starting command: " + err.Error()) + } + + if _, err := stdinPipe.Write([]byte(`{"changed_files":"`)); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("writing opening json to input: " + err.Error()) + } else if _, err := stdinPipe.Write(changedFiles); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("writing changed files to input: " + err.Error()) + } else if _, err := stdinPipe.Write([]byte(`","installed_plugins":"`)); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("writing installed_plugins key to input: " + err.Error()) + } else if _, err := stdinPipe.Write(installedPlugins); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("writing plugins to input: " + err.Error()) + } else if _, err := stdinPipe.Write([]byte(`"}`)); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("writing closing json input: " + err.Error()) + } else if err := stdinPipe.Close(); err != nil { + return t3cutil.ServiceNeedsInvalid, errors.New("closing stdin writer: " + err.Error()) + } + + code := 0 // if cmd.Wait returns no error, that means the command returned 0 + if err := cmd.Wait(); err != nil { + if exitErr, ok := err.(*exec.ExitError); !ok { + return t3cutil.ServiceNeedsInvalid, errors.New("error running command: " + err.Error()) + } else { + code = exitErr.ExitCode() + } + } + + stdOut := outBuf.Bytes() + stdErr := errBuf.Bytes() if code != 0 { logSubAppErr(`t3c-check-reload stdout`, stdOut) diff --git a/cache-config/t3c-apply/torequest/torequest.go b/cache-config/t3c-apply/torequest/torequest.go index 8013b72f85..fee93ed6c9 100644 --- a/cache-config/t3c-apply/torequest/torequest.go +++ b/cache-config/t3c-apply/torequest/torequest.go @@ -217,7 +217,8 @@ func (r *TrafficOpsReq) checkConfigFile(cfg *ConfigFile, filesAdding []string) e log.Infoln("Successfully verified plugins used by '" + cfg.Name + "'") } - changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path, r.Cfg.ReportOnly) + changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path, r.Cfg.ReportOnly, cfg.Perm) + if err != nil { return errors.New("getting diff: " + err.Error()) } @@ -470,14 +471,14 @@ func (r *TrafficOpsReq) replaceCfgFile(cfg *ConfigFile) error { } tmpFileName := cfg.Path + configFileTempSuffix - log.Infof("Writing temp file '%s'\n", tmpFileName) + log.Infof("Writing temp file '%s' with file mode: '%#o' \n", tmpFileName, cfg.Perm) // write a new file, then move to the real location // because moving is atomic but writing is not. // If we just wrote to the real location and the app or OS or anything crashed, // we'd end up with malformed files. - if _, err := util.WriteFileWithOwner(tmpFileName, cfg.Body, &cfg.Uid, &cfg.Gid, 0644); err != nil { + if _, err := util.WriteFileWithOwner(tmpFileName, cfg.Body, &cfg.Uid, &cfg.Gid, cfg.Perm); err != nil { return errors.New("Failed to write temp config file '" + tmpFileName + "': " + err.Error()) } @@ -486,7 +487,7 @@ func (r *TrafficOpsReq) replaceCfgFile(cfg *ConfigFile) error { return errors.New("Failed to move temp '" + tmpFileName + "' to real '" + cfg.Path + "': " + err.Error()) } cfg.ChangeApplied = true - r.changedFiles = append(r.changedFiles, filepath.Join(cfg.Path, cfg.Name)) + r.changedFiles = append(r.changedFiles, cfg.Path) r.RemapConfigReload = r.RemapConfigReload || cfg.RemapPluginConfig || @@ -631,7 +632,14 @@ func (r *TrafficOpsReq) GetConfigFileList() error { } r.configFiles = map[string]*ConfigFile{} + var mode os.FileMode for _, file := range allFiles { + if file.Secure { + mode = 0600 + } else { + mode = 0644 + } + r.configFiles[file.Name] = &ConfigFile{ Name: file.Name, Path: filepath.Join(file.Path, file.Name), @@ -639,7 +647,7 @@ func (r *TrafficOpsReq) GetConfigFileList() error { Body: []byte(file.Text), Uid: atsUid, Gid: atsGid, - Perm: 0644, + Perm: mode, } } return nil diff --git a/cache-config/t3c-apply/util/util.go b/cache-config/t3c-apply/util/util.go index 9974cf1475..7f8c36d7c5 100644 --- a/cache-config/t3c-apply/util/util.go +++ b/cache-config/t3c-apply/util/util.go @@ -200,7 +200,7 @@ func ServiceStart(service string, cmd string) (bool, error) { } func WriteFileWithOwner(fn string, data []byte, uid *int, gid *int, perm os.FileMode) (int, error) { - fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return 0, errors.New("unable to open '" + fn + "' for writing: " + err.Error()) } diff --git a/cache-config/t3c-check-reload/README.md b/cache-config/t3c-check-reload/README.md index af69e32bf0..fcce5823c1 100644 --- a/cache-config/t3c-check-reload/README.md +++ b/cache-config/t3c-check-reload/README.md @@ -39,14 +39,15 @@ t3c-check-reload - Traffic Control Cache Configuration reload check tool # SYNOPSIS -t3c-check-reload [-c paths] [-m mode] [-p packages] +t3c-check-reload [\-\-help] # DESCRIPTION -The t3c-check-reload app takes a comma-delimited list of config file paths -being changed, and a comma-delimited a list of plugin packages being installed, +The t3c-check-reload app takes json input from stdin. +A comma-delimited list of config file paths being changed, +a comma-delimited a list of plugin packages being installed, and returns whether a reload or restart of the caching proxy service is necessary. @@ -58,25 +59,14 @@ Possible return values are: '' - no reload or restart is necessary. -# OPTIONS - --c, --changed-config-paths=value +# JSON Format - comma-delimited list of the full paths of all files changed - by t3c + {"changed_files":"","installed_plugins":""} +# OPTIONS -h, --help Print usage information and exit --m, --run-mode=value - - [badass | report | revalidate | syncds] run mode, default is - 'report' [report] - --p, --plugin-packages-installed=value - - comma-delimited list of ATS plugin packages which were - installed by t3c # AUTHORS diff --git a/cache-config/t3c-check-reload/t3c-check-reload.go b/cache-config/t3c-check-reload/t3c-check-reload.go index d73f6b10b2..7be2ec3c28 100644 --- a/cache-config/t3c-check-reload/t3c-check-reload.go +++ b/cache-config/t3c-check-reload/t3c-check-reload.go @@ -20,6 +20,7 @@ package main */ import ( + "encoding/json" "fmt" "os" "strings" @@ -32,18 +33,21 @@ import ( func main() { // presumably calculated by by t3c-check-refs // TODO remove? The blueprint says t3c/ORT will no longer install packages - pluginPackagesInstalledStr := getopt.StringLong("plugin-packages-installed", 'p', "", "comma-delimited list of ATS plugin packages which were installed by t3c") - // presumably calculated by t3c-diff - changedConfigFilesStr := getopt.StringLong("changed-config-paths", 'c', "", "comma-delimited list of the full paths of all files changed by t3c") + help := getopt.BoolLong("help", 'h', "Print usage information and exit") getopt.Parse() if *help { - getopt.PrintUsage(os.Stdout) + fmt.Println(usageStr()) os.Exit(0) } - changedConfigFiles := strings.Split(*changedConfigFilesStr, ",") + changedCfg := &ChangedCfg{} + if err := json.NewDecoder(os.Stdin).Decode(changedCfg); err != nil { + fmt.Println("Error reading json input", err) + } + + changedConfigFiles := strings.Split(changedCfg.ChangedFiles, ",") changedConfigFiles = StrMap(changedConfigFiles, strings.TrimSpace) changedConfigFiles = StrRemoveIf(changedConfigFiles, StrIsEmpty) @@ -51,7 +55,7 @@ func main() { // Probably not, because whatever told the installer to install them already knew that, // we shouldn't re-calculate it. - pluginPackagesInstalled := strings.Split(*pluginPackagesInstalledStr, ",") + pluginPackagesInstalled := strings.Split(changedCfg.InstalledPlugins, ",") pluginPackagesInstalled = StrMap(pluginPackagesInstalled, strings.TrimSpace) pluginPackagesInstalled = StrRemoveIf(pluginPackagesInstalled, StrIsEmpty) @@ -99,6 +103,11 @@ func main() { ExitNothing() } +type ChangedCfg struct { + ChangedFiles string `json:"changed_files"` + InstalledPlugins string `json:"installed_plugins"` +} + // ExitRestart returns the "needs restart" message and exits. func ExitRestart() { fmt.Fprintf(os.Stdout, t3cutil.ServiceNeedsRestart.String()+"\n") @@ -141,3 +150,9 @@ func StrRemoveIf(strs []string, fn func(str string) bool) []string { // StrIsEmpty returns whether str == "". Helper function for composing with other functions. func StrIsEmpty(str string) bool { return str == "" } + +func usageStr() string { + return `usage: t3c-check-reload [--help] +Accepts json data from stdin in in the following format: +{"changed_files":"","installed_plugins":""}` +} diff --git a/cache-config/t3c-diff/t3c-diff.go b/cache-config/t3c-diff/t3c-diff.go index 22a1d447d1..5eae3f95e3 100644 --- a/cache-config/t3c-diff/t3c-diff.go +++ b/cache-config/t3c-diff/t3c-diff.go @@ -36,8 +36,14 @@ import ( func main() { help := getopt.BoolLong("help", 'h', "Print usage info and exit") + lineComment := getopt.StringLong("line_comment", 'l', "#", "Comment symbol") + mode := getopt.IntLong("file-mode", 'm', 0644, "file mode default is 644") + fa := getopt.StringLong("file-a", 'a', "", "first diff file") + fb := getopt.StringLong("file-b", 'b', "", "second diff file") getopt.ParseV2() + log.Init(os.Stderr, os.Stderr, os.Stderr, os.Stderr, os.Stderr) + if *help { log.Errorln(usageStr) os.Exit(0) @@ -48,8 +54,8 @@ func main() { os.Exit(3) } - fileNameA := strings.TrimSpace(os.Args[1]) - fileNameB := strings.TrimSpace(os.Args[2]) + fileNameA := strings.TrimSpace(*fa) + fileNameB := strings.TrimSpace(*fb) if len(fileNameA) == 0 || len(fileNameB) == 0 { log.Errorln(usageStr) @@ -69,13 +75,13 @@ func main() { fileALines := strings.Split(string(fileA), "\n") fileALines = t3cutil.UnencodeFilter(fileALines) - fileALines = t3cutil.CommentsFilter(fileALines) + fileALines = t3cutil.CommentsFilter(fileALines, *lineComment) fileA = strings.Join(fileALines, "\n") fileA = t3cutil.NewLineFilter(fileA) fileBLines := strings.Split(string(fileB), "\n") fileBLines = t3cutil.UnencodeFilter(fileBLines) - fileBLines = t3cutil.CommentsFilter(fileBLines) + fileBLines = t3cutil.CommentsFilter(fileBLines, *lineComment) fileB = strings.Join(fileBLines, "\n") fileB = t3cutil.NewLineFilter(fileB) @@ -90,12 +96,24 @@ func main() { if fileAExisted != fileBExisted { os.Exit(1) } + switch { + case fileNameA != "stdin": + if t3cutil.PermCk(fileNameA, *mode) { + log.Infoln("File permissions are incorrect, should be ", fmt.Sprintf("%#o", *mode)) + os.Exit(1) + } + case fileNameB != "stdin": + if t3cutil.PermCk(fileNameB, *mode) { + log.Infoln("File permissions are incorrect, should be ", fmt.Sprintf("%#o", *mode)) + os.Exit(1) + } + } os.Exit(0) } const usageStr = `usage: t3c-diff [--help] - + -a -b -l -m Either file may be 'stdin', in which case that file is read from stdin. Either file may not exist. @@ -103,6 +121,9 @@ Either file may not exist. Prints the diff to stdout, and returns the exit code 0 if there was no diff, 1 if there was a diff. If one file exists but the other doesn't, it will always be a diff. +Mode is file permissions in octal format, default is 0644. +Line comment is a character that signals the line is a comment, default is # + Note this means there may be no diff text printed to stdout but still exit 1 indicating a diff if the file being created or deleted is semantically empty.` diff --git a/cache-config/t3c-generate/cfgfile/all.go b/cache-config/t3c-generate/cfgfile/all.go index c1df2a7842..c8a6f4658b 100644 --- a/cache-config/t3c-generate/cfgfile/all.go +++ b/cache-config/t3c-generate/cfgfile/all.go @@ -58,14 +58,14 @@ func GetAllConfigs( if cfg.RevalOnly && fi.Name != atscfg.RegexRevalidateFileName { continue } - txt, contentType, lineComment, err := GetConfigFile(toData, fi, hdrCommentTxt, cfg) + txt, contentType, secure, lineComment, err := GetConfigFile(toData, fi, hdrCommentTxt, cfg) if err != nil { return nil, errors.New("getting config file '" + fi.Name + "': " + err.Error()) } if fi.Name == atscfg.SSLMultiCertConfigFileName { hasSSLMultiCertConfig = true } - configs = append(configs, t3cutil.ATSConfigFile{Name: fi.Name, Path: fi.Path, Text: txt, ContentType: contentType, LineComment: lineComment}) + configs = append(configs, t3cutil.ATSConfigFile{Name: fi.Name, Path: fi.Path, Text: txt, Secure: secure, ContentType: contentType, LineComment: lineComment}) } if hasSSLMultiCertConfig { diff --git a/cache-config/t3c-generate/cfgfile/cfgfile_test.go b/cache-config/t3c-generate/cfgfile/cfgfile_test.go index de0e79ed8e..71f5873d1f 100644 --- a/cache-config/t3c-generate/cfgfile/cfgfile_test.go +++ b/cache-config/t3c-generate/cfgfile/cfgfile_test.go @@ -40,12 +40,14 @@ func TestWriteConfigs(t *testing.T) { Name: "config0.txt", Path: "/my/config0/location", Text: "config0", + Secure: false, ContentType: "text/plain", }, { Name: "config1.txt", Path: "/my/config1/location", Text: "config2,foo", + Secure: false, ContentType: "text/csv", }, } @@ -56,18 +58,18 @@ func TestWriteConfigs(t *testing.T) { actual := buf.String() - expected0 := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","text":"config2,foo"}]` + expected0 := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","secure":false,"text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","secure":false,"text":"config2,foo"}]` if !strings.Contains(actual, expected0) { t.Errorf("WriteConfigs expected '%v' actual '%v'", expected0, actual) } - expected1 := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","text":"config2,foo"}]` + expected1 := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","secure":false,"text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","secure":false,"text":"config2,foo"}]` if !strings.Contains(actual, expected1) { t.Errorf("WriteConfigs expected config1 '%v' actual '%v'", expected1, actual) } - expectedPrefix := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","text":"config2,foo"}]` + expectedPrefix := `[{"name":"config0.txt","path":"/my/config0/location","content_type":"text/plain","line_comment":"","secure":false,"text":"config0"},{"name":"config1.txt","path":"/my/config1/location","content_type":"text/csv","line_comment":"","secure":false,"text":"config2,foo"}]` if !strings.HasPrefix(actual, expectedPrefix) { t.Errorf("WriteConfigs expected prefix '%v' actual '%v'", expectedPrefix, actual) } diff --git a/cache-config/t3c-generate/cfgfile/routing.go b/cache-config/t3c-generate/cfgfile/routing.go index 49e4c3b316..0e34832ab6 100644 --- a/cache-config/t3c-generate/cfgfile/routing.go +++ b/cache-config/t3c-generate/cfgfile/routing.go @@ -32,7 +32,7 @@ import ( // # DO NOT EDIT - Generated for odol-atsec-sea-22 by Traffic Ops (https://trafficops.comcast.net/) on Mon Oct 26 16:22:19 UTC 2020 // GetConfigFile returns the text of the generated config file, the MIME Content Type of the config file, and any error. -func GetConfigFile(toData *t3cutil.ConfigData, fileInfo atscfg.CfgMeta, hdrCommentTxt string, thiscfg config.Cfg) (string, string, string, error) { +func GetConfigFile(toData *t3cutil.ConfigData, fileInfo atscfg.CfgMeta, hdrCommentTxt string, thiscfg config.Cfg) (string, string, bool, string, error) { start := time.Now() defer func() { log.Infof("GetConfigFile %v took %v\n", fileInfo.Name, time.Since(start).Round(time.Millisecond)) @@ -44,9 +44,9 @@ func GetConfigFile(toData *t3cutil.ConfigData, fileInfo atscfg.CfgMeta, hdrComme logWarnings("getting config file '"+fileInfo.Name+"': ", cfg.Warnings) if err != nil { - return "", "", "", err + return "", "", false, "", err } - return cfg.Text, cfg.ContentType, cfg.LineComment, nil + return cfg.Text, cfg.ContentType, cfg.Secure, cfg.LineComment, nil } type ConfigFileFunc func(toData *t3cutil.ConfigData, fileName string, hdrCommentTxt string, cfg config.Cfg) (atscfg.Cfg, error) diff --git a/cache-config/t3c-generate/cfgfile/sslkeys.go b/cache-config/t3c-generate/cfgfile/sslkeys.go index 46ef9b398f..478b38f93f 100644 --- a/cache-config/t3c-generate/cfgfile/sslkeys.go +++ b/cache-config/t3c-generate/cfgfile/sslkeys.go @@ -65,12 +65,14 @@ func GetSSLCertsAndKeyFiles(toData *t3cutil.ConfigData) ([]t3cutil.ATSConfigFile keyFile.Name = keyName keyFile.Path = "/opt/trafficserver/etc/trafficserver/ssl/" // TODO read config, don't hard code keyFile.Text = string(key) + keyFile.Secure = true configs = append(configs, keyFile) certFile := t3cutil.ATSConfigFile{} certFile.Name = certName certFile.Path = "/opt/trafficserver/etc/trafficserver/ssl/" // TODO read config, don't hard code certFile.Text = string(cert) + certFile.Secure = true configs = append(configs, certFile) } diff --git a/cache-config/t3cutil/t3cutil.go b/cache-config/t3cutil/t3cutil.go index 4cbe85ccab..59dea1f5e9 100644 --- a/cache-config/t3cutil/t3cutil.go +++ b/cache-config/t3cutil/t3cutil.go @@ -37,6 +37,7 @@ type ATSConfigFile struct { Path string `json:"path"` ContentType string `json:"content_type"` LineComment string `json:"line_comment"` + Secure bool `json:"secure"` Text string `json:"text"` } @@ -52,17 +53,17 @@ func (fs ATSConfigFiles) Less(i, j int) bool { } func (fs ATSConfigFiles) Swap(i, j int) { fs[i], fs[j] = fs[j], fs[i] } -// commentsFilter is used to remove comment +// CommentsFilter is used to remove comment // lines from config files while making // comparisons. -func CommentsFilter(body []string) []string { +func CommentsFilter(body []string, lineComment string) []string { var newlines []string newlines = make([]string, 0) for ii := range body { line := body[ii] - if strings.HasPrefix(line, "#") { + if strings.HasPrefix(line, lineComment) { continue } newlines = append(newlines, line) @@ -71,6 +72,19 @@ func CommentsFilter(body []string) []string { return newlines } +// PermCk will compare file permissions against existing file and octal permission provided. +func PermCk(path string, perm int) bool { + mode := os.FileMode(perm) + file, err := os.Stat(path) + if err != nil { + fmt.Println("Error getting file status", path) + } + if file.Mode() != mode.Perm() { + return true + } + return false +} + // NewLineFilter removes carriage returns // from config files while making comparisons. func NewLineFilter(str string) string { diff --git a/cache-config/testing/ort-tests/t3c-check-reload_test.go b/cache-config/testing/ort-tests/t3c-check-reload_test.go index ee33a9fd1a..49c4f337e9 100644 --- a/cache-config/testing/ort-tests/t3c-check-reload_test.go +++ b/cache-config/testing/ort-tests/t3c-check-reload_test.go @@ -15,6 +15,7 @@ package orttest */ import ( + "encoding/json" "strings" "testing" @@ -22,103 +23,139 @@ import ( ) func TestCheckReload(t *testing.T) { + type ChangedCfg struct { + ChangedFiles string `json:"changed_files"` + InstalledPlugins string `json:"installed_plugins"` + } + type argsResults struct { - configs []string - packages []string + configs ChangedCfg mode string expected string expectedErr bool } + argsExpected := []argsResults{ { - configs: []string{"/etc/trafficserver/remap.config", "/etc/trafficserver/parent.config"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/etc/trafficserver/remap.config,/etc/trafficserver/parent.config", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"/etc/trafficserver/anything.foo"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/etc/trafficserver/anything.foo", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"/opt/trafficserver/etc/trafficserver/anything.foo"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/opt/trafficserver/etc/trafficserver/anything.foo", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"/foo/bar/hdr_rw_foo.config"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/foo/bar/hdr_rw_foo.config", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"/foo/bar/uri_signing_dsname.config"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/foo/bar/uri_signing_dsname.config", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"/foo/bar/url_sig_dsname.config", "foo"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/foo/bar/url_sig_dsname.config,foo", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"plugin.config", "foo"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "plugin.config,foo", + InstalledPlugins: "", + }, expected: "restart", }, { - configs: []string{"/etc/trafficserver/anything.foo"}, - packages: []string{"anything"}, + configs: ChangedCfg{ + ChangedFiles: "/etc/trafficserver/anything.foo", + InstalledPlugins: "anything", + }, expected: "restart", }, { - configs: nil, - packages: []string{"anything"}, + configs: ChangedCfg{ + ChangedFiles: "", + InstalledPlugins: "anything", + }, expected: "restart", }, { - configs: nil, - packages: []string{"anything", "anythingelse"}, + configs: ChangedCfg{ + ChangedFiles: "", + InstalledPlugins: "anything,anythingelse", + }, expected: "restart", }, { - configs: []string{"/foo/bar/ssl_multicert.config"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/foo/bar/ssl_multicert.config", + InstalledPlugins: "", + }, expected: "reload", }, { - configs: []string{"foo"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "foo", + InstalledPlugins: "", + }, expected: "", }, { - configs: []string{"/foo/bar/baz.config"}, - packages: nil, + configs: ChangedCfg{ + ChangedFiles: "/foo/bar/baz.config", + InstalledPlugins: "", + }, expected: "", }, } for _, ae := range argsExpected { - out, code := t3cCheckReload(ae.configs, ae.packages) + config, err := json.Marshal(ae.configs) + if err != nil { + t.Errorf("Error: %s", err) + } + out, code := t3cCheckReload(config) out = strings.TrimSpace(out) if !ae.expectedErr && code != 0 { - t.Errorf("expected configs %+v packages %+v would not error, actual: code %v output '%v'", ae.configs, ae.packages, code, out) + t.Errorf("expected configs %+v packages %+v would not error, actual: code %v output '%v'", + ae.configs.ChangedFiles, ae.configs.InstalledPlugins, code, out) continue } else if ae.expectedErr && code == 0 { - t.Errorf("expected configs %+v packages %+v would error, actual: no error", ae.configs, ae.packages) + t.Errorf("expected configs %+v packages %+v would error, actual: no error", + ae.configs.ChangedFiles, ae.configs.InstalledPlugins) continue } if out != ae.expected { - t.Errorf("expected configs %+v packages %+v would need '%v', actual: '%v'", ae.configs, ae.packages, ae.expected, out) + t.Errorf("expected configs %+v packages %+v would need '%v', actual: '%v'", + ae.configs.ChangedFiles, ae.configs.InstalledPlugins, ae.expected, out) } } } -func t3cCheckReload(changedConfigPaths []string, packagesInstalled []string) (string, int) { +func t3cCheckReload(configs []byte) (string, int) { args := []string{ "check", "reload", - "--changed-config-paths=" + strings.Join(changedConfigPaths, ","), - "--plugin-packages-installed=" + strings.Join(packagesInstalled, ","), } - stdOut, _, exitCode := t3cutil.Do("t3c", args...) + stdOut, _, exitCode := t3cutil.DoInput(configs, "t3c", args...) return string(stdOut), exitCode } diff --git a/lib/go-atscfg/atscfg.go b/lib/go-atscfg/atscfg.go index b30b27538b..ca3dc3b0e7 100644 --- a/lib/go-atscfg/atscfg.go +++ b/lib/go-atscfg/atscfg.go @@ -117,6 +117,7 @@ type Cfg struct { Text string ContentType string LineComment string + Secure bool Warnings []string } diff --git a/lib/go-atscfg/sslmulticertdotconfig.go b/lib/go-atscfg/sslmulticertdotconfig.go index 4c5ffa157f..a48e430a18 100644 --- a/lib/go-atscfg/sslmulticertdotconfig.go +++ b/lib/go-atscfg/sslmulticertdotconfig.go @@ -72,6 +72,7 @@ func MakeSSLMultiCertDotConfig( Text: txt, ContentType: ContentTypeSSLMultiCertDotConfig, LineComment: LineCommentSSLMultiCertDotConfig, + Secure: true, Warnings: warnings, }, nil } diff --git a/lib/go-atscfg/urisigningconfig.go b/lib/go-atscfg/urisigningconfig.go index 600ef75b57..3566b0f5e4 100644 --- a/lib/go-atscfg/urisigningconfig.go +++ b/lib/go-atscfg/urisigningconfig.go @@ -57,6 +57,7 @@ func MakeURISigningConfig( Text: string(uriSigningKeyBts), ContentType: ContentTypeURISigningDotConfig, LineComment: LineCommentURISigningDotConfig, + Secure: true, Warnings: warnings, }, nil } diff --git a/lib/go-atscfg/urlsigconfig.go b/lib/go-atscfg/urlsigconfig.go index 22bb4c7995..35a2b91d21 100644 --- a/lib/go-atscfg/urlsigconfig.go +++ b/lib/go-atscfg/urlsigconfig.go @@ -93,6 +93,7 @@ func MakeURLSigConfig( Text: text, ContentType: ContentTypeURLSig, LineComment: LineCommentURLSig, + Secure: true, Warnings: warnings, }, nil }