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

etc_hosts resource: test the contents of the /etc/hosts file #2065

Merged
merged 8 commits into from
Aug 31, 2017

Conversation

dromazmj
Copy link
Contributor

Signed-off-by: dromazos [email protected]

@dromazmj dromazmj closed this Aug 15, 2017
@dromazmj dromazmj reopened this Aug 15, 2017
@dromazmj dromazmj closed this Aug 15, 2017
@dromazmj dromazmj reopened this Aug 15, 2017
@adamleff adamleff changed the title New Resource - etc_hosts etc_hosts resource: test the contents of the /etc/hosts file Aug 17, 2017
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.

Thanks for your contribution @dromazmj - I've left some feedback for this PR.

# etc_hosts

Use the `etc_hosts` InSpec audit resource to test rules set to match IP address's with hostnames.
## Syntax
Copy link
Contributor

Choose a reason for hiding this comment

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

Need extra newline here.


# etc_hosts

Use the `etc_hosts` InSpec audit resource to test rules set to match IP address's with hostnames.
Copy link
Contributor

Choose a reason for hiding this comment

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

IP addresses

Use the `etc_hosts` InSpec audit resource to test rules set to match IP address's with hostnames.
## Syntax

An etc/hosts rule specifies an IP address and what it's hostname is along with an aliase names it can have.
Copy link
Contributor

Choose a reason for hiding this comment

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

its

Copy link
Contributor

Choose a reason for hiding this comment

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

Also not sure what aliase should be... alias or aliases? Probably alias?


An etc/hosts rule specifies an IP address and what it's hostname is along with an aliase names it can have.

## Syntax
Copy link
Contributor

Choose a reason for hiding this comment

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

Please see the #2064 PR and apply the same points to the documentation here (remove extra spaces in parens, use the cmp matcher to avoid the double-array stuff, removing the return object type from the headers in each of the supported methods/matchers, etc.)

its ( 'all_host_names' ) { should eq [['list']] }
end

Use the optional constructor parameter to give an alternative path to hosts file
Copy link
Contributor

Choose a reason for hiding this comment

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

The example here doesn't use the optional parameter you speak of. 🙂


def initialize(hosts_path = nil)
return skip_resource 'The `etc_hosts` resource is not supported on your OS.' unless inspec.os.linux? || inspec.os.windows?
@conf_path = get_hosts_path_by_os(hosts_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

It's more common to handle the override here, rather than in the get_hosts_path_by_os method...

@conf_path = hosts_path || get_hosts_path_by_os

I'd also recommend naming the method default_hosts_file_path so it's clear why the method exists and its purpose.


private

def get_hosts_path_by_os(hosts_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rewrite this a bit based on the above comment.

if inspec.os.linux?
  '/etc/hosts'
elsif inspec.os.windows?
  'c:\windows\system32\drivers\etc\hosts'
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This produces an error with lint, it tells you to use the return => unless.

Copy link
Contributor

Choose a reason for hiding this comment

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

I am unable to reproduce that, and likely had to do with the nil checking, not the structure of the conditional. We use this pattern in other resources already. You can see it at the top of the file resource.

{
'ip_address' => line_parts[0],
'canonical_hostname' => line_parts[1],
'all_host_names' => line_parts[1..-1] || '',
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't the default return if there are no elements 1+ be an empty array [] instead of an empty string?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, to avoid that condition completely, maybe this should skip any line that has less than 2 line_parts...

line_parts = line.split
return unless line_parts.length >= 2
... etc ...

Then you shouldn't even need to worry about the default value for all_host_names


raw_conf = file.content
if raw_conf.empty? && !file.empty?
return skip_resource("File is empty.\"#{@conf_path}\"")
Copy link
Contributor

Choose a reason for hiding this comment

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

File isn't empty. Better error message: "Could not read file contents #{@conf_path}"

if raw_conf.empty? && !file.empty?
return skip_resource("File is empty.\"#{@conf_path}\"")
end
inspec.file(conf_path).content.lines
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 reading the file again? You've already read it in and stored it in raw_conf. This should probably be raw_conf.lines

@dromazmj dromazmj requested a review from a team as a code owner August 18, 2017 14:44
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.

Some final cleanup and we should be good to go, @dromazmj!

# author: Matthew Dromazos

require 'utils/parser'
require 'pry'
Copy link
Contributor

Choose a reason for hiding this comment

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

Still needs to be removed, please!


def initialize(hosts_path = nil)
return skip_resource 'The `etc_hosts` resource is not supported on your OS.' unless inspec.os.linux? || inspec.os.windows?
@conf_path = hosts_path || default_hosts_file_path(hosts_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

You're doing an || here (which is great), which means default_hosts_file_path doesn't need to receive it as an argument. It will simplify the default_hosts_file_path method as well.


private

def default_hosts_file_path(hosts_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

As per above, hosts_path should be needed here; this method should just return the appropriate default and let the initialize method either call it or not call it depending on whether the user supplied a path. I'd really simplify down to one line:

inspec.os.windows? ? 'C:\windows\system32\drivers\etc\hosts' : '/etc/hosts'

line_parts = line.split
return nil unless line_parts.length >= 2
{
'ip_address' => line_parts[0],
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please align these or remove the extraneous spaces? Lines 64-66. Either way is fine as long as it's consistent. Thanks!


raw_conf = file.content
if raw_conf.empty? && !file.empty?
return skip_resource("Could not read file contents\"#{@conf_path}\"")
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing a space between contents and \"

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 good to me. We'll need to fix the conflict in test/helper.rb but I'd hold off on doing that until right before we merge after getting a 2nd approval or we're just going to have to come back and fix it again due to the other pending PRs that may get merged before this.

Thanks, @dromazmj.

@adamleff adamleff requested a review from a team August 30, 2017 17:31
Copy link
Contributor

@arlimus arlimus left a comment

Choose a reason for hiding this comment

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

Amazing addition @dromazmj thank you so much!! This is great 😁

Thank you for your guidance in reviewing @adamleff

@adamleff adamleff merged commit cb5b475 into inspec:master Aug 31, 2017
@adamleff adamleff deleted the al/etc_hosts branch August 31, 2017 13:51
@adamleff adamleff restored the al/etc_hosts branch August 31, 2017 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants