@sebspark/gcp-iam 0.3.1 → 0.4.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/README.md +7 -0
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +26 -19
- package/dist/index.mjs +23 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
# `@sebspark/gcp-iam`
|
|
2
2
|
|
|
3
3
|
Google IAM utilities. This package is intended to be run in GCP contexts, such as running under a GKE service account using Workload Identity.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Explanation
|
|
7
|
+
|
|
8
|
+
It generates the JWT that we put into the proxy-authorization header. That JWT is signed by the GCP service account and the aud part of the JWT is set to the URL we are going to call in the API Gateway.
|
|
9
|
+
|
|
10
|
+
Generating and signing the JWT uses a bunch of CPU cycles, so it makes sense to cache them for a short time.
|
package/dist/index.d.mts
CHANGED
|
@@ -8,6 +8,11 @@ import { Logger } from 'winston';
|
|
|
8
8
|
* @param logger An optional logger to use for logging.
|
|
9
9
|
* @returns A JWT.
|
|
10
10
|
*/
|
|
11
|
-
declare const getApiGatewayToken: (apiURL
|
|
11
|
+
declare const getApiGatewayToken: ({ apiURL, key, ttl, logger, }: {
|
|
12
|
+
apiURL: string;
|
|
13
|
+
key?: string;
|
|
14
|
+
ttl?: number;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
}) => Promise<string>;
|
|
12
17
|
|
|
13
18
|
export { getApiGatewayToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,11 @@ import { Logger } from 'winston';
|
|
|
8
8
|
* @param logger An optional logger to use for logging.
|
|
9
9
|
* @returns A JWT.
|
|
10
10
|
*/
|
|
11
|
-
declare const getApiGatewayToken: (apiURL
|
|
11
|
+
declare const getApiGatewayToken: ({ apiURL, key, ttl, logger, }: {
|
|
12
|
+
apiURL: string;
|
|
13
|
+
key?: string;
|
|
14
|
+
ttl?: number;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
}) => Promise<string>;
|
|
12
17
|
|
|
13
18
|
export { getApiGatewayToken };
|
package/dist/index.js
CHANGED
|
@@ -18,11 +18,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
23
|
getApiGatewayToken: () => getApiGatewayToken
|
|
24
24
|
});
|
|
25
|
-
module.exports = __toCommonJS(
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
27
|
// src/apiGatewayToken.ts
|
|
28
28
|
var import_iam_credentials = require("@google-cloud/iam-credentials");
|
|
@@ -32,17 +32,17 @@ var import_google_auth_library = require("google-auth-library");
|
|
|
32
32
|
var LruCache = class {
|
|
33
33
|
values = /* @__PURE__ */ new Map();
|
|
34
34
|
maxEntries = 1e4;
|
|
35
|
-
|
|
36
|
-
//
|
|
35
|
+
defaultTTL = 1e3 * 10;
|
|
36
|
+
// 10 seconds
|
|
37
37
|
constructor(props) {
|
|
38
|
-
this.
|
|
39
|
-
this.maxEntries =
|
|
38
|
+
this.defaultTTL = props?.ttl ?? this.defaultTTL;
|
|
39
|
+
this.maxEntries = props?.maxEntries ?? this.maxEntries;
|
|
40
40
|
}
|
|
41
41
|
get(key) {
|
|
42
42
|
const hasKey = this.values.has(key);
|
|
43
43
|
if (hasKey) {
|
|
44
44
|
const entry = this.values.get(key);
|
|
45
|
-
if (Date.now() - entry.timestamp >
|
|
45
|
+
if (Date.now() - entry.timestamp > entry.ttl) {
|
|
46
46
|
this.values.delete(key);
|
|
47
47
|
return void 0;
|
|
48
48
|
}
|
|
@@ -51,22 +51,29 @@ var LruCache = class {
|
|
|
51
51
|
return entry.data;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
put(key, value) {
|
|
54
|
+
put(key, value, ttl) {
|
|
55
55
|
if (this.values.size >= this.maxEntries) {
|
|
56
56
|
const keyToDelete = this.values.keys().next().value;
|
|
57
57
|
this.values.delete(keyToDelete);
|
|
58
58
|
}
|
|
59
|
-
this.values.set(key, {
|
|
59
|
+
this.values.set(key, {
|
|
60
|
+
data: value,
|
|
61
|
+
timestamp: Date.now(),
|
|
62
|
+
ttl: ttl || this.defaultTTL
|
|
63
|
+
});
|
|
60
64
|
}
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
// src/apiGatewayToken.ts
|
|
64
68
|
var expInSeconds = 60 * 60;
|
|
65
|
-
var apiGatewayJwtCache = new LruCache(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
var apiGatewayJwtCache = new LruCache();
|
|
70
|
+
var getApiGatewayToken = async ({
|
|
71
|
+
apiURL,
|
|
72
|
+
key,
|
|
73
|
+
ttl,
|
|
74
|
+
logger
|
|
75
|
+
}) => {
|
|
76
|
+
const cachedJwt = apiGatewayJwtCache.get(key || apiURL);
|
|
70
77
|
if (cachedJwt) {
|
|
71
78
|
return cachedJwt;
|
|
72
79
|
}
|
|
@@ -78,7 +85,7 @@ var getApiGatewayToken = async (apiURL, logger) => {
|
|
|
78
85
|
if (!serviceAccountEmail) {
|
|
79
86
|
throw new Error("No service account e-mail could be found.");
|
|
80
87
|
}
|
|
81
|
-
logger
|
|
88
|
+
logger?.info(`Serice account e-mail beeing used: ${serviceAccountEmail}`);
|
|
82
89
|
const header = {
|
|
83
90
|
alg: "RS256",
|
|
84
91
|
typ: "JWT"
|
|
@@ -108,14 +115,14 @@ var getApiGatewayToken = async (apiURL, logger) => {
|
|
|
108
115
|
}
|
|
109
116
|
const signature = Buffer.from(response.signedBlob).toString("base64");
|
|
110
117
|
const signedJWT = `${unsignedJWT}.${signature}`;
|
|
111
|
-
apiGatewayJwtCache.put(apiURL, signedJWT);
|
|
118
|
+
apiGatewayJwtCache.put(key || apiURL, signedJWT, ttl);
|
|
112
119
|
return signedJWT;
|
|
113
120
|
} catch (error) {
|
|
114
121
|
if (process.env.GCP_IAM_SOFT_FAIL === "true") {
|
|
115
|
-
logger
|
|
122
|
+
logger?.warn("Soft fail enabled, returning empty JWT");
|
|
116
123
|
return "";
|
|
117
124
|
}
|
|
118
|
-
logger
|
|
125
|
+
logger?.error("Error generating system JWT", error);
|
|
119
126
|
throw new Error(`Error generating system JWT: ${JSON.stringify(error)}`);
|
|
120
127
|
}
|
|
121
128
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -6,17 +6,17 @@ import { GoogleAuth } from "google-auth-library";
|
|
|
6
6
|
var LruCache = class {
|
|
7
7
|
values = /* @__PURE__ */ new Map();
|
|
8
8
|
maxEntries = 1e4;
|
|
9
|
-
|
|
10
|
-
//
|
|
9
|
+
defaultTTL = 1e3 * 10;
|
|
10
|
+
// 10 seconds
|
|
11
11
|
constructor(props) {
|
|
12
|
-
this.
|
|
13
|
-
this.maxEntries =
|
|
12
|
+
this.defaultTTL = props?.ttl ?? this.defaultTTL;
|
|
13
|
+
this.maxEntries = props?.maxEntries ?? this.maxEntries;
|
|
14
14
|
}
|
|
15
15
|
get(key) {
|
|
16
16
|
const hasKey = this.values.has(key);
|
|
17
17
|
if (hasKey) {
|
|
18
18
|
const entry = this.values.get(key);
|
|
19
|
-
if (Date.now() - entry.timestamp >
|
|
19
|
+
if (Date.now() - entry.timestamp > entry.ttl) {
|
|
20
20
|
this.values.delete(key);
|
|
21
21
|
return void 0;
|
|
22
22
|
}
|
|
@@ -25,22 +25,29 @@ var LruCache = class {
|
|
|
25
25
|
return entry.data;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
put(key, value) {
|
|
28
|
+
put(key, value, ttl) {
|
|
29
29
|
if (this.values.size >= this.maxEntries) {
|
|
30
30
|
const keyToDelete = this.values.keys().next().value;
|
|
31
31
|
this.values.delete(keyToDelete);
|
|
32
32
|
}
|
|
33
|
-
this.values.set(key, {
|
|
33
|
+
this.values.set(key, {
|
|
34
|
+
data: value,
|
|
35
|
+
timestamp: Date.now(),
|
|
36
|
+
ttl: ttl || this.defaultTTL
|
|
37
|
+
});
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
// src/apiGatewayToken.ts
|
|
38
42
|
var expInSeconds = 60 * 60;
|
|
39
|
-
var apiGatewayJwtCache = new LruCache(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
var apiGatewayJwtCache = new LruCache();
|
|
44
|
+
var getApiGatewayToken = async ({
|
|
45
|
+
apiURL,
|
|
46
|
+
key,
|
|
47
|
+
ttl,
|
|
48
|
+
logger
|
|
49
|
+
}) => {
|
|
50
|
+
const cachedJwt = apiGatewayJwtCache.get(key || apiURL);
|
|
44
51
|
if (cachedJwt) {
|
|
45
52
|
return cachedJwt;
|
|
46
53
|
}
|
|
@@ -52,7 +59,7 @@ var getApiGatewayToken = async (apiURL, logger) => {
|
|
|
52
59
|
if (!serviceAccountEmail) {
|
|
53
60
|
throw new Error("No service account e-mail could be found.");
|
|
54
61
|
}
|
|
55
|
-
logger
|
|
62
|
+
logger?.info(`Serice account e-mail beeing used: ${serviceAccountEmail}`);
|
|
56
63
|
const header = {
|
|
57
64
|
alg: "RS256",
|
|
58
65
|
typ: "JWT"
|
|
@@ -82,14 +89,14 @@ var getApiGatewayToken = async (apiURL, logger) => {
|
|
|
82
89
|
}
|
|
83
90
|
const signature = Buffer.from(response.signedBlob).toString("base64");
|
|
84
91
|
const signedJWT = `${unsignedJWT}.${signature}`;
|
|
85
|
-
apiGatewayJwtCache.put(apiURL, signedJWT);
|
|
92
|
+
apiGatewayJwtCache.put(key || apiURL, signedJWT, ttl);
|
|
86
93
|
return signedJWT;
|
|
87
94
|
} catch (error) {
|
|
88
95
|
if (process.env.GCP_IAM_SOFT_FAIL === "true") {
|
|
89
|
-
logger
|
|
96
|
+
logger?.warn("Soft fail enabled, returning empty JWT");
|
|
90
97
|
return "";
|
|
91
98
|
}
|
|
92
|
-
logger
|
|
99
|
+
logger?.error("Error generating system JWT", error);
|
|
93
100
|
throw new Error(`Error generating system JWT: ${JSON.stringify(error)}`);
|
|
94
101
|
}
|
|
95
102
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sebspark/gcp-iam",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -20,6 +20,6 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@google-cloud/iam-credentials": "3.3.0",
|
|
23
|
-
"google-auth-library": "
|
|
23
|
+
"google-auth-library": "9.15.1"
|
|
24
24
|
}
|
|
25
25
|
}
|