Git Product home page Git Product logo

aws-iot-device-defender-agent-sdk-python's Introduction

AWS IoT Device Defender Agent SDK (Python)

Example implementation of an AWS IoT Device Defender metrics collection agent, and other Device Defender Python samples.

On starting up for the first time - the DD agent publishes the metric values read from the network stats to DD, without computing any metric values delta. It does this because when it starts up it does not have any information of the previously collected metric values. The side-effect of this is the device's metrics will indicate a large spike each time the device restarts or the agent is restarted which can cause false-positives. Now, we have updated the agent to not send any metrics if it cannot compute the delta.

The provided sample agent can be used as a basis to implement a custom metrics collection agent.

Prerequisites

Minimum System Requirements

The Following requirements are shared with the AWS IoT Device SDK for Python

  • Python 3.5+ for X.509 certificate-based mutual authentication via port 8883 and MQTT over WebSocket protocol with AWS Signature Version 4 authentication
  • Python 3.5+ for X.509 certificate-based mutual authentication via port 443
  • OpenSSL version 1.0.1+ (TLS version 1.2) compiled with the Python executable for X.509 certificate-based mutual authentication

Connect your Device to AWS IoT

If you have never connected your device to AWS IoT before, please follow the Getting Started with AWS IoT Guide. Make sure you note the location of your certificates, you will need to provide the location of these to the Device Defender Sample Agent.

Notes on the sample agent implementation

client id: The sample agent requires a client id that will also be used as the "Thing Name". This only for the sake of making the sample easy to get started with. To customize this behavior, you can modify the way the agent generates the MQTT topic for publishing metrics reports, to use a value other than client id as the thing name portion of the topic.

metric selection: The sample agent attempts to gather all supported Device Defender metrics. Depending on your platform requirements and use case, you may wish to customize your agent to a subset of the metrics.

Quickstart

Installation

  1. Clone the repository
git clone https://github.com/aws-samples/aws-iot-device-defender-agent-sdk-python.git
  1. Install Using pip

Pip is the easiest way to install the sample agent, it will take care of installing dependencies

pip install /path/to/sample/package

Running the Sample Agent

python agent.py --endpoint <your.custom.endpoint.amazonaws.com>  --rootCA </path/to/rootca>  --cert </path/to/cert> --key <path/to/key> --format json -i 300 -id <ThingName>

Command line options

To see a summary of all commandline options:

python agent.py --help

Test Metrics Collection Locally

python collector.py -n 1 -s 1

Custom Metric Integration

The sample agent has a flag allowing it to publish custom metrics

python agent.py --include-custom-metrics --endpoint <your.custom.endpoint.amazonaws.com>  --rootCA </path/to/rootca>  --cert </path/to/cert> --key <path/to/key> --format json -i 300 -id <ThingName>

This flag will tell the agent to publish the custom metric cpu_usage, a number float representing the current cpu usage as a percent. How this looks in the generated report can be seen in the sample report below.

We can run the command seen below to create the custom_metric for cpu_usage.

aws iot create-custom-metric --metric-name "cpu_usage" --metric-type "number" --client-request-token "access-test" --region us-east-1

After creating this custom_metric you will be able to create security profiles that use it.

aws iot create-security-profile \
--security-profile-name CpuUsageIssue \
--security-profile-description "High-Cpu-Usage"  \
--behaviors "[{\"name\":\"great-than-75\",\"metric\":\"cpu_usage\",\"criteria\":{\"comparisonOperator\":\"greater-than\",\"value\":{\"count\":75},\"consecutiveDatapointsToAlarm\":5,\"consecutiveDatapointsToClear\":1}}]" \
--region us-east-1

AWS IoT Greengrass Integration

Overview

AWS IoT Device Defender can be used in conjunction with AWS Greengrass. Integration follows the standard Greengrass lambda deployment model, making it easy to add AWS IoT Device Defender security to your Greengrass Core devices.

Prerequisites

  1. Greengrass environment setup
  2. Greengrass core configured and running
  3. Ensure you can successfully deploy and run a lambda on your core

Using Device Defender with Greengrass Core devices

You can deploy a Device Defender to your Greengrass core in two ways:

  1. Using the pre-built Greengrass Device Defender Connector (recommended)
  2. Create a lambda package manually

Using Greengrass Connector

The Device Defender Greengrass Connector provides the most streamlined and automated means of deploy the Device Defender agent to your Greengrass core, and is the recommended method of using Device Defender with Greengrass.

For detailed information about using Greengrass Connectors see Getting Started with Greengrass Connectors For information about configuring the Device Defender Connector see Device Defender Connector Details

  1. Create a local resource to allow your lambda to collect metrics from the Greengrass Core host
    • Follow the instructions here
    • Use the following parameters:
      • Resource Name: Core_Proc
      • Type: Volume
      • Source Path: /proc
      • Destination Path: /host_proc (make sure the same value is configured for the PROCFS_PATH environment variable above)
      • Group owner file access permission: "Automatically add OS group permissions of the Linux group that owns the resource"
      • Associate the resource with your metrics lambda
  2. From the detail page of your Greengrass Group, click "Connectors" in the left-hand menu
  3. Click the "Add a Connector" button
  4. In the "Select a connector" screen, select the "Device Defender" connector from the list, click "Next"
  5. On the "Configure parameters" screen, select the resource you created in Step 1, in the "Resource for /proc" box
  6. In the "Metrics reporting interval" box, enter 300, or larger if you wish to use a longer reporting interval
  7. Click the "add" button
  8. Deploy your connector to your Greengrass Group

Create Your Lambda Package Manually

For this portion will be following the general process outlined here

Note: Due to platform-specific binary extensions in the psutil package, this process should be performed on the platform where you plan to deploy your lambda.

  1. Clone the AWS IoT Device Defender Python Samples Repository

    git clone https://github.com/aws-samples/aws-iot-device-defender-agent-sdk-python.git
  2. Create, and activate a virtual environment (optional, recommended)

    pip install virtualenv
    virtualenv metrics_lambda_environment
    source metrics_lambda_environment/bin/activate
  3. Install the AWS IoT Device Defender sample agent in the virtual environment Install from PyPi

    pip install AWSIoTDeviceDefenderAgentSDK

    Install from downloaded source

    cd aws-iot-device-defender-agent-sdk-python
    #This must be run from the same directory as setup.py
    pip install .
  4. Create an empty directory to assemble your lambda, we will refer to this as your "lambda directory"

    mkdir metrics_lambda
    cd metrics_lambda
  5. Complete steps 1-4 from this guide
  6. Unzip the Greengrass python sdk into your lambda directory

    unzip ../aws_greengrass_core_sdk/sdk/python_sdk_1_1_0.zip
    cp -R ../aws_greengrass_core_sdk/examples/HelloWorld/greengrass_common .
    cp -R ../aws_greengrass_core_sdk/examples/HelloWorld/greengrasssdk .
    cp -R ../aws_greengrass_core_sdk/examples/HelloWorld/greengrass_ipc_python_sdk .
  7. Copy the AWSIoTDeviceDefenderAgentSDK module to the root level of your lambda

    cp -R ../aws-iot-device-defender-agent-sdk-python/AWSIoTDeviceDefenderAgentSDK .
  8. Copy the Greengrass agent to the root level of your lambda directory

    cp ../aws-iot-device-defender-agent-sdk-python/samples/greengrass/greengrass_core_metrics_agent/greengrass_defender_agent.py .
  9. Copy the dependencies from your virtual environment or your system, into the the root level of your lambda

    cp -R ../metrics_lambda_environment/lib/python2.7/site-packages/psutil .
    cp -R ../metrics_lambda_environment/lib/python2.7/site-packages/cbor .
  10. Create your lambda zipfile Note: you should perform this command in the root level of your lambda directory

    rm *.zip
    zip -r greengrass_defender_metrics_lambda.zip *

