Skip to content
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

Merged

Conversation

aaronlippold
Copy link
Collaborator

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 lippold@gmail.com

@aaronlippold aaronlippold force-pushed the al/postgres_session_query_escape branch from f37aad3 to 5c3ba24 Compare June 19, 2017 03:18
@aaronlippold aaronlippold changed the title updated resource to use 'shellwords' module updated potgres_session resource to use 'shellwords' module Jun 19, 2017
@aaronlippold
Copy link
Collaborator Author

@chris-rock not sure how we would do unit tests for this one? Suggestions?

@chris-rock
Copy link
Contributor

We simulate a sample call and add those result to: https://github.com/chef/inspec/blob/master/test/helper.rb#L164

@aaronlippold aaronlippold force-pushed the al/postgres_session_query_escape branch from 5c3ba24 to f7ea527 Compare June 19, 2017 15:01
@adamleff
Copy link
Contributor

adamleff commented Jun 19, 2017

To test that we're building the correct command, 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 suggested and ensure we take the output received from psql query and treat it properly.

@aaronlippold
Copy link
Collaborator Author

aaronlippold commented Jun 19, 2017 via email

@aaronlippold
Copy link
Collaborator Author

aaronlippold commented Jun 19, 2017 via email

@adamleff
Copy link
Contributor

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.

@aaronlippold aaronlippold force-pushed the al/postgres_session_query_escape branch 3 times, most recently from 70ad996 to 4d23415 Compare June 19, 2017 18:20
Copy link
Contributor

@adamleff adamleff left a 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.


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?
Copy link
Contributor

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 :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Pulled

@@ -39,25 +41,32 @@ class PostgresSession < Inspec.resource(1)
its('output') { should eq('') }
end
"
attr_reader :user, :pass, :host, :db, :escaped_query, :psql_cmd
Copy link
Contributor

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?

Copy link
Collaborator Author

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.

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)
Copy link
Contributor

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)}"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

end

def query(query, db = [])
@db = db
Copy link
Contributor

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.


def query(query, db = [])
@db = db
@psql_cmd = create_psql_cmd(query, @db)
Copy link
Contributor

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']
Copy link
Contributor

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.

Copy link
Collaborator Author

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\\;"
Copy link
Contributor

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.

Copy link
Collaborator Author

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')
Copy link
Contributor

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\\;"
Copy link
Contributor

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.

Copy link
Collaborator Author

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\\'\\)"
Copy link
Contributor

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.

@adamleff
Copy link
Contributor

@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.

Copy link
Contributor

@adamleff adamleff left a 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.


def create_psql_cmd(query, db = [])
dbs = db.map { |x| "-d #{x}" }.join(' ')
@escaped_query = escaped_query(query)
Copy link
Contributor

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.

Copy link
Collaborator Author

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.

@chris-rock
Copy link
Contributor

@aaronlippold we switched our merge process in inspec. we do not need to rebase anymore since we use squash and merge only now.

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 <lippold@gmail.com>
Signed-off-by: Aaron Lippold <lippold@gmail.com>
Signed-off-by: Aaron Lippold <lippold@gmail.com>
Signed-off-by: Aaron Lippold <lippold@gmail.com>
@adamleff adamleff force-pushed the al/postgres_session_query_escape branch from bc8adf6 to 7d60aa7 Compare June 30, 2017 15:02
@adamleff adamleff changed the title updated potgres_session resource to use 'shellwords' module updated postgres_session resource properly escape queries Jun 30, 2017
@adamleff adamleff added the Type: Bug Feature not working as expected label Jun 30, 2017
@adamleff
Copy link
Contributor

@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.

Copy link
Contributor

@chris-rock chris-rock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @aaronlippold

@chris-rock chris-rock merged commit 1b58763 into inspec:master Jul 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug Feature not working as expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

postgres_session escaped_query has issues with SQL that has ( ) in it.
4 participants