From 56107fda5bd4c38c7ffdba0ae8bc0f6e537a61f1 Mon Sep 17 00:00:00 2001 From: Jesse Rittner Date: Wed, 13 Oct 2021 00:04:46 -0400 Subject: [PATCH 1/4] redefine IoT Core custom authorizer request and response structs as per spec --- events/iot.go | 59 +++++++++++++------ events/iot_test.go | 16 ++--- events/testdata/iot-custom-auth-request.json | 36 ++++++----- events/testdata/iot-custom-auth-response.json | 13 +++- 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/events/iot.go b/events/iot.go index 785cbfa3..7e2f96be 100644 --- a/events/iot.go +++ b/events/iot.go @@ -1,34 +1,57 @@ package events -// IoTCustomAuthorizerRequest contains data coming in to a custom IoT device gateway authorizer function. -type IoTCustomAuthorizerRequest struct { - HTTPContext *IoTHTTPContext `json:"httpContext,omitempty"` - MQTTContext *IoTMQTTContext `json:"mqttContext,omitempty"` - TLSContext *IoTTLSContext `json:"tlsContext,omitempty"` - AuthorizationToken string `json:"token"` - TokenSignature string `json:"tokenSignature"` +// IoTCoreCustomAuthorizerRequest represents the request to an IoT Core custom authorizer. +// See https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html +type IoTCoreCustomAuthorizerRequest struct { + Token string `json:"token"` + SignatureVerified bool `json:"signatureVerified"` + Protocols []string `json:"protocols"` + ProtocolData *IoTCoreProtocolData `json:"protocolData,omitempty"` + ConnectionMetadata *IoTCoreConnectionMetadata `json:"connectionMetadata,omitempty"` } -type IoTHTTPContext struct { +type IoTCoreProtocolData struct { + TLS *IoTCoreTLSContext `json:"tls,omitempty"` + HTTP *IoTCoreHTTPContext `json:"http,omitempty"` + MQTT *IoTCoreMQTTContext `json:"mqtt,omitempty"` +} + +type IoTCoreTLSContext struct { + ServerName string `json:"serverName"` +} + +type IoTCoreHTTPContext struct { Headers map[string]string `json:"headers,omitempty"` QueryString string `json:"queryString"` } -type IoTMQTTContext struct { +type IoTCoreMQTTContext struct { ClientID string `json:"clientId"` Password []byte `json:"password"` Username string `json:"username"` } -type IoTTLSContext struct { - ServerName string `json:"serverName"` +type IoTCoreConnectionMetadata struct { + ID string `json:"id"` +} + +// IoTCoreCustomAuthorizerResponse represents the response from an IoT Core custom authorizer. +// See https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html +type IoTCoreCustomAuthorizerResponse struct { + IsAuthenticated bool `json:"isAuthenticated"` + PrincipalID string `json:"principalId"` + DisconnectAfterInSeconds uint32 `json:"disconnectAfterInSeconds"` + RefreshAfterInSeconds uint32 `json:"refreshAfterInSeconds"` + PolicyDocuments []*IoTCorePolicyDocument `json:"policyDocuments"` +} + +type IoTCorePolicyDocument struct { + Version string + Statement []*IoTCorePolicyStatement } -// IoTCustomAuthorizerResponse represents the expected format of an IoT device gateway authorization response. -type IoTCustomAuthorizerResponse struct { - IsAuthenticated bool `json:"isAuthenticated"` - PrincipalID string `json:"principalId"` - DisconnectAfterInSeconds int32 `json:"disconnectAfterInSeconds"` - RefreshAfterInSeconds int32 `json:"refreshAfterInSeconds"` - PolicyDocuments []string `json:"policyDocuments"` +type IoTCorePolicyStatement struct { + Action []string + Effect string + Resource []string } diff --git a/events/iot_test.go b/events/iot_test.go index 4e88cfae..015a13fb 100644 --- a/events/iot_test.go +++ b/events/iot_test.go @@ -8,7 +8,7 @@ import ( "github.com/aws/aws-lambda-go/events/test" ) -func TestIoTCustomAuthorizerRequestMarshaling(t *testing.T) { +func TestIoTCoreCustomAuthorizerRequestMarshaling(t *testing.T) { // read json from file inputJSON, err := ioutil.ReadFile("./testdata/iot-custom-auth-request.json") @@ -17,7 +17,7 @@ func TestIoTCustomAuthorizerRequestMarshaling(t *testing.T) { } // de-serialize into Go object - var inputEvent IoTCustomAuthorizerRequest + var inputEvent IoTCoreCustomAuthorizerRequest if err := json.Unmarshal(inputJSON, &inputEvent); err != nil { t.Errorf("could not unmarshal event. details: %v", err) } @@ -31,11 +31,11 @@ func TestIoTCustomAuthorizerRequestMarshaling(t *testing.T) { test.AssertJsonsEqual(t, inputJSON, outputJSON) } -func TestIoTCustomAuthorizerRequestMalformedJson(t *testing.T) { - test.TestMalformedJson(t, IoTCustomAuthorizerRequest{}) +func TestIoTCoreCustomAuthorizerRequestMalformedJson(t *testing.T) { + test.TestMalformedJson(t, IoTCoreCustomAuthorizerRequest{}) } -func TestIoTCustomAuthorizerResponseMarshaling(t *testing.T) { +func TestIoTCoreCustomAuthorizerResponseMarshaling(t *testing.T) { // read json from file inputJSON, err := ioutil.ReadFile("./testdata/iot-custom-auth-response.json") @@ -44,7 +44,7 @@ func TestIoTCustomAuthorizerResponseMarshaling(t *testing.T) { } // de-serialize into Go object - var inputEvent IoTCustomAuthorizerResponse + var inputEvent IoTCoreCustomAuthorizerResponse if err := json.Unmarshal(inputJSON, &inputEvent); err != nil { t.Errorf("could not unmarshal event. details: %v", err) } @@ -58,6 +58,6 @@ func TestIoTCustomAuthorizerResponseMarshaling(t *testing.T) { test.AssertJsonsEqual(t, inputJSON, outputJSON) } -func TestIoTCustomAuthorizerResponseMalformedJson(t *testing.T) { - test.TestMalformedJson(t, IoTCustomAuthorizerResponse{}) +func TestIoTCoreCustomAuthorizerResponseMalformedJson(t *testing.T) { + test.TestMalformedJson(t, IoTCoreCustomAuthorizerResponse{}) } diff --git a/events/testdata/iot-custom-auth-request.json b/events/testdata/iot-custom-auth-request.json index 631895b2..44d751e5 100644 --- a/events/testdata/iot-custom-auth-request.json +++ b/events/testdata/iot-custom-auth-request.json @@ -1,18 +1,24 @@ { - "httpContext": { - "headers": { - "Accept-Language" : "en" + "token" :"aToken", + "signatureVerified": true, + "protocols": ["tls", "http", "mqtt"], + "protocolData": { + "tls" : { + "serverName": "serverName" }, - "queryString": "abc" - }, - "mqttContext": { - "clientId": "someclient", - "password": "aslkfjwoeiuwekrujwlrueowieurowieurowiuerwleuroiwueroiwueroiuweoriuweoriuwoeiruwoeiur", - "username": "thebestuser" - }, - "tlsContext": { - "serverName": "server.stuff.com" + "http": { + "headers": { + "X-Request-ID": "abc123" + }, + "queryString": "?foo=bar" + }, + "mqtt": { + "username": "myUserName", + "password": "bXlQYXNzd29yZA==", + "clientId": "myClientId" + } }, - "token": "someToken", - "tokenSignature": "somelongtokensignature" -} \ No newline at end of file + "connectionMetadata": { + "id": "e56f08c3-c559-490f-aa9f-7e8427d0f57b" + } +} diff --git a/events/testdata/iot-custom-auth-response.json b/events/testdata/iot-custom-auth-response.json index 55100a9b..debc960c 100644 --- a/events/testdata/iot-custom-auth-response.json +++ b/events/testdata/iot-custom-auth-response.json @@ -4,6 +4,15 @@ "disconnectAfterInSeconds": 86400, "refreshAfterInSeconds": 300, "policyDocuments": [ - "{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Action\": [\"iot:Subscribe\"], \"Effect\": \"Allow\", \"Resource\": [\"*\"] } ] }" + { + "Version": "2012-10-17", + "Statement": [ + { + "Action": ["iot:Publish"], + "Effect": "Allow", + "Resource": ["arn:aws:iot:us-east-1::topic/customauthtesting"] + } + ] + } ] -} \ No newline at end of file +} From 389713b4aa36cedbd49f8fc112fce721f085cbf3 Mon Sep 17 00:00:00 2001 From: Jesse Rittner Date: Mon, 18 Oct 2021 00:03:23 -0400 Subject: [PATCH 2/4] make IAM policy structs reusable --- events/apigw.go | 17 +++++------------ events/iam.go | 14 ++++++++++++++ events/iot.go | 21 +++++---------------- 3 files changed, 24 insertions(+), 28 deletions(-) create mode 100644 events/iam.go diff --git a/events/apigw.go b/events/apigw.go index 06cf8b9f..612e0eb7 100644 --- a/events/apigw.go +++ b/events/apigw.go @@ -291,15 +291,8 @@ type APIGatewayV2CustomAuthorizerSimpleResponse struct { Context map[string]interface{} `json:"context,omitempty"` } -// APIGatewayCustomAuthorizerPolicy represents an IAM policy -type APIGatewayCustomAuthorizerPolicy struct { - Version string - Statement []IAMPolicyStatement -} - -// IAMPolicyStatement represents one statement from IAM policy with action, effect and resource -type IAMPolicyStatement struct { - Action []string - Effect string - Resource []string -} +// APIGatewayCustomAuthorizerPolicy represents an IAM policy. +// +// Deprecated: This type exists for backwards compatibility. New events +// and structs should reference IAMPolicyDocument directly instead. +type APIGatewayCustomAuthorizerPolicy IAMPolicyDocument diff --git a/events/iam.go b/events/iam.go new file mode 100644 index 00000000..090530dd --- /dev/null +++ b/events/iam.go @@ -0,0 +1,14 @@ +package events + +// IAMPolicyDocument represents an IAM policy document. +type IAMPolicyDocument struct { + Version string + Statement []IAMPolicyStatement +} + +// IAMPolicyStatement represents one statement from IAM policy with action, effect and resource. +type IAMPolicyStatement struct { + Action []string + Effect string + Resource []string +} diff --git a/events/iot.go b/events/iot.go index 7e2f96be..afff7028 100644 --- a/events/iot.go +++ b/events/iot.go @@ -38,20 +38,9 @@ type IoTCoreConnectionMetadata struct { // IoTCoreCustomAuthorizerResponse represents the response from an IoT Core custom authorizer. // See https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html type IoTCoreCustomAuthorizerResponse struct { - IsAuthenticated bool `json:"isAuthenticated"` - PrincipalID string `json:"principalId"` - DisconnectAfterInSeconds uint32 `json:"disconnectAfterInSeconds"` - RefreshAfterInSeconds uint32 `json:"refreshAfterInSeconds"` - PolicyDocuments []*IoTCorePolicyDocument `json:"policyDocuments"` -} - -type IoTCorePolicyDocument struct { - Version string - Statement []*IoTCorePolicyStatement -} - -type IoTCorePolicyStatement struct { - Action []string - Effect string - Resource []string + IsAuthenticated bool `json:"isAuthenticated"` + PrincipalID string `json:"principalId"` + DisconnectAfterInSeconds uint32 `json:"disconnectAfterInSeconds"` + RefreshAfterInSeconds uint32 `json:"refreshAfterInSeconds"` + PolicyDocuments []*IAMPolicyDocument `json:"policyDocuments"` } From 6e68d8aa61bef332991515eb18160d6bc1fe9ed1 Mon Sep 17 00:00:00 2001 From: Bryan Moffatt Date: Wed, 18 May 2022 00:28:39 -0700 Subject: [PATCH 3/4] gofmt --- events/apigw.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/events/apigw.go b/events/apigw.go index 47e5da30..47c4db4e 100644 --- a/events/apigw.go +++ b/events/apigw.go @@ -338,7 +338,7 @@ type APIGatewayV2CustomAuthorizerSimpleResponse struct { // APIGatewayCustomAuthorizerPolicy represents an IAM policy. // -// Note: This type exists for backwards compatibility. +// Note: This type exists for backwards compatibility. // should reference IAMPolicyDocument directly instead. type APIGatewayCustomAuthorizerPolicy IAMPolicyDocument From ac94a86d0f55ed96f015d891fdf347901dfa0330 Mon Sep 17 00:00:00 2001 From: Bryan Moffatt Date: Wed, 18 May 2022 00:21:58 -0700 Subject: [PATCH 4/4] restore deleted structs, add deprecation notices --- events/iot_deprecated.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 events/iot_deprecated.go diff --git a/events/iot_deprecated.go b/events/iot_deprecated.go new file mode 100644 index 00000000..9330c6b6 --- /dev/null +++ b/events/iot_deprecated.go @@ -0,0 +1,30 @@ +package events + +// IoTCustomAuthorizerRequest contains data coming in to a custom IoT device gateway authorizer function. +// Deprecated: Use IoTCoreCustomAuthorizerRequest instead. IoTCustomAuthorizerRequest does not correctly model the request schema +type IoTCustomAuthorizerRequest struct { + HTTPContext *IoTHTTPContext `json:"httpContext,omitempty"` + MQTTContext *IoTMQTTContext `json:"mqttContext,omitempty"` + TLSContext *IoTTLSContext `json:"tlsContext,omitempty"` + AuthorizationToken string `json:"token"` + TokenSignature string `json:"tokenSignature"` +} + +// Deprecated: Use IoTCoreHTTPContext +type IoTHTTPContext IoTCoreHTTPContext + +// Deprecated: Use IoTCoreMQTTContext +type IoTMQTTContext IoTCoreMQTTContext + +// Deprecated: Use IotCoreTLSContext +type IoTTLSContext IoTCoreTLSContext + +// IoTCustomAuthorizerResponse represents the expected format of an IoT device gateway authorization response. +// Deprecated: Use IoTCoreCustomAuthorizerResponse. IoTCustomAuthorizerResponse does not correctly model the response schema. +type IoTCustomAuthorizerResponse struct { + IsAuthenticated bool `json:"isAuthenticated"` + PrincipalID string `json:"principalId"` + DisconnectAfterInSeconds int32 `json:"disconnectAfterInSeconds"` + RefreshAfterInSeconds int32 `json:"refreshAfterInSeconds"` + PolicyDocuments []string `json:"policyDocuments"` +}