Maybe make an error from `ChildProcess`'s `exit` event parameters
when you want to fire an event no matter how a process exits.
A replacement for process.exit that ensures stdio are fully drained before exiting.
Run a child as if it's the foreground process. Give it stdio. Exit when it exits.
Run some code when the process exits
A replacement for process.exit that ensures stdio are fully drained before exiting.
A Tailwind CSS plugin for creating beautiful animations.
Execute a function on exit without leaking memory, allowing all objects to be garbage collected
safely cleanup in signal handlers
Run some code when the process exits (supports async hooks and pm2 clustering)
the complete solution for node.js command-line programs
Execute a function right before the process, or the browser's tab, is about to exit.
YAML 1.2 parser and serializer
Cleanly exit process on EPIPE
unist utility to visit nodes
Custom error handler for Node.js CLIs.
errors with more than just a message
Execute shell command forwarding all stdio.
Creates a Promise that waits for a single event
wait-on is a cross platform command line utility and Node.js API which will wait for files, ports, sockets, and http(s) resources to become available
Gracefully restore the CLI cursor on exit
Commands for interacting with Percy builds
Exit,close,kill,shutdown app completely for React Native on iOS and Android.
A TypeScript rewrite of markdown-it with enhancements
Have you ever wanted to call <code>exit()</code> with an error condition, but weren't sure what exit status to use? No? Maybe it's just me, then. Anyway, I was reading manpages late one evening before retiring to bed in my palatial estate in rural Oregon, and I stumbled across <code>sysexits(3)</code>. Much to my chagrin, I couldn't find a +sysexits+ for Ruby! Well, for the other 2 people that actually care about <code>style(9)</code> as it applies to Ruby code, now there is one! Sysexits is a *completely* *awesome* collection of human-readable constants for the standard (BSDish) exit codes, used as arguments to +exit+ to indicate a specific error condition to the parent process. It's so fantastically fabulous that you'll want to fork it right away to avoid being thought of as that guy that's still using Webrick for his blog. I mean, <code>exit(1)</code> is so passé! This is like the 14-point font of Systems Programming. Like the C header file from which this was derived (I mean forked, naturally), error numbers begin at <code>Sysexits::EX__BASE</code> (which is way more cool than plain old +64+) to reduce the possibility of clashing with other exit statuses that other programs may already return. The codes are available in two forms: as constants which can be imported into your own namespace via <code>include Sysexits</code>, or as <code>Sysexits::STATUS_CODES</code>, a Hash keyed by Symbols derived from the constant names. Allow me to demonstrate. First, the old way: exit( 69 ) Whaaa...? Is that a euphemism? What's going on? See how unattractive and... well, 1970 that is? We're not changing vaccuum tubes here, people, we're <em>building a totally-awesome future in the Cloud™!</em> include Sysexits exit EX_UNAVAILABLE Okay, at least this is readable to people who have used <code>fork()</code> more than twice, but you could do so much better! include Sysexits exit :unavailable Holy Toledo! It's like we're writing Ruby, but our own made-up dialect in which variable++ is possible! Well, okay, it's not quite that cool. But it does look more Rubyish. And no monkeys were patched in the filming of this episode! All the simpletons still exiting with icky _numbers_ can still continue blithely along, none the wiser.
Allows you to provide an exclusion list of allowed failures/errors. Failures and errors on this list still get run and reported as usual, but do not cause a non-zero exit code. This enables you to have a green CI with against a list of known bad tests.
The default irb completion code shipped with ruby produces an internal error, exiting from the running script. This script makes it easy to check if a suggested patch has been applied to your current ruby version.
Miscellaneous methods that may or may not be useful. sh:: Safely pass untrusted parameters to sh scripts. fork_and_check:: Run a block in a forked process and raise an exception if the process returns a non-zero value. do_and_exit, do_and_exit!:: Run a block. If the block does not run exit!, a successful exec or equivalent, run exit(1) or exit!(1) ourselves. Useful to make sure a forked block either runs a successful exec or dies. Any exceptions from the block are printed to standard error. overwrite:: Safely replace a file. Writes to a temporary file and then moves it over the old file. tempname_for:: Generates an unique temporary path based on a filename. The generated filename resides in the same directory as the original one. try_n_times:: Retries a block of code until it succeeds or a maximum number of attempts (default 10) is exceeded. Exception#to_formatted_string:: Returns a string that looks like how Ruby would dump an uncaught exception. IO#best_datasync:: Tries fdatasync, falling back to fsync, falling back to flush.
Miscellaneous methods that may or may not be useful. sh:: Safely pass untrusted parameters to sh scripts. Raise an exception if the script returns a non-zero value. fork_and_check:: Run a block in a forked process and raise an exception if the process returns a non-zero value. do_and_exit, do_and_exit!:: Run a block. If the block does not run exit!, a successful exec or equivalent, run exit(1) or exit!(1) ourselves. Useful to make sure a forked block either runs a successful exec or dies. Any exceptions from the block are printed to standard error. overwrite:: Safely replace a file. Writes to a temporary file and then moves it over the old file. tempname_for:: Generates an unique temporary path based on a filename. The generated filename resides in the same directory as the original one. try_n_times:: Retries a block of code until it succeeds or a maximum number of attempts (default 10) is exceeded. Exception#to_formatted_string:: Return a string that looks like how Ruby would dump an uncaught exception. IO#best_datasync:: Try fdatasync, falling back to fsync, falling back to flush. Random#exp:: Return a random integer 0 ≤ n < 2^argument (using SecureRandom). Random#float:: Return a random float 0.0 ≤ n < argument (using SecureRandom). Random#int:: Return a random integer 0 ≤ n < argument (using SecureRandom). Password:: A small wrapper for String#crypt that does secure salt generation and easy password verification.
# COM # COM is an object-oriented wrapper around WIN32OLE. COM makes it easy to add behavior to WIN32OLE objects, making them easier to work with from Ruby. ## Usage ## Using COM is rather straightforward. There’s basically four concepts to keep track of: 1. COM objects 2. Instantiable COM objects 3. COM events 4. COM errors Let’s look at each concept separately, using the following example as a base. module Word end class Word::Application < COM::Instantiable def without_interaction with_properties('displayalerts' => Word::WdAlertsNone){ yield } end def documents Word::Documents.new(com.documents) end def quit(saving = Word::WdDoNotSaveChanges, *args) com.quit saving, *args end end ### COM Objects ### A COM::Object is a wrapper around a COM object. It provides error specialization, which is discussed later and a few utility methods. You typically use it to wrap COM objects that are returned by COM methods. If we take the example given in the introduction, Word::Documents is a good candidate: class Word::Documents < COM::Object DefaultOpenOptions = { 'confirmconversions' => false, 'readonly' => true, 'addtorecentfiles' => false, 'visible' => false }.freeze def open(path, options = {}) options = DefaultOpenOptions.merge(options) options['filename'] = Pathname(path).to_com Word::Document.new(com.open(options)) end end Here we override the #open method to be a bit easier to use, providing sane defaults for COM interaction. Worth noting is the use of the #com method to access the actual COM object to invoke the #open method on it. Also note that Word::Document is also a COM::Object. COM::Object provides a convenience method called #with_properties, which is used in the #without_interaction method above. It lets you set properties on the COM::Object during the duration of a block, restoring them after it exits (successfully or with an error). ### Instantiable COM Objects ### Instantiable COM objects are COM objects that we can connect to and that can be created. The Word::Application object can, for example, be created. Instantiable COM objects should inherit from COM::Instantiable. Instantiable COM objects can be told what program ID to use, whether or not to allow connecting to an already running object, and to load its associated constants upon creation. The program ID is used to determine what instantiable COM object to connect to. By default the name of the COM::Instantiable class’ name is used, taking the last two double-colon-separated components and joining them with a dot. For Word::Application, the program ID is “Word.Application”. The program ID can be set by using the .program_id method: class IDontCare::ForConventions < COM::Instantiable program_id 'Word.Application' end The program ID can be accessed with the same method: Word::Application.program_id # ⇒ 'Word.Application' Connecting to an already running COM object is not done by default, but is sometimes desirable: the COM object might take a long time to create, or some common state needs to be accessed. If the default for a certain instantiable COM object should be to connect, this can be done using the .connect method: class Word::Application < COM::Instantiable connect end If no running COM object is available, then a new COM object will be created in its stead. Whether or not a class uses the connection method can be queried with the .connect? method: Word::Application.connect? # ⇒ true Whether or not to load constants associated with an instantiable COM object is set with the .constants method: class Word::Application < COM::Instantiable constants true end and can similarly be checked: Word::Application.constants? # ⇒ true Constants are loaded by default. When an instance of the instantiable COM object is created, a check is run to see if constants should be loaded and whether or not they already have been loaded. If they should be loaded and they haven’t already been loaded, they’re, you guessed it, loaded. The constants are added to the module containing the COM::Instantiable. Thus, for Word::Application, the Word module will contain all the constants. Whether or not the constants have already been loaded can be checked with .constants_loaded?: Word::Application.constants_loaded # ⇒ false That concludes the class-level methods. Let’s begin with the #connected? method among the instance-level methods. This method queries whether or not this instance connected to an already running COM object: Word::Application.new.connected? # ⇒ false This can be very important in determining how shutdown of a COM object should be done. If you connected to an already COM object it might be foolish to shut it down if someone else is using it. The #initialize method takes a couple of options: * connect: whether or not to connect to a running instance * constants: whether or not to load constants These options will, when given, override the class-level defaults. ### Events ### COM events are easily dealt with: class Word::Application < COM::Instantiable def initialize(options = {}) super @events = COM::Events.new(com, 'ApplicationEvents', 'OnQuit') end def quit(saving = Word::WdDoNotSaveChanges, *args) @events.observe('OnQuit', proc{ com.quit saving, *args }) do yield if block_given? end end end To tell you the truth this API sucks and will most likely be rewritten. The reason that it is the way it is is that WIN32OLE, which COM wraps, sucks. It’s event API is horrid and the implementation is buggy. It will keep every registered event block in memory for ever, freeing neither the blocks nor the COM objects that yield the events. ### Errors ### All errors generated by COM methods descend from COM::Error, except for those cases where a Ruby error already exists. The following HRESULT error codes are turned into Ruby errors: HRESULT Error Code | Error Class -------------------|------------ 0x80004001 | NotImplementedError 0x80020005 | TypeError 0x80020006 | NoMethodError 0x8002000e | ArgumentError 0x800401e4 | ArgumentError There are also a couple of other HRESULT error codes that are turned into more specific errors than COM::Error: HRESULT Error Code | Error Class -------------------|------------ 0x80020003 | MemberNotFoundError 0x800401e3 | OperationUnavailableError Finally, when a method results in any other error, a COM::MethodInvocationError will be raised, which can be queried for the specifics, specifically #message, #method, #server, #code, #hresult_code, and #hresult_message. ### Pathname ### The Pathname object receives an additional method, #to_com. This method is useful for when you want to pass a Pathname object to a COM method. Simply call #to_com to turn it into a String of the right encoding for COM: Word::Application.new.documents.open(Pathname('a.docx').to_com) # ⇒ Word::Document ## Installation ## Install COM with % gem install com ## License ## You may use, copy and redistribute this library under the same [terms][1] as Ruby itself. [1]: http://www.ruby-lang.org/en/LICENSE.txt ## Contributors ## * Nikolai Weibull
= Cirron Cirron measures a piece of Ruby code and reports back several performance counters: CPU instruction count, branch misses, page faults and time spent measuring. It uses the Linux perf events interface or @ibireme's KPC demo[https://gist.github.com/ibireme/173517c208c7dc333ba962c1f0d67d12] on OSX. It can also trace syscalls using +strace+, Linux only! == Prerequisites - Linux with perf events support / Apple ARM OSX - C++ - Ruby 3.x == Usage === Performance Counters $ sudo irb irb(main):001> require 'cirron' => true irb(main):002* c = Cirron::collector do irb(main):003* puts "Hello" irb(main):004> end Hello => Counter(time_enabled_ns: 110260, instruction_count: 15406, branch_misses: 525, page_faults: 0) === Tracing Syscalls $ sudo irb irb> require 'cirron' => true irb> trace = Cirron::tracer do irb> # Your code here irb> puts "Hello" irb> end => [#<Syscall:0x00007c6c1a4b3608 @args="1, [{iov_base=\"Hello\", iov_len=5}, {iov_base=\"\\n\", iov_len=1}], 2", @duration="0.000201", @name="writev", @pid="2261962", @retval="6", @timestamp="1720285300.334976">] # Save the trace for ingesting to Perfetto irb> File.write("/tmp/trace", Cirron::to_tef(trace)) => 267 === Tampering with Syscalls Available tampering actions are: error: Inject a fault with the specified errno. retval: Inject a success with the specified return value. signal: Deliver the specified signal on syscall entry. delay_enter: Delay syscall entry by the specified time. delay_exit: Delay syscall exit by the specified time. poke_enter: Modify memory at argN on syscall entry. poke_exit: Modify memory at argN on syscall exit. syscall: Inject a different syscall instead. The when argument can be used to specify when to perform the tampering. See the Tampering section of the [strace manual page](https://man7.org/linux/man-pages/man1/strace.1.html) for more detailed explanaition of the arguments. ``` $ sudo irb irb> require 'cirron' irb> injector = Cirron.injector irb> injector.inject("openat", "error", "ENOSPC") irb> injector.inject("openat", "delay_enter", "1s", when_condition="2+2") irb> injector.run do irb> # Open now fails with "No space left on device" and every irb> # other call to `openat` will be delayed by 1s. irb> File.open("test.txt", "w") irb> end ``` == Additional Information For more detailed information, please visit the project's GitHub page: https://github.com/s7nfo/Cirron
== Confidently Build Terminal Apps Rooibos[https://rooibos.run] helps you build interactive terminal applications. Keep your code understandable and testable as it scales. Rooibos handles keyboard, mouse, and async work so you can focus on behavior and user experience. gem install rooibos <i>Currently in beta. APIs may change before 1.0.</i> === Get Started in Seconds rooibos new my_app cd my_app rooibos run That's it. You have a working app with keyboard navigation, mouse support, and clickable buttons. Open <tt>lib/my_app.rb</tt> to make it your own. --- === The Pattern \Rooibos uses Model-View-Update, the architecture behind Elm[https://guide.elm-lang.org/architecture/], Redux[https://redux.js.org/], and {Bubble Tea}[https://github.com/charmbracelet/bubbletea]. State lives in one place. Updates flow in one direction. The runtime handles rendering and runs background work for you. --- === Hello, MVU The simplest \Rooibos app. Press any key to increment the counter. Press <tt>Ctrl</tt>+<tt>C</tt> to quit. require "rooibos" module Counter # Init: How do you create the initial model? Init = -> { 0 } # View: What does the user see? View = -> (model, tui) { tui.paragraph(text: <<~END) } Current count: #{model}. Press any key to increment. Press Ctrl+C to quit. END # Update: What happens when things change? Update = -> (message, model) { if message.ctrl_c? Rooibos::Command.exit elsif message.key? model + 1 end } end Rooibos.run(Counter) That's the whole pattern: Model holds state, Init creates it, View renders it, and Update changes it. The runtime handles everything else. --- === Your First Real Application A file browser in sixty lines. It opens files, navigates directories, handles errors, styles directories and hidden files differently, and supports vim-style keyboard shortcuts. If you can do this much with this little code, imagine how easy _your_ app will be to build. require "rooibos" module FileBrowser # Model: What state does your app need? Model = Data.define(:path, :entries, :selected, :error) Init = -> { path = Dir.pwd entries = Entries[path] Ractor.make_shareable( # Ensures thread safety Model.new(path:, entries:, selected: entries.first, error: nil)) } View = -> (model, tui) { tui.block( titles: [model.error || model.path, { content: KEYS, position: :bottom, alignment: :right}], borders: [:all], border_style: if model.error then tui.style(fg: :red) else nil end, children: [tui.list(items: model.entries.map(&ListItem[model, tui]), selected_index: model.entries.index(model.selected), highlight_symbol: "", highlight_style: tui.style(modifiers: [:reversed]))] ) } Update = -> (message, model) { return model.with(error: ERROR) if message.error? model = model.with(error: nil) if model.error && message.key? if message.ctrl_c? || message.q? then Rooibos::Command.exit elsif message.home? || message.g? then model.with(selected: model.entries.first) elsif message.end? || message.G? then model.with(selected: model.entries.last) elsif message.up_arrow? || message.k? then Select[:-, model] elsif message.down_arrow? || message.j? then Select[:+, model] elsif message.enter? then Open[model] elsif message.escape? then Navigate[File.dirname(model.path), model] end } private # Lines below this are implementation details KEYS = "↑/↓/Home/End: Select | Enter: Open | Esc: Navigate Up | q: Quit" ERROR = "Sorry, opening the selected file failed." ListItem = -> (model, tui) { -> (name) { modifiers = name.start_with?(".") ? [:dim] : [] fg = :blue if name.end_with?("/") tui.list_item(content: name, style: tui.style(fg:, modifiers:)) } } Select = -> (operator, model) { new_index = model.entries.index(model.selected).public_send(operator, 1) model.with(selected: model.entries[new_index.clamp(0, model.entries.length - 1)]) } Open = -> (model) { full = File.join(model.path, model.selected.delete_suffix("/")) model.selected.end_with?("/") ? Navigate[full, model] : Rooibos::Command.open(full) } Navigate = -> (path, model) { entries = Entries[path] model.with(path:, entries:, selected: entries.first, error: nil) } Entries = -> (path) { Dir.children(path).map { |name| File.directory?(File.join(path, name)) ? "#{name}/" : name }.sort_by { |name| [name.end_with?("/") ? 0 : 1, name.downcase] } } end Rooibos.run(FileBrowser) --- === Batteries Included ==== Commands Applications fetch data, run shell commands, and set timers. \Rooibos Commands run off the main thread and send results back as messages. <b>HTTP requests:</b> Update = -> (message, model) { case message in :fetch_users [model.with(loading: true), Rooibos::Command.http(:get, "/api/users", :got_users)] in { type: :http, envelope: :got_users, status: 200, body: } model.with(loading: false, users: JSON.parse(body)) in { type: :http, envelope: :got_users, status: } model.with(error: "HTTP #{status}") end } <b>Shell commands:</b> Update = -> (message, model) { case message in :list_files Rooibos::Command.system("ls -la", :listed_files) in { type: :system, envelope: :listed_files, stdout:, status: 0 } model.with(files: stdout.lines.map(&:chomp)) in { type: :system, envelope: :listed_files, stderr:, status: } model.with(error: stderr) end } <b>Timers:</b> Update = -> (message, model) { case message in { type: :timer, envelope: :tick, elapsed: } [model.with(frame: model.frame + 1), Rooibos::Command.wait(1.0 / 24, :tick)] end } <b>And more!</b> \Rooibos includes <tt>all</tt>, <tt>batch</tt>, <tt>bubble</tt>, <tt>cancel</tt>, <tt>custom</tt>, <tt>deliver</tt>, <tt>exit</tt>, <tt>http</tt>, <tt>map</tt>, <tt>open</tt>, <tt>system</tt>, <tt>tick</tt>, and <tt>wait</tt> commands. You can also define your own custom commands for complex orchestration. Every command produces a message, and Update handles it the same way. ==== Testing \Rooibos makes TUIs so easy to test, you'll save more time by writing tests than by not testing. <b>Unit test Update, View, and Init.</b> No terminal needed. Test helpers included. def test_moves_selection_down_with_j model = Ractor.make_shareable(FileBrowser::Model.new( path: "/", entries: %w[bin exe lib], selected: "bin", error: nil)) message = RatatuiRuby::Event::Key.new(code: "j") result = FileBrowser::Update.call(message, model) assert_equal "exe", result.selected end <b>Style assertions.</b> Draw to a headless terminal, verify colors and modifiers. def test_directories_are_blue with_test_terminal(60, 10) do model = Ractor.make_shareable(FileBrowser::Model.new( path: "/", entries: %w[file.txt subdir/], selected: "file.txt", error: nil)) widget = FileBrowser::View.call(model, RatatuiRuby::TUI.new) RatatuiRuby.draw { |frame| frame.render_widget(widget, frame.area) } assert_blue(1, 2) # "subdir/" at column 1, row 2 end end <b>System tests.</b> Inject events, run the full app, snapshot the result. def test_selection_moves_down with_test_terminal(120, 30) do Dir.mktmpdir do |dir| FileUtils.touch(File.join(dir, "a")) FileUtils.touch(File.join(dir, "b")) FileUtils.touch(File.join(dir, "c")) inject_key(:down) inject_key(:ctrl_c) # Tests use explicit params to inject deterministic initial state. Rooibos.run( model: Ractor.make_shareable(FileBrowser::Model.new( path: dir, entries: %w[a b c], selected: "a", error: nil)), view: FileBrowser::View, update: FileBrowser::Update ) assert_snapshots("selection_moved_down") do |lines| title = "┌/tmp/test#{'─' * 107}┐" lines.map do |l| l.gsub(/┌#{Regexp.escape(dir)}[^┐]*┐/, title) end end end end end Snapshots record both plain text and ANSI colors. Normalization blocks mask dynamic content (timestamps, temp paths) for cross-platform reproducibility. Run <tt>UPDATE_SNAPSHOTS=1 rake test</tt> to regenerate baselines. ==== Scale Up Large applications decompose into fragments. Each fragment has its own Model, View, Update, and Init. Parents compose children. The pattern scales. The Router DSL eliminates boilerplate: module Dashboard include Rooibos::Router route :stats, to: StatsPanel route :network, to: NetworkPanel receive_events :ctrl_c, -> { Rooibos::Command.exit } only when: -> (_message, model) { !model.modal_open } do receive_events :q, -> { Rooibos::Command.exit } forward_events :s, to: :stats, as: :fetch forward_events :p, to: :network, as: :ping end Update = from_router # ... Model, Init, View below end Declare routes and event handlers. The router generates Update for you. Use guards to ignore messages when needed. ==== CLI The <tt>rooibos</tt> command scaffolds projects and runs applications. rooibos new my_app # Generate project structure rooibos run # Run the app in current directory Generated apps include tests, type signatures, and a working welcome screen with keyboard and mouse support. --- === The Ecosystem \Rooibos builds on RatatuiRuby[https://www.ratatui-ruby.dev], a Rubygem built on Ratatui[https://ratatui.rs]. You get native performance with the joy of Ruby. \Rooibos is one way to manage state and composition. Kit is another. ==== Rooibos[https://www.rooibos.run] Model-View-Update architecture. Inspired by Elm, Bubble Tea, and React + Redux. Your UI is a pure function of state. - Functional programming with MVU - Commands work off the main thread - Messages, not callbacks, drive updates ==== {Kit}[https://sr.ht/~kerrick/ratatui_ruby/#chapter-3-the-object-path--kit] (Coming Soon) Component-based architecture. Encapsulate state, input handling, and rendering in reusable pieces. - OOP with stateful components - Separate UI state from domain logic - Built-in focus management & click handling Both use the same widget library and rendering engine. Pick the paradigm that fits your brain. --- === Links [Get Started] {Getting Started}[https://www.rooibos.run/docs/trunk/doc/getting_started/index_md.html], {Tutorial}[https://www.rooibos.run/docs/trunk/doc/tutorial/index_md.html], {Examples}[https://www.rooibos.run/docs/trunk/examples/app_fractal_dashboard/README_md.html] [Coming From...] {React/Redux}[https://www.rooibos.run/docs/trunk/doc/getting_started/for_react_developers_md.html], {BubbleTea}[https://www.rooibos.run/docs/trunk/doc/getting_started/for_go_developers_md.html], {Textual}[https://www.rooibos.run/docs/trunk/doc/getting_started/for_python_developers_md.html] [Learn More] {Essentials}[https://www.rooibos.run/docs/trunk/doc/essentials/index_md.html], {Scaling Up}[https://www.rooibos.run/docs/trunk/doc/scaling_up/index_md.html], {Best Practices}[https://www.rooibos.run/docs/trunk/doc/best_practices/index_md.html], {Troubleshooting}[https://www.rooibos.run/docs/trunk/doc/troubleshooting/index_md.html] [Community] {Forum}[https://forum.setdef.com/c/rooibos], {Announcements}[https://forum.setdef.com/tags/c/rooibos/announcement], {Bug Tracker}[https://forum.setdef.com/tags/c/rooibos/bug], {Contribution Guide}[https://github.com/setdef/Rooibos/blob/trunk/CONTRIBUTING.md], {Code of Conduct}[https://github.com/setdef/Rooibos/blob/trunk/CODE_OF_CONDUCT.md] --- [Website] https://rooibos.run [Source] https://github.com/setdef/Rooibos [RubyGems] https://rubygems.org/gems/rooibos © 2026 Kerrick Long · Library: LGPL-3.0-or-later · Website: CC-BY-NC-ND-4.0 · Snippets: MIT-0
# mdtoc - Markdown Table of Contents Read Markdown files and output a table of contents. ## Installation Requirements: * [Ruby](https://www.ruby-lang.org/en/) (see [.ruby-version](./.ruby-version)) ```bash gem install mdtoc ``` ## Usage ```bash mdtoc --help Usage: mdtoc [options] files or directories... -h, --help Show this message -o, --output PATH Update a table of contents in the file at PATH -a, --[no-]append Append to the --output file if a <!-- mdtoc --> tag isn't found -c, --[no-]create Create the --output file if it does not exist ``` 1. Add a `<!-- mdtoc -->` tag to a Markdown file. ```bash echo '<!-- mdtoc -->' >> README.md ``` 2. Run `mdtoc` and specify input files or directories (eg. the "test/samples" directory) and an output file (eg. "README.md"). ```bash mdtoc -aco README.md test/samples ``` ## Example Rakefile Create a `Rakefile` with the contents below, then run [`rake`](https://github.com/ruby/rake) to: * `git pull` * `git add` any `*.md` files * Run `mdtoc` to update the generated table of contents in the ./README.md file * Git commit and push any changes ```ruby task default: %w[mdtoc] desc 'Update Markdown table of contents and push changes to the git repository' task :mdtoc do command = <<~CMD set -e if [ -n "$(git diff --name-only --diff-filter=U)" ]; then echo 'Error: conflicts exist' >&2 exit 1 fi mdtoc --append --create --output README.md docs/ git add *.md **/*.md git commit -qm 'Update TOC' || true git pull git push CMD sh command, verbose: false do |ok, status| unless ok fail "Failed with status: #{status.exitstatus}" end end end ``` See [andornaut/til](https://github.com/andornaut/til/blob/master/Rakefile) for an example. ## Development ### Setup Requirements: * [Bundler](https://bundler.io/) * [chruby](https://github.com/postmodern/chruby) (recommended) ```bash # Setup development environment bin/setup ``` ### Tasks ```bash # List rake tasks rake -T rake build # Build gem into the pkg directory rake default # Run the build, rubocop, sorbet and test tasks rake install # Build and install gem into system gems rake rubocop # Run RuboCop rake sorbet # Run the Sorbet type checker rake test # Run tests # Run mdtoc with test inputs ruby -Ilib bin/mdtoc test/samples # Run mdtoc with test inputs, and write to a newly created output file f=$(mktemp) && ruby -Ilib bin/mdtoc -aco ${f} test/samples ; cat ${f} ``` ### Publishing 1. Bump version in `lib/mdtoc/version.rb` 2. Run `bundle install` to update `Gemfile.lock` 3. Commit the changes 4. Run `rake release` to publish the gem to RubyGems, create the git tag, and push
# Overview This guide documents the InsightVM Application Programming Interface (API) Version 3. This API supports the Representation State Transfer (REST) design pattern. Unless noted otherwise this API accepts and produces the `application/json` media type. This API uses Hypermedia as the Engine of Application State (HATEOAS) and is hypermedia friendly. All API connections must be made to the security console using HTTPS. ## Versioning Versioning is specified in the URL and the base path of this API is: `https://<host>:<port>/api/3/`. ## Specification An <a target="_blank" href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md">OpenAPI v2</a> specification (also known as Swagger 2) of this API is available. Tools such as <a target="_blank" href="https://github.com/swagger-api/swagger-codegen">swagger-codegen</a> can be used to generate an API client in the language of your choosing using this specification document. <p class="openapi">Download the specification: <a class="openapi-button" target="_blank" download="" href="/api/3/json"> Download </a></p> ## Authentication Authorization to the API uses HTTP Basic Authorization (see <a target="_blank" href="https://www.ietf.org/rfc/rfc2617.txt">RFC 2617</a> for more information). Requests must supply authorization credentials in the `Authorization` header using a Base64 encoded hash of `"username:password"`. <!-- ReDoc-Inject: <security-definitions> --> ### 2FA This API supports two-factor authentication (2FA) by supplying an authentication token in addition to the Basic Authorization. The token is specified using the `Token` request header. To leverage two-factor authentication, this must be enabled on the console and be configured for the account accessing the API. ## Resources ### Naming Resource names represent nouns and identify the entity being manipulated or accessed. All collection resources are pluralized to indicate to the client they are interacting with a collection of multiple resources of the same type. Singular resource names are used when there exists only one resource available to interact with. The following naming conventions are used by this API: | Type | Case | | --------------------------------------------- | ------------------------ | | Resource names | `lower_snake_case` | | Header, body, and query parameters parameters | `camelCase` | | JSON fields and property names | `camelCase` | #### Collections A collection resource is a parent resource for instance resources, but can itself be retrieved and operated on independently. Collection resources use a pluralized resource name. The resource path for collection resources follow the convention: ``` /api/3/{resource_name} ``` #### Instances An instance resource is a "leaf" level resource that may be retrieved, optionally nested within a collection resource. Instance resources are usually retrievable with opaque identifiers. The resource path for instance resources follows the convention: ``` /api/3/{resource_name}/{instance_id}... ``` ## Verbs The following HTTP operations are supported throughout this API. The general usage of the operation and both its failure and success status codes are outlined below. | Verb | Usage | Success | Failure | | --------- | ------------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------- | | `GET` | Used to retrieve a resource by identifier, or a collection of resources by type. | `200` | `400`, `401`, `402`, `404`, `405`, `408`, `410`, `415`, `500` | | `POST` | Creates a resource with an application-specified identifier. | `201` | `400`, `401`, `404`, `405`, `408`, `413`, `415`, `500` | | `POST` | Performs a request to queue an asynchronous job. | `202` | `400`, `401`, `405`, `408`, `410`, `413`, `415`, `500` | | `PUT` | Creates a resource with a client-specified identifier. | `200` | `400`, `401`, `403`, `405`, `408`, `410`, `413`, `415`, `500` | | `PUT` | Performs a full update of a resource with a specified identifier. | `201` | `400`, `401`, `403`, `405`, `408`, `410`, `413`, `415`, `500` | | `DELETE` | Deletes a resource by identifier or an entire collection of resources. | `204` | `400`, `401`, `405`, `408`, `410`, `413`, `415`, `500` | | `OPTIONS` | Requests what operations are available on a resource. | `200` | `401`, `404`, `405`, `408`, `500` | ### Common Operations #### OPTIONS All resources respond to the `OPTIONS` request, which allows discoverability of available operations that are supported. The `OPTIONS` response returns the acceptable HTTP operations on that resource within the `Allow` header. The response is always a `200 OK` status. ### Collection Resources Collection resources can support the `GET`, `POST`, `PUT`, and `DELETE` operations. #### GET The `GET` operation invoked on a collection resource indicates a request to retrieve all, or some, of the entities contained within the collection. This also includes the optional capability to filter or search resources during the request. The response from a collection listing is a paginated document. See [hypermedia links](#section/Overview/Paging) for more information. #### POST The `POST` is a non-idempotent operation that allows for the creation of a new resource when the resource identifier is not provided by the system during the creation operation (i.e. the Security Console generates the identifier). The content of the `POST` request is sent in the request body. The response to a successful `POST` request should be a `201 CREATED` with a valid `Location` header field set to the URI that can be used to access to the newly created resource. The `POST` to a collection resource can also be used to interact with asynchronous resources. In this situation, instead of a `201 CREATED` response, the `202 ACCEPTED` response indicates that processing of the request is not fully complete but has been accepted for future processing. This request will respond similarly with a `Location` header with link to the job-oriented asynchronous resource that was created and/or queued. #### PUT The `PUT` is an idempotent operation that either performs a create with user-supplied identity, or a full replace or update of a resource by a known identifier. The response to a `PUT` operation to create an entity is a `201 Created` with a valid `Location` header field set to the URI that can be used to access to the newly created resource. `PUT` on a collection resource replaces all values in the collection. The typical response to a `PUT` operation that updates an entity is hypermedia links, which may link to related resources caused by the side-effects of the changes performed. #### DELETE The `DELETE` is an idempotent operation that physically deletes a resource, or removes an association between resources. The typical response to a `DELETE` operation is hypermedia links, which may link to related resources caused by the side-effects of the changes performed. ### Instance Resources Instance resources can support the `GET`, `PUT`, `POST`, `PATCH` and `DELETE` operations. #### GET Retrieves the details of a specific resource by its identifier. The details retrieved can be controlled through property selection and property views. The content of the resource is returned within the body of the response in the acceptable media type. #### PUT Allows for and idempotent "full update" (complete replacement) on a specific resource. If the resource does not exist, it will be created; if it does exist, it is completely overwritten. Any omitted properties in the request are assumed to be undefined/null. For "partial updates" use `POST` or `PATCH` instead. The content of the `PUT` request is sent in the request body. The identifier of the resource is specified within the URL (not the request body). The response to a successful `PUT` request is a `201 CREATED` to represent the created status, with a valid `Location` header field set to the URI that can be used to access to the newly created (or fully replaced) resource. #### POST Performs a non-idempotent creation of a new resource. The `POST` of an instance resource most commonly occurs with the use of nested resources (e.g. searching on a parent collection resource). The response to a `POST` of an instance resource is typically a `200 OK` if the resource is non-persistent, and a `201 CREATED` if there is a resource created/persisted as a result of the operation. This varies by endpoint. #### PATCH The `PATCH` operation is used to perform a partial update of a resource. `PATCH` is a non-idempotent operation that enforces an atomic mutation of a resource. Only the properties specified in the request are to be overwritten on the resource it is applied to. If a property is missing, it is assumed to not have changed. #### DELETE Permanently removes the individual resource from the system. If the resource is an association between resources, only the association is removed, not the resources themselves. A successful deletion of the resource should return `204 NO CONTENT` with no response body. This operation is not fully idempotent, as follow-up requests to delete a non-existent resource should return a `404 NOT FOUND`. ## Requests Unless otherwise indicated, the default request body media type is `application/json`. ### Headers Commonly used request headers include: | Header | Example | Purpose | | ------------------ | --------------------------------------------- | ---------------------------------------------------------------------------------------------- | | `Accept` | `application/json` | Defines what acceptable content types are allowed by the client. For all types, use `*/*`. | | `Accept-Encoding` | `deflate, gzip` | Allows for the encoding to be specified (such as gzip). | | `Accept-Language` | `en-US` | Indicates to the server the client's locale (defaults `en-US`). | | `Authorization ` | `Basic Base64("username:password")` | Basic authentication | | `Token ` | `123456` | Two-factor authentication token (if enabled) | ### Dates & Times Dates and/or times are specified as strings in the ISO 8601 format(s). The following formats are supported as input: | Value | Format | Notes | | --------------------------- | ------------------------------------------------------ | ----------------------------------------------------- | | Date | YYYY-MM-DD | Defaults to 12 am UTC (if used for a date & time | | Date & time only | YYYY-MM-DD'T'hh:mm:ss[.nnn] | Defaults to UTC | | Date & time in UTC | YYYY-MM-DD'T'hh:mm:ss[.nnn]Z | | | Date & time w/ offset | YYYY-MM-DD'T'hh:mm:ss[.nnn][+|-]hh:mm | | | Date & time w/ zone-offset | YYYY-MM-DD'T'hh:mm:ss[.nnn][+|-]hh:mm[<zone-id>] | | ### Timezones Timezones are specified in the regional zone format, such as `"America/Los_Angeles"`, `"Asia/Tokyo"`, or `"GMT"`. ### Paging Pagination is supported on certain collection resources using a combination of two query parameters, `page` and `size`. As these are control parameters, they are prefixed with the underscore character. The page parameter dictates the zero-based index of the page to retrieve, and the `size` indicates the size of the page. For example, `/resources?page=2&size=10` will return page 3, with 10 records per page, giving results 21-30. The maximum page size for a request is 500. ### Sorting Sorting is supported on paginated resources with the `sort` query parameter(s). The sort query parameter(s) supports identifying a single or multi-property sort with a single or multi-direction output. The format of the parameter is: ``` sort=property[,ASC|DESC]... ``` Therefore, the request `/resources?sort=name,title,DESC` would return the results sorted by the name and title descending, in that order. The sort directions are either ascending `ASC` or descending `DESC`. With single-order sorting, all properties are sorted in the same direction. To sort the results with varying orders by property, multiple sort parameters are passed. For example, the request `/resources?sort=name,ASC&sort=title,DESC` would sort by name ascending and title descending, in that order. ## Responses The following response statuses may be returned by this API. | Status | Meaning | Usage | | ------ | ------------------------ |------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `200` | OK | The operation performed without error according to the specification of the request, and no more specific 2xx code is suitable. | | `201` | Created | A create request has been fulfilled and a resource has been created. The resource is available as the URI specified in the response, including the `Location` header. | | `202` | Accepted | An asynchronous task has been accepted, but not guaranteed, to be processed in the future. | | `400` | Bad Request | The request was invalid or cannot be otherwise served. The request is not likely to succeed in the future without modifications. | | `401` | Unauthorized | The user is unauthorized to perform the operation requested, or does not maintain permissions to perform the operation on the resource specified. | | `403` | Forbidden | The resource exists to which the user has access, but the operating requested is not permitted. | | `404` | Not Found | The resource specified could not be located, does not exist, or an unauthenticated client does not have permissions to a resource. | | `405` | Method Not Allowed | The operations may not be performed on the specific resource. Allowed operations are returned and may be performed on the resource. | | `408` | Request Timeout | The client has failed to complete a request in a timely manner and the request has been discarded. | | `413` | Request Entity Too Large | The request being provided is too large for the server to accept processing. | | `415` | Unsupported Media Type | The media type is not supported for the requested resource. | | `500` | Internal Server Error | An internal and unexpected error has occurred on the server at no fault of the client. | ### Security The response statuses 401, 403 and 404 need special consideration for security purposes. As necessary, error statuses and messages may be obscured to strengthen security and prevent information exposure. The following is a guideline for privileged resource response statuses: | Use Case | Access | Resource | Permission | Status | | ------------------------------------------------------------------ | ------------------ |------------------- | ------------ | ------------ | | Unauthenticated access to an unauthenticated resource. | Unauthenticated | Unauthenticated | Yes | `20x` | | Unauthenticated access to an authenticated resource. | Unauthenticated | Authenticated | No | `401` | | Unauthenticated access to an authenticated resource. | Unauthenticated | Non-existent | No | `401` | | Authenticated access to a unauthenticated resource. | Authenticated | Unauthenticated | Yes | `20x` | | Authenticated access to an authenticated, unprivileged resource. | Authenticated | Authenticated | No | `404` | | Authenticated access to an authenticated, privileged resource. | Authenticated | Authenticated | Yes | `20x` | | Authenticated access to an authenticated, non-existent resource | Authenticated | Non-existent | Yes | `404` | ### Headers Commonly used response headers include: | Header | Example | Purpose | | -------------------------- | --------------------------------- | --------------------------------------------------------------- | | `Allow` | `OPTIONS, GET` | Defines the allowable HTTP operations on a resource. | | `Cache-Control` | `no-store, must-revalidate` | Disables caching of resources (as they are all dynamic). | | `Content-Encoding` | `gzip` | The encoding of the response body (if any). | | `Location` | | Refers to the URI of the resource created by a request. | | `Transfer-Encoding` | `chunked` | Specified the encoding used to transform response. | | `Retry-After` | 5000 | Indicates the time to wait before retrying a request. | | `X-Content-Type-Options` | `nosniff` | Disables MIME type sniffing. | | `X-XSS-Protection` | `1; mode=block` | Enables XSS filter protection. | | `X-Frame-Options` | `SAMEORIGIN` | Prevents rendering in a frame from a different origin. | | `X-UA-Compatible` | `IE=edge,chrome=1` | Specifies the browser mode to render in. | ### Format When `application/json` is returned in the response body it is always pretty-printed (indented, human readable output). Additionally, gzip compression/encoding is supported on all responses. #### Dates & Times Dates or times are returned as strings in the ISO 8601 'extended' format. When a date and time is returned (instant) the value is converted to UTC. For example: | Value | Format | Example | | --------------- | ------------------------------ | --------------------- | | Date | `YYYY-MM-DD` | 2017-12-03 | | Date & Time | `YYYY-MM-DD'T'hh:mm:ss[.nnn]Z` | 2017-12-03T10:15:30Z | #### Content In some resources a Content data type is used. This allows for multiple formats of representation to be returned within resource, specifically `"html"` and `"text"`. The `"text"` property returns a flattened representation suitable for output in textual displays. The `"html"` property returns an HTML fragment suitable for display within an HTML element. Note, the HTML returned is not a valid stand-alone HTML document. #### Paging The response to a paginated request follows the format: ```json { resources": [ ... ], "page": { "number" : ..., "size" : ..., "totalResources" : ..., "totalPages" : ... }, "links": [ "first" : { "href" : "..." }, "prev" : { "href" : "..." }, "self" : { "href" : "..." }, "next" : { "href" : "..." }, "last" : { "href" : "..." } ] } ``` The `resources` property is an array of the resources being retrieved from the endpoint, each which should contain at minimum a "self" relation hypermedia link. The `page` property outlines the details of the current page and total possible pages. The object for the page includes the following properties: - number - The page number (zero-based) of the page returned. - size - The size of the pages, which is less than or equal to the maximum page size. - totalResources - The total amount of resources available across all pages. - totalPages - The total amount of pages. The last property of the paged response is the `links` array, which contains all available hypermedia links. For paginated responses, the "self", "next", "previous", "first", and "last" links are returned. The "self" link must always be returned and should contain a link to allow the client to replicate the original request against the collection resource in an identical manner to that in which it was invoked. The "next" and "previous" links are present if either or both there exists a previous or next page, respectively. The "next" and "previous" links have hrefs that allow "natural movement" to the next page, that is all parameters required to move the next page are provided in the link. The "first" and "last" links provide references to the first and last pages respectively. Requests outside the boundaries of the pageable will result in a `404 NOT FOUND`. Paginated requests do not provide a "stateful cursor" to the client, nor does it need to provide a read consistent view. Records in adjacent pages may change while pagination is being traversed, and the total number of pages and resources may change between requests within the same filtered/queries resource collection. #### Property Views The "depth" of the response of a resource can be configured using a "view". All endpoints supports two views that can tune the extent of the information returned in the resource. The supported views are `summary` and `details` (the default). View are specified using a query parameter, in this format: ```bash /<resource>?view={viewName} ``` #### Error Any error responses can provide a response body with a message to the client indicating more information (if applicable) to aid debugging of the error. All 40x and 50x responses will return an error response in the body. The format of the response is as follows: ```json { "status": <statusCode>, "message": <message>, "links" : [ { "rel" : "...", "href" : "..." } ] } ``` The `status` property is the same as the HTTP status returned in the response, to ease client parsing. The message property is a localized message in the request client's locale (if applicable) that articulates the nature of the error. The last property is the `links` property. This may contain additional [hypermedia links](#section/Overview/Authentication) to troubleshoot. #### Search Criteria <a section="section/Responses/SearchCriteria"></a> Multiple resources make use of search criteria to match assets. Search criteria is an array of search filters. Each search filter has a generic format of: ```json { "field": "<field-name>", "operator": "<operator>", ["value": "<value>",] ["lower": "<value>",] ["upper": "<value>"] } ``` Every filter defines two required properties `field` and `operator`. The field is the name of an asset property that is being filtered on. The operator is a type and property-specific operating performed on the filtered property. The valid values for fields and operators are outlined in the table below. Every filter also defines one or more values that are supplied to the operator. The valid values vary by operator and are outlined below. ##### Fields The following table outlines the search criteria fields and the available operators: | Field | Operators | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | `alternate-address-type` | `in` | | `container-image` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` ` is-like` ` not-like` | | `container-status` | `is` ` is-not` | | `containers` | `are` | | `criticality-tag` | `is` ` is-not` ` is-greater-than` ` is-less-than` ` is-applied` ` is-not-applied` | | `custom-tag` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` ` is-applied` ` is-not-applied` | | `cve` | `is` ` is-not` ` contains` ` does-not-contain` | | `cvss-access-complexity` | `is` ` is-not` | | `cvss-authentication-required` | `is` ` is-not` | | `cvss-access-vector` | `is` ` is-not` | | `cvss-availability-impact` | `is` ` is-not` | | `cvss-confidentiality-impact` | `is` ` is-not` | | `cvss-integrity-impact` | `is` ` is-not` | | `cvss-v3-confidentiality-impact` | `is` ` is-not` | | `cvss-v3-integrity-impact` | `is` ` is-not` | | `cvss-v3-availability-impact` | `is` ` is-not` | | `cvss-v3-attack-vector` | `is` ` is-not` | | `cvss-v3-attack-complexity` | `is` ` is-not` | | `cvss-v3-user-interaction` | `is` ` is-not` | | `cvss-v3-privileges-required` | `is` ` is-not` | | `host-name` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` ` is-empty` ` is-not-empty` ` is-like` ` not-like` | | `host-type` | `in` ` not-in` | | `ip-address` | `is` ` is-not` ` in-range` ` not-in-range` ` is-like` ` not-like` | | `ip-address-type` | `in` ` not-in` | | `last-scan-date` | `is-on-or-before` ` is-on-or-after` ` is-between` ` is-earlier-than` ` is-within-the-last` | | `location-tag` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` ` is-applied` ` is-not-applied` | | `mobile-device-last-sync-time` | `is-within-the-last` ` is-earlier-than` | | `open-ports` | `is` ` is-not` ` in-range` | | `operating-system` | `contains` ` does-not-contain` ` is-empty` ` is-not-empty` | | `owner-tag` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` ` is-applied` ` is-not-applied` | | `pci-compliance` | `is` | | `risk-score` | `is` ` is-not` ` in-range` ` greater-than` ` less-than` | | `service-name` | `contains` ` does-not-contain` | | `site-id` | `in` ` not-in` | | `software` | `contains` ` does-not-contain` | | `vAsset-cluster` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `vAsset-datacenter` | `is` ` is-not` | | `vAsset-host-name` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `vAsset-power-state` | `in` ` not-in` | | `vAsset-resource-pool-path` | `contains` ` does-not-contain` | | `vulnerability-assessed` | `is-on-or-before` ` is-on-or-after` ` is-between` ` is-earlier-than` ` is-within-the-last` | | `vulnerability-category` | `is` ` is-not` ` starts-with` ` ends-with` ` contains` ` does-not-contain` | | `vulnerability-cvss-v3-score` | `is` ` is-not` | | `vulnerability-cvss-score` | `is` ` is-not` ` in-range` ` is-greater-than` ` is-less-than` | | `vulnerability-exposures` | `includes` ` does-not-include` | | `vulnerability-title` | `contains` ` does-not-contain` ` is` ` is-not` ` starts-with` ` ends-with` | | `vulnerability-validated-status` | `are` | ##### Enumerated Properties The following fields have enumerated values: | Field | Acceptable Values | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `alternate-address-type` | 0=IPv4, 1=IPv6 | | `containers` | 0=present, 1=not present | | `container-status` | `created` `running` `paused` `restarting` `exited` `dead` `unknown` | | `cvss-access-complexity` | <ul><li><code>L</code> = Low</li><li><code>M</code> = Medium</li><li><code>H</code> = High</li></ul> | | `cvss-integrity-impact` | <ul><li><code>N</code> = None</li><li><code>P</code> = Partial</li><li><code>C</code> = Complete</li></ul> | | `cvss-confidentiality-impact` | <ul><li><code>N</code> = None</li><li><code>P</code> = Partial</li><li><code>C</code> = Complete</li></ul> | | `cvss-availability-impact` | <ul><li><code>N</code> = None</li><li><code>P</code> = Partial</li><li><code>C</code> = Complete</li></ul> | | `cvss-access-vector` | <ul><li><code>L</code> = Local</li><li><code>A</code> = Adjacent</li><li><code>N</code> = Network</li></ul> | | `cvss-authentication-required` | <ul><li><code>N</code> = None</li><li><code>S</code> = Single</li><li><code>M</code> = Multiple</li></ul> | | `cvss-v3-confidentiality-impact` | <ul><li><code>L</code> = Local</li><li><code>L</code> = Low</li><li><code>N</code> = None</li><li><code>H</code> = High</li></ul> | | `cvss-v3-integrity-impact` | <ul><li><code>L</code> = Local</li><li><code>L</code> = Low</li><li><code>N</code> = None</li><li><code>H</code> = High</li></ul> | | `cvss-v3-availability-impact` | <ul><li><code>N</code> = None</li><li><code>L</code> = Low</li><li><code>H</code> = High</li></ul> | | `cvss-v3-attack-vector` | <ul><li><code>N</code> = Network</li><li><code>A</code> = Adjacent</li><li><code>L</code> = Local</li><li><code>P</code> = Physical</li></ul> | | `cvss-v3-attack-complexity` | <ul><li><code>L</code> = Low</li><li><code>H</code> = High</li></ul> | | `cvss-v3-user-interaction` | <ul><li><code>N</code> = None</li><li><code>R</code> = Required</li></ul> | | `cvss-v3-privileges-required` | <ul><li><code>N</code> = None</li><li><code>L</code> = Low</li><li><code>H</code> = High</li></ul> | | `host-type` | 0=Unknown, 1=Guest, 2=Hypervisor, 3=Physical, 4=Mobile | | `ip-address-type` | 0=IPv4, 1=IPv6 | | `pci-compliance` | 0=fail, 1=pass | | `vulnerability-validated-status` | 0=present, 1=not present | ##### Operator Properties <a section="section/Responses/SearchCriteria/OperatorProperties"></a> The following table outlines which properties are required for each operator and the appropriate data type(s): | Operator | `value` | `lower` | `upper` | | ----------------------|-----------------------|-----------------------|-----------------------| | `are` | `string` | | | | `contains` | `string` | | | | `does-not-contain` | `string` | | | | `ends with` | `string` | | | | `in` | `Array[ string ]` | | | | `in-range` | | `numeric` | `numeric` | | `includes` | `Array[ string ]` | | | | `is` | `string` | | | | `is-applied` | | | | | `is-between` | | `numeric` | `numeric` | | `is-earlier-than` | `numeric` | | | | `is-empty` | | | | | `is-greater-than` | `numeric` | | | | `is-on-or-after` | `string` (yyyy-MM-dd) | | | | `is-on-or-before` | `string` (yyyy-MM-dd) | | | | `is-not` | `string` | | | | `is-not-applied` | | | | | `is-not-empty` | | | | | `is-within-the-last` | `numeric` | | | | `less-than` | `string` | | | | `like` | `string` | | | | `not-contains` | `string` | | | | `not-in` | `Array[ string ]` | | | | `not-in-range` | | `numeric` | `numeric` | | `not-like` | `string` | | | | `starts-with` | `string` | | | #### Discovery Connection Search Criteria <a section="section/Responses/DiscoverySearchCriteria"></a> Dynamic sites make use of search criteria to match assets from a discovery connection. Search criteria is an array of search filters. Each search filter has a generic format of: ```json { "field": "<field-name>", "operator": "<operator>", ["value": "<value>",] ["lower": "<value>",] ["upper": "<value>"] } ``` Every filter defines two required properties `field` and `operator`. The field is the name of an asset property that is being filtered on. The list of supported fields vary depending on the type of discovery connection configured for the dynamic site (e.g vSphere, ActiveSync, etc.). The operator is a type and property-specific operating performed on the filtered property. The valid values for fields outlined in the tables below and are grouped by the type of connection. Every filter also defines one or more values that are supplied to the operator. See <a href="#section/Responses/SearchCriteria/OperatorProperties">Search Criteria Operator Properties</a> for more information on the valid values for each operator. ##### Fields (ActiveSync) This section documents search criteria information for ActiveSync discovery connections. The discovery connections must be one of the following types: `"activesync-ldap"`, `"activesync-office365"`, or `"activesync-powershell"`. The following table outlines the search criteria fields and the available operators for ActiveSync connections: | Field | Operators | | --------------------------------- | ------------------------------------------------------------- | | `last-sync-time` | `is-within-the-last` ` is-earlier-than` | | `operating-system` | `contains` ` does-not-contain` | | `user` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | ##### Fields (AWS) This section documents search criteria information for AWS discovery connections. The discovery connections must be the type `"aws"`. The following table outlines the search criteria fields and the available operators for AWS connections: | Field | Operators | | ----------------------- | ------------------------------------------------------------- | | `availability-zone` | `contains` ` does-not-contain` | | `guest-os-family` | `contains` ` does-not-contain` | | `instance-id` | `contains` ` does-not-contain` | | `instance-name` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `instance-state` | `in` ` not-in` | | `instance-type` | `in` ` not-in` | | `ip-address` | `in-range` ` not-in-range` ` is` ` is-not` | | `region` | `in` ` not-in` | | `vpc-id` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | ##### Fields (DHCP) This section documents search criteria information for DHCP discovery connections. The discovery connections must be the type `"dhcp"`. The following table outlines the search criteria fields and the available operators for DHCP connections: | Field | Operators | | --------------- | ------------------------------------------------------------- | | `host-name` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `ip-address` | `in-range` ` not-in-range` ` is` ` is-not` | | `mac-address` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | ##### Fields (Sonar) This section documents search criteria information for Sonar discovery connections. The discovery connections must be the type `"sonar"`. The following table outlines the search criteria fields and the available operators for Sonar connections: | Field | Operators | | ------------------- | -------------------- | | `search-domain` | `contains` ` is` | | `ip-address` | `in-range` ` is` | | `sonar-scan-date` | `is-within-the-last` | ##### Fields (vSphere) This section documents search criteria information for vSphere discovery connections. The discovery connections must be the type `"vsphere"`. The following table outlines the search criteria fields and the available operators for vSphere connections: | Field | Operators | | -------------------- | ------------------------------------------------------------------------------------------ | | `cluster` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `data-center` | `is` ` is-not` | | `discovered-time` | `is-on-or-before` ` is-on-or-after` ` is-between` ` is-earlier-than` ` is-within-the-last` | | `guest-os-family` | `contains` ` does-not-contain` | | `host-name` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | | `ip-address` | `in-range` ` not-in-range` ` is` ` is-not` | | `power-state` | `in` ` not-in` | | `resource-pool-path` | `contains` ` does-not-contain` | | `last-time-seen` | `is-on-or-before` ` is-on-or-after` ` is-between` ` is-earlier-than` ` is-within-the-last` | | `vm` | `is` ` is-not` ` contains` ` does-not-contain` ` starts-with` | ##### Enumerated Properties (vSphere) The following fields have enumerated values: | Field | Acceptable Values | | ------------- | ------------------------------------ | | `power-state` | `poweredOn` `poweredOff` `suspended` | ## HATEOAS This API follows Hypermedia as the Engine of Application State (HATEOAS) principals and is therefore hypermedia friendly. Hyperlinks are returned in the `links` property of any given resource and contain a fully-qualified hyperlink to the corresponding resource. The format of the hypermedia link adheres to both the <a target="_blank" href="http://jsonapi.org">{json:api} v1</a> <a target="_blank" href="http://jsonapi.org/format/#document-links">"Link Object"</a> and <a target="_blank" href="http://json-schema.org/latest/json-schema-hypermedia.html">JSON Hyper-Schema</a> <a target="_blank" href="http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.5.2">"Link Description Object"</a> formats. For example: ```json "links": [{ "rel": "<relation>", "href": "<href>" ... }] ``` Where appropriate link objects may also contain additional properties than the `rel` and `href` properties, such as `id`, `type`, etc. See the [Root](#tag/Root) resources for the entry points into API discovery.
No description provided.
No description provided.
No description provided.