inspec 2.1.81 → 2.1.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +101 -101
- data/CHANGELOG.md +3183 -3177
- data/Gemfile +56 -56
- data/LICENSE +14 -14
- data/MAINTAINERS.md +33 -33
- data/MAINTAINERS.toml +52 -52
- data/README.md +453 -453
- data/Rakefile +349 -349
- data/bin/inspec +12 -12
- data/docs/.gitignore +2 -2
- data/docs/README.md +41 -40
- data/docs/dev/control-eval.md +61 -61
- data/docs/dsl_inspec.md +258 -258
- data/docs/dsl_resource.md +100 -100
- data/docs/glossary.md +99 -99
- data/docs/habitat.md +191 -191
- data/docs/inspec_and_friends.md +114 -114
- data/docs/matchers.md +169 -169
- data/docs/migration.md +293 -293
- data/docs/platforms.md +118 -118
- data/docs/plugin_kitchen_inspec.md +50 -50
- data/docs/profiles.md +378 -378
- data/docs/reporters.md +105 -105
- data/docs/resources/aide_conf.md.erb +75 -75
- data/docs/resources/apache.md.erb +67 -67
- data/docs/resources/apache_conf.md.erb +68 -68
- data/docs/resources/apt.md.erb +71 -71
- data/docs/resources/audit_policy.md.erb +47 -47
- data/docs/resources/auditd.md.erb +79 -79
- data/docs/resources/auditd_conf.md.erb +68 -68
- data/docs/resources/aws_cloudtrail_trail.md.erb +155 -155
- data/docs/resources/aws_cloudtrail_trails.md.erb +86 -86
- data/docs/resources/aws_cloudwatch_alarm.md.erb +91 -91
- data/docs/resources/aws_cloudwatch_log_metric_filter.md.erb +154 -154
- data/docs/resources/aws_config_delivery_channel.md.erb +101 -101
- data/docs/resources/aws_config_recorder.md.erb +86 -86
- data/docs/resources/aws_ec2_instance.md.erb +112 -112
- data/docs/resources/aws_ec2_instances.md.erb +79 -79
- data/docs/resources/aws_iam_access_key.md.erb +129 -129
- data/docs/resources/aws_iam_access_keys.md.erb +204 -204
- data/docs/resources/aws_iam_group.md.erb +64 -64
- data/docs/resources/aws_iam_groups.md.erb +49 -49
- data/docs/resources/aws_iam_password_policy.md.erb +82 -82
- data/docs/resources/aws_iam_policies.md.erb +87 -87
- data/docs/resources/aws_iam_policy.md.erb +245 -245
- data/docs/resources/aws_iam_role.md.erb +69 -69
- data/docs/resources/aws_iam_root_user.md.erb +76 -76
- data/docs/resources/aws_iam_user.md.erb +120 -120
- data/docs/resources/aws_iam_users.md.erb +279 -279
- data/docs/resources/aws_kms_key.md.erb +177 -177
- data/docs/resources/aws_kms_keys.md.erb +89 -89
- data/docs/resources/aws_rds_instance.md.erb +66 -66
- data/docs/resources/aws_route_table.md.erb +53 -53
- data/docs/resources/aws_route_tables.md.erb +55 -55
- data/docs/resources/aws_s3_bucket.md.erb +146 -146
- data/docs/resources/aws_s3_bucket_object.md.erb +89 -89
- data/docs/resources/aws_s3_buckets.md.erb +59 -59
- data/docs/resources/aws_security_group.md.erb +296 -296
- data/docs/resources/aws_security_groups.md.erb +97 -97
- data/docs/resources/aws_sns_subscription.md.erb +130 -130
- data/docs/resources/aws_sns_topic.md.erb +69 -69
- data/docs/resources/aws_sns_topics.md.erb +58 -58
- data/docs/resources/aws_subnet.md.erb +140 -140
- data/docs/resources/aws_subnets.md.erb +132 -132
- data/docs/resources/aws_vpc.md.erb +125 -125
- data/docs/resources/aws_vpcs.md.erb +125 -125
- data/docs/resources/azure_generic_resource.md.erb +171 -171
- data/docs/resources/azure_resource_group.md.erb +284 -284
- data/docs/resources/azure_virtual_machine.md.erb +347 -347
- data/docs/resources/azure_virtual_machine_data_disk.md.erb +224 -224
- data/docs/resources/bash.md.erb +75 -75
- data/docs/resources/bond.md.erb +90 -90
- data/docs/resources/bridge.md.erb +57 -57
- data/docs/resources/bsd_service.md.erb +67 -67
- data/docs/resources/chocolatey_package.md.erb +58 -58
- data/docs/resources/command.md.erb +138 -138
- data/docs/resources/cpan.md.erb +79 -79
- data/docs/resources/cran.md.erb +64 -64
- data/docs/resources/crontab.md.erb +89 -89
- data/docs/resources/csv.md.erb +54 -54
- data/docs/resources/dh_params.md.erb +205 -205
- data/docs/resources/directory.md.erb +30 -30
- data/docs/resources/docker.md.erb +219 -219
- data/docs/resources/docker_container.md.erb +103 -103
- data/docs/resources/docker_image.md.erb +94 -94
- data/docs/resources/docker_service.md.erb +114 -114
- data/docs/resources/elasticsearch.md.erb +242 -242
- data/docs/resources/etc_fstab.md.erb +125 -125
- data/docs/resources/etc_group.md.erb +75 -75
- data/docs/resources/etc_hosts.md.erb +78 -78
- data/docs/resources/etc_hosts_allow.md.erb +74 -74
- data/docs/resources/etc_hosts_deny.md.erb +74 -74
- data/docs/resources/file.md.erb +526 -526
- data/docs/resources/filesystem.md.erb +41 -41
- data/docs/resources/firewalld.md.erb +107 -107
- data/docs/resources/gem.md.erb +79 -79
- data/docs/resources/group.md.erb +61 -61
- data/docs/resources/grub_conf.md.erb +101 -101
- data/docs/resources/host.md.erb +86 -86
- data/docs/resources/http.md.erb +197 -197
- data/docs/resources/iis_app.md.erb +122 -122
- data/docs/resources/iis_site.md.erb +135 -135
- data/docs/resources/inetd_conf.md.erb +94 -94
- data/docs/resources/ini.md.erb +76 -76
- data/docs/resources/interface.md.erb +58 -58
- data/docs/resources/iptables.md.erb +64 -64
- data/docs/resources/json.md.erb +63 -63
- data/docs/resources/kernel_module.md.erb +120 -120
- data/docs/resources/kernel_parameter.md.erb +53 -53
- data/docs/resources/key_rsa.md.erb +85 -85
- data/docs/resources/launchd_service.md.erb +57 -57
- data/docs/resources/limits_conf.md.erb +75 -75
- data/docs/resources/login_defs.md.erb +71 -71
- data/docs/resources/mount.md.erb +69 -69
- data/docs/resources/mssql_session.md.erb +60 -60
- data/docs/resources/mysql_conf.md.erb +99 -99
- data/docs/resources/mysql_session.md.erb +74 -74
- data/docs/resources/nginx.md.erb +79 -79
- data/docs/resources/nginx_conf.md.erb +138 -138
- data/docs/resources/npm.md.erb +60 -60
- data/docs/resources/ntp_conf.md.erb +60 -60
- data/docs/resources/oneget.md.erb +53 -53
- data/docs/resources/oracledb_session.md.erb +52 -52
- data/docs/resources/os.md.erb +141 -141
- data/docs/resources/os_env.md.erb +91 -91
- data/docs/resources/package.md.erb +120 -120
- data/docs/resources/packages.md.erb +67 -67
- data/docs/resources/parse_config.md.erb +103 -103
- data/docs/resources/parse_config_file.md.erb +138 -138
- data/docs/resources/passwd.md.erb +141 -141
- data/docs/resources/pip.md.erb +67 -67
- data/docs/resources/port.md.erb +137 -137
- data/docs/resources/postgres_conf.md.erb +79 -79
- data/docs/resources/postgres_hba_conf.md.erb +93 -93
- data/docs/resources/postgres_ident_conf.md.erb +76 -76
- data/docs/resources/postgres_session.md.erb +69 -69
- data/docs/resources/powershell.md.erb +102 -102
- data/docs/resources/processes.md.erb +109 -109
- data/docs/resources/rabbitmq_config.md.erb +41 -41
- data/docs/resources/registry_key.md.erb +158 -158
- data/docs/resources/runit_service.md.erb +57 -57
- data/docs/resources/security_policy.md.erb +47 -47
- data/docs/resources/service.md.erb +121 -121
- data/docs/resources/shadow.md.erb +146 -146
- data/docs/resources/ssh_config.md.erb +73 -73
- data/docs/resources/sshd_config.md.erb +83 -83
- data/docs/resources/ssl.md.erb +119 -119
- data/docs/resources/sys_info.md.erb +42 -42
- data/docs/resources/systemd_service.md.erb +57 -57
- data/docs/resources/sysv_service.md.erb +57 -57
- data/docs/resources/upstart_service.md.erb +57 -57
- data/docs/resources/user.md.erb +140 -140
- data/docs/resources/users.md.erb +127 -127
- data/docs/resources/vbscript.md.erb +55 -55
- data/docs/resources/virtualization.md.erb +57 -57
- data/docs/resources/windows_feature.md.erb +47 -47
- data/docs/resources/windows_hotfix.md.erb +53 -53
- data/docs/resources/windows_task.md.erb +95 -95
- data/docs/resources/wmi.md.erb +81 -81
- data/docs/resources/x509_certificate.md.erb +151 -151
- data/docs/resources/xinetd_conf.md.erb +156 -156
- data/docs/resources/xml.md.erb +85 -85
- data/docs/resources/yaml.md.erb +69 -69
- data/docs/resources/yum.md.erb +98 -98
- data/docs/resources/zfs_dataset.md.erb +53 -53
- data/docs/resources/zfs_pool.md.erb +47 -47
- data/docs/ruby_usage.md +203 -203
- data/docs/shared/matcher_be.md.erb +1 -1
- data/docs/shared/matcher_cmp.md.erb +43 -43
- data/docs/shared/matcher_eq.md.erb +3 -3
- data/docs/shared/matcher_include.md.erb +1 -1
- data/docs/shared/matcher_match.md.erb +1 -1
- data/docs/shell.md +217 -217
- data/examples/README.md +8 -8
- data/examples/inheritance/README.md +65 -65
- data/examples/inheritance/controls/example.rb +14 -14
- data/examples/inheritance/inspec.yml +15 -15
- data/examples/kitchen-ansible/.kitchen.yml +25 -25
- data/examples/kitchen-ansible/Gemfile +19 -19
- data/examples/kitchen-ansible/README.md +53 -53
- data/examples/kitchen-ansible/files/nginx.repo +6 -6
- data/examples/kitchen-ansible/tasks/main.yml +16 -16
- data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
- data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
- data/examples/kitchen-chef/.kitchen.yml +20 -20
- data/examples/kitchen-chef/Berksfile +3 -3
- data/examples/kitchen-chef/Gemfile +19 -19
- data/examples/kitchen-chef/README.md +27 -27
- data/examples/kitchen-chef/metadata.rb +7 -7
- data/examples/kitchen-chef/recipes/default.rb +6 -6
- data/examples/kitchen-chef/recipes/nginx.rb +30 -30
- data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
- data/examples/kitchen-puppet/.kitchen.yml +23 -23
- data/examples/kitchen-puppet/Gemfile +20 -20
- data/examples/kitchen-puppet/Puppetfile +25 -25
- data/examples/kitchen-puppet/README.md +53 -53
- data/examples/kitchen-puppet/manifests/site.pp +33 -33
- data/examples/kitchen-puppet/metadata.json +11 -11
- data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
- data/examples/meta-profile/README.md +37 -37
- data/examples/meta-profile/controls/example.rb +13 -13
- data/examples/meta-profile/inspec.yml +13 -13
- data/examples/profile-attribute.yml +2 -2
- data/examples/profile-attribute/README.md +14 -14
- data/examples/profile-attribute/controls/example.rb +11 -11
- data/examples/profile-attribute/inspec.yml +8 -8
- data/examples/profile-aws/controls/iam_password_policy_expiration.rb +8 -8
- data/examples/profile-aws/controls/iam_password_policy_max_age.rb +8 -8
- data/examples/profile-aws/controls/iam_root_user_mfa.rb +8 -8
- data/examples/profile-aws/controls/iam_users_access_key_age.rb +8 -8
- data/examples/profile-aws/controls/iam_users_console_users_mfa.rb +8 -8
- data/examples/profile-aws/inspec.yml +11 -11
- data/examples/profile-azure/controls/azure_resource_group_example.rb +24 -24
- data/examples/profile-azure/controls/azure_vm_example.rb +29 -29
- data/examples/profile-azure/inspec.yml +11 -11
- data/examples/profile-sensitive/README.md +29 -29
- data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
- data/examples/profile-sensitive/controls/sensitive.rb +9 -9
- data/examples/profile-sensitive/inspec.yml +8 -8
- data/examples/profile/README.md +48 -48
- data/examples/profile/controls/example.rb +23 -23
- data/examples/profile/controls/gordon.rb +36 -36
- data/examples/profile/controls/meta.rb +34 -34
- data/examples/profile/inspec.yml +10 -10
- data/examples/profile/libraries/gordon_config.rb +59 -59
- data/inspec.gemspec +49 -49
- data/lib/bundles/README.md +3 -3
- data/lib/bundles/inspec-artifact.rb +7 -7
- data/lib/bundles/inspec-artifact/README.md +1 -1
- data/lib/bundles/inspec-artifact/cli.rb +277 -277
- data/lib/bundles/inspec-compliance.rb +16 -16
- data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
- data/lib/bundles/inspec-compliance/README.md +193 -193
- data/lib/bundles/inspec-compliance/api.rb +360 -360
- data/lib/bundles/inspec-compliance/api/login.rb +193 -193
- data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
- data/lib/bundles/inspec-compliance/cli.rb +260 -260
- data/lib/bundles/inspec-compliance/configuration.rb +103 -103
- data/lib/bundles/inspec-compliance/http.rb +125 -125
- data/lib/bundles/inspec-compliance/support.rb +36 -36
- data/lib/bundles/inspec-compliance/target.rb +112 -112
- data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
- data/lib/bundles/inspec-habitat.rb +12 -12
- data/lib/bundles/inspec-habitat/cli.rb +36 -36
- data/lib/bundles/inspec-habitat/log.rb +10 -10
- data/lib/bundles/inspec-habitat/profile.rb +391 -391
- data/lib/bundles/inspec-init.rb +8 -8
- data/lib/bundles/inspec-init/README.md +31 -31
- data/lib/bundles/inspec-init/cli.rb +97 -97
- data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
- data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
- data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
- data/lib/bundles/inspec-supermarket.rb +13 -13
- data/lib/bundles/inspec-supermarket/README.md +45 -45
- data/lib/bundles/inspec-supermarket/api.rb +84 -84
- data/lib/bundles/inspec-supermarket/cli.rb +73 -73
- data/lib/bundles/inspec-supermarket/target.rb +34 -34
- data/lib/fetchers/git.rb +163 -163
- data/lib/fetchers/local.rb +74 -74
- data/lib/fetchers/mock.rb +35 -35
- data/lib/fetchers/url.rb +247 -247
- data/lib/inspec.rb +24 -24
- data/lib/inspec/archive/tar.rb +29 -29
- data/lib/inspec/archive/zip.rb +19 -19
- data/lib/inspec/backend.rb +93 -93
- data/lib/inspec/base_cli.rb +368 -368
- data/lib/inspec/cached_fetcher.rb +66 -66
- data/lib/inspec/cli.rb +292 -292
- data/lib/inspec/completions/bash.sh.erb +45 -45
- data/lib/inspec/completions/fish.sh.erb +34 -34
- data/lib/inspec/completions/zsh.sh.erb +61 -61
- data/lib/inspec/control_eval_context.rb +179 -179
- data/lib/inspec/dependencies/cache.rb +72 -72
- data/lib/inspec/dependencies/dependency_set.rb +92 -92
- data/lib/inspec/dependencies/lockfile.rb +115 -115
- data/lib/inspec/dependencies/requirement.rb +123 -123
- data/lib/inspec/dependencies/resolver.rb +86 -86
- data/lib/inspec/describe.rb +27 -27
- data/lib/inspec/dsl.rb +66 -66
- data/lib/inspec/dsl_shared.rb +33 -33
- data/lib/inspec/env_printer.rb +157 -157
- data/lib/inspec/errors.rb +14 -14
- data/lib/inspec/exceptions.rb +12 -12
- data/lib/inspec/expect.rb +45 -45
- data/lib/inspec/fetcher.rb +45 -45
- data/lib/inspec/file_provider.rb +275 -275
- data/lib/inspec/formatters.rb +3 -3
- data/lib/inspec/formatters/base.rb +259 -259
- data/lib/inspec/formatters/json_rspec.rb +20 -20
- data/lib/inspec/formatters/show_progress.rb +12 -12
- data/lib/inspec/library_eval_context.rb +58 -58
- data/lib/inspec/log.rb +11 -11
- data/lib/inspec/metadata.rb +247 -247
- data/lib/inspec/method_source.rb +24 -24
- data/lib/inspec/objects.rb +14 -14
- data/lib/inspec/objects/attribute.rb +75 -75
- data/lib/inspec/objects/control.rb +61 -61
- data/lib/inspec/objects/describe.rb +92 -92
- data/lib/inspec/objects/each_loop.rb +36 -36
- data/lib/inspec/objects/list.rb +15 -15
- data/lib/inspec/objects/or_test.rb +40 -40
- data/lib/inspec/objects/ruby_helper.rb +15 -15
- data/lib/inspec/objects/tag.rb +27 -27
- data/lib/inspec/objects/test.rb +87 -87
- data/lib/inspec/objects/value.rb +27 -27
- data/lib/inspec/plugins.rb +60 -60
- data/lib/inspec/plugins/cli.rb +24 -24
- data/lib/inspec/plugins/fetcher.rb +86 -86
- data/lib/inspec/plugins/resource.rb +135 -135
- data/lib/inspec/plugins/secret.rb +15 -15
- data/lib/inspec/plugins/source_reader.rb +40 -40
- data/lib/inspec/polyfill.rb +12 -12
- data/lib/inspec/profile.rb +513 -513
- data/lib/inspec/profile_context.rb +208 -208
- data/lib/inspec/profile_vendor.rb +66 -66
- data/lib/inspec/reporters.rb +60 -60
- data/lib/inspec/reporters/automate.rb +76 -76
- data/lib/inspec/reporters/base.rb +25 -25
- data/lib/inspec/reporters/cli.rb +356 -356
- data/lib/inspec/reporters/json.rb +117 -117
- data/lib/inspec/reporters/json_min.rb +48 -48
- data/lib/inspec/reporters/junit.rb +78 -78
- data/lib/inspec/require_loader.rb +33 -33
- data/lib/inspec/resource.rb +190 -190
- data/lib/inspec/rule.rb +280 -280
- data/lib/inspec/runner.rb +345 -345
- data/lib/inspec/runner_mock.rb +41 -41
- data/lib/inspec/runner_rspec.rb +175 -175
- data/lib/inspec/runtime_profile.rb +26 -26
- data/lib/inspec/schema.rb +213 -213
- data/lib/inspec/secrets.rb +19 -19
- data/lib/inspec/secrets/yaml.rb +30 -30
- data/lib/inspec/shell.rb +220 -220
- data/lib/inspec/shell_detector.rb +90 -90
- data/lib/inspec/source_reader.rb +29 -29
- data/lib/inspec/version.rb +8 -8
- data/lib/matchers/matchers.rb +339 -339
- data/lib/resource_support/aws.rb +50 -50
- data/lib/resource_support/aws/aws_backend_base.rb +12 -12
- data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -12
- data/lib/resource_support/aws/aws_plural_resource_mixin.rb +21 -21
- data/lib/resource_support/aws/aws_resource_mixin.rb +66 -66
- data/lib/resource_support/aws/aws_singular_resource_mixin.rb +24 -24
- data/lib/resources/aide_conf.rb +151 -151
- data/lib/resources/apache.rb +48 -48
- data/lib/resources/apache_conf.rb +149 -149
- data/lib/resources/apt.rb +149 -149
- data/lib/resources/audit_policy.rb +63 -63
- data/lib/resources/auditd.rb +231 -231
- data/lib/resources/auditd_conf.rb +46 -46
- data/lib/resources/aws/aws_cloudtrail_trail.rb +93 -93
- data/lib/resources/aws/aws_cloudtrail_trails.rb +47 -47
- data/lib/resources/aws/aws_cloudwatch_alarm.rb +62 -62
- data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +100 -100
- data/lib/resources/aws/aws_config_delivery_channel.rb +70 -70
- data/lib/resources/aws/aws_config_recorder.rb +93 -93
- data/lib/resources/aws/aws_ec2_instance.rb +157 -157
- data/lib/resources/aws/aws_ec2_instances.rb +64 -64
- data/lib/resources/aws/aws_iam_access_key.rb +106 -106
- data/lib/resources/aws/aws_iam_access_keys.rb +149 -149
- data/lib/resources/aws/aws_iam_group.rb +58 -58
- data/lib/resources/aws/aws_iam_groups.rb +52 -52
- data/lib/resources/aws/aws_iam_password_policy.rb +116 -116
- data/lib/resources/aws/aws_iam_policies.rb +53 -53
- data/lib/resources/aws/aws_iam_policy.rb +291 -291
- data/lib/resources/aws/aws_iam_role.rb +55 -55
- data/lib/resources/aws/aws_iam_root_user.rb +78 -78
- data/lib/resources/aws/aws_iam_user.rb +142 -142
- data/lib/resources/aws/aws_iam_users.rb +146 -146
- data/lib/resources/aws/aws_kms_key.rb +96 -96
- data/lib/resources/aws/aws_kms_keys.rb +53 -53
- data/lib/resources/aws/aws_rds_instance.rb +71 -71
- data/lib/resources/aws/aws_route_table.rb +63 -63
- data/lib/resources/aws/aws_route_tables.rb +60 -60
- data/lib/resources/aws/aws_s3_bucket.rb +137 -137
- data/lib/resources/aws/aws_s3_bucket_object.rb +82 -82
- data/lib/resources/aws/aws_s3_buckets.rb +51 -51
- data/lib/resources/aws/aws_security_group.rb +249 -249
- data/lib/resources/aws/aws_security_groups.rb +68 -68
- data/lib/resources/aws/aws_sns_subscription.rb +78 -78
- data/lib/resources/aws/aws_sns_topic.rb +53 -53
- data/lib/resources/aws/aws_sns_topics.rb +56 -56
- data/lib/resources/aws/aws_subnet.rb +88 -88
- data/lib/resources/aws/aws_subnets.rb +53 -53
- data/lib/resources/aws/aws_vpc.rb +73 -73
- data/lib/resources/aws/aws_vpcs.rb +52 -52
- data/lib/resources/azure/azure_backend.rb +377 -377
- data/lib/resources/azure/azure_generic_resource.rb +59 -59
- data/lib/resources/azure/azure_resource_group.rb +152 -152
- data/lib/resources/azure/azure_virtual_machine.rb +264 -264
- data/lib/resources/azure/azure_virtual_machine_data_disk.rb +134 -134
- data/lib/resources/bash.rb +35 -35
- data/lib/resources/bond.rb +69 -69
- data/lib/resources/bridge.rb +122 -122
- data/lib/resources/chocolatey_package.rb +78 -78
- data/lib/resources/command.rb +73 -73
- data/lib/resources/cpan.rb +58 -58
- data/lib/resources/cran.rb +64 -64
- data/lib/resources/crontab.rb +169 -169
- data/lib/resources/csv.rb +56 -56
- data/lib/resources/dh_params.rb +77 -77
- data/lib/resources/directory.rb +25 -25
- data/lib/resources/docker.rb +236 -236
- data/lib/resources/docker_container.rb +89 -89
- data/lib/resources/docker_image.rb +83 -83
- data/lib/resources/docker_object.rb +57 -57
- data/lib/resources/docker_service.rb +90 -90
- data/lib/resources/elasticsearch.rb +169 -169
- data/lib/resources/etc_fstab.rb +94 -94
- data/lib/resources/etc_group.rb +154 -154
- data/lib/resources/etc_hosts.rb +66 -66
- data/lib/resources/etc_hosts_allow_deny.rb +112 -112
- data/lib/resources/file.rb +298 -298
- data/lib/resources/filesystem.rb +31 -31
- data/lib/resources/firewalld.rb +143 -143
- data/lib/resources/gem.rb +70 -70
- data/lib/resources/groups.rb +215 -215
- data/lib/resources/grub_conf.rb +227 -227
- data/lib/resources/host.rb +306 -306
- data/lib/resources/http.rb +253 -253
- data/lib/resources/iis_app.rb +101 -101
- data/lib/resources/iis_site.rb +148 -148
- data/lib/resources/inetd_conf.rb +54 -54
- data/lib/resources/ini.rb +29 -29
- data/lib/resources/interface.rb +129 -129
- data/lib/resources/iptables.rb +80 -80
- data/lib/resources/json.rb +111 -111
- data/lib/resources/kernel_module.rb +107 -107
- data/lib/resources/kernel_parameter.rb +58 -58
- data/lib/resources/key_rsa.rb +63 -63
- data/lib/resources/limits_conf.rb +46 -46
- data/lib/resources/login_def.rb +57 -57
- data/lib/resources/mount.rb +88 -88
- data/lib/resources/mssql_session.rb +101 -101
- data/lib/resources/mysql.rb +82 -82
- data/lib/resources/mysql_conf.rb +127 -127
- data/lib/resources/mysql_session.rb +85 -85
- data/lib/resources/nginx.rb +96 -96
- data/lib/resources/nginx_conf.rb +226 -226
- data/lib/resources/npm.rb +48 -48
- data/lib/resources/ntp_conf.rb +51 -51
- data/lib/resources/oneget.rb +71 -71
- data/lib/resources/oracledb_session.rb +139 -139
- data/lib/resources/os.rb +36 -36
- data/lib/resources/os_env.rb +86 -86
- data/lib/resources/package.rb +370 -370
- data/lib/resources/packages.rb +111 -111
- data/lib/resources/parse_config.rb +112 -112
- data/lib/resources/passwd.rb +76 -76
- data/lib/resources/pip.rb +130 -130
- data/lib/resources/platform.rb +109 -109
- data/lib/resources/port.rb +771 -771
- data/lib/resources/postgres.rb +131 -131
- data/lib/resources/postgres_conf.rb +114 -114
- data/lib/resources/postgres_hba_conf.rb +90 -90
- data/lib/resources/postgres_ident_conf.rb +79 -79
- data/lib/resources/postgres_session.rb +71 -71
- data/lib/resources/powershell.rb +67 -67
- data/lib/resources/processes.rb +204 -204
- data/lib/resources/rabbitmq_conf.rb +51 -51
- data/lib/resources/registry_key.rb +297 -297
- data/lib/resources/security_policy.rb +180 -180
- data/lib/resources/service.rb +794 -794
- data/lib/resources/shadow.rb +159 -159
- data/lib/resources/ssh_conf.rb +97 -97
- data/lib/resources/ssl.rb +99 -99
- data/lib/resources/sys_info.rb +28 -28
- data/lib/resources/toml.rb +32 -32
- data/lib/resources/users.rb +654 -654
- data/lib/resources/vbscript.rb +68 -68
- data/lib/resources/virtualization.rb +247 -247
- data/lib/resources/windows_feature.rb +84 -84
- data/lib/resources/windows_hotfix.rb +35 -35
- data/lib/resources/windows_task.rb +102 -102
- data/lib/resources/wmi.rb +110 -110
- data/lib/resources/x509_certificate.rb +137 -137
- data/lib/resources/xinetd.rb +106 -106
- data/lib/resources/xml.rb +46 -46
- data/lib/resources/yaml.rb +43 -43
- data/lib/resources/yum.rb +180 -180
- data/lib/resources/zfs_dataset.rb +60 -60
- data/lib/resources/zfs_pool.rb +49 -49
- data/lib/source_readers/flat.rb +39 -39
- data/lib/source_readers/inspec.rb +75 -75
- data/lib/utils/command_wrapper.rb +27 -27
- data/lib/utils/convert.rb +12 -12
- data/lib/utils/database_helpers.rb +77 -77
- data/lib/utils/enumerable_delegation.rb +9 -9
- data/lib/utils/erlang_parser.rb +192 -192
- data/lib/utils/file_reader.rb +25 -25
- data/lib/utils/filter.rb +273 -273
- data/lib/utils/filter_array.rb +27 -27
- data/lib/utils/find_files.rb +47 -47
- data/lib/utils/hash.rb +41 -41
- data/lib/utils/json_log.rb +18 -18
- data/lib/utils/latest_version.rb +22 -22
- data/lib/utils/modulator.rb +12 -12
- data/lib/utils/nginx_parser.rb +105 -105
- data/lib/utils/object_traversal.rb +49 -49
- data/lib/utils/parser.rb +274 -274
- data/lib/utils/pkey_reader.rb +15 -15
- data/lib/utils/plugin_registry.rb +93 -93
- data/lib/utils/simpleconfig.rb +120 -120
- data/lib/utils/spdx.rb +13 -13
- data/lib/utils/spdx.txt +343 -343
- metadata +3 -3
@@ -1 +1 @@
|
|
1
|
-
# TODO
|
1
|
+
# TODO
|
@@ -1,277 +1,277 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
require 'base64'
|
4
|
-
require 'openssl'
|
5
|
-
require 'pathname'
|
6
|
-
require 'set'
|
7
|
-
require 'tempfile'
|
8
|
-
require 'yaml'
|
9
|
-
|
10
|
-
# Notes:
|
11
|
-
#
|
12
|
-
# Generate keys
|
13
|
-
# The initial implementation uses 2048 bit RSA key pairs (public + private).
|
14
|
-
# Public keys must be available for a customer to install and verify an artifact.
|
15
|
-
# Private keys should be stored in a secure location and NOT be distributed.
|
16
|
-
# (They're only for creating artifacts).
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# .IAF file format
|
20
|
-
# .iaf = "Inspec Artifact File", easy to rename if you'd like something more appropriate.
|
21
|
-
# The iaf file wraps a binary artifact with some metadata. The first implementation
|
22
|
-
# looks like this:
|
23
|
-
#
|
24
|
-
# INSPEC-PROFILE-1
|
25
|
-
# name_of_signing_key
|
26
|
-
# algorithm
|
27
|
-
# signature
|
28
|
-
# <empty line>
|
29
|
-
# binary-blob
|
30
|
-
# <eof>
|
31
|
-
#
|
32
|
-
# Let's look at each line:
|
33
|
-
# INSPEC-PROFILE-1:
|
34
|
-
# This is the artifact version descriptor. It should't change unless the
|
35
|
-
# format of the archive changes.
|
36
|
-
#
|
37
|
-
# name_of_signing_key
|
38
|
-
# The name of the public key that can be used to verify an artifact
|
39
|
-
#
|
40
|
-
# algorithm
|
41
|
-
# The digest used to sign, I picked SHA512 to start with.
|
42
|
-
# If we support multiple digests, we'll need to have the verify() method
|
43
|
-
# support each digest.
|
44
|
-
#
|
45
|
-
# signature
|
46
|
-
# The result of passing the binary artifact through the digest algorithm above.
|
47
|
-
# Result is base64 encoded.
|
48
|
-
#
|
49
|
-
# <empty line>
|
50
|
-
# We use an empty line to separate artifact header from artifact body (binary blob).
|
51
|
-
# The artifact body can be anything you like.
|
52
|
-
#
|
53
|
-
# binary-blob
|
54
|
-
# A binary blob, most likely a .tar.gz or tar.xz file. We'll need to pick one and
|
55
|
-
# stick with it as part of the "INSPEC-PROFILE-1" artifact version. If we change block
|
56
|
-
# format, the artifact version descriptor must be incremented, and the sign()
|
57
|
-
# and verify() methods must be updated to support a newer version.
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# Key revocation
|
61
|
-
# This implementation doesn't support key revocation. However, a customer
|
62
|
-
# can remove the public cert file before installation, and artifacts will then
|
63
|
-
# fail verification.
|
64
|
-
#
|
65
|
-
# Key locations
|
66
|
-
# This implementation uses the current working directory to find public and
|
67
|
-
# private keys. We should establish a common key directory (similar to /hab/cache/keys
|
68
|
-
# or ~/.hab/cache/keys in Habitat).
|
69
|
-
#
|
70
|
-
# Extracting artifacts outside of Inspec
|
71
|
-
# As in Habitat, the artifact format for Inspec allows the use of common
|
72
|
-
# Unix tools to read the header and body of an artifact.
|
73
|
-
# To extract the header from a .iaf:
|
74
|
-
# sed '/^$/q' foo.iaf
|
75
|
-
# To extract the raw content from a .iaf:
|
76
|
-
# sed '1,/^$/d' foo.iaf
|
77
|
-
|
78
|
-
module Artifact
|
79
|
-
KEY_BITS=2048
|
80
|
-
KEY_ALG=OpenSSL::PKey::RSA
|
81
|
-
|
82
|
-
INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'
|
83
|
-
INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
|
84
|
-
|
85
|
-
ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
|
86
|
-
ARTIFACT_DIGEST_NAME='SHA512'
|
87
|
-
|
88
|
-
VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
|
89
|
-
VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
|
90
|
-
|
91
|
-
SIGNED_PROFILE_SUFFIX='iaf'
|
92
|
-
SIGNED_REPORT_SUFFIX='iar'
|
93
|
-
class CLI < Inspec::BaseCLI
|
94
|
-
namespace 'artifact'
|
95
|
-
|
96
|
-
# TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
|
97
|
-
def self.banner(command, _namespace = nil, _subcommand = false)
|
98
|
-
"#{basename} #{subcommand_prefix} #{command.usage}"
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.subcommand_prefix
|
102
|
-
namespace
|
103
|
-
end
|
104
|
-
|
105
|
-
desc 'generate', 'Generate a RSA key pair for signing and verification'
|
106
|
-
option :keyname, type: :string, required: true,
|
107
|
-
desc: 'Desriptive name of key'
|
108
|
-
option :keydir, type: :string, default: './',
|
109
|
-
desc: 'Directory to search for keys'
|
110
|
-
def generate_keys
|
111
|
-
puts 'Generating keys'
|
112
|
-
keygen
|
113
|
-
end
|
114
|
-
|
115
|
-
desc 'sign-profile', 'Create a signed .iaf artifact'
|
116
|
-
option :profile, type: :string, required: true,
|
117
|
-
desc: 'Path to profile directory'
|
118
|
-
option :keyname, type: :string, required: true,
|
119
|
-
desc: 'Desriptive name of key'
|
120
|
-
def sign_profile
|
121
|
-
profile_sign
|
122
|
-
end
|
123
|
-
|
124
|
-
desc 'verify-profile', 'Verify a signed .iaf artifact'
|
125
|
-
option :infile, type: :string, required: true,
|
126
|
-
desc: '.iaf file to verify'
|
127
|
-
def verify_profile
|
128
|
-
profile_verify
|
129
|
-
end
|
130
|
-
|
131
|
-
desc 'install-profile', 'Verify and install a signed .iaf artifact'
|
132
|
-
option :infile, type: :string, required: true,
|
133
|
-
desc: '.iaf file to install'
|
134
|
-
option :destdir, type: :string, required: true,
|
135
|
-
desc: 'Installation directory'
|
136
|
-
def install_profile
|
137
|
-
profile_install
|
138
|
-
end
|
139
|
-
|
140
|
-
private
|
141
|
-
|
142
|
-
def keygen
|
143
|
-
key = KEY_ALG.new KEY_BITS
|
144
|
-
puts 'Generating private key'
|
145
|
-
open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
|
146
|
-
puts 'Generating public key'
|
147
|
-
open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
|
148
|
-
end
|
149
|
-
|
150
|
-
def read_profile_metadata(path_to_profile)
|
151
|
-
begin
|
152
|
-
p = Pathname.new(path_to_profile)
|
153
|
-
p = p.join('inspec.yml')
|
154
|
-
if not p.exist?
|
155
|
-
raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
|
156
|
-
end
|
157
|
-
yaml = YAML.load_file(p.to_s)
|
158
|
-
yaml = yaml.to_hash
|
159
|
-
|
160
|
-
if not yaml.key? 'name'
|
161
|
-
raise 'Profile is invalid, name is not defined'
|
162
|
-
end
|
163
|
-
|
164
|
-
if not yaml.key? 'version'
|
165
|
-
raise 'Profile is invalid, version is not defined'
|
166
|
-
end
|
167
|
-
rescue => e
|
168
|
-
# rewrap it and pass it up to the CLI
|
169
|
-
raise "Error reading Inspec profile metadata: #{e}"
|
170
|
-
end
|
171
|
-
|
172
|
-
yaml
|
173
|
-
end
|
174
|
-
|
175
|
-
def profile_compress(path_to_profile, profile_md, workdir)
|
176
|
-
profile_name = profile_md['name']
|
177
|
-
profile_version = profile_md['version']
|
178
|
-
outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
|
179
|
-
`tar czf #{outfile_name} -C #{path_to_profile} .`
|
180
|
-
outfile_name
|
181
|
-
end
|
182
|
-
|
183
|
-
def profile_sign
|
184
|
-
Dir.mktmpdir do |workdir|
|
185
|
-
puts "Signing #{options['profile']} with key #{options['keyname']}"
|
186
|
-
path_to_profile = options['profile']
|
187
|
-
profile_md = read_profile_metadata(path_to_profile)
|
188
|
-
artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
|
189
|
-
tarfile = profile_compress(path_to_profile, profile_md, workdir)
|
190
|
-
content = IO.binread(tarfile)
|
191
|
-
signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
|
192
|
-
sha = ARTIFACT_DIGEST.new
|
193
|
-
signature = signing_key.sign sha, content
|
194
|
-
# convert the signature to Base64
|
195
|
-
signature_base64 = Base64.encode64(signature)
|
196
|
-
tar_content = IO.binread(tarfile)
|
197
|
-
File.open(artifact_filename, 'wb') do |f|
|
198
|
-
f.puts(INSPEC_PROFILE_VERSION_1)
|
199
|
-
f.puts(options['keyname'])
|
200
|
-
f.puts(ARTIFACT_DIGEST_NAME)
|
201
|
-
f.puts(signature_base64)
|
202
|
-
f.puts('') # newline separates artifact header with body
|
203
|
-
f.write(tar_content)
|
204
|
-
end
|
205
|
-
puts "Successfully generated #{artifact_filename}"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def valid_header?(file_alg, file_version, file_keyname)
|
210
|
-
public_keyfile = "#{file_keyname}.pem.pub"
|
211
|
-
puts "Looking for #{public_keyfile} to verify artifact"
|
212
|
-
if !File.exist? public_keyfile
|
213
|
-
raise "Can't find #{public_keyfile}"
|
214
|
-
end
|
215
|
-
|
216
|
-
raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
|
217
|
-
raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
|
218
|
-
end
|
219
|
-
|
220
|
-
def verify(file_to_verifiy, &content_block)
|
221
|
-
f = File.open(file_to_verifiy, 'r')
|
222
|
-
file_version = f.readline.strip!
|
223
|
-
file_keyname = f.readline.strip!
|
224
|
-
file_alg = f.readline.strip!
|
225
|
-
|
226
|
-
file_sig = ''
|
227
|
-
# the signature is multi-line
|
228
|
-
while (line = f.readline) != "\n"
|
229
|
-
file_sig += line
|
230
|
-
end
|
231
|
-
file_sig.strip!
|
232
|
-
f.close
|
233
|
-
|
234
|
-
valid_header?(file_alg, file_version, file_keyname)
|
235
|
-
|
236
|
-
public_keyfile = "#{file_keyname}.pem.pub"
|
237
|
-
verification_key = KEY_ALG.new File.read public_keyfile
|
238
|
-
|
239
|
-
f = File.open(file_to_verifiy, 'r')
|
240
|
-
while f.readline != "\n" do end
|
241
|
-
content = f.read
|
242
|
-
|
243
|
-
signature = Base64.decode64(file_sig)
|
244
|
-
digest = ARTIFACT_DIGEST.new
|
245
|
-
if verification_key.verify digest, signature, content
|
246
|
-
content_block.yield(content)
|
247
|
-
else
|
248
|
-
puts 'Artifact is invalid'
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def profile_verify
|
253
|
-
file_to_verifiy = options['infile']
|
254
|
-
puts "Verifying #{file_to_verifiy}"
|
255
|
-
verify(file_to_verifiy) do ||
|
256
|
-
puts 'Artifact is valid'
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def profile_install
|
261
|
-
puts 'Installing profile'
|
262
|
-
file_to_verifiy = options['infile']
|
263
|
-
dest_dir = options['destdir']
|
264
|
-
verify(file_to_verifiy) do |content|
|
265
|
-
Dir.mktmpdir do |workdir|
|
266
|
-
tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
|
267
|
-
File.write(tmpfile, content)
|
268
|
-
puts "Installing to #{dest_dir}"
|
269
|
-
`tar xzf #{tmpfile} -C #{dest_dir}`
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# register the subcommand to Inspec CLI registry
|
276
|
-
Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
|
277
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'base64'
|
4
|
+
require 'openssl'
|
5
|
+
require 'pathname'
|
6
|
+
require 'set'
|
7
|
+
require 'tempfile'
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
# Notes:
|
11
|
+
#
|
12
|
+
# Generate keys
|
13
|
+
# The initial implementation uses 2048 bit RSA key pairs (public + private).
|
14
|
+
# Public keys must be available for a customer to install and verify an artifact.
|
15
|
+
# Private keys should be stored in a secure location and NOT be distributed.
|
16
|
+
# (They're only for creating artifacts).
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# .IAF file format
|
20
|
+
# .iaf = "Inspec Artifact File", easy to rename if you'd like something more appropriate.
|
21
|
+
# The iaf file wraps a binary artifact with some metadata. The first implementation
|
22
|
+
# looks like this:
|
23
|
+
#
|
24
|
+
# INSPEC-PROFILE-1
|
25
|
+
# name_of_signing_key
|
26
|
+
# algorithm
|
27
|
+
# signature
|
28
|
+
# <empty line>
|
29
|
+
# binary-blob
|
30
|
+
# <eof>
|
31
|
+
#
|
32
|
+
# Let's look at each line:
|
33
|
+
# INSPEC-PROFILE-1:
|
34
|
+
# This is the artifact version descriptor. It should't change unless the
|
35
|
+
# format of the archive changes.
|
36
|
+
#
|
37
|
+
# name_of_signing_key
|
38
|
+
# The name of the public key that can be used to verify an artifact
|
39
|
+
#
|
40
|
+
# algorithm
|
41
|
+
# The digest used to sign, I picked SHA512 to start with.
|
42
|
+
# If we support multiple digests, we'll need to have the verify() method
|
43
|
+
# support each digest.
|
44
|
+
#
|
45
|
+
# signature
|
46
|
+
# The result of passing the binary artifact through the digest algorithm above.
|
47
|
+
# Result is base64 encoded.
|
48
|
+
#
|
49
|
+
# <empty line>
|
50
|
+
# We use an empty line to separate artifact header from artifact body (binary blob).
|
51
|
+
# The artifact body can be anything you like.
|
52
|
+
#
|
53
|
+
# binary-blob
|
54
|
+
# A binary blob, most likely a .tar.gz or tar.xz file. We'll need to pick one and
|
55
|
+
# stick with it as part of the "INSPEC-PROFILE-1" artifact version. If we change block
|
56
|
+
# format, the artifact version descriptor must be incremented, and the sign()
|
57
|
+
# and verify() methods must be updated to support a newer version.
|
58
|
+
#
|
59
|
+
#
|
60
|
+
# Key revocation
|
61
|
+
# This implementation doesn't support key revocation. However, a customer
|
62
|
+
# can remove the public cert file before installation, and artifacts will then
|
63
|
+
# fail verification.
|
64
|
+
#
|
65
|
+
# Key locations
|
66
|
+
# This implementation uses the current working directory to find public and
|
67
|
+
# private keys. We should establish a common key directory (similar to /hab/cache/keys
|
68
|
+
# or ~/.hab/cache/keys in Habitat).
|
69
|
+
#
|
70
|
+
# Extracting artifacts outside of Inspec
|
71
|
+
# As in Habitat, the artifact format for Inspec allows the use of common
|
72
|
+
# Unix tools to read the header and body of an artifact.
|
73
|
+
# To extract the header from a .iaf:
|
74
|
+
# sed '/^$/q' foo.iaf
|
75
|
+
# To extract the raw content from a .iaf:
|
76
|
+
# sed '1,/^$/d' foo.iaf
|
77
|
+
|
78
|
+
module Artifact
|
79
|
+
KEY_BITS=2048
|
80
|
+
KEY_ALG=OpenSSL::PKey::RSA
|
81
|
+
|
82
|
+
INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'
|
83
|
+
INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
|
84
|
+
|
85
|
+
ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
|
86
|
+
ARTIFACT_DIGEST_NAME='SHA512'
|
87
|
+
|
88
|
+
VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
|
89
|
+
VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
|
90
|
+
|
91
|
+
SIGNED_PROFILE_SUFFIX='iaf'
|
92
|
+
SIGNED_REPORT_SUFFIX='iar'
|
93
|
+
class CLI < Inspec::BaseCLI
|
94
|
+
namespace 'artifact'
|
95
|
+
|
96
|
+
# TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
|
97
|
+
def self.banner(command, _namespace = nil, _subcommand = false)
|
98
|
+
"#{basename} #{subcommand_prefix} #{command.usage}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.subcommand_prefix
|
102
|
+
namespace
|
103
|
+
end
|
104
|
+
|
105
|
+
desc 'generate', 'Generate a RSA key pair for signing and verification'
|
106
|
+
option :keyname, type: :string, required: true,
|
107
|
+
desc: 'Desriptive name of key'
|
108
|
+
option :keydir, type: :string, default: './',
|
109
|
+
desc: 'Directory to search for keys'
|
110
|
+
def generate_keys
|
111
|
+
puts 'Generating keys'
|
112
|
+
keygen
|
113
|
+
end
|
114
|
+
|
115
|
+
desc 'sign-profile', 'Create a signed .iaf artifact'
|
116
|
+
option :profile, type: :string, required: true,
|
117
|
+
desc: 'Path to profile directory'
|
118
|
+
option :keyname, type: :string, required: true,
|
119
|
+
desc: 'Desriptive name of key'
|
120
|
+
def sign_profile
|
121
|
+
profile_sign
|
122
|
+
end
|
123
|
+
|
124
|
+
desc 'verify-profile', 'Verify a signed .iaf artifact'
|
125
|
+
option :infile, type: :string, required: true,
|
126
|
+
desc: '.iaf file to verify'
|
127
|
+
def verify_profile
|
128
|
+
profile_verify
|
129
|
+
end
|
130
|
+
|
131
|
+
desc 'install-profile', 'Verify and install a signed .iaf artifact'
|
132
|
+
option :infile, type: :string, required: true,
|
133
|
+
desc: '.iaf file to install'
|
134
|
+
option :destdir, type: :string, required: true,
|
135
|
+
desc: 'Installation directory'
|
136
|
+
def install_profile
|
137
|
+
profile_install
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def keygen
|
143
|
+
key = KEY_ALG.new KEY_BITS
|
144
|
+
puts 'Generating private key'
|
145
|
+
open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
|
146
|
+
puts 'Generating public key'
|
147
|
+
open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
|
148
|
+
end
|
149
|
+
|
150
|
+
def read_profile_metadata(path_to_profile)
|
151
|
+
begin
|
152
|
+
p = Pathname.new(path_to_profile)
|
153
|
+
p = p.join('inspec.yml')
|
154
|
+
if not p.exist?
|
155
|
+
raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
|
156
|
+
end
|
157
|
+
yaml = YAML.load_file(p.to_s)
|
158
|
+
yaml = yaml.to_hash
|
159
|
+
|
160
|
+
if not yaml.key? 'name'
|
161
|
+
raise 'Profile is invalid, name is not defined'
|
162
|
+
end
|
163
|
+
|
164
|
+
if not yaml.key? 'version'
|
165
|
+
raise 'Profile is invalid, version is not defined'
|
166
|
+
end
|
167
|
+
rescue => e
|
168
|
+
# rewrap it and pass it up to the CLI
|
169
|
+
raise "Error reading Inspec profile metadata: #{e}"
|
170
|
+
end
|
171
|
+
|
172
|
+
yaml
|
173
|
+
end
|
174
|
+
|
175
|
+
def profile_compress(path_to_profile, profile_md, workdir)
|
176
|
+
profile_name = profile_md['name']
|
177
|
+
profile_version = profile_md['version']
|
178
|
+
outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
|
179
|
+
`tar czf #{outfile_name} -C #{path_to_profile} .`
|
180
|
+
outfile_name
|
181
|
+
end
|
182
|
+
|
183
|
+
def profile_sign
|
184
|
+
Dir.mktmpdir do |workdir|
|
185
|
+
puts "Signing #{options['profile']} with key #{options['keyname']}"
|
186
|
+
path_to_profile = options['profile']
|
187
|
+
profile_md = read_profile_metadata(path_to_profile)
|
188
|
+
artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
|
189
|
+
tarfile = profile_compress(path_to_profile, profile_md, workdir)
|
190
|
+
content = IO.binread(tarfile)
|
191
|
+
signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
|
192
|
+
sha = ARTIFACT_DIGEST.new
|
193
|
+
signature = signing_key.sign sha, content
|
194
|
+
# convert the signature to Base64
|
195
|
+
signature_base64 = Base64.encode64(signature)
|
196
|
+
tar_content = IO.binread(tarfile)
|
197
|
+
File.open(artifact_filename, 'wb') do |f|
|
198
|
+
f.puts(INSPEC_PROFILE_VERSION_1)
|
199
|
+
f.puts(options['keyname'])
|
200
|
+
f.puts(ARTIFACT_DIGEST_NAME)
|
201
|
+
f.puts(signature_base64)
|
202
|
+
f.puts('') # newline separates artifact header with body
|
203
|
+
f.write(tar_content)
|
204
|
+
end
|
205
|
+
puts "Successfully generated #{artifact_filename}"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def valid_header?(file_alg, file_version, file_keyname)
|
210
|
+
public_keyfile = "#{file_keyname}.pem.pub"
|
211
|
+
puts "Looking for #{public_keyfile} to verify artifact"
|
212
|
+
if !File.exist? public_keyfile
|
213
|
+
raise "Can't find #{public_keyfile}"
|
214
|
+
end
|
215
|
+
|
216
|
+
raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
|
217
|
+
raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
|
218
|
+
end
|
219
|
+
|
220
|
+
def verify(file_to_verifiy, &content_block)
|
221
|
+
f = File.open(file_to_verifiy, 'r')
|
222
|
+
file_version = f.readline.strip!
|
223
|
+
file_keyname = f.readline.strip!
|
224
|
+
file_alg = f.readline.strip!
|
225
|
+
|
226
|
+
file_sig = ''
|
227
|
+
# the signature is multi-line
|
228
|
+
while (line = f.readline) != "\n"
|
229
|
+
file_sig += line
|
230
|
+
end
|
231
|
+
file_sig.strip!
|
232
|
+
f.close
|
233
|
+
|
234
|
+
valid_header?(file_alg, file_version, file_keyname)
|
235
|
+
|
236
|
+
public_keyfile = "#{file_keyname}.pem.pub"
|
237
|
+
verification_key = KEY_ALG.new File.read public_keyfile
|
238
|
+
|
239
|
+
f = File.open(file_to_verifiy, 'r')
|
240
|
+
while f.readline != "\n" do end
|
241
|
+
content = f.read
|
242
|
+
|
243
|
+
signature = Base64.decode64(file_sig)
|
244
|
+
digest = ARTIFACT_DIGEST.new
|
245
|
+
if verification_key.verify digest, signature, content
|
246
|
+
content_block.yield(content)
|
247
|
+
else
|
248
|
+
puts 'Artifact is invalid'
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def profile_verify
|
253
|
+
file_to_verifiy = options['infile']
|
254
|
+
puts "Verifying #{file_to_verifiy}"
|
255
|
+
verify(file_to_verifiy) do ||
|
256
|
+
puts 'Artifact is valid'
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def profile_install
|
261
|
+
puts 'Installing profile'
|
262
|
+
file_to_verifiy = options['infile']
|
263
|
+
dest_dir = options['destdir']
|
264
|
+
verify(file_to_verifiy) do |content|
|
265
|
+
Dir.mktmpdir do |workdir|
|
266
|
+
tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
|
267
|
+
File.write(tmpfile, content)
|
268
|
+
puts "Installing to #{dest_dir}"
|
269
|
+
`tar xzf #{tmpfile} -C #{dest_dir}`
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# register the subcommand to Inspec CLI registry
|
276
|
+
Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
|
277
|
+
end
|