@blakearoberts/visage 0.0.1-rc.6 → 0.0.1-rc.8
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 +1 -1
- package/dist/certs.d.ts.map +1 -1
- package/dist/compose.d.ts.map +1 -1
- package/dist/config.d.ts +18 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +164 -142
- package/dist/render/nginx.d.ts.map +1 -1
- package/dist/types.d.ts +31 -14
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -11
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ Do not treat the managed Dex and OAuth2 Proxy defaults as production auth infras
|
|
|
125
125
|
- If startup fails immediately, confirm Docker is running and `docker compose` works.
|
|
126
126
|
- If NGINX cannot start, check whether the configured `port` is already in use.
|
|
127
127
|
- If the hostname cannot be resolved, Visage may need permission to update `/etc/hosts`.
|
|
128
|
-
- If the browser rejects the certificate, allow the local certificate authority prompt from `mkcert
|
|
128
|
+
- If the browser rejects the certificate, allow the local certificate authority prompt from `mkcert`; CI test runners should be configured to ignore local HTTPS errors.
|
|
129
129
|
|
|
130
130
|
## TO-DO
|
|
131
131
|
|
package/dist/certs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"certs.d.ts","sourceRoot":"","sources":["../src/certs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"certs.d.ts","sourceRoot":"","sources":["../src/certs.ts"],"names":[],"mappings":"AAcA,KAAK,OAAO,GAAG;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E"}
|
package/dist/compose.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAIA,KAAK,WAAW,GAAG,MAAM,IAAI,CAAC;AAI9B,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAwCtD"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ResolvedConfig } from 'vite';
|
|
2
|
-
import type { VisageDexExpiry, VisageDexOptions, VisageDexUser, VisageExternalIdpOptions, VisageOptions, VisageService, VisageUpstream } from './types';
|
|
2
|
+
import type { VisageDexExpiry, VisageDexOptions, VisageDexUser, VisageExternalIdpOptions, VisageOptions, VisageProxyPolicy, VisageService, VisageUpstream } from './types';
|
|
3
3
|
type Volume = readonly [from: string, to: string];
|
|
4
4
|
type ResolvedCookiePolicy = {
|
|
5
5
|
readonly cookie_name: string;
|
|
@@ -17,20 +17,14 @@ type ResolvedOAuth2Client = {
|
|
|
17
17
|
readonly scopes: readonly string[];
|
|
18
18
|
readonly public: boolean;
|
|
19
19
|
};
|
|
20
|
-
type ResolvedService = Omit<VisageService, 'upstream'>;
|
|
21
|
-
type ResolvedUpstream = Omit<VisageUpstream, 'host' | 'port' | 'scheme'> & {
|
|
22
|
-
readonly host: string;
|
|
23
|
-
readonly port: number;
|
|
24
|
-
readonly scheme: 'http' | 'https';
|
|
25
|
-
};
|
|
26
20
|
type ResolvedVisageOptions = {
|
|
27
21
|
readonly host: string;
|
|
28
22
|
readonly port: number;
|
|
29
23
|
readonly cookie: ResolvedCookiePolicy;
|
|
30
24
|
readonly idp: ResolvedIdpOption;
|
|
31
25
|
readonly oauth2: ResolvedOAuth2Client;
|
|
32
|
-
readonly services: Readonly<Record<string,
|
|
33
|
-
readonly upstreams
|
|
26
|
+
readonly services: Readonly<Record<string, VisageService>>;
|
|
27
|
+
readonly upstreams: Record<string, VisageUpstream>;
|
|
34
28
|
};
|
|
35
29
|
type ResolvedBaseIdpConfig = {
|
|
36
30
|
readonly upstream: string;
|
|
@@ -49,6 +43,20 @@ type ResolvedExternalIdpConfig = ResolvedBaseIdpConfig & {
|
|
|
49
43
|
readonly dex?: never;
|
|
50
44
|
};
|
|
51
45
|
type ResolvedIdpConfig = ResolvedDexIdpConfig | ResolvedExternalIdpConfig;
|
|
46
|
+
type ResolvedService = Omit<VisageService, 'upstream'>;
|
|
47
|
+
type ResolvedUpstream = {
|
|
48
|
+
readonly scheme: 'http' | 'https';
|
|
49
|
+
readonly host: string;
|
|
50
|
+
readonly port: number;
|
|
51
|
+
readonly locations: Readonly<Record<string, VisageProxyPolicy>>;
|
|
52
|
+
};
|
|
53
|
+
type ResolvedProxyPolicy = {
|
|
54
|
+
readonly auth: Required<VisageProxyPolicy['auth']>;
|
|
55
|
+
readonly headers: VisageProxyPolicy['headers'];
|
|
56
|
+
};
|
|
57
|
+
type ResolvedConfigUpstream = Omit<ResolvedUpstream, 'locations'> & {
|
|
58
|
+
readonly locations: Readonly<Record<string, ResolvedProxyPolicy>>;
|
|
59
|
+
};
|
|
52
60
|
export type VisageConfig = {
|
|
53
61
|
readonly host: string;
|
|
54
62
|
readonly port: number;
|
|
@@ -65,7 +73,7 @@ export type VisageConfig = {
|
|
|
65
73
|
readonly oauth2ProxyClientSecret: Volume;
|
|
66
74
|
};
|
|
67
75
|
readonly services: Readonly<Record<string, ResolvedService>>;
|
|
68
|
-
readonly upstreams: Readonly<Record<string,
|
|
76
|
+
readonly upstreams: Readonly<Record<string, ResolvedConfigUpstream>>;
|
|
69
77
|
};
|
|
70
78
|
export declare function resolveOptions(options: VisageOptions): ResolvedVisageOptions;
|
|
71
79
|
export declare function resolveConfig(options: ResolvedVisageOptions, config: ResolvedConfig, vitePort: number): VisageConfig;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE3C,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,wBAAwB,EACxB,aAAa,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAOnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAOnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7C,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,wBAAwB,EACxB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,SAAS,CAAC;AAUjB,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAgE1D;AAED,eAAe,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { spawnSync } from 'node:child_process';
|
|
3
|
-
import {
|
|
1
|
+
import { join, dirname } from 'node:path';
|
|
2
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
3
|
+
import { mkdirSync, openSync, chmodSync, rmSync, existsSync, createWriteStream, readFileSync, appendFileSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { Readable } from 'node:stream';
|
|
6
6
|
import { pipeline } from 'node:stream/promises';
|
|
@@ -9,83 +9,78 @@ import { hashSync } from 'bcryptjs';
|
|
|
9
9
|
import { Eta } from 'eta';
|
|
10
10
|
import { createHash } from 'node:crypto';
|
|
11
11
|
|
|
12
|
-
let
|
|
12
|
+
let stopRef;
|
|
13
13
|
function startCompose(file) {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
stopRef?.();
|
|
15
|
+
stopRef = undefined;
|
|
16
|
+
const logs = join(dirname(file), 'logs');
|
|
17
|
+
mkdirSync(logs, { recursive: true });
|
|
18
|
+
const output = openSync(join(logs, 'compose.log'), 'w');
|
|
19
|
+
const compose = [
|
|
20
|
+
'compose',
|
|
21
|
+
`--project-name=${process.env.COMPOSE_PROJECT_NAME ?? 'visage'}`,
|
|
22
|
+
`--file=${file}`,
|
|
23
|
+
];
|
|
24
|
+
const env = { ...process.env, COMPOSE_MENU: 'false' };
|
|
25
|
+
const opts = {
|
|
26
|
+
cwd: dirname(file),
|
|
27
|
+
stdio: ['ignore', output, output],
|
|
28
|
+
env,
|
|
29
|
+
};
|
|
30
|
+
const up = [
|
|
31
|
+
...compose,
|
|
32
|
+
'up',
|
|
33
|
+
'--abort-on-container-failure',
|
|
34
|
+
'--no-color',
|
|
35
|
+
'--remove-orphans',
|
|
36
|
+
];
|
|
37
|
+
const child = spawn('docker', up, opts);
|
|
16
38
|
const stop = () => {
|
|
17
|
-
if (
|
|
39
|
+
if (stopRef !== stop)
|
|
18
40
|
return;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
stopRef = undefined;
|
|
42
|
+
child.kill();
|
|
43
|
+
const down = [...compose, 'down', '--remove-orphans'];
|
|
44
|
+
spawnSync('docker', down, opts);
|
|
23
45
|
};
|
|
24
|
-
|
|
25
|
-
stopCompose = stop;
|
|
26
|
-
process.off('SIGINT', onSigInt);
|
|
27
|
-
process.off('SIGTERM', onSigTerm);
|
|
28
|
-
process.once('SIGINT', onSigInt);
|
|
29
|
-
process.once('SIGTERM', onSigTerm);
|
|
46
|
+
stopRef = stop;
|
|
30
47
|
return stop;
|
|
31
48
|
}
|
|
32
|
-
function run(file, args, message) {
|
|
33
|
-
const result = spawnSync('docker', ['compose', '-f', file, ...args], {
|
|
34
|
-
cwd: dirname(file),
|
|
35
|
-
stdio: 'inherit',
|
|
36
|
-
});
|
|
37
|
-
if (result.error)
|
|
38
|
-
throw result.error;
|
|
39
|
-
if (result.status !== 0)
|
|
40
|
-
throw new Error(message);
|
|
41
|
-
}
|
|
42
|
-
function onSigInt() {
|
|
43
|
-
try {
|
|
44
|
-
stopCompose?.();
|
|
45
|
-
}
|
|
46
|
-
finally {
|
|
47
|
-
process.exit(130);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function onSigTerm() {
|
|
51
|
-
try {
|
|
52
|
-
stopCompose?.();
|
|
53
|
-
}
|
|
54
|
-
finally {
|
|
55
|
-
process.exit(143);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
49
|
|
|
50
|
+
const CACHE_HOME = process.env.XDG_CACHE_HOME || join(homedir(), '.cache');
|
|
59
51
|
async function ensureCerts({ certs, hostname }) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return;
|
|
52
|
+
const CAROOT = join(CACHE_HOME, 'visage/ca');
|
|
53
|
+
mkdirSync(CAROOT, { recursive: true, mode: 0o700 });
|
|
54
|
+
chmodSync(CAROOT, 0o700);
|
|
64
55
|
const mkcert = await ensureMkCert();
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
56
|
+
const logs = join(dirname(certs), 'logs');
|
|
57
|
+
mkdirSync(logs, { recursive: true });
|
|
58
|
+
const log = join(logs, 'mkcert.log');
|
|
59
|
+
const output = openSync(log, 'w');
|
|
60
|
+
const env = { CAROOT, TRUST_STORES: 'system', ...process.env };
|
|
61
|
+
const tty = process.stdin.isTTY;
|
|
62
|
+
const stdio = [
|
|
63
|
+
tty ? 'inherit' : 'ignore',
|
|
64
|
+
output,
|
|
65
|
+
output,
|
|
66
|
+
];
|
|
67
|
+
if (process.env.CI !== 'true') {
|
|
68
|
+
// mkcert -install is idempotent; CA files alone do not prove trust-store state.
|
|
69
|
+
const result = spawnSync(mkcert, ['-install'], { env, stdio });
|
|
78
70
|
if (result.error)
|
|
79
71
|
throw result.error;
|
|
80
72
|
if (result.status !== 0) {
|
|
81
73
|
throw new Error('Failed to install CA');
|
|
82
74
|
}
|
|
83
75
|
}
|
|
84
|
-
|
|
76
|
+
const cert = join(certs, 'tls.crt');
|
|
77
|
+
const key = join(certs, 'tls.key');
|
|
85
78
|
mkdirSync(certs, { recursive: true });
|
|
79
|
+
rmSync(cert, { force: true });
|
|
80
|
+
rmSync(key, { force: true });
|
|
86
81
|
const names = [...new Set([hostname, 'localhost', '127.0.0.1', '::1'])];
|
|
87
82
|
const args = ['-cert-file', cert, '-key-file', key, ...names];
|
|
88
|
-
const result = spawnSync(mkcert, args, { env, stdio
|
|
83
|
+
const result = spawnSync(mkcert, args, { env, stdio });
|
|
89
84
|
if (result.error)
|
|
90
85
|
throw result.error;
|
|
91
86
|
if (result.status !== 0) {
|
|
@@ -93,7 +88,7 @@ async function ensureCerts({ certs, hostname }) {
|
|
|
93
88
|
}
|
|
94
89
|
}
|
|
95
90
|
async function ensureMkCert() {
|
|
96
|
-
const bin = join(
|
|
91
|
+
const bin = join(CACHE_HOME, 'visage/bin');
|
|
97
92
|
const file = join(bin, `mkcert-${process.platform}-${process.arch}`);
|
|
98
93
|
if (existsSync(file))
|
|
99
94
|
return file;
|
|
@@ -254,6 +249,9 @@ http {
|
|
|
254
249
|
ssl_certificate <%~ it.ssl.cert %>;
|
|
255
250
|
ssl_certificate_key <%~ it.ssl.key %>;
|
|
256
251
|
|
|
252
|
+
# Redirect accidental plaintext HTTP requests sent to the HTTPS port.
|
|
253
|
+
error_page 497 =301 https://$http_host$request_uri;
|
|
254
|
+
|
|
257
255
|
<%_ for (const [name, upstream] of Object.entries(it.upstreams)) { %>
|
|
258
256
|
<%_ for (const [path, location] of Object.entries(upstream.locations ?? {})) { %>
|
|
259
257
|
location <%~ path %> {
|
|
@@ -334,6 +332,8 @@ function renderOauth2ProxyConfig(config) {
|
|
|
334
332
|
cookie_httponly: true,
|
|
335
333
|
cookie_secure: true,
|
|
336
334
|
cookie_samesite: 'lax',
|
|
335
|
+
cookie_csrf_per_request: true,
|
|
336
|
+
cookie_csrf_per_request_limit: 16,
|
|
337
337
|
email_domains: ['*'],
|
|
338
338
|
scope: config.oauth2.scopes.join(' '),
|
|
339
339
|
upstreams: ['static://202'],
|
|
@@ -342,6 +342,7 @@ function renderOauth2ProxyConfig(config) {
|
|
|
342
342
|
pass_access_token: true,
|
|
343
343
|
pass_authorization_header: true,
|
|
344
344
|
skip_provider_button: true,
|
|
345
|
+
whitelist_domains: [config.host, `${config.host}:${config.port}`],
|
|
345
346
|
};
|
|
346
347
|
return `${Object.entries(data)
|
|
347
348
|
.map(([key, value]) => {
|
|
@@ -409,11 +410,7 @@ const BaseOauth2ProxyUpstream = {
|
|
|
409
410
|
'/oauth2/': {
|
|
410
411
|
auth: { enabled: false },
|
|
411
412
|
headers: {
|
|
412
|
-
Cookie: '$http_cookie',
|
|
413
|
-
Host: '$host',
|
|
414
|
-
'X-Real-IP': '$remote_addr',
|
|
415
|
-
'X-Forwarded-For': '$proxy_add_x_forwarded_for',
|
|
416
|
-
'X-Forwarded-Proto': '$scheme',
|
|
413
|
+
Cookie: '$http_cookie', // Forward session cookie.
|
|
417
414
|
'X-Auth-Request-Redirect': '$request_uri',
|
|
418
415
|
},
|
|
419
416
|
},
|
|
@@ -461,19 +458,17 @@ function resolveOptions(options) {
|
|
|
461
458
|
const { host = 'localhost', port = 9001, cookie = {}, oauth2 = {} } = options;
|
|
462
459
|
const cookieName = cookie.name ?? 'session';
|
|
463
460
|
const publicClient = oauth2.clientSecret === null;
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
...resolveUpstreams(options.upstreams),
|
|
467
|
-
};
|
|
461
|
+
const services = resolveServicesOptions(options.services);
|
|
462
|
+
const upstreams = resolveUpstreamsOptions(services, options.upstreams);
|
|
468
463
|
return {
|
|
469
464
|
host,
|
|
470
465
|
port,
|
|
471
466
|
cookie: {
|
|
472
467
|
...DefaultCookiePolicy,
|
|
473
468
|
cookie_name: cookie.domains === undefined
|
|
474
|
-
? cookieName.startsWith('
|
|
469
|
+
? cookieName.startsWith('__Host-')
|
|
475
470
|
? cookieName
|
|
476
|
-
: `
|
|
471
|
+
: `__Host-${cookieName}`
|
|
477
472
|
: cookieName,
|
|
478
473
|
...(cookie.expire === undefined ? {} : { cookie_expire: cookie.expire }),
|
|
479
474
|
...(cookie.refresh === undefined
|
|
@@ -493,62 +488,61 @@ function resolveOptions(options) {
|
|
|
493
488
|
scopes: oauth2.scopes ?? DefaultOAuth2Client.scopes,
|
|
494
489
|
public: publicClient,
|
|
495
490
|
},
|
|
496
|
-
services
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
491
|
+
services,
|
|
492
|
+
upstreams,
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function resolveServicesOptions(services = {}) {
|
|
496
|
+
return {
|
|
497
|
+
...services,
|
|
498
|
+
nginx: {
|
|
499
|
+
...BaseServiceNginx,
|
|
500
|
+
...{
|
|
501
|
+
...(services.nginx ?? {}),
|
|
502
|
+
extra_hosts: [
|
|
503
|
+
...BaseServiceNginx.extra_hosts,
|
|
504
|
+
...(services.nginx?.extra_hosts ?? []),
|
|
505
|
+
],
|
|
510
506
|
},
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
],
|
|
519
|
-
|
|
507
|
+
},
|
|
508
|
+
oauth2_proxy: {
|
|
509
|
+
...BaseOAuth2ProxyService,
|
|
510
|
+
...{
|
|
511
|
+
...(services.oauth2_proxy ?? {}),
|
|
512
|
+
extra_hosts: [
|
|
513
|
+
...BaseOAuth2ProxyService.extra_hosts,
|
|
514
|
+
...(services.oauth2_proxy?.extra_hosts ?? []),
|
|
515
|
+
],
|
|
520
516
|
},
|
|
521
517
|
},
|
|
522
|
-
...(Object.keys(upstreams).length === 0 ? {} : { upstreams }),
|
|
523
518
|
};
|
|
524
519
|
}
|
|
525
|
-
function
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
name,
|
|
536
|
-
resolveUpstream(name, service.upstream ?? {}),
|
|
537
|
-
]));
|
|
538
|
-
}
|
|
539
|
-
function resolveUpstreams(upstreams = {}) {
|
|
540
|
-
return Object.fromEntries(Object.entries(upstreams).map(([name, upstream]) => [
|
|
541
|
-
name,
|
|
542
|
-
resolveUpstream(name, upstream),
|
|
543
|
-
]));
|
|
544
|
-
}
|
|
545
|
-
function resolveUpstream(name, upstream) {
|
|
520
|
+
function resolveUpstreamsOptions(services, upstreams = {}) {
|
|
521
|
+
function resolveUpstream(name, upstream) {
|
|
522
|
+
return {
|
|
523
|
+
...upstream,
|
|
524
|
+
scheme: upstream.scheme,
|
|
525
|
+
host: upstream.host ?? name,
|
|
526
|
+
port: upstream.port ?? (upstream.scheme === 'https' ? 443 : 80),
|
|
527
|
+
locations: upstream.locations ?? { [`/${name}/`]: {} },
|
|
528
|
+
};
|
|
529
|
+
}
|
|
546
530
|
return {
|
|
547
|
-
...
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
531
|
+
...Object.fromEntries(Object.entries(services)
|
|
532
|
+
.filter(([name]) =>
|
|
533
|
+
// Exclude base services handled separately.
|
|
534
|
+
name !== 'dex' && name !== 'nginx' && name !== 'oauth2_proxy')
|
|
535
|
+
.map(([name, service]) => [
|
|
536
|
+
name,
|
|
537
|
+
resolveUpstream(name, { scheme: 'http', ...service.upstream }),
|
|
538
|
+
])),
|
|
539
|
+
...Object.fromEntries(Object.entries(upstreams).map(([name, upstream]) => [
|
|
540
|
+
name,
|
|
541
|
+
resolveUpstream(name, {
|
|
542
|
+
scheme: services[name] === undefined ? 'https' : 'http',
|
|
543
|
+
...upstream,
|
|
544
|
+
}),
|
|
545
|
+
])),
|
|
552
546
|
};
|
|
553
547
|
}
|
|
554
548
|
function resolveIdpOption(idp) {
|
|
@@ -605,6 +599,7 @@ function resolveExternalIdpUpstream(idp) {
|
|
|
605
599
|
const issuer = new URL(idp.issuer);
|
|
606
600
|
return {
|
|
607
601
|
host: issuer.hostname,
|
|
602
|
+
locations: {},
|
|
608
603
|
scheme: issuer.protocol === 'https:' ? 'https' : 'http',
|
|
609
604
|
port: Number(issuer.port) || (issuer.protocol === 'https:' ? 443 : 80),
|
|
610
605
|
};
|
|
@@ -643,27 +638,47 @@ function resolveConfig(options, config, vitePort) {
|
|
|
643
638
|
depends_on: ['dex'],
|
|
644
639
|
},
|
|
645
640
|
}),
|
|
646
|
-
...options.services,
|
|
641
|
+
...Object.fromEntries(Object.entries(options.services).map(([name, { upstream: _upstream, ...service }]) => [name, service])),
|
|
647
642
|
},
|
|
648
|
-
upstreams: Object.fromEntries(Object.entries(upstreams).map(([name, upstream]) =>
|
|
649
|
-
name
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
643
|
+
upstreams: Object.fromEntries(Object.entries(upstreams).map(([name, upstream]) => {
|
|
644
|
+
const external = options.upstreams[name] !== undefined &&
|
|
645
|
+
options.services[name] === undefined;
|
|
646
|
+
return [
|
|
647
|
+
name,
|
|
648
|
+
{
|
|
649
|
+
...upstream,
|
|
650
|
+
locations: Object.fromEntries(Object.entries(upstream.locations ?? {}).map(([path, policy]) => [
|
|
651
|
+
path,
|
|
652
|
+
{
|
|
653
|
+
auth: { ...DefaultProxyPolicy.auth, ...policy.auth },
|
|
654
|
+
headers: {
|
|
655
|
+
...(external
|
|
656
|
+
? { ...DefaultProxyPolicy.headers, Host: upstream.host }
|
|
657
|
+
: DefaultProxyPolicy.headers),
|
|
658
|
+
...policy.headers,
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
])),
|
|
662
|
+
},
|
|
663
|
+
];
|
|
664
|
+
})),
|
|
661
665
|
};
|
|
662
666
|
}
|
|
663
667
|
|
|
668
|
+
function formatUrl(host, port) {
|
|
669
|
+
const AnsiGreen = '\x1b[32m';
|
|
670
|
+
const AnsiCyan = '\x1b[36m';
|
|
671
|
+
const AnsiBold = '\x1b[1m';
|
|
672
|
+
const AnsiReset = '\x1b[0m';
|
|
673
|
+
return ` ${AnsiGreen}➜${AnsiReset} ${AnsiBold}Visage${AnsiReset}: ${AnsiCyan}https://${host}:${AnsiBold}${port}${AnsiReset}${AnsiCyan}/${AnsiReset}`;
|
|
674
|
+
}
|
|
664
675
|
function visage(options = {}) {
|
|
665
676
|
const resolvedOptions = resolveOptions(options);
|
|
666
677
|
let stop;
|
|
678
|
+
const closeBundle = () => {
|
|
679
|
+
stop?.();
|
|
680
|
+
stop = undefined;
|
|
681
|
+
};
|
|
667
682
|
return {
|
|
668
683
|
name: 'visage',
|
|
669
684
|
apply: 'serve',
|
|
@@ -680,8 +695,17 @@ function visage(options = {}) {
|
|
|
680
695
|
};
|
|
681
696
|
},
|
|
682
697
|
configureServer(server) {
|
|
698
|
+
let url;
|
|
699
|
+
const printUrls = server.printUrls.bind(server);
|
|
700
|
+
server.printUrls = () => {
|
|
701
|
+
printUrls();
|
|
702
|
+
if (url)
|
|
703
|
+
server.config.logger.info(formatUrl(url.host, url.port));
|
|
704
|
+
};
|
|
683
705
|
async function startVisage(port) {
|
|
684
706
|
const config = resolveConfig(resolvedOptions, server.config, port);
|
|
707
|
+
url = { host: config.host, port: config.port };
|
|
708
|
+
rmSync(join(config.cache, 'logs'), { recursive: true, force: true });
|
|
685
709
|
await ensureCerts({
|
|
686
710
|
certs: join(config.cache, config.files.certs[0]),
|
|
687
711
|
hostname: config.host,
|
|
@@ -698,13 +722,11 @@ function visage(options = {}) {
|
|
|
698
722
|
throw new Error('Failed to resolve port for Visage');
|
|
699
723
|
}
|
|
700
724
|
stop = await startVisage(address.port);
|
|
725
|
+
server.httpServer?.once('close', closeBundle);
|
|
701
726
|
return result;
|
|
702
727
|
};
|
|
703
728
|
},
|
|
704
|
-
closeBundle
|
|
705
|
-
stop?.();
|
|
706
|
-
stop = undefined;
|
|
707
|
-
},
|
|
729
|
+
closeBundle,
|
|
708
730
|
};
|
|
709
731
|
}
|
|
710
732
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nginx.d.ts","sourceRoot":"","sources":["../../src/render/nginx.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"nginx.d.ts","sourceRoot":"","sources":["../../src/render/nginx.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AA0D9C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAI3D"}
|
package/dist/types.d.ts
CHANGED
|
@@ -15,7 +15,8 @@ export type VisageOptions = {
|
|
|
15
15
|
*/
|
|
16
16
|
readonly port?: number;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* OAuth2 Proxy session cookie settings for name, browser scope, lifetime, and
|
|
19
|
+
* refresh timing.
|
|
19
20
|
*/
|
|
20
21
|
readonly cookie?: VisageCookiePolicy;
|
|
21
22
|
/**
|
|
@@ -38,37 +39,48 @@ export type VisageOptions = {
|
|
|
38
39
|
readonly upstreams?: Record<string, VisageUpstream>;
|
|
39
40
|
};
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
+
* Settings for the browser session cookie managed by OAuth2 Proxy.
|
|
43
|
+
*
|
|
44
|
+
* OAuth2 Proxy keeps OIDC session state behind this cookie. The cookie lifetime
|
|
45
|
+
* caps the browser session, while the refresh interval controls when OAuth2
|
|
46
|
+
* Proxy tries to renew token state with the provider.
|
|
42
47
|
*/
|
|
43
48
|
export type VisageCookiePolicy = {
|
|
44
49
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
50
|
+
* Browser session cookie base name. When no domains are configured, Visage
|
|
51
|
+
* renders a host-only name with a `__Host-` prefix, so the default rendered
|
|
52
|
+
* name is `__Host-session`.
|
|
48
53
|
*
|
|
49
54
|
* @defaultValue `'session'`
|
|
50
55
|
*/
|
|
51
56
|
readonly name?: string;
|
|
52
57
|
/**
|
|
53
|
-
* Maximum
|
|
58
|
+
* Maximum browser session lifetime. Rendered as OAuth2 Proxy `cookie_expire`
|
|
59
|
+
* using its duration syntax. Keep this aligned with the identity provider's
|
|
60
|
+
* refresh-token lifetime to avoid sessions that can no longer be renewed
|
|
61
|
+
* silently.
|
|
54
62
|
*
|
|
55
63
|
* @defaultValue `'8h'`
|
|
56
64
|
*/
|
|
57
65
|
readonly expire?: string;
|
|
58
66
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
67
|
+
* Session age after which OAuth2 Proxy attempts silent renewal using the
|
|
68
|
+
* stored refresh token, when one is available. Rendered as `cookie_refresh`
|
|
69
|
+
* using OAuth2 Proxy duration syntax. If upstreams validate forwarded access
|
|
70
|
+
* tokens, set this below the access-token lifetime so OAuth2 Proxy refreshes
|
|
71
|
+
* before forwarding an expired bearer token.
|
|
61
72
|
*
|
|
62
73
|
* @defaultValue `'15m'`
|
|
63
74
|
*/
|
|
64
75
|
readonly refresh?: string;
|
|
65
76
|
/**
|
|
66
|
-
* Cookie domains for sharing
|
|
67
|
-
*
|
|
77
|
+
* Cookie domains for sharing one session across hostnames. Omit for a
|
|
78
|
+
* host-only cookie.
|
|
68
79
|
*/
|
|
69
80
|
readonly domains?: readonly string[];
|
|
70
81
|
/**
|
|
71
|
-
* Cookie path scope.
|
|
82
|
+
* Cookie path scope. Keep broad enough for every protected route that should
|
|
83
|
+
* send the session.
|
|
72
84
|
*
|
|
73
85
|
* @defaultValue `'/'`
|
|
74
86
|
*/
|
|
@@ -139,11 +151,15 @@ export type VisageDexExpiry = {
|
|
|
139
151
|
export type VisageDexUser = {
|
|
140
152
|
/**
|
|
141
153
|
* Email address used as the Dex login identifier.
|
|
154
|
+
*
|
|
155
|
+
* @defaultValue `'user@example.com'`
|
|
142
156
|
*/
|
|
143
157
|
readonly email: string;
|
|
144
158
|
/**
|
|
145
159
|
* Plain-text development password. Visage hashes this before rendering the
|
|
146
160
|
* Dex config.
|
|
161
|
+
*
|
|
162
|
+
* @defaultValue `'pass'`
|
|
147
163
|
*/
|
|
148
164
|
readonly password: string;
|
|
149
165
|
/**
|
|
@@ -254,13 +270,13 @@ export type VisageUpstream = {
|
|
|
254
270
|
/**
|
|
255
271
|
* URL scheme NGINX should use when proxying to this upstream.
|
|
256
272
|
*
|
|
257
|
-
* @defaultValue `'http'`
|
|
273
|
+
* @defaultValue `'https'` for external upstreams; `'http'` otherwise.
|
|
258
274
|
*/
|
|
259
275
|
readonly scheme?: 'http' | 'https';
|
|
260
276
|
/**
|
|
261
277
|
* Port NGINX should proxy to on {@link VisageUpstream.host}.
|
|
262
278
|
*
|
|
263
|
-
* @defaultValue `80`
|
|
279
|
+
* @defaultValue `80`, or `443` when {@link VisageUpstream.scheme} is `'https'`.
|
|
264
280
|
*/
|
|
265
281
|
readonly port?: number;
|
|
266
282
|
/**
|
|
@@ -304,7 +320,8 @@ export type VisageProxyPolicy = {
|
|
|
304
320
|
* Request headers to set when proxying to the upstream. Values may include
|
|
305
321
|
* NGINX variables. These are merged with Visage's default proxy headers:
|
|
306
322
|
* `Cookie`, `Host`, `X-Real-IP`, `X-Forwarded-For`, and
|
|
307
|
-
* `X-Forwarded-Proto`.
|
|
323
|
+
* `X-Forwarded-Proto`. `Host` defaults to the upstream host for top-level
|
|
324
|
+
* upstreams with no matching service, and to `$host` otherwise.
|
|
308
325
|
*/
|
|
309
326
|
readonly headers?: {
|
|
310
327
|
readonly [key: string]: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,wBAAwB,CAAC;IAC3D;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAClD;;OAEG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB;;WAEG;QACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QACpC;;WAEG;QACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QACnC;;WAEG;QACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;QACnC;;WAEG;QACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;KACjC,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAA;KAAE,CAAC;CACrE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE;QACd;;;;WAIG;QACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAC3B;;;;WAIG;QACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAC5B;;;;;WAKG;QACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACvD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blakearoberts/visage",
|
|
3
|
-
"version": "0.0.1-rc.
|
|
3
|
+
"version": "0.0.1-rc.8",
|
|
4
4
|
"description": "Vite plugin for local development with HMR and OIDC session cookie lifecycle semantics.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Blake Roberts",
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
},
|
|
15
15
|
"homepage": "https://github.com/blakearoberts/visage#readme",
|
|
16
16
|
"keywords": [
|
|
17
|
-
"
|
|
18
|
-
"plugin",
|
|
19
|
-
"oidc",
|
|
17
|
+
"authentication",
|
|
20
18
|
"hmr",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
19
|
+
"local-development",
|
|
20
|
+
"oauth2",
|
|
21
|
+
"oidc",
|
|
22
|
+
"pkce",
|
|
23
|
+
"session-cookie",
|
|
24
|
+
"vite",
|
|
25
|
+
"vite-plugin"
|
|
25
26
|
],
|
|
26
27
|
"main": "dist/index.js",
|
|
27
28
|
"types": "dist/index.d.ts",
|
|
@@ -44,11 +45,14 @@
|
|
|
44
45
|
"scripts": {
|
|
45
46
|
"build": "npm run clean && rollup -c",
|
|
46
47
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
47
|
-
"
|
|
48
|
+
"dev:example": "cd examples/managed-service && npm run dev",
|
|
49
|
+
"format": "prettier --write \"{docs,examples,src,test}/**/*.{ts,tsx,js,jsx,json,css,html,md}\" \"*.{json,md}\"",
|
|
50
|
+
"format:check": "prettier --check \"{docs,examples,src,test}/**/*.{ts,tsx,js,jsx,json,css,html,md}\" \"*.{json,md}\"",
|
|
51
|
+
"test": "npm run typecheck && npm run test:unit",
|
|
52
|
+
"test:all": "npm test && npm run test:e2e",
|
|
48
53
|
"test:e2e": "playwright test test/e2e",
|
|
49
54
|
"test:unit": "node --experimental-strip-types --test test/unit/*.test.ts",
|
|
50
|
-
"
|
|
51
|
-
"format:check": "prettier --check \"{docs,examples,src,test}/**/*.{ts,tsx,js,jsx,json,css,html,md}\" \"*.{json,md}\""
|
|
55
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.test.json"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
54
58
|
"@playwright/test": "^1.59.1",
|