Articoli

token OAuth2

Vediamo come utilizzare alcune delle funzionalità introdotte da Microsoft negli ultimi aggiornamenti di Business Central riguardo l’utilizzo e la gestione dei token.

Nello scorso articolo (Business Central Autenticazione oAuth2 e ottenimento di un token) si è parlato di come ottenere un token OAuth2 dalla Azure Directory per accedere alle API di Business Central, in questo verrà mostrato uno dei possibili modi di gestione dei Token OAuth all’interno di BC.

Ipotizziamo di volerci collegare ad un Business Central Saas impostato come mostrato nel precedente articolo, ma la procedura vale per qualsiasi altro servizio che utilizza questo tipo di autenticazione.

Il primo passo da eseguire è l’inserimento dell’app creata su Azure in Business Central inserendola in questa pagina chiamata ”Applicazione di Azure Directory”

In questa pagina è necessario inserire nel campo ID Client lo stesso id dell’applicazione creata sul portale Azure.

Business Central

Nel campo descrizione poi si inserirà una descrizione di quello che l’applicazione deve fare in modo da identificarla e poi andremo ad inserire i vari permessi esattamente come per gli utenti di Business Central.

A questo punto l’applicazione è censita in Business Central e possiamo passare alla parte di codice.

Negli ultimi tempi Microsoft ha arricchito la parte di codeunit riguardante la gestione dei token OAuth al fine di migliorare la vita ai programmatori e standardizzare il più possibile il metodo con cui vengono richiesti.

In questo caso verrà utilizzata la codeunit “OAuth2” che contiene la funzione “AcquireTokenWithClientCredentials” che permette di acquisire il token da utilizzare poi per le richieste http.

La procedura ha bisogno di alcuni parametri in ingresso:

  • ClientID, è l’id dell’app che è stata creata su Azure e censita in Business Central
  • SecretID, è l’id segreto che viene staccato al momento della creazione dell’applicazione su Azure
  • TokenUrl, è l’indirizzo del portale a cui viene richiesto il token nel caso di Business Central è composto in questo modo, dove tenantID è l’id del tenant a cui è necessario collegarsi: ‘https://login.microsoftonline.com/’ + TenantID() + ‘/oauth2/v2.0/token’
  • Scopes è una lista di testi e in questo caso va inserito l’indirizzo delle api di Business Central: https://api.businesscentral.dynamics.com/.default
  • Token è il parametro più importante in quanto la variabile passata come var conterrà il token ottenuto dalla funzione e che servirà poi per le richieste http che verranno fatte dall’Extension che si sta creando

Questo è solo uno dei possibili modi per ottenere un token OAuth tramite le funzioni standard di Business Central e molte altre verranno aggiunte coi prossimi aggiornamenti per ottimizzare ancora di più lo scambio di informazioni tramite Api migliorandone notevolmente la possibilità di connessioni tra Business Central e sistemi terzi.

 

Semplifica i processi, prendi decisioni più informate e accelera la crescita con Dynamics 365 Business Central, una soluzione di gestione aziendale completa progettata per le piccole e medie imprese.

Dynamics 365 Developer

 

Business Central implementa un nuovo formidabile tool: le telemetrie.

Le telemetrie e il relativo ambiente “Application Insights” sono degli strumenti, utilissimi e semplici, indispensabili per investigare sulle segnalazioni di rallentamenti delle API e delle web service, sono inoltre strumenti ufficiali e non contestabili tramite i quali è possibile replicare a clienti e ad utenti ogni qual volta questi percepiscano problemi di affidabilità sugli ambienti sia SaaS che IaaS/PaaS.

Tramite l’analisi delle telemetrie è infatti possibile tenere sotto controllo tutti gli errori che si verificano durante le chiamate API, con particolare attenzione ai tipici errori che impattano sull’operatività, ovvero gli errori http 429, 5XX e 404.

La configurazione delle Telemetrie su Business Central è oltretutto una operazione semplice ed è possibile farla in pochi minuti.

In questo articolo verranno descritte le operazioni necessaria per ottenere un report che fornisca le informazioni che tipicamente sono utili per investigare sulle segnalazioni degli utenti, ovvero: numero errore http, tempo di esecuzione della chiamata, righe sql coinvolte nell’operazione ed endpoint http che ha causato l’errore.

How to: Creare un report delle informazioni utili sulle segnalazioni degli utenti

Su ambienti SaaS le telemetrie sono sicuramente presenti, su ambienti OnPrem sono supportate, per le API e le web service, solo dalla versione 16 e successive.

Le informazioni di telemetria sono trasferite in tempo reale da Business Central su Azure e sono quindi accessibili e consultabili sul portale stesso, oltre che manipolabili tramite script PowerShell.

Iniziamo quindi con la prima configurazione. La prima operazione consiste nell’aprire la pagina web di “Azure Portal” e creare un nuovo “Application Insights”. L’operazione è molto semplice e si conclude dopo tre click come in figura, la creazione guidata di “Application Insights” richiede l’immissione di poche informazioni e può essere conclusa lasciando le impostazioni di default.

Il risultato finale di questa operazione è una pagina che mostra due dati che ci serviranno successivamente: la “Istrumentation Key” e la “Connection String”.

Questi due dati andranno copiati sulla configurazione delle Telemetrie su Business Central.

Passiamo quindi a Business Central e vediamo come configurare un ambiente SaaS tramite “Admin Center”. Su ambienti SaaS l’admin center è accessibile aprendo la URL: https://businesscentral.dynamics.com/{your_tenant_id}/admin.

Sul blade Environment si procede quindi con la selezione dell’environment sul quale si desidera procedere con l’attivazione delle telemetrie.

Una volta selezionato l’environment, copiare  il valore della “Application Insights Key” da “Azure Portal” al relativo campo.

Su ambienti OnPremise di Business Central è necessario invece aprire la schermata della console “Administration Center” e nel tab “Generale” copiare il valore di “Application Insights Instrumentation Key” sulla relativa casella di configurazione.

Terminata la configurazione vediamo ora come accedere ai dati di Telemetria.

Gli strumenti a disposizione sono moltissimi, i principali sono il Portale Azure e PowerShell.

