Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support connecting through a socks proxy #19

Merged
merged 1 commit into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ REDSHIFT_PASSWORD=<password>
make testacc
```

If your cluster is only accessible from within the VPC, you can connect via a socks proxy:
```sh
ALL_PROXY=socks5[h]://[<socks-user>:<socks-password>@]<socks-host>[:<socks-port>]
NO_PROXY=127.0.0.1,192.168.0.0/24,*.example.com,localhost
```

## Documentation

Documentation is generated with
Expand Down
27 changes: 27 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,30 @@ Optional:
- **auto_create_user** (Boolean) Create a database user with the name specified for the user if one does not exist.
- **db_groups** (Set of String) A list of the names of existing database groups that the user will join for the current session, in addition to any group memberships for an existing user. If not specified, a new user is added only to PUBLIC.
- **duration_seconds** (Number) The number of seconds until the returned temporary password expires.

## Proxy Support

If your Redshift cluster is only accessible from within a VPC, you can use the `ALL_PROXY` (`all_proxy`)
and `NO_PROXY` (`no_proxy`) environment variables to configure the provider to access Redshift through
a SOCKS5 proxy

```
ALL_PROXY=socks5[h]://[<socks5-username>:<socks5-password>@]<socks5-hostname>[:<socks5-port>]
NO_PROXY=#....
```

### `ALL_PROXY` URL parameters
* scheme: can be either `socks5` or `socks5h`. The `h` is optional and [does not change the behavior](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/proxy.go;l=92).
* `socks5-username` - optional username for authenticating to the socks proxy
* `socks5-password` - optional password for authenticating to the socks proxy
* `socks5-hostname` - the socks proxy hostname or IP address
* `socks5-port` - optional port number for the socks proxy. Default port is [1080](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/proxy.go;l=96)

### `NO_PROXY` Format

`NO_PROXY`/`no_proxy` is an optional environment variable which bypasses `ALL_PROXY`/`all_proxy`
for specific hosts. This is a [comma-separated string, where each value is one of](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/per_host.go;l=92-96):
* IP address (e.g. `127.0.0.1`)
* CIDR range (e.g. `192.168.0.0/24`)
* zone (e.g. `*.example.com`)
* hostname (e.g. `localhost`)
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ require (
github.com/hashicorp/terraform-plugin-docs v0.4.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1
github.com/lib/pq v1.10.2
golang.org/x/net v0.0.0-20210326060303-6b1517762897
)
4 changes: 2 additions & 2 deletions redshift/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (c *Client) Connect() (*DBConnection, error) {
dsn := c.config.connStr(c.databaseName)
conn, found := dbRegistry[dsn]
if !found {
db, err := sql.Open("postgres", dsn)
db, err := sql.Open(proxyDriverName, dsn)
if err != nil {
return nil, fmt.Errorf("Error connecting to PostgreSQL server %s: %w", c.config.Host, err)
}
Expand Down Expand Up @@ -118,7 +118,7 @@ func (c *Config) Client() (*Client, error) {
c.Port,
c.Database)

db, err := sql.Open("postgres", conninfo)
db, err := sql.Open(proxyDriverName, conninfo)
if err != nil {
db.Close()
return nil, err
Expand Down
35 changes: 35 additions & 0 deletions redshift/proxy_driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package redshift

import (
"context"
"database/sql"
"database/sql/driver"
"net"
"time"

"github.com/lib/pq"
"golang.org/x/net/proxy"
)

const proxyDriverName = "postgresql-proxy"

type proxyDriver struct{}

func (d proxyDriver) Open(name string) (driver.Conn, error) {
return pq.DialOpen(d, name)
}

func (d proxyDriver) Dial(network, address string) (net.Conn, error) {
dialer := proxy.FromEnvironment()
return dialer.Dial(network, address)
}

func (d proxyDriver) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()
return proxy.Dial(ctx, network, address)
}

func init() {
sql.Register(proxyDriverName, proxyDriver{})
}
27 changes: 27 additions & 0 deletions templates/index.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,30 @@ The Redshift provider provides configuration management resources for
{{ tffile "examples/provider/provider_using_temporary_credentials.tf" }}

{{ .SchemaMarkdown | trimspace }}

## Proxy Support

If your Redshift cluster is only accessible from within a VPC, you can use the `ALL_PROXY` (`all_proxy`)
and `NO_PROXY` (`no_proxy`) environment variables to configure the provider to access Redshift through
a SOCKS5 proxy

```
ALL_PROXY=socks5[h]://[<socks5-username>:<socks5-password>@]<socks5-hostname>[:<socks5-port>]
NO_PROXY=#....
```

### `ALL_PROXY` URL parameters
* scheme: can be either `socks5` or `socks5h`. The `h` is optional and [does not change the behavior](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/proxy.go;l=92).
* `socks5-username` - optional username for authenticating to the socks proxy
* `socks5-password` - optional password for authenticating to the socks proxy
* `socks5-hostname` - the socks proxy hostname or IP address
* `socks5-port` - optional port number for the socks proxy. Default port is [1080](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/proxy.go;l=96)

### `NO_PROXY` Format

`NO_PROXY`/`no_proxy` is an optional environment variable which bypasses `ALL_PROXY`/`all_proxy`
for specific hosts. This is a [comma-separated string, where each value is one of](https://cs.opensource.google/go/x/net/+/3a7c4785:proxy/per_host.go;l=92-96):
* IP address (e.g. `127.0.0.1`)
* CIDR range (e.g. `192.168.0.0/24`)
* zone (e.g. `*.example.com`)
* hostname (e.g. `localhost`)