@lowdefy/plugin-aws 0.0.0-experimental-20261007090522 → 0.0.0-experimental-20261007124348
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/dist/connections/AwsS3Bucket/AwsS3PutObject/copyFromUrl.js +7 -2
- package/package.json +10 -9
- package/dist/connections/AwsS3Bucket/AwsS3PutObject/connectPublic.js +0 -39
- package/dist/connections/AwsS3Bucket/AwsS3PutObject/isPublicAddress.js +0 -106
- package/dist/connections/AwsS3Bucket/AwsS3PutObject/lookupPublicAddress.js +0 -40
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
*/ import { Readable } from 'node:stream';
|
|
16
16
|
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
|
17
17
|
import { type } from '@lowdefy/helpers';
|
|
18
|
+
import createConnectPublic from '@lowdefy/node-utils/createConnectPublic.js';
|
|
18
19
|
import { Agent, fetch } from 'undici';
|
|
19
|
-
import connectPublic from './connectPublic.js';
|
|
20
20
|
import createCopyError from './createCopyError.js';
|
|
21
21
|
import limitBody from './limitBody.js';
|
|
22
22
|
import matchesContentType from './matchesContentType.js';
|
|
@@ -36,7 +36,12 @@ const REDIRECT_STATUSES = new Set([
|
|
|
36
36
|
]);
|
|
37
37
|
const MAX_REDIRECTS = 20;
|
|
38
38
|
const dispatcher = new Agent({
|
|
39
|
-
connect:
|
|
39
|
+
connect: createConnectPublic({
|
|
40
|
+
createNotPublicError: ()=>createCopyError({
|
|
41
|
+
code: 'url_not_public',
|
|
42
|
+
message: 'AwsS3PutObject "url" leads to an address that is not public.'
|
|
43
|
+
})
|
|
44
|
+
})
|
|
40
45
|
});
|
|
41
46
|
function isHttps(link) {
|
|
42
47
|
return URL.parse(link)?.protocol === 'https:';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/plugin-aws",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-20261007124348",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -50,11 +50,12 @@
|
|
|
50
50
|
"dist/*"
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@lowdefy/block-utils": "0.0.0-experimental-
|
|
54
|
-
"@lowdefy/blocks-antd": "0.0.0-experimental-
|
|
55
|
-
"@lowdefy/blocks-files": "0.0.0-experimental-
|
|
56
|
-
"@lowdefy/errors": "0.0.0-experimental-
|
|
57
|
-
"@lowdefy/helpers": "0.0.0-experimental-
|
|
53
|
+
"@lowdefy/block-utils": "0.0.0-experimental-20261007124348",
|
|
54
|
+
"@lowdefy/blocks-antd": "0.0.0-experimental-20261007124348",
|
|
55
|
+
"@lowdefy/blocks-files": "0.0.0-experimental-20261007124348",
|
|
56
|
+
"@lowdefy/errors": "0.0.0-experimental-20261007124348",
|
|
57
|
+
"@lowdefy/helpers": "0.0.0-experimental-20261007124348",
|
|
58
|
+
"@lowdefy/node-utils": "0.0.0-experimental-20261007124348",
|
|
58
59
|
"@aws-sdk/client-s3": "3.1141.0",
|
|
59
60
|
"@aws-sdk/s3-presigned-post": "3.1141.0",
|
|
60
61
|
"@aws-sdk/s3-request-presigner": "3.1141.0",
|
|
@@ -67,9 +68,9 @@
|
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@jest/globals": "28.1.3",
|
|
70
|
-
"@lowdefy/ajv": "0.0.0-experimental-
|
|
71
|
-
"@lowdefy/block-dev": "0.0.0-experimental-
|
|
72
|
-
"@lowdefy/jest-yaml-transform": "0.0.0-experimental-
|
|
71
|
+
"@lowdefy/ajv": "0.0.0-experimental-20261007124348",
|
|
72
|
+
"@lowdefy/block-dev": "0.0.0-experimental-20261007124348",
|
|
73
|
+
"@lowdefy/jest-yaml-transform": "0.0.0-experimental-20261007124348",
|
|
73
74
|
"@swc/cli": "0.8.1",
|
|
74
75
|
"@swc/core": "1.15.32",
|
|
75
76
|
"@swc/jest": "0.2.39",
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { isIP } from 'node:net';
|
|
16
|
-
import { buildConnector } from 'undici';
|
|
17
|
-
import lookupPublicAddress from './lookupPublicAddress.js';
|
|
18
|
-
const connect = buildConnector({
|
|
19
|
-
lookup: lookupPublicAddress
|
|
20
|
-
});
|
|
21
|
-
// The undici connector for a url copy: it opens a socket only to a public address, for the first
|
|
22
|
-
// link and every redirect alike. A socket to an IP literal skips the lookup, so a literal is
|
|
23
|
-
// checked here before connecting.
|
|
24
|
-
function connectPublic(options, callback) {
|
|
25
|
-
if (isIP(options.hostname) === 0) {
|
|
26
|
-
connect(options, callback);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
lookupPublicAddress(options.hostname, {
|
|
30
|
-
all: true
|
|
31
|
-
}, (error)=>{
|
|
32
|
-
if (error) {
|
|
33
|
-
callback(error, null);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
connect(options, callback);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
export default connectPublic;
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { BlockList, isIPv6 } from 'node:net';
|
|
16
|
-
// Ranges a url copy may not reach: anything that is not a public unicast address. BlockList also
|
|
17
|
-
// matches an IPv4-mapped IPv6 address (::ffff:127.0.0.1) against the IPv4 ranges.
|
|
18
|
-
const notPublicIPv4 = [
|
|
19
|
-
[
|
|
20
|
-
'0.0.0.0',
|
|
21
|
-
8
|
|
22
|
-
],
|
|
23
|
-
[
|
|
24
|
-
'10.0.0.0',
|
|
25
|
-
8
|
|
26
|
-
],
|
|
27
|
-
[
|
|
28
|
-
'100.64.0.0',
|
|
29
|
-
10
|
|
30
|
-
],
|
|
31
|
-
[
|
|
32
|
-
'127.0.0.0',
|
|
33
|
-
8
|
|
34
|
-
],
|
|
35
|
-
[
|
|
36
|
-
'169.254.0.0',
|
|
37
|
-
16
|
|
38
|
-
],
|
|
39
|
-
[
|
|
40
|
-
'172.16.0.0',
|
|
41
|
-
12
|
|
42
|
-
],
|
|
43
|
-
[
|
|
44
|
-
'192.0.0.0',
|
|
45
|
-
24
|
|
46
|
-
],
|
|
47
|
-
[
|
|
48
|
-
'192.168.0.0',
|
|
49
|
-
16
|
|
50
|
-
],
|
|
51
|
-
[
|
|
52
|
-
'198.18.0.0',
|
|
53
|
-
15
|
|
54
|
-
],
|
|
55
|
-
[
|
|
56
|
-
'224.0.0.0',
|
|
57
|
-
4
|
|
58
|
-
],
|
|
59
|
-
[
|
|
60
|
-
'240.0.0.0',
|
|
61
|
-
4
|
|
62
|
-
]
|
|
63
|
-
];
|
|
64
|
-
// The 6to4 address (2002::/16) that carries an IPv4 network in its next 32 bits.
|
|
65
|
-
function sixToFourNetwork(network) {
|
|
66
|
-
const [a, b, c, d] = network.split('.').map(Number);
|
|
67
|
-
return `2002:${(a << 8 | b).toString(16)}:${(c << 8 | d).toString(16)}::`;
|
|
68
|
-
}
|
|
69
|
-
const notPublic = new BlockList();
|
|
70
|
-
notPublicIPv4.forEach(([network, prefix])=>{
|
|
71
|
-
notPublic.addSubnet(network, prefix, 'ipv4');
|
|
72
|
-
// An IPv6 address that embeds one of these IPv4 addresses: a NAT64 gateway (64:ff9b::/96)
|
|
73
|
-
// or a 6to4 relay forwards it to that IPv4 address.
|
|
74
|
-
notPublic.addSubnet(`64:ff9b::${network}`, 96 + prefix, 'ipv6');
|
|
75
|
-
notPublic.addSubnet(sixToFourNetwork(network), 16 + prefix, 'ipv6');
|
|
76
|
-
});
|
|
77
|
-
[
|
|
78
|
-
[
|
|
79
|
-
'::',
|
|
80
|
-
96
|
|
81
|
-
],
|
|
82
|
-
[
|
|
83
|
-
'64:ff9b:1::',
|
|
84
|
-
48
|
|
85
|
-
],
|
|
86
|
-
[
|
|
87
|
-
'fc00::',
|
|
88
|
-
7
|
|
89
|
-
],
|
|
90
|
-
[
|
|
91
|
-
'fe80::',
|
|
92
|
-
10
|
|
93
|
-
],
|
|
94
|
-
[
|
|
95
|
-
'fec0::',
|
|
96
|
-
10
|
|
97
|
-
],
|
|
98
|
-
[
|
|
99
|
-
'ff00::',
|
|
100
|
-
8
|
|
101
|
-
]
|
|
102
|
-
].forEach(([network, prefix])=>notPublic.addSubnet(network, prefix, 'ipv6'));
|
|
103
|
-
function isPublicAddress(address) {
|
|
104
|
-
return !notPublic.check(address, isIPv6(address) ? 'ipv6' : 'ipv4');
|
|
105
|
-
}
|
|
106
|
-
export default isPublicAddress;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/ import { lookup } from 'node:dns';
|
|
16
|
-
import createCopyError from './createCopyError.js';
|
|
17
|
-
import isPublicAddress from './isPublicAddress.js';
|
|
18
|
-
// A dns.lookup for the socket to use: the socket connects to the addresses this answers, so the
|
|
19
|
-
// address checked is the address connected to, and a name that resolves differently on a second
|
|
20
|
-
// lookup cannot get past the check. Refuses a name when any of its addresses is not public.
|
|
21
|
-
function lookupPublicAddress(hostname, options, callback) {
|
|
22
|
-
lookup(hostname, options, (error, address, family)=>{
|
|
23
|
-
if (error) {
|
|
24
|
-
callback(error);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
const addresses = Array.isArray(address) ? address.map((entry)=>entry.address) : [
|
|
28
|
-
address
|
|
29
|
-
];
|
|
30
|
-
if (!addresses.every(isPublicAddress)) {
|
|
31
|
-
callback(createCopyError({
|
|
32
|
-
code: 'url_not_public',
|
|
33
|
-
message: 'AwsS3PutObject "url" leads to an address that is not public.'
|
|
34
|
-
}));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
callback(null, address, family);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
export default lookupPublicAddress;
|