Skip to content

Commit

Permalink
Merge branch 'master' into add-ssh-jumphost-support
Browse files Browse the repository at this point in the history
  • Loading branch information
marvin-kolja committed Apr 4, 2022
2 parents ac282ce + ec71102 commit b276055
Show file tree
Hide file tree
Showing 16 changed files with 450 additions and 60 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.16.x
go-version: 1.17.x

- run: go mod vendor

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v2.5.2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
go-version: 1.17
-
name: Import GPG key
id: import_gpg
Expand Down
35 changes: 33 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
## Unreleased

## 1.15.0 (February 4, 2022)

FEATURES:

* `postgresql_default_privileges`: Support default privileges for schema - @kostiantyn-nemchenko
[#126](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/126)

* `provider`: Add support for RDS IAM credentials - @Jell
[#134](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/134)

* `postgresql_grant`: Support for procedures and routines - @alec-rabold
[#128](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/128)

FIXES:

* `postgresql_grant`: fix `tuple concurrently updated` error - @boekkooi-lengoo
[#169](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/169)

DEV IMPROVEMENTS:

* Upgrade Terraform SDK to v2- @cyrilgdn
[#140](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/140)

* Remove vendor directory - @cyrilgdn (and lint fixed by @Jell )
[#139](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/139)
[#146](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/146)

* docker-compose: Use Docker healthcheck to wait for Postgres to be available - @boekkooi-lengoo
[#168](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/168)


## 1.14.0 (August 22, 2021)

FEATURE/FIXE:
FEATURES / FIXES:

* `postgresql_replication_slot`: Create resource to manage replication slots - @BarnabyShearer
[#70](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/70)
Expand Down Expand Up @@ -37,7 +68,7 @@ DOCUMENTATION:

## 1.13.0 (May 21, 2021)

FEATURE/FIXE:
FEATURES / FIXES:

* Stop locking catalog for every resources - @cyrilgdn
[#80](https://github.com/cyrilgdn/terraform-provider-postgresql/pull/80)
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ Requirements
Building The Provider
---------------------

Clone repository to: `$GOPATH/src/github.com/terraform-providers/terraform-provider-postgresql`
Clone repository to: `$GOPATH/src/github.com/cyrilgdn/terraform-provider-postgresql`

```sh
$ mkdir -p $GOPATH/src/github.com/terraform-providers; cd $GOPATH/src/github.com/terraform-providers
$ git clone git@github.com:terraform-providers/terraform-provider-postgresql
$ git clone git@github.com:cyrilgdn/terraform-provider-postgresql
```

Enter the provider directory and build the provider

```sh
$ cd $GOPATH/src/github.com/terraform-providers/terraform-provider-postgresql
$ cd $GOPATH/src/github.com/cyrilgdn/terraform-provider-postgresql
$ make build
```

Expand Down Expand Up @@ -60,7 +60,6 @@ In order to run the full suite of Acceptance tests, run `make testacc`.

*Note:*
- Acceptance tests create real resources, and often cost money to run.
- If ran locally `docker-compose` needs to be in the `$PATH`

```sh
$ make testacc
Expand Down
10 changes: 10 additions & 0 deletions examples/issues/169/dev.tfrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# See https://www.terraform.io/cli/config/config-file#development-overrides-for-provider-developers
# Use `go build -o ./examples/issues/169/postgresql/terraform-provider-postgresql` in the project root to build the provider.
# Then run terraform in this example directory.

provider_installation {
dev_overrides {
"cyrilgdn/postgresql" = "./postgresql"
}
direct {}
}
82 changes: 82 additions & 0 deletions examples/issues/169/test.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# This tests reproduces an issue for the following error message.
# ```
# terraform.tfstate
#
# │ Error: could not execute revoke query: pq: tuple concurrently updated
#
# │ with postgresql_grant.public_revoke_database["test3"],
# │ on test.tf line 40, in resource "postgresql_grant" "public_revoke_database":
# │ 40: resource "postgresql_grant" "public_revoke_database" {
#
#
# ```

terraform {
required_version = ">= 1.0"

required_providers {
postgresql = {
source = "cyrilgdn/postgresql"
version = ">=1.14"
}
}
}

locals {
databases = toset([for idx in range(4) : format("test%d", idx)])
}

provider "postgresql" {
superuser = false
}

resource "postgresql_database" "db" {
for_each = local.databases
name = each.key

# Use template1 instead of template0 (see https://www.postgresql.org/docs/current/manage-ag-templatedbs.html)
template = "template1"
}

resource "postgresql_role" "demo" {
name = "demo"
login = true
password = "Happy-Holidays!"
}

locals {
# Create a local that is depends on postgresql_database to ensure it's created
dbs = { for database in local.databases : database => postgresql_database.db[database].name }
}

# Revoke default accesses for PUBLIC role to the databases
resource "postgresql_grant" "public_revoke_database" {
for_each = local.dbs
database = each.value
role = "public"
object_type = "database"
privileges = []

with_grant_option = true
}

# Revoke default accesses for PUBLIC role to the public schema
resource "postgresql_grant" "public_revoke_schema" {
for_each = local.dbs
database = each.value
role = "public"
schema = "public"
object_type = "schema"
privileges = []

with_grant_option = true
}

resource "postgresql_grant" "demo_db_connect" {
for_each = local.dbs
database = each.value
role = postgresql_role.demo.name
schema = "public"
object_type = "database"
privileges = ["CONNECT"]
}
7 changes: 7 additions & 0 deletions postgresql/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const (
featureReplication
featureExtension
featurePrivileges
featureProcedure
featureRoutine
featurePrivilegesOnSchemas
featureForceDropDatabase
featurePid
Expand Down Expand Up @@ -74,6 +76,11 @@ var (
// for Postgresql < 9.
featurePrivileges: semver.MustParseRange(">=9.0.0"),

// Object PROCEDURE support
featureProcedure: semver.MustParseRange(">=11.0.0"),

// Object ROUTINE support
featureRoutine: semver.MustParseRange(">=11.0.0"),
// ALTER DEFAULT PRIVILEGES has ON SCHEMAS support
// for Postgresql >= 10
featurePrivilegesOnSchemas: semver.MustParseRange(">=10.0.0"),
Expand Down
18 changes: 10 additions & 8 deletions postgresql/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,16 @@ func sliceContainsStr(haystack []string, needle string) bool {
// allowedPrivileges is the list of privileges allowed per object types in Postgres.
// see: https://www.postgresql.org/docs/current/sql-grant.html
var allowedPrivileges = map[string][]string{
"database": []string{"ALL", "CREATE", "CONNECT", "TEMPORARY", "TEMP"},
"table": []string{"ALL", "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER"},
"sequence": []string{"ALL", "USAGE", "SELECT", "UPDATE"},
"schema": []string{"ALL", "CREATE", "USAGE"},
"function": []string{"ALL", "EXECUTE"},
"type": []string{"ALL", "USAGE"},
"foreign_data_wrapper": []string{"ALL", "USAGE"},
"foreign_server": []string{"ALL", "USAGE"},
"database": {"ALL", "CREATE", "CONNECT", "TEMPORARY", "TEMP"},
"table": {"ALL", "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER"},
"sequence": {"ALL", "USAGE", "SELECT", "UPDATE"},
"schema": {"ALL", "CREATE", "USAGE"},
"function": {"ALL", "EXECUTE"},
"procedure": {"ALL", "EXECUTE"},
"routine": {"ALL", "EXECUTE"},
"type": {"ALL", "USAGE"},
"foreign_data_wrapper": {"ALL", "USAGE"},
"foreign_server": {"ALL", "USAGE"},
}

// validatePrivileges checks that privileges to apply are allowed for this object type.
Expand Down
66 changes: 62 additions & 4 deletions postgresql/provider.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package postgresql

import (
"context"
"fmt"

"github.com/blang/semver"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"

"github.com/aws/aws-sdk-go-v2/aws"
awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
)

const (
Expand Down Expand Up @@ -61,6 +66,21 @@ func Provider() *schema.Provider {
Description: "Password to be used if the PostgreSQL server demands password authentication",
Sensitive: true,
},

"aws_rds_iam_auth": {
Type: schema.TypeBool,
Optional: true,
Description: "Use rds_iam instead of password authentication " +
"(see: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html)",
},

"aws_rds_iam_profile": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "AWS profile to use for IAM auth",
},

// Conection username can be different than database username with user name mapas (e.g.: in Azure)
// See https://www.postgresql.org/docs/current/auth-username-maps.html
"database_username": {
Expand Down Expand Up @@ -199,6 +219,28 @@ func validateExpectedVersion(v interface{}, key string) (warnings []string, erro
return
}

func getRDSAuthToken(profile string, username string, host string, port int) (string, error) {
endpoint := fmt.Sprintf("%s:%d", host, port)

ctx := context.Background()

var awscfg aws.Config
var err error

if profile != "" {
awscfg, err = awsConfig.LoadDefaultConfig(ctx, awsConfig.WithSharedConfigProfile(profile))
} else {
awscfg, err = awsConfig.LoadDefaultConfig(ctx)
}
if err != nil {
return "", err
}

token, err := auth.BuildAuthToken(ctx, endpoint, awscfg.Region, username, awscfg.Credentials)

return token, err
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
var sslMode string
if sslModeRaw, ok := d.GetOk("sslmode"); ok {
Expand All @@ -212,12 +254,28 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
versionStr := d.Get("expected_version").(string)
version, _ := semver.ParseTolerant(versionStr)

host := d.Get("host").(string)
port := d.Get("port").(int)
username := d.Get("username").(string)

var password string
if d.Get("aws_rds_iam_auth").(bool) {
profile := d.Get("aws_rds_iam_profile").(string)
var err error
password, err = getRDSAuthToken(profile, username, host, port)
if err != nil {
return nil, err
}
} else {
password = d.Get("password").(string)
}

config := Config{
Scheme: d.Get("scheme").(string),
Host: d.Get("host").(string),
Port: d.Get("port").(int),
Username: d.Get("username").(string),
Password: d.Get("password").(string),
Host: host,
Port: port,
Username: username,
Password: password,
DatabaseUsername: d.Get("database_username").(string),
Superuser: d.Get("superuser").(bool),
SSLMode: sslMode,
Expand Down
Loading

0 comments on commit b276055

Please sign in to comment.