diff --git a/manifests/server/default_privileges.pp b/manifests/server/default_privileges.pp index 9cc90935bf..4a6f846785 100644 --- a/manifests/server/default_privileges.pp +++ b/manifests/server/default_privileges.pp @@ -23,7 +23,8 @@ /(?i:^ROUTINES$)/, /(?i:^SEQUENCES$)/, /(?i:^TABLES$)/, - /(?i:^TYPES$)/ + /(?i:^TYPES$)/, + /(?i:^SCHEMAS$)/ ] $object_type, String $schema = 'public', String $psql_db = $postgresql::server::default_database, @@ -140,6 +141,21 @@ } $_check_type = 'T' } + 'SCHEMAS': { + if (versioncmp($version, '10') == -1) { + fail 'Default_privileges on schemas is only supported on PostgreSQL >= 10.0' + } + if $schema != '' { + fail('Cannot alter default schema permissions within a schema') + } + case $_privilege { + /^ALL$/: { $_check_privilege = 'UC' } + /^USAGE$/: { $_check_privilege = 'U' } + /^CREATE$/: { $_check_privilege = 'C' } + default: { fail('Illegal value for $privilege parameter') } + } + $_check_type = 'n' + } default: { fail("Missing privilege validation for object type ${_object_type}") } diff --git a/spec/acceptance/server/default_privileges_spec.rb b/spec/acceptance/server/default_privileges_spec.rb index db474da87b..c3eac9cee9 100644 --- a/spec/acceptance/server/default_privileges_spec.rb +++ b/spec/acceptance/server/default_privileges_spec.rb @@ -167,6 +167,67 @@ class { 'postgresql::server': } MANIFEST end + let(:schema_check_command) do + "SELECT * FROM pg_default_acl WHERE '#{user}=UC' = ANY (defaclacl) AND defaclnamespace = 0 and defaclobjtype = 'n';" + end + + let(:pp_schema) do + <<-MANIFEST.unindent + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Set default privileges on tables + postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'SCHEMAS', + schema => '', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + let(:pp_schema_revoke) do + <<-MANIFEST + $db = #{db} + $user = #{user} + $group = #{group} + $password = #{password} + + class { 'postgresql::server': } + + postgresql::server::role { $user: + password_hash => postgresql::postgresql_password($user, $password), + } + postgresql::server::database { $db: + require => Postgresql::Server::Role[$user], + } + + # Removes default privileges on tables + postgresql::server::default_privileges { "alter default privileges revoke all on tables for ${user}": + db => $db, + role => $user, + privilege => 'ALL', + object_type => 'SCHEMAS', + schema => '', + ensure => 'absent', + require => Postgresql::Server::Database[$db], + } + MANIFEST + end + let(:all_schemas_check_command) do "SELECT * FROM pg_default_acl a WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND defaclnamespace = 0 and defaclobjtype = 'r';" end @@ -274,6 +335,29 @@ class { 'postgresql::server': } end end + it 'grants default privileges to an user on schemas' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('10.0') + idempotent_apply(pp_schema) + + psql("--command=\"SET client_min_messages = 'error';#{schema_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(1 row\)}) + expect(r.stderr).to eq('') + end + end + end + + it 'revokes default privileges for an user on schemas' do + if Gem::Version.new(postgresql_version) >= Gem::Version.new('10.0') + apply_manifest(pp_schema, catch_failures: true) + apply_manifest(pp_schema_revoke, expect_changes: true) + + psql("--command=\"SET client_min_messages = 'error';#{schema_check_command}\" --db=#{db}") do |r| + expect(r.stdout).to match(%r{\(0 rows\)}) + expect(r.stderr).to eq('') + end + end + end + it 'grants default privileges on all schemas to a user' do if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6') idempotent_apply(pp_unset_schema) diff --git a/spec/unit/defines/server/default_privileges_spec.rb b/spec/unit/defines/server/default_privileges_spec.rb index d6612ff14b..d56b79f851 100644 --- a/spec/unit/defines/server/default_privileges_spec.rb +++ b/spec/unit/defines/server/default_privileges_spec.rb @@ -133,6 +133,117 @@ it { is_expected.to compile.and_raise_error(%r{Illegal value for \$privilege parameter}) } end + + context 'schemas on postgres < 10.0' do + let(:facts) do + { + os: { + family: 'Debian', + name: 'Debian', + release: { 'full' => '9.0', 'major' => '9' }, + }, + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: '', + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.and_raise_error(%r{Default_privileges on schemas is only supported on PostgreSQL >= 10.0}m) } + end + + context 'schemas on postgres >= 10.0' do + let :facts do + { + os: { + family: 'Debian', + name: 'Debian', + release: { 'full' => '10.0', 'major' => '10' }, + }, + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: '', + } + end + + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '10.0', + } + class { 'postgresql::server': } + MANIFEST + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + it do + # rubocop:disable Layout/LineLength + is_expected.to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO "test"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=UC' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'n')") + # rubocop:enable Layout/LineLength + end + end + + context 'nested schemas are invalid' do + let :facts do + { + os: { + family: 'Debian', + name: 'Debian', + release: { 'full' => '10.0', 'major' => '10' }, + }, + kernel: 'Linux', + id: 'root', + path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + + let :params do + { + db: 'test', + role: 'test', + privilege: 'all', + object_type: 'schemas', + schema: 'public', + } + end + + let :pre_condition do + <<-MANIFEST + class { 'postgresql::globals': + version => '10.0', + } + class { 'postgresql::server': } + MANIFEST + end + + it { is_expected.to compile.and_raise_error(%r{Cannot alter default schema permissions within a schema}) } + end end context 'with specific db connection settings - default port' do