This repository has been archived by the owner on May 1, 2024. It is now read-only.
forked from skx/overseer
-
Notifications
You must be signed in to change notification settings - Fork 4
/
mysql_probe.go
163 lines (138 loc) · 3.47 KB
/
mysql_probe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// MySQL Tester
//
// The MySQL tester connects to a remote MySQL database and ensures that this
// succeeds. This test is invoked via input like so:
//
// host.example.com must run mysql with username 'root' with password 'test'
//
// Specifying a username and password is mandatory, because otherwise we
// cannot connect to the database.
//
package protocols
import (
"database/sql"
"errors"
"fmt"
"strconv"
"strings"
"github.com/cmaster11/overseer/test"
"github.com/go-sql-driver/mysql"
)
// MYSQLTest is our object
type MYSQLTest struct {
}
// Arguments returns the names of arguments which this protocol-test
// understands, along with corresponding regular-expressions to validate
// their values.
func (s *MYSQLTest) Arguments() map[string]string {
known := map[string]string{
"port": "^[0-9]+$",
"username": ".*",
"password": ".*",
}
return known
}
// ShouldResolveHostname returns if this protocol requires the hostname resolution of the first test argument
func (s *MYSQLTest) ShouldResolveHostname() bool {
return true
}
// Example returns sample usage-instructions for self-documentation purposes.
func (s *MYSQLTest) Example() string {
str := `
MySQL Tester
------------
The MySQL tester connects to a remote MySQL database and ensures that this
succeeds. This test is invoked via input like so:
host.example.com must run mysql [with username 'root' with password 'test'
Specifying a username and password is mandatory, because otherwise we
cannot connect to the database.
`
return str
}
// RunTest is the part of our API which is invoked to actually execute a
// test against the given target.
//
// In this case we make a TCP connection to the host and attempt to login
// with the specified username & password.
func (s *MYSQLTest) RunTest(tst test.Test, target string, opts test.Options) error {
var err error
//
// The password might be blank, but the username is required.
//
if tst.Arguments["username"] == "" {
return errors.New("no username specified")
}
//
// The default port to connect to.
//
port := 3306
if tst.Arguments["port"] != "" {
port, err = strconv.Atoi(tst.Arguments["port"])
if err != nil {
return err
}
}
//
// Create a default configuration structure for MySQL.
//
config := mysql.NewConfig()
//
// Setup the connection timeout
//
config.Timeout = opts.Timeout
//
// Populate the username & password fields.
//
config.User = tst.Arguments["username"]
config.Passwd = tst.Arguments["password"]
//
// Default to connecting to an IPv4-address
//
address := fmt.Sprintf("%s:%d", target, port)
//
// If we find a ":" we know it is an IPv6 address though
//
if strings.Contains(target, ":") {
address = fmt.Sprintf("[%s]:%d", target, port)
}
//
// Setup the address in the configuration structure
//
config.Net = "tcp"
config.Addr = address
//
// Now convert the connection-string to a DSN, which
// is used to connect to the database.
//
dsn := config.FormatDSN()
//
// Show the DSN, if appropriate.
//
if opts.Verbose {
fmt.Printf("\tMySQL DSN is %s\n", dsn)
}
//
// Connect to the database
//
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
defer db.Close()
//
// And test that the connection actually worked.
//
err = db.Ping()
return err
}
func (s *MYSQLTest) GetUniqueHashForTest(tst test.Test, opts test.Options) *string {
return nil
}
//
// Register our protocol-tester.
//
func init() {
Register("mysql", func() ProtocolTest {
return &MYSQLTest{}
})
}