Enable the aws CSM for application specific the following Environment Variables
1export AWS_CSM_ENABLED=true # or config the `~/.aws/config` include `csm_enabled = true`
2export AWS_CSM_HOST=10.0.0.1 # to send message to udp host
3export AWS_CSM_PORT=31000 # the CSM host port to listener
4export AWS_CSM_CLIENT_ID=appName # to set an identifier to differentiate multiple processes you might have configured to send to the same listener.
Receive the message from client in local testing
Receive the message from client use go code
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "log"
7 "net"
8 "os"
9 "os/signal"
10 "runtime"
11 "strconv"
12 "strings"
13 "syscall"
14)
15
16// ActionMessage is a struct representing a message from CSM
17type ActionMessage struct {
18 Version int `json:"Version"`
19 ClientID string `json:"ClientId"`
20 Type string `json:"Type"`
21 Service string `json:"Service"`
22 Action string `json:"Api"`
23 Timestamp int `json:"Timestamp"`
24 AttemptLatency int `json:"AttemptLatency"`
25 Fqdn string `json:"Fqdn"`
26 UserAgent string `json:"UserAgent"`
27 AccessKey string `json:"AccessKey"`
28 Region string `json:"Region"`
29 HTTPStatusCode int `json:"HttpStatusCode"`
30 FinalHTTPStatusCode int `json:"FinalHttpStatusCode"`
31 XAmzRequestID string `json:"XAmzRequestId"`
32 XAmzID2 string `json:"XAmzId2"`
33}
34
35func listen(connection *net.UDPConn, quit chan struct{}) {
36 buffer := make([]byte, 4096)
37 n, _, err := 0, new(net.UDPAddr), error(nil)
38 var message ActionMessage
39 for err == nil {
40 n, _, err = connection.ReadFromUDP(buffer)
41 err := json.Unmarshal(buffer[:n], &message)
42 if err != nil {
43 log.Println(err)
44 }
45 //Each action taken sends two json messages. The first has a type of "ApiCallAttempt" this filters for the API call itself
46 if message.Type == "ApiCall" {
47 fmt.Println(strings.ToLower(message.Service) + ":" + message.Action)
48 }
49 }
50 fmt.Println("listener failed - ", err)
51 quit <- struct{}{}
52}
53
54//SetupCloseHandler Displays a message when the user closes the program
55func SetupCloseHandler() {
56 c := make(chan os.Signal)
57 signal.Notify(c, os.Interrupt, syscall.SIGTERM)
58 go func() {
59 <-c
60 fmt.Println("\rCtrl+C pressed, Stopping...")
61 os.Exit(0)
62 }()
63}
64
65func main() {
66
67 var port = 31000
68 var err error
69 var addr = net.UDPAddr{
70 Port: port,
71 IP: net.IP{127, 0, 0, 1},
72 }
73 if os.Getenv("AWS_CSM_PORT") != "" {
74 port, err = strconv.Atoi(os.Getenv("AWS_CSM_PORT"))
75 if err != nil {
76 fmt.Println("Could not parse value of AWS_CSM_PORT Exiting...")
77 os.Exit(1)
78 }
79 }
80 if os.Getenv("IN_DOCKER") == "True" {
81 addr = net.UDPAddr{
82 Port: port,
83 IP: net.IP{0, 0, 0, 0},
84 }
85 }
86 connection, err := net.ListenUDP("udp", &addr)
87 if err != nil {
88 fmt.Println("Could not start Action hero on the specified port, Exiting...")
89 os.Exit(1)
90 }
91 fmt.Println("Action Hero Starting...")
92 SetupCloseHandler()
93 quit := make(chan struct{})
94 for i := 0; i < runtime.NumCPU(); i++ {
95 go listen(connection, quit)
96 }
97 <-quit // hang until an error
98}
Make a dockerfile
1FROM scratch
2COPY actionhero /
3EXPOSE 31000/udp
4ENTRYPOINT ["/actionhero"]
Health check for udp
1#!/usr/local/bin/python
2
3import enet
4import random
5import sys
6import os
7import signal
8
9udp_socket_port=int(os.environ.get('UDP_SOCKET_PORT'))
10udp_socket_ip=os.environ.get('UDP_SOCKET_IP').encode('utf-8')
11print("checking health of udp endpoint %s %s" %(udp_socket_ip,udp_socket_port))
12
13host = enet.Host(None, 1, 0, 0)
14addr=enet.Address(udp_socket_ip,udp_socket_port)
15peer = host.connect(addr,1)
16if peer:
17 print("%s:" % peer)
18 event = host.service(1000)
19 if event.type == enet.EVENT_TYPE_CONNECT:
20 print("%s: CONNECT" % event.peer.address)
21 elif event.type == enet.EVENT_TYPE_DISCONNECT:
22 print("%s: DISCONNECT" % event.peer.address)
23 os.system("while true; do pkill nginx;sleep 1;done")
24 print ("sidecar NGINX process stopped successfully")
Reference