...

Text file src/cloud.google.com/go/cloudsqlconn/README.md

Documentation: cloud.google.com/go/cloudsqlconn

     1<p align="center">
     2    <a href="https://pkg.go.dev/cloud.google.com/go/cloudsqlconn">
     3        <img src="docs/images/cloud-sql-go-connector.png" alt="cloud-sql-go-connector image">
     4    </a>
     5</p>
     6
     7<h1 align="center">Cloud SQL Go Connector</h1>
     8
     9[![Open In Codelab][codelab-badge]][codelab]
    10[![CI][ci-badge]][ci-build]
    11[![Go Reference][pkg-badge]][pkg-docs]
    12
    13[ci-badge]: https://github.com/GoogleCloudPlatform/cloud-sql-go-connector/actions/workflows/tests.yaml/badge.svg?event=push
    14[ci-build]: https://github.com/GoogleCloudPlatform/cloud-sql-go-connector/actions/workflows/tests.yaml?query=event%3Apush+branch%3Amain
    15[pkg-badge]: https://pkg.go.dev/badge/cloud.google.com/go/cloudsqlconn.svg
    16[pkg-docs]: https://pkg.go.dev/cloud.google.com/go/cloudsqlconn
    17[codelab-badge]: https://img.shields.io/badge/Open%20In%20Codelab-blue?labelColor=grey&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAyVBMVEX////////////////////////+8/L0oZrrTkHqQzXzlY13yKEPnVgdo2KHzqvw+fX4xMDtWk604MssqWz73NnvcWdKtYHS7eD85+ZowpayncOWapvVS0360MzD5tWW1LZxo/dChfSLaKHfR0FMhe2rY4TyiYBlm/bQ4Pz+7sD7xCPPthRJpkegwvl9q/fn8P7+9+D80VL7vASisCQsoU4spV393YHPwDm40ftNjPX7wBP95qHz9/7/++/b6P3+8tD8zUKIsvj81WJbutStAAAABnRSTlMAIKDw/zDiNY+eAAAA+klEQVR4AbzRRYICMRRF0VB5QLlrO+7uDvvfVKfSv91mnGlunDFWUDh+xJUCE4ocv+JFMZ/jD7zAFPxJYRx/4gz/uGpQKquaDsEwLdv5HrieJriAbwqB/yUII00qA7YpxcmHoKRrJAUSk2QOKLi5vdMk7x7CQ0CF9fgSPFUqlWpN09QyiG1REsugkqs3miW8cTIqHApyrTbedLq9vgzkCoMKGY4gjSdTYTY3F74M0G5VyADCckpWnbd3WG+oaAMdGt7uPj7UfvC2BC2wPIACMspvuzkCp60YPo9/+M328LKHcHiek6EmnRMMAUAw2RPMOASzHsHMSzD7AwCdmyeTDUqFKQAAAABJRU5ErkJggg==
    18[codelab]: https://codelabs.developers.google.com/codelabs/cloud-sql-go-connector
    19
    20The _Cloud SQL Go Connector_ is a Cloud SQL connector designed for use with the
    21Go language. Using a Cloud SQL connector provides a native alternative to the
    22[Cloud SQL Auth Proxy][] while providing the following benefits:
    23
    24* **IAM Authorization:** uses IAM permissions to control who/what can connect to
    25  your Cloud SQL instances
    26* **Improved Security:** uses robust, updated TLS 1.3 encryption and
    27  identity verification between the client connector and the server-side proxy,
    28  independent of the database protocol.
    29* **Convenience:** removes the requirement to use and distribute SSL
    30  certificates, as well as manage firewalls or source/destination IP addresses.
    31* (optionally) **IAM DB Authentication:** provides support for
    32  [Cloud SQL’s automatic IAM DB AuthN][iam-db-authn] feature.
    33
    34[iam-db-authn]: https://cloud.google.com/sql/docs/postgres/authentication
    35[Cloud SQL Auth Proxy]: https://cloud.google.com/sql/docs/postgres/sql-proxy
    36
    37For users migrating from the Cloud SQL Proxy drivers, see the [migration
    38guide](./migration-guide.md).
    39
    40For a quick example, try out the Go Connector in a [Codelab][codelab].
    41
    42## Installation
    43
    44You can install this repo with `go get`:
    45```sh
    46go get cloud.google.com/go/cloudsqlconn
    47```
    48
    49## Usage
    50
    51This package provides several functions for authorizing and encrypting
    52connections. These functions can be used with your database driver to connect to
    53your Cloud SQL instance.
    54
    55The instance connection name for your Cloud SQL instance is always in the
    56format `project:region:instance`.
    57
    58### APIs and Services
    59
    60This package requires the following to successfully make Cloud SQL Connections:
    61
    62- IAM principal (user, service account, etc.) with the
    63[Cloud SQL Client][client-role] role or equivalent. This IAM principal will
    64 be used for [credentials](#credentials).
    65- The [Cloud SQL Admin API][admin-api] to be enabled within your Google Cloud
    66Project. By default, the API will be called in the project associated with
    67the IAM principal.
    68
    69[admin-api]: https://console.cloud.google.com/apis/api/sqladmin.googleapis.com
    70[client-role]: https://cloud.google.com/sql/docs/mysql/roles-and-permissions
    71
    72### Credentials
    73
    74This project uses the [Application Default Credentials (ADC)][adc] strategy for
    75resolving credentials. Please see [these instructions for how to set your ADC][set-adc]
    76(Google Cloud Application vs Local Development, IAM user vs service account credentials),
    77or consult the [golang.org/x/oauth2/google][google-auth] documentation.
    78
    79To explicitly set a specific source for the Credentials, see [Using
    80Options](#using-options) below.
    81
    82[adc]: https://cloud.google.com/docs/authentication#adc
    83[set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
    84[google-auth]: https://pkg.go.dev/golang.org/x/oauth2/google#hdr-Credentials
    85
    86### Connecting to a database
    87
    88#### Postgres
    89
    90Postgres users have the option of using the `database/sql` interface or
    91using [pgx][] directly. See [pgx's advice on which to choose][pgx-advice].
    92
    93[pgx]: https://github.com/jackc/pgx
    94[pgx-advice]: https://github.com/jackc/pgx#choosing-between-the-pgx-and-databasesql-interfaces
    95
    96##### Using the dialer with pgx
    97
    98To use the dialer with [pgx][], we recommend using connection pooling with
    99[pgxpool](https://pkg.go.dev/github.com/jackc/pgx/v5/pgxpool) by configuring
   100a [Config.DialFunc][dial-func] like so:
   101
   102``` go
   103import (
   104    "context"
   105    "net"
   106
   107    "cloud.google.com/go/cloudsqlconn"
   108    "github.com/jackc/pgx/v5/pgxpool"
   109)
   110
   111func connect() {
   112    // Configure the driver to connect to the database
   113    dsn := "user=myuser password=mypass dbname=mydb sslmode=disable"
   114    config, err := pgxpool.ParseConfig(dsn)
   115    if err != nil {
   116        /* handle error */
   117    }
   118
   119    // Create a new dialer with any options
   120    d, err := cloudsqlconn.NewDialer(context.Background())
   121    if err != nil {
   122        /* handle error */
   123    }
   124
   125    // Tell the driver to use the Cloud SQL Go Connector to create connections
   126    config.ConnConfig.DialFunc = func(ctx context.Context, _ string, instance string) (net.Conn, error) {
   127        return d.Dial(ctx, "project:region:instance")
   128    }
   129
   130    // Interact with the driver directly as you normally would
   131    pool, err := pgxpool.NewWithConfig(context.Background(), config)
   132    if err != nil {
   133        /* handle error */
   134    }
   135
   136    // call cleanup when you're done with the database connection
   137    cleanup := func() error { return d.Close() }
   138    // ... etc
   139}
   140```
   141
   142[dial-func]: https://pkg.go.dev/github.com/jackc/pgconn#Config
   143
   144##### Using the dialer with `database/sql`
   145
   146To use `database/sql`, call `pgxv5.RegisterDriver` with any necessary Dialer
   147configuration. Note: the connection string must use the keyword/value format
   148with host set to the instance connection name. The returned `cleanup` func
   149will stop the dialer's background refresh goroutine and so should only be called
   150when you're done with the `Dialer`.
   151
   152``` go
   153import (
   154    "database/sql"
   155
   156    "cloud.google.com/go/cloudsqlconn"
   157    "cloud.google.com/go/cloudsqlconn/postgres/pgxv5"
   158)
   159
   160func connect() {
   161    cleanup, err := pgxv5.RegisterDriver("cloudsql-postgres", cloudsqlconn.WithIAMAuthN())
   162    if err != nil {
   163        // ... handle error
   164    }
   165    // call cleanup when you're done with the database connection
   166    defer cleanup()
   167
   168    db, err := sql.Open(
   169        "cloudsql-postgres",
   170        "host=project:region:instance user=myuser password=mypass dbname=mydb sslmode=disable",
   171    )
   172    // ... etc
   173}
   174```
   175
   176#### MySQL
   177
   178To use `database/sql`, use `mysql.RegisterDriver` with any necessary Dialer
   179configuration. The returned `cleanup` func
   180will stop the dialer's background refresh goroutine and so should only be called
   181when you're done with the `Dialer`.
   182
   183```go
   184import (
   185    "database/sql"
   186
   187    "cloud.google.com/go/cloudsqlconn"
   188    "cloud.google.com/go/cloudsqlconn/mysql/mysql"
   189)
   190
   191func connect() {
   192    cleanup, err := mysql.RegisterDriver("cloudsql-mysql", cloudsqlconn.WithCredentialsFile("key.json"))
   193    if err != nil {
   194        // ... handle error
   195    }
   196    // call cleanup when you're done with the database connection
   197    defer cleanup()
   198
   199    db, err := sql.Open(
   200        "cloudsql-mysql",
   201        "myuser:mypass@cloudsql-mysql(project:region:instance)/mydb",
   202    )
   203    // ... etc
   204}
   205```
   206
   207#### SQL Server
   208
   209To use `database/sql`, use `mssql.RegisterDriver` with any necessary Dialer
   210configuration. The returned `cleanup` func
   211will stop the dialer's background refresh goroutine and so should only be called
   212when you're done with the `Dialer`.
   213
   214``` go
   215import (
   216    "database/sql"
   217
   218    "cloud.google.com/go/cloudsqlconn"
   219    "cloud.google.com/go/cloudsqlconn/sqlserver/mssql"
   220)
   221
   222func connect() {
   223    cleanup, err := mssql.RegisterDriver("cloudsql-sqlserver", cloudsqlconn.WithCredentialsFile("key.json"))
   224    if err != nil {
   225        // ... handle error
   226    }
   227    // call cleanup when you're done with the database connection
   228    defer cleanup()
   229
   230    db, err := sql.Open(
   231        "cloudsql-sqlserver",
   232        "sqlserver://user:password@localhost?database=mydb&cloudsql=project:region:instance",
   233    )
   234    // ... etc
   235}
   236```
   237
   238### Using Options
   239
   240If you need to customize something about the `Dialer`, you can initialize
   241directly with `NewDialer`:
   242
   243```go
   244d, err := cloudsqlconn.NewDialer(
   245    ctx,
   246    cloudsqlconn.WithCredentialsFile("key.json"),
   247)
   248if err != nil {
   249    log.Fatalf("unable to initialize dialer: %s", err)
   250}
   251
   252conn, err := d.Dial(ctx, "project:region:instance")
   253```
   254
   255For a full list of customizable behavior, see Option.
   256
   257### Using DialOptions
   258
   259If you want to customize things about how the connection is created, use
   260`Option`:
   261
   262```go
   263conn, err := d.Dial(
   264    ctx,
   265    "project:region:instance",
   266    cloudsqlconn.WithPrivateIP(),
   267)
   268```
   269
   270You can also use the `WithDefaultDialOptions` Option to specify
   271DialOptions to be used by default:
   272
   273```go
   274d, err := cloudsqlconn.NewDialer(
   275    ctx,
   276    cloudsqlconn.WithDefaultDialOptions(
   277        cloudsqlconn.WithPrivateIP(),
   278    ),
   279)
   280```
   281
   282### Automatic IAM Database Authentication
   283
   284Connections using [Automatic IAM database authentication][] are supported when
   285using Postgres or MySQL drivers.
   286
   287Make sure to [configure your Cloud SQL Instance to allow IAM authentication][configure-iam-authn]
   288and [add an IAM database user][add-iam-user].
   289
   290A `Dialer` can be configured to connect to a Cloud SQL instance using
   291automatic IAM database authentication with the `WithIAMAuthN` Option
   292(recommended) or the `WithDialIAMAuthN` DialOption.
   293
   294```go
   295d, err := cloudsqlconn.NewDialer(ctx, cloudsqlconn.WithIAMAuthN())
   296```
   297
   298When configuring the DSN for IAM authentication, the `password` field can be
   299omitted and the `user` field should be formatted as follows:
   300> Postgres: For an IAM user account, this is the user's email address.
   301> For a service account, it is the service account's email without the
   302> `.gserviceaccount.com` domain suffix.
   303>
   304> MySQL: For an IAM user account, this is the user's email address, without
   305> the `@` or domain name. For example, for `test-user@gmail.com`, set the
   306> `user` field to `test-user`. For a service account, this is the service
   307> account's email address without the `@project-id.iam.gserviceaccount.com`
   308> suffix.
   309
   310Example DSNs using the `test-sa@test-project.iam.gserviceaccount.com`
   311service account to connect can be found below.
   312
   313**Postgres**:
   314
   315```go
   316dsn := "user=test-sa@test-project.iam dbname=mydb sslmode=disable"
   317```
   318
   319**MySQL**:
   320
   321```go
   322dsn := "user=test-sa dbname=mydb sslmode=disable"
   323```
   324
   325[Automatic IAM database authentication]: https://cloud.google.com/sql/docs/postgres/authentication#automatic
   326[configure-iam-authn]: https://cloud.google.com/sql/docs/postgres/create-edit-iam-instances#configure-iam-db-instance
   327[add-iam-user]: https://cloud.google.com/sql/docs/postgres/create-manage-iam-users#creating-a-database-user
   328
   329### Enabling Metrics and Tracing
   330
   331This library includes support for metrics and tracing using [OpenCensus][].
   332To enable metrics or tracing, you need to configure an [exporter][].
   333OpenCensus supports many backends for exporters.
   334
   335Supported metrics include:
   336
   337- `cloudsqlconn/dial_latency`: The distribution of dialer latencies (ms)
   338- `cloudsqlconn/open_connections`: The current number of open Cloud SQL
   339  connections
   340- `cloudsqlconn/dial_failure_count`: The number of failed dial attempts
   341- `cloudsqlconn/refresh_success_count`: The number of successful certificate
   342  refresh operations
   343- `cloudsqlconn/refresh_failure_count`: The number of failed refresh
   344  operations.
   345
   346Supported traces include:
   347
   348- `cloud.google.com/go/cloudsqlconn.Dial`: The dial operation including
   349  refreshing an ephemeral certificate and connecting the instance
   350- `cloud.google.com/go/cloudsqlconn/internal.InstanceInfo`: The call to retrieve
   351  instance metadata (e.g., database engine type, IP address, etc)
   352- `cloud.google.com/go/cloudsqlconn/internal.Connect`: The connection attempt
   353  using the ephemeral certificate
   354- SQL Admin API client operations
   355
   356For example, to use [Cloud Monitoring][] and [Cloud Trace][], you would
   357configure an exporter like so:
   358
   359```golang
   360import (
   361    "contrib.go.opencensus.io/exporter/stackdriver"
   362    "go.opencensus.io/trace"
   363)
   364
   365func main() {
   366    sd, err := stackdriver.NewExporter(stackdriver.Options{
   367        ProjectID: "mycoolproject",
   368    })
   369    if err != nil {
   370        // handle error
   371    }
   372    defer sd.Flush()
   373    trace.RegisterExporter(sd)
   374
   375    sd.StartMetricsExporter()
   376    defer sd.StopMetricsExporter()
   377
   378    // Use cloudsqlconn as usual.
   379    // ...
   380}
   381```
   382
   383As OpenTelemetry has now reached feature parity with OpenCensus, the migration
   384from OpenCensus to OpenTelemetry is strongly encouraged.
   385[OpenTelemetry bridge](https://github.com/open-telemetry/opentelemetry-go/tree/main/bridge/opencensus)
   386can be leveraged to migrate to OpenTelemetry without the need of replacing the
   387OpenCensus APIs in this library. Example code is shown below for migrating an
   388application using the OpenTelemetry bridge for traces.
   389
   390```golang
   391import (
   392	texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
   393	"go.opencensus.io/trace"
   394	"go.opentelemetry.io/otel"
   395	"go.opentelemetry.io/otel/bridge/opencensus"
   396	sdktrace "go.opentelemetry.io/otel/sdk/trace"
   397	"google.golang.org/api/option"
   398)
   399
   400func main() {
   401	// trace.AlwaysSample() is expensive. Replacing it with your own
   402	// sampler for production environments is recommended.
   403	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
   404
   405	exporter, err := texporter.New(
   406		texporter.WithTraceClientOptions([]option.ClientOption{option.WithTelemetryDisabled()}),
   407		texporter.WithProjectID("mycoolproject"),
   408	)
   409	if err != nil {
   410		// Handle error
   411	}
   412
   413	tp := sdktrace.NewTracerProvider(sdktrace.WithSyncer(exporter))
   414	otel.SetTracerProvider(tp)
   415	tracer := tp.Tracer("Cloud SQL Go Connector Trace")
   416	trace.DefaultTracer = opencensus.NewTracer(tracer)
   417
   418	// Use cloudsqlconn as usual.
   419	// ...
   420}
   421```
   422
   423A known OpenTelemetry issue has been reported [here](https://github.com/googleapis/google-cloud-go/issues/7100).
   424It shouldn't impact database operations.
   425
   426[OpenCensus]: https://opencensus.io/
   427[exporter]: https://opencensus.io/exporters/
   428[Cloud Monitoring]: https://cloud.google.com/monitoring
   429[Cloud Trace]: https://cloud.google.com/trace
   430
   431### Debug Logging
   432
   433The Go Connector supports optional debug logging to help diagnose problems with
   434the background certificate refresh. To enable it, provide a logger that
   435implements the `debug.ContextLogger` interface when initializing the Dialer.
   436
   437For example:
   438
   439``` go
   440import (
   441    "context"
   442    "net"
   443
   444    "cloud.google.com/go/cloudsqlconn"
   445)
   446
   447type myLogger struct{}
   448
   449func (l *myLogger) Debugf(ctx context.Context, format string, args ...interface{}) {
   450    // Log as you like here
   451}
   452
   453func connect() {
   454    l := &myLogger{}
   455
   456    d, err := NewDialer(
   457        context.Background(),
   458        cloudsqlconn.WithContextDebugLogger(l),
   459    )
   460    // use dialer as usual...
   461}
   462```
   463
   464## Support policy
   465
   466### Major version lifecycle
   467
   468This project uses [semantic versioning](https://semver.org/), and uses the
   469following lifecycle regarding support for a major version:
   470
   471**Active** - Active versions get all new features and security fixes (that
   472wouldn’t otherwise introduce a breaking change). New major versions are
   473guaranteed to be "active" for a minimum of 1 year.
   474
   475**Deprecated** - Deprecated versions continue to receive security and critical
   476bug fixes, but do not receive new features. Deprecated versions will be
   477supported for 1 year.
   478
   479**Unsupported** - Any major version that has been deprecated for >=1 year is
   480considered unsupported.
   481
   482### Supported Go Versions
   483
   484We follow the [Go Version Support Policy][go-policy] used by Google Cloud
   485Libraries for Go.
   486
   487[go-policy]: https://github.com/googleapis/google-cloud-go#go-versions-supported
   488
   489### Release cadence
   490
   491This project aims for a release on at least a monthly basis. If no new features
   492or fixes have been added, a new PATCH version with the latest dependencies is
   493released.

View as plain text