This is an automated email from the ASF dual-hosted git repository.
rawlin 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 06a327a5da Fix tc-health-client env special chars (#6933)
06a327a5da is described below
commit 06a327a5da4bf655dc05cbb5fbe37842753cc152
Author: Robert O Butts <[email protected]>
AuthorDate: Tue Jun 28 15:41:37 2022 -0600
Fix tc-health-client env special chars (#6933)
---
CHANGELOG.md | 1 +
tc-health-client/config/config.go | 84 ++++++++++++++++++----------------
tc-health-client/config/config_test.go | 44 ++++++++++++++++++
3 files changed, 90 insertions(+), 39 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 862c0cb548..2e965a12c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,6 +59,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
- [#6712](https://github.com/apache/trafficcontrol/issues/6712) - Fixed error
when loading the Traffic Vault schema from `create_tables.sql` more than once.
- [#6834](https://github.com/apache/trafficcontrol/issues/6834) - In API 4.0,
fixed `GET` for `/servers` to display all profiles irrespective of the index
position. Also, replaced query param `profileId` with `profileName`.
- [#6299](https://github.com/apache/trafficcontrol/issues/6299) User
representations don't match
+- [#6933](https://github.com/apache/trafficcontrol/issues/6933) Fixed
tc-health-client to handle credentials files with special characters in
variables
- [#6776](https://github.com/apache/trafficcontrol/issues/6776) User
properties only required sometimes
### Removed
diff --git a/tc-health-client/config/config.go
b/tc-health-client/config/config.go
index 99dc1d870c..12f526115b 100644
--- a/tc-health-client/config/config.go
+++ b/tc-health-client/config/config.go
@@ -20,7 +20,6 @@ package config
*/
import (
- "bufio"
"crypto/md5"
"encoding/binary"
"encoding/json"
@@ -34,6 +33,7 @@ import (
"strings"
"time"
+ "github.com/apache/trafficcontrol/cache-config/t3cutil"
"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/tc-health-client/util"
toclient "github.com/apache/trafficcontrol/traffic_ops/v3-client"
@@ -126,47 +126,13 @@ func ReadCredentials(cfg *Cfg, updating bool) error {
return nil
}
- f, err := os.Open(fn.Filename)
+ err := error(nil)
+ cfg.TOUrl, cfg.TOUser, cfg.TOPass, err =
getCredentialsFromFile(cfg.CredentialFile.Filename)
if err != nil {
- return errors.New("failed to open + " + fn.Filename + " :" +
err.Error())
+ return errors.New("reading credentials from file '" +
fn.Filename + "' :" + err.Error())
}
- defer f.Close()
- var to_pass_found = false
- var to_url_found = false
- var to_user_found = false
-
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
- if strings.HasPrefix(line, "#") {
- continue
- }
- fields := strings.Split(line, " ")
- for _, v := range fields {
- if strings.HasPrefix(v, "TO_") {
- sf := strings.Split(v, "=")
- if len(sf) == 2 {
- if sf[0] == "TO_URL" {
- // parse the url after trimming
off any surrounding double quotes
- cfg.TOUrl = strings.Trim(sf[1],
"\"")
- to_url_found = true
- }
- if sf[0] == "TO_USER" {
- // set the TOUser after
trimming off any surrounding quotes.
- cfg.TOUser =
strings.Trim(sf[1], "\"")
- to_user_found = true
- }
- // set the TOPass after trimming off
any surrounding quotes.
- if sf[0] == "TO_PASS" {
- cfg.TOPass =
strings.Trim(sf[1], "\"")
- to_pass_found = true
- }
- }
- }
- }
- }
- if !to_url_found && !to_user_found && !to_pass_found {
+ if cfg.TOUrl == "" || cfg.TOUser == "" || cfg.TOPass == "" {
return errors.New("failed to retrieve one or more TrafficOps
credentails")
}
@@ -415,3 +381,43 @@ func UpdateConfig(cfg *Cfg, newCfg *Cfg) {
func Usage() {
getopt.PrintUsage(os.Stdout)
}
+
+// getCredentialsFromFile gets the TO URL, user, and password from an
environment variable file.
+// from environment variables declared in a credentials file bash script, if
they exist.
+//
+// Returns the TO URL, user, password, and any error.
+//
+// Note this returns empty strings with no error if the file doesn't exist,
+// or if any variables aren't declared.
+//
+func getCredentialsFromFile(filePath string) (string, string, string, error) {
+
+ if inf, err := os.Stat(filePath); os.IsNotExist(err) {
+ return "", "", "", nil
+ } else if inf.IsDir() {
+ return "", "", "", errors.New("credentials path is a directory,
must be a file")
+ }
+
+ // we execute sh and source the file to get the environment variables,
+ // because it's easier and more accurate than writing our own sh env
var parser.
+
+ stdOut, stdErr, code := t3cutil.Do("sh", "-c", `(source "`+filePath+`"
&& printf "${TO_URL}\n")`)
+ if code != 0 {
+ return "", "", "", fmt.Errorf("getting credentials from file
returned error code %v stderr '%v' stdout '%v'", code, string(stdErr),
string(stdOut))
+ }
+ toURL := strings.TrimSpace(string(stdOut))
+
+ stdOut, stdErr, code = t3cutil.Do("sh", "-c", `(source "`+filePath+`"
&& printf "${TO_USER}\n")`)
+ if code != 0 {
+ return "", "", "", fmt.Errorf("getting credentials from file
returned error code %v stderr '%v' stdout '%v'", code, string(stdErr),
string(stdOut))
+ }
+ toUser := strings.TrimSpace(string(stdOut))
+
+ stdOut, stdErr, code = t3cutil.Do("sh", "-c", `(source "`+filePath+`"
&& printf "${TO_PASS}\n")`)
+ if code != 0 {
+ return "", "", "", fmt.Errorf("getting credentials from file
returned error code %v stderr '%v' stdout '%v'", code, string(stdErr),
string(stdOut))
+ }
+ toPass := strings.TrimSpace(string(stdOut))
+
+ return toURL, toUser, toPass, nil
+}
diff --git a/tc-health-client/config/config_test.go
b/tc-health-client/config/config_test.go
index 2d286494ac..db3541b0f1 100644
--- a/tc-health-client/config/config_test.go
+++ b/tc-health-client/config/config_test.go
@@ -20,6 +20,7 @@ package config
*/
import (
+ "os"
"testing"
"github.com/apache/trafficcontrol/tc-health-client/util"
@@ -113,3 +114,46 @@ func TestLoadConfig(t *testing.T) {
t.Fatalf("expected '%s', got %s\n", expect, bindir)
}
}
+
+func TestGetCredentialsFromFile(t *testing.T) {
+
+ fi, err := os.CreateTemp("", "creds")
+ if err != nil {
+ t.Fatalf("creating temp credentials file: %v", err)
+ }
+ defer os.Remove(fi.Name())
+
+ credsFileContents := `
+# credentials
+export TO_URL="https://trafficops.example.net"
+export TO_USER="myuser"
+export TO_PASS="mypass"
+`
+ expectedURL := `https://trafficops.example.net`
+ expectedUser := `myuser`
+ expectedPass := `mypass`
+
+ if _, err := fi.Write([]byte(credsFileContents)); err != nil {
+ t.Fatalf("writing temp credentials file: %v", err)
+ }
+
+ if err := fi.Close(); err != nil {
+ t.Fatalf("closing temp credentials file: %v", err)
+ }
+
+ credsFilePath := fi.Name()
+ toURL, toUser, toPass, err := getCredentialsFromFile(credsFilePath)
+ if err != nil {
+ t.Fatalf("getting temp credentials file: %v", err)
+ }
+ if toURL != expectedURL {
+ t.Errorf("credentials file TO URL expected '%v' actual '%v'",
expectedURL, toURL)
+ }
+ if toUser != expectedUser {
+ t.Errorf("credentials file TO User expected '%v' actual '%v'",
expectedUser, toUser)
+ }
+ if toPass != expectedPass {
+ t.Errorf("credentials file TO Pass expected '%v' actual '%v'",
expectedPass, toPass)
+ }
+
+}