@sudoplatform/sudo-common 7.1.3 → 8.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/bin/outdated-with-suppression.sh +203 -0
- package/bin/suppress-audit.sh +15 -0
- package/bin/suppress-outdated.sh +60 -0
- package/bin/yarn-audit-with-suppression.sh +19 -0
- package/cjs/configurationManager/defaultConfigurationManager.d.ts +123 -0
- package/cjs/configurationManager/defaultConfigurationManager.js +122 -0
- package/cjs/configurationManager/defaultConfigurationManager.js.map +1 -0
- package/cjs/errors/error.d.ts +263 -0
- package/cjs/errors/error.js +442 -0
- package/cjs/errors/error.js.map +1 -0
- package/cjs/index.d.ts +9 -0
- package/cjs/index.js +13 -0
- package/cjs/index.js.map +1 -0
- package/cjs/logging/bunyanLogger.d.ts +8 -0
- package/cjs/logging/bunyanLogger.js +36 -0
- package/cjs/logging/bunyanLogger.js.map +1 -0
- package/cjs/logging/logger.d.ts +87 -0
- package/cjs/logging/logger.js +77 -0
- package/cjs/logging/logger.js.map +1 -0
- package/cjs/sudoKeyArchive/index.d.ts +4 -0
- package/cjs/sudoKeyArchive/index.js +8 -0
- package/cjs/sudoKeyArchive/index.js.map +1 -0
- package/cjs/sudoKeyArchive/keyArchive.d.ts +137 -0
- package/cjs/sudoKeyArchive/keyArchive.js +84 -0
- package/cjs/sudoKeyArchive/keyArchive.js.map +1 -0
- package/cjs/sudoKeyArchive/keyInfo.d.ts +41 -0
- package/cjs/sudoKeyArchive/keyInfo.js +17 -0
- package/cjs/sudoKeyArchive/keyInfo.js.map +1 -0
- package/cjs/sudoKeyArchive/keyType.d.ts +13 -0
- package/cjs/sudoKeyArchive/keyType.js +39 -0
- package/cjs/sudoKeyArchive/keyType.js.map +1 -0
- package/cjs/sudoKeyArchive/sudoKeyArchive.d.ts +190 -0
- package/cjs/sudoKeyArchive/sudoKeyArchive.js +373 -0
- package/cjs/sudoKeyArchive/sudoKeyArchive.js.map +1 -0
- package/cjs/sudoKeyManager/index.d.ts +4 -0
- package/cjs/sudoKeyManager/index.js +8 -0
- package/cjs/sudoKeyManager/index.js.map +1 -0
- package/cjs/sudoKeyManager/keyData.d.ts +56 -0
- package/cjs/sudoKeyManager/keyData.js +46 -0
- package/cjs/sudoKeyManager/keyData.js.map +1 -0
- package/cjs/sudoKeyManager/publicKey.d.ts +8 -0
- package/cjs/sudoKeyManager/publicKey.js +9 -0
- package/cjs/sudoKeyManager/publicKey.js.map +1 -0
- package/cjs/sudoKeyManager/sudoCryptoProvider.d.ts +324 -0
- package/cjs/sudoKeyManager/sudoCryptoProvider.js +12 -0
- package/cjs/sudoKeyManager/sudoCryptoProvider.js.map +1 -0
- package/cjs/sudoKeyManager/sudoKeyManager.d.ts +344 -0
- package/cjs/sudoKeyManager/sudoKeyManager.js +140 -0
- package/cjs/sudoKeyManager/sudoKeyManager.js.map +1 -0
- package/cjs/types/types.d.ts +115 -0
- package/cjs/types/types.js +45 -0
- package/cjs/types/types.js.map +1 -0
- package/cjs/utils/base64.d.ts +44 -0
- package/cjs/utils/base64.js +71 -0
- package/cjs/utils/base64.js.map +1 -0
- package/cjs/utils/buffer.d.ts +13 -0
- package/cjs/utils/buffer.js +37 -0
- package/cjs/utils/buffer.js.map +1 -0
- package/cjs/utils/stream.d.ts +6 -0
- package/cjs/utils/stream.js +70 -0
- package/cjs/utils/stream.js.map +1 -0
- package/lib/configurationManager/defaultConfigurationManager.js +106 -156
- package/lib/configurationManager/defaultConfigurationManager.js.map +1 -0
- package/lib/errors/error.js +226 -438
- package/lib/errors/error.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +10 -109
- package/lib/index.js.map +1 -0
- package/lib/logging/bunyanLogger.js +29 -41
- package/lib/logging/bunyanLogger.js.map +1 -0
- package/lib/logging/logger.js +66 -92
- package/lib/logging/logger.js.map +1 -0
- package/lib/sudoKeyArchive/index.js +5 -57
- package/lib/sudoKeyArchive/index.js.map +1 -0
- package/lib/sudoKeyArchive/keyArchive.d.ts +8 -8
- package/lib/sudoKeyArchive/keyArchive.js +69 -96
- package/lib/sudoKeyArchive/keyArchive.js.map +1 -0
- package/lib/sudoKeyArchive/keyInfo.js +11 -49
- package/lib/sudoKeyArchive/keyInfo.js.map +1 -0
- package/lib/sudoKeyArchive/keyType.js +27 -37
- package/lib/sudoKeyArchive/keyType.js.map +1 -0
- package/lib/sudoKeyArchive/sudoKeyArchive.js +351 -444
- package/lib/sudoKeyArchive/sudoKeyArchive.js.map +1 -0
- package/lib/sudoKeyManager/index.js +5 -57
- package/lib/sudoKeyManager/index.js.map +1 -0
- package/lib/sudoKeyManager/keyData.js +38 -33
- package/lib/sudoKeyManager/keyData.js.map +1 -0
- package/lib/sudoKeyManager/publicKey.js +5 -12
- package/lib/sudoKeyManager/publicKey.js.map +1 -0
- package/lib/sudoKeyManager/sudoCryptoProvider.js +8 -26
- package/lib/sudoKeyManager/sudoCryptoProvider.js.map +1 -0
- package/lib/sudoKeyManager/sudoKeyManager.js +135 -173
- package/lib/sudoKeyManager/sudoKeyManager.js.map +1 -0
- package/lib/types/types.js +27 -33
- package/lib/types/types.js.map +1 -0
- package/lib/utils/base64.js +63 -93
- package/lib/utils/base64.js.map +1 -0
- package/lib/utils/buffer.js +28 -46
- package/lib/utils/buffer.js.map +1 -0
- package/lib/utils/stream.d.ts +6 -0
- package/lib/utils/stream.js +63 -0
- package/lib/utils/stream.js.map +1 -0
- package/package.json +35 -27
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
d="$(dirname "$0")"
|
|
5
|
+
|
|
6
|
+
version_diff_type() {
|
|
7
|
+
v1="$1"
|
|
8
|
+
v2="$2"
|
|
9
|
+
v1_major=$(echo "$v1" | sed -E -e 's/^([^.]+)\..*/\1/')
|
|
10
|
+
v2_major=$(echo "$v2" | sed -E -e 's/^([^.]+)\..*/\1/')
|
|
11
|
+
v1_minor=$(echo "$v1" | sed -E -e 's/^([^.]+)\.([^.]+)\..*/\2/')
|
|
12
|
+
v2_minor=$(echo "$v2" | sed -E -e 's/^([^.]+)\.([^.]+)\..*/\2/')
|
|
13
|
+
if [ "${v1_major}" != "${v2_major}" ]; then echo 'major'; return 0; fi
|
|
14
|
+
if [ "${v1_minor}" != "${v2_minor}" ]; then echo 'minor'; return 0; fi
|
|
15
|
+
if [ "${v1}" != "${v2}" ]; then echo 'patch'; return 0; fi
|
|
16
|
+
echo 'equal'
|
|
17
|
+
return 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
suppression_from_diff_type() {
|
|
21
|
+
diff_type="$1"
|
|
22
|
+
majorSuppression="$2"
|
|
23
|
+
minorSuppression="$3"
|
|
24
|
+
patchSuppression="$4"
|
|
25
|
+
|
|
26
|
+
case "${diff_type}" in
|
|
27
|
+
major)
|
|
28
|
+
if [ -n "${majorSuppression}" ]; then
|
|
29
|
+
echo "major ${majorSuppression}"
|
|
30
|
+
elif [ -n "${minorSuppression}" ]; then
|
|
31
|
+
echo "minor ${minorSuppression}"
|
|
32
|
+
elif [ -n "${patchSuppression}" ]; then
|
|
33
|
+
echo "patch ${patchSuppression}"
|
|
34
|
+
fi
|
|
35
|
+
;;
|
|
36
|
+
minor)
|
|
37
|
+
if [ -n "${minorSuppression}" ]; then
|
|
38
|
+
echo "minor ${minorSuppression}"
|
|
39
|
+
elif [ -n "${patchSuppression}" ]; then
|
|
40
|
+
echo "patch ${patchSuppression}"
|
|
41
|
+
fi
|
|
42
|
+
;;
|
|
43
|
+
patch)
|
|
44
|
+
if [ -n "${patchSuppression}" ]; then
|
|
45
|
+
echo "patch ${patchSuppression}"
|
|
46
|
+
fi
|
|
47
|
+
;;
|
|
48
|
+
esac
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Number of days to suppress if accepting or refreshing and cadence to run if --last specified
|
|
52
|
+
cadence=30
|
|
53
|
+
|
|
54
|
+
# If set, accept any outdated packages. Has the effect of refreshing existing suppressions
|
|
55
|
+
# as well.
|
|
56
|
+
accept=""
|
|
57
|
+
|
|
58
|
+
# If set, refresh any existing suppressions
|
|
59
|
+
refresh=""
|
|
60
|
+
|
|
61
|
+
# If set, records/references last success in the specified directory.
|
|
62
|
+
# Only run the dependency check every cadence days if a last success
|
|
63
|
+
# timestamp is found
|
|
64
|
+
last=""
|
|
65
|
+
|
|
66
|
+
while [ -n "${1}" ]; do
|
|
67
|
+
case "${1}" in
|
|
68
|
+
--cadence)
|
|
69
|
+
if [ -z "$2" ]; then
|
|
70
|
+
echo "ERROR: --cadence requires number of days argument" 1>&2
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
shift
|
|
74
|
+
cadence="$1"
|
|
75
|
+
;;
|
|
76
|
+
--accept) accept="1" ;;
|
|
77
|
+
--refresh) refresh="1" ;;
|
|
78
|
+
--last)
|
|
79
|
+
if [ -z "$2" ]; then
|
|
80
|
+
echo "ERROR: --last requires directory argument in which last successful run timestamp is to be store" 1>&2
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
shift
|
|
84
|
+
last="$1"
|
|
85
|
+
;;
|
|
86
|
+
*)
|
|
87
|
+
echo "ERROR: Unrecognized argument '${1}'" 1>&2
|
|
88
|
+
exit 1
|
|
89
|
+
esac
|
|
90
|
+
shift
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
dateFromSeconds() {
|
|
94
|
+
s="$1"
|
|
95
|
+
case $(uname) in
|
|
96
|
+
Darwin)
|
|
97
|
+
date -Iseconds -r"${s}"
|
|
98
|
+
;;
|
|
99
|
+
*)
|
|
100
|
+
date -Iseconds "-d@${s}"
|
|
101
|
+
;;
|
|
102
|
+
esac
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
within_cadence=""
|
|
106
|
+
if [ -r "${last}/last_success" ]; then
|
|
107
|
+
cadence_seconds=$((cadence * 24 * 3600))
|
|
108
|
+
now="$(date +%s)"
|
|
109
|
+
last_run="$(cat "${last}/last_success")"
|
|
110
|
+
due="$((last_run + cadence_seconds))"
|
|
111
|
+
if [ "$((due > now))" = "1" ]; then
|
|
112
|
+
echo "Last success: $(dateFromSeconds "${last_run}")"
|
|
113
|
+
echo "Now: $(date -Iseconds)"
|
|
114
|
+
echo "Due from: $(dateFromSeconds "${due}")"
|
|
115
|
+
within_cadence="1"
|
|
116
|
+
else
|
|
117
|
+
echo "Last success: $(dateFromSeconds "${last_run}")"
|
|
118
|
+
echo "Now: $(date -Iseconds)"
|
|
119
|
+
echo "Due since: $(dateFromSeconds "${due}")"
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
yarn outdated --json | jq -r -s -c 'map(select(.type == "table").data.body) | .[] | unique_by(.[0]) | .[] | .[0] + " " + .[1] + " " + .[2] + " " + .[3]' | (new=""; while read -r package_name current wanted latest; do
|
|
125
|
+
majorSuppression=$(jq ".outdatedSuppressions.major[\"${package_name}\"] | select (. != null)" package.json)
|
|
126
|
+
minorSuppression=$(jq ".outdatedSuppressions.minor[\"${package_name}\"] | select (. != null)" package.json)
|
|
127
|
+
patchSuppression=$(jq ".outdatedSuppressions[\"${package_name}\"] | select (. != null)" package.json)
|
|
128
|
+
latest_diff_type=$(version_diff_type "${current}" "${latest}")
|
|
129
|
+
wanted_diff_type=$(version_diff_type "${current}" "${wanted}")
|
|
130
|
+
|
|
131
|
+
# shellcheck disable=SC2046
|
|
132
|
+
set -- $(suppression_from_diff_type "${latest_diff_type}" "${majorSuppression}" "${minorSuppression}" "${patchSuppression}")
|
|
133
|
+
latest_suppression_type="$1"
|
|
134
|
+
latest_suppression="$2"
|
|
135
|
+
|
|
136
|
+
# shellcheck disable=SC2046
|
|
137
|
+
set -- $(suppression_from_diff_type "${wanted_diff_type}" "${majorSuppression}" "${minorSuppression}" "${patchSuppression}")
|
|
138
|
+
wanted_suppression_type="$1"
|
|
139
|
+
wanted_suppression="$2"
|
|
140
|
+
|
|
141
|
+
# If package has major update but isn't suppre
|
|
142
|
+
suppression=""
|
|
143
|
+
suppression_type=""
|
|
144
|
+
outdated_diff_type="${latest_diff_type}"
|
|
145
|
+
if [ -n "${latest_suppression_type}" ]; then
|
|
146
|
+
if [ "${wanted_diff_type}" != "equal" ]; then
|
|
147
|
+
outdated_diff_type="${wanted_diff_type}"
|
|
148
|
+
if [ -n "${wanted_suppression_type}" ]; then
|
|
149
|
+
suppression_type="${wanted_suppression_type}"
|
|
150
|
+
suppression="${wanted_suppression}"
|
|
151
|
+
else
|
|
152
|
+
# Only suppressed at major level and we have minor or patch
|
|
153
|
+
# updates available - do not suppress
|
|
154
|
+
:
|
|
155
|
+
fi
|
|
156
|
+
else
|
|
157
|
+
suppression_type="${latest_suppression_type}"
|
|
158
|
+
suppression="${latest_suppression}"
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
suppress_outdated=""
|
|
163
|
+
if [ -e "${d}/suppress-outdated" ]; then
|
|
164
|
+
suppress_outdated="${d}/suppress-outdated"
|
|
165
|
+
elif [ -e "${d}/suppress-outdated.sh" ]; then
|
|
166
|
+
suppress_outdated="${d}/suppress-outdated.sh"
|
|
167
|
+
fi
|
|
168
|
+
if [ -z "${suppress_outdated}" ]; then
|
|
169
|
+
echo "ERROR: Unable to find suppress-outdated" 1>&2
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
if [ -z "${suppression}" ]; then
|
|
173
|
+
if [ -n "${accept}" ]; then
|
|
174
|
+
echo "${package_name}: current: ${current} wanted: ${wanted} latest: ${latest} [${latest_diff_type} accepted]"
|
|
175
|
+
"${suppress_outdated}" --suppression "${cadence}" --"${latest_diff_type}" "${package_name}"
|
|
176
|
+
else
|
|
177
|
+
echo "${package_name}: current: ${current} wanted: ${wanted} latest: ${latest} [${outdated_diff_type} outdated]"
|
|
178
|
+
new=1
|
|
179
|
+
fi
|
|
180
|
+
elif [ -n "${accept}${refresh}" ]; then
|
|
181
|
+
echo "${package_name}: current: ${current} wanted: ${wanted} latest: ${latest} [${suppression_type} suppression refreshed]"
|
|
182
|
+
"${suppress_outdated}" --suppression "${cadence}" --"${suppression_type}" "${package_name}"
|
|
183
|
+
elif [ "$(date '+%s')" -gt "${suppression}" ]; then
|
|
184
|
+
echo "${package_name}: current: ${current} wanted: ${wanted} latest: ${latest} [${outdated_diff_type} suppression expired]"
|
|
185
|
+
new=1
|
|
186
|
+
else
|
|
187
|
+
echo "${package_name}: current: ${current} wanted: ${wanted} latest: ${latest} [${outdated_diff_type} suppressed]"
|
|
188
|
+
fi
|
|
189
|
+
done
|
|
190
|
+
|
|
191
|
+
# If we're not within cadence and there are new outdated dependencies
|
|
192
|
+
# then fail
|
|
193
|
+
if [ -z "${within_cadence}" -a -n "${new}" ]; then
|
|
194
|
+
exit 1
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# If there a no outdated dependencies and we're tracking last success then
|
|
198
|
+
# refresh the last success timestamp.
|
|
199
|
+
if [ -z "${new}" -a -n "${last}" ]; then
|
|
200
|
+
mkdir -p "${last}"
|
|
201
|
+
date +%s > "${last}/last_success"
|
|
202
|
+
fi
|
|
203
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# Insert a audit identifier to suppress in verification proccess.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
auditid=$1
|
|
7
|
+
PACKAGE_JSON="package.json"
|
|
8
|
+
|
|
9
|
+
if [ -z $auditid ]; then
|
|
10
|
+
echo "Usage: yarn suppress-audit <audit id>"
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
cp $PACKAGE_JSON $PACKAGE_JSON.old
|
|
14
|
+
cat $PACKAGE_JSON | jq ".auditSuppressions.\"$auditid\" = (now | floor | . + 1209600)" > $PACKAGE_JSON.staging
|
|
15
|
+
mv $PACKAGE_JSON.staging $PACKAGE_JSON
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# Insert a package name to suppress in outdated checks.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
usage() {
|
|
9
|
+
echo "Usage: suppress-outdated.sh [--suppression <number-of-days>] {--major|--minor|--patch} <package name> ..."
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
suppression=30
|
|
13
|
+
if [ "$1" = "--suppression" ]; then
|
|
14
|
+
if [ -z "$2" ]; then
|
|
15
|
+
echo "ERROR: --suppression argument must specify a number of days argument" 1>&2
|
|
16
|
+
usage 1>&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
shift
|
|
20
|
+
suppression="$1"
|
|
21
|
+
shift
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
case "$1" in
|
|
25
|
+
--major)
|
|
26
|
+
root=".outdatedSuppressions.major"
|
|
27
|
+
;;
|
|
28
|
+
--minor)
|
|
29
|
+
root=".outdatedSuppressions.minor"
|
|
30
|
+
;;
|
|
31
|
+
--patch)
|
|
32
|
+
root=".outdatedSuppressions"
|
|
33
|
+
;;
|
|
34
|
+
*)
|
|
35
|
+
echo "suppress-outdated.sh: Unrecognized option: '$1'" 1>&2
|
|
36
|
+
usage 1>&2
|
|
37
|
+
exit 1
|
|
38
|
+
;;
|
|
39
|
+
esac
|
|
40
|
+
shift
|
|
41
|
+
|
|
42
|
+
if [ -z "$1" ]; then
|
|
43
|
+
echo "suppress-outdated.sh: No package names specified" 1>&2
|
|
44
|
+
usage 1>&2
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
suppression_seconds=$((suppression * 24 * 3600))
|
|
49
|
+
|
|
50
|
+
PACKAGE_JSON="package.json"
|
|
51
|
+
cp "$PACKAGE_JSON" "$PACKAGE_JSON.old"
|
|
52
|
+
|
|
53
|
+
while [ -n "$1" ]; do
|
|
54
|
+
package_name="$1"
|
|
55
|
+
|
|
56
|
+
jq < "$PACKAGE_JSON" "${root}.\"${package_name}\" = (now | floor | . + ${suppression_seconds})" > "$PACKAGE_JSON.staging"
|
|
57
|
+
mv "$PACKAGE_JSON.staging" "$PACKAGE_JSON"
|
|
58
|
+
|
|
59
|
+
shift
|
|
60
|
+
done
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
yarn audit --json --groups "dependencies devDependencies" | jq -s -c 'map(select(.type == "auditAdvisory").data.advisory) | unique_by(.id) | .[] | {id, title, module_name, vulnerable_versions, patched_versions, severity, findings}' | (new=""; while read advisory ; do
|
|
4
|
+
id=$(echo "${advisory}" | jq '.id')
|
|
5
|
+
suppression=$(jq ".auditSuppressions[\"$id\"] | select (. != null)" package.json)
|
|
6
|
+
if [ -z "$suppression" ]; then
|
|
7
|
+
echo "New advisory ${id}:"
|
|
8
|
+
echo "${advisory}" | jq .
|
|
9
|
+
new=1
|
|
10
|
+
elif [ $(date '+%s') -gt "$suppression" ]; then
|
|
11
|
+
echo "Suppression for advisory ${id} has expired. Please revisit:"
|
|
12
|
+
echo "${advisory}" | jq .
|
|
13
|
+
new=1
|
|
14
|
+
fi
|
|
15
|
+
done
|
|
16
|
+
if [ -n "${new}" ]; then
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as t from 'io-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Service compatibility information.
|
|
4
|
+
*/
|
|
5
|
+
export interface ServiceCompatibilityInfo {
|
|
6
|
+
/**
|
|
7
|
+
* The name of the service associated with the compatibility info. This matches one of the
|
|
8
|
+
* service name present in sudoplatformconfig.json.
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
/**
|
|
12
|
+
* The version of the service config present in sudoplatformconfig.json. It defaults
|
|
13
|
+
* to 1 if not present.
|
|
14
|
+
*/
|
|
15
|
+
configVersion: number;
|
|
16
|
+
/**
|
|
17
|
+
* The minimum supported service config version currently supported by the backend.
|
|
18
|
+
*/
|
|
19
|
+
minSupportedVersion?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Any service config version less than or equal to this version is considered deprecated
|
|
22
|
+
* and the backend may remove the support for those versions after a grace period.
|
|
23
|
+
*/
|
|
24
|
+
deprecatedVersion?: number;
|
|
25
|
+
/**
|
|
26
|
+
* After this time any deprecated service config versions will no longer be compatible
|
|
27
|
+
* with the backend. It is recommended to warn the user prior to the deprecation grace.
|
|
28
|
+
*/
|
|
29
|
+
deprecationGrace?: Date;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Result returned by `validateConfig` API if an incompatible client config is found when compared
|
|
33
|
+
* to the deployed backend services.
|
|
34
|
+
*/
|
|
35
|
+
export interface ValidationResult {
|
|
36
|
+
/**
|
|
37
|
+
* The list of incompatible services. The client must be upgraded to the latest
|
|
38
|
+
* version in order to use these services.
|
|
39
|
+
*/
|
|
40
|
+
incompatible: ServiceCompatibilityInfo[];
|
|
41
|
+
/**
|
|
42
|
+
* The list of services that will be made incompatible with the current version of the
|
|
43
|
+
* client. The users should be warned that after the specified grace period these services will be
|
|
44
|
+
* made incompatible.
|
|
45
|
+
*/
|
|
46
|
+
deprecated: ServiceCompatibilityInfo[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Interface that encapsulates the APIs common to all configuration manager implementations.
|
|
50
|
+
* A configuration manager should be a singleton that holds reference to a parsed config
|
|
51
|
+
* and returns the configuration set specific to a given namespace.
|
|
52
|
+
*/
|
|
53
|
+
export interface ConfigurationManager {
|
|
54
|
+
/**
|
|
55
|
+
* Set config that will be parsed as JSON
|
|
56
|
+
*
|
|
57
|
+
* @param config A string representation of configuration
|
|
58
|
+
*
|
|
59
|
+
* @returns ConfigurationManager
|
|
60
|
+
*/
|
|
61
|
+
setConfig(config: string): ConfigurationManager;
|
|
62
|
+
/**
|
|
63
|
+
* Get a subset of configuration by namespace
|
|
64
|
+
*
|
|
65
|
+
* @param namespace The key for the nested json object
|
|
66
|
+
*
|
|
67
|
+
* @returns Configuration set specific to a given namespace
|
|
68
|
+
*
|
|
69
|
+
* @throws {@link ConfigurationNotSetError}
|
|
70
|
+
*/
|
|
71
|
+
getConfigSet(namespace?: string): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Decode a configuration set to a given type
|
|
74
|
+
*
|
|
75
|
+
* @param configSet Configuration set specific to a given namespace
|
|
76
|
+
* @param codec The codec to bind the configuration set to
|
|
77
|
+
*
|
|
78
|
+
* @returns Configuration as a given type
|
|
79
|
+
*
|
|
80
|
+
* @throws {@link DecodeError}
|
|
81
|
+
*/
|
|
82
|
+
bind<T>(configSet: unknown, codec: t.Mixed): T;
|
|
83
|
+
/**
|
|
84
|
+
* Get a configuration by namespace and decode and validate
|
|
85
|
+
* that configuration set to a given type. If no namespace
|
|
86
|
+
* provided, try and use the whole configuration object
|
|
87
|
+
* to bind to the given type.
|
|
88
|
+
*
|
|
89
|
+
* @param namespace The key for the nested json object or undefined
|
|
90
|
+
* @param codec The codec to bind the configuration set to
|
|
91
|
+
*
|
|
92
|
+
* @returns Configuration as a given type
|
|
93
|
+
*
|
|
94
|
+
* @throws {@link ConfigurationNotSetError}
|
|
95
|
+
* @throws {@link ConfigurationSetNotFoundError}
|
|
96
|
+
* @throws {@link DecodeError}
|
|
97
|
+
*/
|
|
98
|
+
bindConfigSet<T>(codec: t.Mixed, namespace?: string): T;
|
|
99
|
+
/**
|
|
100
|
+
* Validates the client configuration (sudoplatformconfig.json) against the currently deployed set of
|
|
101
|
+
* backend services. If the client configuration is valid, i.e. the client is compatible will all deployed
|
|
102
|
+
* backend services, then the call will complete with `success` result. If any part of the client
|
|
103
|
+
* configuration is incompatible then a detailed information on the incompatible service will be
|
|
104
|
+
* returned in `failure` result. See `SudoConfigManagerError.compatibilityIssueFound` for more details.
|
|
105
|
+
*
|
|
106
|
+
* @return validation result with the details of incompatible or deprecated service configurations.
|
|
107
|
+
*/
|
|
108
|
+
validateConfig(): Promise<ValidationResult>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Singleton to manage configuration
|
|
112
|
+
*/
|
|
113
|
+
export declare class DefaultConfigurationManager implements ConfigurationManager {
|
|
114
|
+
private static instance;
|
|
115
|
+
private _config;
|
|
116
|
+
private constructor();
|
|
117
|
+
static getInstance(): DefaultConfigurationManager;
|
|
118
|
+
setConfig(config: string): DefaultConfigurationManager;
|
|
119
|
+
getConfigSet(namespace?: string): string;
|
|
120
|
+
bind<T>(configSet: unknown, codec: t.Mixed): T;
|
|
121
|
+
bindConfigSet<T>(codec: t.Mixed, namespace?: string): T;
|
|
122
|
+
validateConfig(): Promise<ValidationResult>;
|
|
123
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultConfigurationManager = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
8
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
9
|
+
const Either_1 = require("fp-ts/lib/Either");
|
|
10
|
+
const pipeable_1 = require("fp-ts/lib/pipeable");
|
|
11
|
+
const PathReporter_1 = require("io-ts/lib/PathReporter");
|
|
12
|
+
const error_1 = require("../errors/error");
|
|
13
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
14
|
+
const stream_1 = require("../utils/stream");
|
|
15
|
+
/**
|
|
16
|
+
* Singleton to manage configuration
|
|
17
|
+
*/
|
|
18
|
+
class DefaultConfigurationManager {
|
|
19
|
+
constructor() {
|
|
20
|
+
// Do Nothing.
|
|
21
|
+
}
|
|
22
|
+
static getInstance() {
|
|
23
|
+
if (!DefaultConfigurationManager.instance) {
|
|
24
|
+
DefaultConfigurationManager.instance = new DefaultConfigurationManager();
|
|
25
|
+
}
|
|
26
|
+
return DefaultConfigurationManager.instance;
|
|
27
|
+
}
|
|
28
|
+
setConfig(config) {
|
|
29
|
+
this._config = config;
|
|
30
|
+
return DefaultConfigurationManager.instance;
|
|
31
|
+
}
|
|
32
|
+
getConfigSet(namespace) {
|
|
33
|
+
if (!this._config) {
|
|
34
|
+
throw new error_1.ConfigurationNotSetError();
|
|
35
|
+
}
|
|
36
|
+
const parsed = JSON.parse(this._config);
|
|
37
|
+
const configSet = namespace ? parsed[namespace] : parsed;
|
|
38
|
+
return configSet;
|
|
39
|
+
}
|
|
40
|
+
bind(configSet, codec) {
|
|
41
|
+
// Decode and validate config
|
|
42
|
+
return (0, pipeable_1.pipe)(codec.decode(configSet), (0, Either_1.fold)((errors) => {
|
|
43
|
+
throw new error_1.DecodeError(PathReporter_1.PathReporter.report((0, Either_1.left)(errors)).join('\n'));
|
|
44
|
+
}, (v) => v));
|
|
45
|
+
}
|
|
46
|
+
bindConfigSet(codec, namespace) {
|
|
47
|
+
const configSet = this.getConfigSet(namespace);
|
|
48
|
+
if (!configSet) {
|
|
49
|
+
throw new error_1.ConfigurationSetNotFoundError(namespace);
|
|
50
|
+
}
|
|
51
|
+
return this.bind(configSet, codec);
|
|
52
|
+
}
|
|
53
|
+
async validateConfig() {
|
|
54
|
+
if (!this._config) {
|
|
55
|
+
return { incompatible: [], deprecated: [] };
|
|
56
|
+
}
|
|
57
|
+
const config = JSON.parse(this._config);
|
|
58
|
+
const region = config.identityService?.region;
|
|
59
|
+
const bucket = config.identityService?.serviceInfoBucket;
|
|
60
|
+
if (!(region && bucket)) {
|
|
61
|
+
return { incompatible: [], deprecated: [] };
|
|
62
|
+
}
|
|
63
|
+
const s3Client = new client_s3_1.S3Client({
|
|
64
|
+
region: region,
|
|
65
|
+
// We want these request to be unauthenticated
|
|
66
|
+
// so we provide a no-op signer for the requests
|
|
67
|
+
signer: { sign: (request) => Promise.resolve(request) },
|
|
68
|
+
});
|
|
69
|
+
const incompatible = [];
|
|
70
|
+
const deprecated = [];
|
|
71
|
+
const listObjectsCommand = new client_s3_1.ListObjectsCommand({
|
|
72
|
+
Bucket: bucket,
|
|
73
|
+
});
|
|
74
|
+
const objects = await s3Client.send(listObjectsCommand);
|
|
75
|
+
if (!objects.Contents?.length) {
|
|
76
|
+
return { incompatible: [], deprecated: [] };
|
|
77
|
+
}
|
|
78
|
+
const keys = objects.Contents.map((object) => object.Key);
|
|
79
|
+
// Only fetch the service info docs for the services that are present in client config
|
|
80
|
+
// to minimize the network calls.
|
|
81
|
+
const keysToFetch = keys.filter((key) => key.endsWith('.json') && config[key.replace('.json', '')]);
|
|
82
|
+
for (const key of keysToFetch) {
|
|
83
|
+
const getObject = new client_s3_1.GetObjectCommand({
|
|
84
|
+
Key: key,
|
|
85
|
+
Bucket: bucket,
|
|
86
|
+
});
|
|
87
|
+
const object = await s3Client.send(getObject);
|
|
88
|
+
if (!object.Body) {
|
|
89
|
+
throw new error_1.FatalError('No S3 object body');
|
|
90
|
+
}
|
|
91
|
+
const body = await (0, stream_1.bodyToString)(object.Body);
|
|
92
|
+
const json = JSON.parse(body);
|
|
93
|
+
const serviceName = key.replace('.json', '');
|
|
94
|
+
const serviceInfo = json[serviceName];
|
|
95
|
+
const serviceConfig = config[serviceName];
|
|
96
|
+
if (serviceInfo && serviceConfig) {
|
|
97
|
+
const currentVersion = serviceConfig.version ?? 1;
|
|
98
|
+
const deprecationGrace = serviceInfo.deprecationGrace ?? -1;
|
|
99
|
+
const compatibilityInfo = {
|
|
100
|
+
name: serviceName,
|
|
101
|
+
configVersion: currentVersion,
|
|
102
|
+
minSupportedVersion: serviceInfo.minVersion,
|
|
103
|
+
deprecatedVersion: serviceInfo.deprecated,
|
|
104
|
+
deprecationGrace: deprecationGrace != -1 ? new Date(deprecationGrace) : undefined,
|
|
105
|
+
};
|
|
106
|
+
// If the service config in `sudoplatformconfig.json` is less than the
|
|
107
|
+
// minimum supported version then the client is incompatible.
|
|
108
|
+
if (currentVersion < (compatibilityInfo.minSupportedVersion ?? 0)) {
|
|
109
|
+
incompatible.push(compatibilityInfo);
|
|
110
|
+
}
|
|
111
|
+
// If the service config is less than or equal to the deprecated version
|
|
112
|
+
// then it will be made incompatible after the deprecation grace.
|
|
113
|
+
if (currentVersion <= (compatibilityInfo.deprecatedVersion ?? 0)) {
|
|
114
|
+
deprecated.push(compatibilityInfo);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { incompatible, deprecated };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.DefaultConfigurationManager = DefaultConfigurationManager;
|
|
122
|
+
//# sourceMappingURL=defaultConfigurationManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultConfigurationManager.js","sourceRoot":"","sources":["../../src/configurationManager/defaultConfigurationManager.ts"],"names":[],"mappings":"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"}
|