rdsiamwrap

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 25, 2023 License: MIT Imports: 7 Imported by: 0

README

rdsiamwrap

AWS allows you to authenticate to an RDS database using IAM. Configuration information can be found in RDS documentation. The Go SDK has a package which helps with creating the connection.

This is great for brief database activity. However, if a new connection has to be established the Go sql package will reuse the existing DSN to create that connection. This DSN will always contain the same authentication token which will have expired after 15 minutes.

The rdsiamwrap package will allow you to create a custom Driver that creates the authentication token and rebuilds the DSN on demand. If the token it has is still valid it reuses that. If it has exceeded a configurable lifetime (default is 14 minutes) then a new authentication token and DSN are generated and used.

Usage

package main

import (
        "crypto/tls"
        "crypto/x509"
        "database/sql"
        "log"
        "net/url"

        "github.com/AgentZombie/rdsiamwrap"
        "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
        "github.com/aws/aws-sdk-go/aws/session"
        "github.com/go-sql-driver/mysql"
)

const DriverName = "mydriver"
const TLSCfgName = "rds"

// CA Chain from https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
const RDSCAChain = `-----BEGIN CERTIFICATE-----
MIID9DCCAtygAwIBAgIBQjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx
...
-----END CERTIFICATE-----`

func main() {
        rootCertPool := x509.NewCertPool()
        if ok := rootCertPool.AppendCertsFromPEM([]byte(RDSCAChain)); !ok {
                panic("failed to parse RDS CA chain")
        }
        mysql.RegisterTLSConfig(TLSCfgName, &tls.Config{
                RootCAs: rootCertPool,
        })

        v := url.Values{}
        v.Add("tls", TLSCfgName)
        v.Add("allowCleartextPasswords", "true")
        v.Add("parseTime", "true")

        d := rdsiamwrap.New()
        d.Driver = &mysql.MySQLDriver{}
        d.Addr = "db-cluster.cluster-potatochip.us-west-2.rds.amazonaws.com:3306"
        d.Region = "us-west-2"
        d.User = "myrole"
        d.DBName = "mydb"
        // Use the role associated with this EC2 instance
        d.Creds = ec2rolecreds.NewCredentials(session.Must(session.NewSession()))
        d.Params = v
        sql.Register(DriverName, d)

        pool, err := sql.Open(DriverName, "this DSN is unused")
        if err != nil {
                log.Fatal("unable to use data source name", err)
        }
        defer pool.Close()
}

Limitations

  • You must register an rdsiamwrap.Driver and do so only once.
  • You must be able to get an instance of the database/sql/driver.Driver you want to wrap.

Documentation

Overview

rdsiamwrap wraps a database/sql/driver.Driver to provide AWS authentication to RDS databases. Doing this authentication using the rdsutils package alone works for an initial connection but fails if new connections need to be established but the token has expired. This package generates this token as needed using provided AWS credentials.

Index

Constants

View Source
const (
	// Get a new token after this duration if none is specified in the driver struct.
	// AWS's default lifetime is 15 minutes.
	DefaultTokenLifetime = time.Minute * 14 // one minute under 15 minute documented expiration
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Driver

type Driver struct {
	// The actual driver to be wrapped
	Driver driver.Driver
	// Address of the RDS instance
	Addr string
	// AWS region of the RDS instance
	Region string
	// Database username: should be the role name
	User string
	// Name of the database
	DBName string
	// AWS credentials for authentication
	Creds *credentials.Credentials
	// Parameters to pass
	Params url.Values
	// How long to use an auth token. If unset DefaultTokenLifetime is used
	TokenLifetime time.Duration
	// contains filtered or unexported fields
}

Driver implements the sql.driver.Driver interface to provide AWS IAM authentication around an existing driver.

func New

func New() *Driver

New creates a new Driver which will still need configuration fields set.

func (*Driver) Open

func (d *Driver) Open(name string) (driver.Conn, error)

Open opens a new database connection. It creates a new auth token as needed, reusing one that hasn't expired yet.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL