Documentation Index
Fetch the complete documentation index at: https://mintlify.com/lamassuiot/lamassuiot/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The AWS IoT Core connector enables bidirectional synchronization between Lamassu and AWS IoT:
- Device Registration - Create IoT Things from Lamassu devices
- Certificate Management - Register device certificates with AWS IoT
- Shadow Updates - Push device state and remediation actions
- CA Registration - Register Lamassu CAs as AWS IoT CA certificates
- JITP (Just-In-Time Provisioning) - Automatic device onboarding
- Event Handling - React to Lamassu lifecycle events
Import Path:
import "github.com/lamassuiot/lamassuiot/connectors/awsiot/v3/pkg"
Architecture
┌─────────────────┐ Events ┌──────────────────┐
│ Lamassu CA │──────────────────▶│ AWS IoT │
│ DMS Manager │ │ Connector │
│ Device Manager │◀──────────────────│ │
└─────────────────┘ Updates └──────────────────┘
│
│ AWS SDK
▼
┌──────────────────┐
│ AWS IoT Core │
│ - Things │
│ - Certificates │
│ - Policies │
│ - Shadows │
└──────────────────┘
Configuration
connector:
connector_id: aws-iot-prod
# AWS credentials
aws_config:
aws_region: us-east-1
aws_access_key_id: ${AWS_ACCESS_KEY_ID}
aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}
# Bidirectional queue for commands
aws_bidirectional_queue_name: lamassu-iot-commands
# Event bus for Lamassu events
subscriber_event_bus:
provider: amqp
config:
hostname: rabbitmq.example.com
port: 5672
exchange: lamassu-events
# Dead letter queue
subscriber_dlq_event_bus:
provider: amqp
config:
hostname: rabbitmq.example.com
port: 5672
exchange: lamassu-dlq
# Lamassu service clients
ca_client:
base_url: https://ca.lamassu.io
tls_config:
insecure_skip_verify: false
device_manager_client:
base_url: https://device-manager.lamassu.io
dms_manager_client:
base_url: https://dms-manager.lamassu.io
Config Struct:
type ConnectorServiceConfig struct {
Logs cconfig.Logging
SubscriberEventBus cconfig.EventBusEngine
SubscriberDLQEventBus cconfig.EventBusEngine
DMSManagerClient struct {
cconfig.HTTPClient
}
DevManagerClient struct {
cconfig.HTTPClient
}
CAClient struct {
cconfig.HTTPClient
}
ConnectorID string
AWSSDKConfig laws.AWSSDKConfig
AWSBidirectionalQueueName string
}
CA Registration
Register Lamassu CAs with AWS IoT to enable certificate validation.
Primary Account Registration
For the AWS account owning the IoT Core endpoint:
# Via Lamassu API
curl -X POST https://dms.lamassu.io/v1/cas/root-ca/register-aws \
-H "Authorization: Bearer $TOKEN" \
-d '{
"connector_id": "aws-iot-prod",
"primary_account": true
}'
Process:
- Connector generates verification CSR with AWS registration code
- Signs CSR with Lamassu CA
- Registers CA with verification certificate
- Updates Lamassu CA metadata with AWS ARN
Metadata Added:
{
"connectors.lamassu.io/aws-iot-prod": {
"account": "123456789012",
"region": "us-east-1",
"arn": "arn:aws:iot:us-east-1:123456789012:cacert/abc123",
"certificate_id": "abc123...",
"iot_core_mqtt_endpoint": "a1b2c3d4e5f6g7.iot.us-east-1.amazonaws.com",
"registration": {
"status": "succeeded",
"registration_time": "2024-01-15T10:00:00Z",
"primary_account": true
}
}
}
Multi-Account Registration (SNI)
For additional AWS accounts:
curl -X POST https://dms.lamassu.io/v1/cas/root-ca/register-aws \
-H "Authorization: Bearer $TOKEN" \
-d '{
"connector_id": "aws-iot-prod",
"primary_account": false
}'
Uses SNI-only mode (no verification certificate required).
Source: connectors/awsiot/pkg/service.go:692
Device Registration
Automatic Registration (Event-Driven)
The connector listens for device.identity.bound events:
func (svc *Service) HandleDeviceIdentityBound(ctx context.Context, event Event) error {
// 1. Get DMS automation config
dms, _ := svc.GetDMSService().GetDMSByID(ctx, event.DeviceID)
var iotConfig IotAWSDMSMetadata
hasConfig := metadata.Get(dms.Metadata, AWSIoTMetadataKey(connectorID), &iotConfig)
if !hasConfig {
return nil // DMS not configured for AWS IoT
}
// 2. Register Thing and attach certificate
err := svc.RegisterAndAttachThing(ctx, RegisterAndAttachThingInput{
DeviceID: event.DeviceID,
BindedIdentity: event.BindedIdentity,
DMSIoTAutomationConfig: iotConfig,
})
return err
}
Manual Registration
curl -X POST https://device-manager.lamassu.io/v1/devices/device-001/register-aws \
-H "Authorization: Bearer $TOKEN" \
-d '{
"connector_id": "aws-iot-prod"
}'
Registration Process
-
Create/Update Policies
svc.RegisterUpdatePolicies(ctx, RegisterUpdatePoliciesInput{
Policies: dmsConfig.Policies,
})
-
Create Thing Groups
svc.RegisterGroups(ctx, RegisterGroupsInput{
Groups: dmsConfig.GroupNames,
})
-
Revoke Old Certificates
- Lists all certificates attached to Thing
- Revokes previous certificates
-
Register via Provisioning Template
template := map[string]any{
"Parameters": map[string]any{
"ThingName": {"Type": "String"},
"LamassuCertificate": {"Type": "String"},
"LamassuCACertificatePem": {"Type": "String"},
},
"Resources": map[string]any{
"thing": {
"Type": "AWS::IoT::Thing",
"Properties": {
"ThingName": {"Ref": "ThingName"},
"ThingGroups": dmsConfig.GroupNames,
},
},
"certificate": {
"Type": "AWS::IoT::Certificate",
"Properties": {
"CACertificatePem": {"Ref": "LamassuCACertificatePem"},
"CertificatePem": {"Ref": "LamassuCertificate"},
},
},
},
}
registrationOutput, _ := iotSDK.RegisterThing(ctx, &iot.RegisterThingInput{
TemplateBody: aws.String(templateJSON),
Parameters: params,
})
-
Update Metadata
- Adds AWS certificate ARN to Lamassu certificate metadata
- Marks device as registered in AWS IoT
Source: connectors/awsiot/pkg/service.go:222
Shadow Management
Update device shadows with remediation actions based on certificate status.
Configuration (DMS Level)
{
"connectors.lamassu.io/aws-iot-prod": {
"shadow_config": {
"enable": true,
"shadow_name": "lamassu" // Empty = classic shadow
},
"policies": [...],
"group_names": ["production-devices"]
}
}
Shadow Update Process
func (svc *Service) UpdateDeviceShadow(ctx context.Context, input UpdateDeviceShadowInput) error {
// 1. Get current shadow
shadow, err := iotdataplaneSDK.GetThingShadow(ctx, &iotdataplane.GetThingShadowInput{
ThingName: &input.DeviceID,
ShadowName: &shadowName,
})
// 2. Update desired state
shadowState.Desired["identity_actions"] = map[string]int{
"revoke": timestamp,
"rotate": timestamp,
"disconnect": timestamp,
}
// 3. Publish shadow update
_, err = iotdataplaneSDK.UpdateThingShadow(ctx, &iotdataplane.UpdateThingShadowInput{
ThingName: &input.DeviceID,
Payload: shadowJSON,
})
return err
}
Shadow Document
{
"state": {
"desired": {
"identity_actions": {
"revoke": 1705315200000,
"disconnect": 1705315200000
}
},
"reported": {
"connected": true,
"last_seen": 1705315000000
}
},
"metadata": {
"desired": {
"identity_actions": {
"revoke": {"timestamp": 1705315200},
"disconnect": {"timestamp": 1705315200}
}
}
},
"version": 42,
"timestamp": 1705315200
}
Source: connectors/awsiot/pkg/service.go:462
Just-In-Time Provisioning (JITP)
Automatically provision devices when they first connect to AWS IoT.
DMS Configuration
{
"connectors.lamassu.io/aws-iot-prod": {
"jitp_provisioning_template": {
"enable_template": true,
"aws_ca_certificate_id": "abc123...",
"provisioning_role_arn": "arn:aws:iam::123456789012:role/JITPRole"
},
"policies": [
{
"policy_name": "DevicePolicy",
"policy_document": "{...}"
}
],
"group_names": ["jitp-devices"]
}
}
Template Creation
template := {
"Parameters": {
"AWS::IoT::Certificate::CommonName": {"Type": "String"},
"AWS::IoT::Certificate::Organization": {"Type": "String"},
},
"Resources": {
"thing": {
"Type": "AWS::IoT::Thing",
"Properties": {
"ThingName": {"Ref": "AWS::IoT::Certificate::CommonName"},
"ThingGroups": ["jitp-devices"],
},
},
"certificate": {
"Type": "AWS::IoT::Certificate",
"Properties": {
"CertificateId": {"Ref": "AWS::IoT::Certificate::Id"},
"Status": "ACTIVE",
},
},
"DevicePolicy": {
"Type": "AWS::IoT::Policy",
"Properties": {
"PolicyName": "DevicePolicy",
},
},
},
}
_, err := iotSDK.CreateProvisioningTemplate(ctx, &iot.CreateProvisioningTemplateInput{
ProvisioningRoleArn: &roleARN,
TemplateBody: &templateJSON,
TemplateName: &dmsID,
Enabled: aws.Bool(true),
Type: types.TemplateTypeJitp,
})
Source: connectors/awsiot/pkg/service.go:952
IAM Permissions
Connector Service Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:RegisterCACertificate",
"iot:DescribeCACertificate",
"iot:UpdateCACertificate",
"iot:RegisterThing",
"iot:DescribeThing",
"iot:UpdateCertificate",
"iot:CreatePolicy",
"iot:GetPolicy",
"iot:CreatePolicyVersion",
"iot:CreateThingGroup",
"iot:CreateProvisioningTemplate",
"iot:UpdateProvisioningTemplate"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iot:GetThingShadow",
"iot:UpdateThingShadow"
],
"Resource": "arn:aws:iot:*:*:thing/*"
},
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:SendMessage"
],
"Resource": "arn:aws:sqs:*:*:lamassu-*"
}
]
}
JITP Provisioning Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:CreateThing",
"iot:UpdateThing",
"iot:DescribeThing",
"iot:AttachThingPrincipal",
"iot:AttachPolicy",
"iot:UpdateCertificate"
],
"Resource": "*"
}
]
}
Monitoring
Metrics
# Devices registered
lamassu_aws_iot_devices_registered_total 42
# Shadow updates
lamassu_aws_iot_shadow_updates_total{device="device-001"} 15
# Certificate status updates
lamassu_aws_iot_cert_status_updates_total{status="revoked"} 3
# Event processing errors
lamassu_aws_iot_event_errors_total{event_type="device.registered"} 0
Logging
{
"level": "info",
"service": "aws-iot-connector",
"connector_id": "aws-iot-prod",
"device_id": "device-001",
"action": "register_thing",
"thing_arn": "arn:aws:iot:us-east-1:123456789012:thing/device-001",
"message": "Successfully registered thing with AWS IoT"
}
Troubleshooting
Symptoms:something went wrong while registering CA certificate: ValidationException
Solutions:
- Verify CA certificate is valid and not expired
- Check AWS region matches configuration
- Ensure IAM permissions include
iot:RegisterCACertificate
- For primary account, verify registration code CSR is signed correctly
Thing Registration Failed
Symptoms:could not register thing: ResourceAlreadyExistsException
Solutions:
- Thing already exists with different certificate
- Connector will automatically revoke old certificates
- Check device metadata for existing AWS registration
Symptoms:could not update shadow: ResourceNotFoundException
Solutions:
- Verify thing is registered:
aws iot describe-thing --thing-name device-001
- Check shadow name matches DMS configuration
- Ensure device has connected at least once to create shadow
Source Code
- Service:
connectors/awsiot/pkg/service.go:56
- Event Handlers:
connectors/awsiot/pkg/event-handlers.go
- Configuration:
connectors/awsiot/pkg/config.go:8
- Models:
connectors/awsiot/pkg/models.go
Next Steps
Device Management
Learn about device lifecycle management
DMS Configuration
Configure Device Manufacturing Services