Il blade di “Log Analytics” di Azure consente di interrogare i dati con il nuovo linguaggio KQL.

Per filtrare gli eventi che coinvolgono le chiamate API/ODATA è possibile eseguire una query KQL molto semplice:

traces | where operation_Name == ‘Web Services Call’ and message contains  “(Api)”

Questa query darà in uscita un elenco di eventi delle chiamate a WebService eliminando altri tipi di eventi che non sono di interesse.

La finestra che viene mostrata sul blade “Log” di “Application Insights” mostra l’elenco degli eventi e nella parte superiore è possibile digitare ed eseguire la query KQL.

Per ogni riga del singolo evento è possibile espandere e visualizzare i dati dettagliati.

Il risultato HTTP della chiamata è presente all’interno della sottochiave “customDimensions”.

Dato che “customDimensions” è un oggetto di tipo “dynamic type” la query KQL che dobbiamo eseguire per isolare questa informazione è come in figura:

traces 
| extend httpStatusCode = parsejson(tostring(parsejson(tostring(customDimensions.httpStatusCode))))
| extend serverExecutionTime = parsejson(tostring(parsejson(tostring(customDimensions.serverExecutionTime))))
| extend serverExecutionTime = parsejson(tostring(parsejson(tostring(customDimensions.serverExecutionTime))))
| extend totalTime = parsejson(tostring(parsejson(tostring(customDimensions.totalTime))))
| extend category = parsejson(tostring(parsejson(tostring(customDimensions.category))))
| extend sqlRowsRead = parsejson(tostring(parsejson(tostring(customDimensions.sqlRowsRead))))
| extend sqlExecutes = parsejson(tostring(parsejson(tostring(customDimensions.sqlExecutes))))
| extend endpoint = parsejson(tostring(parsejson(tostring(customDimensions.endpoint))))
| where  operation_Name == 'Web Services Call' 
and message  contains "(Api)"
| project httpStatusCode, serverExecutionTime , totalTime , category , sqlRowsRead , sqlExecutes , endpoint , operation_Name

Il risultato finale della query è esattamente il report che ci eravamo prefissati di ottenere, ovvero un elenco di chiamate http ad API e Web Service con i principali dati per verificare eventuali malfunzionamenti o rallentamenti.

I dati di Telemetria sono consultabili anche attraverso PowerShell.

Per utilizzare PowerShell è necessario creare una chiave di consultazione sul Portale Azure.

Per fare questo accedere al blade “API Access” e cliccare su “Create API Key”.

La chiave generata deve essere copiata e salvata, non sarà mai più visualizzabile in futuro, quindi, è importante che venga salvata immediatamente in fase di creazione.

Questa chiave e il valore di “Application ID” ci serviranno successivamente in PowerShell.

Prima di procedere con Power Shell è possibile verificare che le API di Application Insights siano accessibili dall’esterno con applicazioni come Insomia o come PostMan.

Ecco un esempio di chiamata:

GET https://api.applicationinsights.io/v1/apps/{app-id}/query?query=

E la query da passare per avere un elenco di eventi:

?query=traces | where timestamp > ago(1d)

Come è possibile notare in figura l’autenticazione con le API di “Application Insights” avviene impostando l’header http “X-Api-Key” con la chiave ottenuta precedentemente sul portale Azure.

Se la verifica delle chiavi ha avuto esito positivo siamo pronti a manipolare i dati tramite script Power Shell.

Il linguaggio Power Shell permette di estrarre i dati e manipolarli come meglio si ritiene opportuno.

Ecco un esempio di script Power Shell che si connette ad Application Insights ed ottiene i dati e visualizza gli stessi:

$key = "{APP_KEY_FROM_AZURE}"
$appId = "{APP_ID_FROM_AZURE}"

$Query=[uri]::EscapeUriString("?query=traces | where timestamp > ago(1d)")

$filename = "{your_path}/{your_file}.kql"
$queryText = Get-Content $filename
$Query=[uri]::EscapeUriString("?query=$queryText")


$headers = @{ "X-Api-Key" = $key; "Content-Type" = "application/json" }

$response = Invoke-WebRequest -uri  "https://api.applicationinsights.io/v1/apps/$appId/query$Query" -Headers $headers -Method Get

$json = ConvertFrom-Json $response.Content

$headerRow = $null
$headerRow = $json.tables.columns | Select-Object name
$columnsCount = $headerRow.Count
$logData = @()
foreach ($row in $json.tables.rows) {
   $data = new-object PSObject
   for ($i = 0; $i -lt $columnsCount; $i++) {
      $data | add-member -membertype NoteProperty -name $headerRow[$i].name -value         $row[$i]
   }
   $logData += $data
   $data = $null
}

$logData

Lo script esegue un file KQL per filtrare i dati, lo script KQL è esattamente lo stesso che avevamo usato sul portale Azure:

traces 
| extend httpStatusCode = parsejson(tostring(parsejson(tostring(customDimensions.httpStatusCode))))
| extend serverExecutionTime = parsejson(tostring(parsejson(tostring(customDimensions.serverExecutionTime))))
| extend serverExecutionTime = parsejson(tostring(parsejson(tostring(customDimensions.serverExecutionTime))))
| extend totalTime = parsejson(tostring(parsejson(tostring(customDimensions.totalTime))))
| extend category = parsejson(tostring(parsejson(tostring(customDimensions.category))))
| extend sqlRowsRead = parsejson(tostring(parsejson(tostring(customDimensions.sqlRowsRead))))
| extend sqlExecutes = parsejson(tostring(parsejson(tostring(customDimensions.sqlExecutes))))
| extend endpoint = parsejson(tostring(parsejson(tostring(customDimensions.endpoint))))
| where  operation_Name == 'Web Services Call' 
and message  contains "(Api)"
| project httpStatusCode, serverExecutionTime , totalTime , category , sqlRowsRead , sqlExecutes , endpoint , operation_Name
| summarize OpNameCount=count() by tostring(httpStatusCode)

Oltre agli strumenti sopra descritti ne esistono molti altri ancora più potenti, uno di questi è “jupyter notebook”.
È possibile scaricare la guida di jupyter notebook
E gli esempi di query KQL

Inoltre, esiste uno strumento di monitoring che permette di mandare alert automaticamente: Azure Monitor.

