Expand postgresql_role support to include all known options.
This commit is contained in:
parent
4c6c52ee8d
commit
1a93309e50
|
@ -181,10 +181,7 @@ func resourcePostgreSQLRoleCreate(d *schema.ResourceData, meta interface{}) erro
|
||||||
} else {
|
} else {
|
||||||
createOpts = append(createOpts, "UNENCRYPTED")
|
createOpts = append(createOpts, "UNENCRYPTED")
|
||||||
}
|
}
|
||||||
escapedPassword := strconv.Quote(val)
|
createOpts = append(createOpts, fmt.Sprintf("%s '%s'", opt.sqlKey, pqQuoteLiteral(val)))
|
||||||
escapedPassword = strings.TrimLeft(escapedPassword, `"`)
|
|
||||||
escapedPassword = strings.TrimRight(escapedPassword, `"`)
|
|
||||||
createOpts = append(createOpts, fmt.Sprintf("%s '%s'", opt.sqlKey, escapedPassword))
|
|
||||||
}
|
}
|
||||||
case opt.hclKey == roleValidUntilAttr:
|
case opt.hclKey == roleValidUntilAttr:
|
||||||
switch {
|
switch {
|
||||||
|
@ -211,7 +208,6 @@ func resourcePostgreSQLRoleCreate(d *schema.ResourceData, meta interface{}) erro
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val := d.Get(opt.hclKey).(bool)
|
val := d.Get(opt.hclKey).(bool)
|
||||||
|
|
||||||
valStr := opt.sqlKeyDisable
|
valStr := opt.sqlKeyDisable
|
||||||
if val {
|
if val {
|
||||||
valStr = opt.sqlKeyEnable
|
valStr = opt.sqlKeyEnable
|
||||||
|
@ -245,7 +241,6 @@ func resourcePostgreSQLRoleDelete(d *schema.ResourceData, meta interface{}) erro
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
roleName := d.Get(roleNameAttr).(string)
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
|
||||||
query := fmt.Sprintf("DROP ROLE %s", pq.QuoteIdentifier(roleName))
|
query := fmt.Sprintf("DROP ROLE %s", pq.QuoteIdentifier(roleName))
|
||||||
_, err = conn.Query(query)
|
_, err = conn.Query(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -265,91 +260,289 @@ func resourcePostgreSQLRoleRead(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
roleName := d.Get(roleNameAttr).(string)
|
roleId := d.Id()
|
||||||
if roleName == "" {
|
var roleSuperuser, roleInherit, roleCreateRole, roleCreateDB, roleCanLogin, roleReplication, roleBypassRLS bool
|
||||||
roleName = d.Id()
|
var roleConnLimit int
|
||||||
}
|
var roleName, roleValidUntil string
|
||||||
|
err = conn.QueryRow("SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolconnlimit, COALESCE(rolvaliduntil::TEXT, 'infinity'), rolbypassrls FROM pg_catalog.pg_roles WHERE rolname=$1", roleId).Scan(&roleName, &roleSuperuser, &roleInherit, &roleCreateRole, &roleCreateDB, &roleCanLogin, &roleReplication, &roleConnLimit, &roleValidUntil, &roleBypassRLS)
|
||||||
var roleCanLogin bool
|
|
||||||
err = conn.QueryRow("SELECT rolcanlogin FROM pg_roles WHERE rolname=$1", roleName).Scan(&roleCanLogin)
|
|
||||||
switch {
|
switch {
|
||||||
case err == sql.ErrNoRows:
|
case err == sql.ErrNoRows:
|
||||||
log.Printf("[WARN] PostgreSQL database (%s) not found", d.Id())
|
log.Printf("[WARN] PostgreSQL role (%s) not found", roleId)
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return errwrap.Wrapf("Error reading role: {{err}}", err)
|
return errwrap.Wrapf("Error reading role: {{err}}", err)
|
||||||
default:
|
default:
|
||||||
d.Set(roleNameAttr, roleName)
|
d.Set(roleNameAttr, roleName)
|
||||||
|
d.Set(roleBypassRLSAttr, roleBypassRLS)
|
||||||
|
d.Set(roleConnLimitAttr, roleConnLimit)
|
||||||
|
d.Set(roleCreateDBAttr, roleCreateDB)
|
||||||
|
d.Set(roleCreateRoleAttr, roleCreateRole)
|
||||||
|
d.Set(roleEncryptedPassAttr, true)
|
||||||
|
d.Set(roleInheritAttr, roleInherit)
|
||||||
d.Set(roleLoginAttr, roleCanLogin)
|
d.Set(roleLoginAttr, roleCanLogin)
|
||||||
d.Set("encrypted", true)
|
d.Set(roleReplicationAttr, roleReplication)
|
||||||
|
d.Set(roleSuperuserAttr, roleSuperuser)
|
||||||
|
d.Set(roleValidUntilAttr, roleValidUntil)
|
||||||
d.SetId(roleName)
|
d.SetId(roleName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !roleSuperuser {
|
||||||
|
// Return early if not superuser user
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var rolePassword string
|
||||||
|
err = conn.QueryRow("SELECT COALESCE(passwd, '') FROM pg_catalog.pg_shadow AS s WHERE s.usename = $1", roleId).Scan(&rolePassword)
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
return fmt.Errorf("PostgreSQL role (%s) not found in shadow database: {{err}}", roleId)
|
||||||
|
case err != nil:
|
||||||
|
return errwrap.Wrapf("Error reading role: {{err}}", err)
|
||||||
|
default:
|
||||||
|
d.Set(rolePasswordAttr, rolePassword)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourcePostgreSQLRoleUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourcePostgreSQLRoleUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*Client)
|
c := meta.(*Client)
|
||||||
conn, err := client.Connect()
|
conn, err := c.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
d.Partial(true)
|
if err := setRoleName(conn, d); err != nil {
|
||||||
|
return err
|
||||||
roleName := d.Get(roleNameAttr).(string)
|
|
||||||
|
|
||||||
if d.HasChange(roleLoginAttr) {
|
|
||||||
loginAttr := getLoginStr(d.Get(roleLoginAttr).(bool))
|
|
||||||
query := fmt.Sprintf("ALTER ROLE %s %s", pq.QuoteIdentifier(roleName), pq.QuoteIdentifier(loginAttr))
|
|
||||||
_, err := conn.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf("Error updating login attribute for role: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d.SetPartial(roleLoginAttr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
password := d.Get(rolePasswordAttr).(string)
|
if err := setRoleBypassRLS(conn, d); err != nil {
|
||||||
if d.HasChange(rolePasswordAttr) {
|
return err
|
||||||
encryptedCfg := getEncryptedStr(d.Get("encrypted").(bool))
|
|
||||||
|
|
||||||
query := fmt.Sprintf("ALTER ROLE %s %s PASSWORD '%s'", pq.QuoteIdentifier(roleName), encryptedCfg, password)
|
|
||||||
_, err := conn.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
return errwrap.Wrapf("Error updating password attribute for role: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d.SetPartial(rolePasswordAttr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.HasChange("encrypted") {
|
if err := setRoleConnLimit(conn, d); err != nil {
|
||||||
encryptedCfg := getEncryptedStr(d.Get("encrypted").(bool))
|
return err
|
||||||
|
}
|
||||||
query := fmt.Sprintf("ALTER ROLE %s %s PASSWORD '%s'", pq.QuoteIdentifier(roleName), encryptedCfg, password)
|
|
||||||
_, err := conn.Query(query)
|
if err := setRoleCreateDB(conn, d); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return errwrap.Wrapf("Error updating encrypted attribute for role: {{err}}", err)
|
}
|
||||||
}
|
|
||||||
|
if err := setRoleCreateRole(conn, d); err != nil {
|
||||||
d.SetPartial("encrypted")
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setRoleInherit(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setRoleLogin(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setRoleReplication(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setRoleSuperuser(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setRoleValidUntil(conn, d); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Partial(false)
|
|
||||||
return resourcePostgreSQLRoleRead(d, meta)
|
return resourcePostgreSQLRoleRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLoginStr(canLogin bool) string {
|
func setRoleName(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
if canLogin {
|
if !d.HasChange(roleNameAttr) {
|
||||||
return "login"
|
return nil
|
||||||
}
|
}
|
||||||
return "nologin"
|
|
||||||
|
oraw, nraw := d.GetChange(roleNameAttr)
|
||||||
|
o := oraw.(string)
|
||||||
|
n := nraw.(string)
|
||||||
|
if n == "" {
|
||||||
|
return errors.New("Error setting role name to an empty string")
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s RENAME TO %s", pq.QuoteIdentifier(o), pq.QuoteIdentifier(n))
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role NAME: {{err}}", err)
|
||||||
|
}
|
||||||
|
d.SetId(n)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEncryptedStr(isEncrypted bool) string {
|
func setRoleBypassRLS(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
if isEncrypted {
|
if !d.HasChange(roleBypassRLSAttr) {
|
||||||
return "encrypted"
|
return nil
|
||||||
}
|
}
|
||||||
return "unencrypted"
|
|
||||||
|
bypassRLS := d.Get(roleBypassRLSAttr).(bool)
|
||||||
|
tok := "NOBYPASSRLS"
|
||||||
|
if bypassRLS {
|
||||||
|
tok = "BYPASSRLS"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role BYPASSRLS: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleConnLimit(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleConnLimitAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
connLimit := d.Get(roleConnLimitAttr).(int)
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s CONNECTION LIMIT = %d", pq.QuoteIdentifier(roleName), connLimit)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role CONNECTION LIMIT: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleCreateDB(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleCreateDBAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
createDB := d.Get(roleCreateDBAttr).(bool)
|
||||||
|
tok := "NOCREATEDB"
|
||||||
|
if createDB {
|
||||||
|
tok = "CREATEDB"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role CREATEDB: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleCreateRole(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleCreateRoleAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
createRole := d.Get(roleCreateRoleAttr).(bool)
|
||||||
|
tok := "NOCREATEROLE"
|
||||||
|
if createRole {
|
||||||
|
tok = "CREATEROLE"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role CREATEROLE: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleInherit(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleInheritAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
inherit := d.Get(roleInheritAttr).(bool)
|
||||||
|
tok := "NOINHERIT"
|
||||||
|
if inherit {
|
||||||
|
tok = "INHERIT"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role INHERIT: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleLogin(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleLoginAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
login := d.Get(roleLoginAttr).(bool)
|
||||||
|
tok := "NOLOGIN"
|
||||||
|
if login {
|
||||||
|
tok = "LOGIN"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role LOGIN: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleReplication(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleReplicationAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
replication := d.Get(roleReplicationAttr).(bool)
|
||||||
|
tok := "NOREPLICATION"
|
||||||
|
if replication {
|
||||||
|
tok = "REPLICATION"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role REPLICATION: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleSuperuser(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleSuperuserAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
superuser := d.Get(roleSuperuserAttr).(bool)
|
||||||
|
tok := "NOSUPERUSER"
|
||||||
|
if superuser {
|
||||||
|
tok = "SUPERUSER"
|
||||||
|
}
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s WITH %s", pq.QuoteIdentifier(roleName), tok)
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role SUPERUSER: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRoleValidUntil(conn *sql.DB, d *schema.ResourceData) error {
|
||||||
|
if !d.HasChange(roleValidUntilAttr) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
validUntil := d.Get(roleValidUntilAttr).(string)
|
||||||
|
if validUntil == "" {
|
||||||
|
return nil
|
||||||
|
} else if strings.ToLower(validUntil) == "infinity" {
|
||||||
|
validUntil = "infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
roleName := d.Get(roleNameAttr).(string)
|
||||||
|
query := fmt.Sprintf("ALTER ROLE %s VALID UNTIL '%s'", pq.QuoteIdentifier(roleName), pqQuoteLiteral(validUntil))
|
||||||
|
|
||||||
|
if _, err := conn.Query(query); err != nil {
|
||||||
|
return errwrap.Wrapf("Error updating role VALID UNTIL: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue