Module: Pgpass
- Defined in:
- lib/pgpass.rb,
lib/pgpass/version.rb
Overview
The file .pgpass in a user’s home directory or the file referenced by PGPASSFILE can contain passwords to be used if the connection requires a password (and no password has been specified otherwise). On Microsoft Windows the file is named %APPDATA%postgresqlpgpass.conf (where %APPDATA% refers to the Application Data subdirectory in the user’s profile).
This file should contain lines of the following format:
hostname:port:database:username:password
(You can add a reminder comment to the file by copying the line above and preceding it with ‘#`.) Each of the first four fields can be a literal value, or `*`, which matches anything.
The password field from the first line that matches the current connection parameters will be used.
(Therefore, put more-specific entries first when you are using wildcards.) If an entry needs to contain : or , escape this character with .
A host name of localhost matches both TCP (host name localhost) and Unix domain socket (pghost empty or the default socket directory) connections coming from the local machine.
In a standby server, a database name of replication matches streaming replication connections made to the master server.
The database field is of limited usefulness because users have the same password for all databases in the same cluster.
On Unix systems, the permissions on .pgpass must disallow any access to world or group; achieve this by the command chmod 0600 ~/.pgpass. If the permissions are less strict than this, the file will be ignored.
On Microsoft Windows, it is assumed that the file is stored in a directory that is secure, so no special permissions check is made.
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- LOCATIONS =
[ENV['PGPASSFILE'], './.pgpass', '~/.pgpass']
- VERSION =
"2022.07.27"
Class Method Summary collapse
- .guess(paths = PATH) ⇒ Object
- .load(io) ⇒ Object
- .load_file(path) ⇒ Object
- .match(given_options = {}) ⇒ Object
- .parse_line(line) ⇒ Object
Class Method Details
.guess(paths = PATH) ⇒ Object
136 137 138 139 140 141 142 143 144 |
# File 'lib/pgpass.rb', line 136 def guess(paths = PATH) paths.each do |path| begin load_file(File.join(path, '.pgpass')) rescue Errno::ENOENT => e warn(e) end end end |
.load(io) ⇒ Object
150 151 152 |
# File 'lib/pgpass.rb', line 150 def load(io) io.each_line.map { |line| parse_line(line) } end |
.load_file(path) ⇒ Object
146 147 148 |
# File 'lib/pgpass.rb', line 146 def load_file(path) File.open(File.(path), 'r') { |io| load(io) } end |
.match(given_options = {}) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/pgpass.rb', line 108 def match( = {}) search = Entry.create( user: (ENV['PGUSER'] || '*'), password: ENV['PGPASSWORD'], host: (ENV['PGHOST'] || '*'), port: (ENV['PGPORT'] || '*'), database: (ENV['PGDATABASE'] || '*') ).merge() LOCATIONS.compact.each do |path| path = File.(path) # consider only files next unless File.file?(path) # that aren't world/group accessible unless (File.stat(path).mode & 0o077).zero? warn %(WARNING: password file "#{path}" has group or world access; permissions should be u=rw (0600) or less) next end load_file(path).each do |entry| return entry.complement(search) if entry == search end end nil end |
.parse_line(line) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/pgpass.rb', line 154 def parse_line(line) sc = StringScanner.new(line) entry = Entry.new key_index = 0 value = [] loop do pos = sc.pos return if sc.bol? && (sc.scan(/\s*#/) || sc.scan(/\s*$/)) if sc.eos? entry[Entry.members[key_index]] = value.join return entry # end of string end if sc.scan(/\\:/) value << ':' elsif sc.scan(/\\\\/) value << '\\' elsif sc.scan(/:/) entry[Entry.members[key_index]] = value.join key_index += 1 value = [] elsif sc.scan(/\r\n|\r|\n/) entry[Entry.members[key_index]] = value.join return entry elsif sc.scan(/./) value << sc[0] end raise "position didn't advance, stuck in parsing" if sc.pos == pos end entry end |