policy_module(postgresql, 1.16.0)

gen_require(`
	class db_database all_db_database_perms;
	class db_table all_db_table_perms;
	class db_procedure all_db_procedure_perms;
	class db_column all_db_column_perms;
	class db_tuple all_db_tuple_perms;
	class db_blob all_db_blob_perms;
	class db_schema all_db_schema_perms;
	class db_view all_db_view_perms;
	class db_sequence all_db_sequence_perms;
	class db_language all_db_language_perms;
')

#################################
#
# Declarations
#

## <desc>
##	<p>
##	Allow postgresql to use ssh and rsync for point-in-time recovery
##	</p>
## </desc>
gen_tunable(postgresql_can_rsync, false)

## <desc>
##	<p>
##	Allow unprivileged users to execute DDL statement
##	</p>
## </desc>
gen_tunable(postgresql_selinux_users_ddl, true)

## <desc>
## <p>
## Allow transmit client label to foreign database
## </p>
## </desc>
gen_tunable(postgresql_selinux_transmit_client_label, false)

## <desc>
## <p>
## Allow database admins to execute DML statement
## </p>
## </desc>
gen_tunable(postgresql_selinux_unconfined_dbadm, true)

type postgresql_t;
type postgresql_exec_t;
init_daemon_domain(postgresql_t, postgresql_exec_t)

type postgresql_db_t;
files_type(postgresql_db_t)

type postgresql_etc_t;
files_config_file(postgresql_etc_t)

type postgresql_initrc_exec_t;
init_script_file(postgresql_initrc_exec_t)

type postgresql_unit_file_t;
systemd_unit_file(postgresql_unit_file_t)

type postgresql_lock_t;
files_lock_file(postgresql_lock_t)

type postgresql_log_t;
logging_log_file(postgresql_log_t)

type postgresql_tmp_t;
files_tmp_file(postgresql_tmp_t)

type postgresql_var_run_t;
files_pid_file(postgresql_var_run_t)
init_daemon_run_dir(postgresql_var_run_t, "postgresql")

# database clients attribute
attribute sepgsql_admin_type;
attribute sepgsql_client_type;
attribute sepgsql_unconfined_type;

# database objects attribute
attribute sepgsql_database_type;
attribute sepgsql_schema_type;
attribute sepgsql_table_type;
attribute sepgsql_sysobj_table_type;
attribute sepgsql_sequence_type;
attribute sepgsql_view_type;
attribute sepgsql_procedure_type;
attribute sepgsql_trusted_procedure_type;
attribute sepgsql_language_type;
attribute sepgsql_blob_type;
attribute sepgsql_module_type;

# database object types
type sepgsql_blob_t;
postgresql_blob_object(sepgsql_blob_t)

type sepgsql_db_t;
postgresql_database_object(sepgsql_db_t)

type sepgsql_fixed_table_t;
postgresql_table_object(sepgsql_fixed_table_t)

type sepgsql_lang_t;
postgresql_language_object(sepgsql_lang_t)

type sepgsql_priv_lang_t;
postgresql_language_object(sepgsql_priv_lang_t)

type sepgsql_proc_exec_t;
typealias sepgsql_proc_exec_t alias sepgsql_proc_t;
postgresql_procedure_object(sepgsql_proc_exec_t)

type sepgsql_ro_blob_t;
postgresql_blob_object(sepgsql_ro_blob_t)

type sepgsql_ro_table_t;
postgresql_table_object(sepgsql_ro_table_t)

type sepgsql_safe_lang_t;
postgresql_language_object(sepgsql_safe_lang_t)

type sepgsql_schema_t;
postgresql_schema_object(sepgsql_schema_t)

type sepgsql_secret_blob_t;
postgresql_blob_object(sepgsql_secret_blob_t)

type sepgsql_secret_table_t;
postgresql_table_object(sepgsql_secret_table_t)

type sepgsql_seq_t;
postgresql_sequence_object(sepgsql_seq_t)

type sepgsql_sysobj_t;
postgresql_system_table_object(sepgsql_sysobj_t)

type sepgsql_table_t;
postgresql_table_object(sepgsql_table_t)

type sepgsql_trusted_proc_exec_t;
postgresql_trusted_procedure_object(sepgsql_trusted_proc_exec_t)

# Ranged Trusted Procedure Domain
type sepgsql_ranged_proc_t;
domain_type(sepgsql_ranged_proc_t)
role system_r types sepgsql_ranged_proc_t;

type sepgsql_ranged_proc_exec_t;
postgresql_trusted_procedure_object(sepgsql_ranged_proc_exec_t)

# Types for temporary objects
#
# XXX - All the temporary objects are eliminated at end of database session
# and invisible from other sessions, so it is unnecessary to restrict users
# operations on temporary object. For policy simplification, only one type
# is defined for temporary objects under the "pg_temp" schema.
type sepgsql_temp_object_t;
postgresql_table_object(sepgsql_temp_object_t)
postgresql_sequence_object(sepgsql_temp_object_t)
postgresql_view_object(sepgsql_temp_object_t)
postgresql_procedure_object(sepgsql_temp_object_t)

# Trusted Procedure Domain
type sepgsql_trusted_proc_t;
domain_type(sepgsql_trusted_proc_t)
postgresql_unconfined(sepgsql_trusted_proc_t)
role system_r types sepgsql_trusted_proc_t;

type sepgsql_view_t;
postgresql_view_object(sepgsql_view_t)

# Types for unprivileged client
type unpriv_sepgsql_blob_t;
postgresql_blob_object(unpriv_sepgsql_blob_t)

type unpriv_sepgsql_proc_exec_t;
postgresql_procedure_object(unpriv_sepgsql_proc_exec_t)

type unpriv_sepgsql_schema_t;
postgresql_schema_object(unpriv_sepgsql_schema_t)

type unpriv_sepgsql_seq_t;
postgresql_sequence_object(unpriv_sepgsql_seq_t)

type unpriv_sepgsql_sysobj_t;
postgresql_system_table_object(unpriv_sepgsql_sysobj_t)

type unpriv_sepgsql_table_t;
postgresql_table_object(unpriv_sepgsql_table_t)

type unpriv_sepgsql_view_t;
postgresql_view_object(unpriv_sepgsql_view_t)

# Types for UBAC
type user_sepgsql_blob_t;
typealias user_sepgsql_blob_t alias { staff_sepgsql_blob_t sysadm_sepgsql_blob_t };
typealias user_sepgsql_blob_t alias { auditadm_sepgsql_blob_t secadm_sepgsql_blob_t };
postgresql_blob_object(user_sepgsql_blob_t)

type user_sepgsql_proc_exec_t;
typealias user_sepgsql_proc_exec_t alias { staff_sepgsql_proc_exec_t sysadm_sepgsql_proc_exec_t };
typealias user_sepgsql_proc_exec_t alias { auditadm_sepgsql_proc_exec_t secadm_sepgsql_proc_exec_t };
postgresql_procedure_object(user_sepgsql_proc_exec_t)

type user_sepgsql_schema_t;
typealias user_sepgsql_schema_t alias { staff_sepgsql_schema_t sysadm_sepgsql_schema_t };
typealias user_sepgsql_schema_t alias { auditadm_sepgsql_schema_t secadm_sepgsql_schema_t };
postgresql_schema_object(user_sepgsql_schema_t)

type user_sepgsql_seq_t;
typealias user_sepgsql_seq_t alias { staff_sepgsql_seq_t sysadm_sepgsql_seq_t };
typealias user_sepgsql_seq_t alias { auditadm_sepgsql_seq_t secadm_sepgsql_seq_t };
postgresql_sequence_object(user_sepgsql_seq_t)

type user_sepgsql_sysobj_t;
typealias user_sepgsql_sysobj_t alias { staff_sepgsql_sysobj_t sysadm_sepgsql_sysobj_t };
typealias user_sepgsql_sysobj_t alias { auditadm_sepgsql_sysobj_t secadm_sepgsql_sysobj_t };
postgresql_system_table_object(user_sepgsql_sysobj_t)

type user_sepgsql_table_t;
typealias user_sepgsql_table_t alias { staff_sepgsql_table_t sysadm_sepgsql_table_t };
typealias user_sepgsql_table_t alias { auditadm_sepgsql_table_t secadm_sepgsql_table_t };
postgresql_table_object(user_sepgsql_table_t)

type user_sepgsql_view_t;
typealias user_sepgsql_view_t alias { staff_sepgsql_view_t sysadm_sepgsql_view_t };
typealias user_sepgsql_view_t alias { auditadm_sepgsql_view_t secadm_sepgsql_view_t };
postgresql_view_object(user_sepgsql_view_t)

########################################
#
# postgresql Local policy
#
allow postgresql_t self:capability { kill  dac_read_search chown fowner fsetid setuid setgid sys_nice sys_tty_config sys_admin };
dontaudit postgresql_t self:capability { sys_tty_config sys_admin };
allow postgresql_t self:process signal_perms;
allow postgresql_t self:fifo_file rw_fifo_file_perms;
allow postgresql_t self:file { getattr read };
allow postgresql_t self:sem create_sem_perms;
allow postgresql_t self:shm create_shm_perms;
allow postgresql_t self:tcp_socket create_stream_socket_perms;
allow postgresql_t self:udp_socket create_stream_socket_perms;
allow postgresql_t self:unix_dgram_socket create_socket_perms;
allow postgresql_t self:unix_stream_socket { create_stream_socket_perms connectto };
allow postgresql_t self:netlink_selinux_socket create_socket_perms;

tunable_policy(`postgresql_selinux_transmit_client_label',`
	allow postgresql_t self:process { setsockcreate };
')

allow postgresql_t sepgsql_database_type:db_database *;

allow postgresql_t sepgsql_module_type:db_database install_module;
# Database/Loadable module
allow sepgsql_database_type sepgsql_module_type:db_database load_module;

allow postgresql_t {sepgsql_schema_type sepgsql_temp_object_t}:db_schema *;
type_transition postgresql_t sepgsql_database_type:db_schema sepgsql_schema_t;
type_transition postgresql_t sepgsql_database_type:db_schema sepgsql_temp_object_t "pg_temp";

allow postgresql_t sepgsql_table_type:{ db_table db_column db_tuple } *;
type_transition postgresql_t sepgsql_schema_type:db_table sepgsql_sysobj_t;

allow postgresql_t sepgsql_sequence_type:db_sequence *;
type_transition postgresql_t sepgsql_schema_type:db_sequence sepgsql_seq_t;

allow postgresql_t sepgsql_view_type:db_view *;
type_transition postgresql_t sepgsql_schema_type:db_view sepgsql_view_t;

allow postgresql_t sepgsql_procedure_type:db_procedure *;
type_transition postgresql_t sepgsql_schema_type:db_procedure sepgsql_proc_exec_t;

allow postgresql_t sepgsql_blob_type:db_blob *;
type_transition postgresql_t sepgsql_database_type:db_blob sepgsql_blob_t;

manage_dirs_pattern(postgresql_t, postgresql_db_t, postgresql_db_t)
manage_files_pattern(postgresql_t, postgresql_db_t, postgresql_db_t)
manage_lnk_files_pattern(postgresql_t, postgresql_db_t, postgresql_db_t)
manage_fifo_files_pattern(postgresql_t, postgresql_db_t, postgresql_db_t)
manage_sock_files_pattern(postgresql_t, postgresql_db_t, postgresql_db_t)
postgresql_filetrans_named_content(postgresql_t)

allow postgresql_t postgresql_etc_t:dir list_dir_perms;
read_files_pattern(postgresql_t, postgresql_etc_t, postgresql_etc_t)
read_lnk_files_pattern(postgresql_t, postgresql_etc_t, postgresql_etc_t)

allow postgresql_t postgresql_exec_t:lnk_file read_lnk_file_perms;
can_exec(postgresql_t, postgresql_exec_t )

allow postgresql_t postgresql_lock_t:file manage_file_perms;
files_lock_filetrans(postgresql_t, postgresql_lock_t, file)

manage_dirs_pattern(postgresql_t, postgresql_log_t, postgresql_log_t)
manage_files_pattern(postgresql_t, postgresql_log_t, postgresql_log_t)
logging_log_filetrans(postgresql_t, postgresql_log_t, { file dir })

manage_dirs_pattern(postgresql_t, postgresql_tmp_t, postgresql_tmp_t)
manage_files_pattern(postgresql_t, postgresql_tmp_t, postgresql_tmp_t)
manage_lnk_files_pattern(postgresql_t, postgresql_tmp_t, postgresql_tmp_t)
manage_fifo_files_pattern(postgresql_t, postgresql_tmp_t, postgresql_tmp_t)
manage_sock_files_pattern(postgresql_t, postgresql_tmp_t, postgresql_tmp_t)
files_tmp_filetrans(postgresql_t, postgresql_tmp_t, { dir file sock_file })
allow postgresql_t postgresql_tmp_t:file map;
fs_tmpfs_filetrans(postgresql_t, postgresql_tmp_t, { dir file lnk_file sock_file fifo_file })

manage_dirs_pattern(postgresql_t, postgresql_var_run_t, postgresql_var_run_t)
manage_files_pattern(postgresql_t, postgresql_var_run_t, postgresql_var_run_t)
manage_sock_files_pattern(postgresql_t, postgresql_var_run_t, postgresql_var_run_t)
files_pid_filetrans(postgresql_t, postgresql_var_run_t, { dir file })

kernel_read_kernel_sysctls(postgresql_t)
kernel_read_network_state(postgresql_t)
kernel_read_system_state(postgresql_t)
kernel_list_proc(postgresql_t)
kernel_read_all_sysctls(postgresql_t)
kernel_read_proc_symlinks(postgresql_t)

corenet_all_recvfrom_netlabel(postgresql_t)
corenet_tcp_sendrecv_generic_if(postgresql_t)
corenet_udp_sendrecv_generic_if(postgresql_t)
corenet_tcp_sendrecv_generic_node(postgresql_t)
corenet_udp_sendrecv_generic_node(postgresql_t)
corenet_tcp_sendrecv_all_ports(postgresql_t)
corenet_udp_sendrecv_all_ports(postgresql_t)
corenet_udp_bind_generic_node(postgresql_t)
corenet_tcp_bind_generic_node(postgresql_t)
corenet_tcp_bind_postgresql_port(postgresql_t)
corenet_tcp_connect_auth_port(postgresql_t)
corenet_tcp_connect_postgresql_port(postgresql_t)
corenet_sendrecv_postgresql_server_packets(postgresql_t)
corenet_sendrecv_auth_client_packets(postgresql_t)

dev_read_sysfs(postgresql_t)
dev_read_urand(postgresql_t)

fs_getattr_all_fs(postgresql_t)
fs_search_auto_mountpoints(postgresql_t)
fs_rw_hugetlbfs_files(postgresql_t)

selinux_get_enforce_mode(postgresql_t)
selinux_validate_context(postgresql_t)
selinux_compute_access_vector(postgresql_t)
selinux_compute_create_context(postgresql_t)
selinux_compute_relabel_context(postgresql_t)

term_use_controlling_term(postgresql_t)

corecmd_exec_bin(postgresql_t)
corecmd_exec_shell(postgresql_t)

domain_dontaudit_list_all_domains_state(postgresql_t)
domain_use_interactive_fds(postgresql_t)

files_dontaudit_search_home(postgresql_t)
files_read_etc_files(postgresql_t)
files_read_etc_runtime_files(postgresql_t)
files_read_usr_files(postgresql_t)

auth_use_pam(postgresql_t)

init_read_utmp(postgresql_t)

logging_send_syslog_msg(postgresql_t)
logging_send_audit_msgs(postgresql_t)

seutil_libselinux_linked(postgresql_t)
seutil_read_default_contexts(postgresql_t)

sysnet_use_ldap(postgresql_t)

userdom_dontaudit_use_unpriv_user_fds(postgresql_t)
userdom_dontaudit_search_user_home_dirs(postgresql_t)
userdom_dontaudit_use_user_terminals(postgresql_t)

optional_policy(`
	ccs_read_config(postgresql_t)
')

optional_policy(`
	mta_getattr_spool(postgresql_t)
')

optional_policy(`
	rhcs_manage_cluster_pid_files(postgresql_t)
')

tunable_policy(`deny_execmem',`',`
	allow postgresql_t self:process execmem;
')

optional_policy(`
	consoletype_exec(postgresql_t)
')

optional_policy(`
	cron_search_spool(postgresql_t)
	cron_system_entry(postgresql_t, postgresql_exec_t)
')

optional_policy(`
	hostname_exec(postgresql_t)
')

optional_policy(`
	ipsec_match_default_spd(postgresql_t)
')

optional_policy(`
	kerberos_use(postgresql_t)
')

optional_policy(`
	seutil_sigchld_newrole(postgresql_t)
')

optional_policy(`
	udev_read_db(postgresql_t)
')

########################################
#
# Ranged Trusted Procedure Domain
#
# XXX - the purpose of this domain is to switch security context of
# the database client using dynamic domain transition; typically,
# used for connection pooling software that shall assign a security
# context at beginning of the user session based on the credentials
# being invisible from unprivileged domains.
#
allow sepgsql_ranged_proc_t self:process setcurrent;

domain_dyntrans_type(sepgsql_ranged_proc_t)

mcs_process_set_categories(sepgsql_ranged_proc_t)

mls_process_set_level(sepgsql_ranged_proc_t)

postgresql_unconfined(sepgsql_ranged_proc_t)

########################################
#
# Rules common to all clients
#

allow sepgsql_client_type sepgsql_db_t:db_database { getattr access get_param set_param };
type_transition sepgsql_client_type sepgsql_client_type:db_database sepgsql_db_t;

allow sepgsql_client_type sepgsql_schema_t:db_schema { getattr search };

allow sepgsql_client_type sepgsql_fixed_table_t:db_table { getattr select insert lock };
allow sepgsql_client_type sepgsql_fixed_table_t:db_column { getattr select insert };
allow sepgsql_client_type sepgsql_fixed_table_t:db_tuple { select insert };

allow sepgsql_client_type sepgsql_table_t:db_table { getattr select update insert delete lock };
allow sepgsql_client_type sepgsql_table_t:db_column { getattr select update insert };
allow sepgsql_client_type sepgsql_table_t:db_tuple { select update insert delete };

allow sepgsql_client_type sepgsql_ro_table_t:db_table { getattr select lock };
allow sepgsql_client_type sepgsql_ro_table_t:db_column { getattr select };
allow sepgsql_client_type sepgsql_ro_table_t:db_tuple { select };

allow sepgsql_client_type sepgsql_secret_table_t:db_table getattr;
allow sepgsql_client_type sepgsql_secret_table_t:db_column getattr;

allow sepgsql_client_type sepgsql_sysobj_t:db_table { getattr select lock };
allow sepgsql_client_type sepgsql_sysobj_t:db_column { getattr select };
allow sepgsql_client_type sepgsql_sysobj_t:db_tuple { use select };

allow sepgsql_client_type sepgsql_seq_t:db_sequence { getattr get_value next_value };

allow sepgsql_client_type sepgsql_view_t:db_view { getattr expand };

allow sepgsql_client_type sepgsql_proc_exec_t:db_procedure { getattr execute install };
allow sepgsql_client_type sepgsql_trusted_procedure_type:db_procedure { getattr execute entrypoint };

allow sepgsql_client_type sepgsql_lang_t:db_language { getattr };
allow sepgsql_client_type sepgsql_safe_lang_t:db_language { getattr execute };

# Only DBA can implement SQL procedures using `unsafe' procedural languages.
# The `unsafe' one provides a capability to access internal data structure,
# so we don't allow user-defined function being implemented using `unsafe' one.
allow sepgsql_proc_exec_t sepgsql_lang_t:db_language { implement };
allow sepgsql_procedure_type sepgsql_safe_lang_t:db_language { implement };

allow sepgsql_client_type sepgsql_blob_t:db_blob { create drop getattr setattr read write };
allow sepgsql_client_type sepgsql_ro_blob_t:db_blob { getattr read };
allow sepgsql_client_type sepgsql_secret_blob_t:db_blob getattr;

# The purpose of the dontaudit rule in row-level access control is to prevent a flood of logs.
# If a client tries to SELECT a table including violated tuples, these are filtered from
# the result set as if not exist, but its access denied longs can be recorded within log files.
# In generally, the number of tuples are much larger than the number of columns, tables and so on.
# So, it makes a flood of logs when many tuples are violated.
#
# The default policy does not prevent anything for sepgsql_client_type sepgsql_unconfined_type,
# so we don't need "dontaudit" rules in Type-Enforcement. However, MLS/MCS can prevent them
# to access classified tuples and can make a audit record.
#
# Therefore, the following rule is applied for any domains which can connect SE-PostgreSQL.
dontaudit { postgresql_t sepgsql_admin_type sepgsql_client_type sepgsql_unconfined_type } { sepgsql_table_type -sepgsql_sysobj_table_type }:db_tuple { use select update insert delete };

# It is always allowed to operate temporary objects for any database client.
allow sepgsql_client_type sepgsql_temp_object_t:{db_schema db_table db_column db_tuple db_sequence db_view db_procedure} ~{ relabelto relabelfrom };

##############################
#
# Client local policy
#
allow sepgsql_client_type user_sepgsql_schema_t:db_schema { getattr search add_name remove_name };
type_transition sepgsql_client_type sepgsql_database_type:db_schema user_sepgsql_schema_t;
type_transition sepgsql_client_type sepgsql_database_type:db_schema sepgsql_temp_object_t "pg_temp";

allow sepgsql_client_type user_sepgsql_table_t:db_table	{ getattr select update insert delete lock };
allow sepgsql_client_type user_sepgsql_table_t:db_column { getattr select update insert };
allow sepgsql_client_type user_sepgsql_table_t:db_tuple	{ select update insert delete };
type_transition sepgsql_client_type sepgsql_schema_type:db_table user_sepgsql_table_t;

allow sepgsql_client_type user_sepgsql_sysobj_t:db_tuple	{ use select };
type_transition sepgsql_client_type sepgsql_sysobj_table_type:db_tuple user_sepgsql_sysobj_t;

allow sepgsql_client_type user_sepgsql_seq_t:db_sequence { getattr get_value next_value };
type_transition sepgsql_client_type sepgsql_schema_type:db_sequence user_sepgsql_seq_t;

allow sepgsql_client_type user_sepgsql_view_t:db_view { getattr expand };
type_transition sepgsql_client_type sepgsql_schema_type:db_view user_sepgsql_view_t;

allow sepgsql_client_type user_sepgsql_proc_exec_t:db_procedure { getattr execute };
type_transition sepgsql_client_type sepgsql_schema_type:db_procedure user_sepgsql_proc_exec_t;

allow sepgsql_client_type user_sepgsql_blob_t:db_blob { create drop getattr setattr read write import export };
type_transition sepgsql_client_type sepgsql_database_type:db_blob user_sepgsql_blob_t;

allow sepgsql_client_type sepgsql_ranged_proc_t:process transition;
type_transition sepgsql_client_type sepgsql_ranged_proc_exec_t:process sepgsql_ranged_proc_t;
allow sepgsql_ranged_proc_t sepgsql_client_type:process dyntransition;

allow sepgsql_client_type sepgsql_trusted_proc_t:process transition;
type_transition sepgsql_client_type sepgsql_trusted_proc_exec_t:process sepgsql_trusted_proc_t;

tunable_policy(`postgresql_selinux_users_ddl',`
	allow sepgsql_client_type user_sepgsql_schema_t:db_schema { create drop setattr };
	allow sepgsql_client_type user_sepgsql_table_t:db_table { create drop setattr };
	allow sepgsql_client_type user_sepgsql_table_t:db_column { create drop setattr };
	allow sepgsql_client_type user_sepgsql_sysobj_t:db_tuple { update insert delete };
	allow sepgsql_client_type user_sepgsql_seq_t:db_sequence { create drop setattr set_value };
	allow sepgsql_client_type user_sepgsql_view_t:db_view { create drop setattr };
	allow sepgsql_client_type user_sepgsql_proc_exec_t:db_procedure { create drop setattr };
	# Note that permission of creation/deletion are eventually controlled by
	# create or drop permission of individual objects within shared schemas.
	# So, it just allows to create/drop user specific types.
	allow sepgsql_client_type sepgsql_schema_t:db_schema { add_name remove_name };
')

########################################
#
# Rules common to administrator clients
#

allow sepgsql_admin_type sepgsql_database_type:db_database { create drop getattr setattr relabelfrom relabelto access };

allow sepgsql_admin_type sepgsql_schema_type:db_schema { create drop getattr setattr relabelfrom relabelto search add_name remove_name };
type_transition sepgsql_admin_type sepgsql_database_type:db_schema sepgsql_schema_t;
type_transition sepgsql_admin_type sepgsql_database_type:db_schema sepgsql_temp_object_t "pg_temp";

allow sepgsql_admin_type sepgsql_table_type:db_table { create drop getattr setattr relabelfrom relabelto lock };
allow sepgsql_admin_type sepgsql_table_type:db_column { create drop getattr setattr relabelfrom relabelto };
allow sepgsql_admin_type sepgsql_sysobj_table_type:db_tuple { relabelfrom relabelto use select update insert delete };

type_transition sepgsql_admin_type sepgsql_schema_type:db_table sepgsql_table_t;

allow sepgsql_admin_type sepgsql_sequence_type:db_sequence { create drop getattr setattr relabelfrom relabelto get_value next_value set_value };

type_transition sepgsql_admin_type sepgsql_schema_type:db_sequence sepgsql_seq_t;

allow sepgsql_admin_type sepgsql_view_type:db_view { create drop getattr setattr relabelfrom relabelto expand };

type_transition sepgsql_admin_type sepgsql_schema_type:db_view sepgsql_view_t;

allow sepgsql_admin_type sepgsql_procedure_type:db_procedure { create drop getattr relabelfrom relabelto };
allow sepgsql_admin_type sepgsql_proc_exec_t:db_procedure execute;

type_transition sepgsql_admin_type sepgsql_schema_type:db_procedure sepgsql_proc_exec_t;

allow sepgsql_admin_type sepgsql_temp_object_t:{db_schema db_table db_column db_tuple db_sequence db_view db_procedure} ~{ relabelto relabelfrom };

allow sepgsql_admin_type sepgsql_language_type:db_language { create drop getattr setattr relabelfrom relabelto execute };

type_transition sepgsql_admin_type sepgsql_database_type:db_language sepgsql_lang_t;

allow sepgsql_admin_type sepgsql_blob_type:db_blob { create drop getattr setattr relabelfrom relabelto };

type_transition sepgsql_admin_type sepgsql_database_type:db_blob sepgsql_blob_t;

allow sepgsql_admin_type sepgsql_module_type:db_database install_module;

kernel_relabelfrom_unlabeled_database(sepgsql_admin_type)

tunable_policy(`postgresql_selinux_unconfined_dbadm',`
	allow sepgsql_admin_type sepgsql_database_type:db_database *;

	allow sepgsql_admin_type sepgsql_schema_type:db_schema *;

	allow sepgsql_admin_type sepgsql_table_type:{ db_table db_column db_tuple } *;
	allow sepgsql_admin_type sepgsql_sequence_type:db_sequence *;
	allow sepgsql_admin_type sepgsql_view_type:db_view *;

	allow sepgsql_admin_type sepgsql_proc_exec_t:db_procedure *;
	allow sepgsql_admin_type sepgsql_trusted_procedure_type:db_procedure ~install;
	allow sepgsql_admin_type sepgsql_procedure_type:db_procedure ~{ execute install };

	allow sepgsql_admin_type sepgsql_language_type:db_language ~implement;

	allow sepgsql_admin_type sepgsql_blob_type:db_blob *;
')

########################################
#
# Unconfined access to this module
#

allow sepgsql_unconfined_type sepgsql_database_type:db_database *;

allow sepgsql_unconfined_type {sepgsql_schema_type sepgsql_temp_object_t}:db_schema *;
type_transition sepgsql_unconfined_type sepgsql_database_type:db_schema sepgsql_schema_t;
type_transition sepgsql_unconfined_type sepgsql_database_type:db_schema sepgsql_temp_object_t "pg_temp";

type_transition sepgsql_unconfined_type sepgsql_schema_type:db_table sepgsql_table_t;
type_transition sepgsql_unconfined_type sepgsql_schema_type:db_sequence sepgsql_seq_t;
type_transition sepgsql_unconfined_type sepgsql_schema_type:db_view sepgsql_view_t;
type_transition sepgsql_unconfined_type sepgsql_schema_type:db_procedure sepgsql_proc_exec_t;
type_transition sepgsql_unconfined_type sepgsql_database_type:db_language sepgsql_lang_t;
type_transition sepgsql_unconfined_type sepgsql_database_type:db_blob sepgsql_blob_t;

allow sepgsql_unconfined_type sepgsql_table_type:{ db_table db_column db_tuple } *;
allow sepgsql_unconfined_type sepgsql_sequence_type:db_sequence *;
allow sepgsql_unconfined_type sepgsql_view_type:db_view *;

# unconfined domain is not allowed to invoke user defined procedure directly.
# They have to confirm and relabel it at first.
allow sepgsql_unconfined_type sepgsql_proc_exec_t:db_procedure *;
allow sepgsql_unconfined_type sepgsql_trusted_procedure_type:db_procedure ~install;
allow sepgsql_unconfined_type sepgsql_procedure_type:db_procedure ~{ execute install };

allow sepgsql_unconfined_type sepgsql_language_type:db_language ~implement;

allow sepgsql_unconfined_type sepgsql_blob_type:db_blob *;

allow sepgsql_unconfined_type sepgsql_module_type:db_database install_module;

kernel_relabelfrom_unlabeled_database(sepgsql_unconfined_type)

optional_policy(`
	tunable_policy(`postgresql_can_rsync',`
		rsync_exec(postgresql_t)
	')
')

optional_policy(`
	tunable_policy(`postgresql_can_rsync',`
		ssh_exec(postgresql_t)
		ssh_read_user_home_files(postgresql_t)
		corenet_tcp_connect_ssh_port(postgresql_t)
	')
')
