diff --git a/package-lock.json b/package-lock.json index a88c4870..1d644af7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,29 +11,29 @@ "license": "MIT", "dependencies": { "@drunk-pulumi/azure-providers": "^0.0.24", - "@pulumi/azure-native": "^2.47.1", - "@pulumi/azuread": "5.52.0", - "@pulumi/pulumi": "^3.121.0", - "@pulumi/random": "^4.16.2", - "@pulumi/tls": "^5.0.3", + "@pulumi/azure-native": "^2.48.0", + "@pulumi/azuread": "5.53.1", + "@pulumi/pulumi": "^3.122.0", + "@pulumi/random": "^4.16.3", + "@pulumi/tls": "^5.0.4", "axios": "^1.7.2", "netmask": "^2.0.2", "node-forge": "^1.3.1", "to-words": "^4.0.1", - "xml-formatter": "^3.6.2" + "xml-formatter": "^3.6.3" }, "devDependencies": { "@types/chai": "^4.3.16", "@types/mocha": "^10.0.7", "@types/netmask": "^2.0.5", - "@types/node": "^20.14.9", + "@types/node": "^20.14.10", "@types/node-forge": "^1.3.11", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "chai": "^5.1.1", "cpy-cli": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "eslint-plugin-deprecation": "^3.0.0", "husky": "^9.0.11", "lint-staged": "^15.2.7", @@ -41,7 +41,7 @@ "nyc": "^17.0.0", "replace-in-file": "7.2.0", "ts-node": "^10.9.2", - "typescript": "^5.5.2" + "typescript": "^5.5.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -885,15 +885,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", - "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", + "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -941,9 +941,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, "license": "MIT", "engines": { @@ -2013,26 +2013,27 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@pulumi/azure-native": { - "version": "2.47.1", - "resolved": "https://registry.npmjs.org/@pulumi/azure-native/-/azure-native-2.47.1.tgz", - "integrity": "sha512-8orrRkg4ldbuj1xpQP0DdBoH0mjhkva8o1ChJztbbOPkd6UdlVe6IU0qIHJPhJxTdMJ0Mr7KqsWqUgx78/4nig==", + "version": "2.48.0", + "resolved": "https://registry.npmjs.org/@pulumi/azure-native/-/azure-native-2.48.0.tgz", + "integrity": "sha512-HrnpQX9JmcnbECwpGpgKqao0ygE/3Nxfc/0p8ch1ka8rGmO9jxDdOf74IxnIi/cdyE7iH391Qoo0Qoeoopcbeg==", + "license": "Apache-2.0", "dependencies": { "@pulumi/pulumi": "^3.0.0" } }, "node_modules/@pulumi/azuread": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@pulumi/azuread/-/azuread-5.52.0.tgz", - "integrity": "sha512-OsziFk2F8Z7DsSCK7LaMXa1tldcqK/xgyNxdb5DYTjYTVM7TJw7MlbYen+ylukUSFoRj8RW3O+jb2fadqe7L6g==", + "version": "5.53.1", + "resolved": "https://registry.npmjs.org/@pulumi/azuread/-/azuread-5.53.1.tgz", + "integrity": "sha512-bChNTeOsCjLdiDlaUXCvjSfHBGGjKPPN5rvkyPJsv4Kn5ZMVrj6XKm1ZZHi5RT4oNy9MigpOcdHr5pVH7tGN5A==", "license": "Apache-2.0", "dependencies": { "@pulumi/pulumi": "^3.0.0" } }, "node_modules/@pulumi/pulumi": { - "version": "3.121.0", - "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.121.0.tgz", - "integrity": "sha512-fv9sY1e7nPeGpvlHIMZcErHeZAsbdqOi0Jcb1oxi0NvTU3jy1EZa70q+JdE0dmqYlr43HaSL8SU5+G0/S08wGA==", + "version": "3.122.0", + "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.122.0.tgz", + "integrity": "sha512-+EXWVJVLL+s2ianhZ4LxgNA9zt4hfgamnuwPr6qW0eBlk5gr906xSQgw4zdk8CIiAW+VT16TfxXk49Vj1BpBrw==", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.10.1", @@ -2128,17 +2129,19 @@ "integrity": "sha512-xfo+yLRM2zVjVEA4p23IjQWzyWl1ZhWOGobsBqRpIarzLvwNH/RAGaoehdxlhx4X92302DrpdIFgTICMN4P38w==" }, "node_modules/@pulumi/random": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@pulumi/random/-/random-4.16.2.tgz", - "integrity": "sha512-jBYLrb2Bfh5WbmhyqTHVGYIOkckRQefDgBgvwdMF6i0NzboOizmjEj6MdN5RyibVMtWN3b7Y0kwKeE8uPIq3qQ==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/@pulumi/random/-/random-4.16.3.tgz", + "integrity": "sha512-B1cB3RAxC/Ic6g7Rj6bJv+wJJOBR2xorWOTSSTxjr0f10KdoQxLc+vzMu11MMgOzThhL4n7n8ZSLADxc7Rzk/g==", + "license": "Apache-2.0", "dependencies": { "@pulumi/pulumi": "^3.0.0" } }, "node_modules/@pulumi/tls": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@pulumi/tls/-/tls-5.0.3.tgz", - "integrity": "sha512-29NyJnkIDqftK4wA5V5zu/KSkiYXeSEXOgqoaxz37V8Lw8E29iww4fSogjIV5gDJ1pe6/2Q67pmE4BLB6U1qjA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@pulumi/tls/-/tls-5.0.4.tgz", + "integrity": "sha512-9rc0nwclPdtbz9dulKlt5Ki62RXSrTMGjh2OzviMKwP5zAUMmusBX5Y8T/f3z+nhM1XwEexlwi1/j1+UbkO8mw==", + "license": "Apache-2.0", "dependencies": { "@pulumi/pulumi": "^3.0.0" } @@ -2345,9 +2348,10 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", - "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -2375,16 +2379,17 @@ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", - "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz", + "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/type-utils": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/type-utils": "7.15.0", + "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2408,13 +2413,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", + "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2425,13 +2431,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", - "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz", + "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/utils": "7.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2452,10 +2459,11 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", + "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -2465,13 +2473,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", + "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2493,15 +2502,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", - "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz", + "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1" + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2515,12 +2525,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", + "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/types": "7.15.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2536,6 +2547,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2545,6 +2557,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2556,15 +2569,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz", + "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4" }, "engines": { @@ -2584,13 +2598,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz", + "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2601,10 +2616,11 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz", + "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -2614,13 +2630,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz", + "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2642,12 +2659,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz", + "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/types": "7.15.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2663,6 +2681,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2672,6 +2691,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2796,10 +2816,11 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "devOptional": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -3968,17 +3989,17 @@ } }, "node_modules/eslint": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", - "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.16.0", + "@eslint/config-array": "^0.17.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.5.0", + "@eslint/js": "9.6.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -3989,7 +4010,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.0.1", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", + "espree": "^10.1.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4097,12 +4118,13 @@ } }, "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" }, @@ -8663,9 +8685,9 @@ } }, "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -8958,22 +8980,24 @@ } }, "node_modules/xml-formatter": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.6.2.tgz", - "integrity": "sha512-enWhevZNOwffZFUhzl1WMcha8lFLZUgJ7NzFs5Ug4ZOFCoNheGYXz1J9Iz/e+cTn9rCkuT1GwTacz+YlmFHOGw==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.6.3.tgz", + "integrity": "sha512-++x1TlRO1FRlQ82AZ4WnoCSufaI/PT/sycn4K8nRl4gnrNC1uYY2VV/67aALZ2m0Q4Q/BLj/L69K360Itw9NNg==", + "license": "MIT", "dependencies": { - "xml-parser-xo": "^4.1.0" + "xml-parser-xo": "^4.1.2" }, "engines": { - "node": ">= 14" + "node": ">= 16" } }, "node_modules/xml-parser-xo": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.1.tgz", - "integrity": "sha512-Ggf2y90+Y6e9IK5hoPuembVHJ03PhDSdhldEmgzbihzu9k0XBo0sfcFxaSi4W1PlUSSI1ok+MJ0JCXUn+U4Ilw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.2.tgz", + "integrity": "sha512-Z/DRB0ZAKj5vAQg++XsfQQKfT73Vfj5n5lKIVXobBDQEva6NHWUTxOA6OohJmEcpoy8AEqBmSGkXXAnFwt5qAA==", + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 16" } }, "node_modules/y18n": { diff --git a/package.json b/package.json index 4ed8a59a..8134a15f 100644 --- a/package.json +++ b/package.json @@ -43,14 +43,14 @@ "@types/chai": "^4.3.16", "@types/mocha": "^10.0.7", "@types/netmask": "^2.0.5", - "@types/node": "^20.14.9", + "@types/node": "^20.14.10", "@types/node-forge": "^1.3.11", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "chai": "^5.1.1", "cpy-cli": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "eslint-plugin-deprecation": "^3.0.0", "husky": "^9.0.11", "lint-staged": "^15.2.7", @@ -58,20 +58,20 @@ "nyc": "^17.0.0", "replace-in-file": "7.2.0", "ts-node": "^10.9.2", - "typescript": "^5.5.2" + "typescript": "^5.5.3" }, "dependencies": { "@drunk-pulumi/azure-providers": "^0.0.24", - "@pulumi/azure-native": "^2.47.1", - "@pulumi/azuread": "5.52.0", - "@pulumi/pulumi": "^3.121.0", - "@pulumi/random": "^4.16.2", - "@pulumi/tls": "^5.0.3", + "@pulumi/azure-native": "^2.48.0", + "@pulumi/azuread": "5.53.1", + "@pulumi/pulumi": "^3.122.0", + "@pulumi/random": "^4.16.3", + "@pulumi/tls": "^5.0.4", "axios": "^1.7.2", "netmask": "^2.0.2", "node-forge": "^1.3.1", "to-words": "^4.0.1", - "xml-formatter": "^3.6.2" + "xml-formatter": "^3.6.3" }, "husky": { "hooks": { diff --git a/src/Aks/Helper.ts b/src/Aks/Helper.ts index 71f69b61..7c073bc6 100644 --- a/src/Aks/Helper.ts +++ b/src/Aks/Helper.ts @@ -1,9 +1,9 @@ -import * as containerservice from "@pulumi/azure-native/containerservice"; -import { getAksName, getResourceGroupName } from "../Common/Naming"; -import { KeyVaultInfo, ResourceInfo, ResourceType } from "../types"; -import { getSecret } from "../KeyVault/Helper"; -import { interpolate, Output } from "@pulumi/pulumi"; -import { currentRegionName, subscriptionId } from "../Common/AzureEnv"; +import * as containerservice from '@pulumi/azure-native/containerservice'; +import { getAksName, getResourceGroupName } from '../Common/Naming'; +import { KeyVaultInfo, ResourceInfo, ResourceType } from '../types'; +import { getSecret } from '../KeyVault/Helper'; +import { interpolate, Output } from '@pulumi/pulumi'; +import { currentRegionName, subscriptionId } from '../Common/AzureEnv'; /** Get AKS Config from Managed Cluster*/ export const getAksConfig = async ({ @@ -30,7 +30,7 @@ export const getAksConfig = async ({ resourceGroupName: group, }); - return Buffer.from(aks.kubeconfigs[0].value, "base64").toString("utf8"); + return Buffer.from(aks.kubeconfigs[0].value, 'base64').toString('utf8'); }; /** Get AKS Config from Key Vault*/ @@ -52,7 +52,7 @@ export const getAksVaultConfig = async ({ vaultInfo, nameFormatted: false, }); - return rs?.value || ""; + return rs?.value || ''; }; export const getAksPrivateDnz = ({ @@ -70,11 +70,11 @@ export const getAksPrivateDnz = ({ return aks.apply((a) => { if (!a.privateFQDN) return undefined; - const dnsName = a.privateFQDN.split(":").slice(1).join("."); + const dnsName = a.privateFQDN.split(':').slice(1).join('.'); const rsGroup = a.nodeResourceGroup!; return { - resourceName: dnsName, + name: dnsName, group: { resourceGroupName: rsGroup, location: currentRegionName }, id: interpolate`/subscriptions/${subscriptionId}/resourceGroups/${rsGroup}/providers/Microsoft.Network/privateDnsZones/${dnsName}`, } as ResourceInfo; diff --git a/src/Aks/Identity.ts b/src/Aks/Identity.ts index a10dcbbb..ddcfc136 100644 --- a/src/Aks/Identity.ts +++ b/src/Aks/Identity.ts @@ -1,22 +1,22 @@ -import { getGraphPermissions } from "../AzAd/GraphDefinition"; -import identityCreator from "../AzAd/Identity"; -import { BasicArgs, KeyVaultInfo } from "../types"; -import { roleAssignment } from "../AzAd/RoleAssignment"; -import { defaultScope } from "../Common/AzureEnv"; +import { getGraphPermissions } from '../AzAd/GraphDefinition'; +import identityCreator from '../AzAd/Identity'; +import { BasicArgs, KeyVaultInfo } from '../types'; +import { roleAssignment } from '../AzAd/RoleAssignment'; +import { defaultScope } from '../Common/AzureEnv'; interface Props extends BasicArgs { name: string; - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; } //** The AzAD app Identity for Azure Kubernetes for RBAC */ export default ({ name, vaultInfo, dependsOn }: Props) => { //AKS need this permission for AAD integration const graphAccess = getGraphPermissions( - { name: "User.Read", type: "Scope" }, - { name: "Group.Read.All", type: "Scope" }, + { name: 'User.Read', type: 'Scope' }, + { name: 'Group.Read.All', type: 'Scope' }, //{ name: 'Directory.Read.All', type: 'Scope' }, - { name: "Directory.Read.All", type: "Role" }, + { name: 'Directory.Read.All', type: 'Role' }, ); const serverIdentity = identityCreator({ @@ -25,7 +25,7 @@ export default ({ name, vaultInfo, dependsOn }: Props) => { createPrincipal: true, requiredResourceAccesses: [graphAccess], publicClient: false, - appType: "api", + appType: 'api', vaultInfo, dependsOn, }); @@ -33,8 +33,8 @@ export default ({ name, vaultInfo, dependsOn }: Props) => { roleAssignment({ name: `${name}-aks-identity-acr-pull`, principalId: serverIdentity.principalId!, - principalType: "ServicePrincipal", - roleName: "AcrPull", + principalType: 'ServicePrincipal', + roleName: 'AcrPull', scope: defaultScope, dependsOn: serverIdentity.resource, }); diff --git a/src/Aks/VmSetMonitor/index.ts b/src/Aks/VmSetMonitor/index.ts index 5bc8012d..c222f7ec 100644 --- a/src/Aks/VmSetMonitor/index.ts +++ b/src/Aks/VmSetMonitor/index.ts @@ -2,7 +2,7 @@ import * as native from '@pulumi/azure-native'; import { findVMScaleSet } from '../../Core/Helper'; import * as fs from 'fs'; import { BasicMonitorArgs, KeyVaultInfo, ResourceGroupInfo } from '../../types'; -import { Input, all, Resource } from '@pulumi/pulumi'; +import { all, Input, Resource } from '@pulumi/pulumi'; import { replaceAll } from '../../Common/Helpers'; import { getLogWpSecretsById } from '../../Logs/Helpers'; import { getAccountSAS, getStorageSecretsById } from '../../Storage/Helper'; @@ -46,7 +46,7 @@ export default ({ settings = replaceAll( settings, '__DIAGNOSTIC_STORAGE_ACCOUNT__', - logStorage.info!.name + logStorage.info!.name, ); settings = replaceAll(settings, '__VM_OR_VMSS_RESOURCE_ID__', vm.id); @@ -66,13 +66,13 @@ export default ({ protectedSettings: `{ "storageAccountName": "${logStorage.info!.name}", "storageAccountSasToken": "${logSAS.accountSasToken.substring( - logSAS.accountSasToken.indexOf('?') + 1 + logSAS.accountSasToken.indexOf('?') + 1, )}" }`, settings, }, //Ignore changes on this field as API never returns it back - { ignoreChanges: ['protectedSettings'], dependsOn } + { ignoreChanges: ['protectedSettings'], dependsOn }, ); const oms = new native.compute.VirtualMachineScaleSetExtension( @@ -94,7 +94,7 @@ export default ({ settings: `{"workspaceId": "${logWp.info!.id}"}`, }, //Ignore changes on this field as API never returns it back - { ignoreChanges: ['protectedSettings'], dependsOn } + { ignoreChanges: ['protectedSettings'], dependsOn }, ); return { diag, oms }; diff --git a/src/Aks/index.ts b/src/Aks/index.ts index 28a19d86..0317dbe7 100644 --- a/src/Aks/index.ts +++ b/src/Aks/index.ts @@ -8,8 +8,8 @@ import { defaultScope, Environments, getResourceIdFromInfo, - parseResourceInfoFromId, isPrd, + parseResourceInfoFromId, tenantId, } from '../Common/AzureEnv'; import Locker from '../Core/Locker'; @@ -130,7 +130,7 @@ export type AskFeatureProps = { }; export type AksAccessProps = { - envRoles: EnvRolesResults; + envRoles?: EnvRolesResults; authorizedIPRanges?: Input[]; disableLocalAccounts?: boolean; }; @@ -168,7 +168,7 @@ export interface AksProps extends BasicResourceArgs { //kubernetesVersion?: Input; nodePools?: Array; - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; logWpId?: Input; /**Lock resource from delete*/ lock?: boolean; @@ -178,7 +178,7 @@ export type AksResults = ResourceInfo & { serviceIdentity: IdentityResult; aks: ManagedCluster; disableLocalAccounts?: boolean; - getKubeConfig: () => Output; + getKubeConfig: () => Output | undefined; }; //Using this to enable the preview feature https://azurecloudai.blog/2019/10/16/aks-enabling-and-using-preview-features-such-as-nodepools-using-cli/ @@ -211,7 +211,7 @@ export default async ({ const nodeResourceGroup = getResourceGroupName(`${aksName}-nodes`); //Auto detect and disable Local Account - if (aksAccess.disableLocalAccounts === undefined) { + if (aksAccess.disableLocalAccounts === undefined && vaultInfo) { aksAccess.disableLocalAccounts = await getKeyVaultBase(vaultInfo.name) .checkSecretExist(secretName) .catch(() => false); @@ -401,12 +401,14 @@ export default async ({ }, disableLocalAccounts: Boolean(aksAccess.disableLocalAccounts), enableRBAC: true, - aadProfile: { - enableAzureRBAC: true, - managed: true, - adminGroupObjectIDs: [aksAccess.envRoles.admin.objectId], - tenantID: tenantId, - }, + aadProfile: aksAccess.envRoles + ? { + enableAzureRBAC: true, + managed: true, + adminGroupObjectIDs: [aksAccess.envRoles.admin.objectId], + tenantID: tenantId, + } + : undefined, oidcIssuerProfile: { enabled: false }, storageProfile: { blobCSIDriver: { @@ -529,13 +531,15 @@ export default async ({ scope: acrScope, }); - addCustomSecret({ - name: `${name}-identity-clientId`, - value: identityProfile['kubeletidentity'].clientId!, - dependsOn: aks, - contentType: name, - vaultInfo, - }); + if (vaultInfo) { + addCustomSecret({ + name: `${name}-identity-clientId`, + value: identityProfile['kubeletidentity'].clientId!, + dependsOn: aks, + contentType: name, + vaultInfo, + }); + } } if (network.subnetId && identity) { @@ -559,16 +563,18 @@ export default async ({ disableLocalAccounts: aksAccess.disableLocalAccounts, }); - addCustomSecret({ - name: secretName, - value: config, - formattedName: true, - dependsOn: aks, - contentType: aksAccess.disableLocalAccounts - ? `${name}-UserCredentials` - : `${name}-AdminCredentials`, - vaultInfo, - }); + if (vaultInfo) { + addCustomSecret({ + name: secretName, + value: config, + formattedName: true, + dependsOn: aks, + contentType: aksAccess.disableLocalAccounts + ? `${name}-UserCredentials` + : `${name}-AdminCredentials`, + vaultInfo, + }); + } //Diagnostic if (features.enableDiagnosticSetting && logWpId) { @@ -587,27 +593,31 @@ export default async ({ dependsOn: aks, }); - //Apply monitoring for VMScale Sets - vmsDiagnostic({ - group: { resourceGroupName: nodeResourceGroup }, - logWpId, - vaultInfo, - dependsOn: aks, - }); + if (vaultInfo) { + //Apply monitoring for VMScale Sets + vmsDiagnostic({ + group: { resourceGroupName: nodeResourceGroup }, + logWpId, + vaultInfo, + dependsOn: aks, + }); + } } }); return { - resourceName: name, + name, group, id: aks.id, aks, serviceIdentity, - getKubeConfig: (): Output => - output( - getKeyVaultBase(vaultInfo.name) - .getSecret(secretName) - .then((s) => s!.value!), - ), + getKubeConfig: (): Output | undefined => + vaultInfo + ? output( + getKeyVaultBase(vaultInfo.name) + .getSecret(secretName) + .then((s) => s!.value!), + ) + : undefined, }; }; diff --git a/src/Apim/Helpers.ts b/src/Apim/Helpers.ts index 8f07352a..3f844759 100644 --- a/src/Apim/Helpers.ts +++ b/src/Apim/Helpers.ts @@ -1,7 +1,7 @@ -import { ResourceInfo } from "../types"; -import { getApimName, getResourceGroupName } from "../Common/Naming"; -import { interpolate } from "@pulumi/pulumi"; -import { currentRegionName, subscriptionId } from "../Common/AzureEnv"; +import { ResourceInfo } from '../types'; +import { getApimName, getResourceGroupName } from '../Common/Naming'; +import { interpolate } from '@pulumi/pulumi'; +import { currentRegionName, subscriptionId } from '../Common/AzureEnv'; export const getApimInfo = (nameAndGroup: string): ResourceInfo => { const name = getApimName(nameAndGroup); @@ -9,7 +9,7 @@ export const getApimInfo = (nameAndGroup: string): ResourceInfo => { const id = interpolate`/subscriptions/${subscriptionId}/resourceGroups/${rgName}/providers/Microsoft.ApiManagement/service/${name}`; return { - resourceName: name, + name, group: { resourceGroupName: rgName, location: currentRegionName }, id, }; diff --git a/src/AzAd/Identity.ts b/src/AzAd/Identity.ts index 8dd5dc12..9bd3847b 100644 --- a/src/AzAd/Identity.ts +++ b/src/AzAd/Identity.ts @@ -1,17 +1,17 @@ -import * as azureAD from "@pulumi/azuread"; -import { ServicePrincipal } from "@pulumi/azuread"; -import * as pulumi from "@pulumi/pulumi"; -import { Output } from "@pulumi/pulumi"; -import { getIdentityName } from "../Common/Naming"; +import * as azureAD from '@pulumi/azuread'; +import { ServicePrincipal } from '@pulumi/azuread'; +import * as pulumi from '@pulumi/pulumi'; +import { Output } from '@pulumi/pulumi'; +import { getIdentityName } from '../Common'; import { ApplicationApiOauth2PermissionScope, ApplicationAppRole, - ApplicationRequiredResourceAccess, ApplicationOptionalClaims, -} from "@pulumi/azuread/types/input"; -import { BasicArgs, IdentityRoleAssignment, KeyVaultInfo } from "../types"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { getIdentitySecretNames, grantIdentityPermissions } from "./Helper"; + ApplicationRequiredResourceAccess, +} from '@pulumi/azuread/types/input'; +import { BasicArgs, IdentityRoleAssignment, KeyVaultInfo } from '../types'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { getIdentitySecretNames, grantIdentityPermissions } from './Helper'; type PreAuthApplicationProps = { appId: string; @@ -27,7 +27,7 @@ interface IdentityProps extends BasicArgs, IdentityRoleAssignment { publicClient?: boolean; createPrincipal?: boolean; replyUrls?: pulumi.Input[]>; - appType?: "spa" | "web" | "api"; + appType?: 'spa' | 'web' | 'api'; allowMultiOrg?: boolean; appRoles?: pulumi.Input[]>; oauth2Permissions?: pulumi.Input< @@ -39,7 +39,7 @@ interface IdentityProps extends BasicArgs, IdentityRoleAssignment { pulumi.Input[] >; optionalClaims?: pulumi.Input; - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; } export type IdentityResult = { @@ -58,7 +58,7 @@ export default ({ createClientSecret = false, createPrincipal = false, replyUrls, - appType = "spa", + appType = 'spa', allowMultiOrg = false, appRoles, appRoleAssignmentRequired, @@ -87,21 +87,21 @@ export default ({ owners, appRoles, - signInAudience: allowMultiOrg ? "AzureADMultipleOrgs" : "AzureADMyOrg", - groupMembershipClaims: ["SecurityGroup"], + signInAudience: allowMultiOrg ? 'AzureADMultipleOrgs' : 'AzureADMyOrg', + groupMembershipClaims: ['SecurityGroup'], identifierUris, publicClient: publicClient ? { redirectUris: replyUrls } : undefined, singlePageApplication: - appType === "spa" + appType === 'spa' ? { redirectUris: replyUrls, } : undefined, web: - appType === "web" + appType === 'web' ? { redirectUris: replyUrls, implicitGrant: { @@ -112,7 +112,7 @@ export default ({ : undefined, api: - appType === "api" + appType === 'api' ? { oauth2PermissionScopes: oauth2Permissions, mappedClaimsEnabled: true, @@ -131,19 +131,21 @@ export default ({ { dependsOn }, ); - addCustomSecret({ - name: secretNames.objectIdName, - value: app.objectId, - vaultInfo, - contentType: "Identity", - }); + if (vaultInfo) { + addCustomSecret({ + name: secretNames.objectIdName, + value: app.objectId, + vaultInfo, + contentType: 'Identity', + }); - addCustomSecret({ - name: secretNames.clientIdKeyName, - value: app.clientId, - vaultInfo, - contentType: "Identity", - }); + addCustomSecret({ + name: secretNames.clientIdKeyName, + value: app.clientId, + vaultInfo, + contentType: 'Identity', + }); + } let clientSecret: Output | undefined = undefined; if (createClientSecret) { @@ -152,17 +154,19 @@ export default ({ { displayName: name, applicationId: app.id, - endDateRelative: "43800h", + endDateRelative: '43800h', }, - { ignoreChanges: ["applicationId", "applicationObjectId"] }, + { ignoreChanges: ['applicationId', 'applicationObjectId'] }, ).value; - addCustomSecret({ - name: secretNames.clientSecretKeyName, - value: clientSecret, - vaultInfo, - contentType: "Identity", - }); + if (vaultInfo) { + addCustomSecret({ + name: secretNames.clientSecretKeyName, + value: clientSecret, + vaultInfo, + contentType: 'Identity', + }); + } } let principal: ServicePrincipal | undefined; @@ -176,13 +180,13 @@ export default ({ appRoleAssignmentRequired, clientId: app.clientId, }, - { ignoreChanges: ["clientId", "applicationId"] }, + { ignoreChanges: ['clientId', 'applicationId'] }, ); principalSecret = new azureAD.ServicePrincipalPassword(name, { displayName: name, servicePrincipalId: principal.objectId, - endDateRelative: "43800h", + endDateRelative: '43800h', //value: randomPassword({ name: `${name}-principalSecret` }).result, }).value; @@ -194,19 +198,21 @@ export default ({ principalId: principal.objectId, }); - addCustomSecret({ - name: secretNames.principalIdKeyName, - value: principal.objectId, - vaultInfo, - contentType: "Identity", - }); - - addCustomSecret({ - name: secretNames.principalSecretKeyName, - value: principalSecret, - vaultInfo, - contentType: "Identity", - }); + if (vaultInfo) { + addCustomSecret({ + name: secretNames.principalIdKeyName, + value: principal.objectId, + vaultInfo, + contentType: 'Identity', + }); + + addCustomSecret({ + name: secretNames.principalSecretKeyName, + value: principalSecret, + vaultInfo, + contentType: 'Identity', + }); + } } return { diff --git a/src/Builder/AksBuilder.ts b/src/Builder/AksBuilder.ts index 9ed96c8e..f0f62b3c 100644 --- a/src/Builder/AksBuilder.ts +++ b/src/Builder/AksBuilder.ts @@ -1,23 +1,23 @@ import { AksImportProps, + BuilderAsync, + BuilderProps, IAksBuilder, IAksDefaultNodePoolBuilder, IAksNetworkBuilder, ISshBuilder, - BuilderAsync, SshBuilderProps, - BuilderProps, } from './types'; import { generateSsh, SshResults } from '../Core/KeyGenerators'; import { ManagedClusterSKUTier } from '@pulumi/azure-native/containerservice'; import Aks, { + AksAccessProps, + AksNetworkProps, AksNodePoolProps, + AksResults, AskAddonProps, AskFeatureProps, - AksAccessProps, - AksNetworkProps, DefaultAksNodePoolProps, - AksResults, } from '../Aks'; class AksBuilder @@ -87,9 +87,14 @@ class AksBuilder } //Build Methods private buildSsh() { + const vaultInfo = this.commonProps.vaultInfo; + if (!vaultInfo) + throw new Error(`${this.commonProps.name} requires vaultInfo.`); + this._sshInstance = generateSsh({ ...this.commonProps, ...this._sshProps, + vaultInfo, }); } diff --git a/src/Builder/ApimApiBuilder.ts b/src/Builder/ApimApiBuilder.ts index c54dec92..871fab96 100644 --- a/src/Builder/ApimApiBuilder.ts +++ b/src/Builder/ApimApiBuilder.ts @@ -1,23 +1,23 @@ -import * as apim from "@pulumi/azure-native/apimanagement"; -import { enums } from "@pulumi/azure-native/types"; -import { Input, interpolate } from "@pulumi/pulumi"; -import { getImportConfig } from "../Apim/ApiProduct/SwaggerHelper"; -import { organization } from "../Common/StackEnv"; -import { ResourceInfo } from "../types"; -import ApimPolicyBuilder from "./ApimPolicyBuilder"; +import * as apim from '@pulumi/azure-native/apimanagement'; +import { enums } from '@pulumi/azure-native/types'; +import { Input, interpolate } from '@pulumi/pulumi'; +import { getImportConfig } from '../Apim/ApiProduct/SwaggerHelper'; +import { organization } from '../Common/StackEnv'; +import { ResourceInfo } from '../types'; +import ApimPolicyBuilder from './ApimPolicyBuilder'; import { ApimApiKeysType, + ApimApiPolicyType, + ApimApiRevisionProps, ApimApiServiceUrlType, ApimChildBuilderProps, - IApimApiBuilder, - IApimApiServiceBuilder, - ApimApiRevisionProps, BuilderAsync, + IApimApiBuilder, IApimApiRevisionBuilder, + IApimApiServiceBuilder, VersionBuilderFunction, - ApimApiPolicyType, -} from "./types"; +} from './types'; class ApimApiRevisionBuilder implements IApimApiRevisionBuilder { public revisions: ApimApiRevisionProps[] = []; @@ -34,8 +34,8 @@ export default class ApimApiBuilder { private _serviceUrl: ApimApiServiceUrlType | undefined = undefined; private _keyParameters: ApimApiKeysType | undefined = { - header: "x-api-key", - query: "api-key", + header: 'x-api-key', + query: 'api-key', }; private _apis: Record = {}; @@ -134,11 +134,11 @@ export default class ApimApiBuilder serviceUrl: `${this._serviceUrl!.serviceUrl}/${k}`, format: - "swaggerUrl" in rv + 'swaggerUrl' in rv ? enums.apimanagement.ContentFormat.Openapi_json : undefined, value: - "swaggerUrl" in rv + 'swaggerUrl' in rv ? await getImportConfig(rv.swaggerUrl, k) : undefined, }, @@ -165,8 +165,8 @@ export default class ApimApiBuilder serviceName: this.props.apimServiceName, resourceGroupName: this.props.group.resourceGroupName, apiId: apiName, - policyId: "policy", - format: "xml", + policyId: 'policy', + format: 'xml', value: this._policyString, }, { dependsOn: api }, @@ -174,7 +174,7 @@ export default class ApimApiBuilder } //Create Aoi Operations - if ("operations" in rv) { + if ('operations' in rv) { rv.operations.forEach((op) => { const opsName = `${apiName}-${op.name}`; const ops = new apim.ApiOperation( @@ -196,12 +196,12 @@ export default class ApimApiBuilder new apim.ApiOperationPolicy( opName, { - policyId: "policy", + policyId: 'policy', operationId: ops.id, apiId: api.id, serviceName: this.props.apimServiceName, resourceGroupName: this.props.group.resourceGroupName, - format: "xml", + format: 'xml', value: new ApimPolicyBuilder({ ...this.props, name: opName, @@ -226,7 +226,7 @@ export default class ApimApiBuilder await this.buildApis(); return { - resourceName: this._apiInstanceName, + name: this._apiInstanceName, group: this.props.group, id: interpolate`${this.props.productId}`, }; diff --git a/src/Builder/ApimBuilder.ts b/src/Builder/ApimBuilder.ts index 5117a563..b678dd61 100644 --- a/src/Builder/ApimBuilder.ts +++ b/src/Builder/ApimBuilder.ts @@ -13,23 +13,23 @@ import { IApimBuilder, IApimPublisherBuilder, IApimSkuBuilder, -} from "./types"; -import { ResourceInfo } from "../types"; -import * as apimanagement from "@pulumi/azure-native/apimanagement"; -import { getApimName } from "../Common/Naming"; -import { organization } from "../Common/StackEnv"; +} from './types'; +import { ResourceInfo } from '../types'; +import * as apim from '@pulumi/azure-native/apimanagement'; +import { getApimName } from '../Common'; +import { organization } from '../Common/StackEnv'; import { - ApimSignUpSettingsResource, ApimSignInSettingsResource, -} from "@drunk-pulumi/azure-providers"; -import { randomUuId } from "../Core/Random"; -import { AppInsightInfo } from "../Logs/Helpers"; -import * as network from "@pulumi/azure-native/network"; -import IpAddress from "../VNet/IpAddress"; -import Identity from "../AzAd/Identity"; -import { subscriptionId, tenantId } from "../Common/AzureEnv"; -import { interpolate } from "@pulumi/pulumi"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; + ApimSignUpSettingsResource, +} from '@drunk-pulumi/azure-providers'; +import { randomUuId } from '../Core/Random'; +import { AppInsightInfo } from '../Logs/Helpers'; +import * as network from '@pulumi/azure-native/network'; +import IpAddress from '../VNet/IpAddress'; +import Identity from '../AzAd/Identity'; +import { subscriptionId, tenantId } from '../Common/AzureEnv'; +import { interpolate } from '@pulumi/pulumi'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; class ApimBuilder extends Builder @@ -52,8 +52,7 @@ class ApimBuilder private _instanceName: string | undefined = undefined; private _ipAddressInstances: Record = {}; - private _apimInstance: apimanagement.ApiManagementService | undefined = - undefined; + private _apimInstance: apim.ApiManagementService | undefined = undefined; public constructor(props: BuilderProps) { super(props); @@ -125,7 +124,7 @@ class ApimBuilder const ipPros = { ...this.commonProps, name: `${this.commonProps.name}-apim`, - enableZone: this._sku!.sku === "Premium", + enableZone: this._sku!.sku === 'Premium', }; this._ipAddressInstances[this.commonProps.name] = IpAddress(ipPros); @@ -143,11 +142,11 @@ class ApimBuilder this._instanceName = getApimName(this.commonProps.name); const sku = { name: this._sku!.sku, - capacity: this._sku!.sku === "Consumption" ? 0 : this._sku!.capacity ?? 1, + capacity: this._sku!.sku === 'Consumption' ? 0 : this._sku!.capacity ?? 1, }; - const zones = sku.name === "Premium" ? this._zones : undefined; + const zones = sku.name === 'Premium' ? this._zones : undefined; - this._apimInstance = new apimanagement.ApiManagementService( + this._apimInstance = new apim.ApiManagementService( this._instanceName, { serviceName: this._instanceName, @@ -156,21 +155,21 @@ class ApimBuilder publisherName: this._publisher!.publisherName ?? organization, notificationSenderEmail: this._publisher?.notificationSenderEmail ?? - "apimgmt-noreply@mail.windowsazure.com", + 'apimgmt-noreply@mail.windowsazure.com', - identity: { type: "SystemAssigned" }, + identity: { type: 'SystemAssigned' }, sku, certificates: [ ...this._rootCerts.map((c) => ({ encodedCertificate: c.certificate, certificatePassword: c.certificatePassword, - storeName: "Root", + storeName: 'Root', })), ...this._caCerts.map((c) => ({ encodedCertificate: c.certificate, certificatePassword: c.certificatePassword, - storeName: "CertificateAuthority", + storeName: 'CertificateAuthority', })), ], @@ -178,7 +177,7 @@ class ApimBuilder hostnameConfigurations: this._proxyDomain ? [ { - type: "Proxy", + type: 'Proxy', hostName: this._proxyDomain.domain, encodedCertificate: this._proxyDomain.certificate, certificatePassword: this._proxyDomain.certificatePassword, @@ -196,11 +195,11 @@ class ApimBuilder ? this._ipAddressInstances[this.commonProps.name]?.id : undefined, publicNetworkAccess: this._privateLink?.disablePublicAccess - ? "Disabled" - : "Enabled", + ? 'Disabled' + : 'Enabled', //NATGateway - natGatewayState: this._apimVnet?.enableGateway ? "Enabled" : "Disabled", - virtualNetworkType: this._apimVnet?.type ?? "None", + natGatewayState: this._apimVnet?.enableGateway ? 'Enabled' : 'Disabled', + virtualNetworkType: this._apimVnet?.type ?? 'None', virtualNetworkConfiguration: this._apimVnet ? { subnetResourceId: this._apimVnet.subnetId, @@ -211,7 +210,7 @@ class ApimBuilder zones, //Only available for Premium additionalLocations: - sku.name === "Premium" + sku.name === 'Premium' ? this._additionalLocations?.map((a) => ({ ...a, sku, @@ -220,40 +219,40 @@ class ApimBuilder : undefined, customProperties: { - "Microsoft.WindowsAzure.ApiManagement.Gateway.Protocols.Server.Http2": - "true", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_CBC_SHA256": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_GCM_SHA256": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_256_CBC_SHA": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_256_CBC_SHA256": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TripleDes168": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10": - "false", - "Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11": - "false", + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Protocols.Server.Http2': + 'true', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_CBC_SHA256': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_128_GCM_SHA256': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_256_CBC_SHA': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TLS_RSA_WITH_AES_256_CBC_SHA256': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TripleDes168': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10': + 'false', + 'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11': + 'false', }, }, { dependsOn: this.commonProps.dependsOn, deleteBeforeReplace: true }, @@ -268,7 +267,7 @@ class ApimBuilder createClientSecret: true, }); - new apimanagement.IdentityProvider( + new apim.IdentityProvider( this.commonProps.name, { ...this.commonProps.group, @@ -276,8 +275,8 @@ class ApimBuilder clientId: identity.clientId, clientSecret: identity.clientSecret!, authority: interpolate`https://login.microsoftonline.com/${tenantId}/`, - type: "aad", - identityProviderName: "aad", + type: 'aad', + identityProviderName: 'aad', allowedTenants: [tenantId], signinTenant: tenantId, }, @@ -289,7 +288,7 @@ class ApimBuilder this._auths.forEach( (auth) => - new apimanagement.IdentityProvider( + new apim.IdentityProvider( `${this.commonProps.name}-${auth.type}`, { ...this.commonProps.group, @@ -315,7 +314,7 @@ class ApimBuilder termsOfService: { consentRequired: false, enabled: false, - text: "Terms & Conditions Of Service", + text: 'Terms & Conditions Of Service', }, }, { dependsOn: this._apimInstance, deleteBeforeReplace: true }, @@ -337,30 +336,30 @@ class ApimBuilder if (!this._privateLink) return; PrivateEndpoint({ resourceInfo: { - resourceName: this._instanceName!, + name: this._instanceName!, group: this.commonProps.group, id: this._apimInstance!.id, }, - privateDnsZoneName: "privatelink.azure-api.net", + privateDnsZoneName: 'privatelink.azure-api.net', subnetIds: this._privateLink.subnetIds, linkServiceGroupIds: this._privateLink.type ? [this._privateLink.type] - : ["Gateway"], + : ['Gateway'], dependsOn: this._apimInstance, }); } private buildInsightLog() { if (!this._insightLog) return; //App Insight Logs - new apimanagement.Logger( + new apim.Logger( `${this._instanceName}-insight`, { serviceName: this._apimInstance!.name, ...this.commonProps.group, - loggerType: apimanagement.LoggerType.ApplicationInsights, - description: "App Insight Logger", + loggerType: apim.LoggerType.ApplicationInsights, + description: 'App Insight Logger', loggerId: randomUuId(this._instanceName!).result, resourceId: this._insightLog.id, credentials: { @@ -382,7 +381,7 @@ class ApimBuilder this.buildInsightLog(); return { - resourceName: this._instanceName!, + name: this._instanceName!, group: this.commonProps.group, id: this._apimInstance!.id, }; diff --git a/src/Builder/ApimPolicyBuilder.ts b/src/Builder/ApimPolicyBuilder.ts index 1a2629b5..b6a54078 100644 --- a/src/Builder/ApimPolicyBuilder.ts +++ b/src/Builder/ApimPolicyBuilder.ts @@ -1,17 +1,15 @@ -import * as apim from "@pulumi/azure-native/apimanagement"; -import { organization } from "../Common/StackEnv"; -import { ResourceInfo } from "../types"; -import { getIpsRange } from "../VNet/Helper"; -import xmlFormat from "xml-formatter"; +import * as apim from '@pulumi/azure-native/apimanagement'; +import { organization } from '../Common/StackEnv'; +import { getIpsRange } from '../VNet/Helper'; +import xmlFormat from 'xml-formatter'; import { - SetHeaderTypes, ApimAuthCertType, ApimBaseUrlType, ApimCheckHeaderType, + ApimChildBuilderProps, ApimClientCertType, ApimClientIpHeaderType, ApimCorsType, - ApimCustomPolicyType, ApimFindAndReplaceType, ApimMockPropsType, ApimOutCacheType, @@ -21,8 +19,8 @@ import { ApimValidateJwtWhitelistIpType, ApimWhitelistIpType, IApimPolicyBuilder, - ApimChildBuilderProps, -} from "./types"; + SetHeaderTypes, +} from './types'; export default class ApimPolicyBuilder implements IApimPolicyBuilder { private _baseUrl: ApimBaseUrlType | undefined = undefined; @@ -90,7 +88,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { public setClientIpHeader(props: ApimClientIpHeaderType): IApimPolicyBuilder { this._headers.push({ name: props.headerKey ?? `x-${organization}-clientIp`, - value: "@(context.Request.IpAddress)", + value: '@(context.Request.IpAddress)', type: SetHeaderTypes.override, }); return this; @@ -136,7 +134,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { if (h.value) { rs += ` ${h.value}`; } - rs += ""; + rs += ''; return rs; }), ); @@ -149,7 +147,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { }" failed-check-httpcode="401" failed-check-error-message="The header ${ ch.name } is not found" ignore-case="true"> - ${ch.value ? ch.value.map((v) => `${v}`).join("\n") : ""} + ${ch.value ? ch.value.map((v) => `${v}`).join('\n') : ''} `, ), ); @@ -158,14 +156,14 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { this._inboundPolicies.push( ...this._mockResponses.map( (m) => - ``, + ``, ), ); } private buildRewriteUri() { if (!this._rewriteUri) return; this._inboundPolicies.push( - ``, + ``, ); } private buildRateLimit() { @@ -198,20 +196,20 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { this._inboundPolicies.push(` @@ -223,11 +221,11 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { if (!this._cors) return; const orgs = this._cors.origins ? this._cors.origins.map((o) => `${o}`) - : ["*"]; + : ['*']; const cors = ` - ${orgs.join("\n")} + ${orgs.join('\n')} * @@ -241,7 +239,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { private buildValidateJwtWhitelistIp() { if (!this._validateJwtWhitelistIp) return; const claimKey = - this._validateJwtWhitelistIp.claimKey ?? "client_IpWhitelist"; + this._validateJwtWhitelistIp.claimKey ?? 'client_IpWhitelist'; const setHeader = ` @{ Boolean ipAddressValid = false; @@ -293,7 +291,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { description: pfName, serviceName: this.props.apimServiceName, resourceGroupName: this.props.group.resourceGroupName, - format: "xml", + format: 'xml', value: xmlFormat(` ${setHeader} @@ -309,13 +307,13 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { const ipAddresses = this._whitelistIps.flatMap((ip) => ip.ipAddresses); const policy = `\r\n${ipAddresses .map((ip) => { - if (ip.includes("/")) { + if (ip.includes('/')) { const range = getIpsRange(ip); return ``; } return `
${ip}
`; }) - .join("\r\n")} + .join('\r\n')}
`; this._inboundPolicies.push(policy); @@ -325,7 +323,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { this._outboundPolicies.push( ...this._findAndReplaces .map((f) => ``) - .join("\n"), + .join('\n'), ); } // private buildCustomRules() { @@ -358,7 +356,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { //This must be a last rule this.buildVerifyClientCert(); - let backend = ""; + let backend = ''; if (!this._mockResponses) { backend = ''; @@ -367,7 +365,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { const xmlPolicy = ` - ${this._inboundPolicies.join("\n")} + ${this._inboundPolicies.join('\n')} ${backend} @@ -398,7 +396,7 @@ export default class ApimPolicyBuilder implements IApimPolicyBuilder { - ${this._outboundPolicies.join("\n")} + ${this._outboundPolicies.join('\n')} diff --git a/src/Builder/ApimProductBuilder.ts b/src/Builder/ApimProductBuilder.ts index d645e2ab..56de7bf8 100644 --- a/src/Builder/ApimProductBuilder.ts +++ b/src/Builder/ApimProductBuilder.ts @@ -1,11 +1,11 @@ -import * as apim from "@pulumi/azure-native/apimanagement"; -import { interpolate } from "@pulumi/pulumi"; -import { getPasswordName } from "../Common/Naming"; -import { randomPassword } from "../Core/Random"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { ResourceInfo } from "../types"; -import ApimApiBuilder from "./ApimApiBuilder"; -import ApimPolicyBuilder from "./ApimPolicyBuilder"; +import * as apim from '@pulumi/azure-native/apimanagement'; +import { interpolate } from '@pulumi/pulumi'; +import { getPasswordName } from '../Common'; +import { randomPassword } from '../Core/Random'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { ResourceInfo } from '../types'; +import ApimApiBuilder from './ApimApiBuilder'; +import ApimPolicyBuilder from './ApimPolicyBuilder'; import { APimApiBuilderFunction, ApimApiPolicyType, @@ -14,7 +14,7 @@ import { BuilderAsync, IApimProductBuilder, IBuilderAsync, -} from "./types"; +} from './types'; export class ApimProductBuilder extends BuilderAsync @@ -29,7 +29,7 @@ export class ApimProductBuilder private _subInstance: apim.Subscription | undefined = undefined; private _productInstanceName: string; private _policyString: string; - private _state: apim.ProductState = "notPublished"; + private _state: apim.ProductState = 'notPublished'; public constructor(private props: ApimChildBuilderProps) { super(props); @@ -58,7 +58,7 @@ export class ApimProductBuilder return this; } public published(): IBuilderAsync { - this._state = "published"; + this._state = 'published'; return this; } @@ -84,8 +84,8 @@ export class ApimProductBuilder serviceName: this.props.apimServiceName, resourceGroupName: this.props.group.resourceGroupName, productId: this._productInstanceName, - format: "xml", - policyId: "policy", + format: 'xml', + policyId: 'policy', value: this._policyString, }); } @@ -93,8 +93,8 @@ export class ApimProductBuilder private buildSubscription() { if (!this._productInstance) return; const subName = `${this.props.name}-sub`; - const primaryKey = getPasswordName(subName, "primary"); - const secondaryKey = getPasswordName(subName, "secondary"); + const primaryKey = getPasswordName(subName, 'primary'); + const secondaryKey = getPasswordName(subName, 'secondary'); const primaryPass = randomPassword({ name: primaryKey }).result; const secondaryPass = randomPassword({ name: secondaryKey }).result; @@ -113,23 +113,25 @@ export class ApimProductBuilder { dependsOn: this._productInstance }, ); - addCustomSecret({ - name: primaryKey, - formattedName: true, - value: primaryPass, - contentType: subName, - vaultInfo: this.props.vaultInfo, - dependsOn: this._subInstance, - }); + if (this.props.vaultInfo) { + addCustomSecret({ + name: primaryKey, + formattedName: true, + value: primaryPass, + contentType: subName, + vaultInfo: this.props.vaultInfo, + dependsOn: this._subInstance, + }); - addCustomSecret({ - name: secondaryKey, - formattedName: true, - value: secondaryPass, - contentType: subName, - vaultInfo: this.props.vaultInfo, - dependsOn: this._subInstance, - }); + addCustomSecret({ + name: secondaryKey, + formattedName: true, + value: secondaryPass, + contentType: subName, + vaultInfo: this.props.vaultInfo, + dependsOn: this._subInstance, + }); + } } private async buildApis() { @@ -152,7 +154,7 @@ export class ApimProductBuilder await this.buildApis(); return { - resourceName: this._productInstanceName, + name: this._productInstanceName, group: this.props.group, id: this._productInstance!.id, }; diff --git a/src/Builder/ApimRootBuilder.ts b/src/Builder/ApimRootBuilder.ts index 146f86a8..29327927 100644 --- a/src/Builder/ApimRootBuilder.ts +++ b/src/Builder/ApimRootBuilder.ts @@ -1,24 +1,24 @@ -import { ResourceInfo } from "../types"; -import { ApimProductBuilder } from "./ApimProductBuilder"; -import { ApimWorkspaceBuilder } from "./ApimWorkspaceBuilder"; +import { ResourceInfo } from '../types'; +import { ApimProductBuilder } from './ApimProductBuilder'; +import { ApimWorkspaceBuilder } from './ApimWorkspaceBuilder'; import { ApimChildBuilderProps, BuilderProps, IApimProductBuilder, IApimWorkspaceBuilder, -} from "./types"; +} from './types'; export default class ApimRootBuilder { private constructor(private props: ApimChildBuilderProps) {} public static from( apimInfo: ResourceInfo, - props: Omit, + props: Omit, ): ApimRootBuilder { return new ApimRootBuilder({ ...props, - name: apimInfo.resourceName, - apimServiceName: apimInfo.resourceName, + name: apimInfo.name, + apimServiceName: apimInfo.name, group: apimInfo.group, }); } diff --git a/src/Builder/ApimWorkspaceBuilder.ts b/src/Builder/ApimWorkspaceBuilder.ts index f35a3410..8c3c9c5a 100644 --- a/src/Builder/ApimWorkspaceBuilder.ts +++ b/src/Builder/ApimWorkspaceBuilder.ts @@ -1,6 +1,6 @@ -import { ResourceInfo } from "../types"; -import * as apim from "@pulumi/azure-native/apimanagement"; -import { ApimChildBuilderProps, Builder, IApimWorkspaceBuilder } from "./types"; +import { ResourceInfo } from '../types'; +import * as apim from '@pulumi/azure-native/apimanagement'; +import { ApimChildBuilderProps, Builder, IApimWorkspaceBuilder } from './types'; export class ApimWorkspaceBuilder extends Builder @@ -29,7 +29,7 @@ export class ApimWorkspaceBuilder this.buildWp(); return { - resourceName: this._wpInstanceName, + name: this._wpInstanceName, group: this.props.group, id: this._wpInstance!.id, }; diff --git a/src/Builder/DnsZoneBuilder.ts b/src/Builder/DnsZoneBuilder.ts index 5e3ab1f2..70676eac 100644 --- a/src/Builder/DnsZoneBuilder.ts +++ b/src/Builder/DnsZoneBuilder.ts @@ -1,8 +1,7 @@ -import { BasicResourceArgs, ResourceInfo } from "../types"; -import { DnsZoneARecordType, IDnsZoneBuilder } from "./types"; -import * as network from "@pulumi/azure-native/network"; -import { output } from "@pulumi/pulumi"; -import { globalKeyName } from "../Common/GlobalEnv"; +import { BasicResourceArgs, ResourceInfo } from '../types'; +import { DnsZoneARecordType, IDnsZoneBuilder } from './types'; +import * as network from '@pulumi/azure-native/network'; +import { globalKeyName } from '../Common/GlobalEnv'; class DnsZoneBuilder implements IDnsZoneBuilder { private _aRecords: DnsZoneARecordType[] = []; @@ -51,16 +50,16 @@ class DnsZoneBuilder implements IDnsZoneBuilder { this._aRecords.forEach( (a, index) => new network.RecordSet( - a.recordName === "*" + a.recordName === '*' ? `All-${index}-ARecord` - : a.recordName === "@" + : a.recordName === '@' ? `Root-${index}-ARecord` : `${a.recordName}-ARecord`, { zoneName: this._zoneInstance!.name, ...group, relativeRecordSetName: a.recordName, - recordType: "A", + recordType: 'A', aRecords: a.ipAddresses.map((i) => ({ ipv4Address: i })), ttl: 3600, }, @@ -91,7 +90,7 @@ class DnsZoneBuilder implements IDnsZoneBuilder { zoneName: this._zoneInstance!.name, ...group, relativeRecordSetName: cc!.name, - recordType: "NS", + recordType: 'NS', nsRecords: ns.map((s) => ({ nsdname: s })), ttl: 3600, }, @@ -107,7 +106,7 @@ class DnsZoneBuilder implements IDnsZoneBuilder { this.buildChildren(); return { - resourceName: this.commonProps.name, + name: this.commonProps.name, group: this.commonProps.group, id: this._zoneInstance!.id, }; diff --git a/src/Builder/PrivateDnsZoneBuilder.ts b/src/Builder/PrivateDnsZoneBuilder.ts index 871fddda..b2344a61 100644 --- a/src/Builder/PrivateDnsZoneBuilder.ts +++ b/src/Builder/PrivateDnsZoneBuilder.ts @@ -1,14 +1,14 @@ -import { DnsZoneARecordType } from "./types"; -import { BasicResourceArgs, ResourceInfo } from "../types"; -import * as network from "@pulumi/azure-native/network"; +import { DnsZoneARecordType } from './types'; +import { BasicResourceArgs, ResourceInfo } from '../types'; +import * as network from '@pulumi/azure-native/network'; import { IPrivateDnsZoneBuilder, PrivateDnsZoneVnetLinkingType, -} from "./types/privateDnsZoneBuilder"; -import * as native from "@pulumi/azure-native"; -import { output } from "@pulumi/pulumi"; -import { getVnetIdFromSubnetId } from "../VNet/Helper"; -import { globalKeyName } from "../Common/GlobalEnv"; +} from './types/privateDnsZoneBuilder'; +import * as native from '@pulumi/azure-native'; +import { output } from '@pulumi/pulumi'; +import { getVnetIdFromSubnetId } from '../VNet/Helper'; +import { globalKeyName } from '../Common/GlobalEnv'; class PrivateDnsZoneBuilder implements IPrivateDnsZoneBuilder { private _aRecords: DnsZoneARecordType[] = []; @@ -51,16 +51,16 @@ class PrivateDnsZoneBuilder implements IPrivateDnsZoneBuilder { this._aRecords.forEach( (a, index) => new network.PrivateRecordSet( - a.recordName === "*" + a.recordName === '*' ? `All-${index}-ARecord` - : a.recordName === "@" + : a.recordName === '@' ? `Root-${index}-ARecord` : `${a.recordName}-ARecord`, { privateZoneName: this._zoneInstance!.name, ...group, relativeRecordSetName: a.recordName, - recordType: "A", + recordType: 'A', aRecords: a.ipAddresses.map((i) => ({ ipv4Address: i })), ttl: 3600, }, @@ -81,7 +81,7 @@ class PrivateDnsZoneBuilder implements IPrivateDnsZoneBuilder { //output(v).apply((i) => console.log(this.commonProps.name, i)); return new native.network.VirtualNetworkLink( - `${this.commonProps.name.split(".")[0]}-${index}-${i}-link`, + `${this.commonProps.name.split('.')[0]}-${index}-${i}-link`, { ...this.commonProps.group, privateZoneName: this._zoneInstance!.name, @@ -99,7 +99,7 @@ class PrivateDnsZoneBuilder implements IPrivateDnsZoneBuilder { this.buildVnetLinks(); return { - resourceName: this.commonProps.name, + name: this.commonProps.name, group: this.commonProps.group, id: this._zoneInstance!.id, }; diff --git a/src/Builder/ResourceBuilder.ts b/src/Builder/ResourceBuilder.ts index 7138af8e..d29f610a 100644 --- a/src/Builder/ResourceBuilder.ts +++ b/src/Builder/ResourceBuilder.ts @@ -27,8 +27,7 @@ import VnetBuilder from './VnetBuilder'; import { VaultNetworkResource } from '@drunk-pulumi/azure-providers'; import { subscriptionId } from '../Common/AzureEnv'; import { IVaultBuilderResults } from './types/vaultBuilder'; -import { VaultBuilderResults } from './VaultBuilder'; -import VaultBuilder from './VaultBuilder'; +import VaultBuilder, { VaultBuilderResults } from './VaultBuilder'; class ResourceBuilder implements @@ -215,7 +214,7 @@ class ResourceBuilder //Other resources this._otherResources.forEach((b) => { const rs = b(this.getResults()); - this._otherInstances[rs.resourceName] = rs; + this._otherInstances[rs.name] = rs; }); //Other builders diff --git a/src/Builder/SqlBuilder.ts b/src/Builder/SqlBuilder.ts index aaf652b4..7d496dad 100644 --- a/src/Builder/SqlBuilder.ts +++ b/src/Builder/SqlBuilder.ts @@ -1,9 +1,4 @@ -import Sql, { - SqlElasticPoolType, - SqlNetworkType, - SqlResults, - SqlVulnerabilityAssessmentType, -} from "../Sql"; +import Sql, { SqlElasticPoolType, SqlNetworkType, SqlResults } from '../Sql'; import { Builder, BuilderProps, @@ -15,8 +10,8 @@ import { SqlBuilderAuthOptionsType, SqlBuilderVulnerabilityAssessmentType, SqlDbBuilderType, -} from "./types"; -import { randomLogin } from "../Core/Random"; +} from './types'; +import { randomLogin } from '../Core/Random'; class SqlBuilder extends Builder @@ -79,7 +74,7 @@ class SqlBuilder maxUserNameLength: 25, passwordOptions: { length: 50, - policy: "yearly", + policy: 'yearly', options: { lower: true, upper: true, special: false, numeric: true }, }, vaultInfo: this.commonProps.vaultInfo, diff --git a/src/Builder/StorageBuilder.ts b/src/Builder/StorageBuilder.ts index 74993bad..d04a1dc2 100644 --- a/src/Builder/StorageBuilder.ts +++ b/src/Builder/StorageBuilder.ts @@ -3,10 +3,10 @@ import Storage, { StorageNetworkType, StoragePolicyType, StorageResults, -} from "../Storage"; -import CdnEndpoint from "../Cdn/CdnEndpoint"; -import { getDefaultResponseHeaders } from "../Cdn/CdnRules"; -import { ResourceInfo } from "../types"; +} from '../Storage'; +import CdnEndpoint from '../Cdn/CdnEndpoint'; +import { getDefaultResponseHeaders } from '../Cdn/CdnRules'; +import { ResourceInfo } from '../types'; import { Builder, BuilderProps, @@ -16,13 +16,13 @@ import { IStorageStarterBuilder, StorageCdnType, StorageFeatureBuilderType, -} from "./types"; +} from './types'; class StorageBuilder extends Builder implements IStorageStarterBuilder, IStorageBuilder, IStaticWebStorageBuilder { - private _type: "storage" | "staticWeb" = "storage"; + private _type: 'storage' | 'staticWeb' = 'storage'; private _policies: StoragePolicyType | undefined = undefined; private _features: StorageFeatureBuilderType = {}; private _containers: ContainerProps[] = []; @@ -38,11 +38,11 @@ class StorageBuilder super(props); } public asStorage(): IStorageBuilder { - this._type = "storage"; + this._type = 'storage'; return this; } public asStaticWebStorage(): IStaticWebStorageBuilder { - this._type = "staticWeb"; + this._type = 'staticWeb'; return this; } public withCdn(props: StorageCdnType): IStaticWebStorageBuilder { @@ -88,7 +88,7 @@ class StorageBuilder policies: this._policies, featureFlags: { ...this._features, - enableStaticWebsite: this._type === "staticWeb", + enableStaticWebsite: this._type === 'staticWeb', }, lock: this._lock, }); @@ -101,9 +101,9 @@ class StorageBuilder getDefaultResponseHeaders(this._cdnProps.domainName); //Create Azure CDN if customDomain provided - const origin = `${this._storageInstance!.resourceName}.z23.web.core.windows.net`; + const origin = `${this._storageInstance!.name}.z23.web.core.windows.net`; CdnEndpoint({ - name: this._storageInstance!.resourceName, + name: this._storageInstance!.name, ...this._cdnProps, origin, httpsEnabled: true, diff --git a/src/Builder/VdiBuilder.ts b/src/Builder/VdiBuilder.ts index 7e839e1d..ef471ec8 100644 --- a/src/Builder/VdiBuilder.ts +++ b/src/Builder/VdiBuilder.ts @@ -1,15 +1,16 @@ -import { getVdiName } from "../Common"; -import { ResourceInfo } from "../types"; -import * as vdi from "@pulumi/azure-native/desktopvirtualization"; -import { Builder, BuilderProps } from "./types"; +import { getVdiName } from '../Common'; +import { ResourceInfo } from '../types'; +import * as vdi from '@pulumi/azure-native/desktopvirtualization'; import { + Builder, + BuilderProps, IVdiBuilder, IVdiNetworkBuilder, IVdiOptionsBuilder, VdiBuilderAppGroupType, VdiBuilderNetworkType, VdiBuilderOptionsType, -} from "./types/vdiBuilder"; +} from './types'; class VdiBuilder extends Builder @@ -45,18 +46,18 @@ class VdiBuilder description: `${this._hostPoolName} HostPool`, friendlyName: `${this._hostPoolName} HostPool`, identity: { type: vdi.ResourceIdentityType.SystemAssigned }, - personalDesktopAssignmentType: "Automatic", + personalDesktopAssignmentType: 'Automatic', startVMOnConnect: true, agentUpdate: { useSessionHostLocalTime: true, type: vdi.SessionHostComponentUpdateType.Scheduled, maintenanceWindows: [ - { dayOfWeek: "Saturday", hour: 0 }, - { dayOfWeek: "Sunday", hour: 0 }, + { dayOfWeek: 'Saturday', hour: 0 }, + { dayOfWeek: 'Sunday', hour: 0 }, ], }, customRdpProperty: - "audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1", + 'audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1', validationEnvironment: true, ...this.commonProps.group, ...this._options!, @@ -65,7 +66,7 @@ class VdiBuilder private buildAppGroups() { if (this._appGroups.length <= 0) - this._appGroups.push({ applicationGroupType: "Desktop" }); + this._appGroups.push({ applicationGroupType: 'Desktop' }); const apps = this._appGroups.map((appGroup) => { const n = `${appGroup.applicationGroupType}-vdi-apps`; @@ -101,7 +102,7 @@ class VdiBuilder this.buildAppGroups(); return { - resourceName: this._hostPoolName!, + name: this._hostPoolName!, group: this.commonProps.group, id: this._hostPoolInstance!.id, }; diff --git a/src/Builder/VmBuilder.ts b/src/Builder/VmBuilder.ts index cec7fc92..ca1fef65 100644 --- a/src/Builder/VmBuilder.ts +++ b/src/Builder/VmBuilder.ts @@ -1,5 +1,5 @@ -import { Input } from "@pulumi/pulumi"; -import { ResourceInfo } from "../types"; +import { Input } from '@pulumi/pulumi'; +import { ResourceInfo } from '../types'; import { Builder, BuilderProps, @@ -12,10 +12,10 @@ import { VmOsBuilderLinuxProps, VmOsBuilderWindowsProps, VmSizeTypes, -} from "./types"; -import { randomLogin } from "../Core/Random"; -import VM, { VmScheduleType } from "../VM"; -import { VirtualMachine } from "@pulumi/azure-native/compute"; +} from './types'; +import { randomLogin } from '../Core/Random'; +import VM, { VmScheduleType } from '../VM'; +import { VirtualMachine } from '@pulumi/azure-native/compute'; class VmBuilder extends Builder @@ -82,7 +82,7 @@ class VmBuilder maxUserNameLength: 25, passwordOptions: { length: 50, - policy: "yearly", + policy: 'yearly', options: { lower: true, upper: true, special: true, numeric: true }, }, vaultInfo: this.commonProps.vaultInfo, @@ -96,7 +96,7 @@ class VmBuilder ...this.commonProps, subnetId: this._subnetProps!, vmSize: this._vmSize!, - osType: Boolean(this._linuxImage) ? "Linux" : "Windows", + osType: Boolean(this._linuxImage) ? 'Linux' : 'Windows', image: this._linuxImage ?? this._windowImage!, login: { userName: this._loginProps!.adminLogin!, @@ -112,7 +112,7 @@ class VmBuilder this.buildVm(); return { - resourceName: this.commonProps.name, + name: this.commonProps.name, group: this.commonProps.group, id: this._vmInstance!.id, }; diff --git a/src/Builder/types/genericBuilder.ts b/src/Builder/types/genericBuilder.ts index 52421752..9984c256 100644 --- a/src/Builder/types/genericBuilder.ts +++ b/src/Builder/types/genericBuilder.ts @@ -1,15 +1,17 @@ //Common Builder Types -import { Input, Resource } from "@pulumi/pulumi"; -import { KeyVaultInfo, ResourceGroupInfo, ResourceInfo } from "../../types"; -import { EnvRolesResults } from "../../AzAd/EnvRoles"; +import { Input, Resource } from '@pulumi/pulumi'; +import { KeyVaultInfo, ResourceGroupInfo, ResourceInfo } from '../../types'; +import { EnvRolesResults } from '../../AzAd/EnvRoles'; export type BuilderProps = { name: string; group: ResourceGroupInfo; - envRoles: EnvRolesResults; - vaultInfo: KeyVaultInfo; + /** the below are optionals property and will be available depend on the situation*/ + envRoles?: EnvRolesResults; + vaultInfo?: KeyVaultInfo; dependsOn?: Input[]> | Input; }; + export type CommonOmit = Omit; export type LoginBuilderProps = { adminLogin: Input; @@ -36,7 +38,7 @@ export abstract class Builder //Asynchronous export interface IBuilderAsync - extends Omit, "build"> { + extends Omit, 'build'> { build(): Promise; } diff --git a/src/Builder/types/resourceBuilder.ts b/src/Builder/types/resourceBuilder.ts index 4b9bc10c..6e6495c4 100644 --- a/src/Builder/types/resourceBuilder.ts +++ b/src/Builder/types/resourceBuilder.ts @@ -43,7 +43,7 @@ export interface IResourceGroupBuilder { } export interface IResourceVaultBuilder { - createVault(name: string | undefined): IResourceBuilder; + createVault(name?: string): IResourceBuilder; withVault(props: KeyVaultInfo): IResourceBuilder; } diff --git a/src/Cdn/CdnEndpoint.ts b/src/Cdn/CdnEndpoint.ts index 4e11f9e3..a7b7d7ec 100644 --- a/src/Cdn/CdnEndpoint.ts +++ b/src/Cdn/CdnEndpoint.ts @@ -1,17 +1,17 @@ -import { Input } from "@pulumi/pulumi"; -import * as native from "@pulumi/azure-native"; -import CdnHttpsEnable from "@drunk-pulumi/azure-providers/CdnHttpsEnable"; -import { subscriptionId } from "../Common/AzureEnv"; +import { Input } from '@pulumi/pulumi'; +import * as native from '@pulumi/azure-native'; +import CdnHttpsEnable from '@drunk-pulumi/azure-providers/CdnHttpsEnable'; +import { subscriptionId } from '../Common/AzureEnv'; import { - enforceHttpsRule, - indexFileCacheRule, allowsCorsRules, + enforceHttpsRule, getResponseHeadersRule, -} from "./CdnRules"; -import { cdnProfileInfo as globalCdnProfileInfo } from "../Common/GlobalEnv"; -import { replaceAll } from "../Common/Helpers"; -import { getCdnEndpointName } from "../Common/Naming"; -import { BasicArgs, ResourceInfo } from "../types"; + indexFileCacheRule, +} from './CdnRules'; +import { cdnProfileInfo as globalCdnProfileInfo } from '../Common/GlobalEnv'; +import { replaceAll } from '../Common/Helpers'; +import { getCdnEndpointName } from '../Common'; +import { BasicArgs, ResourceInfo } from '../types'; export interface CdnEndpointProps extends BasicArgs { name: string; @@ -51,30 +51,30 @@ export default ({ { endpointName: name, ...cdnProfileInfo!.group, - profileName: cdnProfileInfo!.resourceName, + profileName: cdnProfileInfo!.name, origins: [{ name, hostName: origin }], originHostHeader: origin, - optimizationType: "GeneralWebDelivery", - queryStringCachingBehavior: "IgnoreQueryString", + optimizationType: 'GeneralWebDelivery', + queryStringCachingBehavior: 'IgnoreQueryString', deliveryPolicy: { rules, - description: "Static Website Rules", + description: 'Static Website Rules', }, isCompressionEnabled: true, contentTypesToCompress: [ - "text/plain", - "text/html", - "text/xml", - "text/css", - "application/xml", - "application/xhtml+xml", - "application/rss+xml", - "application/javascript", - "application/x-javascript", + 'text/plain', + 'text/html', + 'text/xml', + 'text/css', + 'application/xml', + 'application/xhtml+xml', + 'application/rss+xml', + 'application/javascript', + 'application/x-javascript', ], isHttpAllowed: true, @@ -89,8 +89,8 @@ export default ({ { endpointName: endpoint.name, ...cdnProfileInfo!.group, - profileName: cdnProfileInfo!.resourceName, - customDomainName: replaceAll(domainName, ".", "-"), + profileName: cdnProfileInfo!.name, + customDomainName: replaceAll(domainName, '.', '-'), hostName: domainName, }, { dependsOn: endpoint }, @@ -102,7 +102,7 @@ export default ({ { endpointName: endpoint.name, ...cdnProfileInfo!.group, - profileName: cdnProfileInfo!.resourceName, + profileName: cdnProfileInfo!.name, customDomainName: customDomain.name, subscriptionId, }, diff --git a/src/Cdn/index.ts b/src/Cdn/index.ts index e9809f75..9d2fa41c 100644 --- a/src/Cdn/index.ts +++ b/src/Cdn/index.ts @@ -1,9 +1,8 @@ -import { EnvRolesResults } from "../AzAd/EnvRoles"; -import { addMemberToGroup } from "../AzAd/Group"; -import { ResourceGroupInfo, ResourceInfo } from "../types"; -import * as cdn from "@pulumi/azure-native/cdn"; -import { getCdnProfileName } from "../Common"; -import { global } from "../Common"; +import { EnvRolesResults } from '../AzAd/EnvRoles'; +import { addMemberToGroup } from '../AzAd/Group'; +import { ResourceGroupInfo, ResourceInfoWithInstance } from '../types'; +import * as cdn from '@pulumi/azure-native/cdn'; +import { getCdnProfileName, global } from '../Common'; interface Props { name: string; @@ -15,9 +14,9 @@ export default ({ name, group = global.groupInfo, envRoles, -}: Props): ResourceInfo & { instance: cdn.Profile } => { +}: Props): ResourceInfoWithInstance => { name = getCdnProfileName(name); - const internalGroup = { ...group, location: "global" }; + const internalGroup = { ...group, location: 'global' }; const profile = new cdn.Profile(name, { profileName: name, @@ -38,7 +37,7 @@ export default ({ } return { - resourceName: name, + name, group: internalGroup, id: profile.id, instance: profile, diff --git a/src/Common/AzureEnv.ts b/src/Common/AzureEnv.ts index 59cb91a5..0329d086 100644 --- a/src/Common/AzureEnv.ts +++ b/src/Common/AzureEnv.ts @@ -1,29 +1,29 @@ -import * as pulumi from "@pulumi/pulumi"; -import { authorization } from "@pulumi/azure-native"; -import { registerAutoTags } from "./AutoTags"; -import { KeyVaultInfo, ResourceGroupInfo, ResourceInfoArg } from "../types"; -import { getKeyVaultName, getResourceGroupName } from "./Naming"; -import { organization, projectName, stack } from "./StackEnv"; -import { getCountryCode, getRegionCode } from "./Location"; +import * as pulumi from '@pulumi/pulumi'; +import { authorization } from '@pulumi/azure-native'; +import { registerAutoTags } from './AutoTags'; +import { KeyVaultInfo, ResourceInfo, ResourceInfoArg } from '../types'; +import { getKeyVaultName, getResourceGroupName } from './Naming'; +import { organization, projectName, stack } from './StackEnv'; +import { getCountryCode, getRegionCode } from './Location'; const config = pulumi.output(authorization.getClientConfig()); export const tenantId = config.apply((c) => c.tenantId); export const subscriptionId = config.apply((c) => c.subscriptionId); export const currentPrincipal = config.apply((c) => c.objectId); -const env = JSON.parse(process.env.PULUMI_CONFIG ?? "{}"); -export const currentRegionName = (env["azure-native:config:location"] ?? - "SoutheastAsia") as string; +const env = JSON.parse(process.env.PULUMI_CONFIG ?? '{}'); +export const currentRegionName = (env['azure-native:config:location'] ?? + 'SoutheastAsia') as string; export const currentRegionCode = getRegionCode(currentRegionName); export const currentCountryCode = getCountryCode(currentRegionName); export const defaultScope = pulumi.interpolate`/subscriptions/${subscriptionId}`; export enum Environments { - Global = "global", - Local = "local", - Dev = "dev", - Sandbox = "sandbox", - Prd = "prd", + Global = 'global', + Local = 'local', + Dev = 'dev', + Sandbox = 'sandbox', + Prd = 'prd', } export const isEnv = (env: Environments) => stack.includes(env); @@ -59,7 +59,7 @@ pulumi.all([subscriptionId, tenantId]).apply(([s, t]) => { registerAutoTags({ environment: stack, organization: organization, - "pulumi-project": projectName, + 'pulumi-project': projectName, }); /** Get Key Vault by Group Name. Group Name is the name use to create the resource and resource group together. */ @@ -69,7 +69,7 @@ export const getKeyVaultInfo = ( ): KeyVaultInfo => { const vaultName = getKeyVaultName(groupName, { region, - suffix: "vlt", + suffix: 'vlt', includeOrgName: true, }); const resourceGroupName = getResourceGroupName(groupName, { region }); @@ -94,38 +94,33 @@ export const getResourceIdFromInfo = ({ else if (name && provider) return pulumi.interpolate`/subscriptions/${subscriptionId}/resourceGroups/${group.resourceGroupName}/providers/${provider}/${name}`; - throw new Error("Resource Info is invalid."); + throw new Error('Resource Info is invalid.'); }; -/**Get Resource Info from Resource ID. Sample ID is "/subscriptions/01af663e-76dd-45ac-9e57-9c8e0d3ee350/resourceGroups/sandbox-codehbd-group-hbd/providers/Microsoft.Network/virtualNetworks/sandbox-codehbd-vnet-hbd"*/ -export interface ResourceInfo { - name: string; - group: ResourceGroupInfo; - subscriptionId: string; - id: string; -} - +export type ParsedResourceInfo = ResourceInfo & { + subscriptionId: pulumi.Input; +}; export const parseResourceInfoFromId = ( id: string, -): ResourceInfo | undefined => { +): ParsedResourceInfo | undefined => { if (!id) return undefined; - const details = id.split("/"); - let name = ""; - let groupName = ""; - let subscriptionId = ""; + const details = id.split('/'); + let name = ''; + let groupName = ''; + let subId = ''; details.forEach((d, index) => { - if (d === "subscriptions") subscriptionId = details[index + 1]; - if (d === "resourceGroups" || d === "resourcegroups") + if (d === 'subscriptions') subId = details[index + 1]; + if (d === 'resourceGroups' || d === 'resourcegroups') groupName = details[index + 1]; if (index === details.length - 1) name = d; }); return { name, - id, + id: pulumi.output(id), group: { resourceGroupName: groupName, location: currentRegionName }, - subscriptionId, + subscriptionId: subId ?? subscriptionId, }; }; diff --git a/src/Common/GlobalEnv.ts b/src/Common/GlobalEnv.ts index 746631b6..e2de121f 100644 --- a/src/Common/GlobalEnv.ts +++ b/src/Common/GlobalEnv.ts @@ -1,14 +1,8 @@ -import { - ConventionProps, - KeyVaultInfo, - ResourceGroupInfo, - ResourceInfo, -} from '../types'; +import { KeyVaultInfo, ResourceGroupInfo, ResourceInfo } from '../types'; import { subscriptionId } from './AzureEnv'; import { getCdnProfileName, getKeyVaultName } from './Naming'; import { getResourceName } from './ResourceEnv'; import { interpolate } from '@pulumi/pulumi'; -import { organization } from './StackEnv'; export const globalKeyName = 'global'; @@ -18,7 +12,7 @@ export const groupInfo: ResourceGroupInfo = { const cdnProfileName = getCdnProfileName(globalKeyName); export const cdnProfileInfo: ResourceInfo = { - resourceName: cdnProfileName, + name: cdnProfileName, group: { resourceGroupName: groupInfo.resourceGroupName, location: globalKeyName, diff --git a/src/ContainerRegistry/index.ts b/src/ContainerRegistry/index.ts index 7a135156..bede77f1 100644 --- a/src/ContainerRegistry/index.ts +++ b/src/ContainerRegistry/index.ts @@ -1,19 +1,15 @@ -import * as containerregistry from "@pulumi/azure-native/containerregistry"; +import * as registry from '@pulumi/azure-native/containerregistry'; import { DefaultResourceArgs, KeyVaultInfo, NetworkPropsType, ResourceGroupInfo, -} from "../types"; -import creator from "../Core/ResourceCreator"; -import * as global from "../Common/GlobalEnv"; -import { - getAcrName, - getPasswordName, - getPrivateEndpointName, -} from "../Common/Naming"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; + ResourceInfoWithInstance, +} from '../types'; +import * as global from '../Common/GlobalEnv'; +import { getAcrName, getPasswordName } from '../Common'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; interface Props extends DefaultResourceArgs { name: string; @@ -21,9 +17,9 @@ interface Props extends DefaultResourceArgs { adminUserEnabled?: boolean; enableStorageAccount?: boolean; vaultInfo?: KeyVaultInfo; - sku?: containerregistry.SkuName; + sku?: registry.SkuName; /**Only support Premium sku*/ - network?: NetworkPropsType; + network?: Omit; } /** The Azure Container Registry will be created at the GLobal Group. @@ -32,50 +28,52 @@ interface Props extends DefaultResourceArgs { export default ({ name, group = global.groupInfo, - sku = containerregistry.SkuName.Basic, + sku = registry.SkuName.Basic, adminUserEnabled = true, vaultInfo, network, - ...others -}: Props) => { + dependsOn, + ignoreChanges, +}: Props): ResourceInfoWithInstance => { name = getAcrName(name); const urlKey = `${name}-url`; const userNameKey = `${name}-user-name`; - const primaryPasswordKey = getPasswordName(name, "primary"); - const secondaryPasswordKey = getPasswordName(name, "secondary"); + const primaryPasswordKey = getPasswordName(name, 'primary'); + const secondaryPasswordKey = getPasswordName(name, 'secondary'); - const { resource, diagnostic } = creator(containerregistry.Registry, { - registryName: name, - ...group, + const resource = new registry.Registry( + name, + { + registryName: name, + ...group, - adminUserEnabled, - sku: { name: sku }, - networkRuleSet: - sku === "Premium" && network - ? { - defaultAction: containerregistry.DefaultAction.Allow, + sku: { name: sku }, + adminUserEnabled, + publicNetworkAccess: network?.privateLink ? 'Disabled' : 'Enabled', - ipRules: network.ipAddresses - ? network.ipAddresses.map((ip) => ({ iPAddressOrRange: ip })) - : undefined, + networkRuleSet: + sku === 'Premium' && network + ? { + defaultAction: registry.DefaultAction.Allow, - virtualNetworkRules: network.subnetId - ? [{ virtualNetworkResourceId: network.subnetId }] - : undefined, - } - : undefined, - ...others, - } as containerregistry.RegistryArgs & DefaultResourceArgs); + ipRules: network.ipAddresses + ? network.ipAddresses.map((ip) => ({ iPAddressOrRange: ip })) + : undefined, + } + : undefined, + }, + { dependsOn, ignoreChanges }, + ); - if (sku === "Premium" && network?.privateLink) { + if (sku === 'Premium' && network?.privateLink) { PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: resource.id }, - privateDnsZoneName: "privatelink.azurecr.io", + resourceInfo: { name, group, id: resource.id }, + privateDnsZoneName: 'privatelink.azurecr.io', subnetIds: network.privateLink.subnetIds, linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["azurecr"], + : ['azurecr'], }); } @@ -84,7 +82,7 @@ export default ({ //The Resource is not created in Azure yet. if (!id) return; //Only able to gert the secret once the resource is created. - const keys = await containerregistry.listRegistryCredentials({ + const keys = await registry.listRegistryCredentials({ registryName: name, resourceGroupName: global.groupInfo.resourceGroupName, }); @@ -93,7 +91,7 @@ export default ({ name: urlKey, value: `https://${name}.azurecr.io`, vaultInfo, - contentType: "Container Registry", + contentType: 'Container Registry', dependsOn: resource, }); @@ -101,7 +99,7 @@ export default ({ name: userNameKey, value: keys.username!, vaultInfo, - contentType: "Container Registry", + contentType: 'Container Registry', dependsOn: resource, }); @@ -110,7 +108,7 @@ export default ({ formattedName: true, value: keys.passwords![0].value!, vaultInfo, - contentType: "Container Registry", + contentType: 'Container Registry', dependsOn: resource, }); @@ -119,7 +117,7 @@ export default ({ formattedName: true, value: keys.passwords![1].value!, vaultInfo, - contentType: "Container Registry", + contentType: 'Container Registry', dependsOn: resource, }); }); @@ -127,13 +125,8 @@ export default ({ return { name, - registry: resource as containerregistry.Registry, - vaultKeyNames: { - userNameKey, - primaryPasswordKey, - secondaryPasswordKey, - urlKey, - }, - diagnostic, + group, + id: resource.id, + instance: resource as registry.Registry, }; }; diff --git a/src/KeyVault/Helper.ts b/src/KeyVault/Helper.ts index 1ed51d90..dfd6e8fc 100644 --- a/src/KeyVault/Helper.ts +++ b/src/KeyVault/Helper.ts @@ -1,9 +1,9 @@ -import * as keyvault from "@pulumi/azure-native/keyvault"; -import { Input, Output, output, Resource } from "@pulumi/pulumi"; -import { KeyVaultInfo } from "../types"; -import { getSecretName } from "../Common/Naming"; -import { replaceAll } from "../Common/Helpers"; -import { getKeyVaultBase } from "@drunk-pulumi/azure-providers/AzBase/KeyVaultBase"; +import * as keyvault from '@pulumi/azure-native/keyvault'; +import { Input, Output, output, Resource } from '@pulumi/pulumi'; +import { KeyVaultInfo } from '../types'; +import { getSecretName } from '../Common/Naming'; +import { replaceAll } from '../Common/Helpers'; +import { getKeyVaultBase } from '@drunk-pulumi/azure-providers/AzBase/KeyVaultBase'; //known issue: https://github.com/pulumi/pulumi-azure-native/issues/1013 type SecretProps = { @@ -32,11 +32,11 @@ export const addKey = ({ vaultInfo, tags, dependsOn, -}: Omit) => { +}: Omit) => { const n = getSecretName(name); return new keyvault.Key( - replaceAll(name, ".", "-"), + replaceAll(name, '.', '-'), { keyName: n, vaultName: vaultInfo.name, @@ -44,14 +44,14 @@ export const addKey = ({ //https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.keyvault.webkey?view=azure-dotnet-legacy properties: { keySize: 2048, - kty: "RSA", + kty: 'RSA', keyOps: [ - "decrypt", - "encrypt", - "sign", - "verify", - "wrapKey", - "unwrapKey", + 'decrypt', + 'encrypt', + 'sign', + 'verify', + 'wrapKey', + 'unwrapKey', ], //curveName: 'P512', attributes: { enabled: true }, @@ -82,7 +82,7 @@ interface KeyVaultPropertiesResults { } interface EncryptionPropertiesArgs { - keySource: "Microsoft.KeyVault"; + keySource: 'Microsoft.KeyVault'; keyVaultProperties: Input; } @@ -103,9 +103,11 @@ const getEncryptionKey = async ( export const getEncryptionKeyOutput = ( name: string, - vaultInfo: KeyVaultInfo, -): Output => - output(getEncryptionKey(name, vaultInfo)); + vaultInfo?: KeyVaultInfo, +): Output | undefined => { + if (!vaultInfo) return undefined; + return output(getEncryptionKey(name, vaultInfo)); +}; /** Get Secret */ export const getSecret = async ({ @@ -129,11 +131,11 @@ interface KeyResult { /** Convert VaultId to VaultInfo */ export const parseKeyUrl = (keyUrl: string): KeyResult => { - const splits = keyUrl.split("/"); + const splits = keyUrl.split('/'); return { keyIdentityUrl: keyUrl, name: splits[4], - version: splits.length > 4 ? splits[5] : "", + version: splits.length > 4 ? splits[5] : '', vaultUrl: `https://${splits[2]}`, }; }; diff --git a/src/KeyVault/index.ts b/src/KeyVault/index.ts index eb60e688..964e238c 100644 --- a/src/KeyVault/index.ts +++ b/src/KeyVault/index.ts @@ -1,17 +1,17 @@ -import * as keyvault from "@pulumi/azure-native/keyvault"; -import { enums } from "@pulumi/azure-native/types"; -import { Input } from "@pulumi/pulumi"; -import { tenantId } from "../Common/AzureEnv"; -import { getKeyVaultName } from "../Common/Naming"; -import { createDiagnostic } from "../Logs/Helpers"; +import * as keyvault from '@pulumi/azure-native/keyvault'; +import { enums } from '@pulumi/azure-native/types'; +import { Input } from '@pulumi/pulumi'; +import { tenantId } from '../Common/AzureEnv'; +import { getKeyVaultName } from '../Common'; +import { createDiagnostic } from '../Logs/Helpers'; import { BasicMonitorArgs, + BasicResourceArgs, KeyVaultInfo, NetworkPropsType, PrivateLinkPropsType, -} from "../types"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import { BasicResourceArgs } from "../types"; +} from '../types'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; export interface KeyVaultProps extends BasicResourceArgs { softDeleteRetentionInDays?: Input; @@ -25,10 +25,10 @@ export const createVaultPrivateLink = ({ vaultInfo: KeyVaultInfo; }) => PrivateEndpoint({ - resourceInfo: { ...vaultInfo, resourceName: vaultInfo.name }, + resourceInfo: vaultInfo, ...props, - privateDnsZoneName: "privatelink.vaultcore.azure.net", - linkServiceGroupIds: props.type ? [props.type] : ["keyVault"], + privateDnsZoneName: 'privatelink.vaultcore.azure.net', + linkServiceGroupIds: props.type ? [props.type] : ['keyVault'], }); export const createVaultDiagnostic = ({ @@ -42,7 +42,7 @@ export const createVaultDiagnostic = ({ name: `${vaultInfo.name}-vault`, targetResourceId: vaultInfo.id, ...logInfo, - logsCategories: ["AuditEvent"], + logsCategories: ['AuditEvent'], }); export default ({ @@ -66,8 +66,8 @@ export default ({ properties: { tenantId, - sku: { name: "standard", family: "A" }, - createMode: "default", + sku: { name: 'standard', family: 'A' }, + createMode: 'default', enableRbacAuthorization: true, accessPolicies: undefined, @@ -80,7 +80,7 @@ export default ({ enabledForDiskEncryption: true, networkAcls: { - bypass: "AzureServices", + bypass: 'AzureServices', defaultAction: enums.keyvault.NetworkRuleAction.Allow, ipRules: network?.ipAddresses @@ -97,9 +97,9 @@ export default ({ dependsOn, import: importUri, ignoreChanges: [ - "softDeleteRetentionInDays", - "enableSoftDelete", - "enablePurgeProtection", + 'softDeleteRetentionInDays', + 'enableSoftDelete', + 'enablePurgeProtection', ...ignoreChanges, ], }, diff --git a/src/Logs/AppInsight.ts b/src/Logs/AppInsight.ts index e4f2d0bb..22a2f91d 100644 --- a/src/Logs/AppInsight.ts +++ b/src/Logs/AppInsight.ts @@ -1,10 +1,10 @@ -import * as native from "@pulumi/azure-native"; +import * as native from '@pulumi/azure-native'; -import { BasicResourceArgs, KeyVaultInfo, ResourceInfo } from "../types"; -import { getSecret } from "../KeyVault/Helper"; -import { getAppInsightName } from "../Common/Naming"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { Input } from "@pulumi/pulumi"; +import { BasicResourceArgs, KeyVaultInfo, ResourceInfo } from '../types'; +import { getSecret } from '../KeyVault/Helper'; +import { getAppInsightName } from '../Common'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { Input } from '@pulumi/pulumi'; interface Props extends BasicResourceArgs { dailyCapGb?: number; @@ -29,10 +29,10 @@ export default ({ resourceName: name, ...group, - kind: "web", + kind: 'web', disableIpMasking: true, - applicationType: "web", - flowType: "Bluefield", + applicationType: 'web', + flowType: 'Bluefield', //samplingPercentage: isPrd ? 100 : 50, retentionInDays: 30, @@ -47,7 +47,7 @@ export default ({ new native.insights.ComponentCurrentBillingFeature( `${name}-CurrentBillingFeature`, { - currentBillingFeatures: ["Basic"], // ['Basic', 'Application Insights Enterprise'], + currentBillingFeatures: ['Basic'], // ['Basic', 'Application Insights Enterprise'], dataVolumeCap: { cap: dailyCapGb, stopSendNotificationWhenHitCap: true, @@ -62,7 +62,7 @@ export default ({ name, value: appInsight.instrumentationKey, vaultInfo, - contentType: "AppInsight", + contentType: 'AppInsight', }); } @@ -77,8 +77,8 @@ export const getAppInsightKey = async ({ vaultInfo: KeyVaultInfo; }): Promise => { const key = await getSecret({ - name: resourceInfo.resourceName, + name: resourceInfo.name, vaultInfo, }); - return key?.value ?? ""; + return key?.value ?? ''; }; diff --git a/src/Logs/Helpers.ts b/src/Logs/Helpers.ts index 1df714dc..7124a91b 100644 --- a/src/Logs/Helpers.ts +++ b/src/Logs/Helpers.ts @@ -1,34 +1,34 @@ -import * as native from "@pulumi/azure-native"; -import { Input, interpolate, Output, output } from "@pulumi/pulumi"; +import * as native from '@pulumi/azure-native'; +import { Input, interpolate, Output, output } from '@pulumi/pulumi'; import { currentRegionName, parseResourceInfoFromId, subscriptionId, -} from "../Common/AzureEnv"; +} from '../Common/AzureEnv'; import { getAppInsightName, getKeyName, getLogWpName, getResourceGroupName, getStorageName, -} from "../Common/Naming"; -import { getSecret } from "../KeyVault/Helper"; -import { getStorageSecrets, StorageConnectionInfo } from "../Storage/Helper"; +} from '../Common'; +import { getSecret } from '../KeyVault/Helper'; +import { getStorageSecrets, StorageConnectionInfo } from '../Storage/Helper'; import { DiagnosticProps, KeyVaultInfo, ResourceGroupInfo, ResourceInfo, -} from "../types"; -import { getResourceName } from "../Common/ResourceEnv"; -import { getAppInsightKey } from "./AppInsight"; +} from '../types'; +import { getResourceName } from '../Common/ResourceEnv'; +import { getAppInsightKey } from './AppInsight'; export const createDiagnostic = ({ name, targetResourceId, logWpId, logStorageId, - metricsCategories = ["AllMetrics"], + metricsCategories = ['AllMetrics'], logsCategories, dependsOn, }: DiagnosticProps) => { @@ -52,7 +52,7 @@ export const createDiagnostic = ({ { name: n, resourceUri: targetResourceId, - logAnalyticsDestinationType: "AzureDiagnostics", + logAnalyticsDestinationType: 'AzureDiagnostics', workspaceId: logWpId, storageAccountId: logWpId ? undefined : logStorageId, @@ -90,7 +90,7 @@ export const createThreatProtection = ({ new native.security.AdvancedThreatProtection(name, { isEnabled: true, resourceId: targetResourceId, - settingName: "current", + settingName: 'current', }); //========================Log WP=========================== @@ -103,8 +103,8 @@ export const getLogWpSecrets = async ({ vaultInfo: KeyVaultInfo; }) => { const workspaceIdKeyName = `${fullName}-Id`; - const primaryKeyName = getKeyName(fullName, "primary"); - const secondaryKeyName = getKeyName(fullName, "secondary"); + const primaryKeyName = getKeyName(fullName, 'primary'); + const secondaryKeyName = getKeyName(fullName, 'secondary'); const [wpId, primaryKey, secondaryKey] = await Promise.all([ getSecret({ name: workspaceIdKeyName, vaultInfo }).then((i) => i?.value), @@ -158,7 +158,7 @@ export const getLogWpInfo = ({ ? output(getLogWpSecrets({ fullName: n, vaultInfo })) : undefined; - return { resourceName: n, group, id, secrets }; + return { name: n, group, id, secrets }; }; //========================Log Storage=========================== @@ -182,7 +182,7 @@ export const getLogStorageInfo = ({ ? output(getStorageSecrets({ name: n, nameFormatted: true, vaultInfo })) : undefined; - return { resourceName: n, group, id, secrets }; + return { name: n, group, id, secrets }; }; //========================App Insight=========================== @@ -205,13 +205,13 @@ export const getAppInsightInfo = ({ const instrumentationKey = vaultInfo ? output( getAppInsightKey({ - resourceInfo: { resourceName: n, group, id }, + resourceInfo: { name: n, group, id }, vaultInfo, }), ) : undefined; - return { resourceName: n, group, id, instrumentationKey }; + return { name: n, group, id, instrumentationKey }; }; export type LogInfoResults = { @@ -225,7 +225,7 @@ export const getLogInfo = ( vaultInfo: KeyVaultInfo | undefined = undefined, ): LogInfoResults => { const rgName = getResourceGroupName(groupName); - const name = getResourceName(groupName, { suffix: "logs" }); + const name = getResourceName(groupName, { suffix: 'logs' }); const group = { resourceGroupName: rgName, location: currentRegionName }; const logWp = getLogWpInfo({ diff --git a/src/MySql/index.ts b/src/MySql/index.ts index 3087b55f..fefa7bfe 100644 --- a/src/MySql/index.ts +++ b/src/MySql/index.ts @@ -1,20 +1,19 @@ -import * as azure from "@pulumi/azure-native"; -import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from "../types"; -import { getMySqlName } from "../Common/Naming"; -import * as pulumi from "@pulumi/pulumi"; -import * as dbformysql from "@pulumi/azure-native/dbformysql"; -import { randomPassword } from "../Core/Random"; -import * as inputs from "@pulumi/azure-native/types/input"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { isPrd, tenantId } from "../Common/AzureEnv"; -import { addMemberToGroup } from "../AzAd/Group"; -import { EnvRolesResults } from "../AzAd/EnvRoles"; -import { getEncryptionKeyOutput } from "../KeyVault/Helper"; -import UserAssignedIdentity from "../AzAd/UserAssignedIdentity"; -import { RandomString } from "@pulumi/random"; -import { convertToIpRange } from "../VNet/Helper"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import Locker from "../Core/Locker"; +import * as azure from '@pulumi/azure-native'; +import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from '../types'; +import { getMySqlName } from '../Common'; +import * as pulumi from '@pulumi/pulumi'; +import * as dbformysql from '@pulumi/azure-native/dbformysql'; +import { randomPassword } from '../Core/Random'; +import * as inputs from '@pulumi/azure-native/types/input'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { isPrd, tenantId } from '../Common/AzureEnv'; +import { addMemberToGroup } from '../AzAd/Group'; +import { EnvRolesResults } from '../AzAd/EnvRoles'; +import { getEncryptionKeyOutput } from '../KeyVault/Helper'; +import UserAssignedIdentity from '../AzAd/UserAssignedIdentity'; +import { RandomString } from '@pulumi/random'; +import { convertToIpRange } from '../VNet/Helper'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; export interface MySqlProps extends BasicResourceArgs { enableEncryption?: boolean; @@ -44,8 +43,8 @@ export default ({ [Standard_B1ms, Standard_B1s, Standard_B2ms, Standard_B2s, Standard_B4ms, Standard_B8ms, Standard_D16s_v3, Standard_D2s_v3, Standard_D32s_v3, Standard_D4s_v3, Standard_D64s_v3, Standard_D8s_v3, Standard_E16s_v3, Standard_E2s_v3, Standard_E32s_v3, Standard_E4s_v3, Standard_E64s_v3, Standard_E8s_v3, Standard_M128ms, Standard_M128s, Standard_M64ms, Standard_M64s, Standard_E48s_v3, Standard_D2ds_v4, Standard_D4ds_v4, Standard_D8ds_v4, Standard_D16ds_v4, Standard_D32ds_v4, Standard_D48ds_v4, Standard_D64ds_v4, Standard_E2ds_v4, Standard_E4ds_v4, Standard_E8ds_v4, Standard_E16ds_v4, Standard_E32ds_v4, Standard_E48ds_v4, Standard_E64ds_v4, Standard_D48s_v3, Standard_E20ds_v4, Standard_M8ms, Standard_M16ms, Standard_M32ts, Standard_M32ls, Standard_M32ms, Standard_M64ls, Standard_M64, Standard_M64m, Standard_M128, Standard_M128m, Standard_B12ms, Standard_B16ms, Standard_B20ms, Standard_D2ads_v5, Standard_D4ads_v5, Standard_D8ads_v5, Standard_D16ads_v5, Standard_D32ads_v5, Standard_D48ads_v5, Standard_D64ads_v5, Standard_D96ads_v5, Standard_E2ads_v5, Standard_E4ads_v5, Standard_E8ads_v5, Standard_E16ads_v5, Standard_E20ads_v5, Standard_E32ads_v5, Standard_E48ads_v5, Standard_E64ads_v5, Standard_E96ads_v5, Standard_D2_v5, Standard_D4_v5, Standard_D8_v5, Standard_D16_v5, Standard_D32_v5, Standard_D48_v5, Standard_D64_v5, Standard_D96_v5, Standard_D2ds_v5, Standard_D4ds_v5, Standard_D8ds_v5, Standard_D16ds_v5, Standard_D32ds_v5, Standard_D48ds_v5, Standard_D64ds_v5, Standard_D96ds_v5, Standard_E2ds_v5, Standard_E4ds_v5, Standard_E8ds_v5, Standard_E16ds_v5, Standard_E20ds_v5, Standard_E32ds_v5, Standard_E48ds_v5, Standard_E64ds_v5, Standard_E96ds_v5, Standard_E104ids_v5, Standard_E2bds_v5, Standard_E4bds_v5, Standard_E8bds_v5, Standard_E16bds_v5, Standard_E32bds_v5, Standard_E48bds_v5, Standard_E64bds_v5, Standard_E112iads_v5, Standard_M32dms_v2, Standard_M64ds_v2, Standard_M64dms_v2, Standard_M128ds_v2, Standard_M128dms_v2, Standard_M192ids_v2, Standard_M192idms_v2] */ sku = { - name: "Standard_B1ms", - tier: "Burstable", + name: 'Standard_B1ms', + tier: 'Burstable', }, network, databases, @@ -87,8 +86,8 @@ export default ({ version, storage: { storageSizeGB, - autoGrow: isPrd ? "Enabled" : "Disabled", - autoIoScaling: isPrd ? "Enabled" : "Disabled", + autoGrow: isPrd ? 'Enabled' : 'Disabled', + autoIoScaling: isPrd ? 'Enabled' : 'Disabled', }, // identity: { @@ -110,23 +109,23 @@ export default ({ //maintenanceWindow: { dayOfWeek: 6 }, sku, backup: { - geoRedundantBackup: isPrd ? "Enabled" : "Disabled", + geoRedundantBackup: isPrd ? 'Enabled' : 'Disabled', backupRetentionDays: isPrd ? 7 : 1, }, highAvailability: { - mode: isPrd ? "ZoneRedundant" : "Disabled", - standbyAvailabilityZone: "3", + mode: isPrd ? 'ZoneRedundant' : 'Disabled', + standbyAvailabilityZone: '3', }, - availabilityZone: isPrd ? "3" : "1", + availabilityZone: isPrd ? '3' : '1', }, { dependsOn, ignoreChanges: [ - "serverName", - "highAvailability", - "availabilityZone", - "administratorLogin", - "dataEncryption", + 'serverName', + 'highAvailability', + 'availabilityZone', + 'administratorLogin', + 'dataEncryption', ], }, ); @@ -147,7 +146,7 @@ export default ({ serverName: mySql.name, ...group, login: username, - administratorType: "ActiveDirectory", + administratorType: 'ActiveDirectory', sid: adminGroup.objectId, tenantId, }); @@ -174,17 +173,17 @@ export default ({ firewallRuleName: `${name}-firewall-allowpublic`, serverName: mySql.name, ...group, - startIpAddress: "0.0.0.0", - endIpAddress: "255.255.255.255", + startIpAddress: '0.0.0.0', + endIpAddress: '255.255.255.255', }); if (network.privateLink) { PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: mySql.id }, - privateDnsZoneName: "mysql.database.azure.com", + resourceInfo: { name, group, id: mySql.id }, + privateDnsZoneName: 'mysql.database.azure.com', linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["mysql"], + : ['mysql'], subnetIds: network.privateLink.subnetIds, }); } diff --git a/src/Postgresql/index.ts b/src/Postgresql/index.ts index a13bd8f1..993e1f1b 100644 --- a/src/Postgresql/index.ts +++ b/src/Postgresql/index.ts @@ -1,15 +1,15 @@ -import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from "../types"; -import { getPostgresqlName } from "../Common/Naming"; -import * as pulumi from "@pulumi/pulumi"; -import * as azure from "@pulumi/azure-native"; -import { isPrd, tenantId } from "../Common/AzureEnv"; -import { randomPassword } from "../Core/Random"; -import * as inputs from "@pulumi/azure-native/types/input"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { RandomString } from "@pulumi/random"; -import { convertToIpRange } from "../VNet/Helper"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import Locker from "../Core/Locker"; +import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from '../types'; +import { getPostgresqlName } from '../Common'; +import * as pulumi from '@pulumi/pulumi'; +import * as azure from '@pulumi/azure-native'; +import { isPrd, tenantId } from '../Common/AzureEnv'; +import { randomPassword } from '../Core/Random'; +import * as inputs from '@pulumi/azure-native/types/input'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { RandomString } from '@pulumi/random'; +import { convertToIpRange } from '../VNet/Helper'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; +import Locker from '../Core/Locker'; export interface PostgresProps extends BasicResourceArgs { // auth: { @@ -37,8 +37,8 @@ export default ({ [Standard_B1ms, Standard_B1s, Standard_B2ms, Standard_B2s, Standard_B4ms, Standard_B8ms, Standard_D16s_v3, Standard_D2s_v3, Standard_D32s_v3, Standard_D4s_v3, Standard_D64s_v3, Standard_D8s_v3, Standard_E16s_v3, Standard_E2s_v3, Standard_E32s_v3, Standard_E4s_v3, Standard_E64s_v3, Standard_E8s_v3, Standard_M128ms, Standard_M128s, Standard_M64ms, Standard_M64s, Standard_E48s_v3, Standard_D2ds_v4, Standard_D4ds_v4, Standard_D8ds_v4, Standard_D16ds_v4, Standard_D32ds_v4, Standard_D48ds_v4, Standard_D64ds_v4, Standard_E2ds_v4, Standard_E4ds_v4, Standard_E8ds_v4, Standard_E16ds_v4, Standard_E32ds_v4, Standard_E48ds_v4, Standard_E64ds_v4, Standard_D48s_v3, Standard_E20ds_v4, Standard_M8ms, Standard_M16ms, Standard_M32ts, Standard_M32ls, Standard_M32ms, Standard_M64ls, Standard_M64, Standard_M64m, Standard_M128, Standard_M128m, Standard_B12ms, Standard_B16ms, Standard_B20ms, Standard_D2ads_v5, Standard_D4ads_v5, Standard_D8ads_v5, Standard_D16ads_v5, Standard_D32ads_v5, Standard_D48ads_v5, Standard_D64ads_v5, Standard_D96ads_v5, Standard_E2ads_v5, Standard_E4ads_v5, Standard_E8ads_v5, Standard_E16ads_v5, Standard_E20ads_v5, Standard_E32ads_v5, Standard_E48ads_v5, Standard_E64ads_v5, Standard_E96ads_v5, Standard_D2_v5, Standard_D4_v5, Standard_D8_v5, Standard_D16_v5, Standard_D32_v5, Standard_D48_v5, Standard_D64_v5, Standard_D96_v5, Standard_D2ds_v5, Standard_D4ds_v5, Standard_D8ds_v5, Standard_D16ds_v5, Standard_D32ds_v5, Standard_D48ds_v5, Standard_D64ds_v5, Standard_D96ds_v5, Standard_E2ds_v5, Standard_E4ds_v5, Standard_E8ds_v5, Standard_E16ds_v5, Standard_E20ds_v5, Standard_E32ds_v5, Standard_E48ds_v5, Standard_E64ds_v5, Standard_E96ds_v5, Standard_E104ids_v5, Standard_E2bds_v5, Standard_E4bds_v5, Standard_E8bds_v5, Standard_E16bds_v5, Standard_E32bds_v5, Standard_E48bds_v5, Standard_E64bds_v5, Standard_E112iads_v5, Standard_M32dms_v2, Standard_M64ds_v2, Standard_M64dms_v2, Standard_M128ds_v2, Standard_M128dms_v2, Standard_M192ids_v2, Standard_M192idms_v2] */ sku = { - name: "Standard_B1ms", - tier: "Burstable", + name: 'Standard_B1ms', + tier: 'Burstable', }, network, databases, @@ -69,32 +69,32 @@ export default ({ storage: { storageSizeGB }, authConfig: { - passwordAuth: "Enabled", - activeDirectoryAuth: "Enabled", + passwordAuth: 'Enabled', + activeDirectoryAuth: 'Enabled', tenantId, }, administratorLogin: username, administratorLoginPassword: password, - dataEncryption: { type: "SystemManaged" }, + dataEncryption: { type: 'SystemManaged' }, //maintenanceWindow: { dayOfWeek: 6 }, sku, //network: {}, backup: { - geoRedundantBackup: isPrd ? "Enabled" : "Disabled", + geoRedundantBackup: isPrd ? 'Enabled' : 'Disabled', backupRetentionDays: 7, }, - highAvailability: { mode: isPrd ? "ZoneRedundant" : "Disabled" }, - availabilityZone: isPrd ? "3" : "1", + highAvailability: { mode: isPrd ? 'ZoneRedundant' : 'Disabled' }, + availabilityZone: isPrd ? '3' : '1', }, { dependsOn, protect: lock, ignoreChanges: [ - "serverName", - "highAvailability", - "availabilityZone", - "administratorLogin", - "dataEncryption", + 'serverName', + 'highAvailability', + 'availabilityZone', + 'administratorLogin', + 'dataEncryption', ], }, ); @@ -124,17 +124,17 @@ export default ({ firewallRuleName: `${name}-firewall-allowpublic`, serverName: postgres.name, ...group, - startIpAddress: "0.0.0.0", - endIpAddress: "255.255.255.255", + startIpAddress: '0.0.0.0', + endIpAddress: '255.255.255.255', }); if (network.privateLink) { PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: postgres.id }, - privateDnsZoneName: "postgres.database.azure.com", + resourceInfo: { name, group, id: postgres.id }, + privateDnsZoneName: 'postgres.database.azure.com', linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["postgresql"], + : ['postgresql'], subnetIds: network.privateLink.subnetIds, }); } diff --git a/src/RedisCache/index.ts b/src/RedisCache/index.ts index e27dffd0..c9d38d10 100644 --- a/src/RedisCache/index.ts +++ b/src/RedisCache/index.ts @@ -1,14 +1,14 @@ -import * as cache from "@pulumi/azure-native/cache"; -import * as pulumi from "@pulumi/pulumi"; +import * as cache from '@pulumi/azure-native/cache'; +import * as pulumi from '@pulumi/pulumi'; -import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from "../types"; +import { BasicResourceArgs, KeyVaultInfo, NetworkPropsType } from '../types'; -import { ToWords } from "to-words"; -import { convertToIpRange } from "../VNet/Helper"; -import { getRedisCacheName } from "../Common/Naming"; -import { isPrd } from "../Common/AzureEnv"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import privateEndpointCreator from "../VNet/PrivateEndpoint"; +import { ToWords } from 'to-words'; +import { convertToIpRange } from '../VNet/Helper'; +import { getRedisCacheName } from '../Common'; +import { isPrd } from '../Common/AzureEnv'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import privateEndpointCreator from '../VNet/PrivateEndpoint'; const toWord = new ToWords(); @@ -27,19 +27,19 @@ export default ({ group, network, vaultInfo, - sku = { name: "Basic", family: "C", capacity: 0 }, + sku = { name: 'Basic', family: 'C', capacity: 0 }, }: Props) => { name = getRedisCacheName(name); const redis = new cache.Redis(name, { name, ...group, - minimumTlsVersion: "1.2", + minimumTlsVersion: '1.2', enableNonSslPort: false, identity: { type: cache.ManagedServiceIdentityType.SystemAssigned }, sku, - zones: isPrd && sku.name === "Premium" ? ["1", "2", "3"] : undefined, + zones: isPrd && sku.name === 'Premium' ? ['1', '2', '3'] : undefined, subnetId: network?.subnetId, - publicNetworkAccess: network?.privateLink ? "Disabled" : "Enabled", + publicNetworkAccess: network?.privateLink ? 'Disabled' : 'Enabled', }); //Whitelist IpAddress @@ -61,12 +61,12 @@ export default ({ //Private Link if (network?.privateLink) { privateEndpointCreator({ - resourceInfo: { resourceName: name, group, id: redis.id }, - privateDnsZoneName: "privatelink.redis.cache.windows.net", + resourceInfo: { name, group, id: redis.id }, + privateDnsZoneName: 'privatelink.redis.cache.windows.net', subnetIds: network.privateLink.subnetIds, linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["redisCache"], + : ['redisCache'], }); } @@ -83,28 +83,28 @@ export default ({ name: `${name}-primary-key`, value: keys.primaryKey, vaultInfo, - contentType: "Redis Cache", + contentType: 'Redis Cache', }); addCustomSecret({ name: `${name}-secondary-key`, value: keys.secondaryKey, vaultInfo, - contentType: "Redis Cache", + contentType: 'Redis Cache', }); addCustomSecret({ name: `${name}-primary-connection`, value: `${name}.redis.cache.windows.net:6380,password=${keys.primaryKey},ssl=True,abortConnect=False`, vaultInfo, - contentType: "Redis Cache", + contentType: 'Redis Cache', }); addCustomSecret({ name: `${name}-secondary-connection`, value: `${name}.redis.cache.windows.net:6380,password=${keys.secondaryKey},ssl=True,abortConnect=False`, vaultInfo, - contentType: "Redis Cache", + contentType: 'Redis Cache', }); }); } diff --git a/src/ServiceBus/index.ts b/src/ServiceBus/index.ts index 161eefb1..55954d08 100644 --- a/src/ServiceBus/index.ts +++ b/src/ServiceBus/index.ts @@ -1,5 +1,5 @@ -import * as bus from "@pulumi/azure-native/servicebus"; -import * as pulumi from "@pulumi/pulumi"; +import * as bus from '@pulumi/azure-native/servicebus'; +import * as pulumi from '@pulumi/pulumi'; import { BasicArgs, BasicMonitorArgs, @@ -9,7 +9,7 @@ import { KeyVaultInfo, NetworkPropsType, ResourceGroupInfo, -} from "../types"; +} from '../types'; import { BusConnectionTypes, getNamespaceVaultName, @@ -17,25 +17,25 @@ import { getSubscriptionName, getTopicName, getTopicOrQueueVaultName, -} from "./ServiceBusHelper"; -import { isPrd } from "../Common/AzureEnv"; -import creator from "../Core/ResourceCreator"; -import { getPrivateEndpointName, getServiceBusName } from "../Common/Naming"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { getSecret } from "../KeyVault/Helper"; +} from './ServiceBusHelper'; +import { isPrd } from '../Common/AzureEnv'; +import creator from '../Core/ResourceCreator'; +import { getServiceBusName } from '../Common'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { getSecret } from '../KeyVault/Helper'; -type TransportTypes = "AmqpWebSockets" | "Amqp" | null; -const duplicateDetectedTime = isPrd ? "P3D" : "PT10M"; +type TransportTypes = 'AmqpWebSockets' | 'Amqp' | null; +const duplicateDetectedTime = isPrd ? 'P3D' : 'PT10M'; const defaultValues = { maxDeliveryCount: 10, enableBatchedOperations: true, - defaultMessageTtl: isPrd ? "P30D" : "P1D", - defaultMessageTimeToLive: isPrd ? "P30D" : "P1D", + defaultMessageTtl: isPrd ? 'P30D' : 'P1D', + defaultMessageTimeToLive: isPrd ? 'P30D' : 'P1D', deadLetteringOnMessageExpiration: true, maxSizeInMegabytes: 1024, - lockDuration: "PT1M", + lockDuration: 'PT1M', //Auto delete subscription after 30 idle. //autoDeleteOnIdle: 'P30D', @@ -65,7 +65,7 @@ const createAndStoreConnection = ({ topicName, queueName, connectionType, - transportType = "AmqpWebSockets", + transportType = 'AmqpWebSockets', resourceGroupName, removeEntityPath, vaultInfo, @@ -159,10 +159,10 @@ const createAndStoreConnection = ({ })); let primaryConn = removeEntityPath - ? keys.primaryConnectionString.replace(`;EntityPath=${name}`, "") + ? keys.primaryConnectionString.replace(`;EntityPath=${name}`, '') : keys.primaryConnectionString; - if (typeof transportType === "string") + if (typeof transportType === 'string') primaryConn += `;TransportType=${transportType};`; addCustomSecret({ @@ -174,10 +174,10 @@ const createAndStoreConnection = ({ }); let secondConn = removeEntityPath - ? keys.secondaryConnectionString.replace(`;EntityPath=${name}`, "") + ? keys.secondaryConnectionString.replace(`;EntityPath=${name}`, '') : keys.secondaryConnectionString; - if (typeof transportType === "string") + if (typeof transportType === 'string') secondConn += `;TransportType=${transportType};`; addCustomSecret({ @@ -193,7 +193,7 @@ const createAndStoreConnection = ({ }; interface TopicProps - extends Pick, + extends Pick, BasicArgs { shortName: string; namespaceFullName: string; @@ -347,7 +347,7 @@ const subscriptionCreator = ({ }; interface QueueProps - extends Pick, + extends Pick, BasicArgs { shortName: string; version: number; @@ -450,12 +450,12 @@ const queueCreator = ({ interface Props extends BasicResourceArgs, - Pick { + Pick { topics?: Array< - Omit + Omit >; queues?: Array< - Omit + Omit >; drConfig?: { alias?: pulumi.Input; @@ -499,7 +499,7 @@ export default ({ monitoring: monitoring ? { ...monitoring, - logsCategories: ["OperationalLogs"], + logsCategories: ['OperationalLogs'], } : undefined, } as bus.NamespaceArgs & DefaultResourceArgs); @@ -591,7 +591,7 @@ export default ({ new bus.NamespaceNetworkRuleSet(name, { namespaceName: namespace.name, ...group, - defaultAction: "Deny", + defaultAction: 'Deny', ipRules: network.ipAddresses ? network.ipAddresses.map((i) => ({ @@ -613,12 +613,12 @@ export default ({ if (network.privateLink) { PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: namespace.id }, + resourceInfo: { name, group, id: namespace.id }, subnetIds: network.privateLink.subnetIds, linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["namespace"], - privateDnsZoneName: "privatelink.servicebus.windows.net", + : ['namespace'], + privateDnsZoneName: 'privatelink.servicebus.windows.net', }); } } diff --git a/src/SignalR/index.ts b/src/SignalR/index.ts index f462c4b3..886e4571 100644 --- a/src/SignalR/index.ts +++ b/src/SignalR/index.ts @@ -1,19 +1,18 @@ -import * as native from "@pulumi/azure-native"; -import * as pulumi from "@pulumi/pulumi"; -import { isDev } from "../Common/AzureEnv"; -import { getPrivateEndpointName, getSignalRName } from "../Common/Naming"; +import * as native from '@pulumi/azure-native'; +import * as pulumi from '@pulumi/pulumi'; +import { getPrivateEndpointName, getSignalRName } from '../Common'; import { BasicResourceArgs, KeyVaultInfo, PrivateLinkPropsType, -} from "../types"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; +} from '../types'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; interface ResourceSkuArgs { capacity?: 1 | 2 | 5 | 10 | 20 | 50 | 100; - name: "Standard_S1" | "Free_F1"; - tier?: "Standard" | "Free"; + name: 'Standard_S1' | 'Free_F1'; + tier?: 'Standard' | 'Free'; } interface Props extends BasicResourceArgs { @@ -31,7 +30,7 @@ export default ({ privateLink, kind = native.signalrservice.ServiceKind.SignalR, sku = { - name: "Standard_S1", + name: 'Standard_S1', tier: native.signalrservice.SignalRSkuTier.Standard, capacity: 1, }, @@ -46,7 +45,7 @@ export default ({ cors: { allowedOrigins }, features: [ - { flag: "ServiceMode", value: "Default" }, + { flag: 'ServiceMode', value: 'Default' }, //{ flag: 'EnableConnectivityLogs', value: 'Default' }, ], networkACLs: privateLink @@ -86,10 +85,10 @@ export default ({ if (privateLink) { //The Private Zone will create in Dev and reuse for sandbox and prd. PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: signalR.id }, - privateDnsZoneName: "privatelink.service.signalr.net", + resourceInfo: { name, group, id: signalR.id }, + privateDnsZoneName: 'privatelink.service.signalr.net', subnetIds: privateLink.subnetIds, - linkServiceGroupIds: ["signalr"], + linkServiceGroupIds: ['signalr'], }); } @@ -106,35 +105,35 @@ export default ({ name: `${name}-host`, value: h, vaultInfo, - contentType: "SignalR", + contentType: 'SignalR', }); addCustomSecret({ name: `${name}-primaryKey`, - value: keys.primaryKey || "", + value: keys.primaryKey || '', vaultInfo, - contentType: "SignalR", + contentType: 'SignalR', }); addCustomSecret({ name: `${name}-primaryConnection`, - value: keys.primaryConnectionString || "", + value: keys.primaryConnectionString || '', vaultInfo, - contentType: "SignalR", + contentType: 'SignalR', }); addCustomSecret({ name: `${name}-secondaryKey`, - value: keys.secondaryKey || "", + value: keys.secondaryKey || '', vaultInfo, - contentType: "SignalR", + contentType: 'SignalR', }); addCustomSecret({ name: `${name}-secondaryConnection`, - value: keys.secondaryConnectionString || "", + value: keys.secondaryConnectionString || '', vaultInfo, - contentType: "SignalR", + contentType: 'SignalR', }); }); } diff --git a/src/Sql/index.ts b/src/Sql/index.ts index 710fca3d..c66f1058 100644 --- a/src/Sql/index.ts +++ b/src/Sql/index.ts @@ -1,22 +1,22 @@ -import * as sql from "@pulumi/azure-native/sql"; -import { all, Input, interpolate, Output } from "@pulumi/pulumi"; -import { getEncryptionKeyOutput } from "../KeyVault/Helper"; -import { EnvRolesResults } from "../AzAd/EnvRoles"; -import { roleAssignment } from "../AzAd/RoleAssignment"; -import { isPrd, subscriptionId, tenantId } from "../Common/AzureEnv"; -import { getElasticPoolName, getSqlServerName } from "../Common/Naming"; +import * as sql from '@pulumi/azure-native/sql'; +import { all, Input, interpolate, Output } from '@pulumi/pulumi'; +import { getEncryptionKeyOutput } from '../KeyVault/Helper'; +import { EnvRolesResults } from '../AzAd/EnvRoles'; +import { roleAssignment } from '../AzAd/RoleAssignment'; +import { isPrd, subscriptionId, tenantId } from '../Common/AzureEnv'; +import { getElasticPoolName, getSqlServerName } from '../Common/Naming'; import { BasicResourceArgs, BasicResourceResultProps, KeyVaultInfo, NetworkPropsType, ResourceInfo, -} from "../types"; -import { convertToIpRange } from "../VNet/Helper"; -import privateEndpointCreator from "../VNet/PrivateEndpoint"; -import sqlDbCreator, { SqlDbProps, SqlDbSku } from "./SqlDb"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; -import { grantIdentityPermissions } from "../AzAd/Helper"; +} from '../types'; +import { convertToIpRange } from '../VNet/Helper'; +import privateEndpointCreator from '../VNet/PrivateEndpoint'; +import sqlDbCreator, { SqlDbSku } from './SqlDb'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; +import { grantIdentityPermissions } from '../AzAd/Helper'; type ElasticPoolCapacityProps = 50 | 100 | 200 | 300 | 400 | 800 | 1200; @@ -24,7 +24,7 @@ interface ElasticPoolProps extends BasicResourceArgs { sqlName: Output; /** Minimum is 50 Gd*/ maxSizeBytesGb?: number; - sku?: { name: "Standard" | "Basic"; capacity: ElasticPoolCapacityProps }; + sku?: { name: 'Standard' | 'Basic'; capacity: ElasticPoolCapacityProps }; } const createElasticPool = ({ @@ -33,7 +33,7 @@ const createElasticPool = ({ sqlName, //Minimum is 50 GD maxSizeBytesGb = 50, - sku = { name: isPrd ? "Standard" : "Basic", capacity: 50 }, + sku = { name: isPrd ? 'Standard' : 'Basic', capacity: 50 }, }: ElasticPoolProps): BasicResourceResultProps => { //Create Sql Elastic const elasticName = getElasticPoolName(name); @@ -51,7 +51,7 @@ const createElasticPool = ({ }, perDatabaseSettings: { minCapacity: 0, - maxCapacity: sku.name === "Basic" ? 5 : sku.capacity, + maxCapacity: sku.name === 'Basic' ? 5 : sku.capacity, }, zoneRedundant: isPrd, //licenseType: sql.ElasticPoolLicenseType.BasePrice, @@ -62,7 +62,7 @@ const createElasticPool = ({ }; export type SqlAuthType = { - envRoles: EnvRolesResults; + envRoles?: EnvRolesResults; azureAdOnlyAuthentication?: boolean; adminLogin: Input; password: Input; @@ -74,7 +74,7 @@ export type SqlNetworkType = NetworkPropsType & { }; export type SqlElasticPoolType = { - name: "Standard" | "Basic"; + name: 'Standard' | 'Basic'; capacity: ElasticPoolCapacityProps; }; @@ -92,7 +92,7 @@ export type SqlVulnerabilityAssessmentType = { }; interface Props extends BasicResourceArgs { - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; enableEncryption?: boolean; /** if Auth is not provided it will be auto generated */ auth: SqlAuthType; @@ -113,18 +113,18 @@ export default ({ vaultInfo, network, vulnerabilityAssessment, - ignoreChanges = ["administratorLogin", "administrators"], + ignoreChanges = ['administratorLogin', 'administrators'], }: Props): SqlResults => { const sqlName = getSqlServerName(name); const encryptKey = enableEncryption ? getEncryptionKeyOutput(name, vaultInfo) : undefined; - const adminGroup = auth.envRoles.contributor; + const adminGroup = auth.envRoles?.contributor; if (auth.azureAdOnlyAuthentication) { - ignoreChanges.push("administratorLogin"); - ignoreChanges.push("administratorLoginPassword"); + ignoreChanges.push('administratorLogin'); + ignoreChanges.push('administratorLoginPassword'); } const sqlServer = new sql.Server( @@ -132,16 +132,20 @@ export default ({ { serverName: sqlName, ...group, - version: "12.0", - minimalTlsVersion: "1.2", + version: '12.0', + minimalTlsVersion: '1.2', - identity: { type: "SystemAssigned" }, + identity: { type: 'SystemAssigned' }, administratorLogin: auth?.adminLogin, administratorLoginPassword: auth?.password, administrators: { - administratorType: sql.AdministratorType.ActiveDirectory, - azureADOnlyAuthentication: Boolean(auth.azureAdOnlyAuthentication), + administratorType: adminGroup + ? sql.AdministratorType.ActiveDirectory + : undefined, + azureADOnlyAuthentication: Boolean( + adminGroup && auth.azureAdOnlyAuthentication, + ), principalType: sql.PrincipalType.Group, tenantId, @@ -161,7 +165,7 @@ export default ({ grantIdentityPermissions({ name, vaultInfo, - envRole: "readOnly", + envRole: 'readOnly', principalId: sqlServer.identity.apply((s) => s!.principalId), }); @@ -189,23 +193,23 @@ export default ({ //Private Link if (network?.privateLink) { privateEndpointCreator({ - resourceInfo: { resourceName: name, group, id: sqlServer.id }, - privateDnsZoneName: "privatelink.database.windows.net", + resourceInfo: { name, group, id: sqlServer.id }, + privateDnsZoneName: 'privatelink.database.windows.net', subnetIds: network.privateLink.subnetIds, linkServiceGroupIds: network.privateLink.type ? [network.privateLink.type] - : ["sqlServer"], + : ['sqlServer'], }); } //Allow Public Ip Accessing if (network?.acceptAllPublicConnect) { - new sql.FirewallRule("accept-all-connection", { - firewallRuleName: "accept-all-connection", + new sql.FirewallRule('accept-all-connection', { + firewallRuleName: 'accept-all-connection', serverName: sqlServer.name, ...group, - startIpAddress: "0.0.0.0", - endIpAddress: "255.255.255.255", + startIpAddress: '0.0.0.0', + endIpAddress: '255.255.255.255', }); } else if (network?.ipAddresses) { all(network.ipAddresses).apply((ips) => @@ -228,9 +232,9 @@ export default ({ if (vulnerabilityAssessment.logStorageId) { roleAssignment({ name, - principalId: sqlServer.identity.apply((i) => i?.principalId || ""), - principalType: "ServicePrincipal", - roleName: "Storage Blob Data Contributor", + principalId: sqlServer.identity.apply((i) => i?.principalId || ''), + principalType: 'ServicePrincipal', + roleName: 'Storage Blob Data Contributor', scope: vulnerabilityAssessment.logStorageId, }); } @@ -239,7 +243,7 @@ export default ({ const alertPolicy = new sql.ServerSecurityAlertPolicy( name, { - securityAlertPolicyName: "default", + securityAlertPolicyName: 'default', ...group, serverName: sqlServer.name, emailAccountAdmins: !vulnerabilityAssessment.alertEmails, @@ -249,7 +253,7 @@ export default ({ storageAccountAccessKey: vulnerabilityAssessment.storageAccessKey, storageEndpoint: vulnerabilityAssessment.storageEndpoint, - state: "Enabled", + state: 'Enabled', }, { dependsOn: sqlServer }, ); @@ -259,20 +263,20 @@ export default ({ name, { auditActionsAndGroups: [ - "SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP", - "FAILED_DATABASE_AUTHENTICATION_GROUP", - "BATCH_COMPLETED_GROUP", + 'SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP', + 'FAILED_DATABASE_AUTHENTICATION_GROUP', + 'BATCH_COMPLETED_GROUP', ], serverName: sqlServer.name, ...group, - blobAuditingPolicyName: "default", + blobAuditingPolicyName: 'default', isAzureMonitorTargetEnabled: true, isStorageSecondaryKeyInUse: false, predicateExpression: "object_name = 'SensitiveData'", queueDelayMs: 4000, retentionDays: isPrd ? 30 : 6, - state: "Enabled", + state: 'Enabled', isDevopsAuditEnabled: true, storageAccountAccessKey: vulnerabilityAssessment.storageAccessKey, @@ -311,20 +315,20 @@ export default ({ { resourceGroupName: group.resourceGroupName, serverName: sqlName, - serverKeyType: "AzureKeyVault", + serverKeyType: 'AzureKeyVault', keyName: encryptKey.keyName, uri: encryptKey.url, }, - { dependsOn: sqlServer, ignoreChanges: ["keyName", "uri"] }, + { dependsOn: sqlServer, ignoreChanges: ['keyName', 'uri'] }, ); new sql.EncryptionProtector( `${sqlName}-encryptionProtector`, { - encryptionProtectorName: "current", + encryptionProtectorName: 'current', resourceGroupName: group.resourceGroupName, serverName: sqlName, - serverKeyType: "AzureKeyVault", + serverKeyType: 'AzureKeyVault', serverKeyName: encryptKey.keyName, autoRotationEnabled: true, }, @@ -375,7 +379,7 @@ export default ({ // } return { - resourceName: sqlName, + name: sqlName, group, id: sqlServer.id, resource: sqlServer, diff --git a/src/Storage/Helper.ts b/src/Storage/Helper.ts index 08617340..23c89132 100644 --- a/src/Storage/Helper.ts +++ b/src/Storage/Helper.ts @@ -1,14 +1,14 @@ -import * as storage from "@pulumi/azure-native/storage"; +import * as storage from '@pulumi/azure-native/storage'; import { getConnectionName, getKeyName, getSecretName, getStorageName, -} from "../Common/Naming"; -import { getSecret } from "../KeyVault/Helper"; -import { BasicResourceArgs, KeyVaultInfo } from "../types"; -import { parseResourceInfoFromId } from "../Common/AzureEnv"; +} from '../Common'; +import { getSecret } from '../KeyVault/Helper'; +import { BasicResourceArgs, KeyVaultInfo } from '../types'; +import { parseResourceInfoFromId } from '../Common/AzureEnv'; export type StorageConnectionInfo = { primaryConnection: string; @@ -35,10 +35,10 @@ export const getStorageSecrets = async ({ vaultInfo: KeyVaultInfo; }): Promise => { name = nameFormatted ? name : getStorageName(name); - const primaryKeyName = getKeyName(name, "primary"); - const secondaryKeyName = getKeyName(name, "secondary"); - const primaryConnectionKeyName = getConnectionName(name, "primary"); - const secondConnectionKeyName = getConnectionName(name, "secondary"); + const primaryKeyName = getKeyName(name, 'primary'); + const secondaryKeyName = getKeyName(name, 'secondary'); + const primaryConnectionKeyName = getConnectionName(name, 'primary'); + const secondConnectionKeyName = getConnectionName(name, 'secondary'); const [primaryConnection, secondaryConnection, primaryKey, secondaryKey] = await Promise.all( diff --git a/src/Storage/index.ts b/src/Storage/index.ts index fb0b0ac0..3a0089b6 100644 --- a/src/Storage/index.ts +++ b/src/Storage/index.ts @@ -1,23 +1,19 @@ -import { KeyVaultSecret } from "@azure/keyvault-secrets"; -import * as storage from "@pulumi/azure-native/storage"; -import { KeyVaultInfo, BasicResourceArgs, ResourceInfo } from "../types"; -import { Input } from "@pulumi/pulumi"; -import { getSecret, getEncryptionKeyOutput } from "../KeyVault/Helper"; -import { isPrd } from "../Common/AzureEnv"; -import { - getConnectionName, - getKeyName, - getStorageName, -} from "../Common/Naming"; -import { addCustomSecrets } from "../KeyVault/CustomHelper"; -import Locker from "../Core/Locker"; -import privateEndpoint from "../VNet/PrivateEndpoint"; +import { KeyVaultSecret } from '@azure/keyvault-secrets'; +import * as storage from '@pulumi/azure-native/storage'; +import { BasicResourceArgs, KeyVaultInfo, ResourceInfo } from '../types'; +import { Input } from '@pulumi/pulumi'; +import { getEncryptionKeyOutput, getSecret } from '../KeyVault/Helper'; +import { isPrd } from '../Common/AzureEnv'; +import { getConnectionName, getKeyName, getStorageName } from '../Common'; +import { addCustomSecrets } from '../KeyVault/CustomHelper'; +import Locker from '../Core/Locker'; +import privateEndpoint from '../VNet/PrivateEndpoint'; import { createManagementRules, DefaultManagementRules, ManagementRules, -} from "./ManagementRules"; -import { grantIdentityPermissions } from "../AzAd/Helper"; +} from './ManagementRules'; +import { grantIdentityPermissions } from '../AzAd/Helper'; export type ContainerProps = { name: string; @@ -40,16 +36,16 @@ export type StoragePolicyType = { defaultManagementRules?: Array; }; export type StorageNetworkType = { - defaultByPass?: "AzureServices" | "None"; + defaultByPass?: 'AzureServices' | 'None'; vnet?: Array<{ subnetId?: Input; ipAddresses?: Array }>; privateEndpoint?: { subnetIds: Input[]; - type: "blob" | "table" | "queue" | "file" | "web" | "dfs"; + type: 'blob' | 'table' | 'queue' | 'file' | 'web' | 'dfs'; }; }; interface StorageProps extends BasicResourceArgs { //This is required for encryption key - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; containers?: Array; queues?: Array; @@ -63,7 +59,7 @@ interface StorageProps extends BasicResourceArgs { export type StorageResults = ResourceInfo & { instance: storage.StorageAccount; - getConnectionString: (name?: string) => Promise; + getConnectionString?: (name?: string) => Promise; }; /** Storage Creator */ @@ -81,10 +77,10 @@ export default ({ }: StorageProps): StorageResults => { name = getStorageName(name); - const primaryKeyName = getKeyName(name, "primary"); - const secondaryKeyName = getKeyName(name, "secondary"); - const primaryConnectionKeyName = getConnectionName(name, "primary"); - const secondConnectionKeyName = getConnectionName(name, "secondary"); + const primaryKeyName = getKeyName(name, 'primary'); + const secondaryKeyName = getKeyName(name, 'secondary'); + const primaryConnectionKeyName = getConnectionName(name, 'primary'); + const secondConnectionKeyName = getConnectionName(name, 'secondary'); const encryptionKey = featureFlags.enableKeyVaultEncryption ? getEncryptionKeyOutput(name, vaultInfo) : undefined; @@ -100,14 +96,14 @@ export default ({ ? storage.SkuName.Standard_ZRS //Zone redundant in PRD : storage.SkuName.Standard_LRS, }, - accessTier: "Hot", + accessTier: 'Hot', isHnsEnabled: true, enableHttpsTrafficOnly: true, allowBlobPublicAccess: policies?.allowBlobPublicAccess, allowSharedKeyAccess: featureFlags.allowSharedKeyAccess, - identity: { type: "SystemAssigned" }, - minimumTlsVersion: "TLS1_2", + identity: { type: 'SystemAssigned' }, + minimumTlsVersion: 'TLS1_2', //1 Year Months keyPolicy: { @@ -126,20 +122,20 @@ export default ({ keyType: storage.KeyType.Account, }, }, - keySource: "Microsoft.KeyVault", + keySource: 'Microsoft.KeyVault', keyVaultProperties: encryptionKey, } : undefined, sasPolicy: { expirationAction: storage.ExpirationAction.Log, - sasExpirationPeriod: "00.00:30:00", + sasExpirationPeriod: '00.00:30:00', }, - publicNetworkAccess: network?.privateEndpoint ? "Disabled" : "Enabled", + publicNetworkAccess: network?.privateEndpoint ? 'Disabled' : 'Enabled', networkRuleSet: { - bypass: network?.defaultByPass ?? "AzureServices", // Logging,Metrics,AzureServices or None - defaultAction: "Allow", + bypass: network?.defaultByPass ?? 'AzureServices', // Logging,Metrics,AzureServices or None + defaultAction: 'Allow', virtualNetworkRules: network?.vnet ? network.vnet @@ -155,7 +151,7 @@ export default ({ .flatMap((s) => s.ipAddresses) .map((i) => ({ iPAddressOrRange: i!, - action: "Allow", + action: 'Allow', })) : undefined, }, @@ -164,7 +160,7 @@ export default ({ if (network?.privateEndpoint) { //Create Private Endpoints privateEndpoint({ - resourceInfo: { resourceName: name, group, id: stg.id }, + resourceInfo: { name, group, id: stg.id }, subnetIds: network.privateEndpoint.subnetIds, privateDnsZoneName: `privatelink.${network.privateEndpoint.type}.core.windows.net`, linkServiceGroupIds: [network.privateEndpoint.type], @@ -191,8 +187,8 @@ export default ({ { accountName: stg.name, ...group, - indexDocument: "index.html", - error404Document: "index.html", + indexDocument: 'index.html', + error404Document: 'index.html', }, { dependsOn: stg }, ); @@ -205,7 +201,7 @@ export default ({ ...group, accountName: stg.name, //denyEncryptionScopeOverride: true, - publicAccess: c.public ? "Blob" : "None", + publicAccess: c.public ? 'Blob' : 'None', }); if (c.managementRules) { @@ -246,7 +242,7 @@ export default ({ grantIdentityPermissions({ name, vaultInfo, - envRole: "readOnly", + envRole: 'readOnly', principalId: stg.identity.apply((s) => s!.principalId), }); @@ -265,7 +261,7 @@ export default ({ //Keys addCustomSecrets({ vaultInfo, - contentType: "Storage", + contentType: 'Storage', formattedName: true, items: [ { @@ -290,11 +286,13 @@ export default ({ }); return { - resourceName: name, + name, group, id: stg.id, instance: stg, - getConnectionString: (name: string = primaryConnectionKeyName) => - getSecret({ name, nameFormatted: true, vaultInfo }), + getConnectionString: vaultInfo + ? (name: string = primaryConnectionKeyName) => + getSecret({ name, nameFormatted: true, vaultInfo }) + : undefined, }; }; diff --git a/src/VM/index.ts b/src/VM/index.ts index b555fff1..21b521d1 100644 --- a/src/VM/index.ts +++ b/src/VM/index.ts @@ -1,16 +1,16 @@ -import { Input, Resource } from "@pulumi/pulumi"; -import * as compute from "@pulumi/azure-native/compute"; -import * as network from "@pulumi/azure-native/network"; -import { BasicResourceArgs, KeyVaultInfo } from "../types"; -import { getNICName, getVMName } from "../Common/Naming"; -import Locker from "../Core/Locker"; -import { getEncryptionKeyOutput } from "../KeyVault/Helper"; -import GlobalSchedule from "./GlobalSchedule"; -import Extension, { VmExtensionProps } from "./Extension"; +import { Input, Resource } from '@pulumi/pulumi'; +import * as compute from '@pulumi/azure-native/compute'; +import * as network from '@pulumi/azure-native/network'; +import { BasicResourceArgs, KeyVaultInfo } from '../types'; +import { getNICName, getVMName } from '../Common/Naming'; +import Locker from '../Core/Locker'; +import { getEncryptionKeyOutput } from '../KeyVault/Helper'; +import GlobalSchedule from './GlobalSchedule'; +import Extension, { VmExtensionProps } from './Extension'; export type VmScheduleType = { /** The time zone ID: https://stackoverflow.com/questions/7908343/list-of-timezone-ids-for-use-with-findtimezonebyid-in-c */ - timeZone?: "Singapore Standard Time" | Input; + timeZone?: 'Singapore Standard Time' | Input; /** The format is ISO 8601 Standard ex: 2200 */ autoShutdownTime?: Input; /** The format is ISO 8601 Standard ex: 0900 */ @@ -25,24 +25,24 @@ interface Props extends BasicResourceArgs { storageAccountType?: compute.StorageAccountTypes; vmSize?: Input; login: { userName: Input; password?: Input }; - osType?: "Windows" | "Linux"; + osType?: 'Windows' | 'Linux'; image: { - offer: "WindowsServer" | "CentOS" | "Windows-10" | "windows-11" | string; + offer: 'WindowsServer' | 'CentOS' | 'Windows-10' | 'windows-11' | string; publisher: - | "MicrosoftWindowsServer" - | "MicrosoftWindowsDesktop" - | "Canonical" + | 'MicrosoftWindowsServer' + | 'MicrosoftWindowsDesktop' + | 'Canonical' | string; - sku: "2019-Datacenter" | "21h1-pro" | "win11-23h2-pro" | string; + sku: '2019-Datacenter' | '21h1-pro' | 'win11-23h2-pro' | string; }; enableEncryption?: boolean; - vaultInfo: KeyVaultInfo; + vaultInfo?: KeyVaultInfo; //licenseType?: 'None' | 'Windows_Client' | 'Windows_Server'; osDiskSizeGB?: number; dataDiskSizeGB?: number; schedule?: VmScheduleType; - extensions?: Array>; + extensions?: Array>; //This need a lock lock?: boolean; tags?: { [key: string]: Input }; @@ -53,15 +53,15 @@ export default ({ name, group, subnetId, - osType = "Windows", - vmSize = "Standard_B2s", + osType = 'Windows', + vmSize = 'Standard_B2s', extensions, storageAccountType = compute.StorageAccountTypes.Premium_LRS, osDiskSizeGB = 128, dataDiskSizeGB, enableEncryption, vaultInfo, - schedule = { timeZone: "Singapore Standard Time" }, + schedule = { timeZone: 'Singapore Standard Time' }, login, image, lock = true, @@ -76,7 +76,7 @@ export default ({ networkInterfaceName: nicName, ...group, ipConfigurations: [ - { name: "ipconfig", subnet: { id: subnetId }, primary: true }, + { name: 'ipconfig', subnet: { id: subnetId }, primary: true }, ], nicType: network.NetworkInterfaceNicType.Standard, }); @@ -97,8 +97,8 @@ export default ({ ...others, hardwareProfile: { vmSize }, - identity: { type: "SystemAssigned" }, - licenseType: "None", + identity: { type: 'SystemAssigned' }, + licenseType: 'None', networkProfile: { networkInterfaces: [{ id: nic.id, primary: true }], }, @@ -111,7 +111,7 @@ export default ({ //Need to be enabled at subscription level //requireGuestProvisionSignal: true, linuxConfiguration: - osType === "Linux" + osType === 'Linux' ? { //ssh: { publicKeys: [{ keyData: linux.sshPublicKey! }] }, disablePasswordAuthentication: false, @@ -131,7 +131,7 @@ export default ({ : undefined, windowsConfiguration: - osType === "Windows" + osType === 'Windows' ? { enableAutomaticUpdates: true, provisionVMAgent: true, @@ -148,35 +148,36 @@ export default ({ storageProfile: { imageReference: { ...image, - version: "latest", + version: 'latest', }, osDisk: { name: `${name}osdisk`, diskSizeGB: osDiskSizeGB, - caching: "ReadWrite", - createOption: "FromImage", + caching: 'ReadWrite', + createOption: 'FromImage', osType, - encryptionSettings: enableEncryption - ? { - diskEncryptionKey: diskEncryption - ? { - secretUrl: diskEncryption.url, - sourceVault: { - id: vaultInfo.id, - }, - } - : undefined, - keyEncryptionKey: keyEncryption - ? { - keyUrl: keyEncryption.url, - sourceVault: { - id: vaultInfo.id, - }, - } - : undefined, - enabled: enableEncryption, - } - : undefined, + encryptionSettings: + enableEncryption && vaultInfo + ? { + diskEncryptionKey: diskEncryption + ? { + secretUrl: diskEncryption.url, + sourceVault: { + id: vaultInfo.id, + }, + } + : undefined, + keyEncryptionKey: keyEncryption + ? { + keyUrl: keyEncryption.url, + sourceVault: { + id: vaultInfo.id, + }, + } + : undefined, + enabled: enableEncryption, + } + : undefined, managedDisk: { //Changes storage account type need to be done manually through portal. storageAccountType, @@ -206,9 +207,9 @@ export default ({ { dependsOn, ignoreChanges: [ - "storageProfile.osDisk.managedDisk.storageAccountType", - "storageProfile.osDisk.managedDisk.id", - "osDisk.osType", + 'storageProfile.osDisk.managedDisk.storageAccountType', + 'storageProfile.osDisk.managedDisk.id', + 'osDisk.osType', ], }, ); @@ -235,7 +236,7 @@ export default ({ time: schedule.autoShutdownTime, timeZone: schedule.timeZone, targetResourceId: vm.id, - task: "ComputeVmShutdownTask", //LabVmsShutdownTask,LabVmsStartupTask,LabVmReclamationTask,ComputeVmShutdownTask + task: 'ComputeVmShutdownTask', //LabVmsShutdownTask,LabVmsStartupTask,LabVmReclamationTask,ComputeVmShutdownTask dependsOn: vm, }); } diff --git a/src/VNet/Helper.ts b/src/VNet/Helper.ts index 0ae57afb..0a8c0cbd 100644 --- a/src/VNet/Helper.ts +++ b/src/VNet/Helper.ts @@ -1,25 +1,25 @@ -import * as network from "@pulumi/azure-native/network"; -import { Input, interpolate, output, Output } from "@pulumi/pulumi"; -import * as netmask from "netmask"; +import * as network from '@pulumi/azure-native/network'; +import { Input, interpolate, output, Output } from '@pulumi/pulumi'; +import * as netmask from 'netmask'; import { currentCountryCode, parseResourceInfoFromId, subscriptionId, -} from "../Common/AzureEnv"; +} from '../Common/AzureEnv'; import { getFirewallName, getIpAddressName, getResourceGroupName, getVnetName, -} from "../Common/Naming"; -import { ResourceGroupInfo } from "../types"; -import { VnetInfoType } from "./types"; +} from '../Common'; +import { ResourceGroupInfo } from '../types'; +import { VnetInfoType } from './types'; -export const appGatewaySubnetName = "app-gateway"; -export const gatewaySubnetName = "GatewaySubnet"; -export const azFirewallSubnet = "AzureFirewallSubnet"; -export const azFirewallManagementSubnet = "AzureFirewallManagementSubnet"; -export const azBastionSubnetName = "AzureBastionSubnet"; +export const appGatewaySubnetName = 'app-gateway'; +export const gatewaySubnetName = 'GatewaySubnet'; +export const azFirewallSubnet = 'AzureFirewallSubnet'; +export const azFirewallManagementSubnet = 'AzureFirewallManagementSubnet'; +export const azBastionSubnetName = 'AzureBastionSubnet'; export const getIpsRange = (prefix: string) => new netmask.Netmask(prefix); @@ -28,7 +28,7 @@ export const convertToIpRange = ( ipAddress: string[], ): Array<{ start: string; end: string }> => ipAddress.map((ip) => { - if (ip.includes("/")) { + if (ip.includes('/')) { const range = getIpsRange(ip); return { start: range.base, end: range.broadcast }; } @@ -37,7 +37,7 @@ export const convertToIpRange = ( export const getVnetIdFromSubnetId = (subnetId: string) => { //The sample SubnetId is /subscriptions/63a31b41-eb5d-4160-9fc9-d30fc00286c9/resourceGroups/sg-dev-aks-vnet/providers/Microsoft.Network/virtualNetworks/sg-vnet-trans/subnets/aks-main-nodes - return subnetId.split("/subnets")[0]; + return subnetId.split('/subnets')[0]; }; interface SubnetProps { diff --git a/src/VNet/PrivateEndpoint.ts b/src/VNet/PrivateEndpoint.ts index 4a0e8280..7caff037 100644 --- a/src/VNet/PrivateEndpoint.ts +++ b/src/VNet/PrivateEndpoint.ts @@ -1,12 +1,12 @@ -import * as network from "@pulumi/azure-native/network"; -import { output } from "@pulumi/pulumi"; -import { BasicArgs, PrivateLinkPropsType, ResourceInfo } from "../types"; -import { parseResourceInfoFromId } from "../Common/AzureEnv"; -import { getPrivateEndpointName } from "../Common/Naming"; -import { PrivateDnsZoneBuilder } from "../Builder"; +import * as network from '@pulumi/azure-native/network'; +import { output } from '@pulumi/pulumi'; +import { BasicArgs, PrivateLinkPropsType, ResourceInfo } from '../types'; +import { parseResourceInfoFromId } from '../Common/AzureEnv'; +import { getPrivateEndpointName } from '../Common'; +import { PrivateDnsZoneBuilder } from '../Builder'; -export type PrivateEndpointProps = Pick & - Pick & { +export type PrivateEndpointProps = Pick & + Pick & { resourceInfo: ResourceInfo; /** check the private link DNS Zone here https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-dns */ privateDnsZoneName: string; @@ -20,7 +20,7 @@ export default ({ linkServiceGroupIds, dependsOn, }: PrivateEndpointProps) => { - const name = getPrivateEndpointName(resourceInfo.resourceName); + const name = getPrivateEndpointName(resourceInfo.name); const endpoints = subnetIds.map( (s, index) => @@ -56,7 +56,7 @@ export default ({ group: resourceInfo!.group, dependsOn, }) - .withARecord({ ipAddresses: ip as string[], recordName: "@" }) + .withARecord({ ipAddresses: ip as string[], recordName: '@' }) .linkTo({ subnetIds, registrationEnabled: false }) .build(); }); diff --git a/src/VNet/Vnet.ts b/src/VNet/Vnet.ts index 3a549fa5..71a3243d 100644 --- a/src/VNet/Vnet.ts +++ b/src/VNet/Vnet.ts @@ -1,24 +1,24 @@ -import * as network from "@pulumi/azure-native/network"; -import * as pulumi from "@pulumi/pulumi"; -import { output as outputs } from "@pulumi/azure-native/types"; -import { BasicResourceArgs, ResourceInfo } from "../types"; -import { RouteArgs, CustomSecurityRuleArgs } from "./types"; +import * as network from '@pulumi/azure-native/network'; +import * as pulumi from '@pulumi/pulumi'; +import { output as outputs } from '@pulumi/azure-native/types'; +import { BasicResourceArgs, ResourceInfo } from '../types'; +import { CustomSecurityRuleArgs, RouteArgs } from './types'; import { appGatewaySubnetName, azBastionSubnetName, azFirewallManagementSubnet, azFirewallSubnet, gatewaySubnetName, -} from "./Helper"; -import { getVnetName } from "../Common/Naming"; -import CreateSubnet, { SubnetProps } from "./Subnet"; -import SecurityGroup from "./SecurityGroup"; -import RouteTable from "./RouteTable"; -import AppGatewaySecurityRule from "./NSGRules/AppGatewaySecurityRule"; +} from './Helper'; +import { getVnetName } from '../Common'; +import CreateSubnet, { SubnetProps } from './Subnet'; +import SecurityGroup from './SecurityGroup'; +import RouteTable from './RouteTable'; +import AppGatewaySecurityRule from './NSGRules/AppGatewaySecurityRule'; export type DelegateServices = - | "Microsoft.ContainerInstance/containerGroups" - | "Microsoft.Web/serverFarms"; + | 'Microsoft.ContainerInstance/containerGroups' + | 'Microsoft.Web/serverFarms'; export interface VnetProps extends BasicResourceArgs { ddosId?: pulumi.Input; @@ -40,7 +40,7 @@ export interface VnetProps extends BasicResourceArgs { appGatewaySubnet?: { addressPrefix: string; - version: "v1" | "v2"; + version: 'v1' | 'v2'; }; gatewaySubnet?: { @@ -164,14 +164,14 @@ export default ({ //Allow outbound internet if (!features.securityGroup.allowOutboundInternetAccess) { securityRules.push({ - name: "DefaultDeniedInternetOutbound", - sourceAddressPrefix: "*", - sourcePortRange: "*", - destinationAddressPrefix: "Internet", - destinationPortRange: "*", - protocol: "*", - access: "Deny", - direction: "Outbound", + name: 'DefaultDeniedInternetOutbound', + sourceAddressPrefix: '*', + sourcePortRange: '*', + destinationAddressPrefix: 'Internet', + destinationPortRange: '*', + protocol: '*', + access: 'Deny', + direction: 'Outbound', priority: 4096, //The last rule in the list; }); } @@ -221,7 +221,7 @@ export default ({ enableDdosProtection: ddosId !== undefined, ddosProtectionPlan: ddosId ? { id: ddosId } : undefined, }, - { dependsOn, ignoreChanges: ["virtualNetworkPeerings"] }, + { dependsOn, ignoreChanges: ['virtualNetworkPeerings'] }, ); const findSubnet = (name: string) => @@ -229,7 +229,7 @@ export default ({ //Return the results return { - resourceName: vName, + name: vName, group, id: vnet.id, vnet, diff --git a/src/Web/AppConfig.ts b/src/Web/AppConfig.ts index 2f38a038..ce2326e9 100644 --- a/src/Web/AppConfig.ts +++ b/src/Web/AppConfig.ts @@ -1,14 +1,14 @@ -import * as appConfig from "@pulumi/azure-native/appconfiguration"; -import { isPrd } from "../Common/AzureEnv"; -import { getAppConfigName, getPrivateEndpointName } from "../Common/Naming"; +import * as appConfig from '@pulumi/azure-native/appconfiguration'; +import { isPrd } from '../Common/AzureEnv'; +import { getAppConfigName } from '../Common/Naming'; import { KeyVaultInfo, PrivateLinkPropsType, ResourceGroupInfo, ResourceInfo, -} from "../types"; -import PrivateEndpoint from "../VNet/PrivateEndpoint"; -import { addCustomSecret } from "../KeyVault/CustomHelper"; +} from '../types'; +import PrivateEndpoint from '../VNet/PrivateEndpoint'; +import { addCustomSecret } from '../KeyVault/CustomHelper'; export type AppConfigProps = { name: string; @@ -34,7 +34,7 @@ export default ({ const app = new appConfig.ConfigurationStore(name, { configStoreName: name, ...group, - identity: { type: "SystemAssigned" }, + identity: { type: 'SystemAssigned' }, enablePurgeProtection: isPrd, softDeleteRetentionInDays: isPrd ? 7 : 1, disableLocalAuth, @@ -42,7 +42,7 @@ export default ({ ? appConfig.PublicNetworkAccess.Disabled : appConfig.PublicNetworkAccess.Enabled, - sku: { name: "Standard" }, + sku: { name: 'Standard' }, }); //Access Keys @@ -60,7 +60,7 @@ export default ({ //Only Read Connection String here if (key.readOnly) { addCustomSecret({ - name: key.name.includes("Primary") + name: key.name.includes('Primary') ? readPrimaryConnectionStringKey : readSecondaryConnectionStringKey, value: key.connectionString, @@ -76,15 +76,15 @@ export default ({ //Private Link if (privateLink) { PrivateEndpoint({ - resourceInfo: { resourceName: name, group, id: app.id }, - privateDnsZoneName: "privatelink.azconfig.io", - linkServiceGroupIds: ["appConfig"], + resourceInfo: { name, group, id: app.id }, + privateDnsZoneName: 'privatelink.azconfig.io', + linkServiceGroupIds: ['appConfig'], ...privateLink, }); } return { - resourceName: name, + name, group, id: app.id, instance: app, diff --git a/src/types.ts b/src/types.ts index d7654825..95eba450 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,6 +11,10 @@ export declare namespace NodeJS { } } +export type NamedResourceType = { + name: string; +}; + export interface ResourceInfoArg { /**If name and provider of the resource is not provided then the Id will be resource group Id*/ name?: Input; @@ -20,30 +24,30 @@ export interface ResourceInfoArg { subscriptionId?: Input; } -export interface BasicArgs { +export type BasicArgs = { dependsOn?: Input[]> | Input; importUri?: string; ignoreChanges?: string[]; -} +}; -export interface ResourceGroupInfo { +export type ResourceGroupInfo = { resourceGroupName: string; location?: Input; -} +}; -export interface ConventionProps { +export type ConventionProps = { prefix?: string; suffix?: string; /**Whether include the Azure Region name at the end of the name or not*/ region?: string; /**Whether include the organization name at the end of the name or not*/ includeOrgName?: boolean; -} +}; -export interface BasicMonitorArgs extends BasicArgs { +export type BasicMonitorArgs = BasicArgs & { logWpId?: Input; logStorageId?: Input; -} +}; export interface DiagnosticProps extends BasicMonitorArgs { name: string; @@ -59,10 +63,15 @@ export type ResourceType = { formattedName?: boolean; }; -export interface ResourceInfo { - resourceName: string; +export type ResourceInfo = NamedResourceType & { group: ResourceGroupInfo; id: Output; +}; + +export type KeyVaultInfo = ResourceInfo; + +export interface ResourceInfoWithInstance extends ResourceInfo { + instance: InstanceType; } export interface BasicResourceArgs extends BasicArgs { @@ -85,8 +94,7 @@ export type NetworkPropsType = { privateLink?: PrivateLinkPropsType; }; -export interface BasicResourceResultProps { - name: string; +export interface BasicResourceResultProps extends NamedResourceType { resource: TClass; } @@ -96,12 +104,6 @@ export interface ResourceResultProps diagnostic?: DiagnosticSetting; } -export interface KeyVaultInfo { - name: string; - group: ResourceGroupInfo; - id: Output; -} - export type IdentityRoleAssignment = { vaultInfo?: KeyVaultInfo; roles?: Array<{ name: string; scope: Input }>;