Skip to content

Commit

Permalink
Merge pull request #70 from shogo82148/introduce-aws-sdk-v2
Browse files Browse the repository at this point in the history
introduce v2 package
  • Loading branch information
shogo82148 authored Oct 8, 2023
2 parents d940e1a + d2118dd commit 3c50fa0
Show file tree
Hide file tree
Showing 14 changed files with 3,618 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.mod/
/artifacts/
/release/
/go.work
2 changes: 1 addition & 1 deletion connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// check Connector implements driver.Connector.
var _ driver.Connector = &Connector{}
var _ driver.Connector = (*Connector)(nil)

// Connector is an implementation of driver.Connector
type Connector struct {
Expand Down
1 change: 1 addition & 0 deletions internal/certificate/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
// [Amazon Aurora MySQL]: https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL.html
const Certificate = rdsCertificates

// Config is the tls.Config for connecting RDS MySQL with SSL/TLS.
var Config *tls.Config

func init() {
Expand Down
4 changes: 2 additions & 2 deletions rdsmysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ type Driver struct {
Session *session.Session
}

var _ driver.Driver = &Driver{}
var _ driver.DriverContext = &Driver{}
var _ driver.Driver = (*Driver)(nil)
var _ driver.DriverContext = (*Driver)(nil)

// Open opens new connection.
func (d *Driver) Open(name string) (driver.Conn, error) {
Expand Down
117 changes: 117 additions & 0 deletions v2/connector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package rdsmysql

import (
"context"
"database/sql/driver"
"errors"
"fmt"
"sync"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
"github.com/go-sql-driver/mysql"
"github.com/shogo82148/rdsmysql/v2/internal/certificate"
"golang.org/x/time/rate"
)

// check Connector implements driver.Connector.
var _ driver.Connector = (*Connector)(nil)

// Connector is an implementation of driver.Connector
type Connector struct {
// AWSConfig is AWS Config.
AWSConfig *aws.Config

// MySQLConfig is a configure for connecting to MySQL servers.
MySQLConfig *mysql.Config

// MaxConnsPerSecond is a limit for creating new connections.
// Zero means no limit.
MaxConnsPerSecond int

mu sync.Mutex
limiter *rate.Limiter
// config is same as Config, but TLS configured
config *mysql.Config
}

// Connect returns a connection to the database.
func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
// rate limit
if l := c.getlimiter(); l != nil {
if err := l.Wait(ctx); err != nil {
return nil, err
}
}

connector, err := c.newConnector(ctx)
if err != nil {
return nil, err
}
return connector.Connect(ctx)
}

func (c *Connector) newConnector(ctx context.Context) (driver.Connector, error) {
config, err := c.newConfig()
if err != nil {
return nil, err
}

// refresh token
cred := c.AWSConfig.Credentials
region := c.AWSConfig.Region
if region == "" {
return nil, errors.New("rdsmysql: region is missing")
}
token, err := auth.BuildAuthToken(ctx, config.Addr, region, config.User, cred)
if err != nil {
return nil, fmt.Errorf("rdsmysql: fail to build auth token: %w", err)
}
config.Passwd = token

// create new connector
connector, err := mysql.NewConnector(config)
if err != nil {
return nil, fmt.Errorf("rdsmysql: fail to created new connector: %w", err)
}
return connector, nil
}

func (c *Connector) newConfig() (*mysql.Config, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.config == nil {
clone := *c.MySQLConfig // shallow copy, but ok. we rewrite only shallow fields.

// override configure for Amazon RDS
// see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.html
clone.AllowCleartextPasswords = true
clone.TLS = certificate.Config

c.config = &clone
}

clone := *c.config // shallow copy, but ok. we rewrite only shallow fields.
return &clone, nil
}

func (c *Connector) getlimiter() *rate.Limiter {
if c.MaxConnsPerSecond == 0 {
return nil
}
c.mu.Lock()
defer c.mu.Unlock()

limiter := c.limiter
if limiter == nil {
limiter = rate.NewLimiter(rate.Limit(c.MaxConnsPerSecond), 1)
c.limiter = limiter
}
return limiter
}

// Driver returns the underlying Driver of the Connector.
func (c *Connector) Driver() driver.Driver {
return &Driver{}
}
12 changes: 12 additions & 0 deletions v2/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/shogo82148/rdsmysql/v2

go 1.20

require (
github.com/aws/aws-sdk-go-v2 v1.18.0
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.2.11
github.com/go-sql-driver/mysql v1.7.1
golang.org/x/time v0.3.0
)

require github.com/aws/smithy-go v1.13.5 // indirect
19 changes: 19 additions & 0 deletions v2/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY=
github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.2.11 h1:Bp8y1d7MpuyzxRseENDoRUncENCETms9TXop+sWSNZ8=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.2.11/go.mod h1:rQTbJtDSEcZd7x+riWfNOzzaf/do/J7BtkZZyeOS9z0=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
35 changes: 35 additions & 0 deletions v2/internal/certificate/certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//go:generate go run ../cmd/update_certificate/main.go

package certificate

import (
"crypto/tls"
"crypto/x509"
"errors"

"github.com/go-sql-driver/mysql"
)

// Certificate is the certificates for connecting RDS MySQL with SSL/TLS.
// It contains the intermediate and root certificates for [Amazon RDS MySQL] and [Amazon Aurora MySQL].
//
// [Amazon RDS MySQL]: https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
// [Amazon Aurora MySQL]: https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL.html
const Certificate = rdsCertificates

// Config is the tls.Config for connecting RDS MySQL with SSL/TLS.
var Config *tls.Config

func init() {
rootCertPool := x509.NewCertPool()
if ok := rootCertPool.AppendCertsFromPEM([]byte(Certificate)); !ok {
panic(errors.New("failed to append certs"))
}
Config = &tls.Config{
RootCAs: rootCertPool,
}
err := mysql.RegisterTLSConfig("rdsmysql", Config)
if err != nil {
panic(err)
}
}
Loading

0 comments on commit 3c50fa0

Please sign in to comment.