Merge pull request #208 from hunner/add_grants
Add grant abilities for more that databases
This commit is contained in:
commit
9471fa5eb7
5 changed files with 225 additions and 53 deletions
45
README.md
45
README.md
|
@ -97,13 +97,21 @@ To manage users, roles and permissions:
|
|||
password_hash => 'foo',
|
||||
}
|
||||
|
||||
postgresql::database_grant{'test1':
|
||||
privilege => 'ALL',
|
||||
db => 'test1',
|
||||
role => 'dan',
|
||||
postgresql::database_grant { 'test1':
|
||||
privilege => 'ALL',
|
||||
db => 'test1',
|
||||
role => 'dan',
|
||||
}
|
||||
|
||||
In this example, you would grant ALL privileges on the test1 database to the user or group specified by dan.
|
||||
postgresql::table_grant { 'my_table of test2':
|
||||
privilege => 'ALL',
|
||||
table => 'my_table',
|
||||
db => 'test2',
|
||||
role => 'dan',
|
||||
}
|
||||
|
||||
|
||||
In this example, you would grant ALL privileges on the test1 database and on the `my_table` table of the test2 database to the user or group specified by dan.
|
||||
|
||||
At this point, you would just need to plunk these database name/username/password values into your PuppetDB config files, and you are good to go.
|
||||
|
||||
|
@ -127,6 +135,7 @@ Resources:
|
|||
* [postgresql::db](#resource-postgresqldb)
|
||||
* [postgresql::database](#resource-postgresqldatabase)
|
||||
* [postgresql::database_grant](#resource-postgresqldatabasegrant)
|
||||
* [postgresql::table_grant](#resource-postgresqltablegrant)
|
||||
* [postgresql::role](#resource-postgresqlrole)
|
||||
* [postgresql::tablespace](#resource-postgresqltablespace)
|
||||
* [postgresql::validate_db_connection](#resource-postgresqlvalidatedbconnection)
|
||||
|
@ -341,7 +350,7 @@ This defined type manages grant based access privileges for users. Consult the P
|
|||
Used to uniquely identify this resource, but functionality not used during grant.
|
||||
|
||||
####`privilege`
|
||||
Can be one of `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, `REFERENCES`, `TRIGGER`, `USAGE`, `TEMPORARY`, `TEMP`, `CONNECT`. `ALL` is used as a synonym for `CREATE`. If you need to add multiple privileges, a space delimited string can be used.
|
||||
Can be one of `SELECT`, `TEMPORARY`, `TEMP`, `CONNECT`. `ALL` is used as a synonym for `CREATE`. If you need to add multiple privileges, a space delimited string can be used.
|
||||
|
||||
####`db`
|
||||
Database to grant access to.
|
||||
|
@ -355,6 +364,30 @@ Database to execute the grant against. This should not ordinarily be changed fro
|
|||
####`psql_user`
|
||||
OS user for running `psql`. Defaults to the default user for the module, usually `postgres`.
|
||||
|
||||
###Resource: postgresql::table\_grant
|
||||
This defined type manages grant based access privileges for users. Consult the PostgreSQL documentation for `grant` for more information.
|
||||
|
||||
####`namevar`
|
||||
Used to uniquely identify this resource, but functionality not used during grant.
|
||||
|
||||
####`privilege`
|
||||
Can be one of `SELECT`, `INSERT`, `UPDATE`, `REFERENCES`. `ALL` is used as a synonym for `CREATE`. If you need to add multiple privileges, a space delimited string can be used.
|
||||
|
||||
####`table`
|
||||
Table to grant access on.
|
||||
|
||||
####`db`
|
||||
Database of table.
|
||||
|
||||
####`role`
|
||||
Role or user whom you are granting access for.
|
||||
|
||||
####`psql_db`
|
||||
Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`.
|
||||
|
||||
####`psql_user`
|
||||
OS user for running `psql`. Defaults to the default user for the module, usually `postgres`.
|
||||
|
||||
###Resource: postgresql::role
|
||||
This resource creates a role or user in PostgreSQL.
|
||||
|
||||
|
|
|
@ -15,50 +15,21 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# TODO: in mysql module, the grant resource name might look like this: 'user@host/dbname';
|
||||
# I think that the API for the resource type should split these up, because it's
|
||||
# easier / safer to recombine them for mysql than it is to parse them for other
|
||||
# databases. Also, in the mysql module, the hostname portion of that string
|
||||
# affects the user's ability to connect from remote hosts. In postgres this is
|
||||
# managed via pg_hba.conf; not sure if we want to try to reconcile that difference
|
||||
# in the modules or not.
|
||||
|
||||
define postgresql::database_grant(
|
||||
# TODO: mysql supports an array of privileges here. We should do that if we
|
||||
# port this to ruby.
|
||||
$privilege,
|
||||
$db,
|
||||
$role,
|
||||
$psql_db = $postgresql::params::user,
|
||||
$psql_user = $postgresql::params::user
|
||||
$psql_db = undef,
|
||||
$psql_user = undef
|
||||
) {
|
||||
include postgresql::params
|
||||
|
||||
Postgresql_psql {
|
||||
psql_user => $postgresql::params::user,
|
||||
psql_group => $postgresql::params::group,
|
||||
psql_path => $postgresql::params::psql_path,
|
||||
}
|
||||
|
||||
# TODO: FIXME: only works on databases, due to using has_database_privilege
|
||||
|
||||
# TODO: this is a terrible hack; if they pass "ALL" as the desired privilege,
|
||||
# we need a way to test for it--and has_database_privilege does not recognize
|
||||
# 'ALL' as a valid privilege name. So we probably need to hard-code a mapping
|
||||
# between 'ALL' and the list of actual privileges that it entails, and loop
|
||||
# over them to check them. That sort of thing will probably need to wait until
|
||||
# we port this over to ruby, so, for now, we're just going to assume that if
|
||||
# they have "CREATE" privileges on a database, then they have "ALL". (I told
|
||||
# you that it was terrible!)
|
||||
$unless_privilege = $privilege ? {
|
||||
'ALL' => 'CREATE',
|
||||
default => $privilege,
|
||||
}
|
||||
|
||||
postgresql_psql {"GRANT ${privilege} ON database \"${db}\" TO \"${role}\"":
|
||||
db => $psql_db,
|
||||
psql_user => $psql_user,
|
||||
unless => "SELECT 1 WHERE has_database_privilege('${role}', '${db}', '${unless_privilege}')",
|
||||
postgresql::grant { "database:${name}":
|
||||
role => $role,
|
||||
db => $db,
|
||||
privilege => $privilege,
|
||||
object_type => 'DATABASE',
|
||||
object_name => $db,
|
||||
psql_db => $psql_db,
|
||||
psql_user => $psql_user,
|
||||
}
|
||||
}
|
||||
|
|
77
manifests/grant.pp
Normal file
77
manifests/grant.pp
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Resource postgresql::grant
|
||||
#
|
||||
# TODO: in mysql module, the grant resource name might look like this: 'user@host/dbname';
|
||||
# I think that the API for the resource type should split these up, because it's
|
||||
# easier / safer to recombine them for mysql than it is to parse them for other
|
||||
# databases. Also, in the mysql module, the hostname portion of that string
|
||||
# affects the user's ability to connect from remote hosts. In postgres this is
|
||||
# managed via pg_hba.conf; not sure if we want to try to reconcile that difference
|
||||
# in the modules or not.
|
||||
define postgresql::grant (
|
||||
$role,
|
||||
$db,
|
||||
# TODO: mysql supports an array of privileges here. We should do that if we
|
||||
# port this to ruby.
|
||||
$privilege = undef,
|
||||
$object_type = 'database',
|
||||
$object_name = $db,
|
||||
$psql_db = $postgresql::params::user,
|
||||
$psql_user = $postgresql::params::user
|
||||
) {
|
||||
|
||||
## Munge the input values
|
||||
$_object_type = upcase($object_type)
|
||||
$_privilege = upcase($privilege)
|
||||
|
||||
## Validate that the object type is known
|
||||
validate_string($_object_type,
|
||||
#'COLUMN',
|
||||
'DATABASE',
|
||||
#'FOREIGN SERVER',
|
||||
#'FOREIGN DATA WRAPPER',
|
||||
#'FUNCTION',
|
||||
#'PROCEDURAL LANGUAGE',
|
||||
#'SCHEMA',
|
||||
#'SEQUENCE',
|
||||
'TABLE',
|
||||
#'TABLESPACE',
|
||||
#'VIEW',
|
||||
)
|
||||
|
||||
## Validate that the object type's privilege is acceptable
|
||||
case $_object_type {
|
||||
'DATABASE': {
|
||||
validate_string($_privilege,'CREATE','CONNECT','TEMPORARY','TEMP','ALL','ALL PRIVILEGES')
|
||||
$unless_function = 'has_database_privilege'
|
||||
$on_db = $psql_db
|
||||
}
|
||||
'TABLE': {
|
||||
validate_string($_privilege,'SELECT','INSERT','UPDATE','REFERENCES','ALL','ALL PRIVILEGES')
|
||||
$unless_function = 'has_table_privilege'
|
||||
$on_db = $db
|
||||
}
|
||||
default: {
|
||||
fail("Missing privilege validation for object type ${_object_type}")
|
||||
}
|
||||
}
|
||||
|
||||
# TODO: this is a terrible hack; if they pass "ALL" as the desired privilege,
|
||||
# we need a way to test for it--and has_database_privilege does not recognize
|
||||
# 'ALL' as a valid privilege name. So we probably need to hard-code a mapping
|
||||
# between 'ALL' and the list of actual privileges that it entails, and loop
|
||||
# over them to check them. That sort of thing will probably need to wait until
|
||||
# we port this over to ruby, so, for now, we're just going to assume that if
|
||||
# they have "CREATE" privileges on a database, then they have "ALL". (I told
|
||||
# you that it was terrible!)
|
||||
$unless_privilege = $_privilege ? {
|
||||
'ALL' => 'CREATE',
|
||||
default => $_privilege,
|
||||
}
|
||||
postgresql_psql { "GRANT ${_privilege} ON ${_object_type} \"${object_name}\" TO \"${role}\"":
|
||||
db => $on_db,
|
||||
psql_user => $psql_user,
|
||||
psql_group => $postgresql::params::group,
|
||||
psql_path => $postgresql::params::psql_path,
|
||||
unless => "SELECT 1 WHERE ${unless_function}('${role}', '${object_name}', '${unless_privilege}')",
|
||||
}
|
||||
}
|
20
manifests/table_grant.pp
Normal file
20
manifests/table_grant.pp
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Resource postgresql::table_grant
|
||||
define postgresql::table_grant(
|
||||
$privilege,
|
||||
$table,
|
||||
$db,
|
||||
$role,
|
||||
$psql_db = undef,
|
||||
$psql_user = undef
|
||||
) {
|
||||
include postgresql::params
|
||||
postgresql::grant { "table:${name}":
|
||||
role => $role,
|
||||
db => $db,
|
||||
privilege => $privilege,
|
||||
object_type => 'TABLE',
|
||||
object_name => $table,
|
||||
psql_db => $psql_db,
|
||||
psql_user => $psql_user,
|
||||
}
|
||||
}
|
|
@ -241,7 +241,7 @@ describe 'install:' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'postgresql::grant' do
|
||||
describe 'postgresql::database_grant' do
|
||||
it 'should grant access so a user can create in a database' do
|
||||
begin
|
||||
pp = <<-EOS
|
||||
|
@ -258,8 +258,10 @@ describe 'install:' do
|
|||
|
||||
postgresql::database_user { $user:
|
||||
password_hash => postgresql_password($user, $password),
|
||||
require => [ Class['postgresql::server'],
|
||||
User[$user] ],
|
||||
require => [
|
||||
Class['postgresql::server'],
|
||||
User[$user],
|
||||
],
|
||||
}
|
||||
|
||||
postgresql::database { $db:
|
||||
|
@ -267,11 +269,13 @@ describe 'install:' do
|
|||
}
|
||||
|
||||
postgresql::database_grant { 'grant create test':
|
||||
privilege => 'CREATE',
|
||||
db => $db,
|
||||
role => $user,
|
||||
require => [ Postgresql::Database[$db],
|
||||
Postgresql::Database_user[$user] ],
|
||||
privilege => 'CREATE',
|
||||
db => $db,
|
||||
role => $user,
|
||||
require => [
|
||||
Postgresql::Database[$db],
|
||||
Postgresql::Database_user[$user],
|
||||
],
|
||||
}
|
||||
EOS
|
||||
|
||||
|
@ -295,6 +299,73 @@ describe 'install:' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'postgresql::table_grant' do
|
||||
it 'should grant access so a user can insert in a table' do
|
||||
begin
|
||||
pp = <<-EOS
|
||||
$db = 'table_grant'
|
||||
$user = 'psql_table_tester'
|
||||
$password = 'psql_table_pw'
|
||||
|
||||
include postgresql::server
|
||||
|
||||
# Since we are not testing pg_hba or any of that, make a local user for ident auth
|
||||
user { $user:
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
postgresql::database_user { $user:
|
||||
password_hash => postgresql_password($user, $password),
|
||||
require => [
|
||||
Class['postgresql::server'],
|
||||
User[$user],
|
||||
],
|
||||
}
|
||||
|
||||
postgresql::database { $db:
|
||||
require => Class['postgresql::server'],
|
||||
}
|
||||
|
||||
postgresql_psql { 'Create testing table':
|
||||
command => 'CREATE TABLE "test_table" (field integer NOT NULL)',
|
||||
db => $db,
|
||||
unless => "SELECT * FROM pg_tables WHERE tablename = 'test_table'",
|
||||
require => Postgresql::Database[$db],
|
||||
}
|
||||
|
||||
postgresql::table_grant { 'grant insert test':
|
||||
privilege => 'INSERT',
|
||||
table => 'test_table',
|
||||
db => $db,
|
||||
role => $user,
|
||||
require => [
|
||||
Postgresql::Database[$db],
|
||||
Postgresql::Database_user[$user],
|
||||
Postgresql_psql['Create testing table'],
|
||||
],
|
||||
}
|
||||
EOS
|
||||
|
||||
puppet_apply(pp) do |r|
|
||||
r.exit_code.should_not == 1
|
||||
end
|
||||
|
||||
puppet_apply(pp) do |r|
|
||||
r.exit_code.should be_zero
|
||||
end
|
||||
|
||||
## Check that the user can create a table in the database
|
||||
#psql('--command="create table foo (foo int)" postgres', 'psql_grant_tester') do |r|
|
||||
# r.stdout.should =~ /CREATE TABLE/
|
||||
# r.stderr.should be_empty
|
||||
# r.exit_code.should == 0
|
||||
#end
|
||||
ensure
|
||||
#psql('--command="drop table foo" postgres', 'psql_grant_tester')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'postgresql::validate_db_connections' do
|
||||
it 'should run puppet with no changes declared if database connectivity works' do
|
||||
pp = <<-EOS
|
||||
|
|
Loading…
Reference in a new issue