@andrewheberle/serverless-ssh-ca 0.18.2 → 0.19.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 +14 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +0 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js.map +1 -1
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +10 -3
- package/src/krl.ts +1 -1
- package/src/router.ts +0 -1
- package/src/types.ts +27 -2
package/README.md
CHANGED
|
@@ -15,8 +15,20 @@ import app from "@andrewheberle/serverless-ssh-ca"
|
|
|
15
15
|
export default app
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
This package
|
|
19
|
-
|
|
18
|
+
This package is built for Cloudflare Workers, and Workers is the only runtime
|
|
19
|
+
it is tested on. There are no plans to support other runtimes at this time.
|
|
20
|
+
|
|
21
|
+
The package doesn't use any Workers-specific APIs and doesn't depend on
|
|
22
|
+
`@cloudflare/workers-types`. It needs:
|
|
23
|
+
|
|
24
|
+
- Web standard APIs (`Request`, `Response` and WebCrypto)
|
|
25
|
+
- Node.js compatibility (`nodejs_compat` on Workers), because `sshpk` uses Node APIs
|
|
26
|
+
- A database binding compatible with Cloudflare D1
|
|
27
|
+
- A secret binding with an async `get()` method that returns the CA private key
|
|
28
|
+
|
|
29
|
+
Its exported types describe only these needs, so the `Env` generated by
|
|
30
|
+
`wrangler types` (with `DB` as a `D1Database` and `PRIVATE_KEY` as a
|
|
31
|
+
`SecretsStoreSecret`) can be passed directly as `SshCaBindings`.
|
|
20
32
|
|
|
21
33
|
See the following respositories for additional information:
|
|
22
34
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { ExecutionContext } from "hono";
|
|
1
2
|
import type { SshCaBindings } from "./types.js";
|
|
2
|
-
export type { SshCaBindings } from "./types.js";
|
|
3
|
+
export type { CaDatabase, CaSecret, SshCaBindings } from "./types.js";
|
|
3
4
|
declare const _default: {
|
|
4
5
|
fetch(req: Request, env: SshCaBindings, ctx: ExecutionContext): Promise<Response> | Response;
|
|
5
|
-
scheduled(controller:
|
|
6
|
+
scheduled(controller: unknown, env: SshCaBindings, ctx: ExecutionContext): Promise<void>;
|
|
6
7
|
};
|
|
7
8
|
export default _default;
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;;eAWtD,OAAO,OAAO,aAAa,OAAO,gBAAgB;0BAMjC,OAAO,OAAO,aAAa,OAAO,gBAAgB"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAUvC,IAAI,GAA6C,CAAA;AAEjD,eAAe;IACX,KAAK,CAAC,GAAY,EAAE,GAAkB,EAAE,GAAqB;QACzD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QACxB,CAAC;QACD,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IACnC,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,UAAmB,EAAE,GAAkB,EAAE,GAAqB;QAC1E,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IACjC,CAAC;CACmB,CAAA"}
|
package/dist/router.d.ts
CHANGED
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,MAAM,CAAA;AAIzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,MAAM,CAAA;AAIzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAAA;AAE7D,eAAO,MAAM,SAAS,QAAS,aAAa,mHA+B3C,CAAA"}
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AACzC,OAAO,EAAE,SAAS,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AACzC,OAAO,EAAE,SAAS,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKpC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAkB,EAAE,EAAE;IAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA;IAEvB,qBAAqB;IACrB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACpB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;QAC5B,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;IACtG,CAAC,CAAC,CAAA;IAEF,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE;QAC7B,MAAM,EAAE;YACP,IAAI,EAAE;gBACL,KAAK,EAAE,uBAAuB;gBAC9B,OAAO,EAAE,OAAO;aAChB;SACD;KACD,CAAC,CAAA;IAEC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,UAAU,EAAE;QAC1D,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,KAAK;KACtB,CAAC,CAAA;IAEF,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IAEhC,OAAO,GAAG,CAAA;AACd,CAAC,CAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -19,10 +19,33 @@ export type SSHExtension = {
|
|
|
19
19
|
name: string;
|
|
20
20
|
data: Buffer<ArrayBuffer>;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* The subset of a Cloudflare D1 database binding used by the CA.
|
|
24
|
+
*
|
|
25
|
+
* A Workers `D1Database` binding satisfies this structurally, so the package
|
|
26
|
+
* does not need to depend on `@cloudflare/workers-types`.
|
|
27
|
+
*/
|
|
28
|
+
export interface CaDatabase {
|
|
29
|
+
prepare(query: string): unknown;
|
|
30
|
+
batch(statements: never[]): Promise<unknown>;
|
|
31
|
+
exec(query: string): Promise<unknown>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The subset of a Cloudflare Secrets Store binding used to load the CA private key.
|
|
35
|
+
*
|
|
36
|
+
* A Workers `SecretsStoreSecret` binding satisfies this structurally.
|
|
37
|
+
*/
|
|
38
|
+
export interface CaSecret {
|
|
39
|
+
get(): Promise<string>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The bindings (environment) the CA expects, see {@link CaDatabase} and
|
|
43
|
+
* {@link CaSecret} for the non-string bindings.
|
|
44
|
+
*/
|
|
22
45
|
export interface SshCaBindings {
|
|
23
|
-
DB:
|
|
46
|
+
DB: CaDatabase;
|
|
24
47
|
DB_CERTIFICATE_RETENTION: string;
|
|
25
|
-
PRIVATE_KEY:
|
|
48
|
+
PRIVATE_KEY: CaSecret;
|
|
26
49
|
SSH_CERTIFICATE_EXTENSIONS: string;
|
|
27
50
|
SSH_CERTIFICATE_LIFETIME: string;
|
|
28
51
|
SSH_CERTIFICATE_INCLUDE_SELF?: string | boolean;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAGjC,MAAM,MAAM,wBAAwB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;CACtB,CAAA;AAGD,MAAM,MAAM,4BAA4B,GAAG;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;CACnC,GAAG,UAAU,CAAA;AAEd,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;CAC5B,CAAA;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,UAAU,CAAA;IACd,wBAAwB,EAAE,MAAM,CAAA;IAChC,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAGjC,MAAM,MAAM,wBAAwB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;CACtB,CAAA;AAGD,MAAM,MAAM,4BAA4B,GAAG;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;CACnC,GAAG,UAAU,CAAA;AAEd,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;CAC5B,CAAA;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/B,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACxC;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACrB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,UAAU,CAAA;IACd,wBAAwB,EAAE,MAAM,CAAA;IAChC,WAAW,EAAE,QAAQ,CAAA;IACrB,0BAA0B,EAAE,MAAM,CAAA;IAClC,wBAAwB,EAAE,MAAM,CAAA;IAChC,4BAA4B,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/C,kCAAkC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACrD,0BAA0B,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC9C,6BAA6B,EAAE,MAAM,CAAA;IACrC,mCAAmC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACvD,kCAAkC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACtD,SAAS,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC,oCAAoC,EAAE,MAAM,CAAA;IAC5C,iCAAiC,EAAE,MAAM,CAAA;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andrewheberle/serverless-ssh-ca",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "A serverless SSH CA built on Cloudflare Workers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@andrewheberle/ts-slog": "^1.3.0",
|
|
34
|
-
"@cloudflare/workers-types": "^5.0.0",
|
|
35
34
|
"chanfana": "^3.0.0",
|
|
36
35
|
"hono": "^4.10.6",
|
|
37
36
|
"itty-time": "^2.0.2",
|
|
38
37
|
"jose": "^6.0.12",
|
|
39
|
-
"workers-qb": "^1.14.0",
|
|
40
38
|
"sshpk": "^1.18.0",
|
|
39
|
+
"workers-qb": "^1.14.0",
|
|
41
40
|
"zod": "^4.0.0"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
43
|
"@eslint/js": "^10.0.1",
|
|
44
|
+
"@types/node": "^24.19.1",
|
|
45
45
|
"@types/sshpk": "^1.17.4",
|
|
46
46
|
"@vitest/coverage-v8": "^4.1.7",
|
|
47
47
|
"eslint": "^10.4.1",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import type { ExecutionContext } from "hono"
|
|
1
2
|
import { dbCleanup } from "./db/index.js"
|
|
2
3
|
import { createApp } from "./router.js"
|
|
3
4
|
import type { SshCaBindings } from "./types.js"
|
|
4
|
-
export type { SshCaBindings } from "./types.js"
|
|
5
|
+
export type { CaDatabase, CaSecret, SshCaBindings } from "./types.js"
|
|
6
|
+
|
|
7
|
+
// the handlers the CA exposes, compatible with a Cloudflare Workers ExportedHandler
|
|
8
|
+
type SshCaHandler = {
|
|
9
|
+
fetch(req: Request, env: SshCaBindings, ctx: ExecutionContext): Response | Promise<Response>
|
|
10
|
+
scheduled(controller: unknown, env: SshCaBindings, ctx: ExecutionContext): Promise<void>
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
let app: ReturnType<typeof createApp> | undefined
|
|
7
14
|
|
|
@@ -12,7 +19,7 @@ export default {
|
|
|
12
19
|
}
|
|
13
20
|
return app.fetch(req, env, ctx)
|
|
14
21
|
},
|
|
15
|
-
async scheduled(controller:
|
|
22
|
+
async scheduled(controller: unknown, env: SshCaBindings, ctx: ExecutionContext) {
|
|
16
23
|
ctx.waitUntil(dbCleanup(env))
|
|
17
24
|
},
|
|
18
|
-
} satisfies
|
|
25
|
+
} satisfies SshCaHandler
|
package/src/krl.ts
CHANGED
|
@@ -123,7 +123,7 @@ function base64url(bytes: Uint8Array): string {
|
|
|
123
123
|
async function importPrivateKey(caKey: PrivateKey): Promise<{
|
|
124
124
|
cryptoKey: CryptoKey
|
|
125
125
|
sigAlgo: string // SSH signature algorithm name
|
|
126
|
-
webCryptoAlgo:
|
|
126
|
+
webCryptoAlgo: Parameters<SubtleCrypto["sign"]>[0]
|
|
127
127
|
}> {
|
|
128
128
|
const type = caKey.type // "ed25519" | "ecdsa" | etc.
|
|
129
129
|
const curve = (caKey as unknown as { curve?: string }).curve
|
package/src/router.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { HTTPException } from "hono/http-exception"
|
|
|
5
5
|
import { logger } from "./logger.js"
|
|
6
6
|
import type { SshCaBindings } from "./types.js"
|
|
7
7
|
|
|
8
|
-
export type CFArgs = [SshCaBindings, ExecutionContext]
|
|
9
8
|
export type AppContext = Context<{ Bindings: SshCaBindings }>
|
|
10
9
|
|
|
11
10
|
export const createApp = (env: SshCaBindings) => {
|
package/src/types.ts
CHANGED
|
@@ -26,10 +26,35 @@ export type SSHExtension = {
|
|
|
26
26
|
data: Buffer<ArrayBuffer>
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* The subset of a Cloudflare D1 database binding used by the CA.
|
|
31
|
+
*
|
|
32
|
+
* A Workers `D1Database` binding satisfies this structurally, so the package
|
|
33
|
+
* does not need to depend on `@cloudflare/workers-types`.
|
|
34
|
+
*/
|
|
35
|
+
export interface CaDatabase {
|
|
36
|
+
prepare(query: string): unknown
|
|
37
|
+
batch(statements: never[]): Promise<unknown>
|
|
38
|
+
exec(query: string): Promise<unknown>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The subset of a Cloudflare Secrets Store binding used to load the CA private key.
|
|
43
|
+
*
|
|
44
|
+
* A Workers `SecretsStoreSecret` binding satisfies this structurally.
|
|
45
|
+
*/
|
|
46
|
+
export interface CaSecret {
|
|
47
|
+
get(): Promise<string>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The bindings (environment) the CA expects, see {@link CaDatabase} and
|
|
52
|
+
* {@link CaSecret} for the non-string bindings.
|
|
53
|
+
*/
|
|
29
54
|
export interface SshCaBindings {
|
|
30
|
-
DB:
|
|
55
|
+
DB: CaDatabase
|
|
31
56
|
DB_CERTIFICATE_RETENTION: string
|
|
32
|
-
PRIVATE_KEY:
|
|
57
|
+
PRIVATE_KEY: CaSecret
|
|
33
58
|
SSH_CERTIFICATE_EXTENSIONS: string
|
|
34
59
|
SSH_CERTIFICATE_LIFETIME: string
|
|
35
60
|
SSH_CERTIFICATE_INCLUDE_SELF?: string | boolean
|