Настройка AWS IoT с использованием Serverless Framework для нескольких устройств IoT - PullRequest
0 голосов
/ 04 сентября 2018

Моя цель - создать систему на AWS с использованием безсерверной инфраструктуры для нескольких устройств IoT для отправки полезных нагрузок JSON в AWS IoT, которая, в свою очередь, будет сохранена в DynamoDB.

Я очень новичок в использовании AWS за пределами создания серверов EC2, и это мой первый проект, использующий безсерверный фреймворк .

После ссылки на пример ниже приведена измененная версия, которую я придумал.

Проблема: Похоже, что в данном примере только 1 устройство подключено к AWS IoT, что я и заключил из используемого жестко закодированного сертификата IoT Thing, такого как

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 настроен только на 1 вещь, то какие модификации мы можем сделать так, чтобы можно было использовать более 1 вещь?

Может быть, настроить все вещи за пределами serverless.yaml? Что означает удаление только SensorPolicyPrincipalAttachmentCert и SensorThingPrincipalAttachmentCert?

Кроме того, как мы должны установить свойство Resource в SensorThingPolicy? В настоящее время они настроены на "*", это слишком сложно? Или есть способ ограничиться только вещами.

serverless.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 Ответ

0 голосов
/ 04 сентября 2018

РЕДАКТИРОВАТЬ 05/09/2018: Я нашел этот пост в блоге, в котором довольно хорошо описывается мой подход: Обеспечение безопасной связи с AWS IoT Core с помощью справочного приложения торгового автомата для сертификатов

Вы можете взглянуть на Предоставление точно в срок или создать собственное решение на основе Программная подготовка .

Я много раз сталкивался с этой темой и должен был понять, что она во многом зависит от варианта использования, что имеет больше смысла. Также безопасность является аспектом, за которым нужно следить. Вы не хотите, чтобы общедоступный API, отвечающий за регистрацию устройства JIT, был доступен для всего Интернета.

Простой сценарий, основанный на программной инициализации, может выглядеть следующим образом: вы создаете объект (возможно, датчик), который должен иметь возможность подключаться к AWS IoT и иметь внутренний процесс подготовки.

Простой процесс обеспечения:

  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
  }
}

регистр-вещь-шаблонный 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 (важно для отмены регистрации).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...