diff --git a/auth/arm-auth.js b/auth/arm-auth.js deleted file mode 100644 index dd4001e3d..000000000 --- a/auth/arm-auth.js +++ /dev/null @@ -1,41 +0,0 @@ -const { InteractiveBrowserCredential } = require('@azure/identity'); - -/** - * Gets authentication ARM token using interactive browser authentication - * @param {Object} options - Configuration options - * @param {string} [options.tenantId] - Optional tenant ID to override default tenant - * @param {string} [options.clientId] - Optional client ID for the application - * @returns {Promise} - Bearer token for portal.azure.com - */ -async function getArmToken(options = {}) { - try { - const credential = new InteractiveBrowserCredential({ - tenantId: options.tenantId, - clientId: options.clientId, - loginStyle: "popup" - }); - - console.log("Please sign in via the browser window that will open..."); - - // Get the token - this will open a browser window for authentication - const scope = "https://management.azure.com/user_impersonation"; - const response = await credential.getToken(scope); - - if (response && response.token) { - console.log("Successfully acquired token with expiration at:", (new Date(response.expiresOnTimestamp)).toLocaleString()); - - return `${response.tokenType} ${response.token}`; - } - else { - throw new Error("Failed to acquire token: Empty response"); - } - } - catch (error) { - console.error("Error acquiring portal token:", error.message); - throw error; - } -} - -module.exports = { - getArmToken -}; diff --git a/auth/authenticator.js b/auth/authenticator.js new file mode 100644 index 000000000..26ae4cfc6 --- /dev/null +++ b/auth/authenticator.js @@ -0,0 +1,47 @@ +const { + ClientSecretCredential, + InteractiveBrowserCredential, +} = require("@azure/identity"); + +// Options may include tenantId and clientId +async function getArmToken(options = {}) { + let credential; + + const clientId = options.clientId || process.env.AZURE_CLIENT_ID; + const tenantId = options.tenantId || process.env.AZURE_TENANT_ID; + const clientSecret = options.clientSecret || process.env.AZURE_CLIENT_SECRET; + + if (process.env.AZURE_CLIENT_SECRET) { + credential = new ClientSecretCredential( + tenantId, + clientId, + clientSecret + ); + } else { + // Use interactive browser authentication (developer/manual mode) + credential = new InteractiveBrowserCredential({ + tenantId: tenantId, + clientId: clientId, + loginStyle: "popup", + }); + console.log("Please sign in via the browser window that will open..."); + } + + // Request ARM token for the Management API + const scope = "https://management.azure.com/.default"; + const response = await credential.getToken(scope); + + if (response && response.token) { + console.log( + "Successfully acquired token with expiration at", + response.expiresOnTimestamp + ? new Date(response.expiresOnTimestamp).toLocaleString() + : "unknown" + ); + return `${response.tokenType} ${response.token}`; // Returns the actual token string + } else { + throw new Error("Failed to acquire token. Empty response."); + } +} + +module.exports = getArmToken; diff --git a/package.json b/package.json index c30ffc524..b98c8e685 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "test": "node node_modules/mocha/bin/_mocha -r mocha.js src/**/*.spec.ts", "deploy-function": "npm run build-function && cd dist/function && func azure functionapp publish < function app name >", "publish": "webpack --config webpack.publisher.js && node dist/publisher/index.js && npm run serve-website", - "publish-arm": "webpack --config webpack.publisher.arm.js && node dist/publisher/index.js && npm run serve-website", "serve-website": "webpack serve --open --static ./dist/website --no-stats", "build-mock-static-data": "webpack --config webpack.mockStaticData.js && node dist/publisher/index.js", "build-static-data": "webpack --config webpack.staticData.js && node dist/publisher/index.js", diff --git a/src/config.publish.json b/src/config.publish.json index e6f5d20b3..790ac8a87 100644 --- a/src/config.publish.json +++ b/src/config.publish.json @@ -1,6 +1,5 @@ { "environment": "publishing", - "isArmAuthEnabled": true, "subscriptionId": "< subscription ID >", "resourceGroupName": "< resource group name >", "serviceName": "< service name >" diff --git a/webpack.develop.js b/webpack.develop.js index 41ec0e3ae..fea0f4b8d 100644 --- a/webpack.develop.js +++ b/webpack.develop.js @@ -4,7 +4,7 @@ const { designerConfig, designerRuntimeConfig, } = require("./webpack.designer.js"); -const { getArmToken } = require("./auth/arm-auth"); +const getArmToken = require("./auth/authenticator"); module.exports = async (env) => { const armToken = await getArmToken({}); diff --git a/webpack.publisher.arm.js b/webpack.publisher.arm.js deleted file mode 100644 index db311e5f7..000000000 --- a/webpack.publisher.arm.js +++ /dev/null @@ -1,115 +0,0 @@ -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const runtimeConfig = require("./webpack.runtime"); -const { getArmToken } = require("./auth/arm-auth"); -const config = require("./src/config.publish.json"); - -const publisherRuntimeConfig = merge(runtimeConfig, { - entry: { "styles/theme": ["./src/themes/website/styles/styles.scss"] }, - output: { "path": path.resolve(__dirname, "dist/publisher/assets") } -}); - -async function generateWebpackConfig() { - const tokenOptions = {}; - if (config.tenantId) { - console.log(`Using tenantId: ${config.tenantId}`); - tokenOptions.tenantId = config.tenantId; - } - if (config.clientId) { - console.log(`Using clientId: ${config.clientId}`); - tokenOptions.clientId = config.clientId; - } - const armToken = await getArmToken(tokenOptions); - - const publisherConfig = { - mode: "development", - target: "node", - node: { - __dirname: false, - __filename: false, - }, - entry: { - "index": ["./src/startup.publish.ts"] - }, - output: { - filename: "./[name].js", - path: path.resolve(__dirname, "dist/publisher") - }, - module: { - rules: [ - { - test: /\.scss$/, - use: [ - MiniCssExtractPlugin.loader, - { loader: "css-loader", options: { url: false } }, - { loader: "postcss-loader" }, - { loader: "sass-loader" } - ] - }, - { - test: /\.tsx?$/, - loader: "ts-loader", - options: { - allowTsInNodeModules: true - } - }, - { - test: /\.html$/, - loader: "html-loader", - options: { - esModule: true, - sources: false, - minimize: { - removeComments: false, - collapseWhitespace: false - } - } - }, - { - test: /\.(png|woff|woff2|eot|ttf|svg)$/, - loader: "url-loader", - options: { - limit: 10000 - } - }, - { - test: /\.(raw|liquid)$/, - loader: "raw-loader" - } - ] - }, - plugins: [ - new webpack.IgnorePlugin({ resourceRegExp: /canvas/ }, { resourceRegExp: /jsdom$/ }), - new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css" }), - new CopyWebpackPlugin({ - patterns: [ - { from: `./src/config.publish.json`, to: `config.json` }, - { from: `./src/config.runtime.json`, to: `assets/config.json` }, - { from: `./templates/default.json`, to: "editors/templates/default.json" }, - { from: `./templates/default-old.json`, to: "editors/templates/default-old.json" } - ] - }), - new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }), - new webpack.DefinePlugin({ 'ARM_TOKEN': JSON.stringify(armToken) }) - ], - resolve: { - extensions: [".ts", ".tsx", ".js", ".jsx", ".html", ".scss"], - fallback: { - buffer: require.resolve("buffer"), - stream: require.resolve("stream-browserify"), - querystring: require.resolve("querystring-es3") - } - } - }; - - - return publisherConfig; -} - -module.exports = async () => { - const publisherConfig = await generateWebpackConfig(); - return [publisherConfig, publisherRuntimeConfig]; -}; \ No newline at end of file diff --git a/webpack.publisher.js b/webpack.publisher.js index 0f7a08470..3ad82ef31 100644 --- a/webpack.publisher.js +++ b/webpack.publisher.js @@ -4,7 +4,7 @@ const { merge } = require("webpack-merge"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const runtimeConfig = require("./webpack.runtime"); -const { getArmToken } = require("./auth/arm-auth"); +const getArmToken = require("./auth/authenticator"); const config = require("./src/config.publish.json"); const publisherRuntimeConfig = merge(runtimeConfig, {