@@ -49,6 +49,24 @@ func TestCreateGrantQuery(t *testing.T) {
4949 privileges : []string {"EXECUTE" },
5050 expected : fmt .Sprintf ("GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA %s TO %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
5151 },
52+ {
53+ resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
54+ "object_type" : "procedure" ,
55+ "schema" : databaseName ,
56+ "role" : roleName ,
57+ }),
58+ privileges : []string {"EXECUTE" },
59+ expected : fmt .Sprintf ("GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA %s TO %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
60+ },
61+ {
62+ resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
63+ "object_type" : "routine" ,
64+ "schema" : databaseName ,
65+ "role" : roleName ,
66+ }),
67+ privileges : []string {"EXECUTE" },
68+ expected : fmt .Sprintf ("GRANT EXECUTE ON ALL ROUTINES IN SCHEMA %s TO %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
69+ },
5270 {
5371 resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
5472 "object_type" : "TABLE" ,
@@ -171,6 +189,30 @@ func TestCreateRevokeQuery(t *testing.T) {
171189 }),
172190 expected : fmt .Sprintf ("REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA %s FROM %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
173191 },
192+ {
193+ resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
194+ "object_type" : "function" ,
195+ "schema" : databaseName ,
196+ "role" : roleName ,
197+ }),
198+ expected : fmt .Sprintf ("REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA %s FROM %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
199+ },
200+ {
201+ resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
202+ "object_type" : "procedure" ,
203+ "schema" : databaseName ,
204+ "role" : roleName ,
205+ }),
206+ expected : fmt .Sprintf ("REVOKE ALL PRIVILEGES ON ALL PROCEDURES IN SCHEMA %s FROM %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
207+ },
208+ {
209+ resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
210+ "object_type" : "routine" ,
211+ "schema" : databaseName ,
212+ "role" : roleName ,
213+ }),
214+ expected : fmt .Sprintf ("REVOKE ALL PRIVILEGES ON ALL ROUTINES IN SCHEMA %s FROM %s" , pq .QuoteIdentifier (databaseName ), pq .QuoteIdentifier (roleName )),
215+ },
174216 {
175217 resource : schema .TestResourceDataRaw (t , resourcePostgreSQLGrant ().Schema , map [string ]interface {}{
176218 "object_type" : "database" ,
@@ -608,6 +650,7 @@ func TestAccPostgresqlGrantFunction(t *testing.T) {
608650 dbExecute (t , dsn , fmt .Sprintf ("CREATE ROLE test_role LOGIN PASSWORD '%s'" , testRolePassword ))
609651 dbExecute (t , dsn , "CREATE SCHEMA test_schema" )
610652 dbExecute (t , dsn , "GRANT USAGE ON SCHEMA test_schema TO test_role" )
653+ dbExecute (t , dsn , "ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC" )
611654
612655 // Create test function in this schema
613656 dbExecute (t , dsn , `
@@ -658,6 +701,137 @@ resource postgresql_grant "test" {
658701 }
659702}
660703
704+ func TestAccPostgresqlGrantProcedure (t * testing.T ) {
705+ skipIfNotAcc (t )
706+ testCheckCompatibleVersion (t , featureProcedure )
707+
708+ config := getTestConfig (t )
709+ dsn := config .connStr ("postgres" )
710+
711+ // Create a test role and a schema as public has too wide open privileges
712+ dbExecute (t , dsn , fmt .Sprintf ("CREATE ROLE test_role LOGIN PASSWORD '%s'" , testRolePassword ))
713+ dbExecute (t , dsn , "CREATE SCHEMA test_schema" )
714+ dbExecute (t , dsn , "GRANT USAGE ON SCHEMA test_schema TO test_role" )
715+ dbExecute (t , dsn , "ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC" )
716+
717+ // Create test procedure in this schema
718+ dbExecute (t , dsn , `
719+ CREATE PROCEDURE test_schema.test()
720+ AS $$ select 'foo'::text $$
721+ LANGUAGE SQL;
722+ ` )
723+ defer func () {
724+ dbExecute (t , dsn , "DROP SCHEMA test_schema CASCADE" )
725+ dbExecute (t , dsn , "DROP ROLE test_role" )
726+ }()
727+
728+ // Test to grant directly to test_role and to public
729+ // in both case test_case should have the right
730+ for _ , role := range []string {"test_role" , "public" } {
731+ t .Run (role , func (t * testing.T ) {
732+
733+ tfConfig := fmt .Sprintf (`
734+ resource postgresql_grant "test" {
735+ database = "postgres"
736+ role = "%s"
737+ schema = "test_schema"
738+ object_type = "procedure"
739+ privileges = ["EXECUTE"]
740+ }
741+ ` , role )
742+
743+ resource .Test (t , resource.TestCase {
744+ PreCheck : func () {
745+ testAccPreCheck (t )
746+ testCheckCompatibleVersion (t , featurePrivileges )
747+ },
748+ Providers : testAccProviders ,
749+ Steps : []resource.TestStep {
750+ {
751+ Config : tfConfig ,
752+ Check : resource .ComposeTestCheckFunc (
753+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "id" , fmt .Sprintf ("%s_postgres_test_schema_procedure" , role )),
754+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "privileges.#" , "1" ),
755+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "privileges.0" , "EXECUTE" ),
756+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "with_grant_option" , "false" ),
757+ testCheckProcedureExecutable (t , "test_role" , "test_schema.test" ),
758+ ),
759+ },
760+ },
761+ })
762+ })
763+ }
764+ }
765+
766+ func TestAccPostgresqlGrantRoutine (t * testing.T ) {
767+ skipIfNotAcc (t )
768+ testCheckCompatibleVersion (t , featureRoutine )
769+
770+ config := getTestConfig (t )
771+ dsn := config .connStr ("postgres" )
772+
773+ // Create a test role and a schema as public has too wide open privileges
774+ dbExecute (t , dsn , fmt .Sprintf ("CREATE ROLE test_role LOGIN PASSWORD '%s'" , testRolePassword ))
775+ dbExecute (t , dsn , "CREATE SCHEMA test_schema" )
776+ dbExecute (t , dsn , "GRANT USAGE ON SCHEMA test_schema TO test_role" )
777+ dbExecute (t , dsn , "ALTER DEFAULT PRIVILEGES REVOKE ALL ON FUNCTIONS FROM PUBLIC" )
778+
779+ // Create test function in this schema
780+ dbExecute (t , dsn , `
781+ CREATE FUNCTION test_schema.test_function() RETURNS text
782+ AS $$ select 'foo'::text $$
783+ LANGUAGE SQL;
784+ ` )
785+ // Create test procedure in this schema
786+ dbExecute (t , dsn , `
787+ CREATE PROCEDURE test_schema.test_procedure()
788+ AS $$ select 'foo'::text $$
789+ LANGUAGE SQL;
790+ ` )
791+ defer func () {
792+ dbExecute (t , dsn , "DROP SCHEMA test_schema CASCADE" )
793+ dbExecute (t , dsn , "DROP ROLE test_role" )
794+ }()
795+
796+ // Test to grant directly to test_role and to public
797+ // in both case test_case should have the right
798+ for _ , role := range []string {"test_role" , "public" } {
799+ t .Run (role , func (t * testing.T ) {
800+
801+ tfConfigRoutine := fmt .Sprintf (`
802+ resource postgresql_grant "test" {
803+ database = "postgres"
804+ role = "%s"
805+ schema = "test_schema"
806+ object_type = "routine"
807+ privileges = ["EXECUTE"]
808+ }
809+ ` , role )
810+
811+ resource .Test (t , resource.TestCase {
812+ PreCheck : func () {
813+ testAccPreCheck (t )
814+ testCheckCompatibleVersion (t , featurePrivileges )
815+ },
816+ Providers : testAccProviders ,
817+ Steps : []resource.TestStep {
818+ {
819+ Config : tfConfigRoutine ,
820+ Check : resource .ComposeTestCheckFunc (
821+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "id" , fmt .Sprintf ("%s_postgres_test_schema_routine" , role )),
822+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "privileges.#" , "1" ),
823+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "privileges.0" , "EXECUTE" ),
824+ resource .TestCheckResourceAttr ("postgresql_grant.test" , "with_grant_option" , "false" ),
825+ testCheckFunctionExecutable (t , "test_role" , "test_schema.test_function" ),
826+ testCheckProcedureExecutable (t , "test_role" , "test_schema.test_procedure" ),
827+ ),
828+ },
829+ },
830+ })
831+ })
832+ }
833+ }
834+
661835func TestAccPostgresqlGrantDatabase (t * testing.T ) {
662836 // create a TF config with placeholder for privileges
663837 // it will be filled in each step.
@@ -931,6 +1105,18 @@ func testCheckFunctionExecutable(t *testing.T, role, function string) func(*terr
9311105 }
9321106}
9331107
1108+ func testCheckProcedureExecutable (t * testing.T , role , procedure string ) func (* terraform.State ) error {
1109+ return func (* terraform.State ) error {
1110+ db := connectAsTestRole (t , role , "postgres" )
1111+ defer db .Close ()
1112+
1113+ if err := testHasGrantForQuery (db , fmt .Sprintf ("CALL %s()" , procedure ), true ); err != nil {
1114+ return err
1115+ }
1116+ return nil
1117+ }
1118+ }
1119+
9341120func testCheckSchemaPrivileges (t * testing.T , usage , create bool ) func (* terraform.State ) error {
9351121 return func (* terraform.State ) error {
9361122 config := getTestConfig (t )
0 commit comments