Skip to content

Finish conversion of postgresql_escape function #1162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ _Private Classes_
_Public Functions_

* [`postgresql::default`](#postgresqldefault): This function pull default values from the `params` class or `globals` class if the value is not present in `params`.
* [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape): This function safely escapes a string using a consistent random tag
* [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape): This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required.
* [`postgresql::postgresql_password`](#postgresqlpostgresql_password): This function returns the postgresql password hash from the clear text username / password
* [`postgresql_escape`](#postgresql_escape): This function safely escapes a string using a consistent random tag
* [`postgresql_escape`](#postgresql_escape): DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.
* [`postgresql_password`](#postgresql_password): DEPRECATED. Use the namespaced function [`postgresql::postgresql_password`](#postgresqlpostgresql_password) instead.

_Private Functions_
Expand Down Expand Up @@ -2787,26 +2787,19 @@ Data type: `String`

Type: Ruby 4.x API

postgresql_escape.rb
---- original file header ----
This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required.

@return Safely escapes a string using $$ using a random tag which should be consistent
#### `postgresql::postgresql_escape(String[1] $input_string)`

#### `postgresql::postgresql_escape(Any *$args)`
The postgresql::postgresql_escape function.

postgresql_escape.rb
---- original file header ----
Returns: `String` A `Dollar Quoted` string

@return Safely escapes a string using $$ using a random tag which should be consistent
##### `input_string`

Returns: `Data type` Describe what the function returns here

##### `*args`

Data type: `Any`
Data type: `String[1]`

The original array of arguments. Port this to individually managed params
to get the full benefit of the modern function API.
The unescaped string you want to escape using `dollar quoting`

### postgresql::postgresql_password

Expand Down Expand Up @@ -2834,15 +2827,21 @@ The clear text `password`

### postgresql_escape

Type: Ruby 3.x API
Type: Ruby 4.x API

DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.

This function safely escapes a string using a consistent random tag
#### `postgresql_escape(Any *$args)`

#### `postgresql_escape()`
The postgresql_escape function.

Returns: `Any`

##### `*args`

Data type: `Any`

This function safely escapes a string using a consistent random tag

Returns: `Any` Safely escapes a string using $$ using a random tag which should be consistent

### postgresql_password

Expand Down
58 changes: 18 additions & 40 deletions lib/puppet/functions/postgresql/postgresql_escape.rb
Original file line number Diff line number Diff line change
@@ -1,52 +1,30 @@
# This is an autogenerated function, ported from the original legacy version.
# It /should work/ as is, but will not have all the benefits of the modern
# function API. You should see the function docs to learn how to add function
# signatures for type safety and to document this function using puppet-strings.
#
# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html
#
# ---- original file header ----
require 'digest/md5'

# postgresql_escape.rb
# ---- original file header ----
#
# @summary
# This function safely escapes a string using a consistent random tag
# @return Safely escapes a string using $$ using a random tag which should be consistent
#
#
# @summary This function escapes a string using [Dollar Quoting](https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING) using a randomly generated tag if required.
Puppet::Functions.create_function(:'postgresql::postgresql_escape') do
# @param args
# The original array of arguments. Port this to individually managed params
# to get the full benefit of the modern function API.
#
# @return [Data type]
# Describe what the function returns here
# @param input_string
# The unescaped string you want to escape using `dollar quoting`
#
# @return [String]
# A `Dollar Quoted` string
dispatch :default_impl do
# Call the method named 'default_impl' when this is matched
# Port this to match individual params for better type safety
repeated_param 'Any', :args
param 'String[1]', :input_string
end

def default_impl(*args)
if args.size != 1
raise(Puppet::ParseError, 'postgresql_escape(): Wrong number of arguments ' \
"given (#{args.size} for 1)")
def default_impl(input_string)
# Where allowed, just return the original string wrapped in `$$`
return "$$#{input_string}$$" unless tag_needed?(input_string)

# Keep generating possible values for tag until we find one that doesn't appear in the input string
tag = Digest::MD5.hexdigest(input_string)[0..5].gsub(%r{\d}, '')
until input_string !~ %r{#{tag}}
tag = Digest::MD5.hexdigest(tag)[0..5].gsub(%r{\d}, '')
end

password = args[0]
"$#{tag}$#{input_string}$#{tag}$"
end

if password !~ %r{\$\$} && password[-1] != '$'
retval = "$$#{password}$$"
else
escape = Digest::MD5.hexdigest(password)[0..5].gsub(%r{\d}, '')
until password !~ %r{#{escape}}
escape = Digest::MD5.hexdigest(escape)[0..5].gsub(%r{\d}, '')
end
retval = "$#{escape}$#{password}$#{escape}$"
end
retval
def tag_needed?(input_string)
input_string =~ %r{\$\$} || input_string.end_with?('$')
end
end
10 changes: 10 additions & 0 deletions lib/puppet/functions/postgresql_escape.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @summary DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.
Puppet::Functions.create_function(:postgresql_escape) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'postgresql_escape', 'This method is deprecated, please use postgresql::postgresql_escape instead.')
call_function('postgresql::postgresql_escape', *args)
end
end
29 changes: 0 additions & 29 deletions lib/puppet/parser/functions/postgresql_escape.rb

This file was deleted.

4 changes: 2 additions & 2 deletions manifests/server/passwd.pp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
default => ''
}

if ($postgres_password != undef) {
if $postgres_password {
# NOTE: this password-setting logic relies on the pg_hba.conf being
# configured to allow the postgres system user to connect via psql
# without specifying a password ('ident' or 'trust' security). This is
# the default for pg_hba.conf.
$escaped = postgresql_escape($postgres_password)
$escaped = postgresql::postgresql_escape($postgres_password)
exec { 'set_postgres_postgrespw':
# This command works w/no password because we run it as postgres system
# user
Expand Down
5 changes: 5 additions & 0 deletions spec/functions/postgresql_escape_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'spec_helper'

describe 'postgresql_escape' do
it_behaves_like 'postgresql_escape function'
end
37 changes: 1 addition & 36 deletions spec/functions/postgresql_postgresql_escape_spec.rb
Original file line number Diff line number Diff line change
@@ -1,40 +1,5 @@
require 'spec_helper'

describe 'postgresql::postgresql_escape' do
# without knowing details about the implementation, this is the only test
# case that we can autogenerate. You should add more examples below!
it { is_expected.not_to eq(nil) }

#################################
# Below are some example test cases. You may uncomment and modify them to match
# your needs. Notice that they all expect the base error class of `StandardError`.
# This is because the autogenerated function uses an untyped array for parameters
# and relies on your implementation to do the validation. As you convert your
# function to proper dispatches and typed signatures, you should change the
# expected error of the argument validation examples to `ArgumentError`.
#
# Other error types you might encounter include
#
# * StandardError
# * ArgumentError
# * Puppet::ParseError
#
# Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/
#
# it 'raises an error if called with no argument' do
# is_expected.to run.with_params.and_raise_error(StandardError)
# end
#
# it 'raises an error if there is more than 1 arguments' do
# is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError)
# end
#
# it 'raises an error if argument is not the proper type' do
# is_expected.to run.with_params('foo').and_raise_error(StandardError)
# end
#
# it 'returns the proper output' do
# is_expected.to run.with_params(123).and_return('the expected output')
# end
#################################
it_behaves_like 'postgresql_escape function'
end
20 changes: 20 additions & 0 deletions spec/spec_helper_local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,23 @@ def param(type, title, param)
is_expected.to run.with_params('foo').and_raise_error(StandardError)
end
end

shared_examples 'postgresql_escape function' do
it { is_expected.not_to eq(nil) }
it {
is_expected.to run.with_params('foo')
.and_return('$$foo$$')
}
it {
is_expected.to run.with_params('fo$$o')
.and_return('$ed$fo$$o$ed$')
}
it {
is_expected.to run.with_params('foo$')
.and_return('$a$foo$$a$')
}
it 'raises an error if there is more than 1 argument' do
is_expected.to run.with_params(['foo'], ['foo'])
.and_raise_error(StandardError)
end
end
27 changes: 0 additions & 27 deletions spec/unit/functions/postgresql_escape_spec.rb

This file was deleted.