fix for double merge issue

update unit-test data

fix gosec

fix gosec

fix gosec
This commit is contained in:
KIRAN DARBHA
2019-09-18 17:56:33 +05:30
committed by Arthur J Barr
parent 8505579b37
commit 4de32ab8d2
3 changed files with 157 additions and 58 deletions

View File

@@ -24,7 +24,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"github.com/ibm-messaging/mq-container/pkg/mqini" "github.com/ibm-messaging/mq-container/pkg/mqini"
@@ -33,7 +32,6 @@ import (
var qmgrDir string var qmgrDir string
var stanzasQMINI []string var stanzasQMINI []string
var stanzasMQATINI []string var stanzasMQATINI []string
// AddStanzas reads supplied MQ INI configuration files and updates the stanzas // AddStanzas reads supplied MQ INI configuration files and updates the stanzas
@@ -59,6 +57,7 @@ func AddStanzas(qmname string) error {
return nil return nil
} }
//read user supplied config file.
iniFileBytes, err := ioutil.ReadFile(files[0]) iniFileBytes, err := ioutil.ReadFile(files[0])
if err != nil { if err != nil {
return err return err
@@ -72,11 +71,11 @@ func AddStanzas(qmname string) error {
PopulateAllAvailableStanzas() PopulateAllAvailableStanzas()
// Update the qmgr ini file with user config. // Update the qmgr ini file with user config.
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig) qminiConfiglist, qmatConfiglist, err := PrepareConfigStanzasToWrite(userconfig)
if err != nil { if err != nil {
return err return err
} }
err = writeConfigStanzas(qmConfig, atConfig) err = writeConfigStanzas(qminiConfiglist, qmatConfiglist)
if err != nil { if err != nil {
return err return err
} }
@@ -126,7 +125,7 @@ func getIniFileList() ([]string, error) {
// PrepareConfigStanzasToWrite Reads through the user supplied INI config file and prepares list of // PrepareConfigStanzasToWrite Reads through the user supplied INI config file and prepares list of
// updates to be written into corresponding mq ini files (qm.ini and/or mqat.ini files) // updates to be written into corresponding mq ini files (qm.ini and/or mqat.ini files)
func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) { func PrepareConfigStanzasToWrite(userconfig string) ([]string, []string, error) {
var qminiConfigStr string var qminiConfigStr string
var mqatiniConfigStr string var mqatiniConfigStr string
@@ -134,16 +133,18 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) {
// #nosec G304 - qmgrDir filepath is derived from dspmqinf // #nosec G304 - qmgrDir filepath is derived from dspmqinf
iniFileBytes, err := ioutil.ReadFile(filepath.Join(qmgrDir, "qm.ini")) iniFileBytes, err := ioutil.ReadFile(filepath.Join(qmgrDir, "qm.ini"))
if err != nil { if err != nil {
return "", "", err return nil, nil, err
} }
qminiConfigStr = string(iniFileBytes) qminiConfigStr = string(iniFileBytes)
qminiConfiglist := strings.Split(qminiConfigStr, "\n")
// #nosec G304 - qmgrDir filepath is derived from dspmqinf // #nosec G304 - qmgrDir filepath is derived from dspmqinf
iniFileBytes, err = ioutil.ReadFile(filepath.Join(qmgrDir, "mqat.ini")) iniFileBytes, err = ioutil.ReadFile(filepath.Join(qmgrDir, "mqat.ini"))
if err != nil { if err != nil {
return "", "", err return nil, nil, err
} }
mqatiniConfigStr = string(iniFileBytes) mqatiniConfigStr = string(iniFileBytes)
qmatConfiglist := strings.Split(mqatiniConfigStr, "\n")
stanzaListMerge := make(map[string]strings.Builder) stanzaListMerge := make(map[string]strings.Builder)
stanzaListAppend := make(map[string]strings.Builder) stanzaListAppend := make(map[string]strings.Builder)
@@ -158,10 +159,16 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) {
// Read through the user file and prepare what we want. // Read through the user file and prepare what we want.
for scanner.Scan() { for scanner.Scan() {
//if this is comment or an empty line, ignore it.
if strings.HasPrefix(scanner.Text(), "#") || len(strings.TrimSpace(scanner.Text())) == 0 {
continue
}
//thumb rule - all stanzas have ":".
if strings.Contains(scanner.Text(), ":") { if strings.Contains(scanner.Text(), ":") {
stanza = strings.TrimSpace(scanner.Text())
consumetoAppend = false consumetoAppend = false
consumeToMerge = false consumeToMerge = false
stanza = scanner.Text()
// Check if this stanza exists in the qm.ini/mqat.ini files // Check if this stanza exists in the qm.ini/mqat.ini files
if strings.Contains(qminiConfigStr, stanza) || if strings.Contains(qminiConfigStr, stanza) ||
(strings.Contains(mqatiniConfigStr, stanza) && !(strings.Contains(stanza, "ApplicationTrace"))) { (strings.Contains(mqatiniConfigStr, stanza) && !(strings.Contains(stanza, "ApplicationTrace"))) {
@@ -179,7 +186,7 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) {
sb := stanzaListAppend[stanza] sb := stanzaListAppend[stanza]
_, err := sb.WriteString(scanner.Text() + "\n") _, err := sb.WriteString(scanner.Text() + "\n")
if err != nil { if err != nil {
return "", "", err return nil, nil, err
} }
stanzaListAppend[stanza] = sb stanzaListAppend[stanza] = sb
} }
@@ -187,14 +194,14 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) {
sb := stanzaListMerge[stanza] sb := stanzaListMerge[stanza]
_, err := sb.WriteString(scanner.Text() + "\n") _, err := sb.WriteString(scanner.Text() + "\n")
if err != nil { if err != nil {
return "", "", err return nil, nil, err
} }
stanzaListMerge[stanza] = sb stanzaListMerge[stanza] = sb
} }
} }
} }
// Merge if stanza exits // do merge.
if len(stanzaListMerge) > 0 { if len(stanzaListMerge) > 0 {
for key := range stanzaListMerge { for key := range stanzaListMerge {
toWrite, filename := ValidateStanzaToWrite(key) toWrite, filename := ValidateStanzaToWrite(key)
@@ -202,37 +209,39 @@ func PrepareConfigStanzasToWrite(userconfig string) (string, string, error) {
attrList := stanzaListMerge[key] attrList := stanzaListMerge[key]
switch filename { switch filename {
case "qm.ini": case "qm.ini":
qminiConfigStr = prepareStanzasToMerge(key, attrList, qminiConfigStr) qminiConfiglist, err = prepareStanzasToMerge(key, attrList, qminiConfiglist)
if err != nil {
return nil, nil, err
}
case "mqat.ini": case "mqat.ini":
mqatiniConfigStr = prepareStanzasToMerge(key, attrList, mqatiniConfigStr) qmatConfiglist, err = prepareStanzasToMerge(key, attrList, qmatConfiglist)
if err != nil {
return nil, nil, err
}
default: default:
} }
} }
} }
} }
// Append new stanzas. // do append.
if len(stanzaListAppend) > 0 { if len(stanzaListAppend) > 0 {
for key := range stanzaListAppend { for key := range stanzaListAppend {
attrList := stanzaListAppend[key] attrList := stanzaListAppend[key]
if strings.Contains(strings.Join(stanzasMQATINI, ", "), strings.TrimSuffix(strings.TrimSpace(key), ":")) { if strings.Contains(strings.Join(stanzasMQATINI, ", "), strings.TrimSuffix(strings.TrimSpace(key), ":")) {
mqatiniConfigStr = prepareStanzasToAppend(key, attrList, mqatiniConfigStr) qmatConfiglist = prepareStanzasToAppend(key, attrList, qmatConfiglist)
} else { } else {
qminiConfigStr = prepareStanzasToAppend(key, attrList, qminiConfigStr) qminiConfiglist = prepareStanzasToAppend(key, attrList, qminiConfiglist)
} }
} }
} }
return qminiConfigStr, mqatiniConfigStr, nil return qminiConfiglist, qmatConfiglist, nil
} }
// ValidateStanzaToWrite validates stanza to be written and the file it belongs to. // ValidateStanzaToWrite validates stanza to be written and the file it belongs to.
func ValidateStanzaToWrite(stanza string) (bool, string) { func ValidateStanzaToWrite(stanza string) (bool, string) {
stanza = strings.TrimSpace(stanza) stanza = strings.TrimSuffix(strings.TrimSpace(stanza), ":")
if strings.Contains(stanza, ":") {
stanza = stanza[:len(stanza)-1]
}
if strings.Contains(strings.Join(stanzasQMINI, ", "), stanza) { if strings.Contains(strings.Join(stanzasQMINI, ", "), stanza) {
return true, "qm.ini" return true, "qm.ini"
} else if strings.Contains(strings.Join(stanzasMQATINI, ", "), stanza) { } else if strings.Contains(strings.Join(stanzasMQATINI, ", "), stanza) {
@@ -243,42 +252,80 @@ func ValidateStanzaToWrite(stanza string) (bool, string) {
} }
// prepareStanzasToAppend Prepares list of stanzas that are to be appended into qm ini files(qm.ini/mqat.ini) // prepareStanzasToAppend Prepares list of stanzas that are to be appended into qm ini files(qm.ini/mqat.ini)
func prepareStanzasToAppend(key string, attrList strings.Builder, iniConfig string) string { func prepareStanzasToAppend(key string, attrList strings.Builder, iniConfigList []string) []string {
newVal := key + "\n" + attrList.String() newVal := key + "\n" + attrList.String()
iniConfig = iniConfig + newVal list := strings.Split(newVal, "\n")
return iniConfig iniConfigList = append(iniConfigList, list...)
return iniConfigList
} }
// prepareStanzasToMerge Prepares list of stanzas that are to be updated into qm ini files(qm.ini/mqat.ini) // prepareStanzasToMerge Prepares list of stanzas that are to be updated into qm ini files(qm.ini/mqat.ini)
// These stanzas are already present in mq ini files and their values have to be updated with user supplied ini. // These stanzas are already present in mq ini files and their values have to be updated with user supplied ini.
func prepareStanzasToMerge(key string, attrList strings.Builder, iniConfig string) string { func prepareStanzasToMerge(key string, attrList strings.Builder, iniConfigList []string) ([]string, error) {
pos := -1
//find the index of current stanza in qm's ini file.
for i := 0; i < len(iniConfigList); i++ {
if strings.Contains(iniConfigList[i], key) {
pos = i
break
}
}
var appList strings.Builder
lineScanner := bufio.NewScanner(strings.NewReader(attrList.String())) lineScanner := bufio.NewScanner(strings.NewReader(attrList.String()))
lineScanner.Split(bufio.ScanLines) lineScanner.Split(bufio.ScanLines)
//Now go through the array and merge the values.
for lineScanner.Scan() { for lineScanner.Scan() {
attrLine := lineScanner.Text() attrLine := lineScanner.Text()
keyvalue := strings.Split(attrLine, "=") keyvalue := strings.Split(attrLine, "=")
// This line present in qm.ini, update value. merged := false
if strings.Contains(iniConfig, keyvalue[0]) { for i := pos + 1; i < len(iniConfigList); i++ {
re := regexp.MustCompile(keyvalue[0] + "=.*") if strings.HasPrefix(iniConfigList[i], "#") {
iniConfig = re.ReplaceAllString(iniConfig, attrLine) continue
} else { }
// This line not present in qm.ini file, add it. if strings.Contains(iniConfigList[i], ":") {
re := regexp.MustCompile(key) break
newVal := key + "\n" + attrLine }
iniConfig = re.ReplaceAllString(iniConfig, newVal) if strings.Contains(iniConfigList[i], keyvalue[0]) {
iniConfigList[i] = attrLine
merged = true
break
}
} }
//If this is not merged, then its a new parameter in existing stanza.
if !merged && len(strings.TrimSpace(attrLine)) > 0 {
_, err := appList.WriteString(attrLine)
if err != nil {
return nil, err
}
merged = false
}
if len(appList.String()) > 0 {
temp := make([]string, pos+1)
for i := 0; i < pos+1; i++ {
temp[i] = iniConfigList[i]
}
list := strings.Split(appList.String(), "\n")
temp = append(temp, list...)
temp1 := iniConfigList[pos+1:]
iniConfigList = append(temp, temp1...)
}
} }
return iniConfig return iniConfigList, nil
} }
// writeConfigStanzas writes the INI file updates into corresponding mq ini files. // writeConfigStanzas writes the INI file updates into corresponding mq ini files.
func writeConfigStanzas(qmConfig string, atConfig string) error { func writeConfigStanzas(qmConfig []string, atConfig []string) error {
err := ioutil.WriteFile(filepath.Join(qmgrDir, "qm.ini"), []byte(qmConfig), 0644) err := ioutil.WriteFile(filepath.Join(qmgrDir, "qm.ini"), []byte(strings.Join(qmConfig, "\n")), 0644)
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(filepath.Join(qmgrDir, "mqat.ini"), []byte(atConfig), 0644) err = ioutil.WriteFile(filepath.Join(qmgrDir, "mqat.ini"), []byte(strings.Join(atConfig, "\n")), 0644)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -60,15 +60,17 @@ func TestIniFile1Update(t *testing.T) {
t.Errorf("Expected stanza file not found: qm.ini\n") t.Errorf("Expected stanza file not found: qm.ini\n")
} }
scanner := bufio.NewScanner(strings.NewReader(userconfig)) count := 0
scanner.Split(bufio.ScanLines) //we want this line to be present exactly one.
for scanner.Scan() { for _, item := range qmConfig {
line := scanner.Text() item = strings.TrimSpace(item)
if !strings.Contains(qmConfig, line) { if strings.Contains(item, "mylib") {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig) count++
break
} }
} }
if count != 1 {
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
}
} }
func TestIniFile2Update(t *testing.T) { func TestIniFile2Update(t *testing.T) {
@@ -88,15 +90,17 @@ func TestIniFile2Update(t *testing.T) {
t.Errorf("Expected stanza file not found: qm.ini\n") t.Errorf("Expected stanza file not found: qm.ini\n")
} }
scanner := bufio.NewScanner(strings.NewReader(userconfig)) count := 0
scanner.Split(bufio.ScanLines) //we want this line to be present exactly one.
for scanner.Scan() { for _, item := range atConfig {
line := scanner.Text() item = strings.TrimSpace(item)
if !strings.Contains(atConfig, line) { if strings.Contains(item, "amqsget") {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig) count++
break
} }
} }
if count != 1 {
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=amqsget, Config:%s\n", strings.Join(atConfig, "\n"))
}
} }
func TestIniFile3Update(t *testing.T) { func TestIniFile3Update(t *testing.T) {
@@ -117,6 +121,9 @@ func TestIniFile3Update(t *testing.T) {
t.Errorf("Expected stanza file not found: mqat.ini\n") t.Errorf("Expected stanza file not found: mqat.ini\n")
} }
qmConfigStr := strings.Join(qmConfig, "\n")
atConfigStr := strings.Join(atConfig, "\n")
scanner := bufio.NewScanner(strings.NewReader(userconfig)) scanner := bufio.NewScanner(strings.NewReader(userconfig))
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
for scanner.Scan() { for scanner.Scan() {
@@ -124,17 +131,62 @@ func TestIniFile3Update(t *testing.T) {
i++ i++
//first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file. //first 20 lines of test3qm.ini shall go into qm.ini file and rest into mqat.ini file.
if i < 20 { if i < 20 {
if !strings.Contains(qmConfig, line) { if !strings.Contains(qmConfigStr, strings.TrimSpace(line)) {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig) t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfigStr)
} }
} else if i > 20 { } else if i > 20 {
if !strings.Contains(atConfig, line) { if !strings.Contains(atConfigStr, line) {
t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, qmConfig) t.Errorf("Expected stanza line not found in updated string. line=%s\n, Stanza:%s\n", line, atConfigStr)
} }
} }
} }
} }
func TestIniFile4Update(t *testing.T) {
iniFileBytes, err := ioutil.ReadFile("test1qm.ini")
if err != nil {
t.Errorf("Unexpected error: [%s]\n", err.Error())
}
//First merge
userconfig := string(iniFileBytes)
qmConfig, atConfig, err := PrepareConfigStanzasToWrite(userconfig)
if err != nil {
t.Errorf("Unexpected error: [%s]\n", err.Error())
}
if len(atConfig) == 0 {
t.Errorf("Expected stanza file not found: mqat.ini\n")
}
if len(qmConfig) == 0 {
t.Errorf("Expected stanza file not found: qm.ini\n")
}
//second merge.
qmConfig, atConfig, err = PrepareConfigStanzasToWrite(userconfig)
if err != nil {
t.Errorf("Unexpected error: [%s]\n", err.Error())
}
if len(atConfig) == 0 {
t.Errorf("Expected stanza file not found: mqat.ini\n")
}
if len(qmConfig) == 0 {
t.Errorf("Expected stanza file not found: qm.ini\n")
}
count := 0
//we just did a double merge, however we want this line to be present exactly one.
for _, item := range qmConfig {
item = strings.TrimSpace(item)
if strings.Contains(item, "mylib") {
count++
}
}
if count != 1 {
t.Errorf("Expected stanza line not found or appeared more than once in updated string. line=mylib\n config=%s\n count=%d\n", strings.Join(qmConfig, "\n"), count)
}
}
func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) { func checkReturns(stanza string, isqmini bool, shouldexist bool, t *testing.T) {
exists, filename := ValidateStanzaToWrite(stanza) exists, filename := ValidateStanzaToWrite(stanza)
if exists != shouldexist { if exists != shouldexist {

View File

@@ -1,5 +1,5 @@
ApiExitLocal:    ApiExitLocal:   
Sequence=1 Sequence=1
Function=EntryPoint Function=EntryPoint
Module=/opt/mylibs/mylib.so Module=/opt/mqm/exitlib.so
Name=mylib Name=mylib