代码之家  ›  专栏  ›  技术社区  ›  Nyxynyx

使用多个物联网设备的无服务器框架设置AWS物联网

  •  1
  • Nyxynyx  · 技术社区  · 7 年前

    我的目标是使用 serverless framework 对于多个物联网设备,将JSON有效载荷发送到AWS物联网,然后将其保存到dynamodb。

    我对在创建EC2服务器之外使用AWS非常陌生,这是我第一个使用 无服务器框架 .

    在提到 an example ,我提出的修改版本发布在下面。

    问题: 似乎只有一个设备连接到AWS物联网,我从使用的硬编码物联网证书得出结论,例如

    SensorPolicyPrincipalAttachmentCert:
      Type: AWS::IoT::PolicyPrincipalAttachment
      Properties:
        PolicyName: { Ref: SensorThingPolicy }
        Principal: ${{custom.iotCertificateArn}}
    
    SensorThingPrincipalAttachmentCert:
      Type: "AWS::IoT::ThingPrincipalAttachment"
      Properties:
        ThingName: { Ref: SensorThing }
        Principal: ${self:custom.iotCertificateArn}
    

    如果这个结论是正确的, serverless.yml 只配置了一件事,那么我们可以做些什么修改来使用一件以上的事?

    也许把所有的事情都安排在 serverless.yaml ?这意味着只需移除 SensorPolicyPrincipalAttachmentCert SensorThingPrincipalAttachmentCert ?

    另外,我们应该如何设置 Resource 属性到 SensorThingPolicy ?它们当前设置为 "*" ,这是不是太布罗德了?或者有没有一种方法来限制仅仅是事情。

    无服务器.yml

    service: garden-iot
    
    provider:
    name: aws
    runtime: nodejs6.10
    region: us-east-1
    
    # load custom variables from a file
    custom: ${file(./vars-dev.yml)}
    
    resources:
    Resources:
        LocationData:
        Type: AWS::DynamoDB::Table
        Properties:
            TableName: location-data-${opt:stage}
            AttributeDefinitions:
            - 
                AttributeName: ClientId
                AttributeType: S
            - 
                AttributeName: Timestamp
                AttributeType: S
            KeySchema:
            - 
                AttributeName: ClientId
                KeyType: HASH
            - 
                AttributeName: Timestamp
                KeyType: RANGE
            ProvisionedThroughput:
            ReadCapacityUnits: 1
            WriteCapacityUnits: 1
    
        SensorThing:
        Type: AWS::IoT::Thing
        Properties:
            AttributePayload:
            Attributes:
                SensorType: soil
    
        SensorThingPolicy:
        Type: AWS::IoT::Policy
        Properties:
            PolicyDocument:
            Version: "2012-10-17"
            Statement:
                - Effect: Allow
                Action: ["iot:Connect"]
                Resource: ["${self:custom.sensorThingClientResource}"]
                - Effect: "Allow"
                Action: ["iot:Publish"]
                Resource: ["${self:custom.sensorThingSoilTopicResource}"]
    
        SensorPolicyPrincipalAttachmentCert:
        Type: AWS::IoT::PolicyPrincipalAttachment
        Properties:
            PolicyName: { Ref: SensorThingPolicy }
            Principal: ${{custom.iotCertificateArn}}
    
        SensorThingPrincipalAttachmentCert:
        Type: "AWS::IoT::ThingPrincipalAttachment"
        Properties:
            ThingName: { Ref: SensorThing }
            Principal: ${self:custom.iotCertificateArn}
    
    IoTRole:
    Type: AWS::IAM::Role
    Properties:
        AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
            -
            Effect: Allow
            Principal:
                Service:
                - iot.amazonaws.com
            Action:
                - sts:AssumeRole
    
    IoTRolePolicies:
    Type: AWS::IAM::Policy
    Properties:
        PolicyName: IoTRole_Policy
        PolicyDocument:
        Version: "2012-10-17"
        Statement:
            -
            Effect: Allow
            Action:
                - dynamodb:PutItem
            Resource: "*"
            -
            Effect: Allow
            Action:
                - lambda:InvokeFunction
            Resource: "*"
        Roles: [{ Ref: IoTRole }]
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   dom    7 年前

    编辑日期:2018年9月5日: 我发现这篇博客文章很好地描述了我的方法: Ensure Secure Communication with AWS IoT Core Using the Certificate Vending Machine Reference Application

    ——

    你可以看看 Just-in-Time Provisioning 或者建立自己的解决方案 Programmatic Provisioning .

    我已经处理过这个主题很多次了,必须认识到它很大程度上依赖于用例,这更有意义。安全也是需要注意的一个方面。你不想让一个公共的API负责整个互联网可以访问的JIT设备注册。

    一个简单的基于程序配置的场景可能是这样的:您构建了一个东西(可能是一个传感器),它应该能够连接到AWS物联网并具有内部配置过程。

    简单的供应过程:

    1. 建造的东西
    2. 东西有序列号
    3. 事物通过内部服务器注册自身

    服务器上运行的注册代码可能如下所示(JS+AWS JS SDK):

    // Modules
    const AWS = require('aws-sdk')
    
    // AWS
    const iot = new AWS.Iot({ region: process.env.region })
    
    // Config
    const templateBodyJson = require('./register-thing-template-body.json')
    
    // registerThing
    const registerThing = async ({ serialNumber = null } = {}) => {
      if (!serialNumber) throw new Error('`serialNumber` required!')
    
      const {
        certificateArn = null,
        certificateId = null,
        certificatePem = null,
        keyPair: {
          PrivateKey: privateKey = null,
          PublicKey: publicKey = null
        } = {}
      } = await iot.createKeysAndCertificate({ setAsActive: true }).promise()
      const registerThingParams = {
        templateBody: JSON.stringify(templateBodyJson),
        parameters: {
          ThingName: serialNumber,
          SerialNumber: serialNumber,
          CertificateId: certificateId
        }
      }
      const { resourceArns = null } = await iot.registerThing(registerThingParams).promise()
    
      return {
        certificateArn,
        certificateId,
        certificatePem,
        privateKey,
        publicKey,
        resourceArns
      }
    }
    
    const unregisterThing = async ({ serialNumber = null } = {}) => {
      if (!serialNumber) throw new Error('`serialNumber` required!')
    
      try {
        const thingName = serialNumber
        const { principals: thingPrincipals } = await iot.listThingPrincipals({ thingName }).promise()
        const certificates = thingPrincipals.map((tp) => ({ certificateId: tp.split('/').pop(), certificateArn: tp }))
    
        for (const { certificateId, certificateArn } of certificates) {
          await iot.detachThingPrincipal({ thingName, principal: certificateArn }).promise()
          await iot.updateCertificate({ certificateId, newStatus: 'INACTIVE' }).promise()
          await iot.deleteCertificate({ certificateId, forceDelete: true }).promise()
        }
    
        await iot.deleteThing({ thingName }).promise()
    
        return {
          deleted: true,
          thingPrincipals
        }
      } catch (err) {
        // Already deleted!
        if (err.code && err.code === 'ResourceNotFoundException') {
          return {
            deleted: true,
            thingPrincipals: []
          }
        }
    
        throw err
      }
    }
    

    register-thing-template-body.json:

    {
      "Parameters": {
         "ThingName": {
           "Type": "String"
         },
         "SerialNumber": {
           "Type": "String"
         },
         "CertificateId": {
           "Type": "String"
         }
      },
      "Resources": {
        "thing": {
          "Type": "AWS::IoT::Thing",
          "Properties": {
            "ThingName": {
              "Ref": "ThingName"
            },
            "AttributePayload": {
              "serialNumber": {
                "Ref": "SerialNumber"
              }
            },
            "ThingTypeName": "NewDevice",
            "ThingGroups": ["NewDevices"]
          }
        },
        "certificate": {
          "Type": "AWS::IoT::Certificate",
          "Properties": {
            "CertificateId": {
              "Ref": "CertificateId"
            }
          }
        },
        "policy": {
          "Type": "AWS::IoT::Policy",
          "Properties": {
            "PolicyName": "DefaultNewDevicePolicy"
          }
        }
      }
    }
    

    确保所有“newdevice”事件类型、组和策略都已就绪。还要记住thingname=serialnumber(对于注销很重要)。