-
Notifications
You must be signed in to change notification settings - Fork 681
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
updated postgres_session resource properly escape queries #1939
updated postgres_session resource properly escape queries #1939
Conversation
f37aad3
to
5c3ba24
Compare
@chris-rock not sure how we would do unit tests for this one? Suggestions? |
We simulate a sample call and add those result to: https://github.com/chef/inspec/blob/master/test/helper.rb#L164 |
5c3ba24
to
f7ea527
Compare
To test that we're building the correct command, it would be best to break out the building of the Then we can test the resource itself by doing what @chris-rock suggested and ensure we take the output received from |
I was thinking the same thing. I will work on that update. It should not be
too big to break it out.
…--------
Aaron Lippold
[email protected]
260-255-4779
twitter/aim/yahoo,etc.
'aaronlippold'
On Mon, Jun 19, 2017 at 11:17 AM, Adam Leff ***@***.***> wrote:
To test the actual query, it would be best to break out the building of
the psql command string into a separate method and test that method.
Then we can test the resource itself by doing what @chris-rock
<https://github.com/chris-rock> suggested and ensure we take the output
received from psql query and treat it properly.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1939 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABauaP4C0UzmhjNKlPvhqIfCC0aXXov_ks5sFpEKgaJpZM4N9noh>
.
|
So something like this @adamleff?
def initialize(user, pass, host = nil)
@user = user || 'postgres'
@pass = pass
@host = host || 'localhost'
end
def escaped_query(query)
return warn 'no query specificed' if query.empty? || query.nil?
Shellwords.escape(query)
end
def create_psql_cmd(query, db = [])
dbs = db.map { |x| "-d #{x}" }.join(' ')
@escaped_query = escaped_query(query)
"PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h #{@host} -A -t -c
#{@escaped_query}"
end
def query(query, db = [])
@psql_cmd = create_psql_cmd(query,db)
cmd = inspec.command(@psql_cmd)
out = cmd.stdout + "\n" + cmd.stderr
if cmd.exit_status != 0 || out =~ /could not connect to .*/ ||
out.downcase =~ /^error:.*/
skip_resource "Can't read run query #{query.inspect} on
postgres_session: #{out}"
else
Lines.new(cmd.stdout.strip, "PostgreSQL query: #{query}")
end
end
…--------
Aaron Lippold
[email protected]
260-255-4779
twitter/aim/yahoo,etc.
'aaronlippold'
On Mon, Jun 19, 2017 at 8:24 AM, Christoph Hartmann < ***@***.***> wrote:
We simulate a sample call and add those result to:
https://github.com/chef/inspec/blob/master/test/helper.rb#L164
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1939 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABauaG-j9olUiFGvOQZZ-F36r9a-yv4Hks5sFmh9gaJpZM4N9noh>
.
|
Possibly? It's really hard to tell when it's in a comment, and isn't a good facility with which to comment on individual lines. Go ahead and add it as a commit and we can work through it that way, please. |
70ad996
to
4d23415
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aaronlippold thanks for your PR. This is a good first step. I left you a bunch of feedback that we'd need to see addressed before we can consider merging. Please add comments to any of the feedback items if you have questions.
lib/resources/postgres_session.rb
Outdated
|
||
def initialize(user, pass, host = nil) | ||
@user = user || 'postgres' | ||
@pass = pass | ||
@host = host || 'localhost' | ||
end | ||
|
||
def query(query, db = []) | ||
def escaped_query(query) | ||
return warn 'no query specificed' if query.empty? || query.nil? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to do this. In the #query
method, the query argument is required so you'll never end up in this method with an empty string.
If someone deliberately passes nil
to #query
then they deserve to get a Ruby exception :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Pulled
lib/resources/postgres_session.rb
Outdated
@@ -39,25 +41,32 @@ class PostgresSession < Inspec.resource(1) | |||
its('output') { should eq('') } | |||
end | |||
" | |||
attr_reader :user, :pass, :host, :db, :escaped_query, :psql_cmd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should only be adding attribute reader methods for parameters we want to expose externally, or if we need it for testing purposes (i.e. you need to mock something that would otherwise be an instance variable... in which case, helper methods are probably the order of the day, or writing different tests). Why do these need to be exposed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expose user, pass and db check the constructor. I exposed db, escaped_query and psql_cmd to test that each of the helper functions was working as expected.
I guess I could just expose user, pass, host and psql_cmd and that would enable us to check that all the parts are working as expected over time.
lib/resources/postgres_session.rb
Outdated
escaped_query = query.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$') | ||
# run the query | ||
cmd = inspec.command("PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h #{@host} -A -t -c \"#{escaped_query}\"") | ||
@escaped_query = escaped_query(query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you setting this to an instance variable? It doesn't look like it's used anywhere outside of this create_psql_cmd
method...
You should be able to just do this:
"PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h #{@host} -A -t -c #{escaped_query(query)}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated.
lib/resources/postgres_session.rb
Outdated
end | ||
|
||
def query(query, db = []) | ||
@db = db |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being set to an instance variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mainly wanted to be able to test the main parts of the construction process to what I was passing to psql. i.e. that the query escaped correctly with the corner case tests - like : SELECT current_setting('client_min_messages') .
I guess if I just expose @psql_cmd I would be able to look at the parts of that and ensure that the functions are all producing what we are expecting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worked out a solution that doesn't require anything to be exposed.
lib/resources/postgres_session.rb
Outdated
|
||
def query(query, db = []) | ||
@db = db | ||
@psql_cmd = create_psql_cmd(query, @db) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being set to an instance variable instead of a local variable?
it 'verify postgres_session create_psql_cmd function' do | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.create_psql_cmd("SELECT * FROM STUDENTS;",['testdb'])).must_equal "PGPASSWORD='mypass' psql -U myuser -d testdb -h 127.0.0.1 -A -t -c SELECT\\ \\*\\ FROM\\ STUDENTS\\;" | ||
_(resource.db).must_equal ['testdb'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't something this function should be responsible for, and therefore shouldn't be tested. Just worry about testing that create_psql_cmd
generates the appropriate output based on a set of input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
||
it 'verify postgres_session create_psql_cmd function' do | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.create_psql_cmd("SELECT * FROM STUDENTS;",['testdb'])).must_equal "PGPASSWORD='mypass' psql -U myuser -d testdb -h 127.0.0.1 -A -t -c SELECT\\ \\*\\ FROM\\ STUDENTS\\;" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check your indentation... you're 2-spaces indented too far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
it 'verify postgres_session escaped_query function' do | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.escaped_query("SELECT * FROM STUDENTS;")).must_equal "SELECT\\ \\*\\ FROM\\ STUDENTS\\;" | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a duplicate line and is not needed.
|
||
it 'verify postgres_session escaped_query function' do | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.escaped_query("SELECT * FROM STUDENTS;")).must_equal "SELECT\\ \\*\\ FROM\\ STUDENTS\\;" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation needs to be fixed -- indented too far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.escaped_query("SELECT * FROM STUDENTS;")).must_equal "SELECT\\ \\*\\ FROM\\ STUDENTS\\;" | ||
resource = load_resource('postgres_session','myuser','mypass','127.0.0.1') | ||
_(resource.escaped_query("SELECT current_setting('client_min_messages')")).must_equal "SELECT\\ current_setting\\(\\'client_min_messages\\'\\)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation needs to be fixed -- indented too far.
@aaronlippold Aaron, also, to make the reviews easier until we're finished with the review, please do not rebase your changes. Just add additional commits without pulling in any merge commits, etc. This will make the review process faster, and we'll squash before we merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty close - one more cleanup item.
lib/resources/postgres_session.rb
Outdated
|
||
def create_psql_cmd(query, db = []) | ||
dbs = db.map { |x| "-d #{x}" }.join(' ') | ||
@escaped_query = escaped_query(query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line can be eliminated, correct? You're not using this variable anywhere, and you're calling escaped_query
directly in the returned string in the next line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, done and pushed.
@aaronlippold we switched our merge process in inspec. we do not need to rebase anymore since we use |
fixed resource to use 'shellwords' module to escape the query requested chances in method architecture for testing added unit tests Fixes: inspec#1814 Signed-off-by: Aaron Lippold <[email protected]>
Signed-off-by: Aaron Lippold <[email protected]>
Signed-off-by: Aaron Lippold <[email protected]>
Signed-off-by: Aaron Lippold <[email protected]>
bc8adf6
to
7d60aa7
Compare
@aaronlippold just FYI, I force-pushed to your branch so that I could fix the merge conflict for you. Just a heads-up that you'll need to force-pull or destroy your branch and pull it down from the remote again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @aaronlippold
updated resource to use 'shellwords' module to escape the query
fixed a small courner case in the error detection - error: vs error
Fixes: #1814
Signed-off-by: Aaron Lippold [email protected]