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

Add sensitive flag to resources to restrict logging output #2017

Merged
merged 4 commits into from
Aug 25, 2017

Conversation

arothian
Copy link
Contributor

Intending this as a starting point for a discussion on how this might best work. In Chef proper, there is a common attribute 'sensitive' that is used to suppress various output that might be logged, particularly during failures. I think the same use case can apply to chef-inspec. In particular, when using the file resource, if you are checking a sensitive file for specific content, you may not want the expected vs actual output to be logged.

This concept adds the same sensitive flag as a base attribute on inspec resources and modifies the formatters to filter out message output if it is set on the resource. What's missing here are some good tests, and I'm curious what thoughts might be for how to mark a resource as sensitive. I added one possibility related to the file resource.

Signed-off-by: Kevin Formsma kevin.formsma@gmail.com

@chris-rock
Copy link
Contributor

@arothian It is a great idea to make information more secure and not expose internal information on CLI or logs that do not belong there. Can you please add some specific cases, where sensitive information is exposed? Shouldn't we expect that each resource knows what is sensitive and what not? How is the resource argument helping to reduce that?

@@ -35,10 +35,11 @@ class FileResource < Inspec.resource(1)
"

attr_reader :file, :mount_options
def initialize(path)
def initialize(path, sensitive = false)
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel that we may do not want to add an additional option to each resource. This adds additional burden and makes resource development more complex.

@adamleff
Copy link
Contributor

I'm very 👍 on this idea, and it comes up relatively frequently. I agree with @chris-rock though that this shouldn't be an argument to the resource itself. I'd rather see the DSL extended similar to how Chef does this with properties:

describe file('/etc/shadow') do
  sensitive true
  its('content') { should match 'blah' }
end

@adamleff
Copy link
Contributor

To @chris-rock's point, I don't think it's reasonable for each resource to know what's sensitive. i.e. the burden on the file resource to know which files are sensitive and which ones aren't is extremely large. I'd rather put control in the hands of the users for something like this.

@arothian
Copy link
Contributor Author

Thanks for the feedback.

@adamleff, I like the suggested format for setting the flag.

I agree that it doesn't make sense for a resource to know what may be sensitive. It should be up to the user to mark as such.

For me, the specific use case is around file resources and the its('content') matchers. I'm creating a check that a configuration file contains the required keys, and that config also has sensitive data. If the check fails, currently the output exposes that file information. There are probably other use cases.

I'll see about updating this PR with the suggested way of setting the property

@arothian
Copy link
Contributor Author

arothian commented Aug 4, 2017

@adamleff, @chris-rock
I updated this with another potential solution for configuring the proposed sensitive flag. I didn't see a straightforward way to add it within the block passed to the rspec example. However, we can use rspec's default functionality for specifying boolean user metadata and then filtering on that it the formatter. Let me know what you think. The direct metadata route, should bypass any complexity with resource development.

I didn't see any unit tests related to the formatters or a easy way to incorporate this into the existing integration tests. If you have an idea there, let me know. The documentation would need to get updated yet.

Here is what I was using to test with. The output from the first resource should be suppressed.
echo "sensitive" > /tmp/example

describe file('/tmp/example'), :sensitive do
  its('content') { should match(/bob/) }
end

describe file('/tmp/example') do
  its('content') { should match(/bob/) }
end

@adamleff
Copy link
Contributor

@arothian I apologize for the delay in our response! I think this is a really neat solution and totally acceptable until we have a better way of extending the describe DSL.

Here's what needs to happen next:

  • another maintainer needs to approve. I'd like @chris-rock to weigh in on this
  • I'd like to see a test added for this new behavior. Unit testing the RSpec formatter is a path to sadness, so I'd recommend adding a functional test (see test/functional for examples). Please let me know if you have any questions or need suggestions on how to proceed
  • We need you to sign-off on your commits per the DCO

Thank you for your contribution thus far!

-Updated check in formatters to filter check output during failures based on
sensitive metadata flag
-Added functional test of output filtering
-Updated documentation with blerb on usage

Signed-off-by: Kevin Formsma <kevin.formsma@gmail.com>
@arothian
Copy link
Contributor Author

@adamleff Thanks for the feedback. I've added the mentioned functional tests for the new functionality, took a stab at updating the docs.

I rebased on the latest from master.

@chris-rock Should be ready to take a look at.

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.

@arothian this looks great! I have one suggestion on the sensitive output that I'd love to see updated, but I'm not going to block this change on that request. But please update if it you agree and you have a moment.

hash[:message] = exception_message(e)

if example.metadata[:sensitive]
hash[:message] = '*** sensitive ***'
Copy link
Contributor

Choose a reason for hiding this comment

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

Can I suggest we change this to *** sensitive output suppressed *** to make it extra clear?

@adamleff adamleff requested a review from a team August 25, 2017 13:34
Signed-off-by: Kevin Formsma <kevin.formsma@gmail.com>
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.

Great idea an approach, thank you @arothian !!

Update the color output to match the newly-expected non-color format if there are no tests that match.

Signed-off-by: Adam Leff <adam@leff.co>
@adamleff
Copy link
Contributor

Pushed up a small change to fix the test output as a result of #2094 getting merged before this. The color control characters around "0 skipped" are no longer necessary as we only colorize the output if the number is > 0.

Once this goes green in Travis, I'll merge!

@adamleff
Copy link
Contributor

Merging! Thanks again, @arothian!

@adamleff adamleff merged commit 94c2e81 into inspec:master Aug 25, 2017
@adamleff adamleff added the Type: New Feature Adds new functionality label Aug 25, 2017
@arothian arothian deleted the sensitive_flag branch August 25, 2017 20:52
@dialex
Copy link

dialex commented Oct 31, 2017

Hi @adamleff, does this feature apply to the bash resource?

I have an inspec test that calls an API via curl with an authentication token. Currently the inspec output shows the whole curl command (including the auth token) and I need to hide it.

describe bash(command_with_sensitive_data), :sensitive do
    its('stdout') { should match "200 OK" }
  end

Using the `:sensitive" flag did not hide the command. Using an env var is not enough, as inspec resolves it before outputting the command.

@adamleff
Copy link
Contributor

The sensitive flag only hides output from the commands/diffs, but not the actual command.

In your case, you'll likely want to the expect syntax which allows you to have a bit more control over the output:

describe "the website" do
  subject { bash(command_with_sensitive_data) }
  it "should return a 200 OK status" do
    expect(subject.stdout).to include("200 OK")
  end
end

@dialex
Copy link

dialex commented Nov 2, 2017

Oh, that works perfectly.

I wasn't aware of that syntax! Do you have any examples on Inspec's documentation? I don't remember seeing it. Where can I read more about it? For instance, is there any other matcher besides includes? Does it accept a regex?

Is there any reason when to use one syntax or the other?

I was actually going to "request a feature" to customise the output of test steps, to avoid printing long regex, or to make them more readable than the automatically generated message. I think this can do the trick...

@adamleff
Copy link
Contributor

adamleff commented Nov 3, 2017

@dialex I recently added an example of the "expect" syntax on the website: https://www.inspec.io/docs/reference/profiles/#should-vs-expect-syntax

Regarding additional matchers, we document some of them on our site, and you can also look through additional RSpec examples at sites like http://www.rubydoc.info/gems/rspec-expectations/frames ... again, we don't advocate for much of the advanced use as one of our primary goals is to remain readable to non-technical users. That said, there's nothing stopping you from going off the beaten path. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: New Feature Adds new functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants