├── .gitignore ├── AnomaliesDetection ├── AnomaliesDetection.json ├── README.md └── images │ ├── KQL.jpg │ ├── apikey.jpg │ ├── compose.jpg │ ├── emailandvariable.jpg │ ├── identitypermission.jpg │ ├── openai.jpg │ ├── parallelism.jpg │ ├── question.jpg │ └── recurrence.jpg ├── Arc-SQL BPA ├── README.md ├── SQLBPA-V2.json └── images │ ├── ApiKey.jpg │ ├── BingKey.jpg │ ├── BingSearch.jpg │ ├── BingSearch_Conf.jpg │ ├── BingSearch_Creation.jpg │ ├── HelpLinkParameter.jpg │ ├── HighThroughput.jpg │ ├── SubRegistration.jpg │ ├── composeCSV.jpeg │ ├── deploy.jpg │ ├── enable.jpg │ ├── final-questiontoAI.jpg │ ├── http-connector.jpg │ ├── identity.jpg │ ├── query-value.jpg │ ├── recurrence.jpg │ ├── run-query-list-result1.jpg │ ├── run-query-list-result2.jpg │ ├── run-query-list-result3.jpg │ ├── send-email1.jpg │ ├── send-email2.jpg │ ├── sendEmail-broken.jpg │ ├── set-variable-redirect-url.jpeg │ ├── severity.jpg │ └── value-question.jpg ├── CODE_OF_CONDUCT.md ├── CostMonthlyCheck ├── CostMonthlyCheck.json ├── README.md └── images │ ├── ApiKey.jpg │ ├── OpenAI.jpg │ ├── Recurrence.jpg │ ├── Sub-Id.jpeg │ ├── example-notification.jpg │ └── identity.jpg ├── FunctionAppSmartDocs ├── README.md ├── function_app.py ├── host.json ├── images │ └── immagine.png ├── local.settings.json └── requirements.txt ├── GIT.jpg ├── LICENSE ├── Learning ├── README.md └── images │ ├── AC.png │ ├── Azure APIM.jpg │ ├── Azure Logic APp.jpg │ ├── AzureOpenAI.png │ ├── Learn.png │ ├── Microsoft Learn.jpg │ └── model.jpg ├── OpenAI-CoreIntegrationLZ ├── AIServicesForInfraELZ.json ├── AnomaliesDetection.json ├── CostMonthlyCheck.json ├── CreateFunction.json ├── README.md ├── SQLBPAV2.json ├── UpdateManagement.json ├── images │ ├── OpenAI-CoreIntegration_page-0001.jpg │ ├── deploy.jpeg │ ├── deployment_complete.jpeg │ └── start_deployment.jpeg ├── templateBingSearch.json └── templateOpenAI.json ├── Prereq.png ├── README.md ├── SECURITY.md ├── SUPPORT.md └── UpdateManagement ├── README.md ├── UpdateManagement.json └── images ├── ApiKey.jpg ├── Compose.jpeg ├── OpenAI.jpg ├── example-notification.jpg ├── identity.jpg └── recurrence.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /AnomaliesDetection/AnomaliesDetection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "workflows_OpenAIAnomalyDetectionAD_gen_name": { 6 | "defaultValue": "OpenAIAnomalyDetectionAD", 7 | "type": "String" 8 | }, 9 | "connections_azuremonitorlogs_1_externalid": { 10 | "defaultValue": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Web/connections/office365')]", 11 | "type": "String" 12 | } 13 | }, 14 | "variables": {}, 15 | "resources": [ 16 | { 17 | "type": "Microsoft.Logic/workflows", 18 | "apiVersion": "2017-07-01", 19 | "name": "[parameters('workflows_OpenAIAnomalyDetectionAD_gen_name')]", 20 | "location": "[resourceGroup().location]", 21 | "identity": { 22 | "type": "SystemAssigned" 23 | }, 24 | "properties": { 25 | "state": "Disabled", 26 | "definition": { 27 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", 28 | "contentVersion": "1.0.0.0", 29 | "parameters": { 30 | "$connections": { 31 | "defaultValue": {}, 32 | "type": "Object" 33 | } 34 | }, 35 | "triggers": { 36 | "Recurrence": { 37 | "recurrence": { 38 | "frequency": "Day", 39 | "interval": 1, 40 | "timeZone": "W. Europe Standard Time", 41 | "schedule": { 42 | "hours": [ 43 | "9" 44 | ] 45 | } 46 | }, 47 | "evaluatedRecurrence": { 48 | "frequency": "Day", 49 | "interval": 1, 50 | "timeZone": "W. Europe Standard Time", 51 | "schedule": { 52 | "hours": [ 53 | "9" 54 | ] 55 | } 56 | }, 57 | "type": "Recurrence" 58 | } 59 | }, 60 | "actions": { 61 | "Api-Key": { 62 | "runAfter": { 63 | "Run_query_and_list_results_V2_(Preview)": [ 64 | "Succeeded" 65 | ] 66 | }, 67 | "type": "InitializeVariable", 68 | "inputs": { 69 | "variables": [ 70 | { 71 | "name": "Api-Key", 72 | "type": "string", 73 | "value": "replace with your OpenAI api key" 74 | } 75 | ] 76 | } 77 | }, 78 | "Compose": { 79 | "runAfter": { 80 | "Clean_Result_III": [ 81 | "Succeeded" 82 | ] 83 | }, 84 | "type": "Compose", 85 | "inputs": "\n\n

Sistema automatico di segnalazione anomalie in ambiente AD- SiverzaLab Environment
\n
\nSalve, a seguito di un analisi all'interno dell'infrastruttura monitorata, è stato evidenziata la seguente anomalia:

\n-------------------------------------------------------------------------------------
\n
\n@{variables('ReportIII')}\n
\n
\n
\n

\n(*) Il sistema genera i dati sfruttando l'OpenAI pertando protrebbero verificarsi delle anomalie nel testo inerenti alla formattazione.

\n\"\"\n\n" 86 | }, 87 | "For_each_result": { 88 | "foreach": "@body('Run_query_and_list_results_V2_(Preview)')?['value']", 89 | "actions": { 90 | "Update_variable_Question": { 91 | "type": "SetVariable", 92 | "inputs": { 93 | "name": "Question", 94 | "value": "E' stata identificata la seguente anomalia da un sistema di monitoraggio. Dai qualche info in più su quando è stato identificato il messaggio, che EventID è con informazioni relative all'errore e la risorsa di riferimento, nient'altro:TimeGenerated=\n@{item()?['TimeGenerated']};@{item()?['ActualUsage']};@{item()?['ExpectedUsage']};@{item()?['AnomalyScore']};EvendID=@{item()?['EventID']};DC=@{item()?['Computer']}\nSegui questo esempio e usa \";\" come separatore:\nIl giorno 24 novembre 2024 alle ore 15 è stata segnalata un'anomalia sul sistema @{item()?['Computer']} con eventID @{item()?['EventID']}; L'event ID indica problemi di autenticazione utente;Alcuni step per il troublescooting:;Verifica Event Viewer; Verifica accessi anomali all'infrastruttura; Controlla le performance dell'applicazione;\n\n " 95 | } 96 | }, 97 | "Ask_to_OpenAI": { 98 | "runAfter": { 99 | "Update_variable_Question": [ 100 | "Succeeded" 101 | ] 102 | }, 103 | "type": "Http", 104 | "inputs": { 105 | "uri": "https://changeendpointname.openai.azure.com/openai/deployments/changemodelname/chat/completions?api-version=2024-02-15-preview", 106 | "method": "POST", 107 | "headers": { 108 | "Content-Type": "application/json", 109 | "api-key": "@variables('Api-Key')" 110 | }, 111 | "body": { 112 | "max_tokens": 600, 113 | "temperature": 0.3, 114 | "messages": [ 115 | { 116 | "content": "Sei un assistente che elenca le anomalie avvenute sui Domain Controllers di Microsoft Active Directory.", 117 | "role": "user" 118 | }, 119 | { 120 | "content": "@{variables('Question')}", 121 | "role": "user" 122 | } 123 | ] 124 | } 125 | } 126 | }, 127 | "Parse_OpenAI_response": { 128 | "runAfter": { 129 | "Ask_to_OpenAI": [ 130 | "Succeeded" 131 | ] 132 | }, 133 | "type": "ParseJson", 134 | "inputs": { 135 | "content": "@body('Ask_to_OpenAI')", 136 | "schema": { 137 | "properties": { 138 | "body": { 139 | "properties": { 140 | "choices": { 141 | "items": { 142 | "properties": { 143 | "content_filter_results": { 144 | "properties": { 145 | "hate": { 146 | "properties": { 147 | "filtered": { 148 | "type": "boolean" 149 | }, 150 | "severity": { 151 | "type": "string" 152 | } 153 | }, 154 | "type": "object" 155 | }, 156 | "self_harm": { 157 | "properties": { 158 | "filtered": { 159 | "type": "boolean" 160 | }, 161 | "severity": { 162 | "type": "string" 163 | } 164 | }, 165 | "type": "object" 166 | }, 167 | "sexual": { 168 | "properties": { 169 | "filtered": { 170 | "type": "boolean" 171 | }, 172 | "severity": { 173 | "type": "string" 174 | } 175 | }, 176 | "type": "object" 177 | }, 178 | "violence": { 179 | "properties": { 180 | "filtered": { 181 | "type": "boolean" 182 | }, 183 | "severity": { 184 | "type": "string" 185 | } 186 | }, 187 | "type": "object" 188 | } 189 | }, 190 | "type": "object" 191 | }, 192 | "finish_reason": { 193 | "type": "string" 194 | }, 195 | "index": { 196 | "type": "integer" 197 | }, 198 | "message": { 199 | "properties": { 200 | "content": { 201 | "type": "string" 202 | }, 203 | "role": { 204 | "type": "string" 205 | } 206 | }, 207 | "type": "object" 208 | } 209 | }, 210 | "required": [ 211 | "index", 212 | "finish_reason", 213 | "message", 214 | "content_filter_results" 215 | ], 216 | "type": "object" 217 | }, 218 | "type": "array" 219 | }, 220 | "created": { 221 | "type": "integer" 222 | }, 223 | "id": { 224 | "type": "string" 225 | }, 226 | "model": { 227 | "type": "string" 228 | }, 229 | "object": { 230 | "type": "string" 231 | }, 232 | "prompt_filter_results": { 233 | "items": { 234 | "properties": { 235 | "content_filter_results": { 236 | "properties": { 237 | "hate": { 238 | "properties": { 239 | "filtered": { 240 | "type": "boolean" 241 | }, 242 | "severity": { 243 | "type": "string" 244 | } 245 | }, 246 | "type": "object" 247 | }, 248 | "self_harm": { 249 | "properties": { 250 | "filtered": { 251 | "type": "boolean" 252 | }, 253 | "severity": { 254 | "type": "string" 255 | } 256 | }, 257 | "type": "object" 258 | }, 259 | "sexual": { 260 | "properties": { 261 | "filtered": { 262 | "type": "boolean" 263 | }, 264 | "severity": { 265 | "type": "string" 266 | } 267 | }, 268 | "type": "object" 269 | }, 270 | "violence": { 271 | "properties": { 272 | "filtered": { 273 | "type": "boolean" 274 | }, 275 | "severity": { 276 | "type": "string" 277 | } 278 | }, 279 | "type": "object" 280 | } 281 | }, 282 | "type": "object" 283 | }, 284 | "prompt_index": { 285 | "type": "integer" 286 | } 287 | }, 288 | "required": [ 289 | "prompt_index", 290 | "content_filter_results" 291 | ], 292 | "type": "object" 293 | }, 294 | "type": "array" 295 | }, 296 | "usage": { 297 | "properties": { 298 | "completion_tokens": { 299 | "type": "integer" 300 | }, 301 | "prompt_tokens": { 302 | "type": "integer" 303 | }, 304 | "total_tokens": { 305 | "type": "integer" 306 | } 307 | }, 308 | "type": "object" 309 | } 310 | }, 311 | "type": "object" 312 | } 313 | }, 314 | "type": "object" 315 | } 316 | } 317 | }, 318 | "For_each": { 319 | "foreach": "@outputs('Parse_OpenAI_response')?['body']?['choices']", 320 | "actions": { 321 | "Append_to_array_variable": { 322 | "type": "AppendToArrayVariable", 323 | "inputs": { 324 | "name": "Anomalies", 325 | "value": "@items('For_each')?['message']?['content']" 326 | } 327 | } 328 | }, 329 | "runAfter": { 330 | "Parse_OpenAI_response": [ 331 | "Succeeded" 332 | ] 333 | }, 334 | "type": "Foreach" 335 | } 336 | }, 337 | "runAfter": { 338 | "Set_Variable_Anomaly_Detection": [ 339 | "Succeeded" 340 | ] 341 | }, 342 | "type": "Foreach", 343 | "runtimeConfiguration": { 344 | "concurrency": { 345 | "repetitions": 1 346 | } 347 | } 348 | }, 349 | "Run_query_and_list_results_V2_(Preview)": { 350 | "runAfter": {}, 351 | "type": "ApiConnection", 352 | "inputs": { 353 | "host": { 354 | "connection": { 355 | "name": "@parameters('$connections')['azuremonitorlogs-1']['connectionId']" 356 | } 357 | }, 358 | "method": "post", 359 | "body": { 360 | "query": "let starttime = 7d; \nlet endtime = 0d;\nlet timeframe = 60m;\nEvent \n| where TimeGenerated between (startofday(ago(starttime)) .. startofday(ago(endtime))) \n| where Computer startswith \"DC\"\n| where RenderedDescription contains \"error\" \n| summarize count() by bin(TimeGenerated, 60s), Computer, EventID \n| make-series ActualUsage=avg(count_) default = 0 on TimeGenerated from startofday(ago(starttime)) \tto startofday(ago(endtime)) step timeframe by Computer, EventID \n| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(ActualUsage) \n| mv-expand\n ActualUsage to typeof(double),\n TimeGenerated to typeof(datetime),\n Anomalies to typeof(double),\n AnomalyScore to typeof(double),\n ExpectedUsage to typeof(long)\n| where abs(AnomalyScore) > 7 and abs(ActualUsage - ExpectedUsage) / ActualUsage > 0.5 \n| project TimeGenerated, ActualUsage, ExpectedUsage, abs(AnomalyScore), EventID, Computer\n| sort by abs(AnomalyScore) desc", 361 | "timerangetype": "3" 362 | }, 363 | "path": "/queryDataV2", 364 | "queries": { 365 | "subscriptions": "replacewithsubid", 366 | "resourcegroups": "replacewithR", 367 | "resourcetype": "Log Analytics Workspace", 368 | "resourcename": "replacewithRN" 369 | } 370 | } 371 | }, 372 | "Set_Variable_Question": { 373 | "runAfter": { 374 | "Api-Key": [ 375 | "Succeeded" 376 | ] 377 | }, 378 | "type": "InitializeVariable", 379 | "inputs": { 380 | "variables": [ 381 | { 382 | "name": "Question", 383 | "type": "string" 384 | } 385 | ] 386 | } 387 | }, 388 | "Set_Variable_Anomaly_Detection": { 389 | "runAfter": { 390 | "Set_Variable_Question": [ 391 | "Succeeded" 392 | ] 393 | }, 394 | "type": "InitializeVariable", 395 | "inputs": { 396 | "variables": [ 397 | { 398 | "name": "Anomalies", 399 | "type": "array" 400 | } 401 | ] 402 | } 403 | }, 404 | "Clean_Result_I": { 405 | "runAfter": { 406 | "For_each_result": [ 407 | "Succeeded" 408 | ] 409 | }, 410 | "type": "InitializeVariable", 411 | "inputs": { 412 | "variables": [ 413 | { 414 | "name": "Report", 415 | "type": "string", 416 | "value": "@replace(string(variables('Anomalies')), '[\"','
')" 417 | } 418 | ] 419 | } 420 | }, 421 | "Clean_Result_II": { 422 | "runAfter": { 423 | "Clean_Result_I": [ 424 | "Succeeded" 425 | ] 426 | }, 427 | "type": "InitializeVariable", 428 | "inputs": { 429 | "variables": [ 430 | { 431 | "name": "ReportII", 432 | "type": "string", 433 | "value": "@replace(variables('Report'), '\",\"','
')" 434 | } 435 | ] 436 | } 437 | }, 438 | "Clean_Result_III": { 439 | "runAfter": { 440 | "Clean_Result_II": [ 441 | "Succeeded" 442 | ] 443 | }, 444 | "type": "InitializeVariable", 445 | "inputs": { 446 | "variables": [ 447 | { 448 | "name": "ReportIII", 449 | "type": "string", 450 | "value": "@replace(variables('ReportII'), '\"]','
')" 451 | } 452 | ] 453 | } 454 | } 455 | }, 456 | "outputs": {} 457 | }, 458 | "parameters": { 459 | "$connections": { 460 | "value": { 461 | 462 | } 463 | } 464 | } 465 | } 466 | } 467 | ] 468 | } -------------------------------------------------------------------------------- /AnomaliesDetection/README.md: -------------------------------------------------------------------------------- 1 |

Azure Anomalies Detection integration: Configuration

2 | 3 | | **Parameters** | **Information** | **Note** | 4 | | ------------- | ------------- | ------------- | 5 | | recurrence | The scheduled option for manage the Logic App execution | Configure the recurrence following your requirements | 6 | | api-key | The API code for manage your OpenAI service | Put your question in the "value" attribute | 7 | | changeendpointname | Insert the OpenAI endpoint name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 8 | | changemodelname | Insert the model name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 9 | 10 |

Important

11 | This LogApp and the following changes are an example of integrating AnomalyDetection results with OpenAI, creating a report to send via Email with OpenAI comment. 12 | 13 | 14 |

Required Identity

15 |

Managed Identity

16 | 17 | After the deployment the Logic App is ready to be configured. As a first requirement, check if the Managed Identity is active and assign the required permission to work with the required resources (Log Analytics). 18 | 19 | 20 | ![identity](./images/identitypermission.jpg) 21 | 22 | Ad this point, in the Logic App Designer, configure the Recurrence following your requirements. 23 | 24 | 25 | ![Recurrence](./images/recurrence.jpg) 26 | 27 | 28 | "Run query and list result V2" is the core block here. We have to replace the block using the same one and modify the query. Below you can found the block and the query: 29 | 30 | 31 | ![Query](./images/KQL.jpg) 32 | 33 | ```KQL 34 | let starttime = 7d; 35 | let endtime = 0d; 36 | let timeframe = 60m; 37 | Event 38 | | where TimeGenerated between (startofday(ago(starttime)) .. startofday(ago(endtime))) 39 | | where Computer startswith "DC" 40 | | where RenderedDescription contains "error" 41 | | summarize count() by bin(TimeGenerated, 60s), Computer, EventID 42 | | make-series ActualUsage=avg(count_) default = 0 on TimeGenerated from startofday(ago(starttime)) to startofday(ago(endtime)) step timeframe by Computer, EventID 43 | | extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(ActualUsage) 44 | | mv-expand 45 | ActualUsage to typeof(double), 46 | TimeGenerated to typeof(datetime), 47 | Anomalies to typeof(double), 48 | AnomalyScore to typeof(double), 49 | ExpectedUsage to typeof(long) 50 | | where abs(AnomalyScore) > 7 and abs(ActualUsage - ExpectedUsage) / ActualUsage > 0.5 51 | | project TimeGenerated, ActualUsage, ExpectedUsage, abs(AnomalyScore), EventID, Computer 52 | | sort by abs(AnomalyScore) desc 53 | ``` 54 | 55 | 56 | The Api-Key is needed for interact with the OpenAI model. You can place your key in the "Api-Key" variable. 57 | 58 | 59 | ![Api-Key](./images/apikey.jpg) 60 | 61 | 62 | Leave the Set Variable Question and Set Variable Anomaly Detection empty, the focus now is the For_each_result. Click on it, swith to "Setting", activate the "Limit" and set the "Degree of parallelism" to 1: 63 | 64 | 65 | ![foreach](./images/parallelism.jpg) 66 | 67 | 68 | "Update variable Question" is another important point, because it handle the question that we pass to OpenAI. Modify the variable following your requirements. 69 | 70 | 71 | ![question](./images/question.jpg) 72 | 73 | 74 | At this point is importat to customize the "Ask to OpenAI" block. This block handle the communication with the LLM model. Customize the required parameters. 75 | 76 | 77 | ![OpenAI](./images/openai.jpg) 78 | 79 | 80 | One of the last block to customize is the "Compose", because it manage the format of the communication that the e-mail block send to the attenders. Here you can found an example: 81 | 82 | ```Compose 83 | 84 | 85 |

Sistema automatico di segnalazione anomalie in ambiente AD- SiverzaLab Environment
86 |
87 | Salve, a seguito di un analisi all'interno dell'infrastruttura monitorata, è stato evidenziata la seguente anomalia:

88 | -------------------------------------------------------------------------------------
89 |
90 | @{variables('ReportIII')} 91 |
92 |
93 |
94 |

95 | (*) Il sistema genera i dati sfruttando l'OpenAI pertando protrebbero verificarsi delle anomalie nel testo inerenti alla formattazione.

96 | 97 | 98 | 99 | ``` 100 | > [!TIP] 101 | > The provided Logic App, as an artifact, will send an email without a condition. An improvement could be to manage the result using a condition, and if the condition is not satisfied, send an e-mail, in order to avoid unattended results. The configuration is up to your requirements. 102 | 103 | ![Compose](./images/compose.jpg) 104 | 105 | 106 | The last point, we are talking about the "Send an email (V2) block. This block is used for send communication to the attenders. Customize the email, you can use the example below: 107 | 108 | 109 | ![email](./images/emailandvariable.jpg) -------------------------------------------------------------------------------- /AnomaliesDetection/images/KQL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/KQL.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/apikey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/apikey.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/compose.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/compose.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/emailandvariable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/emailandvariable.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/identitypermission.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/identitypermission.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/openai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/openai.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/parallelism.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/parallelism.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/question.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/question.jpg -------------------------------------------------------------------------------- /AnomaliesDetection/images/recurrence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/AnomaliesDetection/images/recurrence.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/README.md: -------------------------------------------------------------------------------- 1 |

Azure SQL BPA OpenAI integration: Configuration

2 | 3 | | **Parameters/Requirements** | **Information** | **Note** | 4 | | ------------- | ------------- | ------------- | 5 | | Azure OpenAI Model | This solution require specific Azure OpenAI Model | Version gpt-4-1106-preview | 6 | | replacewithsubid | Connection setting during deployment | Replace with your Subscription ID | 7 | | replacewithRG | Connection setting during deployment | Replace with the selected RG Name for the deployment | 8 | | replace with tenant id | HTTP Module: Tenant ID | Replace with your Tenant ID | 9 | | OpenAI API Key | String Resource to connect to OpenAI | Replace with your Azure OpenAI Key | 10 | 11 | 12 |

Important

13 | This LogApp and the following changes are an example of integrating SQL BPA results with OpenAI, creating an HTML report and CSV file send via Email with OpenAI comment of Severity High and/or Medium results. 14 | You can customize them to your liking such as changing the query and/or question to ChatGPT as well as sending the results not only via email but also to Ondrive or Storage Account for example. 15 | Before using it you must have enabled and performed SQL Best Practices Assessment on your hybrid Machine. 16 | 17 | 18 | Reference: 19 | [Azure ARC SQL Assessment](https://learn.microsoft.com/en-us/sql/sql-server/azure-arc/assess?view=sql-server-ver16&tabs=portal) 20 | 21 |

Deploy

22 | 23 | When you deploy, replace with your SubscriptionID and ResourceGroup Name: 24 | 25 | ![iDeploy](./images/deploy.jpg) 26 | 27 | 28 |

Required Identity

29 |

Managed Identity

30 | 31 | When the deployment is completed go in your Logic App and create a Managed Identity following the example below and give them __LogAnalytics Reader__ permission: 32 | 33 | ![identity](./images/identity.jpg) 34 | 35 |

Logic App Workflow Setting

36 |

High throughput

37 | 38 | Set High throughput to ON: 39 | 40 | ![identity](./images/HighThroughput.jpg) 41 | 42 |

Deployment and Result

43 | 44 | After deployment completed, please follow the documentation: 45 | 46 | 47 | Change __Recurrence__ section after SQL BPA has been performed: 48 | 49 | ![recurrence](./images/recurrence.jpg) 50 | 51 | Change the broken module __Run query and list result__ with a new one 52 | 53 | Before:
54 | ![Run query and list result](./images/run-query-list-result1.jpg) 55 | 56 | After:
57 | ![Run query and list result](./images/run-query-list-result2.jpg) 58 | 59 | Compile all the information following your configuration.
60 | For the query field past the code below: 61 | 62 | ```query 63 | let selectedCategories = dynamic([]); 64 | let selectedTotSev = dynamic([]); 65 | SqlAssessment_CL 66 | | extend asmt = parse_csv(RawData) 67 | //| where asmt[11] =~ "MSSQLSERVER" 68 | | extend 69 | AsmtId=tostring(asmt[1]), 70 | CheckId=tostring(asmt[2]), 71 | DisplayString=asmt[3], 72 | Description=tostring(asmt[4]), 73 | HelpLink=asmt[5], 74 | TargetType=case(asmt[6] == 1, "Server", asmt[6] == 2, "Database", ""), 75 | TargetName=tostring(asmt[7]), 76 | Severity=case(asmt[8] == 30, "High", asmt[8] == 20, "Medium", asmt[8] == 10, "Low", asmt[8] == 0, "Information", asmt[8] == 1, "Warning", asmt[8] == 2, "Critical", "Passed"), 77 | Message=tostring(asmt[9]), 78 | TagsArr=split(tostring(asmt[10]), ","), 79 | Sev = toint(asmt[8]) 80 | | where isnotempty(AsmtId) 81 | and (set_has_element(dynamic(['*']), CheckId) or "'*'" == "'*'") 82 | and (set_has_element(dynamic(['*']), TargetName) or "'*'" == "'*'") 83 | and set_has_element(dynamic([30, 20, 10, 0]), Sev) 84 | and (array_length(set_intersect(TagsArr, dynamic(['*']))) > 0 or "'*'" == "'*'") 85 | and (CheckId == '''' and Sev == 0 or "''" == "''") 86 | | extend Category = case( 87 | array_length(set_intersect(TagsArr, dynamic(["CPU", "IO", "Storage"]))) > 0, 88 | '0', 89 | array_length(set_intersect(TagsArr, dynamic(["TraceFlag", "Backup", "DBCC", "DBConfiguration", "SystemHealth", "Traces", "DBFileConfiguration", "Configuration", "Replication", "Agent", "Security", "DataIntegrity", "MaxDOP", "PageFile", "Memory", "Performance", "Statistics"]))) > 0, 90 | '1', 91 | array_length(set_intersect(TagsArr, dynamic(["UpdateIssues", "Index", "Naming", "Deprecated", "masterDB", "QueryOptimizer", "QueryStore", "Indexes"]))) > 0, 92 | '2', 93 | '3' 94 | ) 95 | | where (Sev >= 0 and array_length(selectedTotSev) == 0 or Sev in (selectedTotSev)) 96 | and (Category in (selectedCategories) or array_length(selectedCategories) == 0) 97 | | project 98 | TargetType, 99 | TargetName, 100 | Severity, 101 | Message, 102 | Tags=strcat_array(array_slice(TagsArr, 1, -1), ', '), 103 | CheckId, 104 | Description, 105 | HelpLink = tostring(HelpLink), 106 | SeverityCode = toint(Sev) 107 | | order by SeverityCode desc, TargetType desc, TargetName asc 108 | | project-away SeverityCode 109 | ``` 110 | 111 | Configure the Api Key with the value inside your OpenAI Service: 112 | 113 | ![Sentinel Api Key](./images/ApiKey.jpg) 114 | 115 | Configure __ForeachSQLResult__ section with value of query result and each parameter in Question variable as you like: 116 | 117 | ![SQL BPA question](./images/query-value.jpg) 118 | 119 | And now configure the RedirectUrl variable following the example: 120 | 121 | ![SQL BPA question](./images/set-variable-redirect-url.jpeg) 122 | 123 | Configure the Question Variable following the example below: 124 | 125 | ![SQL BPA question](./images/value-question.jpg) 126 | 127 | NB. you can use the following variable below to valorize the items i greyed out: 128 | 129 | ``` 130 | @{item()?['Message']} 131 | 132 | @{item()?['Description']} 133 | 134 | @{item()?['TargetType']} 135 | ``` 136 | 137 | Configure the severity level as a condition filter as you prefer: 138 | 139 | ![SQL BPA question](./images/severity.jpg) 140 | 141 | Now configure the HTTP Connector for OpenAI Connection following this configuration: 142 | 143 | ![Sentinel HTTP Connector](./images/http-connector.jpg) 144 | 145 | At this point, be sure that the ComposeCSV block is correctly configured. When the "Run query and list result" block is recreated some link can be resetted. Follow the ComposeCSV attribute configuration following the example below (if the new UI model is not useful for the customization, evaluate to switch in "code view" mode): 146 | 147 | ![ComposeCSV](./images/composeCSV.jpeg) 148 | 149 | NB. you can use the following variable below to valorize the items i greyed out: 150 | 151 | ``` 152 | @{items('For_eachSQLResult')?['TargetName']} 153 | 154 | @{items('For_eachSQLResult')?['Severity']} 155 | 156 | @{items('For_eachSQLResult')?['Message']} 157 | 158 | @{items('For_each_AI_Response')?['message']?['content']} 159 | 160 | @{items('For_eachSQLResult')?['HelpLink']} 161 | 162 | ``` 163 | 164 | The last configuration is change the broken module __Send an email (V2)__ with a new one, add the attachment and customize the file name : 165 | 166 | Before
167 | ![Sentinel Add Content](./images/sendEmail-broken.jpg) 168 | 169 | After
170 | ![Sentinel Add Content](./images/send-email2.jpg) 171 | 172 | Here all the configuration related the 2 attachments: 173 | 174 | ```json 175 | { 176 | "Name": "Sql-BPA-Result@{formatDateTime(convertTimeZone(utcNow(),'UTC','Romance Standard Time'), 'yyyy-MM-ddTHH.mm')}.html", 177 | "ContentBytes": "@{base64(variables('HTML-custom'))}" 178 | }, 179 | { 180 | "Name": "Sql-BPA-Result@{formatDateTime(convertTimeZone(utcNow(),'UTC','Romance Standard Time'), 'yyyy-MM-ddTHH.mm')}.csv", 181 | "ContentBytes": "@{base64(body('Create_CSV_table'))}" 182 | } 183 | ``` 184 | 185 | Now save your LogicApp and __Enable__ it. -------------------------------------------------------------------------------- /Arc-SQL BPA/images/ApiKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/ApiKey.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/BingKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/BingKey.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/BingSearch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/BingSearch.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/BingSearch_Conf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/BingSearch_Conf.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/BingSearch_Creation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/BingSearch_Creation.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/HelpLinkParameter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/HelpLinkParameter.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/HighThroughput.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/HighThroughput.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/SubRegistration.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/SubRegistration.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/composeCSV.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/composeCSV.jpeg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/deploy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/deploy.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/enable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/enable.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/final-questiontoAI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/final-questiontoAI.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/http-connector.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/http-connector.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/identity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/identity.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/query-value.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/query-value.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/recurrence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/recurrence.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/run-query-list-result1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/run-query-list-result1.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/run-query-list-result2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/run-query-list-result2.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/run-query-list-result3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/run-query-list-result3.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/send-email1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/send-email1.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/send-email2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/send-email2.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/sendEmail-broken.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/sendEmail-broken.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/set-variable-redirect-url.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/set-variable-redirect-url.jpeg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/severity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/severity.jpg -------------------------------------------------------------------------------- /Arc-SQL BPA/images/value-question.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Arc-SQL BPA/images/value-question.jpg -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /CostMonthlyCheck/README.md: -------------------------------------------------------------------------------- 1 |

Azure Cost Monthly Check OpenAI integration: Configuration

2 | 3 | | **Parameters** | **Information** | **Note** | 4 | | ------------- | ------------- | ------------- | 5 | | replacewithsubid | Connection setting during deployment | Replace with your Subscription ID | 6 | | repreplacewithRG | Connection setting during deployment | Replace with the selected RG Name for the deployment | 7 | | api-key | The API code for manage your OpenAI service | The parameter is inside the second "Initialize Variable". Put your question in the "value" attribute | 8 | | changeendpointname | Insert the OpenAI endpoint name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 9 | | changemodelname | Insert the model name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 10 | 11 |

Important

12 | This LogApp and the following changes are an example of Cost Monitor check with OpenAI send via Email . 13 | 14 | 15 |

Required Identity

16 |

Managed Identity

17 | 18 | Now configure the HTTP request to the Graph Explorer enabling the authentication via System Assigned Managed Identity. Please remind that the Managed Identity need to have the righ permission on the subscription for read the resources: 19 | 20 | 21 | ![identity](./images/identity.jpg) 22 | 23 | 24 |

Deployment and Result

25 | 26 | After deployment completed, please follow the documentation: 27 | 28 | 29 | As first step please configure the required recurrence: 30 | 31 | ![recurrence](./images/Recurrence.jpg) 32 | 33 | Configure the Api Key with the value inside your OpenAI Service: 34 | 35 | ![Api Key](./images/ApiKey.jpg) 36 | 37 | Modify the required subscription id in each the HTTP connector in order to obtain the required information: 38 | 39 | ![Api Key](./images/Sub-Id.jpeg) 40 | 41 | At this point we need to configure the Ask to OpenAI module replacing the required parameters: 42 | 43 | ![OpenAI](./images/OpenAI.jpg) 44 | 45 | Last step is to add a notification section. 46 | In the example below we have a "Send Email V2" connector for send the final report to the required people or to a Teams channel . If you want to follow the same approach configure the module following the same example adding them at the end of the Logic App. Make sure to use the correct variable in the body of the email in order to have them correctly formatted: 47 | 48 | ![example](./images/example-notification.jpg) -------------------------------------------------------------------------------- /CostMonthlyCheck/images/ApiKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/ApiKey.jpg -------------------------------------------------------------------------------- /CostMonthlyCheck/images/OpenAI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/OpenAI.jpg -------------------------------------------------------------------------------- /CostMonthlyCheck/images/Recurrence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/Recurrence.jpg -------------------------------------------------------------------------------- /CostMonthlyCheck/images/Sub-Id.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/Sub-Id.jpeg -------------------------------------------------------------------------------- /CostMonthlyCheck/images/example-notification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/example-notification.jpg -------------------------------------------------------------------------------- /CostMonthlyCheck/images/identity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/CostMonthlyCheck/images/identity.jpg -------------------------------------------------------------------------------- /FunctionAppSmartDocs/README.md: -------------------------------------------------------------------------------- 1 |

SmartDocs Azure Function

2 | 3 |

Overview

4 | The SmartDocs Azure Function is designed to generate technical documentation and detailed reporting based on Azure resource metadata using Azure OpenAI. The function leverages managed authentication to access Azure services and consolidates resource metadata into an easily readable, automatically generated document. 5 | 6 | 7 | > [!NOTE] 8 | > SmartDocs is an artifact designed to be tailored to specific client needs. Depending on requirements, aspects such as the document storage path and authentication/configuration details may need to be customized. 9 | 10 | 11 |

Requirements

12 | 13 | - Azure OpenAI-CoreIntegration Landing Zone deployed 14 | - A Default Consumption Function App will be deployed with the [foundation ARM Template](../OpenAI-CoreIntegrationLZ/README.md) 15 | - OpenAI in place, always deployed with the [foundation ARM Template](../OpenAI-CoreIntegrationLZ/README.md) 16 | - A local environment ready for deploy the Function App to azure. [Follow the instruction here](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-python). 17 | 18 | 19 | > [!IMPORTANT] 20 | > In the [Consumption Plan](https://learn.microsoft.com/en-us/azure/azure-functions/consumption-plan), the function has a maximum runtime of 10 minutes. For larger workloads, use an App Service Plan with a higher SKU, such as Premium or Dedicated, to increase the allowable execution time. 21 | 22 | 23 | - Managed Identity configured with read access to the required resources (subscriptions, OpenAI for generating text and so on). 24 | 25 | - QUESTION_ENDPOINT Environment Variable: The Azure OpenAI endpoint for sending requests. 26 | 27 |

Example files for Function deployment

28 | 29 | - [host.json](host.json) 30 | - [local.settings.json](./local.settings.json) 31 | - [requirements.txt](./requirements.txt) 32 | - [function_app.py](./function_app.py) 33 | 34 |

PowerShell Script for Invocation

35 | Here is a PowerShell script to invoke the function using an HTTP POST request: 36 | 37 | 38 | 39 | ``` 40 | powershell 41 | Copia codice 42 | # Function app URL 43 | $functionUrl = "https://smartdocsopenai.azurewebsites.net/api/smartdocs" 44 | 45 | # Parameters to send 46 | $body = @{ 47 | tag_key = "Workload" 48 | tag_value = "Production" 49 | } 50 | 51 | # Invoke the Function App 52 | $response = Invoke-RestMethod -Uri $functionUrl -Method Post -Body ($body | ConvertTo-Json) -ContentType "application/json" 53 | 54 | # Output the response 55 | $response 56 | ``` 57 | 58 | 59 | ![Azure Execution](../FunctionAppSmartDocs/images/immagine.png) 60 | 61 | > [!NOTE] 62 | > When planning to use this function for high workloads configure a Premium App Service Plan or higher to avoid time limitations. 63 | Monitor execution logs for potential issues related to timeouts or resource limits. 64 | Future Customizations 65 | 66 | 67 |

Support and Contributions

68 | Contributions and enhancement requests are welcome! For any additional customization, feel free to open an issue or submit a pull request in this repository. 69 | 70 | -------------------------------------------------------------------------------- /FunctionAppSmartDocs/function_app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import docx 4 | import csv 5 | import requests 6 | import collections.abc 7 | import azure.functions as func 8 | from azure.identity import ManagedIdentityCredential 9 | from azure.mgmt.resource import ResourceManagementClient 10 | from azure.mgmt.subscription import SubscriptionClient 11 | 12 | # Configurazione logging avanzato 13 | logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') 14 | 15 | # Endpoint OpenAI 16 | QUESTION_ENDPOINT = os.getenv("QUESTION_ENDPOINT") 17 | logging.info(f"Question endpoint set to: {QUESTION_ENDPOINT}") 18 | 19 | # Autenticazione tramite identità gestita della Function App 20 | credential = ManagedIdentityCredential() 21 | subscription_client = SubscriptionClient(credential) 22 | tokenai = credential.get_token("https://cognitiveservices.azure.com/.default") 23 | 24 | 25 | # Funzione per appiattire un dizionario annidato in una struttura piana 26 | def flatten_dict(d, parent_key='', sep='_'): 27 | #logging.info(f"start function flatten_dict") 28 | items = [] 29 | for k, v in d.items(): 30 | new_key = f"{parent_key}{sep}{k}" if parent_key else k 31 | 32 | if isinstance(v, collections.abc.MutableMapping): 33 | items.extend(flatten_dict(v, new_key, sep=sep).items()) 34 | elif isinstance(v, list): 35 | for i, item in enumerate(v): 36 | if isinstance(item, collections.abc.MutableMapping): 37 | items.extend(flatten_dict(item, f"{new_key}{sep}{i}", sep=sep).items()) 38 | else: 39 | items.append((f"{new_key}{sep}{i}", item)) 40 | else: 41 | items.append((new_key, v)) 42 | return dict(items) 43 | 44 | # Funzione per ottenere tutte le risorse con un determinato tag in una sottoscrizione 45 | def get_resources_by_tag_in_subscription(subscription_id, tag_key, tag_value): 46 | logging.info(f"start get_resources_by_tag_in_subscription") 47 | resource_client = ResourceManagementClient(credential, subscription_id) 48 | tag_filter = f"tagName eq '{tag_key}' and tagValue eq '{tag_value}'" 49 | logging.info(f"Cercando risorse con il tag: {tag_key}={tag_value} nella sottoscrizione {subscription_id}") 50 | 51 | resources = resource_client.resources.list(filter=tag_filter) 52 | resources_list = [] 53 | 54 | for resource in resources: 55 | resource_details = { 56 | 'name': resource.name, 57 | 'id': resource.id, 58 | 'location': resource.location, 59 | 'type': resource.type, 60 | 'tags': resource.tags 61 | } 62 | resources_list.append(resource_details) 63 | logging.info(f"Trovata risorsa: {resource.name} - {resource.type}") 64 | 65 | logging.info(str(resources_list)) 66 | return resources_list 67 | 68 | # Funzione per ottenere i Resource Groups con un determinato tag in una sottoscrizione 69 | def get_resource_groups_by_tag_in_subscription(subscription_id, tag_key, tag_value): 70 | logging.info(f"start get_resource_groups_by_tag_in_subscription") 71 | resource_client = ResourceManagementClient(credential, subscription_id) 72 | logging.info(f"Cercando resource groups con il tag: {tag_key}={tag_value} nella sottoscrizione {subscription_id}") 73 | resource_groups = resource_client.resource_groups.list() 74 | matching_resource_groups = [] 75 | 76 | for rg in resource_groups: 77 | if rg.tags and tag_key in rg.tags and rg.tags[tag_key] == tag_value: 78 | logging.info(f"Trovato resource group: {rg.name}") 79 | matching_resource_groups.append(rg) 80 | logging.info(str(matching_resource_groups)) 81 | return matching_resource_groups 82 | 83 | # Funzione per ottenere tutte le risorse con un determinato tag da tutte le sottoscrizioni 84 | def get_all_resources(tag_key, tag_value): 85 | logging.info(f"start get_all_resources") 86 | all_resources = [] 87 | added_resource_ids = set() 88 | 89 | # Elenca tutte le sottoscrizioni a cui hai accesso 90 | for subscription in subscription_client.subscriptions.list(): 91 | subscription_id = subscription.subscription_id 92 | logging.info(f"Processando la sottoscrizione: {subscription_id}") 93 | 94 | # Cerca le risorse con il tag specificato in questa sottoscrizione 95 | resources = get_resources_by_tag_in_subscription(subscription_id, tag_key, tag_value) 96 | for resource in resources: 97 | logging.info(f"Analizzando risorsa {resource}") 98 | if resource['id'] not in added_resource_ids: 99 | all_resources.append(resource) 100 | added_resource_ids.add(resource['id']) 101 | 102 | # Cerca i resource group con il tag specificato in questa sottoscrizione 103 | resource_groups = get_resource_groups_by_tag_in_subscription(subscription_id, tag_key, tag_value) 104 | for rg in resource_groups: 105 | logging.info(f"Analizzando {rg}") 106 | # Cerca risorse all'interno di ciascun resource group 107 | rg_resources = get_resources_in_resource_group_in_subscription(subscription_id, rg.name) 108 | for resource in rg_resources: 109 | if resource['id'] not in added_resource_ids: 110 | all_resources.append(resource) 111 | added_resource_ids.add(resource['id']) 112 | logging.info(str(all_resources)) 113 | return all_resources 114 | 115 | # Funzione per ottenere le risorse all'interno di un Resource Group in una sottoscrizione 116 | def get_resources_in_resource_group_in_subscription(subscription_id, resource_group_name): 117 | logging.info(f"start get_resources_in_resource_group_in_subscription") 118 | resource_client = ResourceManagementClient(credential, subscription_id) 119 | logging.info(f"Recuperando risorse dal resource group: {resource_group_name} nella sottoscrizione {subscription_id}") 120 | resources = resource_client.resources.list_by_resource_group(resource_group_name) 121 | resources_list = [] 122 | 123 | for resource in resources: 124 | resource_details = { 125 | 'name': resource.name, 126 | 'id': resource.id, 127 | 'location': resource.location, 128 | 'type': resource.type, 129 | 'tags': resource.tags 130 | } 131 | resources_list.append(resource_details) 132 | logging.info(f"Trovata risorsa nel resource group {resource_group_name}: {resource.name} - {resource.type}") 133 | logging.info(str(resources_list)) 134 | return resources_list 135 | 136 | # Funzione per ottenere l'API più recente per una risorsa specifica 137 | def get_latest_api_version(resource_client, resource_type): 138 | logging.info(f"start get_latest_api_version") 139 | provider_namespace, resource_type_name = resource_type.split('/', 1) 140 | provider = resource_client.providers.get(provider_namespace) 141 | resource_type_info = next( 142 | (t for t in provider.resource_types if t.resource_type == resource_type_name), None 143 | ) 144 | if resource_type_info: 145 | return sorted(resource_type_info.api_versions, reverse=True)[0] 146 | return None 147 | 148 | # Funzione per ottenere i metadati completi di una risorsa specifica 149 | def get_resource_metadata(resource_client, resource): 150 | logging.info(f"start get_resource_metadata") 151 | resource_type = resource['type'] 152 | api_version = get_latest_api_version(resource_client, resource_type) 153 | if api_version: 154 | logging.info(f"Usando l'API version: {api_version} per la risorsa {resource['name']}") 155 | resource_metadata = resource_client.resources.get_by_id(resource['id'], api_version=api_version) 156 | return resource_metadata 157 | else: 158 | logging.info(f"Impossibile trovare l'API per la risorsa {resource['name']} con tipo {resource['type']}") 159 | return None 160 | 161 | # Funzione per generare la overview del workload leggendo il file CSV 162 | def generate_workload_overview(): 163 | logging.info(f"start generate_workload_overview") 164 | resources_info = [] 165 | 166 | with open("/tmp/resources_with_expanded_metadata.csv", 'r', encoding='utf-8') as csv_file: 167 | reader = csv.DictReader(csv_file) 168 | for row in reader: 169 | resources_info.append(row) 170 | 171 | resources_str = "\n".join([ 172 | f"Name: {row['Name']}, Type: {row['Type']}, Location: {row['Location']}, Resource Group: {row['Resource ID'].split('/')[4]}" 173 | for row in resources_info]) 174 | 175 | payload = { 176 | "messages": [ 177 | {"role": "system", 178 | "content": "You are an expert Azure Architect and Documentation Writer. Your job is to create a clear and detailed overview of an Azure workload."}, 179 | {"role": "user", 180 | "content": f"Here is the list of resources in the workload:\n{resources_str}.\nGenerate a detailed and human-readable overview. Explain at the end how the workload is splitted, so if is multi-regional or not and so on."} 181 | ], 182 | "temperature": 0.7, 183 | "max_tokens": 16000 184 | } 185 | 186 | response = requests.post( 187 | QUESTION_ENDPOINT, 188 | headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + tokenai.token}, 189 | json=payload 190 | ) 191 | 192 | response.raise_for_status() 193 | response_from_copilot = response.json()['choices'][0]['message']['content'].strip() 194 | logging.info(str(response_from_copilot)) 195 | return response_from_copilot 196 | 197 | # Funzione per generare la documentazione con OpenAI 198 | def generate_infra_config(metadata_list): 199 | logging.info("Inizio della generazione della configurazione dell'infrastruttura.") 200 | document_content = "" 201 | 202 | for index, metadata in enumerate(metadata_list): 203 | logging.debug(f"Elaborazione del metadato {index + 1}/{len(metadata_list)}: {metadata}") 204 | metadata_str = str(metadata) 205 | 206 | payload = { 207 | "messages": [ 208 | {"role": "system", "content": "You are an expert Azure Architect and Documentation Writer."}, 209 | {"role": "user", "content": f"Here is the metadata for an Azure resource: \n{metadata_str}.\nPlease generate a detailed and human-readable documentation."} 210 | ], 211 | "temperature": 0.7, 212 | "max_tokens": 16000 213 | } 214 | 215 | try: 216 | # Invio richiesta a OpenAI 217 | logging.debug("Invio della richiesta a OpenAI con payload.") 218 | response = requests.post( 219 | QUESTION_ENDPOINT, 220 | headers={'Content-Type': 'application/json', 'Authorization': f'Bearer {tokenai.token}'}, 221 | json=payload 222 | ) 223 | 224 | # Gestione della risposta 225 | response.raise_for_status() 226 | response_data = response.json() 227 | response_from_copilot = response_data['choices'][0]['message']['content'].strip() 228 | logging.info(f"Risposta da OpenAI per il metadato {index + 1}: {response_from_copilot}") 229 | 230 | except requests.exceptions.RequestException as e: 231 | logging.error(f"Errore nella richiesta a OpenAI per il metadato {index + 1}: {e}") 232 | continue # Salta al prossimo elemento se c'è un errore 233 | 234 | # Revisione del contenuto tramite ArchitecturalReviewer e DocCreator 235 | response_from_DocCreator = response_from_copilot 236 | previousdoc = response_from_DocCreator 237 | for i in range(3): 238 | try: 239 | ArchitecturalReviewer_response = ArchitecturalReviewer(response_from_DocCreator) 240 | logging.debug(f"Risposta ArchitecturalReviewer (ciclo {i + 1}): {ArchitecturalReviewer_response}") 241 | response_from_DocCreator, previousdoc = DocCreator(ArchitecturalReviewer_response, previousdoc) 242 | logging.debug(f"Documento revisionato (ciclo {i + 1}): {response_from_DocCreator}") 243 | except Exception as e: 244 | logging.error(f"Errore durante la revisione della documentazione (ciclo {i + 1}): {e}") 245 | break # Interrompe la revisione in caso di errore 246 | 247 | # Aggiunge la documentazione revisionata al contenuto finale 248 | document_content += response_from_DocCreator + "\n\n" 249 | 250 | # Scrittura del contenuto finale in un file 251 | try: 252 | logging.info("Scrittura del documento finale nel file architecture.txt.") 253 | with open("/tmp/architecture.txt", "a", encoding="utf-8") as architecturefile: 254 | architecturefile.write(document_content) 255 | logging.info("Documento architecture.txt generato con successo.") 256 | except IOError as e: 257 | logging.error(f"Errore durante la scrittura del file architecture.txt: {e}") 258 | 259 | return document_content 260 | 261 | logging.info(f"start generate_infra_config") 262 | document_content = "" 263 | 264 | for metadata in metadata_list: 265 | metadata_str = str(metadata) 266 | 267 | payload = { 268 | "messages": [ 269 | {"role": "system", 270 | "content": "You are an expert Azure Architect and Documentation Writer."}, 271 | {"role": "user", 272 | "content": f"Here is the metadata for an Azure resource: \n{metadata_str}.\nPlease generate a detailed and human-readable documentation."} 273 | ], 274 | "temperature": 0.7, 275 | "max_tokens": 16000 276 | } 277 | 278 | response = requests.post( 279 | QUESTION_ENDPOINT, 280 | headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + tokenai.token}, 281 | json=payload 282 | ) 283 | 284 | response.raise_for_status() 285 | response_from_copilot = response.json()['choices'][0]['message']['content'].strip() 286 | logging.info(str(response_from_copilot)) 287 | 288 | # Passa il contenuto attraverso 3 cicli di revisione con ArchitecturalReviewer e DocCreator 289 | response_from_DocCreator = response_from_copilot 290 | previousdoc = response_from_DocCreator 291 | for i in range(3): 292 | ArchitecturalReviewer_response = ArchitecturalReviewer(response_from_DocCreator) 293 | response_from_DocCreator, previousdoc = DocCreator(ArchitecturalReviewer_response, previousdoc) 294 | 295 | # Aggiunge la documentazione revisionata al contenuto finale 296 | document_content += response_from_DocCreator + "\n\n" 297 | 298 | with open("architecture.txt", "a", encoding="utf-8") as architecturefile: 299 | architecturefile.write(document_content) 300 | 301 | return document_content 302 | 303 | # Funzione per convertire il file txt in docx e aggiungere l'overview 304 | def txt_to_docx(): 305 | logging.info(f"start txt_to_docx") 306 | logging.info("Generazione dei file in corso...") 307 | 308 | doc = docx.Document() 309 | 310 | # Genera l'overview del workload 311 | overview = generate_workload_overview() 312 | 313 | # Aggiungi "Workload Overview" come Titolo 1 314 | doc.add_heading("Workload Overview", level=1) 315 | doc.add_paragraph(overview) 316 | 317 | # Aggiungi un'interruzione di pagina per iniziare i dettagli su una nuova pagina 318 | doc.add_page_break() 319 | 320 | # Aggiungi "Workload Details" come Titolo 1 321 | doc.add_heading("Workload Details", level=1) 322 | 323 | # Aggiungi il contenuto del file architecture.txt 324 | with open("architecture.txt", 'r', encoding='utf-8', errors='ignore') as openfile: 325 | line = openfile.read() 326 | doc.add_paragraph(line) 327 | 328 | # Salva il documento Word 329 | doc.save("Output.docx") 330 | logging.info("Il file Output.docx è stato creato con successo.") 331 | 332 | def cleanup_files(): 333 | logging.info(f"start cleanup_files") 334 | logging.info("Cleaning up temporary files") 335 | if os.path.exists("architecture.txt"): 336 | os.remove("architecture.txt") 337 | logging.debug("architecture.txt deleted") 338 | if os.path.exists("resources_with_expanded_metadata.csv"): 339 | os.remove("resources_with_expanded_metadata.csv") 340 | logging.debug("resources_with_expanded_metadata.csv") 341 | if os.path.exists("Output.docx"): 342 | os.remove("Output.docx") 343 | logging.debug("Output.docx deleted") 344 | if os.path.exists("/tmp/architecture.txt"): 345 | os.remove("/tmp/architecture.txt") 346 | logging.debug("architecture.txt deleted") 347 | if os.path.exists("/tmp/resources_with_expanded_metadata.csv"): 348 | os.remove("/tmp/resources_with_expanded_metadata.csv") 349 | logging.debug("resources_with_expanded_metadata.csv") 350 | if os.path.exists("/tmp/Output.docx"): 351 | os.remove("/tmp/Output.docx") 352 | logging.debug("Output.docx deleted") 353 | logging.info("Temporary files cleanup completed") 354 | 355 | 356 | def save_resources_with_expanded_metadata_to_csv(resources, metadata_list): 357 | logging.info("Start save_resources_with_expanded_metadata_to_csv") 358 | 359 | all_keys = set() 360 | 361 | # Raccogli tutte le chiavi disponibili nei metadati, incluse quelle dei dizionari annidati 362 | try: 363 | for metadata in metadata_list: 364 | flat_metadata = flatten_dict(metadata.__dict__) # Appiattiamo il dizionario dei metadati 365 | logging.debug(f"Flat metadata for item: {flat_metadata}") 366 | all_keys.update(flat_metadata.keys()) 367 | except AttributeError as e: 368 | logging.error(f"Errore durante l'appiattimento dei metadati: {e}") 369 | return 370 | except Exception as e: 371 | logging.error(f"Errore sconosciuto durante la raccolta delle chiavi: {e}") 372 | return 373 | 374 | # Trasforma il set delle chiavi in una lista ordinata per mantenere ordine nelle colonne 375 | all_keys = list(all_keys) 376 | logging.info(f"All unique metadata keys: {all_keys}") 377 | 378 | # Scrivi le risorse e i loro metadati in un file CSV 379 | try: 380 | with open("/tmp/resources_with_expanded_metadata.csv", mode="w", newline='', encoding="utf-8") as csv_file: 381 | # Creiamo l'header del CSV con tutte le chiavi uniche 382 | fieldnames = ['Name', 'Resource ID', 'Location', 'Type', 'Tags'] + all_keys 383 | logging.debug(f"Fieldnames for CSV: {fieldnames}") 384 | writer = csv.DictWriter(csv_file, fieldnames=fieldnames) 385 | 386 | # Scriviamo l'intestazione 387 | writer.writeheader() 388 | logging.info("CSV header written successfully.") 389 | 390 | # Scrivi i dettagli di ogni risorsa e i suoi metadati 391 | for resource, metadata in zip(resources, metadata_list): 392 | logging.debug(f"Processing resource: {resource['name']}") 393 | 394 | # Crea la riga iniziale per la risorsa 395 | resource_row = { 396 | 'Name': resource['name'], 397 | 'Resource ID': resource['id'], 398 | 'Location': resource['location'], 399 | 'Type': resource['type'], 400 | 'Tags': resource['tags'] 401 | } 402 | 403 | # Appiattiamo i metadati annidati prima di scriverli nel CSV 404 | try: 405 | flat_metadata = flatten_dict(metadata.__dict__) 406 | logging.debug(f"Flat metadata for resource {resource['name']}: {flat_metadata}") 407 | except AttributeError as e: 408 | logging.error(f"Errore durante l'appiattimento dei metadati per la risorsa {resource['name']}: {e}") 409 | continue 410 | except Exception as e: 411 | logging.error(f"Errore sconosciuto durante l'appiattimento dei metadati per {resource['name']}: {e}") 412 | continue 413 | 414 | # Aggiungi i metadati alle colonne, gestendo eventuali valori mancanti 415 | for key in all_keys: 416 | resource_row[key] = flat_metadata.get(key, 'N/A') # Usa 'N/A' per valori mancanti 417 | 418 | # Scrivi la riga nel CSV 419 | writer.writerow(resource_row) 420 | logging.debug(f"Row written for resource {resource['name']}") 421 | 422 | except IOError as e: 423 | logging.error(f"Errore durante la creazione del file CSV: {e}") 424 | except Exception as e: 425 | logging.error(f"Errore sconosciuto durante la scrittura nel file CSV: {e}") 426 | 427 | logging.info("Il file resources_with_expanded_metadata.csv è stato creato con successo.") 428 | 429 | logging.info(f"start save_resources_with_expanded_metadata_to_csv") 430 | all_keys = set() 431 | 432 | # Raccogli tutte le chiavi disponibili nei metadati, incluse quelle dei dizionari annidati 433 | for metadata in metadata_list: 434 | flat_metadata = flatten_dict(metadata.__dict__) # Appiattiamo il dizionario dei metadati 435 | all_keys.update(flat_metadata.keys()) 436 | 437 | # Trasforma il set delle chiavi in una lista ordinata per mantenere ordine nelle colonne 438 | all_keys = list(all_keys) 439 | logging.info(f"all_keys: {all_keys}") 440 | 441 | # Scrivi le risorse e i loro metadati in un file CSV 442 | with open("/tmp/resources_with_expanded_metadata.csv", mode="w", newline='', encoding="utf-8") as csv_file: 443 | # Creiamo l'header del CSV con tutte le chiavi uniche 444 | fieldnames = ['Name', 'Resource ID', 'Location', 'Type', 'Tags'] + all_keys 445 | writer = csv.DictWriter(csv_file, fieldnames=fieldnames) 446 | 447 | # Scriviamo l'intestazione 448 | writer.writeheader() 449 | 450 | # Scrivi i dettagli di ogni risorsa e i suoi metadati 451 | for resource, metadata in zip(resources, metadata_list): 452 | resource_row = { 453 | 'Name': resource['name'], 454 | 'Resource ID': resource['id'], 455 | 'Location': resource['location'], 456 | 'Type': resource['type'], 457 | 'Tags': resource['tags'] 458 | } 459 | 460 | # Appiattiamo i metadati annidati prima di scriverli nel CSV 461 | flat_metadata = flatten_dict(metadata.__dict__) 462 | 463 | # Aggiungi i metadati alle colonne, gestendo eventuali valori mancanti 464 | for key in all_keys: 465 | resource_row[key] = flat_metadata.get(key, 'N/A') # Usa 'N/A' per valori mancanti 466 | 467 | # Scrivi la riga nel CSV 468 | writer.writerow(resource_row) 469 | 470 | logging.info("Il file resources_with_expanded_metadata.csv è stato creato con successo.") 471 | 472 | def ArchitecturalReviewer(response_from_DocCreator): 473 | logging.info(f"start ArchitecturalReviewer") 474 | payload = { 475 | "messages": [ 476 | {"role": "system", 477 | "content": "You are the Azure architectural reviewer of the enterprise. Our team is creating documentation on our Azure architecture for the existing dedicated workload. The team will pass a specific piece of documentation to you each time. Make suggestions on how to make it more user-friendly the part without suggesting to add graph, diagrams, table of contents, feedback and so on. Suggest how to write the doc in a user-friendly readable way."}, 478 | {"role": "user", 479 | "content": f"{response_from_DocCreator}"} 480 | ], 481 | "temperature": 0.7, 482 | "max_tokens": 16000 483 | } 484 | 485 | response = requests.post( 486 | QUESTION_ENDPOINT, 487 | headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + tokenai.token}, 488 | json=payload 489 | ) 490 | 491 | response.raise_for_status() 492 | ArchitecturalReviewer_response = response.json()['choices'][0]['message']['content'].strip() 493 | logging.info(f"Architectural Reviewer Comments: {ArchitecturalReviewer_response}") 494 | 495 | return ArchitecturalReviewer_response 496 | 497 | def DocCreator(ArchitecturalReviewer_response,previousdoc): 498 | logging.info(f"start DocCreator") 499 | payload = { 500 | "messages": [ 501 | {"role": "system", 502 | "content": "You have created a document about your Azure infrastructure related a workload. Your supervisor is reviewing the documentation. Generate a new documentation output based on his suggestions as an output."}, 503 | {"role": "user", 504 | "content": f"source:{previousdoc}. Suggestion: {ArchitecturalReviewer_response}"} 505 | ], 506 | "temperature": 0.7, 507 | "max_tokens": 16000 508 | } 509 | 510 | response = requests.post( 511 | QUESTION_ENDPOINT, 512 | headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + tokenai.token}, 513 | json=payload 514 | ) 515 | 516 | response.raise_for_status() 517 | response_from_DocCreator = response.json()['choices'][0]['message']['content'].strip() 518 | logging.info(f"Doc Creator Repsonse: {response_from_DocCreator}") 519 | 520 | return response_from_DocCreator, response_from_DocCreator 521 | 522 | app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS) 523 | 524 | @app.route(route="smartdocs") 525 | def smartdocs(req: func.HttpRequest) -> func.HttpResponse: 526 | logging.info("Received request for smartdocs function") 527 | 528 | tag_key = req.params.get("tag_key") 529 | tag_value = req.params.get("tag_value") 530 | if not tag_key or not tag_value: 531 | try: 532 | req_body = req.get_json() 533 | tag_key = tag_key or req_body.get("tag_key") 534 | tag_value = tag_value or req_body.get("tag_value") 535 | except ValueError: 536 | logging.error("Invalid request body") 537 | return func.HttpResponse("Missing 'tag_key' or 'tag_value' parameters.", status_code=400) 538 | 539 | if not tag_key or not tag_value: 540 | logging.error("Missing required parameters: 'tag_key' and 'tag_value'") 541 | return func.HttpResponse("Missing 'tag_key' or 'tag_value' parameters.", status_code=400) 542 | 543 | all_resources = get_all_resources(tag_key, tag_value) 544 | metadata_list = [] 545 | processed_resource_ids = set() 546 | 547 | for subscription in subscription_client.subscriptions.list(): 548 | subscription_id = subscription.subscription_id 549 | resource_client = ResourceManagementClient(credential, subscription_id) 550 | for resource in all_resources: 551 | if resource['id'] not in processed_resource_ids: 552 | metadata = get_resource_metadata(resource_client, resource) 553 | if metadata: 554 | metadata_list.append(metadata) 555 | processed_resource_ids.add(resource['id']) 556 | 557 | save_resources_with_expanded_metadata_to_csv(all_resources, metadata_list) 558 | document_content = generate_infra_config(metadata_list) 559 | 560 | with open("architecture.txt", "w", encoding="utf-8") as output_file: 561 | output_file.write(document_content) 562 | logging.info("Architecture text file saved") 563 | 564 | txt_to_docx() 565 | cleanup_files() 566 | 567 | logging.info("Function smartdocs completed successfully") 568 | return func.HttpResponse("Resource data processed successfully.", status_code=200) 569 | -------------------------------------------------------------------------------- /FunctionAppSmartDocs/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingSettings": { 6 | "isEnabled": true, 7 | "excludedTypes": "Request" 8 | } 9 | } 10 | }, 11 | "extensionBundle": { 12 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 13 | "version": "[4.*, 5.0.0)" 14 | } 15 | } -------------------------------------------------------------------------------- /FunctionAppSmartDocs/images/immagine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/FunctionAppSmartDocs/images/immagine.png -------------------------------------------------------------------------------- /FunctionAppSmartDocs/local.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "IsEncrypted": false, 3 | "Values": { 4 | "AzureWebJobsStorage": "", 5 | "FUNCTIONS_WORKER_RUNTIME": "python", 6 | "QUESTION_ENDPOINT": "change-with-openai-endpoint", 7 | "APPINSIGHTS_INSTRUMENTATIONKEY": "e4e0ad95-1088-4cdc-b5a2-0309d643c1a8", 8 | "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=e4e0ad95-1088-4cdc-b5a2-0309d643c1a8;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=5376b542-d34a-4776-b408-f51da0db884f", 9 | "FUNCTIONS_EXTENSION_VERSION": "~4" 10 | } 11 | } -------------------------------------------------------------------------------- /FunctionAppSmartDocs/requirements.txt: -------------------------------------------------------------------------------- 1 | # DO NOT include azure-functions-worker in this file 2 | # The Python Worker is managed by Azure Functions platform 3 | # Manually managing azure-functions-worker may cause unexpected issues 4 | 5 | azure-functions 6 | azure-identity 7 | azure-mgmt-resource 8 | azure-mgmt-subscription 9 | requests 10 | python-docx 11 | -------------------------------------------------------------------------------- /GIT.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/GIT.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Learning/README.md: -------------------------------------------------------------------------------- 1 | # Learning Repository 2 | 3 | Learn 4 | 5 | This folder contains information and learning resources for various Azure and OpenAI technologies. The goal is to provide a comprehensive understanding of these tools, their applications, and how to use them effectively. 6 | 7 | --- 8 | 9 | ##Contents 10 | 11 | Azure OpenAI 12 | ### 1. OpenAI on Azure 13 | - **Overview**: OpenAI on Azure enables developers to integrate advanced AI models like GPT and Codex into their applications. These models can help with text generation, summarization, code completion, and more. 14 | - **Use Cases**: 15 | - **Customer Support**: Implement AI-powered chatbots to handle common customer queries. 16 | - **Content Generation**: Automate the creation of articles, social media posts, and reports. 17 | - **Coding Assistance**: Enhance developer productivity by integrating AI-based coding tools. 18 | - **Key Features**: 19 | - Access to pre-trained OpenAI models such as GPT-4. 20 | - Fine-tuning capabilities for custom model training. 21 | - Built-in Azure security and compliance. 22 | - **Resources**: 23 | - [Azure OpenAI Documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/) 24 | - [Getting Started with Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/chatgpt-quickstart?tabs=command-line%2Cjavascript-keyless%2Ctypescript-keyless%2Cpython-new&pivots=programming-language-python) 25 | --- 26 | 27 | 28 | Logic Apps 29 | ### 2. Azure Logic Apps 30 | - **Overview**: Azure Logic Apps simplifies the creation of automated workflows by connecting various services and applications. It is a low-code/no-code solution suitable for developers and non-developers alike. 31 | - **Use Cases**: 32 | - **Automated Data Processing**: Integrate cloud services to process and store data. 33 | - **Alerting Systems**: Build workflows that trigger alerts based on specific conditions. 34 | - **Integration**: Connect on-premises systems with cloud-based applications. 35 | - **Key Features**: 36 | - Hundreds of pre-built connectors for services like Microsoft 365, SQL Server, and Salesforce. 37 | - Built-in monitoring and diagnostics tools. 38 | - Support for complex workflows with conditional logic. 39 | - **Resources**: 40 | - [Azure Logic Apps Overview](https://learn.microsoft.com/en-us/azure/logic-apps/) 41 | - [Tutorial for Azure Logic Apps](https://learn.microsoft.com/en-us/azure/logic-apps/tutorial-build-schedule-recurring-logic-app-workflow) 42 | --- 43 | 44 | 45 | APIM 46 | ### 3. Azure API Management (APIM) 47 | - **Overview**: Azure API Management provides a comprehensive solution for managing, securing, and monitoring APIs. It is designed to help organizations expose their services securely while ensuring scalability and high performance. 48 | - **Use Cases**: 49 | - **API Gateways**: Centralize API traffic with built-in caching and load balancing. 50 | - **Security**: Protect APIs with authentication, authorization, and rate-limiting features. 51 | - **Developer Portals**: Provide documentation and tools for developers to interact with your APIs. 52 | - **Key Features**: 53 | - Full lifecycle API management: design, deploy, and retire APIs. 54 | - Built-in support for OpenAPI Specification. 55 | - Analytics and insights into API usage. 56 | - **Resources**: 57 | - [Introduction to Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/) 58 | - [How to Create APIs with Azure APIM](https://learn.microsoft.com/en-us/azure/api-management/import-and-publish) 59 | --- 60 | 61 | 62 | SDK 63 | ### 4. Artificial Intelligence (AI) and Machine Learning (ML) on Azure 64 | - **Overview**: Azure provides robust tools and frameworks for incorporating artificial intelligence (AI) and machine learning (ML) into business solutions. It supports a wide range of AI use cases, from large-scale language models to advanced deep learning frameworks. 65 | - **Use Cases**: 66 | - **Generative AI**: Develop applications that create new content such as text, images, or code. 67 | - **Predictive Analytics**: Use ML models to forecast trends and improve decision-making. 68 | - **Intelligent Automation**: Integrate AI into workflows to enhance efficiency and reduce manual effort. 69 | - **Key Features**: 70 | - Support for popular ML frameworks like TensorFlow and PyTorch. 71 | - Comprehensive AI services, including Azure Cognitive Services and Azure Machine Learning. 72 | - Seamless integration with other Azure tools for deployment and monitoring. 73 | - **Resources**: 74 | - [AI and Machine Learning Architecture Overview](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/) 75 | --- 76 | 77 | 78 | Learning 79 | ### 5. Get started with Azure OpenAI Service (MS Learning) and Design Architectures 80 | - **Overview**: This module provides engineers with the skills to begin building an Azure OpenAI Service solution. 81 | - **Learning objectives**: By the end of this module, you'll be able to: 82 | - Create an Azure OpenAI Service resource and understand types of Azure OpenAI base models. 83 | - Use the Azure AI Studio, console, or REST API to deploy a base model and test it in the Studio's playgrounds. 84 | - Generate completions to prompts and begin to manage model parameters. 85 | - **Resources**: 86 | - [Azure OpenAI Service Modules](https://learn.microsoft.com/en-us/training/modules/get-started-openai/) 87 | - [Module assessment](https://learn.microsoft.com/it-it/training/modules/get-started-openai/1-introduction/) 88 | -------------------------------------------------------------------------------- /Learning/images/AC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/AC.png -------------------------------------------------------------------------------- /Learning/images/Azure APIM.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/Azure APIM.jpg -------------------------------------------------------------------------------- /Learning/images/Azure Logic APp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/Azure Logic APp.jpg -------------------------------------------------------------------------------- /Learning/images/AzureOpenAI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/AzureOpenAI.png -------------------------------------------------------------------------------- /Learning/images/Learn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/Learn.png -------------------------------------------------------------------------------- /Learning/images/Microsoft Learn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/Microsoft Learn.jpg -------------------------------------------------------------------------------- /Learning/images/model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Learning/images/model.jpg -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/AIServicesForInfraELZ.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "openAIResourceGroup": { 6 | "type": "string", 7 | "defaultValue": "OpenAIRG", 8 | "metadata": { 9 | "description": "Resource group for the OpenAI resource." 10 | } 11 | }, 12 | "LogicAppsRG": { 13 | "type": "string", 14 | "defaultValue": "LogicAppsforAI", 15 | "metadata": { 16 | "description": "Resource group for the SQL BPA Logic App." 17 | } 18 | }, 19 | "openAILocation": { 20 | "type": "string", 21 | "defaultValue": "westeurope", 22 | "metadata": { 23 | "description": "Location for the OpenAI resource." 24 | } 25 | }, 26 | "logicAppsLocation": { 27 | "type": "string", 28 | "defaultValue": "westeurope", 29 | "metadata": { 30 | "description": "Location for the Logic Apps resource." 31 | } 32 | }, 33 | "openAIName": { 34 | "type": "string", 35 | "defaultValue": "AzureOpenAIResource2024", 36 | "metadata": { 37 | "description": "Name for the OpenAI resource. Must be globally unique." 38 | } 39 | }, 40 | "workflows_SQL_BPA_ReadLink_Generalized_name": { 41 | "defaultValue": "OpenAI-SQL-BPA", 42 | "type": "string", 43 | "metadata": { 44 | "description": "Logic App Name for SQL-BPA." 45 | } 46 | }, 47 | "workflows_OpenAICostMngmtMonthlyCheck_name": { 48 | "defaultValue": "OpenAI-Cost-Monthly-Check", 49 | "type": "string", 50 | "metadata": { 51 | "description": "Logic App Name for Cost-Monthly-Check." 52 | } 53 | }, 54 | "workflows_OpenAIsmartupdate_name": { 55 | "defaultValue": "OpenAI-Update-Management", 56 | "type": "string", 57 | "metadata": { 58 | "description": "Logic App Name for Update-Management." 59 | } 60 | }, 61 | "workflows_AnomaliesDetection_name": { 62 | "defaultValue": "OpenAI-AnomaliesDetection", 63 | "type": "string", 64 | "metadata": { 65 | "description": "Logic App Name for Anomalies Detection." 66 | } 67 | }, 68 | "FunctionRG": { 69 | "defaultValue": "FunctionRGAI", 70 | "type": "string", 71 | "metadata": { 72 | "description": "RG used for the function App" 73 | } 74 | }, 75 | "FunctionRGLocation": { 76 | "defaultValue": "westeurope", 77 | "type": "string", 78 | "metadata": { 79 | "description": "RG used for the function App" 80 | } 81 | }, 82 | "FunctionName": { 83 | "defaultValue": "OpenAISmartDocsFA", 84 | "type": "string", 85 | "metadata": { 86 | "description": "Function Name to Create." 87 | } 88 | }, 89 | "FunctionLocation": { 90 | "defaultValue": "westeurope", 91 | "type": "string", 92 | "metadata": { 93 | "description": "Function location." 94 | } 95 | }, 96 | "StorageAccountNameFunction": { 97 | "defaultValue": "aisafunctionapp2024", 98 | "type": "string", 99 | "metadata": { 100 | "description": "Storage account name for the function app. The name must be unique." 101 | } 102 | } 103 | }, 104 | "resources": [ 105 | { 106 | "type": "Microsoft.Resources/resourceGroups", 107 | "apiVersion": "2022-09-01", 108 | "name": "[parameters('openAIResourceGroup')]", 109 | "location": "[parameters('openAILocation')]", 110 | "properties": {} 111 | }, 112 | { 113 | "type": "Microsoft.Resources/deployments", 114 | "apiVersion": "2022-09-01", 115 | "name": "DeployOpenAI", 116 | "resourceGroup": "[parameters('openAIResourceGroup')]", 117 | "properties": { 118 | "mode": "Incremental", 119 | "templateLink": { 120 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/templateOpenAI.json", 121 | "contentVersion": "1.0.0.0" 122 | }, 123 | "parameters": { 124 | "name": { 125 | "value": "[parameters('openAIName')]" 126 | }, 127 | "vnet": { 128 | "value": {} 129 | }, 130 | "location": { 131 | "value": "[parameters('openAILocation')]" 132 | }, 133 | "sku": { 134 | "value": "S0" 135 | }, 136 | "virtualNetworkType": { 137 | "value": "None" 138 | }, 139 | "resourceGroupName": { 140 | "value": "[parameters('openAIResourceGroup')]" 141 | }, 142 | "resourceGroupId": { 143 | "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('openAIResourceGroup'))]" 144 | }, 145 | "ipRules": { 146 | "value": [] 147 | }, 148 | "privateEndpoints": { 149 | "value": [] 150 | }, 151 | "privateDnsZone": { 152 | "value": "privatelink.openai.azure.com" 153 | }, 154 | "tagValues": { 155 | "value": {} 156 | } 157 | } 158 | }, 159 | "dependsOn": [ 160 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('openAIResourceGroup'))]" 161 | ] 162 | }, 163 | { 164 | "type": "Microsoft.Resources/resourceGroups", 165 | "apiVersion": "2022-09-01", 166 | "name": "[parameters('LogicAppsRG')]", 167 | "location": "[parameters('logicAppsLocation')]", 168 | "properties": {} 169 | }, 170 | { 171 | "type": "Microsoft.Resources/deployments", 172 | "apiVersion": "2019-10-01", 173 | "name": "DeploySQLBPA", 174 | "resourceGroup": "[parameters('LogicAppsRG')]", 175 | "properties": { 176 | "mode": "Incremental", 177 | "templateLink": { 178 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/SQLBPAV2.json", 179 | "contentVersion": "1.0.0.0" 180 | }, 181 | "parameters": { 182 | "workflows_SQL_BPA_ReadLink_Generalized_name": { 183 | "value": "[parameters('workflows_SQL_BPA_ReadLink_Generalized_name')]" 184 | }, 185 | "connections_azuremonitorlogs_externalid": { 186 | "value": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('LogicAppsRG'), '/providers/Microsoft.Web/connections/azuremonitorlogs')]" 187 | }, 188 | "connections_office365_externalid": { 189 | "value": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('LogicAppsRG'), '/providers/Microsoft.Web/connections/office365')]" 190 | }, 191 | "location": { 192 | "value": "[parameters('logicAppsLocation')]" 193 | } 194 | } 195 | }, 196 | "dependsOn": [ 197 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('LogicAppsRG'))]" 198 | ] 199 | }, 200 | { 201 | "type": "Microsoft.Resources/deployments", 202 | "apiVersion": "2019-10-01", 203 | "name": "DeployCostMonthlyCheck", 204 | "resourceGroup": "[parameters('LogicAppsRG')]", 205 | "properties": { 206 | "mode": "Incremental", 207 | "templateLink": { 208 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/CostMonthlyCheck.json", 209 | "contentVersion": "1.0.0.0" 210 | }, 211 | "parameters": { 212 | "workflows_OpenAICostMngmtMonthlyCheck_name": { 213 | "value": "[parameters('workflows_OpenAICostMngmtMonthlyCheck_name')]" 214 | }, 215 | "location": { 216 | "value": "[parameters('logicAppsLocation')]" 217 | } 218 | } 219 | }, 220 | "dependsOn": [ 221 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('LogicAppsRG'))]" 222 | ] 223 | }, 224 | { 225 | "type": "Microsoft.Resources/deployments", 226 | "apiVersion": "2019-10-01", 227 | "name": "DeployUpdateManagement", 228 | "resourceGroup": "[parameters('LogicAppsRG')]", 229 | "properties": { 230 | "mode": "Incremental", 231 | "templateLink": { 232 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/UpdateManagement.json", 233 | "contentVersion": "1.0.0.0" 234 | }, 235 | "parameters": { 236 | "workflows_OpenAIsmartupdate_name": { 237 | "value": "[parameters('workflows_OpenAIsmartupdate_name')]" 238 | }, 239 | "location": { 240 | "value": "[parameters('logicAppsLocation')]" 241 | } 242 | } 243 | }, 244 | "dependsOn": [ 245 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('LogicAppsRG'))]" 246 | ] 247 | }, 248 | { 249 | "type": "Microsoft.Resources/deployments", 250 | "apiVersion": "2019-10-01", 251 | "name": "DeployAnomaliesDetection", 252 | "resourceGroup": "[parameters('LogicAppsRG')]", 253 | "properties": { 254 | "mode": "Incremental", 255 | "templateLink": { 256 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/AnomaliesDetection.json", 257 | "contentVersion": "1.0.0.0" 258 | }, 259 | "parameters": { 260 | "workflows_OpenAIAnomalyDetectionAD_gen_name": { 261 | "value": "[parameters('workflows_AnomaliesDetection_name')]" 262 | }, 263 | "location": { 264 | "value": "[parameters('logicAppsLocation')]" 265 | } 266 | } 267 | }, 268 | "dependsOn": [ 269 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('LogicAppsRG'))]" 270 | ] 271 | }, 272 | { 273 | "type": "Microsoft.Resources/resourceGroups", 274 | "apiVersion": "2022-09-01", 275 | "name": "[parameters('FunctionRG')]", 276 | "location": "[parameters('FunctionRGLocation')]", 277 | "properties": {} 278 | }, 279 | { 280 | "type": "Microsoft.Resources/deployments", 281 | "apiVersion": "2019-10-01", 282 | "name": "DeployFunction", 283 | "resourceGroup": "[parameters('FunctionRG')]", 284 | "properties": { 285 | "mode": "Incremental", 286 | "templateLink": { 287 | "uri": "https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/refs/heads/main/OpenAI-CoreIntegrationLZ/CreateFunction.json", 288 | "contentVersion": "1.0.0.0" 289 | }, 290 | "parameters": { 291 | "subscriptionId": { 292 | "value": "[subscription().subscriptionId]" 293 | }, 294 | "name": { 295 | "value": "[parameters('FunctionName')]" 296 | }, 297 | "location": { 298 | "value": "[parameters('FunctionLocation')]" 299 | }, 300 | "ftpsState": { 301 | "value": "FtpsOnly" 302 | }, 303 | "storageAccountName": { 304 | "value": "[parameters('StorageAccountNameFunction')]" 305 | }, 306 | "sku": { 307 | "value": "Dynamic" 308 | }, 309 | "skuCode": { 310 | "value": "Y1" 311 | }, 312 | "workerSize": { 313 | "value": "0" 314 | }, 315 | "workerSizeId": { 316 | "value": "0" 317 | }, 318 | "numberOfWorkers": { 319 | "value": "1" 320 | }, 321 | "use32BitWorkerProcess": { 322 | "value": false 323 | }, 324 | "linuxFxVersion": { 325 | "value": "Python|3.11" 326 | }, 327 | "hostingPlanName": { 328 | "value": "ASP-OpenAIFunctionApps-b7a4" 329 | }, 330 | "serverFarmResourceGroup": { 331 | "value": "[parameters('FunctionRG')]" 332 | }, 333 | "alwaysOn": { 334 | "value": false 335 | } 336 | } 337 | }, 338 | "dependsOn": [ 339 | "[resourceId('Microsoft.Resources/resourceGroups', parameters('FunctionRG'))]" 340 | ] 341 | } 342 | ], 343 | "outputs": { 344 | "openAIResourceGroup": { 345 | "type": "string", 346 | "value": "[parameters('openAIResourceGroup')]" 347 | }, 348 | "FunctionRG": { 349 | "type": "string", 350 | "value": "[parameters('FunctionRG')]" 351 | }, 352 | "openAILocation": { 353 | "type": "string", 354 | "value": "[parameters('openAILocation')]" 355 | }, 356 | "sqlBPAResourceGroup": { 357 | "type": "string", 358 | "value": "[parameters('LogicAppsRG')]" 359 | } 360 | } 361 | } -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/AnomaliesDetection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "workflows_OpenAIAnomalyDetectionAD_gen_name": { 6 | "defaultValue": "OpenAIAnomalyDetectionAD", 7 | "type": "String" 8 | }, 9 | "connections_azuremonitorlogs_1_externalid": { 10 | "defaultValue": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Web/connections/office365')]", 11 | "type": "String" 12 | }, 13 | "location": { 14 | "defaultValue": "westeurope", 15 | "type": "String" 16 | } 17 | }, 18 | "variables": {}, 19 | "resources": [ 20 | { 21 | "type": "Microsoft.Logic/workflows", 22 | "apiVersion": "2017-07-01", 23 | "name": "[parameters('workflows_OpenAIAnomalyDetectionAD_gen_name')]", 24 | "location": "[resourceGroup().location]", 25 | "identity": { 26 | "type": "SystemAssigned" 27 | }, 28 | "properties": { 29 | "state": "Disabled", 30 | "definition": { 31 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", 32 | "contentVersion": "1.0.0.0", 33 | "parameters": { 34 | "$connections": { 35 | "defaultValue": {}, 36 | "type": "Object" 37 | } 38 | }, 39 | "triggers": { 40 | "Recurrence": { 41 | "recurrence": { 42 | "frequency": "Day", 43 | "interval": 1, 44 | "timeZone": "W. Europe Standard Time", 45 | "schedule": { 46 | "hours": [ 47 | "9" 48 | ] 49 | } 50 | }, 51 | "evaluatedRecurrence": { 52 | "frequency": "Day", 53 | "interval": 1, 54 | "timeZone": "W. Europe Standard Time", 55 | "schedule": { 56 | "hours": [ 57 | "9" 58 | ] 59 | } 60 | }, 61 | "type": "Recurrence" 62 | } 63 | }, 64 | "actions": { 65 | "Api-Key": { 66 | "runAfter": { 67 | "Run_query_and_list_results_V2_(Preview)": [ 68 | "Succeeded" 69 | ] 70 | }, 71 | "type": "InitializeVariable", 72 | "inputs": { 73 | "variables": [ 74 | { 75 | "name": "Api-Key", 76 | "type": "string", 77 | "value": "replace with your OpenAI api key" 78 | } 79 | ] 80 | } 81 | }, 82 | "Compose": { 83 | "runAfter": { 84 | "Clean_Result_III": [ 85 | "Succeeded" 86 | ] 87 | }, 88 | "type": "Compose", 89 | "inputs": "\n\n

Sistema automatico di segnalazione anomalie in ambiente AD- SiverzaLab Environment
\n
\nSalve, a seguito di un analisi all'interno dell'infrastruttura monitorata, è stato evidenziata la seguente anomalia:

\n-------------------------------------------------------------------------------------
\n
\n@{variables('ReportIII')}\n
\n
\n
\n

\n(*) Il sistema genera i dati sfruttando l'OpenAI pertando protrebbero verificarsi delle anomalie nel testo inerenti alla formattazione.

\n\"\"\n\n" 90 | }, 91 | "For_each_result": { 92 | "foreach": "@body('Run_query_and_list_results_V2_(Preview)')?['value']", 93 | "actions": { 94 | "Update_variable_Question": { 95 | "type": "SetVariable", 96 | "inputs": { 97 | "name": "Question", 98 | "value": "E' stata identificata la seguente anomalia da un sistema di monitoraggio. Dai qualche info in più su quando è stato identificato il messaggio, che EventID è con informazioni relative all'errore e la risorsa di riferimento, nient'altro:TimeGenerated=\n@{item()?['TimeGenerated']};@{item()?['ActualUsage']};@{item()?['ExpectedUsage']};@{item()?['AnomalyScore']};EvendID=@{item()?['EventID']};DC=@{item()?['Computer']}\nSegui questo esempio e usa \";\" come separatore:\nIl giorno 24 novembre 2024 alle ore 15 è stata segnalata un'anomalia sul sistema @{item()?['Computer']} con eventID @{item()?['EventID']}; L'event ID indica problemi di autenticazione utente;Alcuni step per il troublescooting:;Verifica Event Viewer; Verifica accessi anomali all'infrastruttura; Controlla le performance dell'applicazione;\n\n " 99 | } 100 | }, 101 | "Ask_to_OpenAI": { 102 | "runAfter": { 103 | "Update_variable_Question": [ 104 | "Succeeded" 105 | ] 106 | }, 107 | "type": "Http", 108 | "inputs": { 109 | "uri": "https://changeendpointname.openai.azure.com/openai/deployments/changemodelname/chat/completions?api-version=2024-02-15-preview", 110 | "method": "POST", 111 | "headers": { 112 | "Content-Type": "application/json", 113 | "api-key": "@variables('Api-Key')" 114 | }, 115 | "body": { 116 | "max_tokens": 600, 117 | "temperature": 0.3, 118 | "messages": [ 119 | { 120 | "content": "Sei un assistente che elenca le anomalie avvenute sui Domain Controllers di Microsoft Active Directory.", 121 | "role": "user" 122 | }, 123 | { 124 | "content": "@{variables('Question')}", 125 | "role": "user" 126 | } 127 | ] 128 | } 129 | } 130 | }, 131 | "Parse_OpenAI_response": { 132 | "runAfter": { 133 | "Ask_to_OpenAI": [ 134 | "Succeeded" 135 | ] 136 | }, 137 | "type": "ParseJson", 138 | "inputs": { 139 | "content": "@body('Ask_to_OpenAI')", 140 | "schema": { 141 | "properties": { 142 | "body": { 143 | "properties": { 144 | "choices": { 145 | "items": { 146 | "properties": { 147 | "content_filter_results": { 148 | "properties": { 149 | "hate": { 150 | "properties": { 151 | "filtered": { 152 | "type": "boolean" 153 | }, 154 | "severity": { 155 | "type": "string" 156 | } 157 | }, 158 | "type": "object" 159 | }, 160 | "self_harm": { 161 | "properties": { 162 | "filtered": { 163 | "type": "boolean" 164 | }, 165 | "severity": { 166 | "type": "string" 167 | } 168 | }, 169 | "type": "object" 170 | }, 171 | "sexual": { 172 | "properties": { 173 | "filtered": { 174 | "type": "boolean" 175 | }, 176 | "severity": { 177 | "type": "string" 178 | } 179 | }, 180 | "type": "object" 181 | }, 182 | "violence": { 183 | "properties": { 184 | "filtered": { 185 | "type": "boolean" 186 | }, 187 | "severity": { 188 | "type": "string" 189 | } 190 | }, 191 | "type": "object" 192 | } 193 | }, 194 | "type": "object" 195 | }, 196 | "finish_reason": { 197 | "type": "string" 198 | }, 199 | "index": { 200 | "type": "integer" 201 | }, 202 | "message": { 203 | "properties": { 204 | "content": { 205 | "type": "string" 206 | }, 207 | "role": { 208 | "type": "string" 209 | } 210 | }, 211 | "type": "object" 212 | } 213 | }, 214 | "required": [ 215 | "index", 216 | "finish_reason", 217 | "message", 218 | "content_filter_results" 219 | ], 220 | "type": "object" 221 | }, 222 | "type": "array" 223 | }, 224 | "created": { 225 | "type": "integer" 226 | }, 227 | "id": { 228 | "type": "string" 229 | }, 230 | "model": { 231 | "type": "string" 232 | }, 233 | "object": { 234 | "type": "string" 235 | }, 236 | "prompt_filter_results": { 237 | "items": { 238 | "properties": { 239 | "content_filter_results": { 240 | "properties": { 241 | "hate": { 242 | "properties": { 243 | "filtered": { 244 | "type": "boolean" 245 | }, 246 | "severity": { 247 | "type": "string" 248 | } 249 | }, 250 | "type": "object" 251 | }, 252 | "self_harm": { 253 | "properties": { 254 | "filtered": { 255 | "type": "boolean" 256 | }, 257 | "severity": { 258 | "type": "string" 259 | } 260 | }, 261 | "type": "object" 262 | }, 263 | "sexual": { 264 | "properties": { 265 | "filtered": { 266 | "type": "boolean" 267 | }, 268 | "severity": { 269 | "type": "string" 270 | } 271 | }, 272 | "type": "object" 273 | }, 274 | "violence": { 275 | "properties": { 276 | "filtered": { 277 | "type": "boolean" 278 | }, 279 | "severity": { 280 | "type": "string" 281 | } 282 | }, 283 | "type": "object" 284 | } 285 | }, 286 | "type": "object" 287 | }, 288 | "prompt_index": { 289 | "type": "integer" 290 | } 291 | }, 292 | "required": [ 293 | "prompt_index", 294 | "content_filter_results" 295 | ], 296 | "type": "object" 297 | }, 298 | "type": "array" 299 | }, 300 | "usage": { 301 | "properties": { 302 | "completion_tokens": { 303 | "type": "integer" 304 | }, 305 | "prompt_tokens": { 306 | "type": "integer" 307 | }, 308 | "total_tokens": { 309 | "type": "integer" 310 | } 311 | }, 312 | "type": "object" 313 | } 314 | }, 315 | "type": "object" 316 | } 317 | }, 318 | "type": "object" 319 | } 320 | } 321 | }, 322 | "For_each": { 323 | "foreach": "@outputs('Parse_OpenAI_response')?['body']?['choices']", 324 | "actions": { 325 | "Append_to_array_variable": { 326 | "type": "AppendToArrayVariable", 327 | "inputs": { 328 | "name": "Anomalies", 329 | "value": "@items('For_each')?['message']?['content']" 330 | } 331 | } 332 | }, 333 | "runAfter": { 334 | "Parse_OpenAI_response": [ 335 | "Succeeded" 336 | ] 337 | }, 338 | "type": "Foreach" 339 | } 340 | }, 341 | "runAfter": { 342 | "Set_Variable_Anomaly_Detection": [ 343 | "Succeeded" 344 | ] 345 | }, 346 | "type": "Foreach", 347 | "runtimeConfiguration": { 348 | "concurrency": { 349 | "repetitions": 1 350 | } 351 | } 352 | }, 353 | "Run_query_and_list_results_V2_(Preview)": { 354 | "runAfter": {}, 355 | "type": "ApiConnection", 356 | "inputs": { 357 | "host": { 358 | "connection": { 359 | "name": "@parameters('$connections')['azuremonitorlogs-1']['connectionId']" 360 | } 361 | }, 362 | "method": "post", 363 | "body": { 364 | "query": "let starttime = 7d; \nlet endtime = 0d;\nlet timeframe = 60m;\nEvent \n| where TimeGenerated between (startofday(ago(starttime)) .. startofday(ago(endtime))) \n| where Computer startswith \"DC\"\n| where RenderedDescription contains \"error\" \n| summarize count() by bin(TimeGenerated, 60s), Computer, EventID \n| make-series ActualUsage=avg(count_) default = 0 on TimeGenerated from startofday(ago(starttime)) \tto startofday(ago(endtime)) step timeframe by Computer, EventID \n| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(ActualUsage) \n| mv-expand\n ActualUsage to typeof(double),\n TimeGenerated to typeof(datetime),\n Anomalies to typeof(double),\n AnomalyScore to typeof(double),\n ExpectedUsage to typeof(long)\n| where abs(AnomalyScore) > 7 and abs(ActualUsage - ExpectedUsage) / ActualUsage > 0.5 \n| project TimeGenerated, ActualUsage, ExpectedUsage, abs(AnomalyScore), EventID, Computer\n| sort by abs(AnomalyScore) desc", 365 | "timerangetype": "3" 366 | }, 367 | "path": "/queryDataV2", 368 | "queries": { 369 | "subscriptions": "replacewithsubid", 370 | "resourcegroups": "replacewithR", 371 | "resourcetype": "Log Analytics Workspace", 372 | "resourcename": "replacewithRN" 373 | } 374 | } 375 | }, 376 | "Set_Variable_Question": { 377 | "runAfter": { 378 | "Api-Key": [ 379 | "Succeeded" 380 | ] 381 | }, 382 | "type": "InitializeVariable", 383 | "inputs": { 384 | "variables": [ 385 | { 386 | "name": "Question", 387 | "type": "string" 388 | } 389 | ] 390 | } 391 | }, 392 | "Set_Variable_Anomaly_Detection": { 393 | "runAfter": { 394 | "Set_Variable_Question": [ 395 | "Succeeded" 396 | ] 397 | }, 398 | "type": "InitializeVariable", 399 | "inputs": { 400 | "variables": [ 401 | { 402 | "name": "Anomalies", 403 | "type": "array" 404 | } 405 | ] 406 | } 407 | }, 408 | "Clean_Result_I": { 409 | "runAfter": { 410 | "For_each_result": [ 411 | "Succeeded" 412 | ] 413 | }, 414 | "type": "InitializeVariable", 415 | "inputs": { 416 | "variables": [ 417 | { 418 | "name": "Report", 419 | "type": "string", 420 | "value": "@replace(string(variables('Anomalies')), '[\"','
')" 421 | } 422 | ] 423 | } 424 | }, 425 | "Clean_Result_II": { 426 | "runAfter": { 427 | "Clean_Result_I": [ 428 | "Succeeded" 429 | ] 430 | }, 431 | "type": "InitializeVariable", 432 | "inputs": { 433 | "variables": [ 434 | { 435 | "name": "ReportII", 436 | "type": "string", 437 | "value": "@replace(variables('Report'), '\",\"','
')" 438 | } 439 | ] 440 | } 441 | }, 442 | "Clean_Result_III": { 443 | "runAfter": { 444 | "Clean_Result_II": [ 445 | "Succeeded" 446 | ] 447 | }, 448 | "type": "InitializeVariable", 449 | "inputs": { 450 | "variables": [ 451 | { 452 | "name": "ReportIII", 453 | "type": "string", 454 | "value": "@replace(variables('ReportII'), '\"]','
')" 455 | } 456 | ] 457 | } 458 | } 459 | }, 460 | "outputs": {} 461 | }, 462 | "parameters": { 463 | "$connections": { 464 | "value": { 465 | 466 | } 467 | } 468 | } 469 | } 470 | } 471 | ] 472 | } -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/CreateFunction.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "subscriptionId": { 6 | "type": "string" 7 | }, 8 | "name": { 9 | "type": "string" 10 | }, 11 | "location": { 12 | "type": "string" 13 | }, 14 | "use32BitWorkerProcess": { 15 | "type": "bool" 16 | }, 17 | "ftpsState": { 18 | "type": "string" 19 | }, 20 | "storageAccountName": { 21 | "type": "string" 22 | }, 23 | "linuxFxVersion": { 24 | "type": "string" 25 | }, 26 | "sku": { 27 | "type": "string" 28 | }, 29 | "skuCode": { 30 | "type": "string" 31 | }, 32 | "workerSize": { 33 | "type": "string" 34 | }, 35 | "workerSizeId": { 36 | "type": "string" 37 | }, 38 | "numberOfWorkers": { 39 | "type": "string" 40 | }, 41 | "hostingPlanName": { 42 | "type": "string" 43 | }, 44 | "serverFarmResourceGroup": { 45 | "type": "string" 46 | }, 47 | "alwaysOn": { 48 | "type": "bool" 49 | } 50 | }, 51 | "variables": { 52 | "contentShare": "openaidocscreator855a" 53 | }, 54 | "resources": [ 55 | { 56 | "apiVersion": "2022-03-01", 57 | "name": "[parameters('name')]", 58 | "type": "Microsoft.Web/sites", 59 | "kind": "functionapp,linux", 60 | "location": "[parameters('location')]", 61 | "tags": {}, 62 | "dependsOn": [ 63 | "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]", 64 | "[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]" 65 | ], 66 | "properties": { 67 | "name": "[parameters('name')]", 68 | "siteConfig": { 69 | "appSettings": [ 70 | { 71 | "name": "FUNCTIONS_EXTENSION_VERSION", 72 | "value": "~4" 73 | }, 74 | { 75 | "name": "FUNCTIONS_WORKER_RUNTIME", 76 | "value": "python" 77 | }, 78 | { 79 | "name": "AzureWebJobsStorage", 80 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]" 81 | }, 82 | { 83 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", 84 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]" 85 | }, 86 | { 87 | "name": "WEBSITE_CONTENTSHARE", 88 | "value": "[variables('contentShare')]" 89 | } 90 | ], 91 | "cors": { 92 | "allowedOrigins": [ 93 | "https://portal.azure.com" 94 | ] 95 | }, 96 | "use32BitWorkerProcess": "[parameters('use32BitWorkerProcess')]", 97 | "ftpsState": "[parameters('ftpsState')]", 98 | "linuxFxVersion": "[parameters('linuxFxVersion')]" 99 | }, 100 | "clientAffinityEnabled": false, 101 | "virtualNetworkSubnetId": null, 102 | "publicNetworkAccess": "Enabled", 103 | "httpsOnly": true, 104 | "serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]" 105 | }, 106 | "resources": [ 107 | { 108 | "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", 109 | "apiVersion": "2022-09-01", 110 | "name": "[concat(parameters('name'), '/scm')]", 111 | "properties": { 112 | "allow": false 113 | }, 114 | "dependsOn": [ 115 | "[resourceId('Microsoft.Web/Sites', parameters('name'))]" 116 | ] 117 | }, 118 | { 119 | "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", 120 | "apiVersion": "2022-09-01", 121 | "name": "[concat(parameters('name'), '/ftp')]", 122 | "properties": { 123 | "allow": false 124 | }, 125 | "dependsOn": [ 126 | "[resourceId('Microsoft.Web/Sites', parameters('name'))]" 127 | ] 128 | } 129 | ] 130 | }, 131 | { 132 | "apiVersion": "2018-11-01", 133 | "name": "[parameters('hostingPlanName')]", 134 | "type": "Microsoft.Web/serverfarms", 135 | "location": "[parameters('location')]", 136 | "kind": "linux", 137 | "tags": {}, 138 | "dependsOn": [], 139 | "properties": { 140 | "name": "[parameters('hostingPlanName')]", 141 | "workerSize": "[parameters('workerSize')]", 142 | "workerSizeId": "[parameters('workerSizeId')]", 143 | "numberOfWorkers": "[parameters('numberOfWorkers')]", 144 | "reserved": true 145 | }, 146 | "sku": { 147 | "Tier": "[parameters('sku')]", 148 | "Name": "[parameters('skuCode')]" 149 | } 150 | }, 151 | { 152 | "apiVersion": "2022-05-01", 153 | "type": "Microsoft.Storage/storageAccounts", 154 | "name": "[parameters('storageAccountName')]", 155 | "dependsOn": [], 156 | "location": "[parameters('location')]", 157 | "tags": {}, 158 | "sku": { 159 | "name": "Standard_LRS" 160 | }, 161 | "properties": { 162 | "supportsHttpsTrafficOnly": true, 163 | "minimumTlsVersion": "TLS1_2", 164 | "defaultToOAuthAuthentication": true 165 | } 166 | } 167 | ] 168 | } -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/README.md: -------------------------------------------------------------------------------- 1 |

AI for Operation Framework LZ

2 | 3 | | **Parameters/Requirements** | **Information** | **Note** | 4 | | ------------- | ------------- | ------------- | 5 | | Region | The Default Region used for the deployment | Select the Region | 6 | | Open AI Resource Group | Create the Resource Group for OpenAI resource | Replace with RG Name | 7 | | Logic Apps Resource Group | Create the Resource Group for Logic Apps resource | Replace with RG Name | 8 | | Open AI Location | Insert the Location for the deployment of Azure OpenAI | Replace with the location | 9 | | Logic Apps Location | Insert the Location for the Logic Apps Deployment | Replace with the location | 10 | | Open AI Name | Insert the name for the Open AI Deployed resource | Replace with the name. Must be Globally unique | 11 | | LogicApp_SQL_BPA_AI_name | Insert the name for the SQL BPA Logic App Deployed | Replace with the required name | 12 | | LogicApp_Open AI Cost Monthly Check_name | Insert the name for the Cost Mgmt Logic App Deployed | Replace with the required name | 13 | | LogicApp_Open AI SmartUpdate | Insert the name for the SmartUpdate Logic App Deployed | Replace with the required name | 14 | | LogicApp_Open AI AnomaliesDetection | Insert the name for the AnomaliesDetection Logic App Deployed | Replace with the required name | 15 | | Function RG | Insert the name for the Function App Resource Group | Replace with the required name | 16 | | Function RG Location | Insert the location for the RG where the Function will be placed | Replace with the location | 17 | | Function Name | Insert the name Function App Deployed | Replace with the required name. Must be Globally unique | 18 | | Function Location | Insert the location for the Function App Deployed | Replace with the location | 19 | | Storage Account Name Function | Insert the name for the Storage Account | The Storage Account is a mandatory resource for the Function App. Name Must be Globally unique | 20 | 21 |

Important

22 | The following deployment require a dedicated Subscription already in-place. This subscription, following the Enterprise Scale Diagram, must be placed in a identified Management Group 23 | 24 | Reference: 25 | [Azure Enterprise Scale Reference](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/#azure-landing-zone-architecture) 26 | 27 |

Architectural Overview

28 | 29 | ![OpenAI-CoreIntegration LZ](./images/OpenAI-CoreIntegration_page-0001.jpg) 30 | 31 |

Deploy

32 | 33 | Configuration 34 | 35 | 36 | 37 | 38 | 39 | 40 | When you deploy, replace all the parameters with the required information 41 | 42 | ![Deploy](./images/deploy.jpeg) 43 | 44 | If the information provided are correct, the deployment will proceed 45 | 46 | ![Deployment Progress](./images/start_deployment.jpeg) 47 | 48 |

Post Deployment

49 | 50 | When the deployment is completed, to view all the resources go to Azure Portal > Subscription > Select the subscription used during the deployment > Resources 51 | 52 | or click on the "Go to subscription" button: 53 | 54 | ![Deployment Progress](./images/deployment_complete.jpeg) 55 | 56 |

Solution Configuration

57 | 58 | Each solution created in the initiative have a dedicated configuration flow: 59 | 60 | - [SQL BPA Enhanced Assessment Logic App](../Arc-SQL%20BPA/README.md) 61 | - [Cost Monthly Check Logic App](../CostMonthlyCheck/README.md) 62 | - [Update Management Logic App](../UpdateManagement/README.md) 63 | - [Anomalies Detection Logic App](../AnomaliesDetection/README.md) 64 | - [Function App](../FunctionAppSmartDocs/README.md): An empty box ready to be used for deploy custom Script\Application integrated with OpenAI. (Some example will be provided during the engagement. An App Developer skilled on Azure Function Customization and Deployment is needed). 65 | 66 | Please reach your CSA for be followed during the configuration. -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/images/OpenAI-CoreIntegration_page-0001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/OpenAI-CoreIntegrationLZ/images/OpenAI-CoreIntegration_page-0001.jpg -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/images/deploy.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/OpenAI-CoreIntegrationLZ/images/deploy.jpeg -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/images/deployment_complete.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/OpenAI-CoreIntegrationLZ/images/deployment_complete.jpeg -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/images/start_deployment.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/OpenAI-CoreIntegrationLZ/images/start_deployment.jpeg -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/templateBingSearch.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "name": { 6 | "type": "string" 7 | }, 8 | "location": { 9 | "type": "string" 10 | }, 11 | "sku": { 12 | "type": "string" 13 | }, 14 | "tagValues": { 15 | "type": "object" 16 | } 17 | }, 18 | "resources": [ 19 | { 20 | "apiVersion": "2020-06-10", 21 | "name": "[parameters('name')]", 22 | "location": "[parameters('location')]", 23 | "type": "Microsoft.Bing/accounts", 24 | "kind": "Bing.Search.v7", 25 | "tags": "[if(contains(parameters('tagValues'), 'Microsoft.Bing/accounts'), parameters('tagValues')['Microsoft.Bing/accounts'], json('{}'))]", 26 | "sku": { 27 | "name": "[parameters('sku')]" 28 | } 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /OpenAI-CoreIntegrationLZ/templateOpenAI.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "name": { 6 | "type": "string" 7 | }, 8 | "location": { 9 | "type": "string" 10 | }, 11 | "sku": { 12 | "type": "string" 13 | }, 14 | "tagValues": { 15 | "type": "object" 16 | }, 17 | "virtualNetworkType": { 18 | "type": "string" 19 | }, 20 | "vnet": { 21 | "type": "object" 22 | }, 23 | "ipRules": { 24 | "type": "array" 25 | }, 26 | "privateEndpoints": { 27 | "type": "array" 28 | }, 29 | "privateDnsZone": { 30 | "type": "string" 31 | }, 32 | "resourceGroupName": { 33 | "type": "string" 34 | }, 35 | "resourceGroupId": { 36 | "type": "string" 37 | }, 38 | "uniqueId": { 39 | "type": "string", 40 | "defaultValue": "[newGuid()]" 41 | } 42 | }, 43 | "resources": [ 44 | { 45 | "type": "Microsoft.Resources/deployments", 46 | "apiVersion": "2017-05-10", 47 | "name": "deployVnet", 48 | "properties": { 49 | "mode": "Incremental", 50 | "template": { 51 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 52 | "contentVersion": "1.0.0.0", 53 | "parameters": {}, 54 | "variables": {}, 55 | "resources": [ 56 | { 57 | "type": "Microsoft.Network/virtualNetworks", 58 | "apiVersion": "2020-04-01", 59 | "name": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').name, variables('defaultVNetName'))]", 60 | "location": "[parameters('location')]", 61 | "properties": { 62 | "addressSpace": { 63 | "addressPrefixes": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').addressPrefixes, json(concat('[{\"', variables('defaultAddressPrefix'),'\"}]')))]" 64 | }, 65 | "subnets": [ 66 | { 67 | "name": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').subnets.subnet.name, variables('defaultSubnetName'))]", 68 | "properties": { 69 | "serviceEndpoints": [ 70 | { 71 | "service": "Microsoft.CognitiveServices", 72 | "locations": [ 73 | "[parameters('location')]" 74 | ] 75 | } 76 | ], 77 | "addressPrefix": "[if(equals(parameters('virtualNetworkType'), 'External'), parameters('vnet').subnets.subnet.addressPrefix, variables('defaultAddressPrefix'))]" 78 | } 79 | } 80 | ] 81 | } 82 | } 83 | ] 84 | }, 85 | "parameters": {} 86 | }, 87 | "condition": "[and(and(not(empty(parameters('vnet'))), equals(parameters('vnet').newOrExisting, 'new')), equals(parameters('virtualNetworkType'), 'External'))]" 88 | }, 89 | { 90 | "apiVersion": "2022-03-01", 91 | "name": "[parameters('name')]", 92 | "location": "[parameters('location')]", 93 | "type": "Microsoft.CognitiveServices/accounts", 94 | "kind": "OpenAI", 95 | "tags": "[if(contains(parameters('tagValues'), 'Microsoft.CognitiveServices/accounts'), parameters('tagValues')['Microsoft.CognitiveServices/accounts'], json('{}'))]", 96 | "sku": { 97 | "name": "[parameters('sku')]" 98 | }, 99 | "properties": { 100 | "customSubDomainName": "[toLower(parameters('name'))]", 101 | "publicNetworkAccess": "[if(equals(parameters('virtualNetworkType'), 'Internal'), 'Disabled', 'Enabled')]", 102 | "networkAcls": { 103 | "defaultAction": "[if(equals(parameters('virtualNetworkType'), 'External'), 'Deny', 'Allow')]", 104 | "virtualNetworkRules": "[if(equals(parameters('virtualNetworkType'), 'External'), json(concat('[{\"id\": \"', concat(subscription().id, '/resourceGroups/', parameters('vnet').resourceGroup, '/providers/Microsoft.Network/virtualNetworks/', parameters('vnet').name, '/subnets/', parameters('vnet').subnets.subnet.name), '\"}]')), json('[]'))]", 105 | "ipRules": "[if(or(empty(parameters('ipRules')), empty(parameters('ipRules')[0].value)), json('[]'), parameters('ipRules'))]" 106 | } 107 | }, 108 | "dependsOn": [ 109 | "[concat('Microsoft.Resources/deployments/', 'deployVnet')]" 110 | ] 111 | }, 112 | { 113 | "apiVersion": "2018-05-01", 114 | "name": "[concat('deployPrivateEndpoint-', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name)]", 115 | "type": "Microsoft.Resources/deployments", 116 | "resourceGroup": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.resourceGroup.value.name]", 117 | "subscriptionId": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.subscription.subscriptionId]", 118 | "dependsOn": [ 119 | "[concat('Microsoft.CognitiveServices/accounts/', parameters('name'))]" 120 | ], 121 | "condition": "[equals(parameters('virtualNetworkType'), 'Internal')]", 122 | "copy": { 123 | "name": "privateendpointscopy", 124 | "count": "[length(parameters('privateEndpoints'))]" 125 | }, 126 | "properties": { 127 | "mode": "Incremental", 128 | "template": { 129 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 130 | "contentVersion": "1.0.0.0", 131 | "resources": [ 132 | { 133 | "location": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.location]", 134 | "name": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name]", 135 | "type": "Microsoft.Network/privateEndpoints", 136 | "apiVersion": "2021-05-01", 137 | "properties": { 138 | "subnet": { 139 | "id": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.properties.subnet.id]" 140 | }, 141 | "privateLinkServiceConnections": [ 142 | { 143 | "name": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name]", 144 | "properties": { 145 | "privateLinkServiceId": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.CognitiveServices/accounts/', parameters('name'))]", 146 | "groupIds": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.properties.privateLinkServiceConnections[0].properties.groupIds]" 147 | } 148 | } 149 | ], 150 | "customNetworkInterfaceName": "[concat(parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name, '-nic')]" 151 | }, 152 | "tags": {} 153 | } 154 | ] 155 | } 156 | } 157 | }, 158 | { 159 | "apiVersion": "2018-05-01", 160 | "name": "[concat('deployDnsZoneGroup-', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name)]", 161 | "type": "Microsoft.Resources/deployments", 162 | "resourceGroup": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.resourceGroup.value.name]", 163 | "subscriptionId": "[parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.subscription.subscriptionId]", 164 | "dependsOn": [ 165 | "[concat('deployPrivateEndpoint-', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name)]" 166 | ], 167 | "condition": "[and(equals(parameters('virtualNetworkType'), 'Internal'), parameters('privateEndpoints')[copyIndex()].privateDnsZoneConfiguration.integrateWithPrivateDnsZone)]", 168 | "copy": { 169 | "name": "privateendpointdnscopy", 170 | "count": "[length(parameters('privateEndpoints'))]" 171 | }, 172 | "properties": { 173 | "mode": "Incremental", 174 | "template": { 175 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 176 | "contentVersion": "1.0.0.0", 177 | "resources": [ 178 | { 179 | "type": "Microsoft.Network/privateDnsZones", 180 | "apiVersion": "2018-09-01", 181 | "name": "[parameters('privateDnsZone')]", 182 | "location": "global", 183 | "tags": {}, 184 | "properties": {} 185 | }, 186 | { 187 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 188 | "apiVersion": "2018-09-01", 189 | "name": "[concat(parameters('privateDnsZone'), '/', replace(uniqueString(parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.properties.subnet.id), '/subnets/default', ''))]", 190 | "location": "global", 191 | "dependsOn": [ 192 | "[parameters('privateDnsZone')]" 193 | ], 194 | "properties": { 195 | "virtualNetwork": { 196 | "id": "[split(parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.properties.subnet.id, '/subnets/')[0]]" 197 | }, 198 | "registrationEnabled": false 199 | } 200 | }, 201 | { 202 | "apiVersion": "2017-05-10", 203 | "name": "[concat('EndpointDnsRecords-', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name)]", 204 | "type": "Microsoft.Resources/deployments", 205 | "dependsOn": [ 206 | "[parameters('privateDnsZone')]" 207 | ], 208 | "properties": { 209 | "mode": "Incremental", 210 | "templatelink": { 211 | "uri": "https://go.microsoft.com/fwlink/?linkid=2264916" 212 | }, 213 | "parameters": { 214 | "privateDnsName": { 215 | "value": "[parameters('privateDnsZone')]" 216 | }, 217 | "privateEndpointNicResourceId": { 218 | "value": "[concat('/subscriptions/', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.subscription.subscriptionId, '/resourceGroups/', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.resourceGroup.value.name, '/providers/Microsoft.Network/networkInterfaces/', parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name, '-nic')]" 219 | }, 220 | "nicRecordsTemplateUri": { 221 | "value": "https://go.microsoft.com/fwlink/?linkid=2264719" 222 | }, 223 | "ipConfigRecordsTemplateUri": { 224 | "value": "https://go.microsoft.com/fwlink/?linkid=2265018" 225 | }, 226 | "uniqueId": { 227 | "value": "[parameters('uniqueId')]" 228 | }, 229 | "existingRecords": { 230 | "value": {} 231 | } 232 | } 233 | } 234 | }, 235 | { 236 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 237 | "apiVersion": "2020-03-01", 238 | "name": "[concat(parameters('privateEndpoints')[copyIndex()].privateEndpointConfiguration.privateEndpoint.name, '/', 'default')]", 239 | "location": "[parameters('location')]", 240 | "dependsOn": [ 241 | "[parameters('privateDnsZone')]" 242 | ], 243 | "properties": { 244 | "privateDnsZoneConfigs": [ 245 | { 246 | "name": "privatelink-cognitiveservices", 247 | "properties": { 248 | "privateDnsZoneId": "[concat(parameters('resourceGroupId'), '/providers/Microsoft.Network/privateDnsZones/', parameters('privateDnsZone'))]" 249 | } 250 | } 251 | ] 252 | } 253 | } 254 | ] 255 | } 256 | } 257 | } 258 | ] 259 | } -------------------------------------------------------------------------------- /Prereq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/Prereq.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AIforOperations 2 | 3 | Welcome to the **Microsoft Azure AI for Operation Framework** repo! The purpose of this site is to provide sample OpenAI integration with LogicApp 4 | 5 | **Solution Name** | **Information** | **Configuration** | 6 | | ------------- | ------------- | ------------- | 7 | | Arc-SQL BPA | Logic App used to Asses with Azure OpenAI your DBs on Azure ARC Solution | [Configuration Link](./Arc-SQL%20BPA/README.md) | 8 | | UpdateManager Integration | Logic App used to Integrate Azure UM with OpenAI comment | [Configuration Link](./UpdateManagement/README.md) | 9 | | CostMonthlyCheck Integration | Logic App used to Monitor Cost Monthly with OpenAI comment | [Configuration Link](./CostMonthlyCheck/README.md) | 10 | | Anomalies Detection Integration | Logic App used to Monitor Anomalies Detection | [Configuration Link](./AnomaliesDetection/README.md) | 11 | | AI for Operation Framework LZ | Foundation - ARM template for AI for Op Landing Zone | [Configuration Link](./OpenAI-CoreIntegrationLZ/README.md) | 12 | 13 |

Learning Resources

14 | 15 | Learning 16 | 17 | Explore detailed resources and guides on key Azure technologies and OpenAI Landing Zone Architectural Reference in the [Learning Folder](./Learning/README.md). This folder includes insights on: 18 | - OpenAI integration with Azure 19 | - Building workflows with Logic Apps 20 | - Managing APIs with Azure API Management 21 | - Using AI and Machine Learning on Azure 22 | - Other essential Azure technologies 23 | 24 | 25 |

Prerequisites

26 | 27 | 28 | Enable Azure OpenAI service and configure LLM model. Please be aware that some solutions may require some specific Azure OpenAI model. If you choose the Landing Zone Deployment that resource will be created automatically. 29 | 30 | ![OpenAI Prereq](./Prereq.png ) 31 | 32 |

Arc-SQL BestPracticesAssessment OpenAI integration

33 | 34 | 35 | This template can be used for the deployment of a Logic App of SQL BPA with OpenAI report. 36 | 37 | 38 | 39 | 40 | 41 | 42 |

Azure UpdateManager OpenAI integration

43 | 44 | 45 | This template can be used for the deployment of a Logic App to send UpdateManager report with OpenAI Comment of Pending security fix. 46 | 47 | 48 | 49 | 50 | 51 |

Azure Cost Monthly Check OpenAI integration

52 | 53 | This template can be used for the deployment of a Logic App to send Monthly Cost Monitor report with OpenAI Comment. 54 | 55 | 56 | 57 | 58 | 59 |

Azure Anomalies Detection

60 | 61 | This template can be used for the deployment of a Logic App to monitor anomalies on AD and other scenario. 62 | 63 | 64 | 65 | 66 | 67 | 68 | ## Contributing 69 | 70 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 71 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 72 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 73 | 74 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 75 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 76 | provided by the bot. You will only need to do this once across all repos using our CLA. 77 | 78 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 79 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 80 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 81 | 82 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. 7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /UpdateManagement/README.md: -------------------------------------------------------------------------------- 1 |

Azure UpdateManager OpenAI integration: Configuration

2 | 3 | | **Parameters** | **Information** | **Note** | 4 | | ------------- | ------------- | ------------- | 5 | | replacewithsubid | Connection setting during deployment | Replace with your Subscription ID | 6 | | repreplacewithRG | Connection setting during deployment | Replace with the selected RG Name for the deployment | 7 | | api-key | The API code for manage your OpenAI service | The parameter is inside the second "Initialize Variable". Put your question in the "value" attribute | 8 | | changeendpointname | Insert the OpenAI endpoint name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 9 | | changemodelname | Insert the model name | You can found the value inside the OpenAI resource inside Azure Cognitive Service | 10 | 11 |

Important

12 | This LogApp and the following changes are an example of integrating UpdateManager results with OpenAI, creating a report send via Email with OpenAI comment of pending Security Update of your environment. 13 | 14 | 15 |

Required Identity

16 |

Managed Identity

17 | 18 | Now configure the HTTP request to the Graph Explorer enabling the authentication via System Assigned Managed Identity. Please remind that the Managed Identity need to have the righ permission on the subscription for read the resources: 19 | 20 | 21 | ![identity](./images/identity.jpg) 22 | 23 | 24 |

Deployment and Result

25 | 26 | After deployment completed, please follow the documentation: 27 | 28 | 29 | As first step please configure the required recurrence: 30 | 31 | ![recurrence](./images/recurrence.jpg) 32 | 33 | 34 | Configure the Api Key with the value inside your OpenAI Service: 35 | 36 | ![Api Key](./images/ApiKey.jpg) 37 | 38 | At this point we need to configure the Ask to OpenAI module replacing the required parameters: 39 | 40 | ![OpenAI](./images/OpenAI.jpg) 41 | 42 | Now we have 2 posibilities: 43 | - Modify the body of the e-mail using a "Compose" module 44 | - Use the body inside the "Send Email V2" module. The choice is up to you. 45 | 46 | In case you choose the first option below an example: 47 | 48 | ![OpenAI](./images/Compose.jpeg) 49 | 50 | Last Replace variable: 51 | 52 | ```Compose 53 | replace(variables('Remove square II'), '\n','') 54 | ``` 55 | 56 | Last step is to add a notification section. 57 | In the example below we have a "Send Email V2" connector for send the final report to the required people or to a Teams channel . If you want to follow the same approach configure the module following the same example adding them at the end of the Logic App. Make sure to use the correct variable in the body of the email in order to have them correctly formatted: 58 | 59 | ![example](./images/example-notification.jpg) 60 | 61 | P.S. if you need an attachment, remember to convert the output file in base 64 using the example below: 62 | 63 | ```Compose 64 | { 65 | "ContentBytes": "@{base64(body('Create_CSV_table'))}", 66 | "Name": "attachment.csv" 67 | } 68 | ``` -------------------------------------------------------------------------------- /UpdateManagement/images/ApiKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/ApiKey.jpg -------------------------------------------------------------------------------- /UpdateManagement/images/Compose.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/Compose.jpeg -------------------------------------------------------------------------------- /UpdateManagement/images/OpenAI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/OpenAI.jpg -------------------------------------------------------------------------------- /UpdateManagement/images/example-notification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/example-notification.jpg -------------------------------------------------------------------------------- /UpdateManagement/images/identity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/identity.jpg -------------------------------------------------------------------------------- /UpdateManagement/images/recurrence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AI-for-Operations-Framework/f31c8c3b06e53b3d532499abd21cf14abdece942/UpdateManagement/images/recurrence.jpg --------------------------------------------------------------------------------