mirror of
https://github.com/hanzo-fi/go-libs.git
synced 2026-10-30 20:53:44 +00:00
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package connect
|
|
|
|
import (
|
|
"context"
|
|
"database/sql/driver"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"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/jackc/pgx/v5"
|
|
"github.com/xo/dburl"
|
|
"go.opentelemetry.io/otel"
|
|
|
|
otlp "github.com/hanzo-fi/go-libs/v5/pkg/observe"
|
|
logging "github.com/hanzo-fi/go-libs/v5/pkg/observe/log"
|
|
)
|
|
|
|
var tracer = otel.Tracer("github.com/hanzo-fi/go-libs/v5/pkg/storage/bun/connect")
|
|
|
|
type iamDriver struct {
|
|
awsConfig aws.Config
|
|
}
|
|
|
|
func (driver *iamDriver) OpenConnector(name string) (driver.Connector, error) {
|
|
return &iamConnector{
|
|
dsn: name,
|
|
driver: driver,
|
|
}, nil
|
|
}
|
|
|
|
func (driver *iamDriver) Open(name string) (driver.Conn, error) {
|
|
connector, err := driver.OpenConnector(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return connector.Connect(context.Background())
|
|
}
|
|
|
|
var _ driver.Driver = &iamDriver{}
|
|
var _ driver.DriverContext = &iamDriver{}
|
|
|
|
type iamConnector struct {
|
|
dsn string
|
|
driver *iamDriver
|
|
logger logging.Logger
|
|
options []Option
|
|
}
|
|
|
|
func (i *iamConnector) Connect(ctx context.Context) (driver.Conn, error) {
|
|
databaseURL, err := dburl.Parse(i.dsn)
|
|
if err != nil {
|
|
return nil, errors.New("parsing dsn")
|
|
}
|
|
|
|
authenticationToken, err := func() (string, error) {
|
|
ctx, span := tracer.Start(ctx, "iam.build-auth-token")
|
|
defer span.End()
|
|
|
|
ret, err := auth.BuildAuthToken(
|
|
ctx,
|
|
databaseURL.Host,
|
|
i.driver.awsConfig.Region,
|
|
databaseURL.User.Username(),
|
|
i.driver.awsConfig.Credentials,
|
|
)
|
|
if err != nil {
|
|
otlp.RecordError(ctx, err)
|
|
}
|
|
|
|
return ret, err
|
|
}()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("building aws auth token: %w", err)
|
|
}
|
|
|
|
dsn := buildIAMAuthDSN(&databaseURL.URL, authenticationToken)
|
|
|
|
i.logger.Debugf("IAM: Connect using dsn '%s'", obfuscateDSN(dsn))
|
|
|
|
config, err := pgx.ParseConfig(dsn)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse dsn: %w", err)
|
|
}
|
|
for _, opt := range i.options {
|
|
opt(config)
|
|
}
|
|
|
|
return buildPGXConnector(config).Connect(ctx)
|
|
}
|
|
|
|
func (i iamConnector) Driver() driver.Driver {
|
|
return &iamDriver{}
|
|
}
|
|
|
|
var _ driver.Connector = &iamConnector{}
|
|
|
|
func buildIAMAuthDSN(databaseURL *url.URL, authenticationToken string) string {
|
|
dsnURL := *databaseURL
|
|
dsnURL.User = url.UserPassword(databaseURL.User.Username(), authenticationToken)
|
|
return dsnURL.String()
|
|
}
|