Skip to content

Commit

Permalink
Verify CA when running mysqldump as well
Browse files Browse the repository at this point in the history
[#160794449]
  • Loading branch information
andreasf committed Sep 27, 2018
1 parent 6e95ba5 commit 0b6c987
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 15 deletions.
16 changes: 9 additions & 7 deletions cfmysql/cfmysqlfakes/fake_mysql_runner.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions cfmysql/mysql_runner.go
Expand Up @@ -12,7 +12,7 @@ import (
//go:generate counterfeiter . MysqlRunner
type MysqlRunner interface {
RunMysql(hostname string, port int, dbName string, username string, password string, caCert string, args ...string) error
RunMysqlDump(hostname string, port int, dbName string, username string, password string, args ...string) error
RunMysqlDump(hostname string, port int, dbName string, username string, password string, caCert string, args ...string) error
}

func NewMysqlRunner(execWrapper ExecWrapper, ioUtilWrapper IoUtilWrapper, osWrapper OsWrapper) MysqlRunner {
Expand Down Expand Up @@ -59,7 +59,7 @@ func (self *mysqlRunner) RunMysql(hostname string, port int, dbName string, user
return nil
}

func (self *mysqlRunner) RunMysqlDump(hostname string, port int, dbName string, username string, password string, mysqlDumpArgs ...string) error {
func (self *mysqlRunner) RunMysqlDump(hostname string, port int, dbName string, username string, password string, caCert string, mysqlDumpArgs ...string) error {
path, err := self.execWrapper.LookPath("mysqldump")
if err != nil {
return errors.New("'mysqldump' not found in PATH")
Expand All @@ -77,7 +77,14 @@ func (self *mysqlRunner) RunMysqlDump(hostname string, port int, dbName string,
nonTableArgs = mysqlDumpArgs[i+1:]
}

caCertArgs, caCertPath, err := self.storeCaCert(path, caCert)
defer self.osWrapper.Remove(caCertPath)
if err != nil {
return fmt.Errorf("error preparing TLS arguments: %s", err)
}

args := []string{"-u", username, "-p" + password, "-h", hostname, "-P", strconv.Itoa(port)}
args = append(args, caCertArgs...)
args = append(args, nonTableArgs...)
args = append(args, dbName)
args = append(args, tableArgs...)
Expand Down
45 changes: 41 additions & 4 deletions cfmysql/mysql_runner_test.go
Expand Up @@ -138,7 +138,7 @@ var _ = Describe("MysqlRunner", func() {
It("Returns an error", func() {
exec.LookPathReturns("", errors.New("PC LOAD LETTER"))

err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password")
err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "")

Expect(err).To(Equal(errors.New("'mysqldump' not found in PATH")))
Expect(exec.LookPathArgsForCall(0)).To(Equal("mysqldump"))
Expand All @@ -150,7 +150,7 @@ var _ = Describe("MysqlRunner", func() {
exec.LookPathReturns("/path/to/mysqldump", nil)
exec.RunReturns(errors.New("PC LOAD LETTER"))

err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password")
err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "")

Expect(err).To(Equal(errors.New("error running mysqldump: PC LOAD LETTER")))
})
Expand All @@ -160,7 +160,7 @@ var _ = Describe("MysqlRunner", func() {
It("Calls mysqldump with the right arguments", func() {
exec.LookPathReturns("/path/to/mysqldump", nil)

err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password")
err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "")

Expect(err).To(BeNil())
Expect(exec.LookPathCallCount()).To(Equal(1))
Expand All @@ -179,7 +179,7 @@ var _ = Describe("MysqlRunner", func() {
It("Calls mysqldump with the right arguments", func() {
exec.LookPathReturns("/path/to/mysqldump", nil)

err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "table1", "table2", "--foo", "bar", "--baz")
err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "", "table1", "table2", "--foo", "bar", "--baz")

Expect(err).To(BeNil())
Expect(exec.LookPathCallCount()).To(Equal(1))
Expand All @@ -193,5 +193,42 @@ var _ = Describe("MysqlRunner", func() {
Expect(cmd.Stderr).To(Equal(os.Stderr))
})
})

Context("When mysqldump is in PATH and a TLS CA certificate is part of the service credentials", func() {
It("Stores the cert in a temp file and calls mysqldump with --ssl-ca=path", func() {
exec.LookPathReturns("/path/to/mysqldump", nil)
tempFile := new(os.File)
ioutil.TempFileReturns(tempFile, nil)
osWrapper.NameReturns("/path/to/cert.pem")

err := runner.RunMysqlDump("hostname", 42, "dbname", "username", "password", "cert-content", "table1", "table2", "--foo", "bar", "--baz")

Expect(err).To(BeNil())
Expect(exec.LookPathCallCount()).To(Equal(1))
Expect(ioutil.TempFileCallCount()).To(Equal(1))
Expect(osWrapper.WriteStringCallCount()).To(Equal(1))
Expect(osWrapper.NameCallCount()).To(Equal(1))
Expect(exec.RunCallCount()).To(Equal(1))
Expect(osWrapper.RemoveCallCount()).To(Equal(1))

tempFileDir, tempFilePattern := ioutil.TempFileArgsForCall(0)
Expect(tempFileDir).To(Equal(""))
Expect(tempFilePattern).To(Equal("mysql-ca-cert.pem"))

writeStringFile, writeStringString := osWrapper.WriteStringArgsForCall(0)
Expect(writeStringFile).To(BeIdenticalTo(tempFile))
Expect(writeStringString).To(Equal("cert-content"))

cmd := exec.RunArgsForCall(0)
Expect(cmd.Path).To(Equal("/path/to/mysqldump"))
Expect(cmd.Args).To(Equal([]string{"/path/to/mysqldump", "-u", "username", "-ppassword", "-h", "hostname", "-P", "42", "--ssl-ca=/path/to/cert.pem", "--foo", "bar", "--baz", "dbname", "table1", "table2"}))
Expect(cmd.Stdin).To(Equal(os.Stdin))
Expect(cmd.Stdout).To(Equal(os.Stdout))
Expect(cmd.Stderr).To(Equal(os.Stderr))

removePath := osWrapper.RemoveArgsForCall(0)
Expect(removePath).To(Equal("/path/to/cert.pem"))
})
})
})
})
2 changes: 1 addition & 1 deletion cfmysql/plugin.go
Expand Up @@ -165,7 +165,7 @@ func (self *MysqlPlugin) runClient(command string, hostname string, port int, db
return self.MysqlRunner.RunMysql(hostname, port, dbName, username, password, caCert, args...)

case "mysqldump":
return self.MysqlRunner.RunMysqlDump(hostname, port, dbName, username, password, args...)
return self.MysqlRunner.RunMysqlDump(hostname, port, dbName, username, password, caCert, args...)
}

panic(fmt.Errorf("command not implemented: %s", command))
Expand Down
4 changes: 3 additions & 1 deletion cfmysql/plugin_test.go
Expand Up @@ -231,6 +231,7 @@ var _ = Describe("Plugin", func() {
DbName: "dbname-a",
Username: "username",
Password: "password",
CaCert: "ca-cert",
}
})

Expand Down Expand Up @@ -280,12 +281,13 @@ var _ = Describe("Plugin", func() {
Expect(mocks.PortFinder.GetPortCallCount()).To(Equal(1))
Expect(mocks.MysqlRunner.RunMysqlDumpCallCount()).To(Equal(1))

hostname, port, dbName, username, password, _ := mocks.MysqlRunner.RunMysqlDumpArgsForCall(0)
hostname, port, dbName, username, password, caCert, _ := mocks.MysqlRunner.RunMysqlDumpArgsForCall(0)
Expect(hostname).To(Equal("127.0.0.1"))
Expect(port).To(Equal(2342))
Expect(dbName).To(Equal(serviceA.DbName))
Expect(username).To(Equal(serviceA.Username))
Expect(password).To(Equal(serviceA.Password))
Expect(caCert).To(Equal(serviceA.CaCert))
})
})
})
Expand Down

0 comments on commit 0b6c987

Please sign in to comment.