Configure and deploy your Greengrass Lambda

  1. Upload your lambda zip file
  2. Select the Python 2.7 runtime, and enter greengrass_defender_agent.function_handler in the Handler field
  3. Configure your lambda as a long-lived lambda
  4. Configure the following environment variables:
    • SAMPLE_INTERVAL_SECONDS: The metrics generation interval. The default is 300 seconds. Note: 5 minutes (300 seconds) is the shortest reporting interval supported by AWS IoT Device Defender
    • PROCFS_PATH: The destination path that you will configure for your /proc resource as shown below.
  5. Configure a subscription from your lambda to the AWS IoT Cloud Note: For AWS IoT Device Defender, a subscription from AWS IoT Cloud to your lambda is not required
  6. Create a local resource to allow your lambda to collect metrics from the Greengrass Core host
    • Follow the instructions here
    • Use the following parameters:
      • Resource Name: Core_Proc
      • Type: Volume
      • Source Path: /proc
      • Destination Path: /host_proc (make sure the same value is configured for the PROCFS_PATH environment variable above)
      • Group owner file access permission: "Automatically add OS group permissions of the Linux group that owns the resource"
      • Associate the resource with your metrics lambda
  7. Deploy your connector to your Greengrass Group

Troubleshooting

Reviewing AWS IoT Device Defender device metrics using AWS IoT Console
  1. Temporarily modify your publish topic in your Greengrass lambda to something such as metrics/test
  2. Deploy the lambda
  3. Add a subscription to the temporary topic in the "Test" section of the iot console, shortly you should the metrics your Greengrass Core is emitting

Metrics Report Details

Overall Structure

Long Name Short Name Required Type Constraints Notes
header hed Y Object Complete block required for well-formed report
metrics met Y Object Complete block required for well-formed report
custom_metrics cmet N Object Complete block required for well-formed report

Header Block

Long Name Short Name Requi red Type Constr aints Notes
report _id rid Y Inte ger Monotonically increasing value, epoch timestamp recommended
versio n v Y Stri ng Major. Minor Minor increments with addition of field, major increments if metrics removed

Metrics Block

TCP Connections
Long Name Short Name Parent Element Required Type Constraints Notes
tcp_connections tc metrics N Object
established_connections ec tcp_connections N List ESTABLISHED TCP State
connections cs established_connections N List
remote_addr rad connections Y Number ip:port ip can be ipv6 or ipv4
local_port lp connections N Number >0
local_interface li connections N String interface name
total t established_connections N Number >= 0 Number established connections
Listening TCP Ports
Long Name Short Name Parent Element Required Type Constraints Notes
listening_tcp_ports tp metrics N Object
ports pts listening_tcp_ports N List > 0
port pt ports N Number >= 0 ports should be numbers > 0
interface if ports N String Interface Name
total t listening_tcp_ports N Number >= 0
Listening UDP Ports
Long Name Short Name Parent Element Required Type Constraints Notes
listening_udp_ports up metrics N Object
ports pts listening_udp_ports N List > 0
port pt ports N Number > 0 ports should be numbers > 0
interface if ports N String Interface Name
total t listening_udp_ports N Number >= 0
Network Stats
Long Name Short Name Parent Element Required Type Constraints Notes
network_stats ns metrics N Object
bytes_in bi network_stats N Number Delta Metric, >= 0
bytes_out bo network_stats N Number Delta Metric, >= 0
packets_in pi network_stats N Number Delta Metric, >= 0
packets_out po network_stats N Number Delta Metric, >= 0
Custom Metrics
Long Name Short Name Parent Element Required Type Constraints Notes
cpu_usage cpu custom_metrics N Number

Sample Metrics Reports

Long Field Names

