mirror of
https://github.com/inspec/inspec
synced 2024-11-22 12:43:07 +00:00
Inspec automate command extended for compliances
Signed-off-by: Nikita Mathur <nikita.mathur@chef.io>
This commit is contained in:
parent
8a93f08a13
commit
a4d822ae43
12 changed files with 220 additions and 26 deletions
|
@ -179,7 +179,7 @@ $ inspec --help
|
|||
Commands:
|
||||
inspec archive PATH # archive a profile to tar.gz (default) ...
|
||||
inspec check PATH # verify all tests at the specified PATH
|
||||
inspec compliance SUBCOMMAND ... # Chef Compliance commands
|
||||
inspec compliance SUBCOMMAND or automate SUBCOMMAND ... # Chef Compliance commands
|
||||
inspec detect # detect the target OS
|
||||
inspec exec PATH(S) # run all test files at the specified PATH.
|
||||
inspec help [COMMAND] # Describe available commands or one spe...
|
||||
|
|
|
@ -8,6 +8,8 @@ The `compliance` set of subcommands handle user-initiated communication with Che
|
|||
|
||||
When Automate initiates scans, the `compliance` subcommand is not used.
|
||||
|
||||
An alternate subcommand to `compliance` is `automate`. And it works similarly using `inspec automate`.
|
||||
|
||||
## Operational Notes
|
||||
|
||||
### Obtaining an a test Automate server
|
||||
|
@ -65,9 +67,10 @@ There are several other minor commands not listed here - see `lib/cli.rb` for a
|
|||
|
||||
### login
|
||||
|
||||
Saves a credentials file locally. Future invocations of `inspec compliance` use the credentials file to authenticate.
|
||||
Saves a credentials file locally. Future invocations of `inspec compliance` or `inspec automate` use the credentials file to authenticate.
|
||||
|
||||
`be inspec compliance login --user=admin --token='1234567890asdfghjkl' --insecure https://chef-automate.test`
|
||||
`be inspec compliance login --user=admin --token='1234567890asdfghjkl' --insecure https://chef-automate.test` or
|
||||
`be inspec automate login --user=admin --token='1234567890asdfghjkl' --insecure https://chef-automate.test`
|
||||
|
||||
Here are the results of running login, from `.inspec/compliance/config.json`:
|
||||
|
||||
|
|
|
@ -187,6 +187,10 @@ Chef Automate:
|
|||
inspec compliance login
|
||||
inspec exec compliance://username/linux-baseline
|
||||
```
|
||||
An alternate command for login:
|
||||
```
|
||||
inspec automate login
|
||||
```
|
||||
|
||||
Chef Supermarket:
|
||||
```
|
||||
|
|
|
@ -40,6 +40,11 @@ inspec compliance login https://compliance.test --user admin --insecure --token
|
|||
|
||||
where `--insecure` is required when using self-signed certificates.
|
||||
|
||||
An alternate command for login:
|
||||
```bash
|
||||
inspec automate login https://compliance.test --user admin --insecure --token ''
|
||||
```
|
||||
|
||||
Use a compliance profile from the Chef Supermarket:
|
||||
|
||||
```YML
|
||||
|
|
|
@ -221,6 +221,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|||
#{Inspec::Dist::EXEC_NAME} compliance login
|
||||
#{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline
|
||||
```
|
||||
An alternate command for login:
|
||||
```
|
||||
#{Inspec::Dist::EXEC_NAME} automate login
|
||||
```
|
||||
|
||||
Supermarket:
|
||||
```
|
||||
|
|
|
@ -117,6 +117,15 @@ module Inspec::Plugin::V2
|
|||
# `inspec dosomething` => activate the :dosomething hook
|
||||
activate_me ||= cli_args.include?(act.activator_name.to_s)
|
||||
|
||||
# Only one compliance command to be activated at one time.
|
||||
# Since both commands are defined in the same class,
|
||||
# activators were not getting fetched uniquely.
|
||||
if cli_args.include?("automate") && act.activator_name.to_s.eql?("compliance")
|
||||
activate_me = false
|
||||
elsif cli_args.include?("compliance") && act.activator_name.to_s.eql?("automate")
|
||||
activate_me = false
|
||||
end
|
||||
|
||||
# OK, activate.
|
||||
if activate_me
|
||||
act.activate
|
||||
|
|
|
@ -6,6 +6,7 @@ This extensions offers the following features:
|
|||
- execute profiles directly from Chef Automate/Chef Compliance locally
|
||||
- upload a local profile to Chef Automate/Chef Compliance
|
||||
|
||||
The subcommand `compliance` has an alternate `automate`. And it works similarly using `inspec automate`.
|
||||
To use the CLI, this InSpec add-on adds the following commands:
|
||||
|
||||
* `$ inspec compliance login` - authentication of the API token against Chef Automate/Chef Compliance
|
||||
|
@ -14,12 +15,21 @@ To use the CLI, this InSpec add-on adds the following commands:
|
|||
* `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
|
||||
* `$ inspec compliance logout` - logout of Chef Automate/Chef Compliance
|
||||
|
||||
Similar to these CLI commands are:
|
||||
|
||||
* `$ inspec automate login` - authentication of the API token against Chef Automate/Chef Compliance
|
||||
* `$ inspec automate profiles` - list all available Compliance profiles
|
||||
* `$ inspec automate upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
|
||||
* `$ inspec automate logout` - logout of Chef Automate/Chef Compliance
|
||||
|
||||
Compliance profiles can be executed in two ways:
|
||||
|
||||
- via compliance exec: `inspec compliance exec profile`
|
||||
- via compliance exec: `inspec compliance exec profile` or `inspec automate exec profile`
|
||||
- via compliance scheme: `inspec exec compliance://profile`
|
||||
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Command options
|
||||
|
@ -37,6 +47,21 @@ Commands:
|
|||
inspec compliance version # displays the version of the Chef Compliance server
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate
|
||||
Commands:
|
||||
inspec automate download PROFILE # downloads a profile from Chef Compliance
|
||||
inspec automate exec PROFILE # executes a Chef Compliance profile
|
||||
inspec automate help [COMMAND] # Describe subcommands or one specific subcommand
|
||||
inspec automate login SERVER # Log in to a Chef Automate/Chef Compliance SERVER
|
||||
inspec automate logout # user logout from Chef Compliance
|
||||
inspec automate profiles # list all available profiles in Chef Compliance
|
||||
inspec automate upload PATH # uploads a local profile to Chef Compliance
|
||||
inspec automate version # displays the version of the Chef Compliance server
|
||||
```
|
||||
|
||||
### Login with Chef Automate 2
|
||||
|
||||
You will need an API token for authentication. You can retrieve one via the admin section of your A2 web gui.
|
||||
|
@ -67,6 +92,12 @@ You will need an access token for authentication. You can retrieve one via [UI](
|
|||
$ inspec compliance login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
|
||||
```
|
||||
|
||||
### Login with Chef Compliance
|
||||
|
||||
You will need an access token for authentication. You can retrieve one via:
|
||||
|
@ -79,6 +110,12 @@ You can choose the access token (`--token`) or the refresh token (`--refresh_tok
|
|||
$ inspec compliance login https://compliance.test --user admin --insecure --token '...'
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate login https://compliance.test --user admin --insecure --token '...'
|
||||
```
|
||||
|
||||
### List available profiles via Chef Compliance / Automate
|
||||
|
||||
```
|
||||
|
@ -103,6 +140,30 @@ Available profiles:
|
|||
* cis/cis-ubuntu14.04lts-level2
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate profiles
|
||||
Available profiles:
|
||||
-------------------
|
||||
* base/apache
|
||||
* base/linux
|
||||
* base/mysql
|
||||
* base/postgres
|
||||
* base/ssh
|
||||
* base/windows
|
||||
* cis/cis-centos6-level1
|
||||
* cis/cis-centos6-level2
|
||||
* cis/cis-centos7-level1
|
||||
* cis/cis-centos7-level2
|
||||
* cis/cis-rhel7-level1
|
||||
* cis/cis-rhel7-level2
|
||||
* cis/cis-ubuntu12.04lts-level1
|
||||
* cis/cis-ubuntu12.04lts-level2
|
||||
* cis/cis-ubuntu14.04lts-level1
|
||||
* cis/cis-ubuntu14.04lts-level2
|
||||
```
|
||||
|
||||
### Upload a profile to Chef Compliance / Automate
|
||||
|
||||
```
|
||||
|
@ -144,6 +205,47 @@ Available profiles:
|
|||
* cis/cis-ubuntu14.04lts-level2
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate version
|
||||
Chef Compliance version: 1.0.11
|
||||
➜ inspec git:(chris-rock/cc-error-not-loggedin) ✗ b inspec automate upload examples/profile
|
||||
I, [2016-05-06T14:27:20.907547 #37592] INFO -- : Checking profile in examples/profile
|
||||
I, [2016-05-06T14:27:20.907668 #37592] INFO -- : Metadata OK.
|
||||
I, [2016-05-06T14:27:20.968584 #37592] INFO -- : Found 4 controls.
|
||||
I, [2016-05-06T14:27:20.968638 #37592] INFO -- : Control definitions OK.
|
||||
Profile is valid
|
||||
Generate temporary profile archive at /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz
|
||||
I, [2016-05-06T14:27:21.020017 #37592] INFO -- : Generate archive /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz.
|
||||
I, [2016-05-06T14:27:21.024837 #37592] INFO -- : Finished archive generation.
|
||||
Start upload to admin/profile
|
||||
Uploading to Chef Compliance
|
||||
Successfully uploaded profile
|
||||
|
||||
# display all profiles
|
||||
$ inspec automate profiles
|
||||
Available profiles:
|
||||
-------------------
|
||||
* admin/profile
|
||||
* base/apache
|
||||
* base/linux
|
||||
* base/mysql
|
||||
* base/postgres
|
||||
* base/ssh
|
||||
* base/windows
|
||||
* cis/cis-centos6-level1
|
||||
* cis/cis-centos6-level2
|
||||
* cis/cis-centos7-level1
|
||||
* cis/cis-centos7-level2
|
||||
* cis/cis-rhel7-level1
|
||||
* cis/cis-rhel7-level2
|
||||
* cis/cis-ubuntu12.04lts-level1
|
||||
* cis/cis-ubuntu12.04lts-level2
|
||||
* cis/cis-ubuntu14.04lts-level1
|
||||
* cis/cis-ubuntu14.04lts-level2
|
||||
```
|
||||
|
||||
### Run a profile from Chef Compliance / Chef Automate on Workstation
|
||||
|
||||
```
|
||||
|
@ -179,6 +281,14 @@ $ inspec compliance logout
|
|||
Successfully logged out
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ inspec automate logout
|
||||
Successfully logged out
|
||||
```
|
||||
|
||||
|
||||
## Integration Tests
|
||||
|
||||
At this point of time, InSpec is not able to pick up the token directly, therefore the integration test is semi-automatic at this point of time:
|
||||
|
|
|
@ -7,6 +7,11 @@ module InspecPlugins
|
|||
require_relative "inspec-compliance/cli"
|
||||
InspecPlugins::Compliance::CLI
|
||||
end
|
||||
|
||||
cli_command :automate do
|
||||
require_relative "inspec-compliance/cli"
|
||||
InspecPlugins::Compliance::CLI
|
||||
end
|
||||
end
|
||||
|
||||
autoload :Configuration, "plugins/inspec-compliance/lib/inspec-compliance/configuration"
|
||||
|
|
|
@ -9,7 +9,7 @@ module InspecPlugins
|
|||
class CannotDetermineServerType < StandardError; end
|
||||
|
||||
def login(options)
|
||||
raise ArgumentError, "Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
|
||||
raise ArgumentError, "Please specify a server using `#{EXEC_NAME} compliance login https://SERVER` or `#{EXEC_NAME} automate login https://SERVER`" unless options["server"]
|
||||
|
||||
options["server"] = URI("https://#{options["server"]}").to_s if URI(options["server"]).scheme.nil?
|
||||
|
||||
|
@ -179,7 +179,7 @@ module InspecPlugins
|
|||
def self.compliance_verify_thor_options(o)
|
||||
error_msg = []
|
||||
|
||||
error_msg.push("Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`") if o["server"].nil?
|
||||
error_msg.push("Please specify a server using `#{EXEC_NAME} compliance login https://SERVER` or `#{EXEC_NAME} automate login https://SERVER`") if o["server"].nil?
|
||||
|
||||
if o["user"].nil? && o["refresh_token"].nil?
|
||||
error_msg.push("Please specify a `--user='USER'` or a `--refresh-token='TOKEN'`")
|
||||
|
|
|
@ -6,8 +6,7 @@ module InspecPlugins
|
|||
module Compliance
|
||||
class CLI < Inspec.plugin(2, :cli_command)
|
||||
include Inspec::Dist
|
||||
|
||||
subcommand_desc "compliance SUBCOMMAND", "#{COMPLIANCE_PRODUCT_NAME} commands"
|
||||
subcommand_desc "compliance SUBCOMMAND or automate SUBCOMMAND", "#{COMPLIANCE_PRODUCT_NAME} commands"
|
||||
|
||||
# desc "login https://SERVER --insecure --user='USER' --ent='ENTERPRISE' --token='TOKEN'", 'Log in to a Chef Compliance/Chef Automate SERVER'
|
||||
desc "login", "Log in to a #{COMPLIANCE_PRODUCT_NAME}/#{AUTOMATE_PRODUCT_NAME} SERVER"
|
||||
|
@ -65,7 +64,7 @@ module InspecPlugins
|
|||
exit 1
|
||||
end
|
||||
rescue InspecPlugins::Compliance::ServerConfigurationMissing
|
||||
$stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} compliance login`"
|
||||
$stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
|
||||
exit 1
|
||||
end
|
||||
|
||||
|
@ -167,7 +166,7 @@ module InspecPlugins
|
|||
|
||||
# determine user information
|
||||
if (config["token"].nil? && config["refresh_token"].nil?) || config["user"].nil?
|
||||
error.call("Please login via `#{EXEC_NAME} compliance login`")
|
||||
error.call("Please login via `#{EXEC_NAME} #{subcommand_name} login`")
|
||||
end
|
||||
|
||||
# read profile name from inspec.yml
|
||||
|
@ -233,7 +232,7 @@ module InspecPlugins
|
|||
exit 1
|
||||
end
|
||||
rescue InspecPlugins::Compliance::ServerConfigurationMissing
|
||||
puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} compliance login`"
|
||||
puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
|
||||
exit 1
|
||||
end
|
||||
|
||||
|
@ -258,9 +257,13 @@ module InspecPlugins
|
|||
|
||||
def loggedin(config)
|
||||
serverknown = !config["server"].nil?
|
||||
puts "You need to login first with `#{EXEC_NAME} compliance login`" unless serverknown
|
||||
puts "You need to login first with `#{EXEC_NAME} #{subcommand_name} login`" unless serverknown
|
||||
serverknown
|
||||
end
|
||||
|
||||
def subcommand_name
|
||||
@_invocations[Inspec::InspecCLI]&.first || "automate"
|
||||
end
|
||||
end
|
||||
|
||||
# register the subcommand to InSpec CLI registry
|
||||
|
|
|
@ -34,13 +34,13 @@ module InspecPlugins
|
|||
if config["token"].nil? && config["refresh_token"].nil?
|
||||
if config["server_type"] == "automate"
|
||||
server = "automate"
|
||||
msg = "#{EXEC_NAME} compliance login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
|
||||
msg = "#{EXEC_NAME} compliance or automate login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
|
||||
elsif config["server_type"] == "automate2"
|
||||
server = "automate2"
|
||||
msg = "#{EXEC_NAME} compliance login https://your_automate2_server --user USER --token APITOKEN"
|
||||
msg = "#{EXEC_NAME} compliance or automate login https://your_automate2_server --user USER --token APITOKEN"
|
||||
else
|
||||
server = "compliance"
|
||||
msg = "#{EXEC_NAME} compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
|
||||
msg = "#{EXEC_NAME} compliance or automate login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
|
||||
end
|
||||
raise Inspec::FetcherFailure, <<~EOF
|
||||
|
||||
|
@ -136,7 +136,8 @@ module InspecPlugins
|
|||
if m.nil?
|
||||
raise "Unable to determine compliance profile name. This can be caused by " \
|
||||
"an incorrect server in your configuration. Try to login to compliance " \
|
||||
"via the `#{EXEC_NAME} compliance login` command."
|
||||
"via the `#{EXEC_NAME} compliance login` command or " \
|
||||
"via the `#{EXEC_NAME} automate login` command."
|
||||
end
|
||||
|
||||
"#{m[:owner]}/#{m[:id]}"
|
||||
|
|
|
@ -50,4 +50,54 @@ class ComplianceCli < Minitest::Test
|
|||
|
||||
assert_exit_code 0, out # TODO: make this error
|
||||
end
|
||||
|
||||
## testing automate command for compliances
|
||||
|
||||
def test_help_output_using_automate_cmd
|
||||
out = run_inspec_process("automate help")
|
||||
|
||||
assert_includes out.stdout, "inspec automate exec PROFILE"
|
||||
|
||||
assert_exit_code 0, out
|
||||
end
|
||||
|
||||
def test_logout_command_using_automate_cmd
|
||||
out = run_inspec_process("automate logout")
|
||||
|
||||
assert_includes out.stdout, ""
|
||||
|
||||
assert_exit_code 0, out
|
||||
end
|
||||
|
||||
def test_error_login_with_invalid_url_using_automate_cmd
|
||||
out = run_inspec_process("automate login")
|
||||
|
||||
assert_includes out.stderr, 'ERROR: "inspec automate login" was called with no arguments'
|
||||
|
||||
assert_exit_code 1, out
|
||||
end
|
||||
|
||||
def test_profile_list_without_auth_using_automate_cmd
|
||||
out = run_inspec_process("automate profiles")
|
||||
|
||||
assert_includes out.stdout, "You need to login first with `inspec automate login`"
|
||||
|
||||
assert_exit_code 0, out # TODO: make this error
|
||||
end
|
||||
|
||||
def test_error_upload_without_args_using_automate_cmd
|
||||
out = run_inspec_process("automate upload")
|
||||
|
||||
assert_includes out.stderr, 'ERROR: "inspec automate upload" was called with no arguments'
|
||||
|
||||
assert_exit_code 1, out
|
||||
end
|
||||
|
||||
def test_error_upload_with_fake_path_using_automate_cmd
|
||||
out = run_inspec_process("automate upload /path/to/dir")
|
||||
|
||||
assert_includes out.stdout, "You need to login first with `inspec automate login`"
|
||||
|
||||
assert_exit_code 0, out # TODO: make this error
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue