github.com/StackExchange/blackbox/v2@v2.0.1-0.20220331193400-d84e904973ab/integrationTest/integration_test.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "testing" 10 11 "github.com/StackExchange/blackbox/v2/pkg/bblog" 12 _ "github.com/StackExchange/blackbox/v2/pkg/bblog" 13 _ "github.com/StackExchange/blackbox/v2/pkg/vcs/_all" 14 ) 15 16 var vcsToTest = flag.String("testvcs", "GIT", "VCS to test") 17 var longTests = flag.Bool("long", false, "Run long version of tests") 18 19 //var crypterToTest = flag.String("crypter", "GnuPG", "crypter to test") 20 21 func init() { 22 testing.Init() 23 flag.Parse() 24 25 op, err := os.Getwd() 26 if err != nil { 27 panic(err) 28 } 29 originPath = op 30 } 31 32 func compile(t *testing.T) { 33 if PathToBlackBox() != "" { 34 // It's been compiled already. 35 return 36 } 37 // Make sure we have the latest binary 38 fmt.Println("========== Compiling") 39 cmd := exec.Command("go", "build", "-o", "../bbintegration", "../cmd/blackbox") 40 cmd.Stdout = os.Stdout 41 cmd.Stderr = os.Stderr 42 err := cmd.Run() 43 if err != nil { 44 t.Fatalf("setup_compile: %v", err) 45 } 46 cwd, err := os.Getwd() 47 if err != nil { 48 t.Fatal(err) 49 } 50 SetPathToBlackBox(filepath.Join(cwd, "../bbintegration")) 51 } 52 53 func setup(t *testing.T) { 54 logDebug := bblog.GetDebug(*verbose) 55 56 logDebug.Printf("flag.testvcs is %v", *vcsToTest) 57 vh := getVcs(t, *vcsToTest) 58 logDebug.Printf("Using BLACKBOX_VCS=%v", vh.Name()) 59 os.Setenv("BLACKBOX_VCS", vh.Name()) 60 61 } 62 63 func TestInit(t *testing.T) { 64 if !*longTests { 65 return 66 } 67 compile(t) 68 makeHomeDir(t, "init") 69 70 // Only zero or one args are permitted. 71 invalidArgs(t, "init", "one", "two") 72 invalidArgs(t, "init", "one", "two", "three") 73 74 runBB(t, "init", "yes") 75 assertFileEmpty(t, ".blackbox/blackbox-admins.txt") 76 assertFileEmpty(t, ".blackbox/blackbox-files.txt") 77 assertFilePerms(t, ".blackbox/blackbox-admins.txt", 0o640) 78 assertFilePerms(t, ".blackbox/blackbox-files.txt", 0o640) 79 } 80 81 func TestList(t *testing.T) { 82 if !*longTests { 83 return 84 } 85 compile(t) 86 makeHomeDir(t, "init") 87 88 runBB(t, "init", "yes") 89 createDummyFilesAdmin(t) 90 checkOutput("000-admin-list.txt", t, "admin", "list") 91 checkOutput("000-file-list.txt", t, "file", "list") 92 93 invalidArgs(t, "file", "list", "extra") 94 invalidArgs(t, "admin", "list", "extra") 95 } 96 97 func TestStatus(t *testing.T) { 98 if !*longTests { 99 return 100 } 101 compile(t) 102 makeHomeDir(t, "init") 103 104 runBB(t, "init", "yes") 105 createFilesStatus(t) 106 checkOutput("000-status.txt", t, "status") 107 } 108 109 func TestShred(t *testing.T) { 110 if !*longTests { 111 return 112 } 113 compile(t) 114 makeHomeDir(t, "shred") 115 runBB(t, "init", "yes") 116 117 makeFile(t, "shredme.txt", "File with SHREDME in it.\n") 118 assertFileExists(t, "shredme.txt") 119 runBB(t, "shred", "shredme.txt") 120 assertFileMissing(t, "shredme.txt") 121 } 122 123 func TestStatus_notreg(t *testing.T) { 124 if !*longTests { 125 return 126 } 127 compile(t) 128 makeHomeDir(t, "init") 129 130 runBB(t, "init", "yes") 131 createFilesStatus(t) 132 checkOutput("status-noreg.txt", t, "status", "status-ENCRYPTED.txt", "blah.txt") 133 } 134 135 // TestHard tests the functions using a fake homedir and repo. 136 func TestHard(t *testing.T) { 137 if !*longTests { 138 return 139 } 140 // These are basic tests that work on a fake repo. 141 // The repo has mostly real data, except any .gpg file 142 // is just garbage. 143 compile(t) 144 setup(t) 145 146 for _, cx := range []struct{ subname, prefix string }{ 147 //{subname: ".", prefix: "."}, 148 {subname: "mysub", prefix: ".."}, 149 } { 150 subname := cx.subname 151 prefix := cx.prefix 152 _ = prefix 153 154 phase("========== SUBDIR = " + subname + " ==========") 155 156 makeHomeDir(t, "BasicAlice") 157 158 plaintextFoo := "I am the foo.txt file!\n" 159 plainAltered := "I am the altered file!\n" 160 161 runBB(t, "testing_init") // Runs "git init" or equiv 162 assertFileExists(t, ".git") 163 runBB(t, "init", "yes") // Creates .blackbox or equiv 164 165 if subname != "." { 166 err := os.Mkdir(subname, 0770) 167 if err != nil { 168 t.Fatal(fmt.Errorf("hard-mk-home %q: %v", subname, err)) 169 } 170 } 171 olddir, err := os.Getwd() 172 if err != nil { 173 t.Fatal(err) 174 } 175 176 os.Chdir(subname) 177 os.Chdir(olddir) 178 179 phase("Alice creates a GPG key") 180 gpgdir := makeAdmin(t, "alice", "Alice Example", "alice@example.com") 181 become(t, "alice") 182 183 phase("Alice enrolls as an admin") 184 //os.Chdir(subname) 185 runBB(t, "admin", "add", "alice@example.com", gpgdir) 186 //os.Chdir(olddir) 187 188 // encrypt 189 phase("Alice registers foo.txt") 190 makeFile(t, "foo.txt", plaintextFoo) 191 //os.Chdir(subname) 192 //runBB(t, "file", "add", "--shred", filepath.Join(prefix, "foo.txt")) 193 runBB(t, "file", "add", "--shred", "foo.txt") 194 //os.Chdir(olddir) 195 // "file add" encrypts the file. 196 // We shred the plaintext so that we are sure that when Decrypt runs, 197 // we can verify the contents wasn't just sitting there all the time. 198 assertFileMissing(t, "foo.txt") 199 assertFileExists(t, "foo.txt.gpg") 200 201 phase("Alice decrypts foo.txt") 202 // decrypt 203 //os.Chdir(subname) 204 runBB(t, "decrypt", "foo.txt") 205 //runBB(t, "decrypt", filepath.Join(prefix, "foo.txt")) 206 //os.Chdir(olddir) 207 assertFileExists(t, "foo.txt") 208 assertFileExists(t, "foo.txt.gpg") 209 assertFileContents(t, "foo.txt", plaintextFoo) 210 211 // encrypts (without shredding) 212 phase("Alice encrypts foo.txt (again)") 213 runBB(t, "encrypt", "foo.txt") 214 assertFileExists(t, "foo.txt") 215 assertFileExists(t, "foo.txt.gpg") 216 assertFileContents(t, "foo.txt", plaintextFoo) 217 218 // reencrypt 219 phase("Alice reencrypts") 220 checkOutput("basic-status.txt", t, "status") 221 runBB(t, "reencrypt", "--overwrite", "foo.txt") 222 223 // Test variations of cat 224 225 // foo.txt=plain result=plain 226 phase("Alice cats plain:plain") 227 makeFile(t, "foo.txt", plaintextFoo) 228 assertFileExists(t, "foo.txt") 229 runBB(t, "encrypt", "foo.txt") 230 assertFileExists(t, "foo.txt") 231 assertFileExists(t, "foo.txt.gpg") 232 checkOutput("alice-cat-plain.txt", t, "cat", "foo.txt") 233 assertFileExists(t, "foo.txt") 234 assertFileExists(t, "foo.txt.gpg") 235 236 // foo.txt=altered result=plain 237 phase("Alice cats altered:plain") 238 makeFile(t, "foo.txt", plainAltered) 239 assertFileExists(t, "foo.txt") 240 assertFileExists(t, "foo.txt.gpg") 241 checkOutput("alice-cat-plain.txt", t, "cat", "foo.txt") 242 assertFileExists(t, "foo.txt") 243 assertFileExists(t, "foo.txt.gpg") 244 245 // foo.txt=missing result=plain 246 phase("Alice cats missing:plain") 247 removeFile(t, "foo.txt") 248 assertFileMissing(t, "foo.txt") 249 assertFileMissing(t, "foo.txt") 250 assertFileExists(t, "foo.txt.gpg") 251 checkOutput("alice-cat-plain.txt", t, "cat", "foo.txt") 252 assertFileMissing(t, "foo.txt") 253 assertFileExists(t, "foo.txt.gpg") 254 255 // Chapter 2: Bob 256 // Alice adds Bob. 257 // Bob encrypts a file. 258 // Bob makes sure he can decrypt alice's file. 259 // Bob removes Alice. 260 // Alice verifies she CAN'T decrypt files. 261 // Bob adds Alice back. 262 // Alice verifies she CAN decrypt files. 263 // Bob adds an encrypted file by mistake, "bb add" and fixes it. 264 // Bob corrupts the blackbox-admins.txt file, verifies that commands fail. 265 266 } 267 268 } 269 270 // TestEvilFilenames verifies commands work with "difficult" file names 271 func TestEvilFilenames(t *testing.T) { 272 if !*longTests { 273 return 274 } 275 compile(t) 276 setup(t) 277 makeHomeDir(t, "Mallory") 278 279 runBB(t, "testing_init") // Runs "git init" or equiv 280 assertFileExists(t, ".git") 281 runBB(t, "init", "yes") // Creates .blackbox or equiv 282 283 phase("Malory creates a GPG key") 284 gpgdir := makeAdmin(t, "mallory", "Mallory Evil", "mallory@example.com") 285 become(t, "mallory") 286 287 phase("Mallory enrolls as an admin") 288 runBB(t, "admin", "add", "mallory@example.com", gpgdir) 289 290 _ = os.MkdirAll("my/path/to", 0o770) 291 _ = os.Mkdir("other", 0o770) 292 293 for i, name := range []string{ 294 "!important!.txt", 295 "#andpounds.txt", 296 "stars*bars?.txt", 297 "space space.txt", 298 "tab\ttab.txt", 299 "ret\rret.txt", 300 "smile😁eyes", 301 "¡que!", 302 "thé", 303 "pound£", 304 "*.go", 305 "rm -f erase ; echo done", 306 `smile☺`, 307 `dub𝓦`, 308 "my/path/to/relsecrets.txt", 309 //"my/../my/path/../path/to/myother.txt", // Not permitted yet 310 //"other/../my//path/../path/to/otherother.txt", // Not permitted yet 311 //"new\nnew.txt", // \n not permitted 312 //"two\n", // \n not permitted (yet) 313 //"four\U0010FFFF", // Illegal byte sequence. git won't accept. 314 } { 315 phase(fmt.Sprintf("Mallory tries %02d: %q", i, name)) 316 contents := "the name of this file is the talking heads... i mean, " + name 317 makeFile(t, name, contents) 318 assertFileExists(t, name) 319 assertFileMissing(t, name+".gpg") 320 assertFileContents(t, name, contents) 321 322 runBB(t, "file", "add", name) 323 assertFileMissing(t, name) 324 assertFileExists(t, name+".gpg") 325 326 runBB(t, "decrypt", name) 327 assertFileExists(t, name) 328 assertFileExists(t, name+".gpg") 329 assertFileContents(t, name, contents) 330 331 runBB(t, "encrypt", name) 332 assertFileExists(t, name) 333 assertFileExists(t, name+".gpg") 334 assertFileContents(t, name, contents) 335 336 runBB(t, "shred", name) 337 assertFileMissing(t, name) 338 assertFileExists(t, name+".gpg") 339 } 340 } 341 342 // More tests to implement. 343 // 1. Verify that the --gid works (blackbox decrypt --gid)