{
    "header": {
        "report_id": 1529963534,
        "version": "1.0"
    },
    "metrics": {
        "listening_tcp_ports": {
            "ports": [
                {
                    "interface": "eth0",
                    "port": 24800
                },
                {
                    "interface": "eth0",
                    "port": 22
                },
                {
                    "interface": "eth0",
                    "port": 53
                }
            ],
            "total": 3
        },
        "listening_udp_ports": {
            "ports": [
                {
                    "interface": "eth0",
                    "port": 5353
                },
                {
                    "interface": "eth0",
                    "port": 67
                }
            ],
            "total": 2
        },
        "network_stats": {
            "bytes_in": 1157864729406,
            "bytes_out": 1170821865,
            "packets_in": 693092175031,
            "packets_out": 738917180
        },
        "tcp_connections": {
            "established_connections":{
                "connections": [
                    {
                    "local_interface": "eth0",
                    "local_port": 80,
                    "remote_addr": "192.168.0.1:8000"
                    },
                    {
                    "local_interface": "eth0",
                    "local_port": 80,
                    "remote_addr": "192.168.0.1:8000"
                    }
                ],
                "total": 2
            }
        }
    },
    "custom_metrics": {                                                                                                                                                                                        
        "cpu_usage": [                                                                                                                                                                                         
            {                                                                                                                                                                                                  
                "number": 26.1                                                                                                                                                                                 
            }                                                                                                                                                                                                  
        ]                                                                                                                                                                                                      
    }
}

Short Field Names

{
    "hed": {
        "rid": 1529963534,
        "v": "1.0"
    },
    "met": {
        "tp": {
            "pts": [
                {
                    "if": "eth0",
                    "pt": 24800
                },
                {
                    "if": "eth0",
                    "pt": 22
                },
                {
                    "if": "eth0",
                    "pt": 53
                }
            ],
            "t": 3
        },
        "up": {
            "pts": [
                {
                    "if": "eth0",
                    "pt": 5353
                },
                {
                    "if": "eth0",
                    "pt": 67
                }
            ],
            "t": 2
        },
        "ns": {
            "bi": 1157864729406,
            "bo": 1170821865,
            "pi": 693092175031,
            "po": 738917180
        },
        "tc": {
            "ec":{
                "cs": [
                    {
                    "li": "eth0",
                    "lp": 80,
                    "rad": "192.168.0.1:8000"
                    },
                    {
                    "li": "eth0",
                    "lp": 80,
                    "rad": "192.168.0.1:8000"
                    }
                ],
                "t": 2
            }
        }
    },
    "cmet": {                                                                                                                                                                                        
        "cpu": [                                                                                                                                                                                         
            {                                                                                                                                                                                                  
                "number": 26.1                                                                                                                                                                                 
            }                                                                                                                                                                                                  
        ]                                                                                                                                                                                                      
    }
}

API Documentation

You can find the API documentation here

References

License

This library is licensed under the Apache 2.0 License.

Support

If you have technical questions about the AWS IoT Device SDK, use the AWS IoT Forum. For any other questions about AWS IoT, contact AWS Support.

aws-iot-device-defender-agent-sdk-python's People

Contributors

da-miller avatar jpeddicord avatar lwilkovich avatar svarvadekar avatar tolysz avatar vareddy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

aws-iot-device-defender-agent-sdk-python's Issues

Greengrass DeviceDefender: weird behaviour with Bytes In and Bytes Out

Describe the bug
Can't seem to be able to configure AWS Device Defender Security Profile with the data Bytes In / Bytes Out that Greengrass device defender sends from this Python SDK.

To Reproduce
Greengrass component setup using the following (this component is using aws-iot-device-defender-agent-sdk-python)

    "aws.greengrass.DeviceDefender": {
      "componentVersion": "3.0.0",
      "configurationUpdate": {
        "merge": "{\"SampleIntervalSeconds\":300,\"UseInstaller\":true}"
      }
    }

Security Profile with following criteria (here as IaC, can be created manually in AWS Console):

        {
          name: "BytesIn",
          criteria: {
            comparisonOperator: "less-than-equals",
            consecutiveDatapointsToAlarm: 1,
            consecutiveDatapointsToClear: 3,
            durationSeconds: 300,
            value: {
              count: "100000",
            },
          },
          metric: "aws:all-bytes-in",
          suppressAlerts: true,
        }

