func Connect(c mysql.Config) { var err error db, err = sql.Open("mysql", c.FormatDSN()) if err != nil { log.Fatal(err) } }
// NewDbMapFromConfig functions similarly to NewDbMap, but it takes the // decomposed form of the connection string, a *mysql.Config. func NewDbMapFromConfig(config *mysql.Config, maxOpenConns int) (*gorp.DbMap, error) { adjustMySQLConfig(config) // We always want strict mode. Rather than leaving this up to DB config, we // prefix each statement with it. prefix := "SET STATEMENT sql_mode='STRICT_ALL_TABLES' FOR " // If a read timeout is set, we set max_statement_time to 95% of that, and // long_query_time to 80% of that. That way we get logs of queries that are // close to timing out but not yet doing so, and our queries get stopped by // max_statement_time before timing out the read. This generates clearer // errors, and avoids unnecessary reconnects. if config.ReadTimeout != 0 { // In MariaDB, max_statement_time and long_query_time are both seconds. // Note: in MySQL (which we don't use), max_statement_time is millis. readTimeout := config.ReadTimeout.Seconds() prefix = fmt.Sprintf( "SET STATEMENT max_statement_time=%g, long_query_time=%g, sql_mode='STRICT_ALL_TABLES' FOR ", readTimeout*0.95, readTimeout*0.80) } // The way we generate a customized database driver means that we need to // choose a name to register the driver with. Because this function can be // called multiple times with different parameters, we choose a random name // each time we register to avoid conflicts with other DB instances. // We use crypto/rand rather than math.Rand not out of a particular necessity // for high-quality randomness, but simply because using non-crypto rand is a // code smell. driverNum, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) if err != nil { return nil, err } driverName := fmt.Sprintf("mysql-%d", driverNum) sql.Register(driverName, prefixdb.New(prefix, mysql.MySQLDriver{})) db, err := sqlOpen(driverName, config.FormatDSN()) if err != nil { return nil, err } if err = db.Ping(); err != nil { return nil, err } setMaxOpenConns(db, maxOpenConns) dialect := gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"} dbmap := &gorp.DbMap{Db: db, Dialect: dialect, TypeConverter: BoulderTypeConverter{}} initTables(dbmap) return dbmap, err }
// adjustMySQLConfig sets certain flags that we want on every connection. func adjustMySQLConfig(conf *mysql.Config) *mysql.Config { // Required to turn DATETIME fields into time.Time conf.ParseTime = true // Required to make UPDATE return the number of rows matched, // instead of the number of rows changed by the UPDATE. conf.ClientFoundRows = true // Ensures that MySQL/MariaDB warnings are treated as errors. This // avoids a number of nasty edge conditions we could wander into. // Common things this discovers includes places where data being sent // had a different type than what is in the schema, strings being // truncated, writing null to a NOT NULL column, and so on. See // <https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-strict>. conf.Strict = true return conf }
// NewDbMapFromConfig functions similarly to NewDbMap, but it takes the // decomposed form of the connection string, a *mysql.Config. func NewDbMapFromConfig(config *mysql.Config) (*gorp.DbMap, error) { adjustMySQLConfig(config) db, err := sqlOpen("mysql", config.FormatDSN()) if err != nil { return nil, err } if err = db.Ping(); err != nil { return nil, err } dialect := gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"} dbmap := &gorp.DbMap{Db: db, Dialect: dialect, TypeConverter: BoulderTypeConverter{}} initTables(dbmap) return dbmap, err }
func main() { listen := ":8899" logrus.Info("Starting Rancher V2 API on ", listen) config := mysql.Config{ User: "******", Passwd: "cattle", Net: "tcp", Addr: "localhost:3306", DBName: "cattle", Collation: "utf8_general_ci", } server, err := server.New("mysql", config.FormatDSN()) if err != nil { logrus.Fatal(err) } r := router.New(server) http.ListenAndServe(listen, r) }
// NewDbMapFromConfig functions similarly to NewDbMap, but it takes the // decomposed form of the connection string, a *mysql.Config. func NewDbMapFromConfig(config *mysql.Config, maxOpenConns int) (*gorp.DbMap, error) { adjustMySQLConfig(config) db, err := sqlOpen("mysql", config.FormatDSN()) if err != nil { return nil, err } if err = db.Ping(); err != nil { return nil, err } setMaxOpenConns(db, maxOpenConns) dialect := gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"} dbmap := &gorp.DbMap{Db: db, Dialect: dialect, TypeConverter: BoulderTypeConverter{}} initTables(dbmap) _, err = dbmap.Exec("SET sql_mode = 'STRICT_ALL_TABLES';") if err != nil { return nil, err } return dbmap, err }
func main() { var ( dbUser = flag.String("db-user", "auth", "Auth database username.") dbPasswd = flag.String("db-pass", "", "Auth database password.") dbHost = flag.String("db-host", "", "Auth database host.") dbPort = flag.String("db-port", "3306", "Auth database port.") dbServerName = flag.String("db-server-name", "", "Auth database server name.") dbServerCACert = flag.String("db-server-ca-cert", "/etc/auth/db-server-ca.pem", "Database server ca certificate") dbClientCert = flag.String("db-client-cert", "/etc/auth/db-client-cert.pem", "Database client certificate.") dbClientKey = flag.String("db-client-key", "/etc/auth/db-client-key.pem", "Database client key.") debugListenAddr = flag.String("debug-listen-addr", "127.0.0.1:7801", "HTTP listen address.") listenAddr = flag.String("listen-addr", "127.0.0.1:7800", "HTTP listen address.") tlsCert = flag.String("tls-cert", "/etc/auth/cert.pem", "TLS server certificate.") tlsKey = flag.String("tls-key", "/etc/auth/key.pem", "TLS server key.") jwtPrivateKey = flag.String("jwt-private-key", "/etc/auth/jwt-key.pem", "The RSA private key to use for signing JWTs") ) flag.Parse() var err error log.Println("Auth service starting...") certPool := x509.NewCertPool() pem, err := ioutil.ReadFile(*dbServerCACert) if err != nil { log.Fatal(err) } if ok := certPool.AppendCertsFromPEM(pem); !ok { log.Fatal("Failed to append PEM.") } clientCert := make([]tls.Certificate, 0, 1) certs, err := tls.LoadX509KeyPair(*dbClientCert, *dbClientKey) if err != nil { log.Fatal(err) } clientCert = append(clientCert, certs) mysql.RegisterTLSConfig("custom", &tls.Config{ ServerName: *dbServerName, RootCAs: certPool, Certificates: clientCert, }) dbAddr := net.JoinHostPort(*dbHost, *dbPort) dbConfig := mysql.Config{ User: *dbUser, Passwd: *dbPasswd, Net: "tcp", Addr: dbAddr, DBName: "auth", TLSConfig: "custom", } for { db, err = sql.Open("mysql", dbConfig.FormatDSN()) if err != nil { goto dberror } err = db.Ping() if err != nil { goto dberror } break dberror: log.Println(err) log.Println("error connecting to the auth database, retrying in 5 secs.") time.Sleep(5 * time.Second) } ta, err := credentials.NewServerTLSFromFile(*tlsCert, *tlsKey) if err != nil { log.Fatal(err) } gs := grpc.NewServer(grpc.Creds(ta)) as, err := NewAuthServer(*jwtPrivateKey) if err != nil { log.Fatal(err) } pb.RegisterAuthServer(gs, as) hs := health.NewHealthServer() hs.SetServingStatus("grpc.health.v1.authservice", 1) healthpb.RegisterHealthServer(gs, hs) ln, err := net.Listen("tcp", *listenAddr) if err != nil { log.Fatal(err) } go gs.Serve(ln) trace.AuthRequest = func(req *http.Request) (any, sensitive bool) { return true, true } log.Println("Auth service started successfully.") log.Fatal(http.ListenAndServe(*debugListenAddr, nil)) }