Update the postgresql_schema resource to accept policies.
It is now possible to begin specifying DCL for schemas.
This commit is contained in:
parent
fab7bd3daf
commit
38928b91ba
|
@ -67,7 +67,6 @@ func Provider() terraform.ResourceProvider {
|
||||||
"postgresql_database": resourcePostgreSQLDatabase(),
|
"postgresql_database": resourcePostgreSQLDatabase(),
|
||||||
"postgresql_extension": resourcePostgreSQLExtension(),
|
"postgresql_extension": resourcePostgreSQLExtension(),
|
||||||
"postgresql_schema": resourcePostgreSQLSchema(),
|
"postgresql_schema": resourcePostgreSQLSchema(),
|
||||||
"postgresql_schema_policy": resourcePostgreSQLSchemaPolicy(),
|
|
||||||
"postgresql_role": resourcePostgreSQLRole(),
|
"postgresql_role": resourcePostgreSQLRole(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,26 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
|
"github.com/sean-/postgresql-acl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
schemaNameAttr = "name"
|
schemaNameAttr = "name"
|
||||||
schemaOwnerAttr = "owner"
|
schemaOwnerAttr = "owner"
|
||||||
|
schemaPolicyAttr = "policy"
|
||||||
|
schemaIfNotExists = "if_not_exists"
|
||||||
|
|
||||||
|
schemaPolicyCreateAttr = "create"
|
||||||
|
schemaPolicyCreateWithGrantAttr = "create_with_grant"
|
||||||
|
schemaPolicyRoleAttr = "role"
|
||||||
|
schemaPolicyUsageAttr = "usage"
|
||||||
|
schemaPolicyUsageWithGrantAttr = "usage_with_grant"
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourcePostgreSQLSchema() *schema.Resource {
|
func resourcePostgreSQLSchema() *schema.Resource {
|
||||||
|
@ -39,11 +50,105 @@ func resourcePostgreSQLSchema() *schema.Resource {
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The ROLE name who owns the schema",
|
Description: "The ROLE name who owns the schema",
|
||||||
},
|
},
|
||||||
|
schemaIfNotExists: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
Description: "When true, use the existing schema if it exsts",
|
||||||
|
},
|
||||||
|
schemaPolicyAttr: &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
schemaPolicyCreateAttr: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
Description: "If true, allow the specified ROLEs to CREATE new objects within the schema(s)",
|
||||||
|
ConflictsWith: []string{schemaPolicyAttr + "." + schemaPolicyCreateWithGrantAttr},
|
||||||
|
},
|
||||||
|
schemaPolicyCreateWithGrantAttr: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
Description: "If true, allow the specified ROLEs to CREATE new objects within the schema(s) and GRANT the same CREATE privilege to different ROLEs",
|
||||||
|
ConflictsWith: []string{schemaPolicyAttr + "." + schemaPolicyCreateAttr},
|
||||||
|
},
|
||||||
|
schemaPolicyRoleAttr: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Required: true,
|
||||||
|
Description: "ROLE who will receive this policy",
|
||||||
|
},
|
||||||
|
schemaPolicyUsageAttr: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
Description: "If true, allow the specified ROLEs to use objects within the schema(s)",
|
||||||
|
ConflictsWith: []string{schemaPolicyAttr + "." + schemaPolicyUsageWithGrantAttr},
|
||||||
|
},
|
||||||
|
schemaPolicyUsageWithGrantAttr: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
Description: "If true, allow the specified ROLEs to use objects within the schema(s) and GRANT the same USAGE privilege to different ROLEs",
|
||||||
|
ConflictsWith: []string{schemaPolicyAttr + "." + schemaPolicyUsageAttr},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourcePostgreSQLSchemaCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
queries := []string{}
|
||||||
|
|
||||||
|
schemaName := d.Get(schemaNameAttr).(string)
|
||||||
|
{
|
||||||
|
b := bytes.NewBufferString("CREATE SCHEMA ")
|
||||||
|
if v := d.Get(schemaIfNotExists); v.(bool) {
|
||||||
|
fmt.Fprint(b, "IF NOT EXISTS ")
|
||||||
|
}
|
||||||
|
fmt.Fprint(b, pq.QuoteIdentifier(schemaName))
|
||||||
|
|
||||||
|
switch v, ok := d.GetOk(schemaOwnerAttr); {
|
||||||
|
case ok:
|
||||||
|
fmt.Fprint(b, " AUTHORIZATION ", pq.QuoteIdentifier(v.(string)))
|
||||||
|
}
|
||||||
|
queries = append(queries, b.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACL objects that can generate the necessary SQL
|
||||||
|
type RoleKey string
|
||||||
|
var schemaPolicies map[RoleKey]acl.Schema
|
||||||
|
|
||||||
|
if policiesRaw, ok := d.GetOk(schemaPolicyAttr); ok {
|
||||||
|
policiesList := policiesRaw.(*schema.Set).List()
|
||||||
|
|
||||||
|
// NOTE: len(policiesList) doesn't take into account multiple
|
||||||
|
// roles per policy.
|
||||||
|
schemaPolicies = make(map[RoleKey]acl.Schema, len(policiesList))
|
||||||
|
|
||||||
|
for _, policyRaw := range policiesList {
|
||||||
|
policyMap := policyRaw.(map[string]interface{})
|
||||||
|
rolePolicy := schemaPolicyToACL(policyMap)
|
||||||
|
|
||||||
|
roleKey := RoleKey(strings.ToLower(rolePolicy.Role))
|
||||||
|
if existingRolePolicy, ok := schemaPolicies[roleKey]; ok {
|
||||||
|
schemaPolicies[roleKey] = existingRolePolicy.Merge(rolePolicy)
|
||||||
|
} else {
|
||||||
|
schemaPolicies[roleKey] = rolePolicy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, policy := range schemaPolicies {
|
||||||
|
queries = append(queries, policy.Grants(schemaName)...)
|
||||||
|
}
|
||||||
|
|
||||||
c := meta.(*Client)
|
c := meta.(*Client)
|
||||||
conn, err := c.Connect()
|
conn, err := c.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -51,20 +156,22 @@ func resourcePostgreSQLSchemaCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
schemaName := d.Get(schemaNameAttr).(string)
|
txn, err := conn.Begin()
|
||||||
b := bytes.NewBufferString("CREATE SCHEMA ")
|
if err != nil {
|
||||||
fmt.Fprintf(b, pq.QuoteIdentifier(schemaName))
|
return err
|
||||||
|
|
||||||
switch v, ok := d.GetOk(schemaOwnerAttr); {
|
|
||||||
case ok:
|
|
||||||
fmt.Fprint(b, " AUTHORIZATION ", pq.QuoteIdentifier(v.(string)))
|
|
||||||
}
|
}
|
||||||
|
defer txn.Rollback()
|
||||||
|
|
||||||
query := b.String()
|
for _, query := range queries {
|
||||||
_, err = conn.Query(query)
|
_, err = txn.Query(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf(fmt.Sprintf("Error creating schema %s: {{err}}", schemaName), err)
|
return errwrap.Wrapf(fmt.Sprintf("Error creating schema %s: {{err}}", schemaName), err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := txn.Commit(); err != nil {
|
||||||
|
return errwrap.Wrapf("Error committing schema: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
d.SetId(schemaName)
|
d.SetId(schemaName)
|
||||||
|
|
||||||
|
@ -79,13 +186,25 @@ func resourcePostgreSQLSchemaDelete(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
txn, err := conn.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer txn.Rollback()
|
||||||
|
|
||||||
schemaName := d.Get(schemaNameAttr).(string)
|
schemaName := d.Get(schemaNameAttr).(string)
|
||||||
|
|
||||||
|
// NOTE(sean@): Deliberately not performing a cascading drop.
|
||||||
query := fmt.Sprintf("DROP SCHEMA %s", pq.QuoteIdentifier(schemaName))
|
query := fmt.Sprintf("DROP SCHEMA %s", pq.QuoteIdentifier(schemaName))
|
||||||
_, err = conn.Query(query)
|
_, err = txn.Query(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf("Error deleting schema: {{err}}", err)
|
return errwrap.Wrapf("Error deleting schema: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := txn.Commit(); err != nil {
|
||||||
|
return errwrap.Wrapf("Error committing schema: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -101,7 +220,8 @@ func resourcePostgreSQLSchemaRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
|
|
||||||
schemaId := d.Id()
|
schemaId := d.Id()
|
||||||
var schemaName, schemaOwner string
|
var schemaName, schemaOwner string
|
||||||
err = conn.QueryRow("SELECT nspname, pg_catalog.pg_get_userbyid(nspowner) FROM pg_catalog.pg_namespace WHERE nspname=$1", schemaId).Scan(&schemaName, &schemaOwner)
|
var schemaACLs []string
|
||||||
|
err = conn.QueryRow("SELECT n.nspname, pg_catalog.pg_get_userbyid(n.nspowner), COALESCE(n.nspacl, '{}'::aclitem[])::TEXT[] FROM pg_catalog.pg_namespace n WHERE n.nspname=$1", schemaId).Scan(&schemaName, &schemaOwner, pq.Array(&schemaACLs))
|
||||||
switch {
|
switch {
|
||||||
case err == sql.ErrNoRows:
|
case err == sql.ErrNoRows:
|
||||||
log.Printf("[WARN] PostgreSQL schema (%s) not found", schemaId)
|
log.Printf("[WARN] PostgreSQL schema (%s) not found", schemaId)
|
||||||
|
@ -110,6 +230,29 @@ func resourcePostgreSQLSchemaRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return errwrap.Wrapf("Error reading schema: {{err}}", err)
|
return errwrap.Wrapf("Error reading schema: {{err}}", err)
|
||||||
default:
|
default:
|
||||||
|
type RoleKey string
|
||||||
|
schemaPolicies := make(map[RoleKey]acl.Schema, len(schemaACLs))
|
||||||
|
for _, aclStr := range schemaACLs {
|
||||||
|
aclItem, err := acl.Parse(aclStr)
|
||||||
|
if err != nil {
|
||||||
|
return errwrap.Wrapf("Error parsing aclitem: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaACL, err := acl.NewSchema(aclItem)
|
||||||
|
if err != nil {
|
||||||
|
return errwrap.Wrapf("invalid perms for schema: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
roleKey := RoleKey(strings.ToLower(schemaACL.Role))
|
||||||
|
var mergedPolicy acl.Schema
|
||||||
|
if existingRolePolicy, ok := schemaPolicies[roleKey]; ok {
|
||||||
|
mergedPolicy = existingRolePolicy.Merge(schemaACL)
|
||||||
|
} else {
|
||||||
|
mergedPolicy = schemaACL
|
||||||
|
}
|
||||||
|
schemaPolicies[roleKey] = mergedPolicy
|
||||||
|
}
|
||||||
|
|
||||||
d.Set(schemaNameAttr, schemaName)
|
d.Set(schemaNameAttr, schemaName)
|
||||||
d.Set(schemaOwnerAttr, schemaOwner)
|
d.Set(schemaOwnerAttr, schemaOwner)
|
||||||
d.SetId(schemaName)
|
d.SetId(schemaName)
|
||||||
|
@ -125,18 +268,32 @@ func resourcePostgreSQLSchemaUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
if err := setSchemaName(conn, d); err != nil {
|
txn, err := conn.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer txn.Rollback()
|
||||||
|
|
||||||
|
if err := setSchemaName(txn, d); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setSchemaOwner(conn, d); err != nil {
|
if err := setSchemaOwner(txn, d); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := setSchemaPolicy(txn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := txn.Commit(); err != nil {
|
||||||
|
return errwrap.Wrapf("Error committing schema: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
return resourcePostgreSQLSchemaRead(d, meta)
|
return resourcePostgreSQLSchemaRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSchemaName(conn *sql.DB, d *schema.ResourceData) error {
|
func setSchemaName(txn *sql.Tx, d *schema.ResourceData) error {
|
||||||
if !d.HasChange(schemaNameAttr) {
|
if !d.HasChange(schemaNameAttr) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -149,7 +306,7 @@ func setSchemaName(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("ALTER SCHEMA %s RENAME TO %s", pq.QuoteIdentifier(o), pq.QuoteIdentifier(n))
|
query := fmt.Sprintf("ALTER SCHEMA %s RENAME TO %s", pq.QuoteIdentifier(o), pq.QuoteIdentifier(n))
|
||||||
if _, err := conn.Query(query); err != nil {
|
if _, err := txn.Query(query); err != nil {
|
||||||
return errwrap.Wrapf("Error updating schema NAME: {{err}}", err)
|
return errwrap.Wrapf("Error updating schema NAME: {{err}}", err)
|
||||||
}
|
}
|
||||||
d.SetId(n)
|
d.SetId(n)
|
||||||
|
@ -157,7 +314,7 @@ func setSchemaName(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSchemaOwner(conn *sql.DB, d *schema.ResourceData) error {
|
func setSchemaOwner(txn *sql.Tx, d *schema.ResourceData) error {
|
||||||
if !d.HasChange(schemaOwnerAttr) {
|
if !d.HasChange(schemaOwnerAttr) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -170,9 +327,157 @@ func setSchemaOwner(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("ALTER SCHEMA %s OWNER TO %s", pq.QuoteIdentifier(o), pq.QuoteIdentifier(n))
|
query := fmt.Sprintf("ALTER SCHEMA %s OWNER TO %s", pq.QuoteIdentifier(o), pq.QuoteIdentifier(n))
|
||||||
if _, err := conn.Query(query); err != nil {
|
if _, err := txn.Query(query); err != nil {
|
||||||
return errwrap.Wrapf("Error updating schema OWNER: {{err}}", err)
|
return errwrap.Wrapf("Error updating schema OWNER: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSchemaPolicy(txn *sql.Tx, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(schemaPolicyAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaName := d.Get(schemaNameAttr).(string)
|
||||||
|
|
||||||
|
oraw, nraw := d.GetChange(schemaPolicyAttr)
|
||||||
|
oldList := oraw.(*schema.Set).List()
|
||||||
|
newList := nraw.(*schema.Set).List()
|
||||||
|
queries := make([]string, 0, len(oldList)+len(newList))
|
||||||
|
dropped, added, updated, _ := schemaChangedPolicies(oldList, newList)
|
||||||
|
|
||||||
|
for _, p := range dropped {
|
||||||
|
pMap := p.(map[string]interface{})
|
||||||
|
rolePolicy := schemaPolicyToACL(pMap)
|
||||||
|
queries = append(queries, rolePolicy.Revokes(schemaName)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range added {
|
||||||
|
pMap := p.(map[string]interface{})
|
||||||
|
rolePolicy := schemaPolicyToACL(pMap)
|
||||||
|
queries = append(queries, rolePolicy.Grants(schemaName)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range updated {
|
||||||
|
policies := p.([]interface{})
|
||||||
|
if len(policies) != 2 {
|
||||||
|
panic("expected 2 policies, old and new")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
oldPolicies := policies[0].(map[string]interface{})
|
||||||
|
rolePolicy := schemaPolicyToACL(oldPolicies)
|
||||||
|
queries = append(queries, rolePolicy.Revokes(schemaName)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
newPolicies := policies[1].(map[string]interface{})
|
||||||
|
rolePolicy := schemaPolicyToACL(newPolicies)
|
||||||
|
queries = append(queries, rolePolicy.Grants(schemaName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, query := range queries {
|
||||||
|
if _, err := txn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating schema DCL: {{err}}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// schemaChangedPolicies walks old and new to create a set of queries that can
|
||||||
|
// be executed to enact each type of state change (roles that have been dropped
|
||||||
|
// from the policy, added to a policy, have updated privilges, or are
|
||||||
|
// unchanged).
|
||||||
|
func schemaChangedPolicies(old, new []interface{}) (dropped, added, update, unchanged map[string]interface{}) {
|
||||||
|
type RoleKey string
|
||||||
|
oldLookupMap := make(map[RoleKey]interface{}, len(old))
|
||||||
|
for idx, _ := range old {
|
||||||
|
v := old[idx]
|
||||||
|
schemaPolicy := v.(map[string]interface{})
|
||||||
|
if roleRaw, ok := schemaPolicy[schemaPolicyRoleAttr]; ok {
|
||||||
|
role := roleRaw.(string)
|
||||||
|
roleKey := strings.ToLower(role)
|
||||||
|
oldLookupMap[RoleKey(roleKey)] = schemaPolicy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newLookupMap := make(map[RoleKey]interface{}, len(new))
|
||||||
|
for idx, _ := range new {
|
||||||
|
v := new[idx]
|
||||||
|
schemaPolicy := v.(map[string]interface{})
|
||||||
|
if roleRaw, ok := schemaPolicy[schemaPolicyRoleAttr]; ok {
|
||||||
|
role := roleRaw.(string)
|
||||||
|
roleKey := strings.ToLower(role)
|
||||||
|
newLookupMap[RoleKey(roleKey)] = schemaPolicy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
droppedRoles := make(map[string]interface{}, len(old))
|
||||||
|
for kOld, vOld := range oldLookupMap {
|
||||||
|
if _, ok := newLookupMap[kOld]; !ok {
|
||||||
|
droppedRoles[string(kOld)] = vOld
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addedRoles := make(map[string]interface{}, len(new))
|
||||||
|
for kNew, vNew := range newLookupMap {
|
||||||
|
if _, ok := oldLookupMap[kNew]; !ok {
|
||||||
|
addedRoles[string(kNew)] = vNew
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedRoles := make(map[string]interface{}, len(new))
|
||||||
|
unchangedRoles := make(map[string]interface{}, len(new))
|
||||||
|
for kOld, vOld := range oldLookupMap {
|
||||||
|
if vNew, ok := newLookupMap[kOld]; ok {
|
||||||
|
if reflect.DeepEqual(vOld, vNew) {
|
||||||
|
unchangedRoles[string(kOld)] = vOld
|
||||||
|
} else {
|
||||||
|
updatedRoles[string(kOld)] = []interface{}{vOld, vNew}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return droppedRoles, addedRoles, updatedRoles, unchangedRoles
|
||||||
|
}
|
||||||
|
|
||||||
|
func schemaPolicyToHCL(s *acl.Schema) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
schemaPolicyRoleAttr: s.Role,
|
||||||
|
schemaPolicyCreateAttr: s.GetPrivilege(acl.Create),
|
||||||
|
schemaPolicyCreateWithGrantAttr: s.GetGrantOption(acl.Create),
|
||||||
|
schemaPolicyUsageAttr: s.GetPrivilege(acl.Usage),
|
||||||
|
schemaPolicyUsageWithGrantAttr: s.GetGrantOption(acl.Usage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func schemaPolicyToACL(policyMap map[string]interface{}) acl.Schema {
|
||||||
|
var rolePolicy acl.Schema
|
||||||
|
|
||||||
|
if policyMap[schemaPolicyCreateAttr].(bool) {
|
||||||
|
rolePolicy.Privileges |= acl.Create
|
||||||
|
}
|
||||||
|
|
||||||
|
if policyMap[schemaPolicyCreateWithGrantAttr].(bool) {
|
||||||
|
rolePolicy.Privileges |= acl.Create
|
||||||
|
rolePolicy.GrantOptions |= acl.Create
|
||||||
|
}
|
||||||
|
|
||||||
|
if policyMap[schemaPolicyUsageAttr].(bool) {
|
||||||
|
rolePolicy.Privileges |= acl.Usage
|
||||||
|
}
|
||||||
|
|
||||||
|
if policyMap[schemaPolicyUsageWithGrantAttr].(bool) {
|
||||||
|
rolePolicy.Privileges |= acl.Usage
|
||||||
|
rolePolicy.GrantOptions |= acl.Usage
|
||||||
|
}
|
||||||
|
|
||||||
|
if roleRaw, ok := policyMap[schemaPolicyRoleAttr]; ok {
|
||||||
|
rolePolicy.Role = roleRaw.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rolePolicy
|
||||||
|
}
|
||||||
|
|
|
@ -1,442 +0,0 @@
|
||||||
package postgresql
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
|
||||||
"github.com/lib/pq"
|
|
||||||
"github.com/sean-/pgacl"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
schemaPolicyCreateAttr = "create"
|
|
||||||
schemaPolicyCreateWithGrantAttr = "create_with_grant"
|
|
||||||
schemaPolicyRoleAttr = "role"
|
|
||||||
schemaPolicySchemaAttr = "schema"
|
|
||||||
schemaPolicyUsageAttr = "usage"
|
|
||||||
schemaPolicyUsageWithGrantAttr = "usage_with_grant"
|
|
||||||
// schemaPolicyRolesAttr = "roles"
|
|
||||||
// schemaPolicySchemasAttr = "schemas"
|
|
||||||
)
|
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaPolicy() *schema.Resource {
|
|
||||||
return &schema.Resource{
|
|
||||||
Create: resourcePostgreSQLSchemaPolicyCreate,
|
|
||||||
Read: resourcePostgreSQLSchemaPolicyRead,
|
|
||||||
Update: resourcePostgreSQLSchemaPolicyUpdate,
|
|
||||||
Delete: resourcePostgreSQLSchemaPolicyDelete,
|
|
||||||
Importer: &schema.ResourceImporter{
|
|
||||||
State: schema.ImportStatePassthrough,
|
|
||||||
},
|
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
schemaPolicyCreateAttr: {
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: false,
|
|
||||||
Description: "If true, allow the specified ROLEs to CREATE new objects within the schema(s)",
|
|
||||||
ConflictsWith: []string{schemaPolicyCreateWithGrantAttr},
|
|
||||||
},
|
|
||||||
schemaPolicyCreateWithGrantAttr: {
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: false,
|
|
||||||
Description: "If true, allow the specified ROLEs to CREATE new objects within the schema(s) and GRANT the same CREATE privilege to different ROLEs",
|
|
||||||
ConflictsWith: []string{schemaPolicyCreateAttr},
|
|
||||||
},
|
|
||||||
// schemaPolicyRolesAttr: {
|
|
||||||
// Type: schema.TypeList,
|
|
||||||
// Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
// Description: "List of ROLEs who will receive this policy",
|
|
||||||
// },
|
|
||||||
schemaPolicyRoleAttr: {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
Description: "ROLE who will receive this policy",
|
|
||||||
},
|
|
||||||
schemaPolicySchemaAttr: {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
Description: "Target SCHEMA who will have this policy applied to it",
|
|
||||||
},
|
|
||||||
schemaPolicyUsageAttr: {
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: false,
|
|
||||||
Description: "If true, allow the specified ROLEs to use objects within the schema(s)",
|
|
||||||
ConflictsWith: []string{schemaPolicyUsageWithGrantAttr},
|
|
||||||
},
|
|
||||||
schemaPolicyUsageWithGrantAttr: {
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: false,
|
|
||||||
Description: "If true, allow the specified ROLEs to use objects within the schema(s) and GRANT the same USAGE privilege to different ROLEs",
|
|
||||||
ConflictsWith: []string{schemaPolicyUsageAttr},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaPolicyCreate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
id, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf("Unable to generate schema policy ID: {{err}}", err)
|
|
||||||
}
|
|
||||||
d.SetId(id)
|
|
||||||
|
|
||||||
acl := pgacl.Schema{}
|
|
||||||
role := d.Get(schemaPolicyRoleAttr).(string)
|
|
||||||
if strings.ToUpper(role) != "PUBLIC" {
|
|
||||||
role = pq.QuoteIdentifier(role)
|
|
||||||
}
|
|
||||||
|
|
||||||
acl.CreateGrant = d.Get(schemaPolicyCreateWithGrantAttr).(bool)
|
|
||||||
if acl.CreateGrant {
|
|
||||||
acl.Create = true
|
|
||||||
} else {
|
|
||||||
acl.Create = d.Get(schemaPolicyCreateAttr).(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
acl.UsageGrant = d.Get(schemaPolicyUsageWithGrantAttr).(bool)
|
|
||||||
if acl.UsageGrant {
|
|
||||||
acl.Usage = true
|
|
||||||
} else {
|
|
||||||
acl.Usage = d.Get(schemaPolicyUsageAttr).(bool)
|
|
||||||
}
|
|
||||||
schema := d.Get(schemaPolicySchemaAttr).(string)
|
|
||||||
|
|
||||||
queries := make([]string, 0, 2)
|
|
||||||
if acl.Create {
|
|
||||||
b := bytes.NewBufferString("GRANT CREATE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s TO %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
|
|
||||||
if acl.CreateGrant {
|
|
||||||
fmt.Fprint(b, " WITH GRANT OPTION")
|
|
||||||
}
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if acl.Usage {
|
|
||||||
b := bytes.NewBufferString("GRANT USAGE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s TO %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
if acl.UsageGrant {
|
|
||||||
fmt.Fprint(b, " WITH GRANT OPTION")
|
|
||||||
}
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
c := meta.(*Client)
|
|
||||||
conn, err := c.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
txn, err := conn.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
for _, query := range queries {
|
|
||||||
_, err = txn.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf(fmt.Sprintf("Error applying policy on schema (%+q): {{err}}", query), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := txn.Commit(); err != nil {
|
|
||||||
return errwrap.Wrapf("Error committing schema policy: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resourcePostgreSQLSchemaPolicyRead(d, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaPolicyDelete(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
role := d.Get(schemaPolicyRoleAttr).(string)
|
|
||||||
schema := d.Get(schemaPolicySchemaAttr).(string)
|
|
||||||
|
|
||||||
acl := pgacl.Schema{}
|
|
||||||
if strings.ToUpper(role) != "PUBLIC" {
|
|
||||||
role = pq.QuoteIdentifier(role)
|
|
||||||
}
|
|
||||||
|
|
||||||
acl.CreateGrant = d.Get(schemaPolicyCreateWithGrantAttr).(bool)
|
|
||||||
if acl.CreateGrant {
|
|
||||||
acl.Create = true
|
|
||||||
} else {
|
|
||||||
acl.Create = d.Get(schemaPolicyCreateAttr).(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
acl.UsageGrant = d.Get(schemaPolicyUsageWithGrantAttr).(bool)
|
|
||||||
if acl.UsageGrant {
|
|
||||||
acl.Usage = true
|
|
||||||
} else {
|
|
||||||
acl.Usage = d.Get(schemaPolicyUsageAttr).(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
queries := make([]string, 0, 2)
|
|
||||||
switch {
|
|
||||||
case !acl.Create:
|
|
||||||
b := bytes.NewBufferString("REVOKE CREATE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
case acl.Create && !acl.CreateGrant:
|
|
||||||
b := bytes.NewBufferString("REVOKE GRANT OPTION FOR CREATE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case !acl.Usage:
|
|
||||||
b := bytes.NewBufferString("REVOKE USAGE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
case acl.Usage && !acl.UsageGrant:
|
|
||||||
b := bytes.NewBufferString("REVOKE GRANT OPTION FOR USAGE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
queries = append(queries, b.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
c := meta.(*Client)
|
|
||||||
conn, err := c.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
txn, err := conn.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
for _, query := range queries {
|
|
||||||
_, err = txn.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf(fmt.Sprintf("Error removing policy on schema (%+q): {{err}}", query), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
txn.Commit()
|
|
||||||
|
|
||||||
d.SetId("")
|
|
||||||
|
|
||||||
return resourcePostgreSQLSchemaPolicyRead(d, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaPolicyRead(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
c := meta.(*Client)
|
|
||||||
conn, err := c.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
oraw, _ := d.GetChange(schemaPolicySchemaAttr)
|
|
||||||
o := oraw.(string)
|
|
||||||
|
|
||||||
var schemaName, schemaOwner, schemaACL string
|
|
||||||
err = conn.QueryRow("SELECT n.nspname, pg_catalog.pg_get_userbyid(n.nspowner), n.nspacl FROM pg_catalog.pg_namespace n WHERE n.nspname = $1", o).Scan(&schemaName, &schemaOwner, &schemaACL)
|
|
||||||
switch {
|
|
||||||
case err == sql.ErrNoRows:
|
|
||||||
log.Printf("[WARN] PostgreSQL schema (%s) not found", o)
|
|
||||||
d.SetId("")
|
|
||||||
return nil
|
|
||||||
case err != nil:
|
|
||||||
return errwrap.Wrapf("Error reading schema ACLs: {{err}}", err)
|
|
||||||
default:
|
|
||||||
acl, err := pgacl.NewSchema(schemaACL)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case acl.CreateGrant:
|
|
||||||
d.Set(schemaPolicyCreateWithGrantAttr, true)
|
|
||||||
d.Set(schemaPolicyCreateAttr, false)
|
|
||||||
case acl.Create:
|
|
||||||
d.Set(schemaPolicyCreateAttr, true)
|
|
||||||
d.Set(schemaPolicyCreateWithGrantAttr, false)
|
|
||||||
default:
|
|
||||||
d.Set(schemaPolicyCreateWithGrantAttr, false)
|
|
||||||
d.Set(schemaPolicyCreateAttr, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case acl.UsageGrant:
|
|
||||||
d.Set(schemaPolicyUsageWithGrantAttr, true)
|
|
||||||
d.Set(schemaPolicyUsageAttr, false)
|
|
||||||
case acl.Usage:
|
|
||||||
d.Set(schemaPolicyUsageAttr, true)
|
|
||||||
d.Set(schemaPolicyUsageWithGrantAttr, false)
|
|
||||||
default:
|
|
||||||
d.Set(schemaPolicyUsageWithGrantAttr, false)
|
|
||||||
d.Set(schemaPolicyUsageAttr, false)
|
|
||||||
}
|
|
||||||
d.Set(schemaPolicySchemaAttr, acl.Role)
|
|
||||||
d.Set(schemaPolicySchemaAttr, schemaName)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func resourcePostgreSQLSchemaPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
||||||
c := meta.(*Client)
|
|
||||||
conn, err := c.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
txn, err := conn.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
if err := setSchemaPolicyCreate(txn, d); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := setSchemaPolicyUsage(txn, d); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
txn.Commit()
|
|
||||||
|
|
||||||
return resourcePostgreSQLSchemaRead(d, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setSchemaPolicyCreate(txn *sql.Tx, d *schema.ResourceData) error {
|
|
||||||
if !d.HasChange(schemaPolicyCreateAttr) && !d.HasChange(schemaPolicyCreateWithGrantAttr) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
oldCreateRaw, newCreateRaw := d.GetChange(schemaPolicyCreateAttr)
|
|
||||||
oldCreate := oldCreateRaw.(bool)
|
|
||||||
newCreate := newCreateRaw.(bool)
|
|
||||||
|
|
||||||
oldGrantRaw, newGrantRaw := d.GetChange(schemaPolicyCreateWithGrantAttr)
|
|
||||||
oldGrant := oldGrantRaw.(bool)
|
|
||||||
newGrant := newGrantRaw.(bool)
|
|
||||||
|
|
||||||
var grant, revoke, withGrant bool
|
|
||||||
switch {
|
|
||||||
case oldCreate == newCreate:
|
|
||||||
// nothing changed
|
|
||||||
case oldCreate && !newCreate:
|
|
||||||
// Lost create privs
|
|
||||||
revoke = true
|
|
||||||
case !oldCreate && newCreate:
|
|
||||||
// Gaining create privs
|
|
||||||
grant = true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case newGrant == oldGrant:
|
|
||||||
// Nothing changed
|
|
||||||
case newGrant && !oldGrant, // Getting WITH GRANT OPTION priv
|
|
||||||
!newGrant && oldGrant: // Loosing WITH GRANT OPTION priv
|
|
||||||
withGrant = true
|
|
||||||
}
|
|
||||||
|
|
||||||
role := d.Get(schemaPolicyRoleAttr).(string)
|
|
||||||
if strings.ToUpper(role) != "PUBLIC" {
|
|
||||||
role = pq.QuoteIdentifier(role)
|
|
||||||
}
|
|
||||||
|
|
||||||
schema := d.Get(schemaPolicySchemaAttr).(string)
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
switch {
|
|
||||||
case grant:
|
|
||||||
b = bytes.NewBufferString("GRANT CREATE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s TO %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
if withGrant {
|
|
||||||
fmt.Fprint(b, " WITH GRANT OPTION")
|
|
||||||
}
|
|
||||||
case revoke:
|
|
||||||
b = bytes.NewBufferString("REVOKE")
|
|
||||||
if withGrant {
|
|
||||||
fmt.Fprint(b, " GRANT OPTION FOR")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(b, " CREATE ON SCHEMA %s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
}
|
|
||||||
|
|
||||||
query := b.String()
|
|
||||||
if _, err := txn.Query(query); err != nil {
|
|
||||||
return errwrap.Wrapf("Error updating schema create privileges: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setSchemaPolicyUsage(txn *sql.Tx, d *schema.ResourceData) error {
|
|
||||||
if !d.HasChange(schemaPolicyUsageAttr) && !d.HasChange(schemaPolicyUsageWithGrantAttr) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
oldUsageRaw, newUsageRaw := d.GetChange(schemaPolicyUsageAttr)
|
|
||||||
oldUsage := oldUsageRaw.(bool)
|
|
||||||
newUsage := newUsageRaw.(bool)
|
|
||||||
|
|
||||||
oldGrantRaw, newGrantRaw := d.GetChange(schemaPolicyUsageWithGrantAttr)
|
|
||||||
oldGrant := oldGrantRaw.(bool)
|
|
||||||
newGrant := newGrantRaw.(bool)
|
|
||||||
|
|
||||||
var grant, revoke, withGrant bool
|
|
||||||
switch {
|
|
||||||
case oldUsage == newUsage:
|
|
||||||
// nothing changed
|
|
||||||
case oldUsage && !newUsage:
|
|
||||||
// Lost usage privs
|
|
||||||
revoke = true
|
|
||||||
case !oldUsage && newUsage:
|
|
||||||
// Gaining usage privs
|
|
||||||
grant = true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case newGrant == oldGrant:
|
|
||||||
// Nothing changed
|
|
||||||
case newGrant && !oldGrant, // Getting WITH GRANT OPTION priv
|
|
||||||
!newGrant && oldGrant: // Loosing WITH GRANT OPTION priv
|
|
||||||
withGrant = true
|
|
||||||
}
|
|
||||||
|
|
||||||
role := d.Get(schemaPolicyRoleAttr).(string)
|
|
||||||
if strings.ToUpper(role) != "PUBLIC" {
|
|
||||||
role = pq.QuoteIdentifier(role)
|
|
||||||
}
|
|
||||||
|
|
||||||
schema := d.Get(schemaPolicySchemaAttr).(string)
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
switch {
|
|
||||||
case grant:
|
|
||||||
b = bytes.NewBufferString("GRANT USAGE ON SCHEMA ")
|
|
||||||
fmt.Fprintf(b, "%s TO %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
if withGrant {
|
|
||||||
fmt.Fprint(b, " WITH GRANT OPTION")
|
|
||||||
}
|
|
||||||
case revoke:
|
|
||||||
b = bytes.NewBufferString("REVOKE")
|
|
||||||
if withGrant {
|
|
||||||
fmt.Fprint(b, " GRANT OPTION FOR")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(b, " USAGE ON SCHEMA %s FROM %s", pq.QuoteIdentifier(schema), role)
|
|
||||||
}
|
|
||||||
|
|
||||||
query := b.String()
|
|
||||||
if _, err := txn.Query(query); err != nil {
|
|
||||||
return errwrap.Wrapf("Error updating schema usage privileges: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
package postgresql
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAccPostgreSQLSchemaPolicy_Basic(t *testing.T) {
|
|
||||||
resource.Test(t, resource.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Providers: testAccProviders,
|
|
||||||
CheckDestroy: testAccCheckPostgreSQLSchemaPolicyDestroy,
|
|
||||||
Steps: []resource.TestStep{
|
|
||||||
{
|
|
||||||
Config: testAccPostgreSQLSchemaPolicyConfig,
|
|
||||||
Check: resource.ComposeTestCheckFunc(
|
|
||||||
testAccCheckPostgreSQLSchemaPolicyExists("postgresql_schema.test1", "foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_role.dba", "name", "dba"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_role.app1", "name", "app1"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_role.app2", "name", "app2"),
|
|
||||||
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema.foo", "name", "foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema.owner", "name", "dba"),
|
|
||||||
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "create", "false"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "create_with_grant", "true"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "usage", "false"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "usage_with_grant", "true"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "schema", "foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_allow", "role", "app1"),
|
|
||||||
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_deny", "schema", "foo"),
|
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_schema_policy.foo_deny", "role", "app2"),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckPostgreSQLSchemaPolicyDestroy(s *terraform.State) error {
|
|
||||||
client := testAccProvider.Meta().(*Client)
|
|
||||||
|
|
||||||
for _, rs := range s.RootModule().Resources {
|
|
||||||
if rs.Type != "postgresql_schema" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
exists, err := checkSchemaExists(client, rs.Primary.ID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error checking schema %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if exists {
|
|
||||||
return fmt.Errorf("Schema still exists after destroy")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccCheckPostgreSQLSchemaPolicyExists(n string, schemaName string) resource.TestCheckFunc {
|
|
||||||
return func(s *terraform.State) error {
|
|
||||||
rs, ok := s.RootModule().Resources[n]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("Resource not found: %s", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rs.Primary.ID == "" {
|
|
||||||
return fmt.Errorf("No ID is set")
|
|
||||||
}
|
|
||||||
|
|
||||||
actualSchemaName := rs.Primary.Attributes["name"]
|
|
||||||
if actualSchemaName != schemaName {
|
|
||||||
return fmt.Errorf("Wrong value for schema name expected %s got %s", schemaName, actualSchemaName)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := testAccProvider.Meta().(*Client)
|
|
||||||
exists, err := checkSchemaExists(client, rs.Primary.ID)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error checking schema %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
return fmt.Errorf("Schema not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSchemaPolicyExists(client *Client, schemaName string) (bool, error) {
|
|
||||||
conn, err := client.Connect()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
var _rez string
|
|
||||||
err = conn.QueryRow("SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname=$1", schemaName).Scan(&_rez)
|
|
||||||
switch {
|
|
||||||
case err == sql.ErrNoRows:
|
|
||||||
return false, nil
|
|
||||||
case err != nil:
|
|
||||||
return false, fmt.Errorf("Error reading info about schema: %s", err)
|
|
||||||
default:
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testAccPostgreSQLSchemaPolicyConfig = `
|
|
||||||
resource "postgresql_role" "dba" {
|
|
||||||
name = "dba"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "postgresql_role" "app1" {
|
|
||||||
name = "app1"
|
|
||||||
# depends_on = ["postgresql_schema_policy.foo_allow"]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "postgresql_role" "app2" {
|
|
||||||
name = "app2"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "postgresql_schema" "foo" {
|
|
||||||
name = "foo"
|
|
||||||
owner = "${postgresql_role.dba.name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "postgresql_schema_policy" "foo_allow" {
|
|
||||||
create_with_grant = true
|
|
||||||
usage_with_grant = true
|
|
||||||
|
|
||||||
schema = "${postgresql_schema.foo.name}"
|
|
||||||
role = "${postgresql_role.app1.name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "postgresql_schema_policy" "foo_deny" {
|
|
||||||
schema = "${postgresql_schema.foo.name}"
|
|
||||||
role = "${postgresql_role.app2.name}"
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -19,18 +19,142 @@ func TestAccPostgresqlSchema_Basic(t *testing.T) {
|
||||||
Config: testAccPostgresqlSchemaConfig,
|
Config: testAccPostgresqlSchemaConfig,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckPostgresqlSchemaExists("postgresql_schema.test1", "foo"),
|
testAccCheckPostgresqlSchemaExists("postgresql_schema.test1", "foo"),
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr("postgresql_role.role_all_without_grant", "name", "role_all_without_grant"),
|
||||||
"postgresql_role.myrole3", "name", "myrole3"),
|
resource.TestCheckResourceAttr("postgresql_role.role_all_without_grant", "login", "true"),
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"postgresql_role.myrole3", "login", "true"),
|
|
||||||
|
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr("postgresql_role.role_all_with_grant", "name", "role_all_with_grant"),
|
||||||
"postgresql_schema.test1", "name", "foo"),
|
|
||||||
|
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr("postgresql_schema.test1", "name", "foo"),
|
||||||
"postgresql_schema.test2", "name", "bar"),
|
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "name", "bar"),
|
||||||
"postgresql_schema.test2", "owner", "myrole3"),
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "owner", "role_all_without_grant"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "if_not_exists", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.#", "1"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.1948480595.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.1948480595.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.1948480595.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.1948480595.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test2", "policy.1948480595.role", "role_all_without_grant"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "name", "baz"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "owner", "role_all_without_grant"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "if_not_exists", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.#", "2"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1013320538.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1013320538.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1013320538.role", "role_all_with_grant"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1948480595.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1948480595.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test3", "policy.1948480595.role", "role_all_without_grant"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccPostgresqlSchema_AddPolicy(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckPostgresqlSchemaDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccPostgresqlSchemaGrant1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckPostgresqlSchemaExists("postgresql_schema.test4", "test4"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_without_grant_stay", "name", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_without_grant_drop", "name", "all_without_grant_drop"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.policy_compose", "name", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.policy_move", "name", "policy_move"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_with_grantstay", "name", "all_with_grantstay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_with_grantdrop", "name", "all_with_grantdrop"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "name", "test4"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "owner", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.#", "7"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.role", "all_with_grantstay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1417738359.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1417738359.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1417738359.role", "policy_move"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1417738359.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1417738359.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1762357194.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1762357194.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1762357194.role", "all_without_grant_drop"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1762357194.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.1762357194.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.role", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.role", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.4178211897.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.4178211897.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.4178211897.role", "all_with_grantdrop"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.4178211897.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.4178211897.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.role", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.usage_with_grant", "false"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccPostgresqlSchemaGrant2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckPostgresqlSchemaExists("postgresql_schema.test4", "test4"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_without_grant_stay", "name", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_without_grant_drop", "name", "all_without_grant_drop"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.policy_compose", "name", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.policy_move", "name", "policy_move"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_role.all_with_grantstay", "name", "all_with_grantstay"),
|
||||||
|
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "name", "test4"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "owner", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.#", "6"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.role", "all_with_grantstay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.108605972.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.role", "all_without_grant_stay"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.2524457447.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3831594020.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3831594020.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3831594020.role", "policy_move"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3831594020.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3831594020.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.create", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.create_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.role", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.usage", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.3959936977.usage_with_grant", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.468685299.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.468685299.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.468685299.role", "policy_new"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.468685299.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.468685299.usage_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.create", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.create_with_grant", "false"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.role", "policy_compose"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.usage", "true"),
|
||||||
|
resource.TestCheckResourceAttr("postgresql_schema.test4", "policy.815478369.usage_with_grant", "false"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -108,18 +232,187 @@ func checkSchemaExists(client *Client, schemaName string) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var testAccPostgresqlSchemaConfig = `
|
const testAccPostgresqlSchemaConfig = `
|
||||||
resource "postgresql_role" "myrole3" {
|
resource "postgresql_role" "role_all_without_grant" {
|
||||||
name = "myrole3"
|
name = "role_all_without_grant"
|
||||||
login = true
|
login = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "role_all_with_grant" {
|
||||||
|
name = "role_all_with_grant"
|
||||||
|
}
|
||||||
|
|
||||||
resource "postgresql_schema" "test1" {
|
resource "postgresql_schema" "test1" {
|
||||||
name = "foo"
|
name = "foo"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "postgresql_schema" "test2" {
|
resource "postgresql_schema" "test2" {
|
||||||
name = "bar"
|
name = "bar"
|
||||||
owner = "${postgresql_role.myrole3.name}"
|
owner = "${postgresql_role.role_all_without_grant.name}"
|
||||||
|
if_not_exists = false
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.role_all_without_grant.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_schema" "test3" {
|
||||||
|
name = "baz"
|
||||||
|
owner = "${postgresql_role.role_all_without_grant.name}"
|
||||||
|
if_not_exists = true
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.role_all_with_grant.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.role_all_without_grant.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccPostgresqlSchemaGrant1 = `
|
||||||
|
resource "postgresql_role" "all_without_grant_stay" {
|
||||||
|
name = "all_without_grant_stay"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "all_without_grant_drop" {
|
||||||
|
name = "all_without_grant_drop"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "policy_compose" {
|
||||||
|
name = "policy_compose"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "policy_move" {
|
||||||
|
name = "policy_move"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "all_with_grantstay" {
|
||||||
|
name = "all_with_grantstay"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "all_with_grantdrop" {
|
||||||
|
name = "all_with_grantdrop"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_schema" "test4" {
|
||||||
|
name = "test4"
|
||||||
|
owner = "${postgresql_role.all_without_grant_stay.name}"
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.all_without_grant_stay.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.all_without_grant_drop.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.policy_compose.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.policy_move.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.all_with_grantstay.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.all_with_grantdrop.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.policy_compose.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccPostgresqlSchemaGrant2 = `
|
||||||
|
resource "postgresql_role" "all_without_grant_stay" {
|
||||||
|
name = "all_without_grant_stay"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "all_without_grant_drop" {
|
||||||
|
name = "all_without_grant_drop"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "policy_compose" {
|
||||||
|
name = "policy_compose"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "policy_move" {
|
||||||
|
name = "policy_move"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "all_with_grantstay" {
|
||||||
|
name = "all_with_grantstay"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_role" "policy_new" {
|
||||||
|
name = "policy_new"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "postgresql_schema" "test4" {
|
||||||
|
name = "test4"
|
||||||
|
owner = "${postgresql_role.all_without_grant_stay.name}"
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.all_without_grant_stay.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.policy_compose.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.all_with_grantstay.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.policy_compose.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create_with_grant = true
|
||||||
|
usage_with_grant = true
|
||||||
|
role = "${postgresql_role.policy_move.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
create = true
|
||||||
|
usage = true
|
||||||
|
role = "${postgresql_role.policy_new.name}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
Loading…
Reference in New Issue