Skip to content

Commit b2b8b22

Browse files
committed
rename init.go to server.go, use configuration struct and add validation, add constants for lambda memory/frequency, increase LambdaMaxMemorySize to 3008, set minimum execution frequency to 60 seconds, use logrus for logger with flag to enable debug
1 parent b87f634 commit b2b8b22

File tree

2 files changed

+206
-56
lines changed

2 files changed

+206
-56
lines changed

pkg/server/init.go

Lines changed: 0 additions & 56 deletions
This file was deleted.

pkg/server/server.go

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package server
2+
3+
import (
4+
"fmt"
5+
"runtime"
6+
"time"
7+
8+
"github.com/dan-v/awslambdaproxy/pkg/server/publicip"
9+
"github.com/dan-v/awslambdaproxy/pkg/server/publicip/awspublicip"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
const (
14+
// LambdaMinMemorySize is the minimum memory size for a Lambda function in MB
15+
LambdaMinMemorySize = 128
16+
// LambdaMaxMemorySize is the maximum memory size for a Lambda function in MB
17+
LambdaMaxMemorySize = 3008
18+
19+
// LambdaDelayedCleanupTime is the time to wait if active connections still exist
20+
// this should be never be higher than LambdaExecutionTimeoutBuffer or function timeout
21+
// will happen before cleanup occurs
22+
LambdaDelayedCleanupTime = time.Second * 20
23+
// LambdaExecutionTimeoutBuffer is the time added to user specified execution frequency
24+
// to get the overall function timeout value
25+
LambdaExecutionTimeoutBuffer = time.Second * 30
26+
27+
// LambdaMinExecutionFrequency is the minimum frequency for function execution.
28+
LambdaMinExecutionFrequency = time.Second * 60
29+
// LambdaMaxExecutionFrequency is the maximum frequency for function execution.
30+
// The current max execution time is 900 seconds, but this takes into account
31+
// LambdaExecutionTimeoutBuffer + 10 seconds of leeway
32+
LambdaMaxExecutionFrequency = time.Second * 860
33+
)
34+
35+
// Config is used to define the configuration for Server
36+
type Config struct {
37+
// LambdaRegions is all regions to execute Lambda functions in
38+
LambdaRegions []string
39+
// LambdaMemory is the size of memory to assign Lambda function
40+
LambdaMemory int
41+
// LambdaExecutionFrequency is the frequency at which to execute Lambda functions
42+
LambdaExecutionFrequency time.Duration
43+
// ProxyListeners defines all listeners, protocol, and auth information
44+
// in format like this [scheme://][user:pass@host]:port.
45+
// see https://github.com/ginuerzh/gost/blob/master/README_en.md#getting-started
46+
ProxyListeners []string
47+
// ProxyDebug is whether debug logging should be shown for proxy traffic
48+
// note this will log all visited domains
49+
ProxyDebug bool
50+
// ReverseTunnelSSHUser is the ssh user to use for the lambda reverse ssh tunnel
51+
ReverseTunnelSSHUser string
52+
// ReverseTunnelSSHPort is the ssh port to use for the lambda reverse ssh tunnel
53+
ReverseTunnelSSHPort string
54+
// Debug enables general debug logging
55+
Debug bool
56+
}
57+
58+
// Server is the long running server component of awslambdaproxy
59+
type Server struct {
60+
publicIPClient publicip.Client
61+
lambdaRegions []string
62+
lambdaMemory int64
63+
lambdaExecutionFrequency time.Duration
64+
lambdaTimeoutSeconds int64
65+
proxyListeners []string
66+
proxyDebug bool
67+
reverseTunnelSSHUser string
68+
reverseTunnelSSHPort string
69+
debug bool
70+
logger *logrus.Logger
71+
}
72+
73+
func New(config Config) (*Server, error) {
74+
logger := logrus.New()
75+
if config.Debug {
76+
logger.SetLevel(logrus.DebugLevel)
77+
}
78+
79+
err := validateConfig(config)
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
functionTimeout := int(config.LambdaExecutionFrequency.Seconds()) + int(LambdaExecutionTimeoutBuffer.Seconds())
85+
s := &Server{
86+
publicIPClient: awspublicip.New(),
87+
lambdaRegions: config.LambdaRegions,
88+
lambdaMemory: int64(config.LambdaMemory),
89+
lambdaExecutionFrequency: config.LambdaExecutionFrequency,
90+
lambdaTimeoutSeconds: int64(functionTimeout),
91+
proxyListeners: config.ProxyListeners,
92+
proxyDebug: config.ProxyDebug,
93+
reverseTunnelSSHUser: config.ReverseTunnelSSHUser,
94+
reverseTunnelSSHPort: config.ReverseTunnelSSHPort,
95+
debug: config.Debug,
96+
logger: logger,
97+
}
98+
99+
logger.WithFields(logrus.Fields{
100+
"publicIPClient": s.publicIPClient.ProviderURL(),
101+
"lambdaRegions": s.lambdaRegions,
102+
"lambdaMemory": s.lambdaMemory,
103+
"lambdaExecutionFrequency": s.lambdaExecutionFrequency,
104+
"lambdaTimeoutSeconds": s.lambdaTimeoutSeconds,
105+
"proxyListeners": s.proxyListeners,
106+
"proxyDebug": s.proxyDebug,
107+
"reverseTunnelSSHUser": s.reverseTunnelSSHUser,
108+
"reverseTunnelSSHPort": s.reverseTunnelSSHPort,
109+
"debug": s.debug,
110+
}).Info("server has been configured with the following values")
111+
112+
return s, nil
113+
}
114+
115+
func (s *Server) Run() {
116+
publicIP, err := s.publicIPClient.GetIP()
117+
if err != nil {
118+
s.logger.WithError(err).Fatalf("error getting public IP address")
119+
}
120+
121+
s.logger.Infof("setting up lambda infrastructure")
122+
err = setupLambdaInfrastructure(s.lambdaRegions, s.lambdaMemory, s.lambdaTimeoutSeconds)
123+
if err != nil {
124+
s.logger.WithError(err).Fatalf("failed to setup lambda infrastructure")
125+
}
126+
127+
s.logger.Infof("starting ssh tunnel manager")
128+
privateKey, err := NewSSHManager()
129+
if err != nil {
130+
s.logger.WithError(err).Fatalf("failed to setup ssh tunnel manager")
131+
}
132+
133+
s.logger.Infof("starting local proxy")
134+
localProxy, err := NewLocalProxy(s.proxyListeners, s.proxyDebug)
135+
if err != nil {
136+
s.logger.WithError(err).Fatalf("failed to setup local proxy")
137+
}
138+
139+
s.logger.Println("starting connection manager")
140+
tunnelConnectionManager, err := newTunnelConnectionManager(s.lambdaExecutionFrequency, localProxy)
141+
if err != nil {
142+
s.logger.WithError(err).Fatalf("failed to setup connection manager")
143+
}
144+
145+
s.logger.Println("starting lambda execution manager")
146+
_, err = newLambdaExecutionManager(publicIP, s.lambdaRegions, s.lambdaExecutionFrequency,
147+
s.reverseTunnelSSHUser, s.reverseTunnelSSHPort, privateKey, tunnelConnectionManager.tunnelRedeployNeeded)
148+
if err != nil {
149+
s.logger.WithError(err).Fatalf("failed to setup lambda execution manager")
150+
}
151+
152+
s.logger.Println("#######################################")
153+
s.logger.Println("proxy ip address: ", publicIP)
154+
s.logger.Println("listeners: ", s.proxyListeners)
155+
s.logger.Println("#######################################")
156+
157+
runtime.Goexit()
158+
}
159+
160+
func validateConfig(config Config) error {
161+
// validate memory
162+
if config.LambdaMemory < LambdaMinMemorySize || config.LambdaMemory > LambdaMaxMemorySize {
163+
return fmt.Errorf("invalid lambda memory size '%vMB' - should be between %v and %v",
164+
config.LambdaMemory, LambdaMinMemorySize, LambdaMaxMemorySize)
165+
}
166+
if config.LambdaMemory%64 != 0 {
167+
return fmt.Errorf("invalid lambda memory size '%vMB' - should be in increments of 64MB",
168+
config.LambdaMemory)
169+
}
170+
171+
// validate frequency
172+
if config.LambdaExecutionFrequency < LambdaMinExecutionFrequency || config.LambdaExecutionFrequency > LambdaMaxExecutionFrequency {
173+
return fmt.Errorf("invalid lambda execution frequency '%v' - should be between %v and %v",
174+
config.LambdaExecutionFrequency, LambdaMinExecutionFrequency, LambdaMaxExecutionFrequency)
175+
}
176+
177+
// validate ssh user and port
178+
if config.ReverseTunnelSSHUser == "" {
179+
return fmt.Errorf("need to specify ReverseTunnelSSHUser")
180+
}
181+
if config.ReverseTunnelSSHPort == "" {
182+
return fmt.Errorf("need to specify ReverseTunnelSSHPort")
183+
}
184+
185+
// validate listeners
186+
if len(config.ProxyListeners) == 0 {
187+
return fmt.Errorf("no listener has been specified")
188+
}
189+
190+
// validate regions
191+
validRegions := GetValidLambdaRegions()
192+
for _, region := range config.LambdaRegions {
193+
valid := false
194+
for _, validRegion := range validRegions {
195+
if region == validRegion {
196+
valid = true
197+
break
198+
}
199+
}
200+
if !valid {
201+
return fmt.Errorf("invalid region '%v' specified. valid regions: %v",
202+
region, validRegions)
203+
}
204+
}
205+
return nil
206+
}

0 commit comments

Comments
 (0)