Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(general): added cli argument for extra resources in report #3588

Merged
merged 6 commits into from
Oct 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions checkov/common/runners/runner_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ def print_reports(
cyclonedx_reports = []
csv_sbom_report = CSVSBOM()

try:
if config.skip_resources_without_violations:
for report in scan_reports:
report.extra_resources = set()
except AttributeError:
# config attribute wasn't set, defaults to False and print extra resources to report
pass

data_outputs: dict[str, str] = defaultdict(str)
for report in scan_reports:
if not report.is_empty():
Expand Down
4 changes: 4 additions & 0 deletions checkov/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,10 @@ def add_parser_args(parser: ArgumentParser) -> None:
parser.add('--summary-position', default='top', choices=SUMMARY_POSITIONS,
help='Chose whether the summary will be appended on top (before the checks results) or on bottom '
'(after check results), default is on top.')
parser.add('--skip-resources-without-violations',
help="exclude extra resources (resources without violations) from report output",
action='store_true',
env_var='CKV_SKIP_RESOURCES_WITHOUT_VIOLATIONS')


def get_external_checks_dir(config: Any) -> Any:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
@description('Virtual machine size (has to be at least the size of Standard_A3 to support 2 NICs)')
param virtualMachineSize string = 'Standard_DS1_v2'

@description('Default Admin username')
param adminUsername string

@description('Default Admin password')
@secure()
param adminPassword string

@description('Storage Account type for the VM and VM diagnostic storage')
@allowed([
'Standard_LRS'
'Premium_LRS'
])
param storageAccountType string = 'Standard_LRS'

@description('Location for all resources.')
param location string = resourceGroup().location

var virtualMachineName = 'VM-MultiNic'
var nic1Name = 'nic-1'
var nic2Name = 'nic-2'
var virtualNetworkName = 'virtualNetwork'
var subnet1Name = 'subnet-1'
var subnet2Name = 'subnet-2'
var publicIPAddressName = 'publicIp'
var diagStorageAccountName = 'diags${uniqueString(resourceGroup().id)}'
var networkSecurityGroupName = 'NSG'
var networkSecurityGroupName2 = '${subnet2Name}-nsg'

// This is the virtual machine that you're building.
resource vm 'Microsoft.Compute/virtualMachines@2020-06-01' = {
name: virtualMachineName
location: location
properties: {
osProfile: {
computerName: virtualMachineName
adminUsername: adminUsername
adminPassword: adminPassword
windowsConfiguration: {
provisionVMAgent: true
}
}
hardwareProfile: {
vmSize: virtualMachineSize
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: '2019-Datacenter'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
properties: {
primary: true
}
id: nic1.id
}
{
properties: {
primary: false
}
id: nic2.id
}
]
}
diagnosticsProfile: {
bootDiagnostics: {
enabled: true
storageUri: diagsAccount.properties.primaryEndpoints.blob
}
}
}
}

resource diagsAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = {
// checkov:skip=CKV_AZURE_35: just skip it
name: diagStorageAccountName
location: location
sku: {
name: storageAccountType
}
kind: 'StorageV2'
}

// Simple Network Security Group for subnet2
resource nsg2 'Microsoft.Network/networkSecurityGroups@2020-06-01' = {
name: networkSecurityGroupName2
location: location
}

// This will build a Virtual Network.
resource vnet 'Microsoft.Network/virtualNetworks@2020-06-01' = {
name: virtualNetworkName
location: location
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/16'
]
}
subnets: [
{
name: subnet1Name
properties: {
addressPrefix: '10.0.0.0/24'
}
}
{
name: subnet2Name
properties: {
addressPrefix: '10.0.1.0/24'
networkSecurityGroup: {
id: nsg2.id
}
}
}
]
}
}

// This will be your Primary NIC
resource nic1 'Microsoft.Network/networkInterfaces@2020-06-01' = {
name: nic1Name
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, subnet1Name)
}
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: pip.id
}
}
}
]
networkSecurityGroup: {
id: nsg.id
}
}
}

// This will be your Secondary NIC
resource nic2 'Microsoft.Network/networkInterfaces@2020-06-01' = {
name: nic2Name
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, subnet2Name)
}
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
}

// Public IP for your Primary NIC
resource pip 'Microsoft.Network/publicIPAddresses@2020-06-01' = {
name: publicIPAddressName
location: location
properties: {
publicIPAllocationMethod: 'Dynamic'
}
}

// Network Security Group (NSG) for your Primary NIC
resource nsg 'Microsoft.Network/networkSecurityGroups@2020-06-01' = {
name: networkSecurityGroupName
location: location
properties: {
securityRules: [
{
name: 'default-allow-rdp'
properties: {
priority: 1000
sourceAddressPrefix: '*'
protocol: 'Tcp'
destinationPortRange: '3389'
access: 'Allow'
direction: 'Inbound'
sourcePortRange: '*'
destinationAddressPrefix: '*'
}
}
]
}
}
60 changes: 60 additions & 0 deletions tests/common/runner_registry/test_runner_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from checkov.main import DEFAULT_RUNNERS
from checkov.runner_filter import RunnerFilter
from checkov.terraform.runner import Runner as tf_runner
from checkov.bicep.runner import Runner as bicep_runner
import re


Expand Down Expand Up @@ -296,5 +297,64 @@ def test_non_compact_json_output(capsys):
assert 'code_block' in captured.out


def test_extra_resources_in_report(capsys):
# given
PelegLi marked this conversation as resolved.
Show resolved Hide resolved
test_files_dir = os.path.dirname(os.path.realpath(__file__)) + "/example_bicep_with_empty_resources"
runner_filter = RunnerFilter(framework=None, checks=None, skip_checks=None)
runner_registry = RunnerRegistry(
banner, runner_filter, bicep_runner()
)
reports = runner_registry.run(root_folder=test_files_dir)

config = argparse.Namespace(
file=['./example_bicep_with_empty_resources/playground.bicep'],
compact=False,
output=['json'],
quiet=False,
soft_fail=False,
soft_fail_on=None,
hard_fail_on=None,
output_file_path=None,
use_enforcement_rules=None
)

# when
runner_registry.print_reports(scan_reports=reports, config=config)

# then
for report in reports:
assert len(report.extra_resources) > 0


def test_extra_resources_removed_from_report(capsys):
# given
test_files_dir = os.path.dirname(os.path.realpath(__file__)) + "/example_bicep_with_empty_resources"
runner_filter = RunnerFilter(framework=None, checks=None, skip_checks=None)
runner_registry = RunnerRegistry(
banner, runner_filter, bicep_runner()
)
reports = runner_registry.run(root_folder=test_files_dir)

config = argparse.Namespace(
file=['./example_bicep_with_empty_resources/playground.bicep'],
compact=False,
output=['json'],
quiet=False,
soft_fail=False,
soft_fail_on=None,
hard_fail_on=None,
output_file_path=None,
use_enforcement_rules=None,
skip_resources_without_violations=True
)

# when
runner_registry.print_reports(scan_reports=reports, config=config)

# then
for report in reports:
assert len(report.extra_resources) == 0


if __name__ == "__main__":
unittest.main()