{"id":18397906,"url":"https://github.com/jmgogo/postgresql-security","last_synced_at":"2025-04-12T15:23:54.404Z","repository":{"id":246575838,"uuid":"821513700","full_name":"jmgogo/postgresql-security","owner":"jmgogo","description":"A short recap of PostgreSQL security configuration settings with examples","archived":false,"fork":false,"pushed_at":"2024-06-28T19:17:17.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-16T02:41:21.081Z","etag":null,"topics":["dotenv","host-based-authentication","postgresql","postgresql-conf","role-based-access-control"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmgogo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-28T18:00:49.000Z","updated_at":"2024-06-28T20:55:58.000Z","dependencies_parsed_at":"2024-06-28T20:10:44.885Z","dependency_job_id":null,"html_url":"https://github.com/jmgogo/postgresql-security","commit_stats":null,"previous_names":["jgome284/postgresql-security","jmgogo/postgresql-security"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmgogo%2Fpostgresql-security","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmgogo%2Fpostgresql-security/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmgogo%2Fpostgresql-security/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmgogo%2Fpostgresql-security/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmgogo","download_url":"https://codeload.github.com/jmgogo/postgresql-security/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248587279,"owners_count":21129202,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotenv","host-based-authentication","postgresql","postgresql-conf","role-based-access-control"],"created_at":"2024-11-06T02:19:12.441Z","updated_at":"2025-04-12T15:23:54.370Z","avatar_url":"https://github.com/jmgogo.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# postgresql-security\r\n\r\n## Set Up Permissions\r\n\r\nThe first thing we need to do is manage the permissions. Permissions are made with the following naming convention\r\n\r\np_table_read / p_table_write\r\n\r\nFor example:\r\n\r\np_students_read: permission to read the students table\r\np_teachers_read: permission to read the teachers table\r\np_students_write: permission to write to the students table\r\np_teachers_write: permission to write to the teachers table\r\n\r\nTo create a role, use `CREATE ROLE role_name;`.\r\n\r\n### Read Permissions\r\n\r\nGive the read roles, permission to SELECT items in their respective tables.\r\n\r\nTo grant a permission, use `GRANT PERMISSION ON table TO role`;. For example:\r\n\r\n`GRANT SELECT ON students TO p_students_read;`\r\n\r\nand\r\n\r\n`GRANT SELECT ON teachers TO p_teachers_read;`\r\n\r\n### Write Permissions\r\n\r\nGive the roles, p_students_write and p_teachers_write, permission to SELECT, INSERT, UPDATE, and DELETE items in the students and teachers tables, respectively.\r\n\r\nTo grant multiple permissions, you can use GRANT SELECT, INSERT, UPDATE, DELETE ON table TO role;\r\n\r\n## Set Up Groups\r\n\r\nThe convention to create group roles is g_purpose. For example, you can create group roles like the following. To create a role, use `CREATE ROLE role_name;`.\r\n\r\n- g_school: group for the school employees\r\n- g_district: group for the district employees\r\n\r\nEach group role can then be assigned a set of permissions. For example:\r\n\r\n- Grant the permission roles, p_students_read and p_teachers_read, to the group g_school.\r\n- Grant the permission roles, p_students_write and p_teachers_write, to the group g_district.\r\n\r\nTo do so use `GRANT role TO other_role;`.\r\n\r\n## Create User Accounts\r\n\r\nTo create roles with login, use `CREATE ROLE user_name WITH LOGIN;.`\r\n\r\nCreate three user account roles that can log in: u_principal_skinner, u_teacher_hodge, and u_it_sonia.\r\n\r\nAdd the user role u_principal_skinner to the group g_district and the user roles, u_teacher_hodge and u_it_sonia, to the group g_school.\r\n\r\n## Default Deny\r\n\r\nIn PostgreSQL you can add default-deny permissions. Use `REVOKE PERMISSION ON table FROM PUBLIC`; to revoke a permission.\r\n\r\nRemove all public permissions for the tables, students and teachers. For this task, you will need to run two commands:\r\n\r\n`REVOKE ALL ON students FROM PUBLIC;`\r\n\r\nand\r\n\r\n`REVOKE ALL ON teachers FROM PUBLIC;`\r\n\r\n## Configure Postgres Settings\r\n\r\n### Listen Addresses\r\n\r\nNext, we need to make sure the Postgres server does not accept connections from every IP address. Edit postgresql.conf to change the listen_addresses parameter so that the server only accepts connections from the school network ( localhost) and the district network (235.84.86.65).\r\n\r\nSet the listen_addresses parameter in postgresql.conf to 'localhost, 235.84.86.65'.\r\n\r\nlisten_addresses = 'localhost, 235.84.86.65'\r\n\r\n### Port\r\n\r\nThe server currently listens on port 5432, which is very dangerous because it’s the default Postgres port. Change the port parameter to 61342,\r\n\r\nHint: Set the port parameter in postgresql.conf to 61342.\r\n\r\nport = 61342\r\n\r\n### Enable SSL\r\n\r\nEnable SSL on the server.\r\n\r\nHint: Set the ssl parameter in postgresql.conf to on.\r\n\r\nssl = on\r\n\r\n## Configure Postgres Host-Based Authentication\r\n\r\nNow that the server settings are configured, move to pg_hba.conf. This `pg_hba.conf` file is a configuration file for PostgreSQL's host-based authentication. It contains a set of rules that determine how clients are allowed to connect to the PostgreSQL database server.\r\n\r\nAdd a rule to allow members of the g_school group on the school’s local network to access the students database. SSL is not necessary. We should use SHA-256 password authentication.\r\n\r\nRemember, the order is\r\n\r\n`connection_type  db  user  address  auth_method  [auth_options]`\r\n\r\nThis gives us:\r\n\r\n`host students +g_school samenet scram-sha-256`\r\n\r\nAdd another rule using the same configuration as the last rule but change the database to teachers.\r\n\r\n`host teachers +g_school samenet scram-sha-256`\r\n\r\nAdd a rule for the principal’s account, u_principal_skinner, to access all databases from any address. Use SSL and SHA-256 password authentication.\r\n\r\n`hostssl all u_principal_skinner all scram-sha-256`\r\n\r\nAdd a rule for the members of the school district in the group, g_district, to access all databases from the district’s network, 235.84.86.65. Use SSL and SHA-256 password authentication.\r\n\r\nFinally, add a default-deny rule to deny all other connections.\r\n\r\nhost all all all reject\r\n\r\nOverall, this configuration file allows users in the `g_school` group to connect as either `students` or `teachers` from hosts in the `samenet` network, while requiring SSL for connections as the `u_principal_skinner` role. All other connection attempts are rejected.\r\n\r\n## Implement Environment Variables\r\n\r\nYou can create an environment variable using the format: NAME=VALUE in .env.\r\n\r\nFor example, your .env file could look like so...\r\n\r\n```dotenv\r\n# NOTE - FAKE DATA FOR DEMONSTRATION ONLY...\r\n\r\n# Postgres API Key (students)\r\nPOSTGRES_API_KEY=gVvzJqrWLL6MXLzHeHERnKp\r\n\r\n# District API Key (teachers)\r\nDISTRICT_API_KEY=zsi9DeEcewB7MsgzPy2zxsp\r\n```\r\n\r\nThese variables can be used in your scripts with the dotenv package. For example in a JavaScript file:\r\n\r\n```JavaScript\r\n// Import the dotenv package\r\nimport dotenv from \"dotenv\"\r\n\r\n// Inject environment variables\r\ndotenv.config()\r\n\r\n// print API keys that are injected as environment variables.\r\nconsole.log(process.env.POSTGRES_API_KEY);\r\nconsole.log(process.env.DISTRICT_API_KEY);\r\n\r\n```\r\n\r\n## Prevent Uploading Sensitive Information\r\n\r\nLastly, we need to make sure the Postgres configuration files and the environment variables are not uploaded to the public repository. Using .gitignore, ignore the following files: .env, pg_hba.conf, and postgresql.conf.\r\n\r\n.gitignore should contain:\r\n\r\n```.gitignore\r\n.env\r\npg_hba.conf\r\npostgresql.conf\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmgogo%2Fpostgresql-security","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmgogo%2Fpostgresql-security","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmgogo%2Fpostgresql-security/lists"}