Ecco alcuni riferimenti su Telemetrie, Application Insights e linguaggio KQL:

https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/telemetry-enable-application-insights
https://dev.applicationinsights.io/documentation/Using-the-API/Query
https://docs.microsoft.com/it-it/azure/data-explorer/kql-quick-reference

 

Aumenta la produttività e migliora la percezione del tuo brand. Scopri le nostre soluzioni aziendali che ti consentono di gestire l’intera azienda e di offrire risultati migliori

Dynamics 365 Developer

 

how to

Business Central offre di default l’integrazione al Common Data Service, come tutte le sue funzionalità però si può estendere, vediamo in che modo.

Oggigiorno l’integrazione tra sistemi è sempre più importante, app e servizi diversi si integrano sempre più tra loro formando un’unica rete al servizio dell’utente. Business Central si integra con la suite di Office365 tramite il Common Data Service (Cds), una base dati comune a tutti i servizi che vengono utilizzati da Office365, alla base standard di dati esposti sul Cds, è possibile come molte altre funzionalità, aggiungere le proprie personalizzazioni per modellare al meglio l’utilizzo del prodotto alle proprie esigenze.

Ipotizziamo quindi di dover integrare nel common data service una nuova tabella di business central che servirà nell’esecuzione di un Flow di Power Automate basato su Planner in modo che ad ogni nuova task venga generato e assegnato un numero di serie definito in Business Central.

Il primo passo è quindi la creazione di una normalissima tabella:

table 89100 "VAR Projects Planner Teams"
{
    Caption = 'Projects Planner Teams Setup';
    DataClassification = CustomerContent;

    fields
    {
        field(1; "Project Code"; Code[50])
        {
            DataClassification = CustomerContent;
        }
        field(15; "Planner Id"; text[100])
        {
            DataClassification = CustomerContent;
        }
        field(20; "Planner Task No. Series"; Code[50])
        {
            DataClassification = CustomerContent;
            TableRelation = "No. Series";
        }
    }
keys
    {
        key(PK; "Project Code")
        {
            Clustered = true;
        }
    }
}

Seguita dalla sua page per l’inserimento dei dati

