serverless-vpc-discovery 4.0.2 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +1 -1
- package/README.md +63 -32
- package/dist/src/aws/ec2-wrapper.js +20 -15
- package/dist/src/common/lambda-function.js +52 -10
- package/dist/src/globals.js +8 -36
- package/dist/src/index.js +7 -11
- package/dist/src/logging.js +45 -0
- package/dist/src/utils.js +10 -45
- package/package.json +27 -23
- package/CHANGELOG.md +0 -72
- package/package-lock.json +0 -6826
package/.eslintrc.json
CHANGED
package/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# serverless-vpc-discovery
|
|
2
|
+
|
|
2
3
|
[](http://www.serverless.com)
|
|
3
4
|
[](https://travis-ci.org/amplify-education/serverless-vpc-discovery)
|
|
4
5
|
[](https://badge.fury.io/js/serverless-vpc-discovery)
|
|
5
6
|
[](https://raw.githubusercontent.com/amplify-education/serverless-vpc-discovery/master/LICENSE)
|
|
6
|
-
[](https://app.codacy.com/gh/amplify-education/serverless-vpc-discovery/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
7
8
|
[](https://www.npmjs.com/package/serverless-vpc-discovery)
|
|
8
9
|
|
|
9
|
-
The vpc discovery plugin takes the given vpc name, subnet tag key/value, and security group tag key/value or names in
|
|
10
|
+
The vpc discovery plugin takes the given vpc name, subnet tag key/value, and security group tag key/value or names in
|
|
11
|
+
the serverless file to setup the vpc configuration for the lambda.
|
|
10
12
|
|
|
11
13
|
Basically we use this config:
|
|
14
|
+
|
|
12
15
|
```
|
|
13
16
|
vpcDiscovery:
|
|
14
17
|
vpcName: '<vpc_name>'
|
|
@@ -21,7 +24,9 @@ vpcDiscovery:
|
|
|
21
24
|
tagValues:
|
|
22
25
|
- '<tag_value>'
|
|
23
26
|
```
|
|
27
|
+
|
|
24
28
|
To generate this config:
|
|
29
|
+
|
|
25
30
|
```
|
|
26
31
|
vpc:
|
|
27
32
|
subnetIds:
|
|
@@ -31,30 +36,43 @@ vpc:
|
|
|
31
36
|
- sg-123456789
|
|
32
37
|
...
|
|
33
38
|
```
|
|
39
|
+
|
|
34
40
|
For each lambda function.
|
|
35
|
-
|
|
36
|
-
> Note: The core serverless `provider.vpc` settings will be used, if they are set, instead of `vpcDiscovery`. You can
|
|
41
|
+
|
|
42
|
+
> Note: The core serverless `provider.vpc` settings will be used, if they are set, instead of `vpcDiscovery`. You can
|
|
43
|
+
> use also mix settings. For example you may set `provider.vpc.subnetIds` while using `vpcDiscovery` to set
|
|
44
|
+
> the `securityGroupIds`. Take a look
|
|
45
|
+
> at [official documentation](https://www.serverless.com/framework/docs/providers/aws/guide/functions#vpc-configuration).
|
|
37
46
|
|
|
38
47
|
# About Amplify
|
|
39
|
-
|
|
48
|
+
|
|
49
|
+
Amplify builds innovative and compelling digital educational products that empower teachers and students across the
|
|
50
|
+
country. We have a long history as the leading innovator in K-12 education - and have been described as the best tech
|
|
51
|
+
company in education and the best education company in tech. While others try to shrink the learning experience into the
|
|
52
|
+
technology, we use technology to expand what is possible in real classrooms with real students and teachers.
|
|
40
53
|
|
|
41
54
|
Learn more at https://www.amplify.com
|
|
42
55
|
|
|
43
56
|
# Getting Started
|
|
44
57
|
|
|
45
58
|
## Prerequisites
|
|
59
|
+
|
|
46
60
|
Make sure you have the following installed before starting:
|
|
61
|
+
|
|
47
62
|
* [nodejs](https://nodejs.org/en/download/)
|
|
48
|
-
* [npm](https://www.npmjs.com/get-npm?utm_source=house
|
|
63
|
+
* [npm](https://www.npmjs.com/get-npm?utm_source=house\&utm_medium=homepage\&utm_campaign=free%20orgs\&utm_term=Install%20npm)
|
|
49
64
|
* [serverless](https://serverless.com/framework/docs/providers/aws/guide/installation/)
|
|
50
65
|
|
|
51
66
|
Also allow the lambda to have the following IAM permissions:
|
|
67
|
+
|
|
52
68
|
* ec2:CreateNetworkInterface
|
|
53
69
|
* ec2:DescribeNetworkInterfaces
|
|
54
70
|
* ec2:DeleteNetworkInterface
|
|
55
71
|
|
|
56
72
|
## Installation
|
|
73
|
+
|
|
57
74
|
Run:
|
|
75
|
+
|
|
58
76
|
```
|
|
59
77
|
# From npm (recommended)
|
|
60
78
|
npm install serverless-vpc-discovery
|
|
@@ -62,7 +80,9 @@ npm install serverless-vpc-discovery
|
|
|
62
80
|
# From github
|
|
63
81
|
npm install https://github.com/amplify-education/serverless-vpc-discovery.git
|
|
64
82
|
```
|
|
83
|
+
|
|
65
84
|
Then make the following edits to your serverless.yaml file:
|
|
85
|
+
|
|
66
86
|
```yaml
|
|
67
87
|
plugins:
|
|
68
88
|
- serverless-vpc-discovery
|
|
@@ -71,12 +91,12 @@ plugins:
|
|
|
71
91
|
custom:
|
|
72
92
|
vpcDiscovery:
|
|
73
93
|
vpcName: '<vpc_name>'
|
|
74
|
-
|
|
94
|
+
|
|
75
95
|
# optional if `securityGroups` option is specified
|
|
76
96
|
# list of tag key and values
|
|
77
97
|
subnets:
|
|
78
98
|
- tagKey: <tag_name>
|
|
79
|
-
|
|
99
|
+
|
|
80
100
|
# an array of values
|
|
81
101
|
tagValues:
|
|
82
102
|
- '<tag_value>'
|
|
@@ -85,79 +105,83 @@ custom:
|
|
|
85
105
|
# list of tag key and value or names
|
|
86
106
|
securityGroups:
|
|
87
107
|
- tagKey: <tag_name>
|
|
88
|
-
|
|
108
|
+
|
|
89
109
|
# an array of values
|
|
90
110
|
tagValues:
|
|
91
111
|
- '<tag_value>'
|
|
92
|
-
|
|
112
|
+
|
|
93
113
|
# optional if `tagKey` and `tagValues` are specified
|
|
94
114
|
# an array of values
|
|
95
115
|
- names:
|
|
96
|
-
|
|
116
|
+
- '<security_group_name>'
|
|
97
117
|
|
|
98
118
|
# Optional: Either set `custom.vpcDiscovery` or `functions.<function name>.vpcDiscovery`
|
|
99
119
|
functions:
|
|
100
120
|
example:
|
|
101
121
|
handler: handler.example
|
|
102
122
|
# inherit `custom.vpcDiscovery` config in case `custom.vpcDiscovery` is specified
|
|
103
|
-
|
|
123
|
+
|
|
104
124
|
example2:
|
|
105
125
|
handler: handler.example
|
|
106
|
-
|
|
126
|
+
|
|
107
127
|
# skip vpc configuration for the current function
|
|
108
128
|
vpcDiscovery: false
|
|
109
|
-
|
|
129
|
+
|
|
110
130
|
example3:
|
|
111
131
|
handler: handler.example
|
|
112
|
-
|
|
132
|
+
|
|
113
133
|
# inherit `custom.vpcDiscovery` config in case `custom.vpcDiscovery` is specified and override security group names
|
|
114
134
|
vpcDiscovery:
|
|
115
135
|
vpcName: '<vpc_name>'
|
|
116
136
|
securityGroups:
|
|
117
137
|
- tagKey: <tag_name>
|
|
118
|
-
|
|
138
|
+
|
|
119
139
|
# an array of values
|
|
120
140
|
tagValues:
|
|
121
141
|
- '<tag_value>'
|
|
122
|
-
|
|
142
|
+
|
|
123
143
|
example4:
|
|
124
144
|
handler: handler.example
|
|
125
145
|
# override or set basic subnets and security groups items
|
|
126
146
|
vpcDiscovery:
|
|
127
147
|
vpcName: '<vpc_name>'
|
|
128
|
-
|
|
148
|
+
|
|
129
149
|
# optional if `custom.vpcDiscovery.securityGroups` option is specified
|
|
130
|
-
subnets:
|
|
150
|
+
subnets:
|
|
131
151
|
- tagKey: <tag_name>
|
|
132
|
-
|
|
152
|
+
|
|
133
153
|
# an array of values
|
|
134
154
|
tagValues:
|
|
135
155
|
- '<tag_value>'
|
|
136
156
|
|
|
137
157
|
# optional if `custom.vpcDiscovery.subnets` option is specified
|
|
138
|
-
securityGroups:
|
|
139
|
-
|
|
158
|
+
securityGroups:
|
|
159
|
+
|
|
140
160
|
# optional if `names` option is specified
|
|
141
161
|
- tagKey: <tag_name>
|
|
142
|
-
|
|
162
|
+
|
|
143
163
|
# an array of values
|
|
144
164
|
tagValues:
|
|
145
165
|
- '<tag_value>'
|
|
146
|
-
|
|
166
|
+
|
|
147
167
|
# optional if `tagKey` and `tagValues` are specified
|
|
148
168
|
# an array of values
|
|
149
|
-
- names:
|
|
150
|
-
|
|
169
|
+
- names:
|
|
170
|
+
- '<security_group_name>'
|
|
151
171
|
```
|
|
152
172
|
|
|
153
173
|
## Running Tests
|
|
174
|
+
|
|
154
175
|
To run the test:
|
|
176
|
+
|
|
155
177
|
```
|
|
156
178
|
npm test
|
|
157
179
|
```
|
|
180
|
+
|
|
158
181
|
All tests should pass.
|
|
159
182
|
|
|
160
|
-
To run integration tests, set an environment variable
|
|
183
|
+
To run integration tests, set an environment variable TEST\_VPC\_NAME to the VPC you will be testing for. Then,
|
|
184
|
+
|
|
161
185
|
```
|
|
162
186
|
export AWS_PROFILE=your_profile
|
|
163
187
|
export TEST_VPC_NAME=vpc_name
|
|
@@ -165,16 +189,19 @@ npm build
|
|
|
165
189
|
npm run integration-test
|
|
166
190
|
```
|
|
167
191
|
|
|
168
|
-
If there is an error build and install the
|
|
192
|
+
If there is an error build and install the node\_module inside the serverless-vpc-discovery folder:
|
|
193
|
+
|
|
169
194
|
```
|
|
170
195
|
npm build
|
|
171
196
|
npm install .
|
|
172
197
|
```
|
|
173
198
|
|
|
174
199
|
## Deploying with the plugin
|
|
200
|
+
|
|
175
201
|
When deploying run:
|
|
202
|
+
|
|
176
203
|
```
|
|
177
|
-
serverless deploy
|
|
204
|
+
serverless deploy
|
|
178
205
|
```
|
|
179
206
|
|
|
180
207
|
And that should be it! Good Luck!
|
|
@@ -185,14 +212,18 @@ The vpc, subnets, and security groups are found by filtering based on a specifie
|
|
|
185
212
|
Vpc and subnets are found under the tag name `tag:Name`.
|
|
186
213
|
Security groups are found by the name of the group under `group-name`.
|
|
187
214
|
|
|
188
|
-
The vpc is found first as it is used to find the subnets and security groups. Once all of the subnets and security
|
|
215
|
+
The vpc is found first as it is used to find the subnets and security groups. Once all of the subnets and security
|
|
216
|
+
groups are found the serverless service provider creates a vpc object and stores the subnets and security groups.
|
|
189
217
|
|
|
190
218
|
# Responsible Disclosure
|
|
219
|
+
|
|
191
220
|
If you have any security issue to report, contact project maintainers privately.
|
|
192
221
|
You can reach us at <github@amplify.com>
|
|
193
222
|
|
|
194
223
|
# Contributing
|
|
224
|
+
|
|
195
225
|
We welcome pull requests! For your pull request to be accepted smoothly, we suggest that you:
|
|
226
|
+
|
|
196
227
|
1. For any sizable change, first open a GitHub issue to discuss your idea.
|
|
197
|
-
2. Create a pull request.
|
|
198
|
-
We’ll try to answer any PR’s promptly.
|
|
228
|
+
2. Create a pull request. Explain why you want to make the change and what it’s for.
|
|
229
|
+
We’ll try to answer any PR’s promptly.
|
|
@@ -8,13 +8,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.EC2Wrapper = void 0;
|
|
13
|
-
const aws_sdk_1 = require("aws-sdk");
|
|
14
16
|
const utils_1 = require("../utils");
|
|
17
|
+
const client_ec2_1 = require("@aws-sdk/client-ec2");
|
|
18
|
+
const globals_1 = __importDefault(require("../globals"));
|
|
15
19
|
class EC2Wrapper {
|
|
16
20
|
constructor(credentials) {
|
|
17
|
-
this.ec2 = new
|
|
21
|
+
this.ec2 = new client_ec2_1.EC2Client([{
|
|
22
|
+
credentials,
|
|
23
|
+
retryStrategy: globals_1.default.getRetryStrategy()
|
|
24
|
+
}]);
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* Returns the promise that contains the vpc-id
|
|
@@ -23,13 +30,12 @@ class EC2Wrapper {
|
|
|
23
30
|
*/
|
|
24
31
|
getVpcId(vpcName) {
|
|
25
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const
|
|
33
|
+
const vpcItems = yield (0, utils_1.getAWSPagedResults)(this.ec2, "Vpcs", "NextToken", "NextToken", new client_ec2_1.DescribeVpcsCommand({
|
|
27
34
|
Filters: [{
|
|
28
35
|
Name: "tag:Name",
|
|
29
36
|
Values: [vpcName]
|
|
30
37
|
}]
|
|
31
|
-
};
|
|
32
|
-
const vpcItems = yield utils_1.getAWSPagedResults(this.ec2, "describeVpcs", "Vpcs", "NextToken", "NextToken", params);
|
|
38
|
+
}));
|
|
33
39
|
if (vpcItems.length === 0) {
|
|
34
40
|
throw new Error(`VPC with tag key 'Name' and tag value '${vpcName}' does not exist.`);
|
|
35
41
|
}
|
|
@@ -46,7 +52,7 @@ class EC2Wrapper {
|
|
|
46
52
|
*/
|
|
47
53
|
getSubnetIds(vpcId, tagKey, tagValues) {
|
|
48
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const
|
|
55
|
+
const subnets = yield (0, utils_1.getAWSPagedResults)(this.ec2, "Subnets", "NextToken", "NextToken", new client_ec2_1.DescribeSubnetsCommand({
|
|
50
56
|
Filters: [{
|
|
51
57
|
Name: "vpc-id",
|
|
52
58
|
Values: [vpcId]
|
|
@@ -54,12 +60,11 @@ class EC2Wrapper {
|
|
|
54
60
|
Name: `tag:${tagKey}`,
|
|
55
61
|
Values: tagValues
|
|
56
62
|
}]
|
|
57
|
-
};
|
|
58
|
-
const subnets = yield utils_1.getAWSPagedResults(this.ec2, "describeSubnets", "Subnets", "NextToken", "NextToken", params);
|
|
63
|
+
}));
|
|
59
64
|
const missingSubnetValues = tagValues.filter((tagValue) => {
|
|
60
65
|
// collect subnets by name
|
|
61
66
|
const subnetsByName = subnets.filter((subnet) => {
|
|
62
|
-
return utils_1.wildcardMatches(tagValue, utils_1.getValueFromTags(subnet.Tags, tagKey));
|
|
67
|
+
return (0, utils_1.wildcardMatches)(tagValue, (0, utils_1.getValueFromTags)(subnet.Tags, tagKey));
|
|
63
68
|
});
|
|
64
69
|
return subnetsByName.length === 0;
|
|
65
70
|
});
|
|
@@ -81,16 +86,16 @@ class EC2Wrapper {
|
|
|
81
86
|
getSecurityGroupIds(vpcId, names, tagKey, tagValues) {
|
|
82
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
88
|
// init filter by vpc id
|
|
84
|
-
const
|
|
89
|
+
const input = { Filters: [{ Name: "vpc-id", Values: [vpcId] }] };
|
|
85
90
|
// update filters with names if specified
|
|
86
91
|
if (names) {
|
|
87
|
-
|
|
92
|
+
input.Filters.push({ Name: "group-name", Values: names });
|
|
88
93
|
}
|
|
89
94
|
// update filters with tag and values if specified
|
|
90
95
|
if (tagKey && tagValues) {
|
|
91
|
-
|
|
96
|
+
input.Filters.push({ Name: `tag:${tagKey}`, Values: tagValues });
|
|
92
97
|
}
|
|
93
|
-
const securityGroups = yield utils_1.getAWSPagedResults(this.ec2, "
|
|
98
|
+
const securityGroups = yield (0, utils_1.getAWSPagedResults)(this.ec2, "SecurityGroups", "NextToken", "NextToken", new client_ec2_1.DescribeSecurityGroupsCommand(input));
|
|
94
99
|
if (securityGroups.length === 0) {
|
|
95
100
|
const namesErrorText = names ? `, names '${names}'` : "";
|
|
96
101
|
const tagErrorText = tagKey && tagValues ? `, tag key '${tagKey}' and tag values '${tagValues}'` : "";
|
|
@@ -100,7 +105,7 @@ class EC2Wrapper {
|
|
|
100
105
|
const missingGroupsNames = names.filter((groupName) => {
|
|
101
106
|
// collect security groups by name
|
|
102
107
|
const securityGroupsByName = securityGroups.filter((securityGroup) => {
|
|
103
|
-
return utils_1.wildcardMatches(groupName, securityGroup.GroupName);
|
|
108
|
+
return (0, utils_1.wildcardMatches)(groupName, securityGroup.GroupName);
|
|
104
109
|
});
|
|
105
110
|
return securityGroupsByName.length === 0;
|
|
106
111
|
});
|
|
@@ -114,7 +119,7 @@ class EC2Wrapper {
|
|
|
114
119
|
const missingGroupsTagNames = tagValues.filter((tagValue) => {
|
|
115
120
|
// collect subnets by name
|
|
116
121
|
const groupsByName = securityGroups.filter((securityGroup) => {
|
|
117
|
-
const groupTagValue = utils_1.getValueFromTags(securityGroup.Tags, tagKey);
|
|
122
|
+
const groupTagValue = (0, utils_1.getValueFromTags)(securityGroup.Tags, tagKey);
|
|
118
123
|
return groupTagValue === tagValue;
|
|
119
124
|
});
|
|
120
125
|
return groupsByName.length === 0;
|
|
@@ -14,11 +14,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.LambdaFunction = void 0;
|
|
16
16
|
const ec2_wrapper_1 = require("../aws/ec2-wrapper");
|
|
17
|
-
const globals_1 = __importDefault(require("../globals"));
|
|
18
17
|
const utils_1 = require("../utils");
|
|
19
18
|
const validation_1 = require("../validation");
|
|
19
|
+
const logging_1 = __importDefault(require("../logging"));
|
|
20
|
+
const ts_md5_1 = require("ts-md5");
|
|
20
21
|
class LambdaFunction {
|
|
21
22
|
constructor(credentials, basicVPCDiscovery) {
|
|
23
|
+
this.vpcIdsCache = {};
|
|
24
|
+
this.subnetsIdsCache = {};
|
|
25
|
+
this.SGIdsCache = {};
|
|
22
26
|
this.ec2Wrapper = new ec2_wrapper_1.EC2Wrapper(credentials);
|
|
23
27
|
this.basicVPCDiscovery = basicVPCDiscovery;
|
|
24
28
|
}
|
|
@@ -30,29 +34,29 @@ class LambdaFunction {
|
|
|
30
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
31
35
|
if (typeof funcVPCDiscovery === "boolean" && !funcVPCDiscovery) {
|
|
32
36
|
// skip vpc setup for `vpcDiscovery=false` option
|
|
33
|
-
|
|
37
|
+
logging_1.default.logInfo(`Skipping VPC config for the function '${funcName}'`);
|
|
34
38
|
return null;
|
|
35
39
|
}
|
|
36
40
|
// inherit the `custom.vpcDiscovery`
|
|
37
41
|
const vpcDiscovery = Object.assign({}, this.basicVPCDiscovery, funcVPCDiscovery);
|
|
38
42
|
// return null in case vpcDiscovery not setup
|
|
39
|
-
if (utils_1.isObjectEmpty(vpcDiscovery)) {
|
|
43
|
+
if ((0, utils_1.isObjectEmpty)(vpcDiscovery)) {
|
|
40
44
|
return null;
|
|
41
45
|
}
|
|
42
46
|
// validate func vpcDiscovery config
|
|
43
47
|
try {
|
|
44
|
-
validation_1.validateVPCDiscoveryConfig(vpcDiscovery);
|
|
48
|
+
(0, validation_1.validateVPCDiscoveryConfig)(vpcDiscovery);
|
|
45
49
|
}
|
|
46
50
|
catch (e) {
|
|
47
51
|
throw new Error(`Function '${funcName}' is not configured correctly: ${e} VPC not configured. ` +
|
|
48
52
|
"Please see the README for the proper setup.");
|
|
49
53
|
}
|
|
50
54
|
try {
|
|
51
|
-
|
|
55
|
+
logging_1.default.logInfo(`Getting VPC config for the function: '${funcName}'\n`);
|
|
52
56
|
return yield this.getVpcConfig(vpcDiscovery);
|
|
53
57
|
}
|
|
54
58
|
catch (e) {
|
|
55
|
-
|
|
59
|
+
logging_1.default.logError(`Function '${funcName}' VPC not configured based on the error: ${e}`);
|
|
56
60
|
}
|
|
57
61
|
return null;
|
|
58
62
|
});
|
|
@@ -65,12 +69,12 @@ class LambdaFunction {
|
|
|
65
69
|
getVpcConfig(vpcDiscovery) {
|
|
66
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
71
|
const vpc = {};
|
|
68
|
-
const vpcId = yield this.
|
|
69
|
-
|
|
72
|
+
const vpcId = yield this.getVPCId(vpcDiscovery.vpcName);
|
|
73
|
+
logging_1.default.logInfo(`Found VPC with id '${vpcId}'`);
|
|
70
74
|
if (vpcDiscovery.subnets) {
|
|
71
75
|
vpc.subnetIds = [];
|
|
72
76
|
for (const subnet of vpcDiscovery.subnets) {
|
|
73
|
-
const subnetIds = yield this.
|
|
77
|
+
const subnetIds = yield this.getVPCSubnets(vpcId, subnet.tagKey, subnet.tagValues);
|
|
74
78
|
vpc.subnetIds = vpc.subnetIds.concat(subnetIds);
|
|
75
79
|
}
|
|
76
80
|
// remove duplicate elements from the array
|
|
@@ -79,7 +83,7 @@ class LambdaFunction {
|
|
|
79
83
|
if (vpcDiscovery.securityGroups) {
|
|
80
84
|
vpc.securityGroupIds = [];
|
|
81
85
|
for (const group of vpcDiscovery.securityGroups) {
|
|
82
|
-
const groupIds = yield this.
|
|
86
|
+
const groupIds = yield this.getVPCSecurityGroups(vpcId, group.names, group.tagKey, group.tagValues);
|
|
83
87
|
vpc.securityGroupIds = vpc.securityGroupIds.concat(groupIds);
|
|
84
88
|
}
|
|
85
89
|
// remove duplicate elements from the array
|
|
@@ -88,5 +92,43 @@ class LambdaFunction {
|
|
|
88
92
|
return vpc;
|
|
89
93
|
});
|
|
90
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the VPC id from cache or read from AWS
|
|
97
|
+
* @returns {Promise<object>}
|
|
98
|
+
*/
|
|
99
|
+
getVPCId(vpcName) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
if (this.vpcIdsCache[vpcName] === undefined) {
|
|
102
|
+
this.vpcIdsCache[vpcName] = yield this.ec2Wrapper.getVpcId(vpcName);
|
|
103
|
+
}
|
|
104
|
+
return this.vpcIdsCache[vpcName];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get the subnet ids from cache or read from AWS
|
|
109
|
+
* @returns {Promise<object>}
|
|
110
|
+
*/
|
|
111
|
+
getVPCSubnets(vpcId, tagKey, tagValues) {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
const hash = ts_md5_1.Md5.hashStr(vpcId + tagKey + tagValues.join());
|
|
114
|
+
if (!this.subnetsIdsCache[hash]) {
|
|
115
|
+
this.subnetsIdsCache[hash] = yield this.ec2Wrapper.getSubnetIds(vpcId, tagKey, tagValues);
|
|
116
|
+
}
|
|
117
|
+
return this.subnetsIdsCache[hash];
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the security group ids from cache or read from AWS
|
|
122
|
+
* @returns {Promise<object>}
|
|
123
|
+
*/
|
|
124
|
+
getVPCSecurityGroups(vpcId, names, tagKey, tagValues) {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
const hash = ts_md5_1.Md5.hashStr(vpcId + (names || []).join() + tagKey + (tagValues || []).join());
|
|
127
|
+
if (!this.SGIdsCache[hash]) {
|
|
128
|
+
this.SGIdsCache[hash] = yield this.ec2Wrapper.getSecurityGroupIds(vpcId, names, tagKey, tagValues);
|
|
129
|
+
}
|
|
130
|
+
return this.SGIdsCache[hash];
|
|
131
|
+
});
|
|
132
|
+
}
|
|
91
133
|
}
|
|
92
134
|
exports.LambdaFunction = LambdaFunction;
|
package/dist/src/globals.js
CHANGED
|
@@ -1,42 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const util_retry_1 = require("@smithy/util-retry");
|
|
3
4
|
class Globals {
|
|
4
|
-
static
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
static logError(message) {
|
|
11
|
-
if (Globals.v3Utils) {
|
|
12
|
-
Globals.v3Utils.log.error(message);
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
Globals.cliLog("[Error]", message);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Logs info message
|
|
20
|
-
*/
|
|
21
|
-
static logInfo(message) {
|
|
22
|
-
if (Globals.v3Utils) {
|
|
23
|
-
Globals.v3Utils.log.verbose(message);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
Globals.cliLog("[Info]", message);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Logs warning message
|
|
31
|
-
*/
|
|
32
|
-
static logWarning(message) {
|
|
33
|
-
if (Globals.v3Utils) {
|
|
34
|
-
Globals.v3Utils.log.warning(message);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
Globals.cliLog("[WARNING]", message);
|
|
38
|
-
}
|
|
5
|
+
static getRetryStrategy(attempts = 3, delay = 3000, backoff = 500) {
|
|
6
|
+
return new util_retry_1.ConfiguredRetryStrategy(attempts, // max attempts.
|
|
7
|
+
// This example sets the backoff at 500ms plus 3s per attempt.
|
|
8
|
+
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_util_retry.html#aws-sdkutil-retry
|
|
9
|
+
(attempt) => backoff + attempt * delay // backoff function.
|
|
10
|
+
);
|
|
39
11
|
}
|
|
40
12
|
}
|
|
41
|
-
exports.default = Globals;
|
|
42
13
|
Globals.pluginName = "Serverless VPC Discovery";
|
|
14
|
+
exports.default = Globals;
|
package/dist/src/index.js
CHANGED
|
@@ -15,11 +15,12 @@ const lambda_function_1 = require("./common/lambda-function");
|
|
|
15
15
|
const globals_1 = __importDefault(require("./globals"));
|
|
16
16
|
const validation_1 = require("./validation");
|
|
17
17
|
const schema_1 = require("./schema");
|
|
18
|
+
const logging_1 = __importDefault(require("./logging"));
|
|
18
19
|
class VPCPlugin {
|
|
19
20
|
constructor(serverless, options, v3Utils) {
|
|
20
21
|
this.serverless = serverless;
|
|
21
22
|
globals_1.default.serverless = serverless;
|
|
22
|
-
if (v3Utils) {
|
|
23
|
+
if (v3Utils === null || v3Utils === void 0 ? void 0 : v3Utils.log) {
|
|
23
24
|
globals_1.default.v3Utils = v3Utils;
|
|
24
25
|
}
|
|
25
26
|
/* hooks are the actual code that will run when called */
|
|
@@ -53,7 +54,7 @@ class VPCPlugin {
|
|
|
53
54
|
try {
|
|
54
55
|
// the validateVPCDiscoveryConfig is general for custom and func configs
|
|
55
56
|
// so try catch for extend error message with `custom.vpcDiscovery` as a source
|
|
56
|
-
validation_1.validateVPCDiscoveryConfig(vpcDiscovery);
|
|
57
|
+
(0, validation_1.validateVPCDiscoveryConfig)(vpcDiscovery);
|
|
57
58
|
}
|
|
58
59
|
catch (e) {
|
|
59
60
|
throw new Error(`The \`custom.vpcDiscovery\` is not configured correctly: \n${e} ` + " Please see README for proper setup.");
|
|
@@ -74,14 +75,9 @@ class VPCPlugin {
|
|
|
74
75
|
if (vpcDiscovery.securityGroupNames) {
|
|
75
76
|
vpcDiscovery.securityGroups = [{ names: vpcDiscovery.securityGroupNames }];
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
logging_1.default.logWarning("The `vpcDiscovery.subnetNames` and `vpcDiscovery.securityGroupNames` options are deprecated " +
|
|
78
79
|
"and will be removed in the future. Please see README for proper setup.");
|
|
79
80
|
}
|
|
80
|
-
else {
|
|
81
|
-
// log warning in case mixed config are specified
|
|
82
|
-
globals_1.default.logWarning("The `vpcDiscovery.subnetNames` and `vpcDiscovery.securityGroupNames` are deprecated " +
|
|
83
|
-
"and will not be applied. Please remove mentioned option to not see this warning message.");
|
|
84
|
-
}
|
|
85
81
|
}
|
|
86
82
|
}
|
|
87
83
|
/**
|
|
@@ -99,7 +95,7 @@ class VPCPlugin {
|
|
|
99
95
|
*/
|
|
100
96
|
updateFunctionsVpcConfig() {
|
|
101
97
|
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
-
|
|
98
|
+
logging_1.default.logInfo("Updating VPC config...");
|
|
103
99
|
const service = this.serverless.service;
|
|
104
100
|
const functions = service.functions || {};
|
|
105
101
|
// Sets the serverless's vpc config
|
|
@@ -115,12 +111,12 @@ class VPCPlugin {
|
|
|
115
111
|
func.vpc = func.vpc || {};
|
|
116
112
|
// log warning in case vpc.subnetIds and vpcDiscovery.subnetNames are specified.
|
|
117
113
|
if (func.vpc.subnetIds && func.vpcDiscovery && func.vpcDiscovery.subnets) {
|
|
118
|
-
|
|
114
|
+
logging_1.default.logWarning(`vpc.subnetIds' are specified for the function '${funcName}' ` +
|
|
119
115
|
"and overrides 'vpcDiscovery.subnets' discovery config.");
|
|
120
116
|
}
|
|
121
117
|
// log warning in case vpc.securityGroupIds and vpcDiscovery.securityGroupNames are specified.
|
|
122
118
|
if (func.vpc.securityGroupIds && func.vpcDiscovery && func.vpcDiscovery.securityGroups) {
|
|
123
|
-
|
|
119
|
+
logging_1.default.logWarning(`vpc.securityGroupIds' are specified for the function '${funcName}' ` +
|
|
124
120
|
"and overrides 'vpcDiscovery.securityGroups' discovery config.");
|
|
125
121
|
}
|
|
126
122
|
// set vpc.subnetIds if it does not exists
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const globals_1 = __importDefault(require("./globals"));
|
|
7
|
+
class Logging {
|
|
8
|
+
static cliLog(prefix, message) {
|
|
9
|
+
globals_1.default.serverless.cli.log(`${prefix} ${message}`, globals_1.default.pluginName);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Logs error message
|
|
13
|
+
*/
|
|
14
|
+
static logError(message) {
|
|
15
|
+
if (globals_1.default.v3Utils) {
|
|
16
|
+
globals_1.default.v3Utils.log.error(message);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
Logging.cliLog("[Error]", message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Logs info message
|
|
24
|
+
*/
|
|
25
|
+
static logInfo(message) {
|
|
26
|
+
if (globals_1.default.v3Utils) {
|
|
27
|
+
globals_1.default.v3Utils.log.verbose(message);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
Logging.cliLog("[Info]", message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Logs warning message
|
|
35
|
+
*/
|
|
36
|
+
static logWarning(message) {
|
|
37
|
+
if (globals_1.default.v3Utils) {
|
|
38
|
+
globals_1.default.v3Utils.log.warning(message);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
Logging.cliLog("[WARNING]", message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = Logging;
|