Expected behavior
Between two data points of 5 min interval, we never have more than 100000 Bytes sent. It should not alarm.

Actual behavior
Instead it alarms, most probably because instead of making the difference in bytes between two data points, what's being pushed is a cumulative BytesIn values which never cease to increase over time?

Should this component be changed to send delta between two datapoints to be compatible with a Security Profile? Or otherwise how can we use the BytesIn BytesOut data as pushed by this component in a Device Defender Security Profile?

More Information
Navigating to Defend -> Detect -> Security Profile -> Defender Metrics -> Bytes In.

The resulting graph looks like this:

143419195-e0d5b378-fae1-48be-a22f-c023a4c3ca69

As you can see Bytes In is steadily growing. From one data point to another (at 5 min Interval), there is never more than a 50,000 Bytes difference. Our IoT device is supposed to push and pull data at a steady rate (the graph confirms it is indeed the case).

We would like to setup a defender rule in our security profile around these metrics (BytesIn and Out). Essentially saying that between two data points (5 min interval) there should never be more than 100,000 Bytes difference (bumping a bit the previous 50,000 value). How can we do this with our security profile rule?

Our understanding was that the rule we talked about earlier would do just this:

143420147-a7d17d3b-d18f-4938-a686-cdf72b3f002e

But it alarms unfortunately. And when it does, it shows the total number of BytesIn : 34104770 which is the sum of two Bytes In metric that are sent within 5 min interval.

143428275-668699fe-aaa5-409c-a9db-4fa52f5c4067

So if the rule itself for "aws:all-bytes-in" (in the security profile) is doing a sum of what's being sent during the interval Duration, then that means that the rule anticipates the metrics to send a delta of Bytes In rather than a cumulative value we would think.

Otherwise, if we are mistaken, then how can we use the Bytes In / Bytes Out metrics as it is currently being sent by this component into a Device Defender Security Profile: how can we put a threashold on something that never stops growing?

NB: this problem was originally described in the aws-greengrass-device-defender. aws-greengrass/aws-greengrass-device-defender#3
We have been asked to log this issue directly here as the Greengrass Component appears to be just a wrapper around this SDK.

Thanks a lot for your help!

should update to sdk v2 ?

it seems does not work now .

2020-06-15 04:31:52,432 - AWSIoTPythonSDK.core.protocol.mqtt_core - ERROR - Connect timed out
Traceback (most recent call last):
File "agent.py", line 174, in
main()
File "agent.py", line 140, in main
iot_client.connect()
File "agent.py", line 77, in connect
self.iot_client.connect()
File "/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/MQTTLib.py", line 513, in connect
return self._mqtt_core.connect(keepAliveIntervalSecond)
File "/usr/local/lib/python2.7/dist-packages/AWSIoTPythonSDK/core/protocol/mqtt_core.py", line 199, in connect
raise connectTimeoutException()
AWSIoTPythonSDK.exception.AWSIoTExceptions.connectTimeoutException

psutil issues on Raspberry Pi

I've followed the instructions to deploy this function to a Greengrass Core running on a Rasperry Pi, and I'm seeing an issue in my logs:

[2018-12-12T16:09:58.94Z][FATAL]-lambda_runtime.py:356,Failed to initialize Lambda runtime due to exception: cannot import name _psutil_linux

This message is showing up in /greengrass/ggc/var/log/user/us-east-1/myaccountid/greengrass_defender_metrics_lambda.log.

I've tried re-installing psutil locally, re-copied it into the metrics_lambda and then zipping a new version of the function and uploading it to the Lambda console, redeployed to the GG group, but without success.

Based on my understanding of how this should work, the Lambda function running on the GG device should pull its dependencies from the included dependencies uploaded as part of the zip folder, but the version of psutil included does not seem to be the right version. Is this because I ran pip install psutil on OSX and not on a Linux machine?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.