diff --git a/CHANGELOG.md b/CHANGELOG.md index 67bdef8de6..dd9be2d21d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added a Traffic Ops endpoint and Traffic Portal page to view all CDNi configuration update requests and approve or deny. - Added layered profile feature to 4.0 for `GET` /deliveryservices/{id}/servers/ and /deliveryservices/{id}/servers/eligible. - Change to t3c regex_revalidate so that STALE is no longer explicitly added for default revalidate rule for ATS version backwards compatibility. +- Change to t3c diff to flag a config file for replacement if owner/group settings are not `ats` [#6879](https://github.com/apache/trafficcontrol/issues/6879). ### Fixed - [#6291](https://github.com/apache/trafficcontrol/issues/6291) Prevent Traffic Ops from modifying and/or deleting reserved statuses. diff --git a/cache-config/t3c-apply/torequest/cmd.go b/cache-config/t3c-apply/torequest/cmd.go index 74b80da0b2..fcf347e634 100644 --- a/cache-config/t3c-apply/torequest/cmd.go +++ b/cache-config/t3c-apply/torequest/cmd.go @@ -277,12 +277,14 @@ func sendUpdate(cfg config.Cfg, configApplyTime, revalApplyTime *time.Time, conf // 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, perm os.FileMode) (bool, error) { +func diff(cfg config.Cfg, newFile []byte, fileLocation string, reportOnly bool, perm os.FileMode, uid int, gid int) (bool, error) { diffMsg := "" args := []string{ "--file-a=stdin", "--file-b=" + fileLocation, "--file-mode=" + fmt.Sprintf("%#o", perm), + "--file-uid=" + fmt.Sprint(uid), + "--file-gid=" + fmt.Sprint(gid), } stdOut, stdErr, code := t3cutil.DoInput(newFile, `t3c-diff`, args...) diff --git a/cache-config/t3c-apply/torequest/torequest.go b/cache-config/t3c-apply/torequest/torequest.go index 7a107d7c9b..e61168209e 100644 --- a/cache-config/t3c-apply/torequest/torequest.go +++ b/cache-config/t3c-apply/torequest/torequest.go @@ -237,7 +237,7 @@ func (r *TrafficOpsReq) checkConfigFile(cfg *ConfigFile, filesAdding []string) e } } - changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path, r.Cfg.ReportOnly, cfg.Perm) + changeNeeded, err := diff(r.Cfg, cfg.Body, cfg.Path, r.Cfg.ReportOnly, cfg.Perm, cfg.Uid, cfg.Gid) if err != nil { return errors.New("getting diff: " + err.Error()) diff --git a/cache-config/t3c-diff/README.md b/cache-config/t3c-diff/README.md index 00eec199cf..fd3e945cf7 100644 --- a/cache-config/t3c-diff/README.md +++ b/cache-config/t3c-diff/README.md @@ -38,7 +38,7 @@ t3c-diff - Traffic Control Cache Configuration contextual diff tool # SYNOPSIS -t3c-diff \ \ +t3c-diff \-a \ \-b \ \-l \ \-m \ \-u \ \-g \ [\-\-help] @@ -58,12 +58,37 @@ If one file exists but the other doesn't, it will always be a diff. 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. +Mode is file permissions in octal format, default is 0644. +Line comment is a character that signals the line is a comment, default is # + +Uid is the User id the file being checked should have, default is running process's uid. +Gid is the Group id the file being checked should have, default is running process's gid.` + # OPTIONS +-a, -\-file-a + + Path to first diff file, can also be stdin. + +-b, -\-file-b + Path to second diff file, can also be stdin. + +-g, -\-file-gid + Group id the file being checked should have. + -h, -\-help Print usage info and exit. +-l, -\-line_comment + Symbol used to denote the line is a comment. + +-m, -\-file-mode + Octal permissions mode for file being checked. + +-u, -\-file-uid + User id the file being checked should have. + -V, -\-version Print version information and exit. diff --git a/cache-config/t3c-diff/t3c-diff.go b/cache-config/t3c-diff/t3c-diff.go index e6f6f5ae59..e80eb39a4b 100644 --- a/cache-config/t3c-diff/t3c-diff.go +++ b/cache-config/t3c-diff/t3c-diff.go @@ -49,6 +49,8 @@ func main() { version := getopt.BoolLong("version", 'V', "Print version information and exit") lineComment := getopt.StringLong("line_comment", 'l', "#", "Comment symbol") mode := getopt.IntLong("file-mode", 'm', 0644, "file mode default is 644") + uid := getopt.IntLong("file-uid", 'u', 0, "User id the file being checked should have, default is running process's uid") + gid := getopt.IntLong("file-gid", 'g', 0, "Group id the file being checked should have, default is running process's gid") fa := getopt.StringLong("file-a", 'a', "", "first diff file") fb := getopt.StringLong("file-b", 'b', "", "second diff file") getopt.ParseV2() @@ -76,6 +78,14 @@ func main() { os.Exit(4) } + if *uid == 0 { + *uid = os.Geteuid() + } + + if *gid == 0 { + *gid = os.Getgid() + } + fileA, fileAExisted, err := readFileOrStdin(fileNameA) if err != nil { log.Errorf("error reading first: %s\n", err.Error()) @@ -116,18 +126,26 @@ func main() { log.Infoln("File permissions are incorrect, should be ", fmt.Sprintf("%#o", *mode)) os.Exit(1) } + if t3cutil.OwnershipCk(fileNameA, *uid, *gid) { + log.Infoln("user or group ownership are incorrect, should be ", fmt.Sprintf("Uid:%d Gid:%d", *uid, *gid)) + 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) } + if t3cutil.OwnershipCk(fileNameB, *uid, *gid) { + log.Infoln("user or group ownership are incorrect, should be ", fmt.Sprintf("Uid:%d Gid:%d", *uid, *gid)) + os.Exit(1) + } } os.Exit(0) } const usageStr = `usage: t3c-diff [--help] - -a -b -l -m + -a -b -l -m -u -g Either file may be 'stdin', in which case that file is read from stdin. Either file may not exist. @@ -138,6 +156,9 @@ 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 # +Uid is the User id the file being checked should have, default is running process's uid. +Gid is the Group id the file being checked should have, default is running process's gid. + 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/t3cutil/t3cutil.go b/cache-config/t3cutil/t3cutil.go index 5678ba9c3f..782548301f 100644 --- a/cache-config/t3cutil/t3cutil.go +++ b/cache-config/t3cutil/t3cutil.go @@ -30,6 +30,7 @@ import ( "os/exec" "regexp" "strings" + "syscall" ) type ATSConfigFile struct { @@ -86,6 +87,19 @@ func PermCk(path string, perm int) bool { return false } +// OwnershipCk will compare owner and group settings against existing file and owner/group settings provided. +func OwnershipCk(path string, uid int, gid int) bool { + file, err := os.Stat(path) + if err != nil { + fmt.Println("error getting file status", path) + } + stat := file.Sys().(*syscall.Stat_t) + if uid != int(stat.Uid) || gid != int(stat.Gid) { + return true + } + return false +} + // NewLineFilter removes carriage returns // from config files while making comparisons. func NewLineFilter(str string) string {