mirror of
https://github.com/inspec/inspec
synced 2024-11-10 07:04:15 +00:00
load content into demo and handle shell commands
This commit is contained in:
parent
4048cc6b4c
commit
66e54b675f
56 changed files with 963 additions and 233 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -15,4 +15,4 @@ omnibus/pkg
|
|||
www/tutorial/typings
|
||||
www/tutorial/node_modules
|
||||
www/tutorial/**/*.js.map
|
||||
www/tutorial/**/*.js
|
||||
www/tutorial/dist
|
||||
|
|
|
@ -1,20 +1,85 @@
|
|||
# encoding: utf-8
|
||||
require 'train'
|
||||
require 'yaml'
|
||||
require 'json'
|
||||
require 'shellwords'
|
||||
|
||||
commands = { 'inspec_exec' => 'inspec exec examples/profile/controls/example.rb', 'inspec_version' => 'inspec version', 'help' => 'inspec help' }
|
||||
# Load all commands and instructions
|
||||
demos = YAML.load(File.read('www/tutorial/tutorial.yml'))['demos']
|
||||
commands = demos.map { |x| x['desc'] }.map { |x| x.scan(/```(.*?)```/m) }.flatten.map(&:strip).map { |x| x.split("\n") }
|
||||
tutorial_instructions = demos.map { |x| [x['demo'], x['desc']] }
|
||||
extra_commands = YAML.load(File.read('www/tutorial/commands.yml'))['commands']
|
||||
|
||||
# find out if we have a single command or a multiline shell command
|
||||
cmds = commands.map { |x|
|
||||
cmd = x.join("\n")
|
||||
if cmd.include?('describe')
|
||||
cmd
|
||||
else
|
||||
x
|
||||
end
|
||||
}
|
||||
tutorial_commands = cmds.flatten
|
||||
|
||||
# Pull shell commands out so they can be handled
|
||||
# This is currently done by checking if the command includes the word inspec :/
|
||||
no_shell_tutorial_commands = tutorial_commands.select { |a| a.include?('inspec') }
|
||||
shell_tutorial_commands = tutorial_commands.reject { |a| a.include?('inspec') }
|
||||
|
||||
# escape the shell commands for echo
|
||||
shell_tutorial_commands.map! { |x|
|
||||
Shellwords.escape(x)
|
||||
}
|
||||
# Add 'echo' and ' | inspec shell' to shell commands to enable inspec shell command functionality
|
||||
shell_commands = shell_tutorial_commands.map { |x| 'echo ' + x + ' | inspec shell' }
|
||||
|
||||
# Merge the output
|
||||
commands = no_shell_tutorial_commands + extra_commands + shell_commands
|
||||
|
||||
# TEMPORARY: REMOVE SSH COMMANDS (-t & -b)
|
||||
commands.delete_if { |x| x.include? '-t' }
|
||||
commands.delete_if { |x| x.include? '-b' }
|
||||
|
||||
# Create key given command
|
||||
def create_key(command)
|
||||
formatted_command = command.gsub(/\W/, '_')
|
||||
not_too_long = formatted_command.gsub(/_{2,}/, '_')
|
||||
not_too_long + '.txt'
|
||||
end
|
||||
|
||||
# Create commands.json file
|
||||
commands_file = File.new('www/tutorial/commands.json', 'w')
|
||||
json = commands.map { |x| [x => create_key(x)] }.to_json
|
||||
commands_file.write(json)
|
||||
puts 'Wrote www/tutorial/commands.json'
|
||||
|
||||
# Create instructions.json file
|
||||
instructions_file = File.new('www/tutorial/instructions.json', 'w')
|
||||
instructions_file.write(tutorial_instructions.to_json)
|
||||
puts 'Wrote www/tutorial/instructions.json'
|
||||
|
||||
# Create extra_commands.json file used to expose the extra commands
|
||||
# that have been enabled but not noted in the tutorial instructions
|
||||
extra_commands_file = File.new('www/tutorial/extra_commands.json', 'w')
|
||||
extra_commands_file.write(extra_commands.to_json)
|
||||
puts 'Wrote www/tutorial/extra_commands.json'
|
||||
|
||||
# Generate command results files
|
||||
# Create Train connection
|
||||
backend = Train.create('local')
|
||||
conn = backend.connection
|
||||
|
||||
commands.each do |keyname, command|
|
||||
# loop around commands
|
||||
# Loop over commands
|
||||
commands.each do |command|
|
||||
cmd = conn.run_command(command)
|
||||
cmd.stdout
|
||||
|
||||
# save the result and put it in inspec/www/app/results with the keyname as filename
|
||||
# save the result and put it in inspec/www/app/results with command as filename
|
||||
result = cmd.stdout
|
||||
dir = 'www/tutorial/app/responses/'
|
||||
filename = File.join(dir, "#{keyname}.txt")
|
||||
|
||||
key = create_key(command)
|
||||
filename = File.join(dir, key.to_s)
|
||||
out_file = File.new(filename, 'w')
|
||||
result.lines.each do |line|
|
||||
line_to_write = "#{line.chomp}\r\n"
|
||||
|
|
4
www/tutorial/.gitignore
vendored
4
www/tutorial/.gitignore
vendored
|
@ -10,4 +10,6 @@ npm-debug.log
|
|||
app/*.js
|
||||
app/*.map
|
||||
app/**/*.js
|
||||
app/**/*.map
|
||||
app/**/*.map
|
||||
|
||||
!webpack.config.js
|
|
@ -1,7 +1,58 @@
|
|||
## InSpec Demo
|
||||
# Welcome to the InSpec Tutorial
|
||||
-----------------------------------------------------------
|
||||
|
||||
|
||||
## The InSpec whaaaat? What is this thing?
|
||||
This is an Angular 2 app that uses Xterm (https://github.com/sourcelair/xterm.js/) to simulate a terminal.
|
||||
'Ok, but why?'
|
||||
To give people an easy quick introduction to inspec and all it can do! Give it a try,
|
||||
learn a thing or two, tell us what you'd like to know more about, and have fun exploring!
|
||||
|
||||
|
||||
## How to run it
|
||||
run `npm install` to load dependencies
|
||||
run `npm run start` and browse to localhost:8080
|
||||
run `npm run start` to open in your browser @ localhost:8080
|
||||
|
||||
To generate content for the app/responses folder,
|
||||
run `bundle exec rake update demo` from the root of inspec project.
|
||||
-----------------------------------------------------------
|
||||
|
||||
## How does it work???
|
||||
|
||||
Well, let me tell you a story of a file named `tutorial.yml`, who lives in a directory named `inspec/www/tutorial`.
|
||||
|
||||
This kind, informational file was full of content, and oh so desired to spread its knowledge.
|
||||
But it knew not how to do so, for it was a simple yml file.
|
||||
|
||||
Then, from around the corner, came a sweet little ruby file, whose only wish was to help people
|
||||
do the things they needed to do. It's name, in fact, was `command_simulator.rb`, and it lived in a
|
||||
nearby directory named `inspec/tasks`. And, aha, a match was found.
|
||||
|
||||
And so command_simulator kindly took tutorialyml by the hand, and said 'let me help you! I can parse you, and help you help others'.
|
||||
And thus it began...
|
||||
command_simulator parsed tutorialyml to find the instructions and commands that are noted in the instructions.
|
||||
After that, the real fun began: command_simulator worked and worked to format the commands and prepare them.
|
||||
She created json files for instructions and commands, and used Train with MixLib:Shellout in the background to
|
||||
run the commands and record the output to some .txt files in the `www/tutorial/app/responses` directory.
|
||||
Pleased with her work, command_simulator turned to her friend the webapp, and said to her: 'take these json files, and show them to the people.'
|
||||
|
||||
Webapp then went and found her friend xterm, and said, why let's do this together, for two heads are always better than one!
|
||||
And so webapp said to her dear friend angular2, please help me make this work! and angular2 came running, as friends always do.
|
||||
And so angular2 met xterm, and as they shook hands, they knew they would be good friends together. So they put their heads together,
|
||||
and made some decisions about what each one's role would be. Xterm claimed responsiblity for creating the terminal view,
|
||||
reading the user's input, and displaying it. App then explained she could take that final user input sent over by xterm and
|
||||
and transform it into a regular expression, which she could then use to match against the information in the commandsjson file,
|
||||
matching the user's input against the key and then retrieving the associated value's txt file.
|
||||
And it was so. :)
|
||||
|
||||
|
||||
## How to generate content for tutorial/update the tutorial
|
||||
|
||||
To generate content for the tutorial, update the tutorial.yml and/or commands.yml file and
|
||||
run `bundle exec rake update_demo` from the root of inspec project.
|
||||
|
||||
This will create/update two json files (commands.json and instructions.json)
|
||||
and the .txt files for the app/responses/ directory (generated from the commands included in the tutorial.yml)
|
||||
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
### Author: Victoria Jeffrey
|
|
@ -1,3 +1,7 @@
|
|||
.main {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.terminal-nav {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
|
@ -10,7 +14,6 @@
|
|||
line-height: 60px;
|
||||
font-size: 30px;
|
||||
font-family: "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-weight: 300;
|
||||
transition: all 200ms ease-in;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
|
@ -20,27 +23,45 @@
|
|||
color: #ccc;
|
||||
}
|
||||
|
||||
.guide {
|
||||
font-family: monospace;
|
||||
font-size: 1.2rem;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: #444;
|
||||
img {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: lightskyblue;
|
||||
text-decoration: none;
|
||||
.guide {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #DDDDDD;
|
||||
font-family: monospace;
|
||||
font-weight: 100;
|
||||
font-size: 16px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
background-color: #444;
|
||||
text-align: left;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.cli {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: monospace;
|
||||
font-size: 1.2rem;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
height: 70%;
|
||||
}
|
||||
|
|
|
@ -4,24 +4,14 @@
|
|||
<span> x </span>
|
||||
</div>
|
||||
|
||||
<div class="guide" *ngIf="counter === 0">
|
||||
Welcome to the interactive InSpec demo!
|
||||
<p>
|
||||
This tutorial is great for getting familiar with InSpec. There are 3 sections:
|
||||
</p>
|
||||
<ol>
|
||||
<!--TODO: give these real links-->
|
||||
<li><a href="...">InSpec commandline interface</a></li>
|
||||
<li><a href="...">InSpec interactive shell</a></li>
|
||||
<li><a href="...">Create test and compliance profile</a></li>
|
||||
</ol>
|
||||
<p>Use the command "next" to move forward or "prev" to move backwards.</p>
|
||||
</div>
|
||||
<img src="inspec-logo.png" alt="Inspec Logo">
|
||||
<div class="main">
|
||||
<div class="guide">
|
||||
<p class="bold">{{title}}</p>
|
||||
<pre>{{instructions}}</pre>
|
||||
</div>
|
||||
|
||||
<div class="guide" *ngIf="counter > 0">
|
||||
<pre> {{ instructions }} </pre>
|
||||
</div>
|
||||
|
||||
<div class="cli">
|
||||
<xterm-terminal (command)="evalCommand(command=$event)" [responsesArray]="responsesArray" [response]="response" [shell]="shell"></xterm-terminal>
|
||||
</div>
|
||||
<div class="cli">
|
||||
<xterm-terminal (command)="evalCommand(command=$event)" [response]="response" [shell]="shell"></xterm-terminal>
|
||||
</div>
|
||||
</div>
|
|
@ -3,6 +3,8 @@ import { Http, Response } from '@angular/http';
|
|||
import { Observable } from 'rxjs/Rx';
|
||||
import { HTTP_PROVIDERS } from '@angular/http';
|
||||
import { XtermTerminalComponent } from './xterm-terminal/xterm-terminal.component';
|
||||
declare var require: any;
|
||||
var shellwords = require("shellwords");
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -13,20 +15,39 @@ import { XtermTerminalComponent } from './xterm-terminal/xterm-terminal.componen
|
|||
})
|
||||
|
||||
export class AppComponent implements OnInit {
|
||||
// template values
|
||||
instructions: any;
|
||||
instructionsArray: any;
|
||||
responsesArray: any;
|
||||
counter: number = 0;
|
||||
title: string;
|
||||
|
||||
// taken as input by xterm terminal componen
|
||||
response: string;
|
||||
shell: string;
|
||||
|
||||
// colors for responses
|
||||
red: string = " [31m";
|
||||
white: string = " [37m";
|
||||
black: string = " [30m";
|
||||
|
||||
matchFound: boolean; // helps to handle no match found response
|
||||
counter: number = 0; // keeps track of step number count
|
||||
userCommand: string; // used to display better error msg when no match is found
|
||||
extraCmds: string = ''; // used to display extra commands available (from commands.yml)
|
||||
|
||||
// arrays of data parsed from json files
|
||||
commandsArray: any = [];
|
||||
instructionsArray: any = [];
|
||||
|
||||
constructor(private http: Http) { }
|
||||
|
||||
ngOnInit() {
|
||||
// load json files
|
||||
this.getInstructions();
|
||||
this.getResponses();
|
||||
this.getExtraCmds();
|
||||
}
|
||||
|
||||
// called when command entered is 'next' or 'prev'
|
||||
// modifies value of counter and calls displayInstructions
|
||||
updateInstructions(step) {
|
||||
let totalSteps = this.instructionsArray.length - 1;
|
||||
let msg = Math.random();
|
||||
|
@ -34,117 +55,187 @@ export class AppComponent implements OnInit {
|
|||
if (this.counter < totalSteps) {
|
||||
this.counter += 1;
|
||||
}
|
||||
this.response = ' [30mMessage: ' + msg;
|
||||
|
||||
this.response = this.black + 'next' + msg;
|
||||
} else if (step === 'prev') {
|
||||
if (this.counter > 0) {
|
||||
this.counter -= 1;
|
||||
}
|
||||
this.response = ' [30mMessage: ' + msg;
|
||||
this.response = this.black + 'prev' + msg;
|
||||
}
|
||||
this.instructions = this.instructionsArray[this.counter]['_body'];
|
||||
this.displayInstructions();
|
||||
}
|
||||
|
||||
// display instructions based on value of counter and
|
||||
// format text to remove triple backticks. if the user has reached
|
||||
// then end of the demo, display a message containing extra commands that have been
|
||||
// enabled in the demo
|
||||
displayInstructions() {
|
||||
if (this.counter === this.instructionsArray.length - 1) {
|
||||
this.title = "the end; that's all folks!";
|
||||
this.instructions = "here are some other commands you can try out: \r\n\r\n" + this.extraCmds;
|
||||
} else {
|
||||
if (this.instructionsArray[this.counter][1]) {
|
||||
this.title = this.instructionsArray[this.counter][0];
|
||||
let text = this.instructionsArray[this.counter][1];
|
||||
let formattedText = text.replace(/```/g, '');
|
||||
this.instructions = formattedText;
|
||||
} else {
|
||||
this.instructions = 'Sorry, something seems to have gone wrong. Please try refreshing your browser.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called when a new value is emitted for command
|
||||
// checks for a match, calls parseInspecShell if shell is inspec-shell
|
||||
// and calls checkCommand if none of the first commands match
|
||||
evalCommand(command) {
|
||||
if (this.shell === 'inspec-shell') {
|
||||
this.parseInspecShell(command);
|
||||
}
|
||||
else if (command.match(/^inspec\s*.*/)) {
|
||||
this.parseInspecCommand(command);
|
||||
}
|
||||
else if (command.match(/^next\s*/)) {
|
||||
this.userCommand = command;
|
||||
if (command.match(/^next\s*/)) {
|
||||
this.updateInstructions('next');
|
||||
}
|
||||
else if (command.match(/^prev\s*/)) {
|
||||
this.updateInstructions('prev');
|
||||
}
|
||||
else if (this.shell === 'inspec-shell') {
|
||||
this.parseInspecShell(command);
|
||||
}
|
||||
else if (command.match(/^ls\s*/)) {
|
||||
this.response = " [37m" + this.responsesArray[1]['_body'];
|
||||
this.response = this.white + "README.md";
|
||||
}
|
||||
else if (command.match(/^pwd\s*/)) {
|
||||
this.response = " [37m" + this.responsesArray[2]['_body'];
|
||||
this.response = this.white + "anonymous-web-user/inspec";
|
||||
}
|
||||
else if (command.match(/^cat\s*README.md\s*/i)) {
|
||||
this.response = " [37mOnly a few commands are implemented in this terminal. Please follow the demo";
|
||||
this.response = this.white + "Only a few commands are implemented in this terminal. Please follow the demo";
|
||||
}
|
||||
else if (command.match(/^less\s*README.md\s*/i)) {
|
||||
this.response = " [37mOnly a few commands are implemented in this terminal. Please follow the demo.";
|
||||
this.response = this.white + "Only a few commands are implemented in this terminal. Please follow the demo.";
|
||||
}
|
||||
else {
|
||||
this.response = " [37minvalid command: " + command;
|
||||
}
|
||||
}
|
||||
|
||||
parseInspecCommand(command) {
|
||||
let command_target = command.match(/^inspec\s*(.*)/);
|
||||
if (command_target[1] === 'shell') {
|
||||
this.shell = 'inspec-shell'
|
||||
this.response = " [37m" + 'Welcome to the InSpec Shell\r\n To find out how to use it, type: help\r\n To leave, type: exit';
|
||||
}
|
||||
else if (command_target[1].match(/^exec\s*.*/)) {
|
||||
this.parseInspecExec(command);
|
||||
}
|
||||
else if (command_target[1].match(/^version\s*/)) {
|
||||
this.response = " [37m" + this.responsesArray[4]['_body'];
|
||||
}
|
||||
else {
|
||||
let msg = Math.random();
|
||||
this.response = " [37m" + this.responsesArray[0]['_body'] + " [30m" + msg;
|
||||
}
|
||||
}
|
||||
|
||||
parseInspecExec(command) {
|
||||
let target = command.match(/^inspec exec\s*(.*)/);
|
||||
if (target[1] === 'examples/profile') {
|
||||
this.response = " [37m" + this.responsesArray[3]['_body'];
|
||||
} else {
|
||||
this.response = " [31m Could not fetch inspec profile in '" + target[1] + "' ";
|
||||
this.checkCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
// if the shell is inspec-shell, we want to exit the shell env on 'exit'
|
||||
// format the command for checkCommand by using shellwords.escape and
|
||||
// adding 'echo' and 'inspec shell' to match command from commands.json
|
||||
parseInspecShell(command) {
|
||||
// exit inspec shell
|
||||
if (command.match(/^exit\s*/)) {
|
||||
this.shell = '';
|
||||
this.response = '';
|
||||
}
|
||||
else if (command.match(/^ls\s*/)) {
|
||||
this.response = " [37m" + this.responsesArray[5]['_body'];
|
||||
else if (command.match(/^pwd\s*/)) {
|
||||
this.response = this.white + "anonymous-web-user/inspec-shell";
|
||||
}
|
||||
// TODO: functionality for inspec Shell
|
||||
else {
|
||||
this.response = " [37m" + 'soon this will work, but not yet :) '
|
||||
let escaped_cmd;
|
||||
let formatted_cmd;
|
||||
// TODO: make this better
|
||||
// I don't really like what we're doing here when we have a
|
||||
// describe and control block, but I had a lot of trouble getting this
|
||||
// to work because of the new lines carriage returns in the command from commands.json
|
||||
// so at the moment we're splitting the command on "do" and assuming a match if that first
|
||||
// result group matches (everything before do) :/
|
||||
if (command.match(/^describe.*|^control/)) {
|
||||
let split_cmd = command.split('do');
|
||||
escaped_cmd = shellwords.escape(split_cmd[0]);
|
||||
formatted_cmd = 'echo.*' + escaped_cmd ;
|
||||
} else {
|
||||
escaped_cmd = shellwords.escape(command)
|
||||
formatted_cmd = 'echo.*' + escaped_cmd + '.*inspec.*shell';
|
||||
}
|
||||
let regex_compatible = formatted_cmd.replace(/\W+/g, '.*');
|
||||
this.checkCommand(regex_compatible);
|
||||
}
|
||||
}
|
||||
|
||||
// takes the command as input, replaces all white space with regex whitespace matcher
|
||||
// and creates a new regex. check if the regex matches any of the keys in the commandsArray
|
||||
// if it matches, we set matchFound to true and call displayResult. if it doesn't match,
|
||||
// we display a default error message
|
||||
checkCommand(command) {
|
||||
let dir = 'app/responses/';
|
||||
let cmd = command.replace(/ /g,"\\s*")
|
||||
let regexcmd = new RegExp(('^'+cmd+'$'), 'm')
|
||||
this.matchFound = false;
|
||||
for (var i = 0; i < this.commandsArray.length; i++) {
|
||||
let object = this.commandsArray[i]
|
||||
for (let key in object) {
|
||||
if (key.match(regexcmd)) {
|
||||
this.matchFound = true;
|
||||
let value = object[key];
|
||||
this.http.get(dir + value).subscribe(data => {
|
||||
this.displayResult(command, data);
|
||||
},
|
||||
err => console.error(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
// if no match is found, we check if the command entered was inspec exec something
|
||||
// and if it is respond appropriately ('could not fetch inspec profile in ''), otherwise
|
||||
// respond with 'invalid command' and the command entered
|
||||
if (this.matchFound === false) {
|
||||
let msg = Math.random();
|
||||
if (command.match(/^inspec exec\s*.*/)) {
|
||||
let target = command.match(/^inspec exec\s*(.*)/)
|
||||
if (target[1].match(/.*-t.*|.*-b.*/)) {
|
||||
this.response = this.red + "Sorry, we haven't figured out how to handle the transport options in this demo just yet." + this.black + msg;
|
||||
} else {
|
||||
this.response = this.red + "Could not fetch inspec profile in '" + target[1] + "' " + this.black + msg;
|
||||
}
|
||||
} else {
|
||||
this.response = this.red + 'invalid command: ' + this.userCommand + this.black + msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the command if inspec shell, we also need to set the shell variable to
|
||||
// inspec shell. print response value and random msg (to ensure recognition of value change by xterm
|
||||
// terminal component)
|
||||
displayResult(command, data) {
|
||||
if (command.match(/^inspec\s*shell\s*$/)) {
|
||||
this.shell = 'inspec-shell';
|
||||
}
|
||||
let msg = Math.random();
|
||||
this.response = this.white + data['_body'] + this.black + msg;
|
||||
}
|
||||
|
||||
// load json file for instructions and save to instructionsArray
|
||||
// call displayInstructions to load first set of instructions
|
||||
getInstructions() {
|
||||
Observable.forkJoin(
|
||||
this.http.get('/app/instructions/step0.txt'),
|
||||
this.http.get('/app/instructions/step1.txt'),
|
||||
this.http.get('/app/instructions/step2.txt')
|
||||
).subscribe(
|
||||
data => {
|
||||
this.instructionsArray = data;
|
||||
this.updateInstructions(0);
|
||||
this.http.get('instructions.json')
|
||||
.subscribe(data => {
|
||||
this.instructionsArray = JSON.parse(data['_body']);
|
||||
this.displayInstructions();
|
||||
},
|
||||
err => console.error(err)
|
||||
);
|
||||
}
|
||||
|
||||
// load json file for commands and push each object to commandsArray
|
||||
getResponses() {
|
||||
Observable.forkJoin(
|
||||
this.http.get('/app/responses/help.txt'), // 0
|
||||
this.http.get('/app/responses/ls.txt'), // 1
|
||||
this.http.get('/app/responses/pwd.txt'), // 2
|
||||
this.http.get('/app/responses/inspec_exec.txt'), // 3
|
||||
this.http.get('/app/responses/inspec_version.txt'), // 4
|
||||
this.http.get('/app/responses/pwd_inspec_shell.txt') // 5
|
||||
).subscribe(
|
||||
data => {
|
||||
this.responsesArray = data;
|
||||
this.http.get('commands.json')
|
||||
.subscribe(data => {
|
||||
let result = JSON.parse(data['_body']);
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
let object = result[i][0];
|
||||
this.commandsArray.push(object);
|
||||
}
|
||||
},
|
||||
err => console.error(err)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// load json file for extra commands to display extra commands available to user
|
||||
getExtraCmds() {
|
||||
this.http.get('extra_commands.json')
|
||||
.subscribe(data => {
|
||||
let result = JSON.parse(data['_body']);
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
this.extraCmds += result[i] + "\r\n";
|
||||
}
|
||||
},
|
||||
err => console.error(err)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<b>Welcome to the interactive InSpec demo!</b>
|
||||
<p>
|
||||
This tutorial is great for getting familiar with InSpec. There are 3 sections:
|
||||
</p>
|
||||
<ol>
|
||||
<!--TODO: give these real links-->
|
||||
<li><a href="...">InSpec commandline interface</a></li>
|
||||
<li><a href="...">InSpec interactive shell</a></li>
|
||||
<li><a href="...">Create test and compliance profile</a></li>
|
||||
</ol>
|
||||
<p><b>Use the command "next" to move forward</b> or "prev" to move backwards.</p>
|
|
@ -1,7 +0,0 @@
|
|||
Step 1
|
||||
hey look we made it to step 1!
|
||||
|
||||
here are more things to do
|
||||
talk to a frog, smell a flower
|
||||
stare at the sky
|
||||
and try typing 'inspec exec examples/profile'
|
|
@ -1 +0,0 @@
|
|||
whoa there! that's all the steps we got! go experiment @ 'https://github.com/chef/inspec'
|
|
@ -0,0 +1,5 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m=> [31m[1;31m"[0m[31mDarwin vjeffrey01 15.6.0 Darwin Kernel Version 15.6.0: Mon Aug 29 20:21:34 PDT 2016; root:xnu-3248.60.11~1/RELEASE_X86_64 x86_64[1;35m\n[0m[31m[1;31m"[0m[31m[0m
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,8 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m[0;32minspec> [0m [0;32minspec> [0m [0;32minspec> [0m [0;32minspec> [0m [0;32minspec> [0m [0;32minspec> [0m [31m ✖ id: File /root mode should cmp "0750" (wrong number of arguments (1 for 0))[0m
|
||||
|
||||
|
||||
Summary: [32m0 successful[0m, [31m1 failures[0m, [37m0 skipped[0m
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,10 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m[0;32minspec> [0m [0;32minspec> [0m [0;32minspec> [0m
|
||||
File /root
|
||||
[31m ✖ should exist
|
||||
expected File /root to exist[0m
|
||||
|
||||
Summary: [32m0 successful[0m, [31m2 failures[0m, [37m0 skipped[0m
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,5 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m=> [1;36mnil[0m
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,27 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m[1mName:[0m command
|
||||
|
||||
[1mDescription:[0m
|
||||
|
||||
Use the command InSpec audit resource to test an arbitrary command that is run on the system.
|
||||
|
||||
[1mExample:[0m
|
||||
|
||||
describe command('ls -al /') do
|
||||
its('stdout') { should match /bin/ }
|
||||
its('stderr') { should eq '' }
|
||||
its('exit_status') { should eq 0 }
|
||||
end
|
||||
command('ls -al /').exist? will return false. Existence of command should be checked this way.
|
||||
describe command('ls') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
|
||||
[1mWeb Reference:[0m
|
||||
|
||||
https://github.com/chef/inspec/blob/master/docs/resources.rst#command
|
||||
|
||||
[0;32minspec> [0m
|
26
www/tutorial/app/responses/echo_help_file_inspec_shell.txt
Normal file
26
www/tutorial/app/responses/echo_help_file_inspec_shell.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m[1mName:[0m file
|
||||
|
||||
[1mDescription:[0m
|
||||
|
||||
Use the file InSpec audit resource to test all system file types, including files, directories, symbolic links, named pipes, sockets, character devices, block devices, and doors.
|
||||
|
||||
[1mExample:[0m
|
||||
|
||||
describe file('path') do
|
||||
it { should exist }
|
||||
it { should be_file }
|
||||
it { should be_readable }
|
||||
it { should be_writable }
|
||||
it { should be_owned_by 'root' }
|
||||
its('mode') { should cmp '0644' }
|
||||
end
|
||||
|
||||
|
||||
[1mWeb Reference:[0m
|
||||
|
||||
https://github.com/chef/inspec/blob/master/docs/resources.rst#file
|
||||
|
||||
[0;32minspec> [0m
|
23
www/tutorial/app/responses/echo_help_inspec_shell.txt
Normal file
23
www/tutorial/app/responses/echo_help_inspec_shell.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m
|
||||
Available commands:
|
||||
|
||||
`[resource]` - run resource on target machine
|
||||
`help resources` - show all available resources that can be used as commands
|
||||
`help [resource]` - information about a specific resource
|
||||
`exit` - exit the InSpec shell
|
||||
|
||||
You can use resources in this environment to test the target machine. For example:
|
||||
|
||||
command('uname -a').stdout
|
||||
file('/proc/cpuinfo').content => "value",
|
||||
|
||||
You are currently running on:
|
||||
|
||||
OS platform: [1mmac_os_x[0m
|
||||
OS family: [1mdarwin[0m
|
||||
OS release: [1m10.11.6[0m
|
||||
|
||||
[0;32minspec> [0m
|
27
www/tutorial/app/responses/echo_help_os_inspec_shell.txt
Normal file
27
www/tutorial/app/responses/echo_help_os_inspec_shell.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m[1mName:[0m os
|
||||
|
||||
[1mDescription:[0m
|
||||
|
||||
Use the os InSpec audit resource to test the platform on which the system is running.
|
||||
|
||||
[1mExample:[0m
|
||||
|
||||
describe os.family do
|
||||
it { should eq 'redhat' }
|
||||
end
|
||||
describe os.redhat? do
|
||||
it { should eq true }
|
||||
end
|
||||
describe os.linux? do
|
||||
it { should eq true }
|
||||
end
|
||||
|
||||
|
||||
[1mWeb Reference:[0m
|
||||
|
||||
https://github.com/chef/inspec/blob/master/docs/resources.rst#os
|
||||
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,5 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0mapache apache_conf apt ppa audit_policy auditd_conf auditd_rules command bash file bond bridge directory etc_group gem group grub_conf host iis_site inetd_conf interface iptables json kernel_module kernel_parameter linux_kernel_parameter limits_conf login_defs mount mssql_session mysql mysql_conf mysql_session npm ntp_conf oneget os os_env package parse_config parse_config_file passwd pip port postgres postgres_conf postgres_session powershell script processes registry_key windows_registry_key security_policy service systemd_service upstart_service sysv_service bsd_service launchd_service runit_service shadow ssl ssh_config sshd_config sys_info users user vbscript windows_feature xinetd_conf wmi yum yumrepo yaml csv ini
|
||||
[0;32minspec> [0m
|
|
@ -0,0 +1,10 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m=> {[31m[1;31m"[0m[31mprotocol[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31m2[1;31m"[0m[31m[0m],
|
||||
[31m[1;31m"[0m[31msyslogfacility[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31mAUTHPRIV[1;31m"[0m[31m[0m],
|
||||
[31m[1;31m"[0m[31mauthorizedkeysfile[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31m.ssh/authorized_keys[1;31m"[0m[31m[0m],
|
||||
[31m[1;31m"[0m[31museprivilegeseparation[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31msandbox[1;31m"[0m[31m[0m],
|
||||
[31m[1;31m"[0m[31macceptenv[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31mLANG LC_*[1;31m"[0m[31m[0m],
|
||||
[31m[1;31m"[0m[31msubsystem[1;31m"[0m[31m[0m=>[[31m[1;31m"[0m[31msftp[1;35m\t[0m[31m/usr/libexec/sftp-server[1;31m"[0m[31m[0m]}
|
||||
[0;32minspec> [0m
|
|
@ -1,20 +1,19 @@
|
|||
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 detect # detect the target OS
|
||||
inspec env # Output shell-appropriate completion co...
|
||||
inspec exec PATHS # run all test files at the specified PATH.
|
||||
inspec help [COMMAND] # Describe available commands or one spe...
|
||||
inspec init TEMPLATE ... # Scaffolds a new project
|
||||
inspec json PATH # read all tests in PATH and generate a ...
|
||||
inspec shell # open an interactive debugging shell
|
||||
inspec supermarket SUBCOMMAND ... # Supermarket commands
|
||||
inspec vendor # Download all dependencies and generate...
|
||||
inspec version # prints the version of this tool
|
||||
|
||||
Options:
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
||||
|
||||
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 detect # detect the target OS
|
||||
inspec env # Output shell-appropriate completion co...
|
||||
inspec exec PATHS # run all test files at the specified PATH.
|
||||
inspec help [COMMAND] # Describe available commands or one spe...
|
||||
inspec init TEMPLATE ... # Scaffolds a new project
|
||||
inspec json PATH # read all tests in PATH and generate a ...
|
||||
inspec shell # open an interactive debugging shell
|
||||
inspec supermarket SUBCOMMAND ... # Supermarket commands
|
||||
inspec vendor # Download all dependencies and generate...
|
||||
inspec version # prints the version of this tool
|
||||
|
||||
Options:
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
|
@ -0,0 +1,5 @@
|
|||
I, [2016-09-11T18:48:39.514660 #65769] INFO -- : Checking profile in examples/profile
|
||||
I, [2016-09-11T18:48:39.514820 #65769] INFO -- : Metadata OK.
|
||||
I, [2016-09-11T18:48:39.532230 #65769] INFO -- : Found 4 controls.
|
||||
I, [2016-09-11T18:48:39.532272 #65769] INFO -- : Control definitions OK.
|
||||
I, [2016-09-11T18:48:39.532442 #65769] INFO -- : Archive /Users/vjeffrey/code/compliance/inspec/profile.tar.gz exists already. Use --overwrite.
|
|
@ -0,0 +1,7 @@
|
|||
Location: [0;36mexamples/profile[0m
|
||||
Profile: [0;36mprofile[0m
|
||||
Controls: [0;36m4[0m
|
||||
Timestamp: [0;36m2016-09-11T18:48:28-04:00[0m
|
||||
Valid: [0;36mtrue[0m
|
||||
|
||||
No errors or warnings
|
7
www/tutorial/app/responses/inspec_detect.txt
Normal file
7
www/tutorial/app/responses/inspec_detect.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
== Operating System Details
|
||||
|
||||
Name: [0;36mmac_os_x[0m
|
||||
Family: [0;36mdarwin[0m
|
||||
Release: [0;36m10.11.6[0m
|
||||
Arch: [0;36mx86_64[0m
|
1
www/tutorial/app/responses/inspec_detect_format_json.txt
Normal file
1
www/tutorial/app/responses/inspec_detect_format_json.txt
Normal file
|
@ -0,0 +1 @@
|
|||
{"name":"mac_os_x","family":"darwin","release":"10.11.6","arch":"x86_64"}
|
110
www/tutorial/app/responses/inspec_env.txt
Normal file
110
www/tutorial/app/responses/inspec_env.txt
Normal file
|
@ -0,0 +1,110 @@
|
|||
function _inspec() {
|
||||
local curcontext="$curcontext" state line
|
||||
typeset -A opt_args
|
||||
|
||||
local -a _top_level_commands _compliance_commands _init_commands _supermarket_commands
|
||||
|
||||
_top_level_commands=(
|
||||
"help:Describe\ available\ commands\ or\ one\ specific\ command"
|
||||
"json:read\ all\ tests\ in\ PATH\ and\ generate\ a\ JSON\ summary"
|
||||
"check:verify\ all\ tests\ at\ the\ specified\ PATH"
|
||||
"vendor:Download\ all\ dependencies\ and\ generate\ a\ lockfile"
|
||||
"archive:archive\ a\ profile\ to\ tar.gz\ \(default\)\ or\ zip"
|
||||
"exec:run\ all\ test\ files\ at\ the\ specified\ PATH."
|
||||
"detect:detect\ the\ target\ OS"
|
||||
"shell:open\ an\ interactive\ debugging\ shell"
|
||||
"env:Output\ shell-appropriate\ completion\ configuration"
|
||||
"version:prints\ the\ version\ of\ this\ tool"
|
||||
"compliance:Chef\ Compliance\ commands"
|
||||
"init:Scaffolds\ a\ new\ project"
|
||||
"supermarket:Supermarket\ commands"
|
||||
)
|
||||
|
||||
_compliance_commands=(
|
||||
"help:Describe\ subcommands\ or\ one\ specific\ subcommand"
|
||||
"login:Log\ in\ to\ a\ Chef\ Compliance\ SERVER"
|
||||
"profiles:list\ all\ available\ profiles\ in\ Chef\ Compliance"
|
||||
"exec:executes\ a\ Chef\ Compliance\ profile"
|
||||
"upload:uploads\ a\ local\ profile\ to\ Chef\ Compliance"
|
||||
"version:displays\ the\ version\ of\ the\ Chef\ Compliance\ server"
|
||||
"logout:user\ logout\ from\ Chef\ Compliance"
|
||||
)
|
||||
|
||||
_init_commands=(
|
||||
"help:Describe\ subcommands\ or\ one\ specific\ subcommand"
|
||||
"profile:Create\ a\ new\ profile"
|
||||
)
|
||||
|
||||
_supermarket_commands=(
|
||||
"help:Describe\ subcommands\ or\ one\ specific\ subcommand"
|
||||
"profiles:list\ all\ available\ profiles\ in\ Chef\ Supermarket"
|
||||
"exec:execute\ a\ Supermarket\ profile"
|
||||
"info:display\ Supermarket\ profile\ details"
|
||||
)
|
||||
|
||||
_arguments '1:::->toplevel' && return 0
|
||||
_arguments '2:::->subcommand' && return 0
|
||||
_arguments '3:::->subsubcommand' && return 0
|
||||
|
||||
#
|
||||
# Are you thinking? "Jeez, whoever wrote this really doesn't get
|
||||
# zsh's completion system?" If so, you are correct. However, I
|
||||
# have goodnews! Pull requests are accepted!
|
||||
#
|
||||
case $state in
|
||||
toplevel)
|
||||
_describe -t commands "InSpec subcommands" _top_level_commands
|
||||
;;
|
||||
subcommand)
|
||||
case "$words[2]" in
|
||||
archive|check|exec|json)
|
||||
_alternative 'files:filenames:_files'
|
||||
;;
|
||||
help)
|
||||
_describe -t commands "InSpec subcommands" _top_level_commands
|
||||
;;
|
||||
compliance)
|
||||
_describe -t compliance_commands "InSpec compliance subcommands" _compliance_commands
|
||||
;;
|
||||
init)
|
||||
_describe -t init_commands "InSpec init subcommands" _init_commands
|
||||
;;
|
||||
supermarket)
|
||||
_describe -t supermarket_commands "InSpec supermarket subcommands" _supermarket_commands
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
subsubcommand)
|
||||
case "$words[2]-$words[3]" in
|
||||
compliance-upload)
|
||||
_alternative 'files:filenames:_files'
|
||||
;;
|
||||
compliance-help)
|
||||
_describe -t compliance_commands "InSpec compliance subcommands" _compliance_commands
|
||||
;;
|
||||
init-help)
|
||||
_describe -t init_commands "InSpec init subcommands" _init_commands
|
||||
;;
|
||||
supermarket-help)
|
||||
_describe -t supermarket_commands "InSpec supermarket subcommands" _supermarket_commands
|
||||
;;
|
||||
esac
|
||||
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
compdef _inspec inspec
|
||||
#
|
||||
# The shell zsh was auto-detected. If this is incorrect, please
|
||||
# specify a shell explicitly by running:
|
||||
#
|
||||
# inspec env SHELLNAME
|
||||
#
|
||||
# Currently supported shells are: bash, zsh
|
||||
#
|
||||
# To use this, eval it in your shell
|
||||
#
|
||||
# eval "$(inspec env zsh)"
|
||||
#
|
||||
#
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
Target: local://
|
||||
|
||||
[32m ✔ tmp-1.0: Create /tmp directory[0m
|
||||
[32m File /tmp should be directory[0m
|
||||
|
||||
File /tmp
|
||||
[32m ✔ should be directory[0m
|
||||
|
||||
Summary: [32m2 successful[0m, [31m0 failures[0m, [37m0 skipped[0m
|
|
@ -0,0 +1,16 @@
|
|||
[37m ○ gordon-1.0: Verify the version number of Gordon (1 skipped)[0m
|
||||
[37m ○ Can't find file "/tmp/gordon/config.yaml"[0m
|
||||
[32m ✔ File content should match nil[0m
|
||||
[32m ✔ ssh-1: Allow only SSH Protocol 2[0m
|
||||
[32m ✔ File /bin/sh should be owned by "root"[0m
|
||||
|
||||
File /tmp
|
||||
[32m ✔ should be directory[0m
|
||||
|
||||
|
||||
Profile: InSpec example inheritance (inheritance)
|
||||
Version: 1.0.0
|
||||
Target: local://
|
||||
|
||||
|
||||
Summary: [32m3 successful[0m, [31m0 failures[0m, [37m1 skipped[0m
|
17
www/tutorial/app/responses/inspec_exec_examples_profile.txt
Normal file
17
www/tutorial/app/responses/inspec_exec_examples_profile.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
Profile: InSpec Example Profile (profile)
|
||||
Version: 1.0.0
|
||||
Target: local://
|
||||
|
||||
[32m ✔ tmp-1.0: Create /tmp directory[0m
|
||||
[32m ✔ File /tmp should be directory[0m
|
||||
[37m ○ gordon-1.0: Verify the version number of Gordon (1 skipped)[0m
|
||||
[37m ○ Can't find file "/tmp/gordon/config.yaml"[0m
|
||||
[32m ✔ File content should match nil[0m
|
||||
[32m ✔ ssh-1: Allow only SSH Protocol 2[0m
|
||||
[32m ✔ File /bin/sh should be owned by "root"[0m
|
||||
|
||||
File /tmp
|
||||
[32m ✔ should be directory[0m
|
||||
|
||||
Summary: [32m4 successful[0m, [31m0 failures[0m, [37m1 skipped[0m
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,18 @@
|
|||
|
||||
Profile: InSpec Profile (failures)
|
||||
Version: 0.1.0
|
||||
Target: local://
|
||||
|
||||
[31;1m ✖ tmp-1.0: Create /tmp directory (1 failed)[0m
|
||||
[31;1m ✖ expected `File /tmp.directory?` to return false, got true[0m
|
||||
[32m ✔ File /tmp should be directory[0m
|
||||
|
||||
File /tmp
|
||||
[32m ✔ should be directory[0m
|
||||
[31m ✖ undefined method `should_nota' for #<RSpec::ExampleGroups::FileTmp_2:0x007fd2fc4f8e50>[0m
|
||||
File /tmp
|
||||
[31m ✖ should not be directory
|
||||
expected `File /tmp.directory?` to return false, got true[0m
|
||||
[32m ✔ should be directory[0m
|
||||
|
||||
Summary: [32m3 successful[0m, [31m3 failures[0m, [37m0 skipped[0m
|
19
www/tutorial/app/responses/inspec_help.txt
Normal file
19
www/tutorial/app/responses/inspec_help.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
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 detect # detect the target OS
|
||||
inspec env # Output shell-appropriate completion co...
|
||||
inspec exec PATHS # run all test files at the specified PATH.
|
||||
inspec help [COMMAND] # Describe available commands or one spe...
|
||||
inspec init TEMPLATE ... # Scaffolds a new project
|
||||
inspec json PATH # read all tests in PATH and generate a ...
|
||||
inspec shell # open an interactive debugging shell
|
||||
inspec supermarket SUBCOMMAND ... # Supermarket commands
|
||||
inspec vendor # Download all dependencies and generate...
|
||||
inspec version # prints the version of this tool
|
||||
|
||||
Options:
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
26
www/tutorial/app/responses/inspec_help_detect.txt
Normal file
26
www/tutorial/app/responses/inspec_help_detect.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
Usage:
|
||||
inspec detect
|
||||
|
||||
Options:
|
||||
t, [--target=TARGET] # Simple targeting option using URIs, e.g. ssh://user:pass@host:port
|
||||
b, [--backend=BACKEND] # Choose a backend: local, ssh, winrm, docker.
|
||||
[--host=HOST] # Specify a remote host which is tested.
|
||||
p, [--port=N] # Specify the login port for a remote scan.
|
||||
[--user=USER] # The login user for a remote scan.
|
||||
[--password=PASSWORD] # Login password for a remote scan, if required.
|
||||
i, [--key-files=one two three] # Login key or certificate file for a remote scan.
|
||||
[--path=PATH] # Login path to use when connecting to the target (WinRM).
|
||||
[--sudo], [--no-sudo] # Run scans with sudo. Only activates on Unix and non-root user.
|
||||
[--sudo-password=SUDO_PASSWORD] # Specify a sudo password, if it is required.
|
||||
[--sudo-options=SUDO_OPTIONS] # Additional sudo options for a remote scan.
|
||||
[--sudo-command=SUDO_COMMAND] # Alternate command for sudo.
|
||||
[--ssl], [--no-ssl] # Use SSL for transport layer encryption (WinRM).
|
||||
[--self-signed], [--no-self-signed] # Allow remote scans with self-signed certificates (WinRM).
|
||||
[--json-config=JSON_CONFIG] # Read configuration from JSON file (`-` reads from stdin).
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--format=FORMAT]
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
||||
|
||||
detect the target OS
|
31
www/tutorial/app/responses/inspec_help_exec.txt
Normal file
31
www/tutorial/app/responses/inspec_help_exec.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
Usage:
|
||||
inspec exec PATHS
|
||||
|
||||
Options:
|
||||
t, [--target=TARGET] # Simple targeting option using URIs, e.g. ssh://user:pass@host:port
|
||||
b, [--backend=BACKEND] # Choose a backend: local, ssh, winrm, docker.
|
||||
[--host=HOST] # Specify a remote host which is tested.
|
||||
p, [--port=N] # Specify the login port for a remote scan.
|
||||
[--user=USER] # The login user for a remote scan.
|
||||
[--password=PASSWORD] # Login password for a remote scan, if required.
|
||||
i, [--key-files=one two three] # Login key or certificate file for a remote scan.
|
||||
[--path=PATH] # Login path to use when connecting to the target (WinRM).
|
||||
[--sudo], [--no-sudo] # Run scans with sudo. Only activates on Unix and non-root user.
|
||||
[--sudo-password=SUDO_PASSWORD] # Specify a sudo password, if it is required.
|
||||
[--sudo-options=SUDO_OPTIONS] # Additional sudo options for a remote scan.
|
||||
[--sudo-command=SUDO_COMMAND] # Alternate command for sudo.
|
||||
[--ssl], [--no-ssl] # Use SSL for transport layer encryption (WinRM).
|
||||
[--self-signed], [--no-self-signed] # Allow remote scans with self-signed certificates (WinRM).
|
||||
[--json-config=JSON_CONFIG] # Read configuration from JSON file (`-` reads from stdin).
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--profiles-path=PROFILES_PATH] # Folder which contains referenced profiles.
|
||||
[--controls=one two three] # A list of controls to run. Ignore all other tests.
|
||||
[--format=FORMAT] # Which formatter to use: cli, progress, documentation, json, json-min
|
||||
[--color], [--no-color] # Use colors in output.
|
||||
# Default: true
|
||||
[--attrs=one two three] # Load attributes file (experimental)
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
||||
|
||||
run all test files at the specified PATH.
|
9
www/tutorial/app/responses/inspec_help_version.txt
Normal file
9
www/tutorial/app/responses/inspec_help_version.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
Usage:
|
||||
inspec version
|
||||
|
||||
Options:
|
||||
l, [--log-level=LOG_LEVEL] # Set the log level: info (default), debug, warn, error
|
||||
[--log-location=LOG_LOCATION] # Location to send diagnostic log messages to. (default: STDOUT or STDERR)
|
||||
[--diagnose], [--no-diagnose] # Show diagnostics (versions, configurations)
|
||||
|
||||
prints the version of this tool
|
|
@ -0,0 +1 @@
|
|||
{"name":"profile","title":"InSpec Example Profile","maintainer":"Chef Software, Inc.","copyright":"Chef Software, Inc.","copyright_email":"support@chef.io","license":"Apache 2 license","summary":"Demonstrates the use of InSpec Compliance Profile","version":"1.0.0","supports":[{"os-family":"unix"}],"controls":{"tmp-1.0":{"title":"Create /tmp directory","desc":"An optional description...","impact":0.7,"refs":[{"url":"http://...","ref":"Document A-12"}],"tags":{"data":"temp data","security":null},"code":"control \"tmp-1.0\" do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title \"Create /tmp directory\" # A human-readable title\n desc \"An optional description...\" # Describe why this is needed\n tag data: \"temp data\" # A tag allows you to associate key information\n tag \"security\" # to the test\n ref \"Document A-12\", url: 'http://...' # Additional references\n\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n","source_location":{"ref":"examples/profile/controls/example.rb","line":8}},"(generated from example.rb:22 3dea2a8293410b58623a60f2e924ba9a)":{"title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":" rule = rule_class.new(id, profile_id, {}) do\n res = describe(*args, &block)\n end\n","source_location":{"ref":"/Users/vjeffrey/code/compliance/inspec/lib/inspec/control_eval_context.rb","line":87}},"gordon-1.0":{"title":"Verify the version number of Gordon","desc":"An optional description...","impact":0.7,"refs":[{"uri":"http://...","ref":"Gordon Requirements 1.0"}],"tags":{"gordon":null},"code":"control 'gordon-1.0' do\n impact 0.7\n title 'Verify the version number of Gordon'\n desc 'An optional description...'\n tag 'gordon'\n ref 'Gordon Requirements 1.0', uri: 'http://...'\n\n # Test using the custom gordon_config Inspec resource\n # Find the resource content here: ../libraries/\n describe gordon_config do\n it { should exist }\n its('version') { should eq('1.0') }\n its('file_size') { should <= 20 }\n its('comma_count') { should eq 0 }\n end\n\n # Test the version again to showcase variables\n g = gordon_config\n g_path = g.file_path\n g_version = g.version\n describe file(g_path) do\n its('content') { should match g_version }\n end\nend\n","source_location":{"ref":"examples/profile/controls/gordon.rb","line":14}},"ssh-1":{"title":"Allow only SSH Protocol 2","desc":"Only SSH protocol version 2 connections should be permitted. The default setting in /etc/ssh/sshd_config is correct, and can be verified by ensuring that the following line appears: Protocol 2","impact":1.0,"refs":[{"url":"https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf","ref":"NSA-RH6-STIG - Section 3.5.2.1"},{"url":"http://iasecontent.disa.mil/stigs/zip/Jan2016/U_RedHat_6_V1R10_STIG.zip","ref":"DISA-RHEL6-SG - Section 9.2.1"},{"ref":"http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html"}],"tags":{"production":null,"development":null,"ssh":null,"sshd":null,"openssh-server":null,"cce":"CCE-27072-8","disa":"RHEL-06-000227","nist":"IA-5(1)","cci":"CCI-001436","remediation":"https://supermarket.chef.io/cookbooks/ssh-hardening"},"code":"control 'ssh-1' do\n impact 1.0\n\n title 'Allow only SSH Protocol 2'\n desc 'Only SSH protocol version 2 connections should be permitted.\n The default setting in /etc/ssh/sshd_config is correct, and can be\n verified by ensuring that the following line appears: Protocol 2'\n\n tag 'production','development'\n tag 'ssh','sshd','openssh-server'\n\n tag cce: 'CCE-27072-8'\n tag disa: 'RHEL-06-000227'\n\n tag nist: 'AC-3(10).i'\n tag nist: 'IA-5(1)'\n\n tag cci: 'CCI-000776'\n tag cci: 'CCI-000774'\n tag cci: 'CCI-001436'\n\n tag remediation: 'stig_rhel6/recipes/sshd-config.rb'\n tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'\n\n ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'\n ref 'DISA-RHEL6-SG - Section 9.2.1', url: 'http://iasecontent.disa.mil/stigs/zip/Jan2016/U_RedHat_6_V1R10_STIG.zip'\n ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'\n\n describe file('/bin/sh') do\n it { should be_owned_by 'root' }\n end\nend\n","source_location":{"ref":"examples/profile/controls/meta.rb","line":3}}},"groups":{"controls/example.rb":{"title":"/tmp profile","controls":["tmp-1.0","(generated from example.rb:22 3dea2a8293410b58623a60f2e924ba9a)"]},"controls/gordon.rb":{"title":"Gordon Config Checks","controls":["gordon-1.0"]},"controls/meta.rb":{"title":"SSH Server Configuration","controls":["ssh-1"]}},"attributes":[]}
|
4
www/tutorial/app/responses/inspec_shell.txt
Normal file
4
www/tutorial/app/responses/inspec_shell.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Welcome to the interactive InSpec Shell
|
||||
To find out how to use it, type: [1mhelp[0m
|
||||
|
||||
[0G[?1034h[0;32minspec> [0m
|
1
www/tutorial/app/responses/inspec_shell_c_os_params_.txt
Normal file
1
www/tutorial/app/responses/inspec_shell_c_os_params_.txt
Normal file
|
@ -0,0 +1 @@
|
|||
{:name=>"mac_os_x", :family=>"darwin", :release=>"10.11.6", :arch=>"x86_64"}
|
|
@ -0,0 +1 @@
|
|||
2
|
|
@ -1 +1 @@
|
|||
0.32.0
|
||||
0.33.2
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
README.md
|
|
@ -1 +0,0 @@
|
|||
anonymous-web-user/inspec
|
|
@ -1 +0,0 @@
|
|||
anonymous-web-user/inspec-shell
|
|
@ -1,6 +1,6 @@
|
|||
#terminal-container {
|
||||
width: 1200px;
|
||||
height: 500px;
|
||||
height: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 2px;
|
||||
font-size: 16px;
|
||||
|
@ -17,10 +17,14 @@
|
|||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
/* the black color used by xterm terminal isn't quite black
|
||||
so we're deep assigning here to make sure that 0 is marked as black */
|
||||
:host /deep/ .xterm-color-0 {
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* the blue color that xterm terminal uses doesn't show well
|
||||
on the black background so we're deep assigning to make 6 a lightskyblu*/
|
||||
:host /deep/ .xterm-color-6 {
|
||||
color: lightskyblue;
|
||||
}
|
|
@ -1 +1 @@
|
|||
<div (keyup)="onKey($event)" id="terminal-container"></div>
|
||||
<div (keyup)="onKey($event)" (keydown)="handleDelete($event)" id="terminal-container"></div>
|
||||
|
|
|
@ -8,15 +8,17 @@ declare var Terminal: any;
|
|||
})
|
||||
export class XtermTerminalComponent implements OnInit {
|
||||
@Input() response: string;
|
||||
@Input() responsesArray: any;
|
||||
@Input() shell: string;
|
||||
@Output() command: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
// handle up/down arrow functionality
|
||||
previousCommands: any = [];
|
||||
last: number;
|
||||
currentResponse: string;
|
||||
shellStatus: string;
|
||||
buffer: string = '';
|
||||
poppedCommands: any = [];
|
||||
last: number;
|
||||
|
||||
// handle user input
|
||||
buffer: string = ''; // the buffer is our string of user input
|
||||
blockCmd: string = ''; // handle describe and control blocks
|
||||
|
||||
// xterm variables
|
||||
terminalContainer: any;
|
||||
|
@ -24,24 +26,24 @@ export class XtermTerminalComponent implements OnInit {
|
|||
optionElements: any;
|
||||
cols: string;
|
||||
rows: string;
|
||||
shellprompt: string = ' [36m$ ';
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit() {
|
||||
// set up Xterm terminal (https://github.com/sourcelair/xterm.js)
|
||||
this.terminalContainer = document.getElementById('terminal-container');
|
||||
this.cols = '70';
|
||||
this.rows = '70';
|
||||
this.createTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
// watch for changes on the value of response and call printResponse
|
||||
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
|
||||
if (changes['response'] && this.term) {
|
||||
this.currentResponse = changes['response'].currentValue;
|
||||
this.term.writeln(this.currentResponse);
|
||||
this.setPrompt();
|
||||
let currentResponse = changes['response'].currentValue;
|
||||
this.printResponse(currentResponse);
|
||||
}
|
||||
}
|
||||
|
||||
// create Xterm terminal (https://github.com/sourcelair/xterm.js)
|
||||
createTerminal() {
|
||||
while (this.terminalContainer.children.length) {
|
||||
this.terminalContainer.removeChild(this.terminalContainer.children[0]);
|
||||
|
@ -62,6 +64,7 @@ export class XtermTerminalComponent implements OnInit {
|
|||
this.runFakeTerminal()
|
||||
}
|
||||
|
||||
// more Xterm terminal stuff. we're faking it. faking it can be a good thing ;)
|
||||
runFakeTerminal() {
|
||||
if (this.term._initialized) {
|
||||
return;
|
||||
|
@ -70,85 +73,155 @@ export class XtermTerminalComponent implements OnInit {
|
|||
this.setPrompt();
|
||||
}
|
||||
|
||||
setPrompt() {
|
||||
this.buffer = '';
|
||||
if (this.shell === 'inspec-shell') {
|
||||
this.term.write(" [32m" + '\r\ninspec> ');
|
||||
// if the response matches the special message we send when the user
|
||||
// has entered 'next' or 'prev' (to navigate through the demo)
|
||||
// then no need to print the response, just set the prompt. otherwise,
|
||||
// print response and set prompt
|
||||
printResponse(response) {
|
||||
if (response.match(/.30mnext|.30mprev/)) {
|
||||
this.deleteCharacters();
|
||||
if (this.term.x < 3) {
|
||||
// this check prevents us from printing a second prompt on the line
|
||||
// when the arrow in the nav is used to move forward
|
||||
this.setPrompt();
|
||||
}
|
||||
} else {
|
||||
this.term.write(this.shellprompt);
|
||||
this.term.writeln(response);
|
||||
this.setPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
// the value of shell is taken as an input. the default
|
||||
// shellprompt is displayed unless shell is set to 'inspec-shell'
|
||||
setPrompt() {
|
||||
this.buffer = '';
|
||||
if (this.shell === 'inspec-shell') {
|
||||
if (this.blockCmd != '') {
|
||||
this.term.write(' [32minspec>*'); // green inspec shell prompt with * to denote multi-line command
|
||||
} else {
|
||||
this.term.write(' [32minspec> '); // green inspec shell prompt
|
||||
}
|
||||
} else {
|
||||
this.term.write(' [36m$ '); // blue regular shell prompt
|
||||
}
|
||||
}
|
||||
|
||||
// delete everything on the line
|
||||
deleteCharacters() {
|
||||
// don't delete the prompt
|
||||
let letters = this.term.x - 3;
|
||||
for (var i = 0; i < letters; i++) {
|
||||
this.term.write('\b \b');
|
||||
}
|
||||
}
|
||||
|
||||
// keydown calls handleDelete to check if the user is holding down the backpace key
|
||||
// TODO: make this work! the backspace event isn't coming in for some reason :(
|
||||
handleDelete(ev) {
|
||||
if (ev.keyCode == 8) {
|
||||
this.deleteCharacters();
|
||||
}
|
||||
}
|
||||
|
||||
// handle describe and control blocks. if the command entered matches the
|
||||
// syntax we would generally expect in a control/describe block, then we
|
||||
// wait to have the whole string command (as marked by 'end' for a simple describe
|
||||
// block and end end for a control block) and emit that
|
||||
handleBlockCommand(buffer) {
|
||||
this.blockCmd += buffer + '';
|
||||
if (this.blockCmd.match(/^control/)) {
|
||||
if (this.blockCmd.match(/end.*end.*/)) {
|
||||
this.command.emit(this.blockCmd);
|
||||
this.blockCmd = '';
|
||||
} else {
|
||||
this.setPrompt();
|
||||
}
|
||||
} else {
|
||||
if (buffer.match(/^end$/)) {
|
||||
this.command.emit(this.blockCmd);
|
||||
this.blockCmd = '';
|
||||
} else {
|
||||
this.setPrompt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// onKey will check if the character is printable (on keyup) and add it to the buffer. if the enter key is hit
|
||||
// the value of the buffer is emitted as 'command'. onKey also supports proper backspace handling and
|
||||
// the ability to up-arrow through previous commands/down arrow back through them.
|
||||
onKey(ev) {
|
||||
var shell = null
|
||||
// determine if the character is a printable one
|
||||
var printable = ['Alt', 'Control', 'Meta', 'Shift', 'CapsLock', 'Tab', 'Escape', 'ArrowLeft', 'ArrowRight'].indexOf(ev.key) == -1
|
||||
|
||||
// on enter, save command to array and send current value of buffer
|
||||
// to parent component (app). if the command is the same as the previous command
|
||||
// entered, we just diplay the currentResponse. the reason this is being done here and
|
||||
// not in the app component is because the ngOnChanges that tracks the value of the
|
||||
// emitted event won't recognize that there has been a change if it is the same.
|
||||
// to parent component (app)
|
||||
if (ev.keyCode == 13) {
|
||||
this.previousCommands.push(this.buffer);
|
||||
this.term.write('\r\n');
|
||||
if (this.previousCommands.length > 1) {
|
||||
this.last = this.previousCommands.length - 2
|
||||
}
|
||||
if (this.buffer === this.previousCommands[this.last]) {
|
||||
// if the command is next or last, we still want to emit
|
||||
// the value, since the parent component is responsible
|
||||
// for interpreting that value and displaying the correct instructions
|
||||
if (this.buffer.match(/^next\s*/) || this.buffer.match(/^prev\s*/)) {
|
||||
this.command.emit(this.buffer);
|
||||
} else {
|
||||
this.term.writeln(this.currentResponse);
|
||||
this.setPrompt();
|
||||
if ((this.buffer === 'clear') || (this.buffer === 'clr')) {
|
||||
this.createTerminal();
|
||||
} else {
|
||||
this.previousCommands.push(this.buffer);
|
||||
this.term.write('\r\n');
|
||||
if (this.shell === 'inspec-shell') {
|
||||
// if the command entered matches any of the typical describe and
|
||||
// control blocks, then we call handleBlockCommand to not emit the
|
||||
// value until we have the whole multi-line command
|
||||
if (this.buffer.match(/^describe.*|^it.*|^end$|^impact.*|^title.*|^control.*/)) {
|
||||
this.handleBlockCommand(this.buffer);
|
||||
}
|
||||
} else {
|
||||
this.command.emit(this.buffer);
|
||||
}
|
||||
else {
|
||||
this.command.emit(this.buffer);
|
||||
}
|
||||
}
|
||||
// on backspace, pop characters from buffer
|
||||
else if (ev.keyCode == 8) {
|
||||
if (this.term.x > 2) {
|
||||
this.buffer = this.buffer.substr(0, this.buffer.length-1);
|
||||
this.term.write('\b \b');
|
||||
// if inspec shell is being used, this needs to be set to 9 to account for the extra letters
|
||||
if (this.shell === 'inspec-shell') {
|
||||
if (this.term.x > 9) {
|
||||
this.buffer = this.buffer.substr(0, this.buffer.length-1);
|
||||
this.term.write('\b \b');
|
||||
}
|
||||
} else {
|
||||
// setting the value here to 3 ensures that we don't delete the promp '$' or the space after it
|
||||
if (this.term.x > 3) {
|
||||
this.buffer = this.buffer.substr(0, this.buffer.length-1);
|
||||
this.term.write('\b \b');
|
||||
}
|
||||
}
|
||||
}
|
||||
// on up arrow, delete anything on line and print previous command
|
||||
// on up arrow, delete anything on line, print previous command
|
||||
// and push last to poppedCommands
|
||||
else if (ev.keyCode === 38) {
|
||||
let last;
|
||||
this.buffer = '';
|
||||
if (this.previousCommands.length > 0) {
|
||||
last = this.previousCommands.pop();
|
||||
this.poppedCommands.push(last);
|
||||
} else {
|
||||
last = '';
|
||||
}
|
||||
let letters = this.term.x - 3;
|
||||
for (var i = 0; i < letters; i++) {
|
||||
this.term.write('\b \b');
|
||||
}
|
||||
this.deleteCharacters();
|
||||
this.buffer = last;
|
||||
this.term.write(last);
|
||||
}
|
||||
// on down arrow, delete anything on line and print from popped command
|
||||
// on down arrow, delete anything on line, print last item from poppedCommands
|
||||
// and push previous to previousCommands
|
||||
else if (ev.keyCode === 40) {
|
||||
let previous;
|
||||
this.buffer = '';
|
||||
if (this.poppedCommands.length > 0) {
|
||||
previous = this.poppedCommands.pop();
|
||||
this.previousCommands.push(previous);
|
||||
} else {
|
||||
previous = '';
|
||||
}
|
||||
let letters = this.term.x - 3;
|
||||
for (var i = 0; i < letters; i++) {
|
||||
this.term.write('\b \b');
|
||||
}
|
||||
this.deleteCharacters();
|
||||
this.buffer = previous;
|
||||
this.term.write(previous);
|
||||
}
|
||||
// write each character on prompt line
|
||||
// if the character is printable and none of the event key codes from above were matched
|
||||
// then we write the character on the prompt line and add the character to the buffer
|
||||
else if (printable) {
|
||||
this.term.write(ev.key);
|
||||
this.buffer += ev.key;
|
||||
|
|
1
www/tutorial/commands.json
Normal file
1
www/tutorial/commands.json
Normal file
|
@ -0,0 +1 @@
|
|||
[[{"inspec":"inspec.txt"}],[{"inspec help":"inspec_help.txt"}],[{"inspec help version":"inspec_help_version.txt"}],[{"inspec help detect":"inspec_help_detect.txt"}],[{"inspec help exec":"inspec_help_exec.txt"}],[{"inspec check examples/profile":"inspec_check_examples_profile.txt"}],[{"inspec exec examples/profile":"inspec_exec_examples_profile.txt"}],[{"inspec help exec":"inspec_help_exec.txt"}],[{"inspec detect":"inspec_detect.txt"}],[{"inspec shell -c 'os.params'":"inspec_shell_c_os_params_.txt"}],[{"inspec shell -c 'sshd_config.Protocol'":"inspec_shell_c_sshd_config_Protocol_.txt"}],[{"inspec shell":"inspec_shell.txt"}],[{"inspec version":"inspec_version.txt"}],[{"inspec detect --format json":"inspec_detect_format_json.txt"}],[{"inspec exec examples/profile --format json":"inspec_exec_examples_profile_format_json.txt"}],[{"inspec exec examples/profile --format json | jq":"inspec_exec_examples_profile_format_json_jq.txt"}],[{"inspec json examples/profile":"inspec_json_examples_profile.txt"}],[{"inspec archive examples/profile":"inspec_archive_examples_profile.txt"}],[{"inspec env":"inspec_env.txt"}],[{"inspec exec examples/inheritance":"inspec_exec_examples_inheritance.txt"}],[{"inspec exec test/unit/mock/profiles/failures":"inspec_exec_test_unit_mock_profiles_failures.txt"}],[{"echo help | inspec shell":"echo_help_inspec_shell.txt"}],[{"echo help\\ resources | inspec shell":"echo_help_resources_inspec_shell.txt"}],[{"echo help\\ file | inspec shell":"echo_help_file_inspec_shell.txt"}],[{"echo help\\ command | inspec shell":"echo_help_command_inspec_shell.txt"}],[{"echo help\\ os | inspec shell":"echo_help_os_inspec_shell.txt"}],[{"echo command\\(\\'uname\\ -a\\'\\).stdout | inspec shell":"echo_command_uname_a_stdout_inspec_shell.txt"}],[{"echo file\\(\\'/proc/cpuinfo\\'\\).owner | inspec shell":"echo_file_proc_cpuinfo_owner_inspec_shell.txt"}],[{"echo sshd_config.params | inspec shell":"echo_sshd_config_params_inspec_shell.txt"}],[{"echo describe\\ file\\(\\'/root\\'\\)\\ do'\n'\\ \\ it\\ \\{\\ should\\ exist\\ \\}'\n'\\ \\ its\\(\\'mode\\'\\)\\ \\{\\ should\\ cmp\\ \\'0750\\'\\}'\n'end | inspec shell":"echo_describe_file_root_do_it_should_exist_its_mode_should_cmp_0750_end_inspec_shell.txt"}],[{"echo control\\ \\\"id\\\"\\ do'\n'\\ \\ title\\ \\\"Check\\ permissions\\ on\\ /root\\!\\\"'\n'\\ \\ impact\\ 0.5'\n'\\ \\ describe\\ file\\(\\'/root\\'\\)\\ do'\n'\\ \\ \\ \\ its\\(\\'mode\\'\\)\\ \\{\\ should\\ cmp\\ \\'0750\\'\\}'\n'\\ \\ end'\n'end | inspec shell":"echo_control_id_do_title_Check_permissions_on_root_impact_0_5_describe_file_root_do_its_mode_should_cmp_0750_end_end_inspec_shell.txt"}]]
|
10
www/tutorial/commands.yml
Normal file
10
www/tutorial/commands.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
commands:
|
||||
- inspec version
|
||||
- inspec detect --format json
|
||||
- inspec exec examples/profile --format json
|
||||
- inspec exec examples/profile --format json | jq
|
||||
- inspec json examples/profile
|
||||
- inspec archive examples/profile
|
||||
- inspec env
|
||||
- inspec exec examples/inheritance
|
||||
- inspec exec test/unit/mock/profiles/failures
|
32
www/tutorial/config/webpack.config.js
Normal file
32
www/tutorial/config/webpack.config.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
module.exports = {
|
||||
entry: "./app/main.ts",
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "./dist/bundle.js",
|
||||
},
|
||||
|
||||
// Enable sourcemaps for debugging webpack's output.
|
||||
devtool: "source-map",
|
||||
|
||||
resolve: {
|
||||
// Add '.ts' and '.tsx' as resolvable extensions.
|
||||
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
|
||||
},
|
||||
|
||||
module: {
|
||||
loaders: [
|
||||
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
|
||||
{
|
||||
test: /\.tsx?$/, loader: "ts-loader"
|
||||
},
|
||||
{
|
||||
test: /\.css$/, loader: 'style!css',
|
||||
}
|
||||
],
|
||||
|
||||
preLoaders: [
|
||||
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
|
||||
{ test: /\.js$/, loader: "source-map-loader" }
|
||||
]
|
||||
},
|
||||
};
|
1
www/tutorial/extra_commands.json
Normal file
1
www/tutorial/extra_commands.json
Normal file
|
@ -0,0 +1 @@
|
|||
["inspec version","inspec detect --format json","inspec exec examples/profile --format json","inspec exec examples/profile --format json | jq","inspec json examples/profile","inspec archive examples/profile","inspec env","inspec exec examples/inheritance","inspec exec test/unit/mock/profiles/failures"]
|
|
@ -7,6 +7,7 @@
|
|||
<link rel="stylesheet" href="node_modules/xterm/src/xterm.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
|
||||
<!-- 1. Load libraries -->
|
||||
<script src="node_modules/shellwords/src/shellwords.coffee"></script>
|
||||
<!-- Polyfill(s) for older browsers -->
|
||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||
|
|
BIN
www/tutorial/inspec-logo.png
Normal file
BIN
www/tutorial/inspec-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
1
www/tutorial/instructions.json
Normal file
1
www/tutorial/instructions.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -23,6 +23,7 @@
|
|||
"core-js": "^2.4.0",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "5.0.0-beta.6",
|
||||
"shellwords": "^0.1.0",
|
||||
"systemjs": "0.19.27",
|
||||
"webpack": "^1.13.2",
|
||||
"webpack-dev-server": "^1.15.1",
|
||||
|
|
|
@ -2,18 +2,17 @@
|
|||
demos:
|
||||
- demo: 0:intro
|
||||
desc: |
|
||||
Welcome to the interactive InSpec demo. You will learn how to use the commandline and shell and get an introduction to all aspects of the language.
|
||||
Welcome to the interactive InSpec demo. You will learn how to use the command line and shell and get an introduction to all aspects of the language.
|
||||
|
||||
To navigate this demo, type `next` to move forward and `prev` to move back.
|
||||
Use `clear` to clear the terminal screen.
|
||||
- demo: 1:inspec-help
|
||||
desc: |
|
||||
InSpec is called via
|
||||
```
|
||||
inspec
|
||||
```
|
||||
Try it out!
|
||||
|
||||
You will see the help menu. You can also view it with
|
||||
Try it out! You will see the help menu. You can also view it with:
|
||||
```
|
||||
inspec help
|
||||
```
|
||||
|
@ -31,31 +30,31 @@ demos:
|
|||
The easiest subcommand is `inspec version`. It tells you which version of InSpec is running.
|
||||
- demo: 1:inspec-check
|
||||
desc: |
|
||||
The most frequent use of InSpec is to execute profiles. You can find the `example/profile` in the InSpec repository. Before executing it for the first time, let's verify if it is valid profile
|
||||
The most frequent use of InSpec is to execute profiles. You can find the `examples/profile` in the InSpec repository. Before executing it for the first time, let's verify if it is valid profile
|
||||
```
|
||||
inspec check example/profile
|
||||
inspec check examples/profile
|
||||
```
|
||||
This command is not only used for syntax testing and linting, but can also provide information on valid profiles including its version and control overview.
|
||||
- demo: 1:inspec-exec
|
||||
desc: |
|
||||
Let's try testing some profiles! To run the profile and test the local machine, type:
|
||||
```
|
||||
inspec exec example/profile
|
||||
inspec exec examples/profile
|
||||
```
|
||||
The result is shown in the report.
|
||||
- demo: 1:inspec-exec-ssh
|
||||
desc: |
|
||||
InSpec can also test your remote machines! Let's assume there is node `host.node` registered with SSH configured for user `bob` with a keyfile in the current directory (`bob.rsa`). You can run the same profile against this node via:
|
||||
```
|
||||
inspec exec example/profile -t ssh://bob@host.node -i bob.rsa
|
||||
inspec exec examples/profile -t ssh://bob@host.node -i bob.rsa
|
||||
```
|
||||
- demo: 1:inspec-exec-ssh-long
|
||||
desc: |
|
||||
The wonderful `-t` option (or `--target`) is a shorthand for specifying all fields separately:
|
||||
```
|
||||
inspec exec example/profile -b ssh --host host.node --user bob -i bob.rsa
|
||||
inspec exec examples/profile -b ssh --host host.node --user bob -i bob.rsa
|
||||
```
|
||||
For more options try
|
||||
For more options try:
|
||||
```
|
||||
inspec help exec
|
||||
```
|
||||
|
@ -63,19 +62,19 @@ demos:
|
|||
desc: |
|
||||
We can also scan Windows machines. Let's assume `windows.node` is configured with WinRM access for user `alice` with a password `pass`. The command will now read:
|
||||
```
|
||||
inspec exec example/profile -t winrm://alice:pass@windows.node
|
||||
inspec exec examples/profile -t winrm://alice:pass@windows.node
|
||||
```
|
||||
- demo: 1:inspec-exec-winrm-ssl
|
||||
desc: |
|
||||
The previous example is not quite realistic. Most Windows nodes with WinRM are configured to use SSL. Let's assume the user also has a self-signed certificate. It would now read
|
||||
```
|
||||
inspec exec example/profile -t winrm://alice:pass@windows.node --ssl --self-signed
|
||||
inspec exec examples/profile -t winrm://alice:pass@windows.node --ssl --self-signed
|
||||
```
|
||||
- demo: 1:inspec-exec-docker
|
||||
desc: |
|
||||
InSpec also supports scanning containers. Let's try it with Docker and pick a container
|
||||
```
|
||||
inspec exec example/profile -t docker://abcdef123
|
||||
inspec exec examples/profile -t docker://abcdef123
|
||||
```
|
||||
- demo: 1:inspec-detect
|
||||
desc: |
|
||||
|
|
Loading…
Reference in a new issue