0

Any idea on what can cause the following issue? We're trying to migrate to the official Cloud SQL Node.js Connector but for some reason I'm getting the following issue when running a test connection with the new config:

Support to node crypto module is required in node_modules/@google-cloud/cloud-sql-connector/src/node-crypto.ts:26:11

It's this bit in the package:

Object.defineProperty(exports, "__esModule", { value: true });
exports.cryptoModule = cryptoModule;
const errors_1 = require("./errors");
async function cryptoModule() {
    // check for availability of crypto module and throws an error otherwise
    // ref: https://nodejs.org/dist/latest-v18.x/docs/api/crypto.html#determining-if-crypto-support-is-unavailable
    let crypto;
    try {
        crypto = await import('node:crypto');
        /* c8 ignore next 6 */
    }
    catch (err) {
        throw new errors_1.CloudSQLConnectorError({
            message: 'Support to node crypto module is required',
            code: 'ENOCRYPTOMODULE',
        });
    }
    return crypto;
}
//# sourceMappingURL=node-crypto.js.map

We are running on Node v20

This is our webpack config:

const webpack = require("webpack");
const NodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");

let {
    TRAVIS_BRANCH,
    TRAVIS_COMMIT,
    TRAVIS_COMMIT_MESSAGE,
    TRAVIS_BUILD_NUMBER,
    TRAVIS_BUILD_ID,
} = process.env;

let buildInfo = {
    started: Date.now(),
    buildId: isNaN(parseInt(TRAVIS_BUILD_ID)) ? null : parseInt(TRAVIS_BUILD_ID),
    buildNumber: isNaN(parseInt(TRAVIS_BUILD_NUMBER))
        ? null
        : parseInt(TRAVIS_BUILD_NUMBER),
    commitMessage: TRAVIS_COMMIT_MESSAGE || null,
    commit: TRAVIS_COMMIT || null,
    branch: TRAVIS_BRANCH || "local",
};

module.exports = {
    mode: "production",
    entry: { index: "./index.js" },
    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    mangle: false, // <-- IMPORTANT, we use func.name for things
                },
            }),
        ],
    },
    output: {
        filename: "[name].js",
        libraryTarget: "commonjs",
        devtoolModuleFilenameTemplate: "[resource-path]",
    },
    target: "node",
    module: {
        rules: [
            {
                test: /\.(jsx?)$/,
                exclude: /node_modules/,
                use: ["swc-loader"],
            },
            {
                test: /\.(tsx?)$/,
                exclude: /node_modules/,
                use: {
                    loader: "swc-loader",
                    options: {
                        jsc: {
                            parser: {
                                syntax: "typescript",
                            },
                        },
                    },
                },
            },
        ],
    },
    resolve: {
        extensions: [".js", ".ts", ".json"],
        alias: {
            "@Api": path.resolve(process.cwd(), "src/api"),
            "@Models": path.resolve(process.cwd(), "src/api/models"),
            "@Types": path.resolve(process.cwd(), "src/api/types"),
            "@Consts": path.resolve(process.cwd(), "src/api/consts"),
            "@Utils": path.resolve(process.cwd(), "src/api/utils"),
            "@Functions": path.resolve(process.cwd(), "src/functions"),
        },
    },
    devtool: "source-map",
    plugins: [
        new webpack.BannerPlugin({
            raw: true,
            banner: "require('source-map-support').install();",
        }),
        new webpack.DefinePlugin({
            "process.env.BUILD_INFO": JSON.stringify(buildInfo),
        }),
        new CopyWebpackPlugin({
            patterns: [{ from: "package.json" }],
        }),
    ],
    externals: [NodeExternals()],
};

And this is where it fails:

console.log("[sql-connector] crypto available:", typeof require("crypto"));
console.log("[sql-connector] connector loaded from:", require.resolve("@google-cloud/cloud-sql-connector"));

        const clientOpts = await connector.getOptions({
            instanceConnectionName: config.connect.cloudConnectionName,
            authType: AuthTypes.IAM,
            ipType: IpAddressTypes.PRIVATE, 
        });

Crpyto is available at the time of the logs and connector is properly loaded from: @google-cloud/cloud-sql-connector

I've tried:

  • using different auth / ip types
  • Checked the format of cloudConnectionName which matches the required format of: my-project:europe-west1:db-name
  • Tried setting a fallback on the crypto dependency to avoid polyfills like:
fallback: {
 crypto: false,
},

//and also in externals
externals: [NodeExternals(), {crypto: false}],
  • checked that the target is "node"

I want to avoid patching this package by updating the import to the commonJs require format and using npx patch-package

3
  • Can you provide more information, like what environment do you have Node running in? I know in embedded systems or highly constrained environments, a custom build or a different JS runtime might be used, potentially without the crypto module. Commented Apr 4 at 20:27
  • 1
    Consider opening an issue on GitHub: github.com/GoogleCloudPlatform/cloud-sql-nodejs-connector. I know the team would be interested to hear about this. Commented Apr 7 at 15:14
  • @rasulfahad I'm running this locally with SWC as the transpiler. We do use nodemon but thats it. Just trying to establish the remote connnection locally atm. The package.json script basically runs a webpack build like: webpack --config ./webpack/webpack.config.js && webpack --config ./webpack/webpack.api.config.js --watch Commented Apr 8 at 9:35

2 Answers 2

0

It seems like Webpack is ignoring or blocking access to the crypto module which is why Connector can’t use it for encryption, thus receiving that error. Basically externals prevent bundling of dependencies but will retrieve them at runtime. Try removing {crypto: false} in externals in your Webpack config. According to this documentation, externals: [NodeExternals()], will ignore all modules in the node_modules folder.

Sign up to request clarification or add additional context in comments.

2 Comments

Let me know if this has resolved your issue. If it did, an upvote or marking it as accepted would be appreciated as this helps the community.
Hey, by default the config didn't have {crypto: false} in externals. I just showed how I applied fallbacks and tried to avoid polyfills by adding them. So this won't solve the issue unfortunately
0

Thank you for reporting the issue. This seems like either a webpack configuration issue or an unexpected difference between your local dev environment and the remote runtime environment.

I created PR #436 to make this easier to troubleshoot. This will report the underlying error caused by import('node:crypto'). I hope this helps you get to the bottom of the issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.