OpenPostgresURL opens a new RDS database connection wrapped with OpenTelemetry instrumentation.
(ctx context.Context, u *url.URL)
| 90 | |
| 91 | // OpenPostgresURL opens a new RDS database connection wrapped with OpenTelemetry instrumentation. |
| 92 | func (uo *URLOpener) OpenPostgresURL(ctx context.Context, u *url.URL) (*sql.DB, error) { |
| 93 | source := uo.CertSource |
| 94 | if source == nil { |
| 95 | source = &rds.CertFetcher{Client: uo.HTTPClient} |
| 96 | } |
| 97 | if u.Host == "" { |
| 98 | return nil, fmt.Errorf("awspostgres: open: empty endpoint") |
| 99 | } |
| 100 | |
| 101 | query := u.Query() |
| 102 | for k := range query { |
| 103 | // Forbid SSL-related parameters. |
| 104 | if k == "sslmode" || k == "sslcert" || k == "sslkey" || k == "sslrootcert" { |
| 105 | return nil, fmt.Errorf("awspostgres: open: parameter %q not allowed; sslmode must be disabled because the underlying dialer is already providing TLS", k) |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | // If no password provided, assume it's AWS IAM authentication. |
| 110 | var iam func(context.Context) (string, error) |
| 111 | if _, ok := u.User.Password(); !ok { |
| 112 | var cfgOpts []func(*config.LoadOptions) error |
| 113 | if uo.HTTPClient != nil { |
| 114 | cfgOpts = append(cfgOpts, config.WithHTTPClient(uo.HTTPClient)) |
| 115 | } |
| 116 | if profile := query.Get("aws_profile"); profile != "" { |
| 117 | cfgOpts = append(cfgOpts, config.WithSharedConfigProfile(profile)) |
| 118 | query.Del("aws_profile") |
| 119 | } |
| 120 | cfg, err := config.LoadDefaultConfig(ctx, cfgOpts...) |
| 121 | if err != nil { |
| 122 | return nil, fmt.Errorf("awspostgres: open: load AWS config: %w", err) |
| 123 | } |
| 124 | creds := cfg.Credentials |
| 125 | if roleARN := query.Get("aws_role_arn"); roleARN != "" { |
| 126 | creds = stscreds.NewAssumeRoleProvider(sts.NewFromConfig(cfg), roleARN) |
| 127 | query.Del("aws_role_arn") |
| 128 | } |
| 129 | creds = aws.NewCredentialsCache(creds) |
| 130 | iam = func(ctx context.Context) (string, error) { |
| 131 | return auth.BuildAuthToken(ctx, u.Host, cfg.Region, u.User.Username(), creds) |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | // sslmode must be disabled because the underlying dialer is already providing TLS. |
| 136 | query.Set("sslmode", "disable") |
| 137 | |
| 138 | u2 := new(url.URL) |
| 139 | *u2 = *u |
| 140 | u2.Scheme = "postgres" |
| 141 | u2.RawQuery = query.Encode() |
| 142 | db := sql.OpenDB(connector{ |
| 143 | provider: source, |
| 144 | pqConn: u2.String(), |
| 145 | traceOpts: append([]otelsql.Option(nil), uo.TraceOpts...), |
| 146 | iam: iam, |
| 147 | }) |
| 148 | return db, nil |
| 149 | } |