From 6c53f5a77826615a9351a175c678cb724c41e871 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:02:56 +0100 Subject: [PATCH 01/10] go get github.com/aws/aws-sdk-go-v2/config github.com/aws/aws-sdk-go-v2/service/sts --- go.mod | 21 +++++++++++++++++++-- go.sum | 26 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index aa3c37d..b3495b5 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,31 @@ module aws-golang-simple-http-endpoint -go 1.18 +go 1.22 + +toolchain go1.23.9 require ( github.com/aws/aws-lambda-go v1.35.0 + github.com/aws/aws-sdk-go-v2/config v1.29.14 + github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.1 ) -require github.com/hashicorp/errwrap v1.0.0 // indirect +require ( + github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect + github.com/aws/smithy-go v1.22.2 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index 21c623c..224c997 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,31 @@ github.com/aws/aws-lambda-go v1.35.0 h1:iocVDy5Cw5SCRrKOPHwarkdFwwy48OkfmHoE6SJ3ATg= github.com/aws/aws-lambda-go v1.35.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM= +github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= +github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= +github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= From e591673b8a82ef14552da5ad3fdff8a132376c00 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:03:14 +0100 Subject: [PATCH 02/10] Add RegionName and AccountID to FiretailLog struct --- logs-handler/firetail_log.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/logs-handler/firetail_log.go b/logs-handler/firetail_log.go index c7e3dc8..ed79042 100644 --- a/logs-handler/firetail_log.go +++ b/logs-handler/firetail_log.go @@ -38,6 +38,8 @@ type FiretailLog struct { RequestSummary *json.RawMessage `json:"requestSummary,omitempty"` ResponseHeaders *json.RawMessage `json:"responseHeaders,omitempty"` ResponseMappings *[]json.RawMessage `json:"responseMappings,omitempty"` + RegionName string `json:"regionName"` + AccountID string `json:"accountId"` } func (f *FiretailLog) IsPopulated() bool { From 22f561cff9dc362ac1f6522a615de5f10ac1e700 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:03:44 +0100 Subject: [PATCH 03/10] Implement getting account ID and region name from STS and env vars respectively --- logs-handler/main.go | 50 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/logs-handler/main.go b/logs-handler/main.go index 7aa3276..df23be5 100644 --- a/logs-handler/main.go +++ b/logs-handler/main.go @@ -1,26 +1,70 @@ package main import ( + "context" "os" "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/pkg/errors" ) const DefaultFiretailApiUrl string = "https://api.logging.eu-west-1.prod.firetail.app/logs/aws/appsync" var firetailApiUrl string var firetailApiToken string +var regionName string -func loadEnvVars() { +func loadEnvVars() error { var firetailApiUrlSet bool firetailApiUrl, firetailApiUrlSet = os.LookupEnv("FIRETAIL_API_URL") if !firetailApiUrlSet { firetailApiUrl = DefaultFiretailApiUrl } - firetailApiToken = os.Getenv("FIRETAIL_API_TOKEN") + + var firetailApiTokenSet bool + firetailApiToken, firetailApiTokenSet = os.LookupEnv("FIRETAIL_API_TOKEN") + if !firetailApiTokenSet { + return errors.New("FIRETAIL_API_TOKEN is not set") + } + + var regionNameExists bool + regionName, regionNameExists = os.LookupEnv("AWS_REGION") + if !regionNameExists { + regionName, regionNameExists = os.LookupEnv("AWS_DEFAULT_REGION") + } + if !regionNameExists { + return errors.New("Neither AWS_REGION nor AWS_DEFAULT_REGION are set. Cannot continue.") + } + + return nil +} + +var accountID string + +func loadAccountID() error { + cfg, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + return errors.Errorf("Failed to determine account ID: %v", err) + } + client := sts.NewFromConfig(cfg) + resp, err := client.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{}) + if err != nil { + return errors.Errorf("Failed to determine account ID: %v", err) + } + accountID = *resp.Account + return nil } func main() { - loadEnvVars() + err := loadAccountID() + if err != nil { + panic(err) + } + err = loadEnvVars() + if err != nil { + panic(err) + } lambda.Start(Handler) } From ab6d8559cdc3d23c3a78ca43d27204ed75150647 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:04:28 +0100 Subject: [PATCH 04/10] Add RegionName and AccountID to initialisation of FireTail log structs --- logs-handler/extract_firetail_logs.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/logs-handler/extract_firetail_logs.go b/logs-handler/extract_firetail_logs.go index af90ecd..77205a8 100644 --- a/logs-handler/extract_firetail_logs.go +++ b/logs-handler/extract_firetail_logs.go @@ -44,7 +44,9 @@ func ExtractFiretailLogs(logsData *events.CloudwatchLogsData) (map[string]*Firet firetailLog, firetailLogExists := firetailLogs[requestID] if !firetailLogExists { firetailLog = &FiretailLog{ - RequestID: requestID, + RequestID: requestID, + RegionName: regionName, + AccountID: accountID, } } From 1e76d4739c0e4dbc94563bdffde416465213c9c2 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:04:54 +0100 Subject: [PATCH 05/10] Remove redundant nil check --- logs-handler/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logs-handler/handler.go b/logs-handler/handler.go index c76b36b..cb0a63b 100644 --- a/logs-handler/handler.go +++ b/logs-handler/handler.go @@ -19,7 +19,7 @@ func Handler(ctx context.Context, event events.CloudwatchLogsEvent) error { if err != nil { log.Println("Errs extracting Firetail logs:", err.Error()) } - if firetailLogs == nil || len(firetailLogs) == 0 { + if len(firetailLogs) == 0 { log.Println("Generated no Firetail logs from this batch. Exiting...") return nil } From 40e2a29d4312c4457d01ac0b65aabe6112e9226e Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:05:04 +0100 Subject: [PATCH 06/10] update expected logs in tests --- logs-handler/handler_test.go | 2 +- logs-handler/send_to_firetail_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/logs-handler/handler_test.go b/logs-handler/handler_test.go index 0b6de99..f0e02b6 100644 --- a/logs-handler/handler_test.go +++ b/logs-handler/handler_test.go @@ -20,7 +20,7 @@ import ( func TestHandler(t *testing.T) { testData := "H4sIAAAAAAAAAO1ae3PbNhL/Kjj9lXRECS8SpDKcjuM4ridx01Zum6uUyUAkJNHmQwVBO7bH3/0WFCVbku3Kj2smvbM9EogFFovfPgHzspWpspQTdXQ+U61e683O0c7nw71+f2d/r9VuFWe50tDNXeYJQgnm3IXutJjs66KaAaUrz8qunM3K8zyC76TsptH5l/NTqqt8MhWTeGrEeaqruDw+n8/sG61kBlOxwMwdK48LaHiuT+KxckfCi9WIc8ZGeMRlFMR8FKuIR5SNY6UkAaIngoDHGNiV1aiMdDIzSZG/TVKjdNnqDVrjRCsjk9RpBHNSmY1i6cTq1HlfTMo3spxOZR6nStvH/gaX3bSo4t+liaZAJ86ZSw05xvLs4req9anexd6pyo1d7LKVxLAZJigTAWUcY8KIH/gupQwHxIMWdFMPU9+1zYBjV1AqfOHDWLsJk4AOjMwATuLBeOxR5mHstxe6sVip8dj1RthxIzl2uJC+Eyg/doQkgquAST8eoddqkuToF/VnBfxaV+1N0ajnCkyDgLkYsGcuLOYTnwji+ZT6PsOCg/Tc8zweiDtFI/zBou1rOZv+/B79XCl93kNZZaRFGx2eHy6al8McoQhsw6ifitK8SPJZZXro0iQmVT00bO2gIxAGWeKwdfVyPgGhJLbfV8Mc/ob5n3YBYFsvNB8yUWbOMLZcpMsBfeE7YGuxw0c0cPyIeg5WnMuAEjmSZNha445QLUWzEEJpUtY8yxdpkiUgJcHXM4zKysXDNYOraynb6MNM6XrXvYWobfSb1IkcpaqEPV/dqj0BH8T3OAVV8MDzwIBcjj1BXRK4nHOPMWte1HVh+J3aY+4jDWvvi4qqWlUOsuEC/SgzUMwcafAm9DZRadz0NqA/eR/ulvu4HFqvtGINW71hq3GCQwgAST4ZttrD1kyaKdAGw1Yj2xBceQixAoS2MtfzliSgaFUW6anSOzqvaVLnPYh2vSao9FTlnMEaDundDI+9vwiCXQMylt0ate5iibK7unAt/EFcL7uNhuppUZEb9QVY9C6tsJMqsyFq/pjMeW1n/FfADPAuLVyX9qGozJ7WhbbMBp+uFqgd5HUvdI5lWiroVtejasQ1SLDUSb3lWtLJPBrs/HTQ7PFuuOrxRsu8HBc6U/GRymYphIh62uXQOtVwOGxZDMEybbNXd1BMhIOpQ3371F4OLBaedz10X5kD8NnVcSfqfD5ivsa8E1Bc9A1b/bptP7ZCdVjjWgcB+3UFj092Du8rO/kyDD55J3cnm8e7+VK62xz9BvHvdvX1pZ/d2eucBE2C/8c8uR/JfHXQuC7n5iNQXqUpuqbNYapJBF935wDrUXGiGr520n0OSzEV3LN2TnxOBfWpRz1GmB8QIjwfu4RB3eULQgLm3e2wAbvXzMtZkZfq/+nssekMJKtS84jJ1mbr0s9OWa1AvxnfSuJwm82250VueGOXz2L0d8f2VaPfKkvtLVPQMlPdKiAh9hDjczjH+Cxw4Ujm04DCUcfncA7zOAf5GQETJ5jRuwUUj/bK/2cfvOF49mRk0XlOJ7zmhWMplcdAcE+OHKteB+TljqIR86QYY6xGG7z6CvYSr7C06iohk+Qq3i2q3ApPvyFntyCHg6c4fRvZ2dvAeT17HUdAES0zaVgnUXQT1JDCs5HaqHjH1PQ7Y81DXJlt6cpfLdbcfS7fiDVx1dQ3rZ5HIaxC5dxejUBLsfpVlsnGkh7p0rUyjpImQEGApw4hDsNHhPQw67leB0pxQr0/6tEqj+8fGwiG6R9NTISKzsZHGwPqZT6Mx6WyfuVCriDtla3ygLie9adFIQgg2SeZJvFizAYfwqgI8CojwYQrrh7qWk83wbtvLB5hgvND2ZGWESD4ZNHuKT/vMT7Xp76HfbJmfI1QjytG19Tnupzxb7BGvTOca2UqnS8Jy3X+Zlu8p/S6R+FcCPEwZbfnSXhT57Z3Q92ubyV02bPhfkONK7AfvPnX10DdfxTqlHjr8f2vUW9KmU3gG8Jt2AtOXPxfx75vNIj+VfAPHpdjIQrBIcbdSgcPqO7X8IdTEWXfZNH/kGC3W0ClF82R/dsNgN/9X7V78xzx/Icqv7081dwS++aEDROAYg5TTsSzuuAa4GsqGdghn76GKsjjYiFn28XCW1XRxg/LR6AQCnuh/9B8xB9wv3FDB8QTT3CHNnmwDhicBYJ/qg6e/WD6TGcC/oAD6S3/eXmGg+dDbz5AUFOVu0VsBaHY+rq9/cgjIPf8ANc/T1fYsx7jGrTQD0rGkI976LK+QcuNk6p8YqbhgOHgUxtpNVZa6XAwNWZW9rrdZRXQgQmQzVUHaoSOzORFkUNX1oVJkX1ZZayBoXOaqDOlncjesOjzcPDje6CXKnLGykRTpwTnDAeRLsqybgPxiyOzi9xpdJfE4WCbDcHEQidwNN1e0sVaTlWChIBdbsLBzu99Z3c+3NmZzfr2JaJ64LjQZ1LHKnZmhYaBnDPoP01kOKAdjKQ/8nw4QiiiqCtcwtk4EIL74/FoRAOJO9eYdHJl0Iv6hZ639vllgwjAUUknK0ZJCph8j28FUpawQ0KYt0pNSidW5YkpZs3AcGB0ZeGcQtQBhN34gqliZI4jJWZcwSrspEhOZ7KzeCMJ6rjONWRzmCxgc6QW1mGruXAAc9IkquNy97gs8hWdZuAIsGKhy3XgdGGKRj9AklGkZmBvMp9UgH44ULmz/7oNn7/2X/0Z4k4A7brhrzGCVjgQokME69AA/tqIuB3i+h2OoXPJe1PQNrK3xN1ZKhNof9f9bgPGEqKHMadLGOtb05saCiHB7BfFJFVod6oLm0JenYbDFsECogEaturepMrW+38sTLjz/Wst87ghUW6z0cLiDcRP5ViD/6WAocTxmC+YH4wcwWLw85HgsRsHYyi9PSGk9OWG8Ma+rmM2ZP9ileucKPC/7+AnmySxTlaszl7X2rtbu7lMRh/6tWA3mP+VFiHaFTFE/3AwuUhmbRSrsY2BbTTSSz+LxvXupqf8Y5p93DkxR95v7gU9m73bOzu+iPRH/W7n6Dh+Y/59nJrZ++hg//MPb7LXUfzlon8WhsDnpqceFhdJmsquC9734tCmHlOU01foAAw1RdCBPvTRR0TwZ+J+Fi8ReHOqflejd4npukx0mIdevPvh6PB9G6XJiUL7KjopXjY67YLWOtj+or4cS500UzYQn7vrrdYy9wZwSxBWZTNz/unpOWDb+7Itc8D830U3ksBu4+Y2q4brzvMKRVOpoToKfz166/hP3822l0Fb7aa+1y+RDd5VpuIeIk+Wb9trk61LpOWbkJ+u/gM4Pc+p6CoAAA==" - expectedPayload := "{\"executionSummary\":{\"duration\":62176672,\"logType\":\"ExecutionSummary\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"startTime\":\"2022-11-30T11:03:56.035126Z\",\"endTime\":\"2022-11-30T11:03:56.097302Z\",\"parsing\":{\"startOffset\":56801,\"duration\":49156},\"version\":1,\"validation\":{\"startOffset\":132790,\"duration\":73757},\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\"},\"query\":\"mutation MyMutation {\\n createPost(input: {title: \\\"A Test Post\\\"}) {\\n id\\n }\\n}\\n\\nquery MyQuery {\\n getPost(id: \\\"a5422778-e5bd-4b29-8c26-0e44a921aba1\\\") {\\n id\\n title\\n }\\n listPosts(limit: 10) {\\n items {\\n id\\n }\\n }\\n}\\n, Operation: MyQuery, Variables: {}\",\"request_id\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"requestHeaders\":{\"accept\":[\"application/json, text/plain, */*\"],\"accept-encoding\":[\"gzip, deflate, br\"],\"accept-language\":[\"en-GB,en-US;q=0.9,en;q=0.8\"],\"cloudfront-forwarded-proto\":[\"https\"],\"cloudfront-is-desktop-viewer\":[\"true\"],\"cloudfront-is-mobile-viewer\":[\"false\"],\"cloudfront-is-smarttv-viewer\":[\"false\"],\"cloudfront-is-tablet-viewer\":[\"false\"],\"cloudfront-viewer-asn\":[\"1136\"],\"cloudfront-viewer-country\":[\"NL\"],\"content-length\":[\"309\"],\"content-type\":[\"application/json\"],\"host\":[\"c5dz3eobtjce7p4emob3koivpa.appsync-api.eu-west-1.amazonaws.com\"],\"origin\":[\"https://eu-west-1.console.aws.amazon.com\"],\"referer\":[\"https://eu-west-1.console.aws.amazon.com/\"],\"sec-ch-ua\":[\"\\\"Google Chrome\\\";v=\\\"107\\\", \\\"Chromium\\\";v=\\\"107\\\", \\\"Not=A?Brand\\\";v=\\\"24\\\"\"],\"sec-ch-ua-mobile\":[\"?0\"],\"sec-ch-ua-platform\":[\"\\\"macOS\\\"\"],\"sec-fetch-dest\":[\"empty\"],\"sec-fetch-mode\":[\"cors\"],\"sec-fetch-site\":[\"cross-site\"],\"user-agent\":[\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"],\"via\":[\"2.0 a8b68315e1e2575143f97748ffbb29a0.cloudfront.net (CloudFront)\"],\"x-amz-cf-id\":[\"hv4XlmXAktT6V5z2wpKEwjzcrXrKATjdDtYjltpLcIG_HDmBcdxzSw==\"],\"x-amz-user-agent\":[\"AWS-Console-AppSync/\"],\"x-amzn-requestid\":[\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\"],\"x-amzn-trace-id\":[\"Root=1-6387389b-73d623b74d5d9f671677aa8a\"],\"x-api-key\":[\"****mgidri\"],\"x-forwarded-for\":[\"77.173.29.29, 15.158.40.17\"],\"x-forwarded-port\":[\"443\"],\"x-forwarded-proto\":[\"https\"]},\"requestMappings\":[{\"logType\":\"RequestMapping\",\"path\":[\"getPost\"],\"fieldName\":\"getPost\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/getPost\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\"},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{\\n \\\"version\\\": \\\"2017-02-28\\\",\\n \\\"operation\\\": \\\"GetItem\\\",\\n \\\"key\\\": {\\n \\\"id\\\": {\\\"S\\\":\\\"a5422778-e5bd-4b29-8c26-0e44a921aba1\\\"},\\n },\\n}\"},{\"logType\":\"RequestMapping\",\"path\":[\"listPosts\"],\"fieldName\":\"listPosts\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/listPosts\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"limit\":10},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{\\n \\\"version\\\": \\\"2017-02-28\\\",\\n \\\"operation\\\": \\\"Scan\\\",\\n \\\"filter\\\": null ,\\n \\\"limit\\\": 10,\\n \\\"nextToken\\\": null,\\n}\"}],\"requestSummary\":{\"logType\":\"RequestSummary\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"statusCode\":200,\"latency\":89000000},\"responseHeaders\":{\"Content-Type\":\"application/json; charset=UTF-8\"},\"responseMappings\":[{\"logType\":\"ResponseMapping\",\"path\":[\"getPost\"],\"fieldName\":\"getPost\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/getPost\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\"},\"result\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\",\"title\":\"A Test Post\"},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{id=a5422778-e5bd-4b29-8c26-0e44a921aba1, title=A Test Post}\"},{\"logType\":\"ResponseMapping\",\"path\":[\"listPosts\"],\"fieldName\":\"listPosts\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/listPosts\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"limit\":10},\"result\":{\"items\":[{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\",\"title\":\"A Test Post\"},{\"id\":\"0daae63f-46ab-4631-8db4-e2c36a7f00eb\",\"title\":\"A Second Test Post\"}],\"scannedCount\":2},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{items=[{id=a5422778-e5bd-4b29-8c26-0e44a921aba1, title=A Test Post}, {id=0daae63f-46ab-4631-8db4-e2c36a7f00eb, title=A Second Test Post}], nextToken=null, scannedCount=2, startedAt=null}\"}]}\n" + expectedPayload := "{\"executionSummary\":{\"duration\":62176672,\"logType\":\"ExecutionSummary\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"startTime\":\"2022-11-30T11:03:56.035126Z\",\"endTime\":\"2022-11-30T11:03:56.097302Z\",\"parsing\":{\"startOffset\":56801,\"duration\":49156},\"version\":1,\"validation\":{\"startOffset\":132790,\"duration\":73757},\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\"},\"query\":\"mutation MyMutation {\\n createPost(input: {title: \\\"A Test Post\\\"}) {\\n id\\n }\\n}\\n\\nquery MyQuery {\\n getPost(id: \\\"a5422778-e5bd-4b29-8c26-0e44a921aba1\\\") {\\n id\\n title\\n }\\n listPosts(limit: 10) {\\n items {\\n id\\n }\\n }\\n}\\n, Operation: MyQuery, Variables: {}\",\"request_id\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"requestHeaders\":{\"accept\":[\"application/json, text/plain, */*\"],\"accept-encoding\":[\"gzip, deflate, br\"],\"accept-language\":[\"en-GB,en-US;q=0.9,en;q=0.8\"],\"cloudfront-forwarded-proto\":[\"https\"],\"cloudfront-is-desktop-viewer\":[\"true\"],\"cloudfront-is-mobile-viewer\":[\"false\"],\"cloudfront-is-smarttv-viewer\":[\"false\"],\"cloudfront-is-tablet-viewer\":[\"false\"],\"cloudfront-viewer-asn\":[\"1136\"],\"cloudfront-viewer-country\":[\"NL\"],\"content-length\":[\"309\"],\"content-type\":[\"application/json\"],\"host\":[\"c5dz3eobtjce7p4emob3koivpa.appsync-api.eu-west-1.amazonaws.com\"],\"origin\":[\"https://eu-west-1.console.aws.amazon.com\"],\"referer\":[\"https://eu-west-1.console.aws.amazon.com/\"],\"sec-ch-ua\":[\"\\\"Google Chrome\\\";v=\\\"107\\\", \\\"Chromium\\\";v=\\\"107\\\", \\\"Not=A?Brand\\\";v=\\\"24\\\"\"],\"sec-ch-ua-mobile\":[\"?0\"],\"sec-ch-ua-platform\":[\"\\\"macOS\\\"\"],\"sec-fetch-dest\":[\"empty\"],\"sec-fetch-mode\":[\"cors\"],\"sec-fetch-site\":[\"cross-site\"],\"user-agent\":[\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"],\"via\":[\"2.0 a8b68315e1e2575143f97748ffbb29a0.cloudfront.net (CloudFront)\"],\"x-amz-cf-id\":[\"hv4XlmXAktT6V5z2wpKEwjzcrXrKATjdDtYjltpLcIG_HDmBcdxzSw==\"],\"x-amz-user-agent\":[\"AWS-Console-AppSync/\"],\"x-amzn-requestid\":[\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\"],\"x-amzn-trace-id\":[\"Root=1-6387389b-73d623b74d5d9f671677aa8a\"],\"x-api-key\":[\"****mgidri\"],\"x-forwarded-for\":[\"77.173.29.29, 15.158.40.17\"],\"x-forwarded-port\":[\"443\"],\"x-forwarded-proto\":[\"https\"]},\"requestMappings\":[{\"logType\":\"RequestMapping\",\"path\":[\"getPost\"],\"fieldName\":\"getPost\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/getPost\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\"},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{\\n \\\"version\\\": \\\"2017-02-28\\\",\\n \\\"operation\\\": \\\"GetItem\\\",\\n \\\"key\\\": {\\n \\\"id\\\": {\\\"S\\\":\\\"a5422778-e5bd-4b29-8c26-0e44a921aba1\\\"},\\n },\\n}\"},{\"logType\":\"RequestMapping\",\"path\":[\"listPosts\"],\"fieldName\":\"listPosts\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/listPosts\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"limit\":10},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{\\n \\\"version\\\": \\\"2017-02-28\\\",\\n \\\"operation\\\": \\\"Scan\\\",\\n \\\"filter\\\": null ,\\n \\\"limit\\\": 10,\\n \\\"nextToken\\\": null,\\n}\"}],\"requestSummary\":{\"logType\":\"RequestSummary\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"statusCode\":200,\"latency\":89000000},\"responseHeaders\":{\"Content-Type\":\"application/json; charset=UTF-8\"},\"responseMappings\":[{\"logType\":\"ResponseMapping\",\"path\":[\"getPost\"],\"fieldName\":\"getPost\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/getPost\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\"},\"result\":{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\",\"title\":\"A Test Post\"},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{id=a5422778-e5bd-4b29-8c26-0e44a921aba1, title=A Test Post}\"},{\"logType\":\"ResponseMapping\",\"path\":[\"listPosts\"],\"fieldName\":\"listPosts\",\"resolverArn\":\"arn:aws:appsync:eu-west-1:453671210445:apis/lcyxyv2rungh7gdht7ylrudsjy/types/Query/resolvers/listPosts\",\"requestId\":\"0eff56b0-5caf-47a8-9e8d-7a174e93a8db\",\"context\":{\"arguments\":{\"limit\":10},\"result\":{\"items\":[{\"id\":\"a5422778-e5bd-4b29-8c26-0e44a921aba1\",\"title\":\"A Test Post\"},{\"id\":\"0daae63f-46ab-4631-8db4-e2c36a7f00eb\",\"title\":\"A Second Test Post\"}],\"scannedCount\":2},\"stash\":{},\"outErrors\":[]},\"fieldInError\":false,\"errors\":[],\"parentType\":\"Query\",\"graphQLAPIId\":\"lcyxyv2rungh7gdht7ylrudsjy\",\"transformedTemplate\":\"{items=[{id=a5422778-e5bd-4b29-8c26-0e44a921aba1, title=A Test Post}, {id=0daae63f-46ab-4631-8db4-e2c36a7f00eb, title=A Second Test Post}], nextToken=null, scannedCount=2, startedAt=null}\"}],\"regionName\":\"\",\"accountId\":\"\"}\n" wg := &sync.WaitGroup{} wg.Add(1) diff --git a/logs-handler/send_to_firetail_test.go b/logs-handler/send_to_firetail_test.go index 2f20ba0..f9ee439 100644 --- a/logs-handler/send_to_firetail_test.go +++ b/logs-handler/send_to_firetail_test.go @@ -17,7 +17,7 @@ func TestSendToFiretail(t *testing.T) { testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requestBody, err := ioutil.ReadAll(r.Body) require.Nil(t, err) - assert.Equal(t, "{\"query\":\"TEST_QUERY\",\"request_id\":\"TEST_ID\"}\n", string(requestBody)) + assert.Equal(t, "{\"query\":\"TEST_QUERY\",\"request_id\":\"TEST_ID\",\"regionName\":\"\",\"accountId\":\"\"}\n", string(requestBody)) wg.Done() w.Write([]byte(`{"message":"success"}`)) })) @@ -40,7 +40,7 @@ func TestSendToFiretailBadServer(t *testing.T) { testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requestBody, err := ioutil.ReadAll(r.Body) require.Nil(t, err) - assert.Equal(t, "{\"query\":\"TEST_QUERY\",\"request_id\":\"TEST_ID\"}\n", string(requestBody)) + assert.Equal(t, "{\"query\":\"TEST_QUERY\",\"request_id\":\"TEST_ID\",\"regionName\":\"\",\"accountId\":\"\"}\n", string(requestBody)) wg.Done() w.Write([]byte(`{"message":"fail"}`)) })) From cb5c6d305c5bfd4eb1afbd1eb39b6a4d0d01eaae Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:20:29 +0100 Subject: [PATCH 07/10] bump semantic version in sandbox workflow --- .github/workflows/deploy-sandbox.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml index 8288d62..e455306 100644 --- a/.github/workflows/deploy-sandbox.yaml +++ b/.github/workflows/deploy-sandbox.yaml @@ -7,7 +7,7 @@ env: CFN_TEMPLATES_BUCKET: firetail-sandbox-us-east-1-cf-templates CFN_TEMPLATES_BUCKET_REGION: us-east-1 APP_NAME: aws-appsync-logging-lambda - SEMANTIC_VERSION: 1.1.39 + SEMANTIC_VERSION: 1.2.1 name: Deploy to Sandbox run-name: "@${{ github.triggering_actor }}: ${{ github.ref_name }}: ${{ github.event_name }}" on: From 242859627e3cf519d0ca9c272f498b65c6377e2c Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:40:35 +0100 Subject: [PATCH 08/10] load app token from FIRETAIL_APP_TOKEN --- src/main.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main.go b/src/main.go index df23be5..d4f61cc 100644 --- a/src/main.go +++ b/src/main.go @@ -13,7 +13,8 @@ import ( const DefaultFiretailApiUrl string = "https://api.logging.eu-west-1.prod.firetail.app/logs/aws/appsync" var firetailApiUrl string -var firetailApiToken string +var firetailToken string +var firetailTokenHeaderName string = "x-ft-api-key" var regionName string func loadEnvVars() error { @@ -23,10 +24,14 @@ func loadEnvVars() error { firetailApiUrl = DefaultFiretailApiUrl } - var firetailApiTokenSet bool - firetailApiToken, firetailApiTokenSet = os.LookupEnv("FIRETAIL_API_TOKEN") - if !firetailApiTokenSet { - return errors.New("FIRETAIL_API_TOKEN is not set") + var firetailTokenSet bool + firetailToken, firetailTokenSet = os.LookupEnv("FIRETAIL_API_TOKEN") + if !firetailTokenSet { + firetailToken, firetailTokenSet = os.LookupEnv("FIRETAIL_APP_TOKEN") + firetailTokenHeaderName = "x-ft-app-key" + } + if !firetailTokenSet { + return errors.New("Neither FIRETAIL_API_TOKEN or FIRETAIL_APP_TOKEN are set. Cannot continue.") } var regionNameExists bool @@ -35,7 +40,7 @@ func loadEnvVars() error { regionName, regionNameExists = os.LookupEnv("AWS_DEFAULT_REGION") } if !regionNameExists { - return errors.New("Neither AWS_REGION nor AWS_DEFAULT_REGION are set. Cannot continue.") + return errors.New("Neither AWS_REGION or AWS_DEFAULT_REGION are set. Cannot continue.") } return nil From 59ac88686d10bfdf0933452dd1c46318eb5b81f1 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:41:01 +0100 Subject: [PATCH 09/10] update SendToFiretail to take header name for token as arg --- src/handler.go | 2 +- src/send_to_firetail.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/handler.go b/src/handler.go index cb0a63b..170bc63 100644 --- a/src/handler.go +++ b/src/handler.go @@ -33,5 +33,5 @@ func Handler(ctx context.Context, event events.CloudwatchLogsEvent) error { log.Println(string(logBytes)) } - return SendToFiretail(firetailLogs, firetailApiUrl, firetailApiToken) + return SendToFiretail(firetailLogs, firetailApiUrl, firetailTokenHeaderName, firetailToken) } diff --git a/src/send_to_firetail.go b/src/send_to_firetail.go index 016645f..bdff625 100644 --- a/src/send_to_firetail.go +++ b/src/send_to_firetail.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" ) -func SendToFiretail(firetailLogs map[string]*FiretailLog, apiUrl, apiToken string) error { +func SendToFiretail(firetailLogs map[string]*FiretailLog, apiUrl, tokenHeaderName, token string) error { reqBytes := []byte{} for _, firetailLog := range firetailLogs { logBytes, err := json.Marshal(*firetailLog) @@ -29,7 +29,7 @@ func SendToFiretail(firetailLogs map[string]*FiretailLog, apiUrl, apiToken strin return err } - req.Header.Set("x-ft-api-key", apiToken) + req.Header.Set(tokenHeaderName, token) resp, err := http.DefaultClient.Do(req) if err != nil { From 9bb6dbfa3a382340ef1d12c9c0a2653f2f418176 Mon Sep 17 00:00:00 2001 From: theteacat Date: Wed, 7 May 2025 10:41:07 +0100 Subject: [PATCH 10/10] update tests --- src/main_test.go | 6 +++--- src/send_to_firetail_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main_test.go b/src/main_test.go index 8bd2c80..e46f9e8 100644 --- a/src/main_test.go +++ b/src/main_test.go @@ -16,7 +16,7 @@ func TestLoadEnvVars(t *testing.T) { loadEnvVars() assert.Equal(t, firetailApiUrl, MockFiretailApiUrl) - assert.Equal(t, firetailApiToken, MockFiretailApiToken) + assert.Equal(t, firetailToken, MockFiretailApiToken) } func TestLoadEnvVarsApiUrlUnset(t *testing.T) { @@ -27,5 +27,5 @@ func TestLoadEnvVarsApiUrlUnset(t *testing.T) { loadEnvVars() assert.Equal(t, firetailApiUrl, DefaultFiretailApiUrl) - assert.Equal(t, firetailApiToken, MockFiretailApiToken) -} \ No newline at end of file + assert.Equal(t, firetailToken, MockFiretailApiToken) +} diff --git a/src/send_to_firetail_test.go b/src/send_to_firetail_test.go index f9ee439..65e3a54 100644 --- a/src/send_to_firetail_test.go +++ b/src/send_to_firetail_test.go @@ -28,7 +28,7 @@ func TestSendToFiretail(t *testing.T) { Query: &testQuery, RequestID: "TEST_ID", }, - }, testServer.URL, "TEST_KEY") + }, testServer.URL, "x-ft-api-key", "TEST_KEY") require.Nil(t, err) wg.Wait() @@ -51,7 +51,7 @@ func TestSendToFiretailBadServer(t *testing.T) { Query: &testQuery, RequestID: "TEST_ID", }, - }, testServer.URL, "TEST_KEY") + }, testServer.URL, "x-ft-api-key", "TEST_KEY") require.NotNil(t, err) assert.Equal(t, "got err response from firetail api: map[message:fail]", err.Error()) @@ -65,7 +65,7 @@ func TestSendToFiretailNoServer(t *testing.T) { Query: &testQuery, RequestID: "TEST_ID", }, - }, "http://127.0.0.1:0", "TEST_KEY") + }, "http://127.0.0.1:0", "x-ft-api-key", "TEST_KEY") require.NotNil(t, err) assert.Contains(t, err.Error(), "Post \"http://127.0.0.1:0\": dial tcp 127.0.0.1:0") } @@ -77,7 +77,7 @@ func TestSendToFiretailBadUrl(t *testing.T) { Query: &testQuery, RequestID: "TEST_ID", }, - }, "\n", "TEST_KEY") + }, "\n", "x-ft-api-key", "TEST_KEY") require.NotNil(t, err) assert.Equal(t, "parse \"\\n\": net/url: invalid control character in URL", err.Error()) }