package trustmanager import ( "bytes" "crypto/rand" "fmt" "io/ioutil" "os" "path/filepath" "strconv" "testing" ) func TestAddFile(t *testing.T) { testData := []byte("This test data should be part of the file.") testName := "docker.com/notary/certificate" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) // Since we're generating this manually we need to add the extension '.' expectedFilePath := filepath.Join(tempBaseDir, testName+"."+testExt) // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the Add function err = store.Add(testName, testData) if err != nil { t.Fatalf("failed to add file to store: %v", err) } // Check to see if file exists b, err := ioutil.ReadFile(expectedFilePath) if err != nil { t.Fatalf("expected file not found: %v", err) } if !bytes.Equal(b, testData) { t.Fatalf("unexpected content in the file: %s", expectedFilePath) } } func TestRemoveFile(t *testing.T) { testName := "docker.com/notary/certificate" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) // Since we're generating this manually we need to add the extension '.' expectedFilePath := filepath.Join(tempBaseDir, testName+"."+testExt) _, err = generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the Remove function err = store.Remove(testName) if err != nil { t.Fatalf("failed to remove file from store: %v", err) } // Check to see if file exists _, err = os.Stat(expectedFilePath) if err == nil { t.Fatalf("expected not to find file: %s", expectedFilePath) } } func TestRemoveDir(t *testing.T) { testName := "docker.com/diogomonica/" testExt := "key" perms := os.FileMode(0700) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) // Since we're generating this manually we need to add the extension '.' expectedFilePath := filepath.Join(tempBaseDir, testName+"."+testExt) _, err = generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the RemoveDir function err = store.RemoveDir(testName) if err != nil { t.Fatalf("failed to remove directory: %v", err) } expectedDirectory := filepath.Dir(expectedFilePath) // Check to see if file exists _, err = os.Stat(expectedDirectory) if err == nil { t.Fatalf("expected not to find directory: %s", expectedDirectory) } } func TestListFiles(t *testing.T) { testName := "docker.com/notary/certificate" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) var expectedFilePath string // Create 10 randomfiles for i := 1; i <= 10; i++ { // Since we're generating this manually we need to add the extension '.' expectedFilename := testName + strconv.Itoa(i) + "." + testExt expectedFilePath = filepath.Join(tempBaseDir, expectedFilename) _, err = generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } // Create symlinks for all the files err = os.Symlink(expectedFilename, filepath.Join(tempBaseDir, expectedFilename+".link."+testExt)) if err != nil { t.Fatalf("failed to create symlink: %v", err) } } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the List function. Expect 10 real files when not listing symlinks files := store.ListFiles(false) if len(files) != 10 { t.Fatalf("expected 10 files in listing, got: %d", len(files)) } // Call the List function. Expect 20 total files when listing symlinks files = store.ListFiles(true) if len(files) != 20 { t.Fatalf("expected 20 files in listing, got: %d", len(files)) } } func TestListDir(t *testing.T) { testName := "docker.com/notary/certificate" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) var expectedFilePath string // Create 10 randomfiles for i := 1; i <= 10; i++ { // Since we're generating this manually we need to add the extension '.' fileName := fmt.Sprintf("%s-%s.%s", testName, strconv.Itoa(i), testExt) expectedFilePath = filepath.Join(tempBaseDir, fileName) _, err = generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the ListDir function files := store.ListDir("docker.com/", true) if len(files) != 10 { t.Fatalf("expected 10 files in listing, got: %d", len(files)) } files = store.ListDir("docker.com/notary", true) if len(files) != 10 { t.Fatalf("expected 10 files in listing, got: %d", len(files)) } files = store.ListDir("fakedocker.com/", true) if len(files) != 0 { t.Fatalf("expected 0 files in listing, got: %d", len(files)) } } func TestLink(t *testing.T) { testName := "docker.com/notary/certificate" testSymlink := "docker.com/notary/certificate-symlink" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) // Since we're generating this manually we need to add the extension '.' expectedFilePath := filepath.Join(tempBaseDir, testName+"."+testExt) expectedSymlinkPath := filepath.Join(tempBaseDir, testSymlink+"."+testExt) _, err = generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } // Call the Link function err = store.Link("certificate", testSymlink) if err != nil { t.Fatalf("failed to create symlink: %v", err) } // Check to see if the symlink exists actualSymlinkDest, err := os.Readlink(expectedSymlinkPath) if err != nil { t.Fatalf("expected to find symlink at path: %s", expectedSymlinkPath) } if actualSymlinkDest != "certificate."+testExt { t.Fatalf("symlink has wrong destination: %s", actualSymlinkDest) } } func TestGetPath(t *testing.T) { testExt := "crt" perms := os.FileMode(0755) // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: "", fileExt: testExt, perms: perms, } firstPath := "diogomonica.com/openvpn/0xdeadbeef.crt" secondPath := "/docker.io/testing-dashes/@#$%^&().crt" result, err := store.GetPath("diogomonica.com/openvpn/0xdeadbeef") if err != nil { t.Fatalf("unexpected error from GetPath: %v", err) } if result != firstPath { t.Fatalf("Expecting: %s", firstPath) } result, err = store.GetPath("/docker.io/testing-dashes/@#$%^&()") if err != nil { t.Fatalf("unexpected error from GetPath: %v", err) } if result != secondPath { t.Fatalf("Expecting: %s", secondPath) } } func TestGetPathProtection(t *testing.T) { testExt := "crt" perms := os.FileMode(0755) // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: "/path/to/filestore/", fileExt: testExt, perms: perms, } // Should deny requests for paths outside the filestore if _, err := store.GetPath("../../etc/passwd"); err != ErrPathOutsideStore { t.Fatalf("expected ErrPathOutsideStore error from GetPath") } if _, err := store.GetPath("private/../../../etc/passwd"); err != ErrPathOutsideStore { t.Fatalf("expected ErrPathOutsideStore error from GetPath") } // Convoluted paths should work as long as they end up inside the store expected := "/path/to/filestore/filename.crt" result, err := store.GetPath("private/../../filestore/./filename") if err != nil { t.Fatalf("unexpected error from GetPath: %v", err) } if result != expected { t.Fatalf("Expecting: %s (got: %s)", expected, result) } // Repeat tests with a relative baseDir relStore := &SimpleFileStore{ baseDir: "relative/file/path", fileExt: testExt, perms: perms, } // Should deny requests for paths outside the filestore if _, err := relStore.GetPath("../../etc/passwd"); err != ErrPathOutsideStore { t.Fatalf("expected ErrPathOutsideStore error from GetPath") } if _, err := relStore.GetPath("private/../../../etc/passwd"); err != ErrPathOutsideStore { t.Fatalf("expected ErrPathOutsideStore error from GetPath") } // Convoluted paths should work as long as they end up inside the store expected = "relative/file/path/filename.crt" result, err = relStore.GetPath("private/../../path/./filename") if err != nil { t.Fatalf("unexpected error from GetPath: %v", err) } if result != expected { t.Fatalf("Expecting: %s (got: %s)", expected, result) } } func TestGetData(t *testing.T) { testName := "docker.com/notary/certificate" testExt := "crt" perms := os.FileMode(0755) // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) // Since we're generating this manually we need to add the extension '.' expectedFilePath := filepath.Join(tempBaseDir, testName+"."+testExt) expectedData, err := generateRandomFile(expectedFilePath, perms) if err != nil { t.Fatalf("failed to generate random file: %v", err) } // Create our SimpleFileStore store := &SimpleFileStore{ baseDir: tempBaseDir, fileExt: testExt, perms: perms, } testData, err := store.Get(testName) if err != nil { t.Fatalf("failed to get data from: %s", testName) } if !bytes.Equal(testData, expectedData) { t.Fatalf("unexpected content for the file: %s", expectedFilePath) } } func TestCreateDirectory(t *testing.T) { testDir := "fake/path/to/directory" // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) dirPath := filepath.Join(tempBaseDir, testDir) // Call createDirectory CreateDirectory(dirPath) // Check to see if file exists fi, err := os.Stat(dirPath) if err != nil { t.Fatalf("expected find directory: %s", dirPath) } // Check to see if it is a directory if !fi.IsDir() { t.Fatalf("expected to be directory: %s", dirPath) } // Check to see if the permissions match if fi.Mode().String() != "drwxr-xr-x" { t.Fatalf("permissions are wrong for: %s. Got: %s", dirPath, fi.Mode().String()) } } func TestCreatePrivateDirectory(t *testing.T) { testDir := "fake/path/to/private/directory" // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") if err != nil { t.Fatalf("failed to create a temporary directory: %v", err) } defer os.RemoveAll(tempBaseDir) dirPath := filepath.Join(tempBaseDir, testDir) // Call createDirectory CreatePrivateDirectory(dirPath) // Check to see if file exists fi, err := os.Stat(dirPath) if err != nil { t.Fatalf("expected find directory: %s", dirPath) } // Check to see if it is a directory if !fi.IsDir() { t.Fatalf("expected to be directory: %s", dirPath) } // Check to see if the permissions match if fi.Mode().String() != "drwx------" { t.Fatalf("permissions are wrong for: %s. Got: %s", dirPath, fi.Mode().String()) } } func generateRandomFile(filePath string, perms os.FileMode) ([]byte, error) { rndBytes := make([]byte, 10) _, err := rand.Read(rndBytes) if err != nil { return nil, err } os.MkdirAll(filepath.Dir(filePath), perms) if err = ioutil.WriteFile(filePath, rndBytes, perms); err != nil { return nil, err } return rndBytes, nil }