fix(module-federation): remote proxies should use https when host is configured with ssl #27360 (#27381)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When the host uses SSL, the remote proxies are not created on a secure
server.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
When the host uses SSL, the remote proxies should be created on a secure
server

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #27360
This commit is contained in:
Colum Ferry 2024-08-12 20:05:49 +01:00 committed by GitHub
parent ef036b4a46
commit 010c6ec24c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 6 deletions

View File

@ -4,6 +4,8 @@ import type {
SchemaWithBrowserTarget, SchemaWithBrowserTarget,
SchemaWithBuildTarget, SchemaWithBuildTarget,
} from '../schema'; } from '../schema';
import { join } from 'path';
import { workspaceRoot } from '@nx/devkit';
export function normalizeOptions(schema: Schema): NormalizedSchema { export function normalizeOptions(schema: Schema): NormalizedSchema {
let buildTarget = (schema as SchemaWithBuildTarget).buildTarget; let buildTarget = (schema as SchemaWithBuildTarget).buildTarget;
@ -24,5 +26,7 @@ export function normalizeOptions(schema: Schema): NormalizedSchema {
liveReload: schema.liveReload ?? true, liveReload: schema.liveReload ?? true,
open: schema.open ?? false, open: schema.open ?? false,
ssl: schema.ssl ?? false, ssl: schema.ssl ?? false,
sslCert: schema.sslCert ? join(workspaceRoot, schema.sslCert) : undefined,
sslKey: schema.sslKey ? join(workspaceRoot, schema.sslKey) : undefined,
}; };
} }

View File

@ -156,7 +156,16 @@ export async function* moduleFederationDevServerExecutor(
options options
); );
startRemoteProxies(staticRemotesConfig, mappedLocationsOfStaticRemotes); startRemoteProxies(
staticRemotesConfig,
mappedLocationsOfStaticRemotes,
options.ssl
? {
pathToCert: options.sslCert,
pathToKey: options.sslKey,
}
: undefined
);
const removeBaseUrlEmission = (iter: AsyncIterable<unknown>) => const removeBaseUrlEmission = (iter: AsyncIterable<unknown>) =>
mapAsyncIterable(iter, (v) => ({ mapAsyncIterable(iter, (v) => ({

View File

@ -365,7 +365,16 @@ export default async function* moduleFederationDevServer(
options options
); );
startRemoteProxies(staticRemotesConfig, mappedLocationsOfStaticRemotes); startRemoteProxies(
staticRemotesConfig,
mappedLocationsOfStaticRemotes,
options.ssl
? {
pathToCert: join(workspaceRoot, options.sslCert),
pathToKey: join(workspaceRoot, options.sslKey),
}
: undefined
);
return yield* combineAsyncIterables( return yield* combineAsyncIterables(
currIter, currIter,

View File

@ -1,13 +1,33 @@
import type { Express } from 'express'; import type { Express } from 'express';
import { logger } from '@nx/devkit'; import { logger } from '@nx/devkit';
import { StaticRemotesConfig } from './parse-static-remotes-config'; import { StaticRemotesConfig } from './parse-static-remotes-config';
import { existsSync, readFileSync } from 'fs';
export function startRemoteProxies( export function startRemoteProxies(
staticRemotesConfig: StaticRemotesConfig, staticRemotesConfig: StaticRemotesConfig,
mappedLocationsOfRemotes: Record<string, string> mappedLocationsOfRemotes: Record<string, string>,
sslOptions?: { pathToCert: string; pathToKey: string }
) { ) {
const { createProxyMiddleware } = require('http-proxy-middleware'); const { createProxyMiddleware } = require('http-proxy-middleware');
const express = require('express'); const express = require('express');
let sslCert: Buffer;
let sslKey: Buffer;
if (sslOptions && sslOptions.pathToCert && sslOptions.pathToKey) {
if (existsSync(sslOptions.pathToCert) && existsSync(sslOptions.pathToKey)) {
sslCert = readFileSync(sslOptions.pathToCert);
sslKey = readFileSync(sslOptions.pathToKey);
} else {
logger.warn(
`Encountered SSL options in project.json, however, the certificate files do not exist in the filesystem. Using http.`
);
logger.warn(
`Attempted to find '${sslOptions.pathToCert}' and '${sslOptions.pathToKey}'.`
);
}
}
const http = require('http');
const https = require('https');
logger.info(`NX Starting static remotes proxies...`); logger.info(`NX Starting static remotes proxies...`);
for (const app of staticRemotesConfig.remotes) { for (const app of staticRemotesConfig.remotes) {
const expressProxy: Express = express(); const expressProxy: Express = express();
@ -15,11 +35,12 @@ export function startRemoteProxies(
createProxyMiddleware({ createProxyMiddleware({
target: mappedLocationsOfRemotes[app], target: mappedLocationsOfRemotes[app],
changeOrigin: true, changeOrigin: true,
secure: sslCert ? false : undefined,
}) })
); );
const proxyServer = expressProxy.listen( const proxyServer = (sslCert ? https : http)
staticRemotesConfig.config[app].port .createServer({ cert: sslCert, key: sslKey }, expressProxy)
); .listen(staticRemotesConfig.config[app].port);
process.on('SIGTERM', () => proxyServer.close()); process.on('SIGTERM', () => proxyServer.close());
process.on('exit', () => proxyServer.close()); process.on('exit', () => proxyServer.close());
} }