page 89100 "VAR Project Planner Teams"
{
    PageType = List;
    ApplicationArea = All;
    UsageCategory = Administration;
    SourceTable = "VAR Projects Planner Teams";

    layout
    {
        area(Content)
        {
            repeater(GroupName)
            {
                field("Project Code"; "Project Code")
                {
                    ApplicationArea = All;

                }
                field("Planner Id"; "Planner Id")
                {
                    ApplicationArea = All;
                }
                field("Planner Task No. Series"; "Planner Task No. Series")
                {
                    ApplicationArea = All;
                }
            }
        }
    }

Fin qua nulla di particolare, passiamo ora alla parte che serve all’esposizione sul Common Data Service.
Come detto inizialmente servono alcune cose:

    • Una pagina esposta sul Cds contenente le info di setup.
    • Una Procedura esposta anch’essa sul cds che stacchi un nuovo numero di serie alla creazione del task planner.

Iniziamo con la creazione della page esposta sul common data service, per fare questo basta creare una pagina di tipo API della tabella creata poco prima:

page 89101 "VAR Project Planner Teams API"
{
    PageType = API;
    Caption = 'VARProjectPlannerTeamsAPI';
    APIPublisher = 'VRP';
    APIVersion = 'v2.0';
    APIGroup = 'PRIMECDSDT';
    EntityName = 'VRPProjectPlannerTeams';
    EntitySetName = 'PPTSetup';
    DelayedInsert = true;
    SourceTable = "VAR Projects Planner Teams";

    layout
    {
        area(Content)
        {
            repeater(GroupName)
            {
                field(ProjectCode; "Project Code")
                {
                    applicationarea = all;
                }
                field(PlannerId; "Planner Id")
                {
                    applicationarea = all;
                }
                field(PlannerTaskNoSeries; "Planner Task No. Series")
                {
                    applicationarea = all;
                }
            }
        }
    }
}

E quindi creiamo anche la Codeunit contenente la funzione riguardante il nr. di serie da staccare.

codeunit 89100 "VAR CDS Connector"
{
    procedure GetNextNoSeries(plannerid: text): Text[50]
    var
        ProjectPlannerTeamsSetup: Record "VAR Projects Planner Teams";
        NoSeriesMgt: Codeunit NoSeriesManagement;
        JsonArray: JsonArray;
        JsonToken: JsonToken;
    begin
        ProjectPlannerTeamsSetup.Reset();
        ProjectPlannerTeamsSetup.SetRange("Planner Id", PlannerId);
        if not ProjectPlannerTeamsSetup.FindFirst() then exit('');

        exit(NoSeriesMgt.GetNextNo(ProjectPlannerTeamsSetup."Planner Task No. Series", WorkDate(), true));
    end;
}

Questa codeunit dovrà essere esposta come servizio web nel webclient di Business Central.

A questo punto l’app di Business Central è pronta e può essere pubblicata.

Si passa ora su PowerAutomate (ma potrebbe valere la stessa cosa anche per PowerApp).

La page e la codeunit sono esposte dal servizio di Business Central ma non sono ancora visibili nel common data service, per poterle vedere è necessario creare un connettore personalizzato.

Un connettore personalizzato si crea accedendo alla sezione dati e selezionando “connettori personalizzati”

Si accede così alla pagina dove è possibile creare o gestire i vari connettori di dati, dove si dovrà creare un nuovo connettore da zero.

A questo punto basterà seguire i passaggi per configurare il connettore.

La configurazione avviene tramite 4 passi più uno di test in cui si definiscono url di collegamento, credenziali che devono essere richieste, le chiamate che il connettore deve fare e le risposte che il connettore riceve.

Nel primo passo si definisce il nome che il connettore avrà e l’host con l’indirizzo che espone le API, nel nostro caso essendo le api esposte da un Business Central Saas inseriremo l’endpoint generale della API di Business Central (api.businesscentral.dynamics.com)

Il secondo passo consiste nella definizione dei criteri di autenticazione al servizio. Quindi definiremo per semplicità l’autenticazione di Base (traduzione italiana per la Basic Authentication), con i due parametri che dovranno essere richiesti dal connettore al momento dell’utilizzo nel flow nel nostro caso inseriremo il parametro di username (nome utente) e password.

N.B. in questa scheda si definiscono solo i parametri e non vanno immessi dati sensibili.

Arriviamo al terzo passo, in questa scheda vengono definiti le azioni e i trigger che il connettore deve eseguire. Le azioni sono le operazioni che il connettore esegue e nel nostro caso sono due chiamate ai webservice di Business Central. I trigger invece sono le operazioni, eseguite da Business Central che possono fare scattare il flow, questi trigger vengono creati con i webhook ma nel nostro caso non ne abbiamo bisogno.

Definiremo quindi due azioni: GetProjectData che recupera le informazioni di setup come l’Id del planner e il nr. di serie da utilizzare e GetPlannerTaskNo che stacca il nr. di serie da assegnare al Task di Planner.

Le azioni si creano cliccando su “Nuova Azione” e compilando le varie schede che vengono proposte, nella prima si definiscono i nomi dell’azione, nella seconda si definisce qual è la richiesta da fare al servizio web, è possibile inserire dei parametri in modo che possano variare a richiesta nel Flow inserendoli tra due parantesi graffe {}.

La creazione delle azioni può avvenire in maniera manuale o in maniera semi automatica cliccando su “Importa da esempio”, in questo caso utilizzando un software esterno come Insomnia è possibile copiare la chiamata al webservice e la risposta che il webservice restituisce. Leggendo i Json in automatico verranno impostati i nomi dei valori che il webservice restituisce.

A questo punto passiamo a creare anche la seconda azione nello stesso modo, una volta ultimato è possibile passare al quarto step e testare il connettore.

Una volta testato è possibile salvarlo e a questo punto il connettore è pronto ad essere utilizzato.

Passiamo quindi alla creazione del flow.

Il nostro connettore lo troviamo tra i connettori personalizzati:

E il suo utilizzo è identico a tutti gli altri connettori standard di Power Automate.

Creiamo quindi il nostro flow:

Una volta salvato e attivato sarà pronto all’utilizzo.

Andiamo nel nostro planner per verificare se funziona, creiamo un task e attendiamo qualche secondo per l’esecuzione del flow.

Dopo qualche secondo il titolo del task prende il nr. di serie staccato da Business Central.

Questo è solo un esempio dei numerosi modi in cui Business Central può essere integrato al meglio all’interno della suite di Office365 al fine di rispecchiare al meglio i flussi aziendali dei clienti.

 

Semplifica i processi, prendi decisioni più informate e accelera la crescita con Dynamics 365 Business Central, una soluzione di gestione aziendale completa progettata per le piccole e medie imprese.

Dynamics 365 Developer

 

Mettere in sicurezza VM e applicazioni è possibile grazie a diversi servizi attivabili sulle Virtual Network di Microsoft Azure: mostriamo le loro possibili combinazioni e integrazioni attraverso una serie di architetture e scenari.

I servizi che possiamo attivare su Azure sono sempre di più e molti di essi sono connessi a Virtual Network o anche esposti pubblicamente su Internet. Sono quindi in aumento le tipologie di workload che necessitano di protezione, e dobbiamo proteggere tutte le relative risorse da attacchi che diventano sempre più sofisticati.

Per rispondere a questa sfida, possiamo però contare su diversi strumenti che Microsoft Azure ci mette a disposizione per difenderci: essendo però questi piuttosto eterogenei, non sempre è immediato orientarsi nella scelta di quelli più adatti.

In questa guida mostriamo diversi scenari che possiamo incontrare nel mondo reale andando a pubblicare applicazioni in cloud e quali servizi Azure o loro combinazioni possiamo adottare di volta in volta per avere una protezione efficace e “mirata” sulle nostre esigenze.

Scenario 1: Nessuna Applicazione Web

Nello scenario che stiamo per descrivere ci basterà implementare solo Azure Firewall. Questo servizio offre tutte le funzionalità di un firewall di ultima generazione, quindi è in grado di effettuare packet filtering sia sugli indirizzi IP che sulle porte dei protocolli TCP/UDP, ma anche di operare a un livello più alto, cioè sugli attributi delle applicazioni HTTPS o SQL.

Descrivendo il flusso: il client che stabilisce una connessione chiamerà l’IP pubblico di Azure Firewall come IP di destinazione. Azure Firewall effettua quindi un Destination Network Address Translation (DNAT) “traducendo” l’IP di destinazione con quello privato del server che esegue l’applicazione e un Source NAT traducendo l’IP sorgente del client con il proprio IP privato. Quando l’applicazione risponde, il flusso viene ripetuto con la logica inversa.

Scenario 2: Solo Applicazioni Web

In questo scenario è sufficiente la sola presenza di Application Gateway, servizio che offre le funzionalità di un web load balancer e che a differenza di Azure Firewall funziona come un vero e proprio Reverse Application Proxy. I bilanciatori tradizionali operano al livello 4 della pila OSI, ovvero di Transport, effettuando il bilanciamento in base a indirizzo IP sorgente e porta. Application Gateway può invece smistare il traffico effettuando decisioni di livello più avanzato, per es. in base agli attributi della richiesta http, in quanto opera a livello OSI 7 (Application)

AG non effettua nessun NAT (Network Address Translation), ma inoltra al server di backend anche l’indirizzo IP originale del client, aggiungendolo nell’http header. Questo può essere utile nel caso di applicazioni web che necessitano di conoscere l’indirizzo sorgente del client per fornire contenuto specifico in base alla geolocalizzazione: per questo motivo in questo scenario abbiamo preferito Application Gateway ad Azure Firewall.

Scenario 3: Mix di Applicazioni Web e Applicazioni non-web

Finora abbiamo visto Azure Firewall e Application Gateway come servizi complementari, ma a seconda del contesto possono anche essere usati assieme per incrementarne l’efficacia.

In questo nuovo scenario la soluzione migliore è l’utilizzo di Application Gateway e Azure Firewall in parallelo: è il caso in cui ad esempio vogliamo pubblicare sia applicazioni web che non-web, dunque può essere utile sfruttare i vantaggi di entrambi i servizi. Quindi Azure Firewall si occuperà di ispezionare il traffico in ingresso per le applicazioni non web, mentre Application Gateway proteggerà quello diretto alle applicazioni web.

Per ottenere lo stesso livello di protezione su entrambi i tipi di applicazioni, sull’Application Gateway oltre alle feature già descritte prima potremmo abilitare un ulteriore servizio: WAF (Web Application Firewall). Si tratta di un device con funzionalità da firewall, specializzato per le applicazioni web: consente di proteggere in maniera centralizzata le applicazioni dai più diffusi tipi di attacchi e vulnerabilità.

Scenario 4: Applicazioni che necessitano di gestione dell’IP sorgente o destinazione

A seconda delle esigenze sulla gestione dell’IP sorgente, possiamo ipotizzare due nuove architetture dove anzichè collocare Application Gateway e Azure Firewall in parallelo, li mettiamo in serie.

Nel primo caso andiamo a gestire quelle applicazioni che necessitano di conoscere l’IP sorgente del client, a prescindere che siano web based o no. Collocheremo quindi come primo servizio che il client contatterà l’Application Gateway con l’aggiunta di WAF, in modo che offra protezione per le web application e possa preservare anche l’IP originale del client, mentre Azure Firewall verrà messo a valle come secondo livello di ispezione e si occuperà di controllo centralizzato e raccolta log.

Nel secondo caso gestiamo quelle situazioni in cui non ci interessa preservare l’IP sorgente ma vogliamo che sia Azure Firewall, con i suoi filtri più avanzati, a bloccare il traffico malevolo prima che raggiunga Application Gateway. In tal caso invertiremo la configurazione mettendo Azure Firewall come primo punto di accesso e Application Gateway dopo di esso.

Scenario 5: Protezione a layer 3+4 con DDoS Protection Standard

Introduciamo ora un altro interessante servizio Azure per la security: il DDoS Protection Standard, creato appositamente per proteggere le risorse dagli attacchi di tipo “Distributed denial of service (DDoS)”. Le risorse Azure, quando sono esposte su internet, possono essere facilmente oggetto di questi attacchi che consistono nel saturare tutte le risorse dell’applicazione fino a renderla indisponibile. Attacchi di questo tipo sfruttano di solito vulnerabilità nei livelli 3 e 4 della pila OSI, e la protezione del servizio DDoS si concentra quindi su queste.

Mentre la rete globale di Azure è protetta di default attraverso la DDoS Protection livello Basic, offerta quindi gratuitamente, il servizio Standard offre una protezione aggiuntiva attraverso delle policies che possono essere adattate alle applicazioni specifiche del cliente, il tutto in maniera intelligente in quanto il servizio è in grado di analizzare il traffico tipico dell’applicazione in modo da profilarlo e potere così più facilmente riconoscere le attività anomale. In più offre una serie di report e alert sugli attacchi rilevati, e la possibilità di essere integrato con Azure Security Center per potenziare ulteriormente il monitoraggio.

Scenario 6: Protezione a layer 3+4+livello Application

Possiamo ipotizzare un’ulteriore combinazione di due servizi di Azure Security appena visti per ottenere un doppio livello di protezione: Azure DDos e WAF. Essendo quest’ultimo basato su Application Gateway come mostrato nei precedenti scenari, otterremmo quindi una protezione completa ai livelli 3, 4 e 7 della pila OSI aggregando le feature di questi servizi.

Come mostrato nello screenshot, questi 2 servizi potrebbero lavorare assieme proteggendo la rete centrale nell’ambito di una particolare architettura di rete denominata “hub and spoke”.

Descrivendo in breve questa topologia standard: distribuiamo delle risorse condivise in una virtual network centrale denominata “hub”, che potranno connettersi a specifiche applicazioni isolate in apposite virtual network grazie ai virtual network peering. In questa architettura quindi, Azure Firewall e Application Gateway insieme a DDoS Protection verranno attivati nella virtual network con ruolo hub, anche se i server di backend che pubblicheranno possono stare nelle reti spoke, ottenendo quindi un ulteriore livello di isolamento e quindi protezione.

Conclusioni

Abbiamo visto una serie di servizi che sono tra loro complementari e possono quindi essere usati da soli o integrati tra loro: gli scenari mostrati sono solo alcuni esempi possibili tra le varie combinazioni che possono essere ipotizzate sulla base delle peculiari esigenze del cliente.

Partendo dai primi due scenari più semplici e dal costo più ridotto in quanto adottiamo un solo tipo di servizio, arriviamo fino a quelli (5 e 6) con la presenza di servizi dal costo più elevato come la DDoS Protection Standard, di conseguenza più adatti per aziende con un volume più elevato di workload da proteggere.

Infine consideriamo che gli strumenti visti presentano potenziali integrazioni con ulteriori servizi. Un esempio può essere Azure Kubernetes, nel caso in cui vogliamo proteggere i workload contenuti negli AKS cluster, oppure Azure Front Door che è un servizio molto simile a Application Gateway ma che anziché essere collocato in una Virtual Network, è disponibile a livello globale e decentralizzato.

 

Fonti e approfondimenti:

Firewall and Application Gateway for virtual networks – Azure Example Scenarios | Microsoft Docs

Azure DDoS Protection Standard Overview | Microsoft Docs

 

Microsoft Azure è una piattaforma di Cloud Computing accessibile tramite un portale online che consente di accedere e gestire i servizi e le risorse cloud forniti da Microsoft

 

Azure Engineer

 

Azure Shared Disk

Azure Shared Disk è una nuova funzionalità che permette di usare lo stesso disco gestito da più Virtual Machines sia con sistema operativo Windows che con sistema operativo Linux.

Il grosso vantaggio è che è possibile migrare tutte quelle applicazioni ancora presenti sulle infrastrutture on premises che dipendono dai servizi cluster e che sono sensibili a livello di latenza, senza compromettere l’alta affidabilità e il fast failover.

Queste includono database in cluster, scale-out File Server, SAP Workload, containers persistenti e applicazioni di Machine Learning.

Fatta questa promessa, andremo ora a configurare Windows Failover Cluster usando gli Azure Shared Disk.

Prerequisiti:

  • Sottoscrizione attiva Azure
  • Un dominio Active Directory già creato in precedenza
  • Proximity Placement Group

La scelta del disco deve ricadere su uno di tipo Premium o Ultra SSD, gli unici subset attualmente disponibili e ogni tipo di disco ha le sue limitazioni che potete trovare sulle docs di Microsoft (Share an Azure managed disk across VMs – Azure Virtual Machines | Microsoft Docs)

Durante la creazione del disco, nelle opzioni avanzate, ci verrà chiesto se si tratta di uno shared disk.

inoltre, dobbiamo indicare anche il numero massimo di shares (in poche parole il numero delle Virtual Machines che condivideranno il disco) questo valore varia in base al tipo di disco: più il disco è prestante più è possibile condividerlo con più Virtual Machines.

Ora possiamo procedere con l’aggiunta del disco a due nodi (precedentemente creati), al momento dell’aggiunta i nodi devono essere spenti.

Una volta aggiunto il disco, possiamo procedere con la semplice formattazione dal disk management di Windows.

In questo momento abbiamo entrambe le VM con il disco condiviso, ma ognuna di esse non condivide nessuna informazione con l’altra.

Procediamo quindi con l’installazione del ruolo Failover Cluster in entrambi i nodi che comporranno il cluster.

Per fare questo lanciamo tramite PowerShell il seguente comando e successivamente procediamo con il riavvio di ogni singolo nodo:

Una volta ripartite le VM, procediamo con la creazione del cluster tramite questo comando PowerShell in cui verrà anche specificato l’indirizzo Ip assegnato al cluster stesso (nel mio caso ho creato un ILB Azure).

Collegandoci al Failover Cluster Manager, possiamo verificare che il cluster sia correttamente configurato, In particolare, nella sezione storage, possiamo vedere che il nostro Shared Disk precedentemente creato:

Per rendere il cluster più stabile, possiamo procedere con la configurazione del Quorum, configurandolo in uno storage account:

Quando richiesto, andremo ad impostare il nome dello storage account e la Key di autenticazione che possiamo trovare nei settings dello storage account.

Il cluster è ora online e disponibile per installazioni quali SQL Server Failover Cluster necessarie per installazioni di applicazioni legate al mondo delle SAN on premise che hanno necessità di bassissima latenza pur conservando tutti i dogmi dell’alta affidabilità.

 

Fonti e approfondimenti:

Share an Azure managed disk across VMs – Azure Virtual Machines | Microsoft DocsEnable

shared disks for Azure managed disks – Azure Virtual Machines | Microsoft Docs

 

Microsoft Azure è una piattaforma di Cloud Computing accessibile tramite un portale online che consente di accedere e gestire i servizi e le risorse cloud forniti da Microsoft

 

Azure Engineer

 

How to

Trello, uno strumento online per la gestione dei progetti e dei task personali.

Una delle richieste sempre più comuni è quella di integrare Business Central con altri software e portali. Oggi riportiamo l’esempio di un integrazione con il sito web di Trello.

Trello (https://trello.com/it) è uno strumento di base gratuito, formato da tre elementi chiave: la board, le list e le card.

  • Le board (possono essere private o pubbliche) sono il contenitore principale di tutti i task.
  • Le card, che contengono i vari task, sono organizzati all’interno di liste e rappresentano l’unità base.

L’obiettivo che ci siamo dati all’inizio di questo sviluppo è provare ad integrare Business Central con una bacheca creata su Trello per inviare verso il loro sito delle anagrafiche clienti (per esempio dei soggetti da contattare per campagne promozionali) e fornitori.

Per prima cosa abbiamo creato su Trello una bacheca con due list (Clienti\ Fornitori) seguendo la loro guida: https://trello.com/it/guide/trello-101.html

Sempre da Trello abbiamo poi preso alcune informazioni che ci serviranno per l’integrazione: la chiave API ed il Token: https://trello.com/app-key

Trello

A questo punto abbiamo consultato la documentazione sulle API di Trello che potete trovare a questo link: https://developer.atlassian.com/cloud/trello/rest/ ed abbiamo estratto da l’ultima informazione fondamentale: l’id della nostra board e list.

Per fare questo abbiamo creato una card di test ed abbiamo esportato il Json.

Le informazioni sono contenute nell’idBoard e l’idList.

A questo punto abbiamo tutte le informazioni per fare l’integrazione.

Ci spostiamo in Visual Studio Code, creiamo una page extension della customer card e un action che ci permette di inviare il cliente nella nostra bacheca su Trello

action(SENDTRELLO)
            {
                Caption = 'Send Customer To Trello';
               Visible = true;
               Image= Sendto;
               ApplicationArea = All;
                
                trigger OnAction()
                var
                    client: HttpClient;
                    Path: Text;
                    RequestContent: HttpContent;
                    ResponseMessage: HttpResponseMessage;
                    StatusCode: text;
                    AuthHeaderValue: HttpHeaders;
                    Content: HttpContent;
                    Result: Text;
                begin
  Path :='https://api.trello.com/1/cards?key=20fb8653332….&token=a1fca508d75689ba5f…&name=' + rec."No." + ' - ' + rec.Name + '&idList=5fe21834211dab1e01c005a2';
                    Client.SetBaseAddress(path);
                    Client.DefaultRequestHeaders.Add('User-Agent', 'Dynamics 365');

                    if Client.Post(path, RequestContent, ResponseMessage) then begin
                        if ResponseMessage.IsSuccessStatusCode then begin
                            StatusCode := '00';
                            AuthHeaderValue := ResponseMessage.Headers;
                            Content := ResponseMessage.Content;
                            Content.ReadAs(Result);
                        end else begin
                            AuthHeaderValue := ResponseMessage.Headers;
                            Content := ResponseMessage.Content;
                            Content.ReadAs(Result);
                            StatusCode := Format(ResponseMessage.HttpStatusCode);
                            Error(format(ResponseMessage.HttpStatusCode) + Result)
                        end;
                    end;
                end;
}

Pubblichiamo la page ext e ci troviamo la nostra azione sulla customer card

Clicchiamo sull’azione e sulla nostra bacheca ecco arrivare il cliente

Ripetendo la cosa per i fornitori (cambiando solo id della lista) raggiungiamo il nostro obiettivo.

Questo ovviamente è solo un esempio e un primo passo dell’integrazione e delle possibilità che offre Trello e delle potenzialità che Business Central ha per integrarsi con numerosi software disponibili su web.

 

Semplifica i processi, prendi decisioni più informate e accelera la crescita con Dynamics 365 Business Central, una soluzione di gestione aziendale completa progettata per le piccole e medie imprese.

Dynamics 365 Developer

 

Business Central

Business Central 2020 Wave2: Nuove funzionalità per ottimizzare il codice.

Il rilascio di Business Central 2020 Wave2 ad inizio ottobre ha portato con sé numerose migliorie “sotto al cofano”, tra queste alcune funzionalità che permettono allo sviluppatore di ottimizzare ulteriormente il proprio codice, riducendo così i tempi di esecuzione delle varie procedure.

Le nuove funzionalità introdotte sono:

  • Caricamento di record parziali
  • Tabelle temporanee
  • Proprietà QueryCategory.

La prima funzionalità è la possibilità di caricare un record parzialmente, ovvero selezionare preventivamente i soli campi che serviranno nella procedura seguente. Questo fa sì che il sistema vada a leggere solo pochi campi rispetto a tutti quelli presenti nella tabella, le differenze utilizzando questa funzione si noteranno soprattutto quando si caricano record con numerosi campi ad esempio caricando record riferiti a tabelle come la Sales Header.

Il caricamento parziale dei record si attiva tramite il metodo SetLoadFields indicando quali campi del record caricare.

La sintassi è la seguente:

local procedure tprocedure()
var
        SalesHeader: Record "Sales Header";
begin
        SalesHeader.SetLoadFields("VAT Registration No.");
        SalesHeader.FindFirst();
end;

In questo modo verrà caricato nel record solo il campo relativo alla partita iva senza caricare tutti gli altri campi presenti nella tabella.

Questo tipo di chiamata non deve essere utilizzata nel caso si effettuino inserimenti, cancellazioni o modifiche al record.

Un’altra utile funzionalità, richiesta da molti sono le tabelle temporanee, la gestione di record temporanei esiste da sempre in Business Central ma mancava la possibilità di dichiarare una tabella temporanea già nella struttura tramite l’abilitazione della proprietà TableType.

La proprietà va impostata in questo modo nella dichiarazione della tabella:

table 80074 MyTable
{
    DataClassification = ToBeClassified;
    TableType = Temporary;

Il grosso vantaggio generato da questa proprietà è dato dal fatto che lo schema di una tabella impostata in questo modo non viene mai sincronizzato con il database questo fa sì che sarà possibile eliminare campi e fare modifiche che di norma richiederebbero una forzatura della sincronizzazione dello schema della tabella e quindi proibite soprattutto nel SaaS.

L’ultima novità non è una funzionalità riguardante l’ottimizzazione del codice, riguarda invece una funzionalità che aiuta lo sviluppatore ad implementare le funzionalità richieste dall’utente.

Questa funzionalità è una nuova proprietà presente negli oggetti di tipo Query si chiama QueryCategory e permette l’inserimento al suo interno dei nomi delle pagine dove dovrà essere richiamata.

La proprietà va richiamata in questo modo:

query 93200 "Top 20 Customer for Sales Test"
{
    Caption = 'Top 20 Customer Sales Test';
    OrderBy = Descending(Sum_Sales_LCY);
    TopNumberOfRows = 20;
    QueryCategory = 'Customer List';

    elements
    {
        dataitem(Cust_Ledger_Entry; "Cust. Ledger Entry")
        {
            filter(Posting_Date; "Posting Date")
            {
            }
            column(Customer_No; "Customer No.")
            {
            }
            column(Sum_Sales_LCY; "Sales (LCY)")
            {
                Method = Sum;
            }
        }
    }
}

dichiarando nella Query le pagine dove dovrà essere richiamata, la query apparirà in automatico nella pagina indicata senza dover aggiungere altro codice nella pagina stessa:

questa è una piccola funzionalità che permette una migliore integrazione delle modifiche con lo standard offerto da Business Central allineando l’user experience a quella voluta da Microsoft.

Queste nuove funzionalità rilasciate da Microsoft per gli sviluppatori non sono fondamentali ma devono essere sempre considerate come opportunità da uno sviluppatore per rendere il proprio codice più veloce ed efficiente migliorando notevolmente l’user experience dell’utente finale.

Semplifica i processi, prendi decisioni più informate e accelera la crescita con Dynamics 365 Business Central, una soluzione di gestione aziendale completa progettata per le piccole e medie imprese.

 

Dynamics 365 Developer

 

Microsoft Dynamics 365 Business Central: i servizi di geolocalizzazione

Come implementare una mappa all’interno di una pagina, utilizzando le funzionalità standard di Business Central

Business Central può offrire numerosi spunti di personalizzazione già all’interno della Base Application, l’app basilare fornita da Microsoft che contiene tutte le funzionalità standard.
Un esempio può essere dato da una funzionalità che potrebbe passare inosservata tra le varie altre  ovvero la gestione dell’integrazione con i servizi di geolocalizzazione.

All’interno dell’anagrafica clienti, o fornitori (e anche in altri punti come ad esempio le risorse), dopo i vari dati dell’indirizzo nel gruppo “Indirizzo e contatto” è presente il tasto “Mostra su mappa

Cliccando sopra verranno richieste alcune informazioni su cosa si vuole vedere e procedendo si arriva all’apertura di una nuova scheda del browser con le indicazioni del percorso, oppure semplicemente con l’indirizzo dell’anagrafica visualizzato sulla mappa:

Il servizio utilizzato è quello di Bing, ma è possibile inserire il servizio di mappe preferito in quanto tutto è gestito tramite dal setup chiamato “Mappe in linea

A cui si accede alle varie pagine di setup dove è possibile inserire oltre a Bing altri setup di altri servizi.

Il funzionamento di tutto questo è molto semplice e Business Central utilizza la codeunit chiamata “Online map management” che contiene tutte le funzioni necessarie a rielaborare i setup immessi nella page indicata prima al fine di creare un indirizzo lanciabile tramite brower.

Grazie alla flessibilità data dagli eventi esposti dalla codeunit e il modo in cui sono state create le codeunit è possibile posizionare la funzionalità delle mappe su qualunque pagina di business central con pochi passaggi.

How to: i passaggi per l’implementazione

Il primo passaggio è la sottoscrizione di un evento al fine di “attivare” la funzionalità, per farlo basterà sottoscrivere questo evento impostando la variabile IsValid a true.

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Online Map Management", 'OnAfterValidAddress', '', false, false)]
local procedure OnlineMapManagementOnAfterValidAddress(TableID: Integer; var IsValid: Boolean)
begin
end;

Il secondo passaggio è un secondo evento da sottoscrivere, questa volta per impostare l’indirizzo di “destinazione” o semplicemente l’indirizzo che verrà visualizzato nella mappa:

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Online Map Management", 'OnAfterGetAddress', '', false, false)]
local procedure OnlineMapManagementOnAfterGetAddress(TableID: Integer; RecPosition: Text; var Parameters: array[12] of Text[100]; var RecordRef: RecordRef)
Begin
end;

Impostando l’array Parameters con le informazioni relative all’indirizzo desiderato:

Parameters[1] := Addr;
Parameters[2] := City;
Parameters[3] := County;
Parameters[4] := PostCode;
Parameters[5] := CountryCode;

A questo punto il tutto è già impostato per funzionare, basterà creare una action sulla page desiderata in modo che lanci la funzione MakeSelection della codeunit Online Map Managemente e il gioco è fatto.

OnlineMapManagement.ProcessMap(DocumentRecRef.Number, DocumentRecRef.GetPosition())

La funzione riceve in ingresso dei recordref e gli eventi esposti espongono la tabella che ha generato l’evento in questo modo è possibile creare un’unica funzione in grado di accettare qualsiasi tabella e quindi indirizzo all’interno del database senza dover duplicare ulteriormente il codice.

In questo modo è stato replicato esattamente quello che lo standard fa sulle pagine in cui espone la possibilità di visualizzare la mappa, ma è possibile andare oltre con pochi passaggi e tramite l’utilizzo di un servizio diverso da Bing ovvero HereWeGo.

L’indirizzo infatti è possibile visualizzarlo direttamente all’interno della pagina di Business Central sfruttando in modo differente la stessa struttura che viene utilizzata per l’esposizione dei report PowerBi.

How to: aggiungere le funzionalità

Prima di andare a creare la pagina bisogna aggiungere un paio di funzionalità a quanto è stato creato in precedenza.

La prima è la funzione di restituzione della url che verrà mostrata all’interno della pagina sfruttando direttamente la funzione presente all’interno della codeunit di gestione delle mappe. La url però non è direttamente visibile in quanto l’apertura della scheda del browser è all’interno della funzione stessa di creazione della url. Bisogna recuperarla tramite un piccolo escamotage dichiarando la codeunit in cui vengono sottoscritti gli eventi come “singleinstance” e dichiarando una variabile globale “weburl” e una seconda variabile booleana “isPagePart” (il cui motivo verrà spiegato poco più avanti).

A questo punto si crea la funzione che restituirà la url alla pagina:


    procedure GetMapUrl(Document: Variant): Text
    var
        OnlineMapSetup: Record "Online Map Setup";
        OnlineMapManagement: Codeunit "Online Map Management";
        Err001: Label 'Please setup a valid map setup';
    begin
        isPagePart := true;
        DatatypeManagement.GetRecordRef(Document, DocumentRecRef);
        if OnlineMapSetup.FindFirst() then
            OnlineMapManagement.ProcessMap(DocumentRecRef.Number, DocumentRecRef.GetPosition())
        else
            Error(Err001);

        Exit(WebUrl);
    end;

Come si può notare in questa funzione non viene assegnata da nessuna parte la variabile WebUrl, questo perché in realtà la url viene composta dalla procedura ProcessMap, che non avendo nessun valore di ritorno espone un evento che si andrà a sottoscrivere:

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Online Map Management", 'OnAfterProcessWebMap', '', false, false)]
    local procedure MapManagementOnAfterProcessWebMap(url: Text[1024]; var IsHandled: Boolean)
    begin
        if not isPagePart then exit;
        WebUrl := url;
        IsHandled := true;
        isPagePart := false;
    end;

Da questo evento possiamo ricavare la url assegnandola alla variabile WebUrl e impostando la variabile isHandled a true evitiamo l’apertura della scheda del browser. Come si può notare viene controllata la variabile isPagePart (impostata a true nella funzione) questo serve a mantenere inalterata la funzionalità del tasto standard.
A questo punto si può creare la page part, riferita alla sourcetable della pagina in cui verrà visualizzata la mappa.
Al suo interno non si andrà a dichiarare alcun campo ma solo un usercontrol fatto in questo modo:

layout
    {
        area(Content)
        {
            group(Map)
            {
                ShowCaption = false;
                usercontrol(WebReportViewer; "Microsoft.Dynamics.Nav.Client.WebPageViewer")
                {
                    ApplicationArea = All;
                    trigger ControlAddInReady(callbackUrl: Text)
                    begin
                        CurrPage.WebReportViewer.Navigate(Url);
                    end;
                }
            }
        }
    }

Oltre allo usercontrol nel trigger “onaftergetrecord” andremo a richiamare la funzione creata prima:

trigger OnAfterGetRecord()
    var
        MapsCu: Codeunit "Maps Cu";
    begin
        Clear(MapsCu);
        Url := MapsCu.GetMapUrl(Rec);
    end;

A questo punto non resta che pubblicare il tutto ed ecco il risultato:

Con questi passaggi è possibile integrare la funzionalità di utilizzo della geolocalizzazione all’interno di una propria app senza dover scrivere del codice di gestione a riguardo e allo stesso tempo potrebbe fungere da base per ulteriori sviluppi più complessi tramite l’utilizzo delle API forniti dai vari gestori di servizi di geolocalizzazione, la flessibilità del setup infatti permette di utilizzare oltre a Bing, anche Google Maps, Openstreet Maps e non ultimo HereWeGo.

 

Semplifica i processi, prendi decisioni più informate e accelera la crescita con Dynamics 365 Business Central, una soluzione di gestione aziendale completa progettata per le piccole e medie imprese.

 

Dynamics 365 Developer