github.com/verrazzano/verrazzano@v1.7.1/tools/vz/pkg/helpers/vzsanitize_test.go (about) 1 // Copyright (c) 2022, 2024, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package helpers 5 6 import ( 7 "encoding/csv" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/verrazzano/verrazzano/tools/vz/pkg/constants" 15 ) 16 17 var ( 18 testIPToRemove = "127.255.255.255" 19 testIP = "az0/:" + testIPToRemove + "l2/}" 20 testOCIDToRemove = "ocid1.tenancy.oc1..a763cu5f3m7qpzwnvr2so2655cpzgxmglgtui3v7q" 21 testOCID = "az0/:" + testOCIDToRemove + "/}az" 22 testSSHToRemove = "ssh-NewKey-Format9@. AAAAB3NzaCDo798PWwYniRpZ/DEKAapLQDfrHeR/OO59T4ZUr4ln/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/IYp3cumJef9Y99+/=foo @foo-mac z" 23 testSSH = "abcd/0: " + testSSHToRemove + "\n xYz123" 24 testSSHToRemovenoComment = "ssh-NewKey-Format9@. AAAAB3NzaCDo798PWwYniRpZ/DEKAapLQDfrHeR/OO59T4ZUr4ln/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/IYp3cumJef9Y99+/=" 25 testSSHnoComment = "abcd/0: " + testSSHToRemovenoComment + "\n xYz123" 26 testSSHToRemoveRSA = "ssh-rsa AAAAB3NzaCDo798PWwYniRpZ/DEKAapLQDfrHeR/OO59T4ZUr4ln/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/IYp3cumJef9Y99+/=foo @foo-mac z" 27 testSSHrsa = "abcd/0: " + testSSHToRemoveRSA + "\n xYz123" 28 testSSHToRemoveSk25519 = "sk-ssh-ed25519@openssh.com AAAAW2XXFA0S2f2tHUFyEb6ktadcbfO2MczKg7z/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/IYp3cumJef9Y99+/== z@dxy fyz-ru" 29 testSSHsk25519 = "abcd/0: " + testSSHToRemoveSk25519 + "\n xYz123" 30 testSSHToRemoveSkEcdsa = "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNYniRpZ/DEKAapLQDfrHeR/OO59T4ZUr4ln/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/YniRpZ/DEKAapLQDfrHeR/OO59T4ZUr4ln/5EoUGYu1HRVWmvQx4wsKZRwl4u8pi9gYOW1pL/IYp3cumJef9Y99+/=== z@dxy fyz-ru" 31 testSSHskEcdsa = "edcsa-abcd/0: " + testSSHToRemoveSkEcdsa + "\n xYz123" 32 testSSHToRemoveEcdsaSha2 = "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADz1oA4gh3qZExdiS6krVOHXhh3KAMG9SHj1RqMXskDy2sTmO9mPF0P2HJfkm0OgCSMo3BZfvh2rh23fMfUI67gigAmOm41fGQ8B/K82sWj0LuskUR2TqRGQFwwWOVZYtUVtiboTg+XgL5fcGitxL+biT9LMTSOAiRw39cHmk6+B0kXBw== z@dxy fyz-ru" 33 testSSHecdsaSha2 = "ecdsa-abcd " + testSSHToRemoveEcdsaSha2 + "\n xYz123" 34 testSSHToRemoveEd25519 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/PsfEX91dggIwWL4edgvgVgn4FJdtZd9ZFXXXXXXXX z@dxy fyz-ru" 35 testSSHed25519 = "ecdsa-abcd0 " + testSSHToRemoveEd25519 + "\n xYz123" 36 testSSHToRemoveDss = "ssh-dss AAAAB3NzaC1kc3MAAACBAM6RtXQiwMnnreGmgpT9yinlWLFA8tycOT7or/7iXG06cp7BixJg65Xkl2zKXbq9/Sv+PAFfy7uK0ROSlya1IirMTDFWjMCXaOPwyHb+pM6uBA5UFQxQ9/I+KhWcfelqVVaGK36Xz7N8tCf+IwPvlkK4JeOnbmFfF0a3+nmlPsuXAAAAFQDFlq/WHwSVHlQXzBGRw6Kx7fbj6wAAAIAUZSEIPUFW7bKn8zQ7G7OXpIyMjxnWrpoDb38qTKyhcVrlMgH8cLb558SO/itTkLNRyNPLlSVuxM6qngm1jzPK0NzZbnVtxhTQjCbPmIml3nFjpXpJDUo7nXdR/Gzk15ffQTN/44cqkY/90x87ZgwqNLF8x44B1IUDyyG7NvTNcQAAAIEAy18U+7rh21k5pHBzOY0peZu/x/9/Cu7eJMFpmY7Za+XChjGHmuu2lw9xqebP3SQDIFyMQzXnV39bJXggAHPeGD+Rg2028PcF8w8veBh/+8OgQn+AyFinBRSir7huSApU223R+HvSMZsmXY9I9ycmVULOFy7/WLAcOXXXXX3ig1I= z@dxy fyz-ru" 37 testSSHdss = "ssh-xyz " + testSSHToRemoveDss + "\n xYz123" 38 testUserDataToRemove = "\"user_data\": \"abcABC012=+\"" 39 testUserData = "az0:/" + testUserDataToRemove + "az0:/" 40 testOPCIDToRemove = " a634bbc217b8188f263d98bc0b3d5c05/9AG80960E22B0EDFEFE506BA8D73DF3C/814906C375D7F4651B8A47987CCB4478" 41 testOPCID = "\"message\": \"Request a service limit increase from the service limits page in the console. . http status code: 400. Opc request id:" + testOPCIDToRemove + "\", xyz123" 42 43 // Specifies the location and name of the CSV file written to by WriteRedactionMapFile for these tests. 44 redactMapFileLocation = os.TempDir() 45 ) 46 47 // TestSanitizeALine tests the SanitizeString function. 48 // GIVEN a variety of input strings, 49 // WHEN I call SanitizeString, 50 // THEN I expect the output strings to be properly sanitized. 51 func TestSanitizeALine(t *testing.T) { 52 testRedactedValues := make(map[string]string) 53 strictCheck := func(message string, toRemove string) { 54 assert.Contains(t, message, toRemove, "The test case does not contain the expression to remove: "+toRemove) 55 i := strings.Index(message, toRemove) 56 sanitized := SanitizeString(message, testRedactedValues) 57 assert.NotContains(t, sanitized, toRemove, "Failed to remove expression from string: "+toRemove) 58 hashLength := (len(sanitized) - len(message)) + len(toRemove) 59 reconstructed := sanitized[:i] + toRemove + sanitized[i+hashLength:] 60 assert.Equal(t, message, reconstructed, "Extra character(s) removed from the message. Message: "+message+"\n reconstructed message: "+reconstructed) 61 } 62 strictCheck(testIP, testIPToRemove) 63 strictCheck(testOCID, testOCIDToRemove) 64 strictCheck(testSSH, testSSHToRemove) 65 strictCheck(testSSHnoComment, testSSHToRemovenoComment) 66 strictCheck(testSSHrsa, testSSHToRemoveRSA) 67 strictCheck(testSSHsk25519, testSSHToRemoveSk25519) 68 strictCheck(testSSHskEcdsa, testSSHToRemoveSkEcdsa) 69 strictCheck(testSSHecdsaSha2, testSSHToRemoveEcdsaSha2) 70 strictCheck(testSSHed25519, testSSHToRemoveEd25519) 71 strictCheck(testSSHdss, testSSHToRemoveDss) 72 strictCheck(testUserData, testUserDataToRemove) 73 strictCheck(testOPCID, testOPCIDToRemove) 74 } 75 76 // TestWriteRedactionMapFileEmpty tests that a CSV file is successfully created upon calling WriteRedactionMapFile. 77 // GIVEN zero calls to the redact function, 78 // WHEN I call WriteRedactionMapFile, 79 // THEN I expect it to still successfully create a CSV file. 80 func TestWriteRedactionMapFileEmpty(t *testing.T) { 81 a := assert.New(t) 82 testRedactedValues := make(map[string]string) 83 redactMapFilePath := filepath.Join(redactMapFileLocation, "empty-redaction-map.csv") 84 85 // Should create the CSV file 86 err := WriteRedactionMapFile(redactMapFilePath, testRedactedValues) 87 a.Nil(err) 88 89 // Open the file 90 f, err := os.Open(redactMapFilePath) 91 a.Nil(err) 92 defer f.Close() 93 defer os.Remove(f.Name()) 94 95 // Check the file is empty 96 reader := csv.NewReader(f) 97 data, err := reader.ReadAll() 98 a.Nil(err) 99 a.Zero(len(data)) 100 } 101 102 // TestWriteRedactionMapFile tests that WriteRedactionMapFile correctly writes redacted string mapping to a CSV file. 103 // GIVEN a few calls to the redact function, 104 // WHEN I call WriteRedactionMapFile, 105 // THEN I expect it create a CSV file which contains mappings for all the previously redacted strings. 106 func TestWriteRedactionMapFile(t *testing.T) { 107 a := assert.New(t) 108 testRedactedValues := make(map[string]string) 109 redactMapFilePath := filepath.Join(redactMapFileLocation, "test-redaction-map.csv") 110 111 // redact a variety of inputs, as well as inputting a value more than once. 112 testInputs := []string{testIP, testOCID, testSSH, testUserData, testOPCID, testIP} 113 for _, input := range testInputs { 114 redact(input, testRedactedValues) 115 } 116 numUniqueInputs := 5 117 a.Len(testRedactedValues, numUniqueInputs) 118 119 // write the redacted values to the CSV file 120 err := WriteRedactionMapFile(redactMapFilePath, testRedactedValues) 121 a.Nil(err) 122 123 // open the file 124 f, err := os.Open(redactMapFilePath) 125 a.Nil(err) 126 defer f.Close() 127 defer os.Remove(f.Name()) 128 129 // read the file line by line 130 numLines := 0 131 reader := csv.NewReader(f) 132 record, err := reader.Read() 133 for record != nil { 134 numLines++ 135 a.Nil(err) 136 137 // check that this line of the CSV file is as expected 138 hash, found := testRedactedValues[record[1]] 139 a.True(found) 140 a.Equal(record[0], hash) 141 142 record, err = reader.Read() 143 } 144 145 // expected number of lines in the csv 146 a.Equal(numUniqueInputs, numLines) 147 } 148 149 // TestRedact tests the redact function. 150 // WHEN I call redact on various input strings, 151 // THEN the output redacted strings should follow a specific format. 152 func TestRedact(t *testing.T) { 153 a := assert.New(t) 154 testRedactedValues := make(map[string]string) 155 156 // test that redacting the same value repeatedly returns the same value 157 redactedIP := redact(testIP, testRedactedValues) 158 a.Contains(redactedIP, constants.RedactionPrefix) 159 a.NotContains(redactedIP, testIP) 160 for i := 0; i < 2; i++ { 161 r := redact(testIP, testRedactedValues) 162 a.Equal(redactedIP, r) 163 } 164 165 // test a redacting a different value 166 redactedSSH := redact(testSSH, testRedactedValues) 167 a.Contains(redactedSSH, constants.RedactionPrefix) 168 a.NotContains(redactedSSH, testSSH) 169 a.NotEqual(redactedSSH, redactedIP) 170 171 // test redacting the same value yet again returns the same value 172 r := redact(testIP, testRedactedValues) 173 a.Equal(redactedIP, r) 174 }