mirror of
https://github.com/inspec/inspec
synced 2024-11-26 14:40:26 +00:00
Adding docker plugin support (#3074)
* Fixing tests and squashing * Updating as per some PR comments * PR comments Signed-off-by: Noel Georgi <18496730+frezbo@users.noreply.github.com>
This commit is contained in:
parent
b872e9135a
commit
9d3beb8d41
9 changed files with 239 additions and 0 deletions
|
@ -148,6 +148,17 @@ Or execute the profile directly via URL:
|
||||||
its('sizes') { should_not include "1.41 GB" }
|
its('sizes') { should_not include "1.41 GB" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
### plugins
|
||||||
|
|
||||||
|
`plugins` returns information about Docker plugins as returned by [docker plugin ls](https://docs.docker.com/engine/reference/commandline/plugin/).
|
||||||
|
|
||||||
|
describe docker.plugins do
|
||||||
|
its('names') { should include ["store/weaveworks/net-plugin", "docker4x/cloudstor"] }
|
||||||
|
its('ids') { should cmp ["6ea8176de74b", "771d3ee7c7ea"] }
|
||||||
|
its('versions') { should cmp ["2.3.0", "18.03.1-ce-aws1"] }
|
||||||
|
its('enabled') { should cmp [true, false] }
|
||||||
|
end
|
||||||
|
|
||||||
### info
|
### info
|
||||||
|
|
||||||
`info` returns the parsed result of [docker info](https://docs.docker.com/engine/reference/commandline/info/)
|
`info` returns the parsed result of [docker info](https://docs.docker.com/engine/reference/commandline/info/)
|
||||||
|
|
80
docs/resources/docker_plugin.md.erb
Normal file
80
docs/resources/docker_plugin.md.erb
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
title: About the docker_plugin Resource
|
||||||
|
platform: linux
|
||||||
|
---
|
||||||
|
|
||||||
|
# docker_plugin
|
||||||
|
|
||||||
|
Use the `docker_plugin` InSpec audit resource to verify a Docker plugin.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A `docker_plugin` resource block declares the plugin:
|
||||||
|
|
||||||
|
describe docker_plugin('rexray/ebs') do
|
||||||
|
it { should exist }
|
||||||
|
its('id') { should_not eq '0ac30b93ad40' }
|
||||||
|
its('version') { should eq '0.11.1' }
|
||||||
|
it { should be_enabled }
|
||||||
|
end
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Resource Parameter Examples
|
||||||
|
|
||||||
|
The resource allows you to pass in an plugin id:
|
||||||
|
|
||||||
|
describe docker_plugin(id: plugin_id) do
|
||||||
|
it { should be_enabled }
|
||||||
|
end
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
### id
|
||||||
|
|
||||||
|
The `id` property returns the full plugin id:
|
||||||
|
|
||||||
|
describe docker_plugin('cloudstor/aws') do
|
||||||
|
its('id') { should eq '0ac30b93ad40' }
|
||||||
|
end
|
||||||
|
|
||||||
|
### version
|
||||||
|
|
||||||
|
The `version` property tests the value of plugin version:
|
||||||
|
|
||||||
|
describe docker_plugin('cloudstor/aws') do
|
||||||
|
its('version') { should eq '0.11.0' }
|
||||||
|
end
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Test a Docker plugin
|
||||||
|
|
||||||
|
describe docker_plugin('rexray/ebs') do
|
||||||
|
it { should exist }
|
||||||
|
its('id') { should_not eq '0ac30b93ad40' }
|
||||||
|
its('version') { should eq '0.11.1' }
|
||||||
|
it { should be_enabled }
|
||||||
|
end
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Matchers
|
||||||
|
|
||||||
|
For a full list of available matchers, please visit our [Universal Matchers](https://www.inspec.io/docs/reference/matchers/).
|
||||||
|
|
||||||
|
### exist
|
||||||
|
|
||||||
|
The `exist` matcher tests if the plugin is available on the node:
|
||||||
|
|
||||||
|
describe docker_plugin('rexray/ebs') do
|
||||||
|
it { should exist }
|
||||||
|
end
|
||||||
|
|
||||||
|
### enabled
|
||||||
|
|
||||||
|
The `be_enabled` matches tests if the plugin is enabled
|
|
@ -128,6 +128,7 @@ require 'resources/directory'
|
||||||
require 'resources/docker'
|
require 'resources/docker'
|
||||||
require 'resources/docker_container'
|
require 'resources/docker_container'
|
||||||
require 'resources/docker_image'
|
require 'resources/docker_image'
|
||||||
|
require 'resources/docker_plugin'
|
||||||
require 'resources/docker_service'
|
require 'resources/docker_service'
|
||||||
require 'resources/elasticsearch'
|
require 'resources/elasticsearch'
|
||||||
require 'resources/etc_fstab'
|
require 'resources/etc_fstab'
|
||||||
|
|
|
@ -52,6 +52,20 @@ module Inspec::Resources
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DockerPluginFilter
|
||||||
|
filter = FilterTable.create
|
||||||
|
filter.add(:ids, field: 'id')
|
||||||
|
.add(:names, field: 'name')
|
||||||
|
.add(:versions, field: 'version')
|
||||||
|
.add(:enabled, field: 'enabled')
|
||||||
|
filter.connect(self, :plugins)
|
||||||
|
|
||||||
|
attr_reader :plugins
|
||||||
|
def initialize(plugins)
|
||||||
|
@plugins = plugins
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class DockerServiceFilter
|
class DockerServiceFilter
|
||||||
filter = FilterTable.create
|
filter = FilterTable.create
|
||||||
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
||||||
|
@ -89,6 +103,10 @@ module Inspec::Resources
|
||||||
its('repositories') { should_not include 'inssecure_image' }
|
its('repositories') { should_not include 'inssecure_image' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe docker.plugins.where { name == 'rexray/ebs' } do
|
||||||
|
it { should exist }
|
||||||
|
end
|
||||||
|
|
||||||
describe docker.services do
|
describe docker.services do
|
||||||
its('images') { should_not include 'inssecure_image' }
|
its('images') { should_not include 'inssecure_image' }
|
||||||
end
|
end
|
||||||
|
@ -119,6 +137,10 @@ module Inspec::Resources
|
||||||
DockerImageFilter.new(parse_images)
|
DockerImageFilter.new(parse_images)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def plugins
|
||||||
|
DockerPluginFilter.new(parse_plugins)
|
||||||
|
end
|
||||||
|
|
||||||
def services
|
def services
|
||||||
DockerServiceFilter.new(parse_services)
|
DockerServiceFilter.new(parse_services)
|
||||||
end
|
end
|
||||||
|
@ -226,5 +248,17 @@ module Inspec::Resources
|
||||||
warn 'Could not parse `docker images` output'
|
warn 'Could not parse `docker images` output'
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parse_plugins
|
||||||
|
plugins = inspec.command('docker plugin ls --format \'{"id": {{json .ID}}, "name": "{{ with split .Name ":"}}{{index . 0}}{{end}}", "version": "{{ with split .Name ":"}}{{index . 1}}{{end}}", "enabled": {{json .Enabled}} }\'').stdout
|
||||||
|
c_plugins = []
|
||||||
|
plugins.each_line { |entry|
|
||||||
|
c_plugins.push(JSON.parse(entry))
|
||||||
|
}
|
||||||
|
c_plugins
|
||||||
|
rescue JSON::ParserError => _e
|
||||||
|
warn 'Could not parse `docker plugin ls` output'
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
63
lib/resources/docker_plugin.rb
Normal file
63
lib/resources/docker_plugin.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
module Inspec::Resources
|
||||||
|
class DockerPlugin < Inspec.resource(1)
|
||||||
|
name 'docker_plugin'
|
||||||
|
supports platform: 'unix'
|
||||||
|
desc 'Retrieves info about docker plugins'
|
||||||
|
example "
|
||||||
|
describe docker_plugin('rexray/ebs') do
|
||||||
|
it { should exist }
|
||||||
|
its('id') { should_not eq '0ac30b93ad40' }
|
||||||
|
its('version') { should eq '0.11.1' }
|
||||||
|
it { should be_enabled }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe docker_plugin('alpine:latest') do
|
||||||
|
it { should exist }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe docker_plugin(id: '4a415e366388') do
|
||||||
|
it { should exist }
|
||||||
|
end
|
||||||
|
"
|
||||||
|
|
||||||
|
def initialize(opts = {})
|
||||||
|
# do sanitizion of input values
|
||||||
|
o = opts.dup
|
||||||
|
o = { name: opts } if opts.is_a?(String)
|
||||||
|
@opts = o
|
||||||
|
end
|
||||||
|
|
||||||
|
def exist?
|
||||||
|
object_info.entries.size == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def enabled?
|
||||||
|
object_info.enabled[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def id
|
||||||
|
object_info.ids[0] if object_info.entries.size == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def version
|
||||||
|
object_info.versions[0] if object_info.entries.size == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
plugin = @opts[:name] || @opts[:id]
|
||||||
|
"Docker plugin #{plugin}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def object_info
|
||||||
|
return @info if defined?(@info)
|
||||||
|
opts = @opts
|
||||||
|
@info = inspec.docker.plugins.where {
|
||||||
|
(name == opts[:name]) || (!id.nil? && !opts[:id].nil? && (id == opts[:id]))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -425,6 +425,8 @@ class MockLoader
|
||||||
"83c36bfade9375ae1feb91023cd1f7409b786fd992ad4013bf0f2259d33d6406" => cmd.call('docker-images'),
|
"83c36bfade9375ae1feb91023cd1f7409b786fd992ad4013bf0f2259d33d6406" => cmd.call('docker-images'),
|
||||||
# docker services
|
# docker services
|
||||||
%{docker service ls --format '{"ID": {{json .ID}}, "Name": {{json .Name}}, "Mode": {{json .Mode}}, "Replicas": {{json .Replicas}}, "Image": {{json .Image}}, "Ports": {{json .Ports}}}'} => cmd.call('docker-service-ls'),
|
%{docker service ls --format '{"ID": {{json .ID}}, "Name": {{json .Name}}, "Mode": {{json .Mode}}, "Replicas": {{json .Replicas}}, "Image": {{json .Image}}, "Ports": {{json .Ports}}}'} => cmd.call('docker-service-ls'),
|
||||||
|
# docker plugins
|
||||||
|
%{docker plugin ls --format '{"id": {{json .ID}}, "name": "{{ with split .Name ":"}}{{index . 0}}{{end}}", "version": "{{ with split .Name ":"}}{{index . 1}}{{end}}", "enabled": {{json .Enabled}} }'} => cmd.call('docker-plugin-ls'),
|
||||||
# modprobe for kernel_module
|
# modprobe for kernel_module
|
||||||
"modprobe --showconfig" => cmd.call('modprobe-config'),
|
"modprobe --showconfig" => cmd.call('modprobe-config'),
|
||||||
# get-process cmdlet for processes resource
|
# get-process cmdlet for processes resource
|
||||||
|
|
2
test/unit/mock/cmd/docker-plugin-ls
Normal file
2
test/unit/mock/cmd/docker-plugin-ls
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{"id": "6ea8176de74b", "name": "store/weaveworks/net-plugin", "version": "2.3.0", "enabled": true }
|
||||||
|
{"id": "771d3ee7c7ea", "name": "docker4x/cloudstor", "version": "18.03.1-ce-aws1", "enabled": false }
|
39
test/unit/resources/docker_plugin_test.rb
Normal file
39
test/unit/resources/docker_plugin_test.rb
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# author: Noel Georgi
|
||||||
|
|
||||||
|
require 'helper'
|
||||||
|
require 'inspec/resource'
|
||||||
|
|
||||||
|
describe 'Inspec::Resources::DockerContainer' do
|
||||||
|
describe 'docker_plugin' do
|
||||||
|
it 'check plugin parsing for docker4x/cloudstor' do
|
||||||
|
resource = load_resource('docker_plugin', 'docker4x/cloudstor')
|
||||||
|
_(resource.id).must_equal '771d3ee7c7ea'
|
||||||
|
_(resource.version).must_equal '18.03.1-ce-aws1'
|
||||||
|
_(resource.enabled?).must_equal false
|
||||||
|
_(resource.exist?).must_equal true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'check plugin parsing for store/weaveworks/net-plugin' do
|
||||||
|
resource = load_resource('docker_plugin', 'store/weaveworks/net-plugin')
|
||||||
|
_(resource.id).must_equal '6ea8176de74b'
|
||||||
|
_(resource.version).must_equal '2.3.0'
|
||||||
|
_(resource.enabled?).must_equal true
|
||||||
|
_(resource.exist?).must_equal true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'check plugin parsing when there are no plugins' do
|
||||||
|
resource = load_resource('docker_plugin')
|
||||||
|
assert_nil resource.id
|
||||||
|
assert_nil resource.version
|
||||||
|
assert_nil resource.id
|
||||||
|
assert_nil resource.enabled?
|
||||||
|
_(resource.exist?).must_equal false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prints as a docker resource' do
|
||||||
|
resource = load_resource('docker_plugin', 'store/weaveworks/net-plugin')
|
||||||
|
resource.to_s.must_equal 'Docker plugin store/weaveworks/net-plugin'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -24,6 +24,13 @@ describe 'Inspec::Resources::Docker' do
|
||||||
_(resource.services.images).must_equal ["foo/image:1.0", "foo/image:1.1", "bar:latest", "bar:latest"]
|
_(resource.services.images).must_equal ["foo/image:1.0", "foo/image:1.1", "bar:latest", "bar:latest"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'check docker plugins parsing' do
|
||||||
|
_(resource.plugins.ids).must_equal ["6ea8176de74b", "771d3ee7c7ea"]
|
||||||
|
_(resource.plugins.names).must_equal ["store/weaveworks/net-plugin", "docker4x/cloudstor"]
|
||||||
|
_(resource.plugins.versions).must_equal ["2.3.0", "18.03.1-ce-aws1"]
|
||||||
|
_(resource.plugins.enabled).must_equal [true, false]
|
||||||
|
end
|
||||||
|
|
||||||
it 'check docker version parsing' do
|
it 'check docker version parsing' do
|
||||||
_(resource.version.Server.Version).must_equal '17.03.0-ce'
|
_(resource.version.Server.Version).must_equal '17.03.0-ce'
|
||||||
_(resource.version.Client.Version).must_equal '17.03.0-ce'
|
_(resource.version.Client.Version).must_equal '17.03.0-ce'
|
||||||
|
|
Loading…
Reference in a new issue