def test_send_metrics(mocker):

    expected_response = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.3',
            'type':
            '1.3 Ensure credentials unused for 90 days or greater are disabled',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'unit-test',
            'region': mocker.ANY
        },
        'Version': 'v1.2.0TEST'
    }

    os.environ['sendAnonymousMetrics'] = 'Yes'

    finding = utils.load_test_data(test_data + 'cis_1-3-iamuser1.json',
                                   my_region).get('detail').get('findings')[0]

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()

    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)

    metrics = Metrics({"detail-type": "unit-test"})
    metrics_data = metrics.get_metrics_from_finding(finding)

    send_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    metrics.send_metrics(metrics_data)

    send_metrics.assert_called_with(expected_response)
Пример #2
0
def notify(finding, message, logger, cwlogs=False, sechub=True, sns=False):
    """
    Consolidates several outputs to a single call.

    Attributes
    ----------
    finding: finding object for which notification is to be done
    message: dict of notification data:
        {
            'Account': string,
            'AffectedOject': string,
            'Remediation': string,
            'State': string,
            'Note': string
        }
    logger: logger object for logging to stdout
    cwlogs: boolean - log to application log group?
    sechub: boolean - update Security Hub notes on the finding?
    sns: boolean - send to sns topic?
    """

    remediation_adj = ''
    if 'State' in message:
        if message['State'] == 'RESOLVED':
            remediation_adj = 'remediation was successful'
        elif message['State'] == 'INITIAL':
            remediation_adj = 'remediation started'
        elif message['State'] == 'FAILED':
            remediation_adj = 'remediation failed. Please remediate manually'
        if 'Note' not in message or not message['Note']:
            message['Note'] = '"' + message.get('Remediation', 'error missing remediation') +\
            '" ' + remediation_adj
    else:
        message['State'] = 'INFO'

    if 'Note' not in message or not message['Note']:
        message['Note'] = 'error - missing note'

    #send metrics
    try:
        metrics_data = message['metrics_data']
        metrics = Metrics({'detail-type': 'None'})
        metrics_data['status'] = message['State']
        metrics.send_metrics(metrics_data)
    except Exception as e:
        logger.error(e)
        logger.error('Failed to send metrics')

    # lambda logs - always
    logger.info(
        message.get('State', 'INFO') + ': ' + message.get('Note') +\
        ', Account Id: ' + message.get('Account', 'error') + \
        ', Resource: ' + message.get('AffectedObject', 'error')
    )

    # log to application log
    if cwlogs:
        # to take advantage of buffering, the caller controls the
        # connection.
        cwlogs.add_message(
            message.get('State') + ': ' + message.get('Note') +\
            ', Account Id: ' + message.get('Account', 'error') + \
            ', Resource: ' + message.get('AffectedObject', 'error')
        )

    if sechub:
        if message.get('State') == 'RESOLVED':
            finding.resolve(message.get('State') + ': ' + message.get('Note'))
        elif message.get('State') == 'INITIAL':
            finding.flag(message.get('State') + ': ' + message.get('Note'))
        else:
            finding.update_text(
                message.get('State', 'INFO') + ': ' + message.get('Note'))

    if sns:
        try:
            sns.postit('SO0111-SHARR_Topic', message, AWS_REGION)
        except Exception as e:
            logger.error(e)
            logger.error('Unable to send to sns')