Distribuzione a livello di codice dei prodotti Marketplace

Questo articolo illustra come usare l'interfaccia della riga di comando di Azure, Azure PowerShell e Terraform per distribuire le risorse dei prodotti Marketplace in Azure.

Prerequisiti

È necessario installare Azure PowerShell e connettersi ad Azure:

I comandi di distribuzione sono stati modificati nell'interfaccia della riga di comando di Azure versione 2.2.0. Gli esempi in questo articolo richiedono l'interfaccia della riga di comando di Azure versione 2.20.0 o successiva.

Per eseguire questo esempio, installare l'ultima versione dell'interfaccia della riga di comando di Azure. Per iniziare, eseguire az sign-in per creare una connessione con Azure.

Come trovare gli identificatori di prodotto del Marketplace per editore, offerta e piano

Per distribuire a livello di codice il prodotto Marketplace, è prima necessario ottenere gli identificatori univoci di un prodotto Marketplace.

Per trovare gli identificatori univoci:

  1. Aprire il portale di Azure e passare all'esperienza marketplace.
  2. Cercare il prodotto Marketplace da distribuire
  3. Aprire la pagina dei dettagli del prodotto selezionando il nome del prodotto.
  4. Passare alla scheda Informazioni sull'utilizzo e supporto . In Informazioni sull'utilizzo vengono visualizzati l'ID editore, l'ID prodotto e l'ID piano.

Screenshot della pagina ID prodotto.

Nota

In alcune API l'ID prodotto è noto anche come ID offerta e ID piano è noto anche come ID SKU.

Macchina virtuale da Azure Marketplace

Per distribuire macchine virtuali di terze parti da Azure Marketplace, è necessario prima accettare il Contratto di licenza con l'utente finale per l'immagine di macchina virtuale in fase di distribuzione. Dopo aver accettato il contratto di licenza una volta in una sottoscrizione di Azure, è necessario poter distribuire nuovamente la stessa offerta di macchina virtuale senza dover accettare di nuovo le condizioni. Se si distribuisce la macchina virtuale da portale di Azure, vengono accettate le condizioni. Tuttavia, quando si esegue la distribuzione a livello di codice, è necessario accettare i termini usando az vm image terms accept --publisher X --offer Y --plan Z o usando ARM.

Se i termini non sono ancora accettati, viene visualizzato l'errore seguente:

Code : MarketplacePurchaseEligibilityFailed
Message: Marketplace purchase eligibility check returned errors. See inner errors for details
Details: Offer with PublisherId: '<PublisherId>', OfferId: '<OfferId>' cannot be purchased due to validation errors. For more information see details. Correlation Id: 'aaaa0000-bb11-2222-33cc-444444dddddd' You have not accepted the legal terms on this subscription: 'aaaa0000-bb11-2222-33cc-444444dddddd' for this plan. Before the subscription can be used, you need to accept the legal terms of the image. To read and accept legal terms, use the Azure CLI commands described at https://go.microsoft.com/fwlink/?linkid=2110637 or the PowerShell commands available at https://go.microsoft.com/fwlink/?linkid=862451. Alternatively, deploying via the Azure portal provides a UI experience for reading and accepting the legal terms.

Distribuire una macchina virtuale da Azure Marketplace usando l'interfaccia della riga di comando di Azure

Dopo aver accettato le condizioni, è possibile distribuire la macchina virtuale usando i metodi regolari, ad esempio il modello ARM/Bicep, l'interfaccia della riga di comando di Azure, Terraform e così via.

Per altre informazioni sulla ricerca di immagini di macchine virtuali, accettazione delle condizioni e distribuzione della macchina virtuale tramite l'interfaccia della riga di comando, vedere Trovare e usare le informazioni sul piano di acquisto del Marketplace tramite l'interfaccia della riga di comando.

Distribuire una macchina virtuale da Azure Marketplace usando Terraform

Istruzioni su come distribuire Macchine virtuali usando Terraform per macchine virtuali Windows o vm Linux.

Per usare Terraform per distribuire le macchine virtuali del Marketplace, è necessario eseguire le azioni seguenti:

  1. Accettare le condizioni legali del prodotto della macchina virtuale usando azurerm_marketplace_agreement

  2. Specificare il plan blocco nel provider di azurerm_virtual_machine

Nota

Se il blocco di piano non viene specificato, la distribuzione avrà esito negativo con l'errore seguente:

Code: VMMarketplaceInvalidInput Message: Creating a virtual machine from Marketplace image or a custom image sourced from a Marketplace image requires Plan information in the request. VM: '/subscriptions/<Subscription ID>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM

Nota

azurerm_marketplace_agreement viene considerato come una risorsa Terraform, pertanto, la prima volta che si crea un prodotto macchina virtuale del Marketplace specifico, viene creata una risorsa univoca per rappresentare il fatto che sono state accettate le condizioni legali. Tuttavia, la volta successiva che si tenta di distribuire un'altra macchina virtuale (con lo stesso ID editore e ID offerta) nella stessa sottoscrizione di Azure, verrà visualizzato un errore:

A resource with the ID "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e /providers/Microsoft.MarketplaceOrdering/agreements/<Publisher ID>/offers/<Product ID>/plans/<Plan ID>" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_marketplace_agreement" for more information

È necessario eseguire Terraform state list per verificare se si dispone di azurerm_marketplace_agreement stato della risorsa e, se non è necessario importare lo stato della risorsa nello stato terraform.

terraform import azurerm_marketplace_agreement.<TerraformResourceName> /subscriptions/<AzureSubscriptionId>/providers/Microsoft.MarketplaceOrdering/agreements/<Publisher ID>/offers/<Product ID>/plans/<Plan ID>

Offerta SaaS da Azure Marketplace

Le offerte SaaS vengono in genere distribuite dai clienti tramite il portale di Azure. Dopo aver distribuito l'offerta SaaS usando portale di Azure, il cliente usa il pulsante "Configura account ora" per visitare la pagina di destinazione dell'ISV SaaS e completare la configurazione dell'offerta SaaS. Dopo aver configurato l'offerta, l'ISV SaaS lo attiva usando l'API di evasione SaaS.

Quando si distribuisce un'offerta SaaS tramite il portale di Azure, viene creato un modello di Resource Manager e vengono assegnati valori di parametro specifici per la distribuzione. Uno dei parametri è termId, che identifica il termine di sottoscrizione per l'offerta. Il valore termId non è statico, ma dipende dalla configurazione dell'offerta e dal tempo di distribuzione. Pertanto, non è possibile usare un valore fisso per termId nel modello di Resource Manager. È invece necessario individuare il valore termId corrente seguendo questa procedura:

  1. Distribuire l'offerta manualmente tramite il portale di Azure.
  2. Passare al gruppo di risorse in cui viene distribuita l'offerta.
  3. Selezionare il nome della distribuzione nella sezione Distribuzioni.
  4. Visualizzare i parametri di input e copiare il valore di termId.

Se una determinata offerta SaaS non è mai stata distribuita nella sottoscrizione di Azure, la distribuzione a livello di codice ha esito negativo con un errore simile al seguente:

code: DeploymentFailed

message: At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage

Details: Failed to process eligibility check with error Purchase has failed due to signature verification on Marketplace legal agreement. Please retry. If error persists use different Azure subscription, or contact support with correlation-id 'aaaa0000-bb11-2222-33cc-444444dddddd' and this error message

Distribuire un'offerta SaaS usando il modello di Resource Manager e l'interfaccia della riga di comando di Azure

Vedere il modello di esempio di Resource Manager.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "name": {
            "type": "string"
        },
        "planId": {
            "type": "string"
        },
        "offerId": {
            "type": "string"
        },
        "publisherId": {
            "type": "string"
        },
        "quantity": {
            "type": "int"
        },
        "termId": {
            "type": "string"
        },
        "azureSubscriptionId": {
            "type": "string"
        },
        "publisherTestEnvironment": {
            "type": "string",
            "defaultValue": ""
        },
        "autoRenew": {
            "type": "bool"
        }
    },
    "resources": [
        {
            "type": "Microsoft.SaaS/resources",
            "apiVersion": "2018-03-01-beta",
            "name": "[parameters('name')]",
            "location": "global",
            "properties": {
                "saasResourceName": "[parameters('name')]",
                "publisherId": "[parameters('publisherId')]",
                "SKUId": "[parameters('planId')]",
                "offerId": "[parameters('offerId')]",
                "quantity": "[parameters('quantity')]",
                "termId": "[parameters('termId')]",
                "autoRenew": "[parameters('autoRenew')]",
                "paymentChannelType": "SubscriptionDelegated",
                "paymentChannelMetadata": {
                    "AzureSubscriptionId": "[parameters('azureSubscriptionId')]"
                },
                "publisherTestEnvironment": "[parameters('publisherTestEnvironment')]",
                "storeFront": "AzurePortal"
            }
        }
    ]
}

  • Salvare il file precedente come SaaS-ARM.json
  • Eseguire i comandi seguenti:
az group create --resource-group <ResourceGroupName> --location <Location>

az deployment group create --resource-group <Resource Group Name> --template-file ./SaaS-ARM.json --parameters name=<SaaS Resource Name> publisherId=<Publisher ID> offerId=<Product ID> planId=<Plan ID> termId=<termId> quantity=1 azureSubscriptionId=11111111-1111-1111-1111-11111111 autoRenew=true

Dopo il provisioning della risorsa offerta SaaS, è possibile richiamare l'API ARM seguente per visualizzarne le proprietà:

az rest --method get --uri /subscriptions/<AzureSubscriptionId>/resourceGroups/<ResourceGroupName>/providers/Microsoft.SaaS/resources/<SaaS Resource Name>?api-version=2018-03-01-beta -o json

È ora possibile effettuare una POST chiamata per ottenere il token del Marketplace e l'URL della pagina di destinazione. Questo URL può essere usato per esplorare la pagina di destinazione dell'ISV SaaS per completare la configurazione e l'attivazione dell'offerta SaaS.

az rest --method post --uri /subscriptions/<AzureSubscriptionId>/resourceGroups/<ResourceGroupName> /providers/Microsoft.SaaS/resources/<SaaS Resource Name>/listAccessToken?api-version=2018-03-01-beta -o json

Altre informazioni sono disponibili qui: specifica del provider di risorse Microsoft.SaaS.

Distribuire un'offerta SaaS da Azure Marketplace usando Terraform

Esaminare la sezione precedente che descrive come distribuire un'offerta SaaS usando ARM poiché la distribuzione di Terraform userebbe lo stesso uso del modello di Resource Manager.

app Azure lication da Azure Marketplace

app Azure tipo di prodotto è un'offerta unica che consente all'editore di creare un modello di Resource Manager che include un set di risorse di Azure e prodotti Marketplace in bundle e configurati per fornire applicazioni multi-risorse completamente funzionali, app Azure lication ha tre tipi di piano:

  • Modello di soluzione : offerta gratuita, distribuzione di modelli di Resource Manager
  • Applicazioni gestite : offerta gratuita o a pagamento, crea un tipo di risorsa Microsoft.Solutions/applications

portale di Azure genera un modello arm per la distribuzione app Azure lication (applicazione gestita). Questo modello di Resource Manager crea una risorsa di tipo Microsoft.Solutions/applications che punta a un piano specifico e passa i parametri specifici dell'applicazione dai campi dell'interfaccia utente compilati dal cliente in portale di Azure.

Accettare le condizioni dell'app gestita di Azure

Analogamente all'offerta macchina virtuale, per distribuire il app Azure lication (applicazione gestita) a livello di codice usando il modello di Resource Manager in una sottoscrizione di Azure, la sottoscrizione deve accettare le condizioni per il piano dell'app gestita di Azure. Quando vengono distribuite tramite il portale di Azure, le condizioni di accettazione vengono eseguite in modo implicito e successivo distribuzioni a livello di codice dello stesso piano nella stessa sottoscrizione di Azure funzionano senza problemi.

È anche possibile accettare le condizioni di un'offerta di app Azure lication (applicazione gestita) usando la stessa az vm image terms accept procedura descritta in precedenza nella sezione vm.

Se il prodotto app Azure lication (applicazione gestita) è un prodotto a pagamento (ad esempio, usa la fatturazione mensile o a consumo), la sottoscrizione di Azure usata per distribuirla deve essere associata a un metodo di pagamento valido(ad esempio, non può essere una sottoscrizione gratuita o sponsorizzata).

Distribuire app Azure lication (applicazione gestita) usando il modello di Resource Manager e l'interfaccia della riga di comando di Azure

Di seguito è riportato un esempio di modello di Resource Manager per la distribuzione di un'applicazione gestita.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "allowedValues": [
                "westus2",
                "westeurope",
                "eastus",
                "northeurope",
                "centralus",
                "eastus2",
                "francecentral",
                "uksouth"
            ]
        },
        "applicationResourceName": {
            "type": "string"
        },
        "managedResourceGroupId": {
            "type": "string",
            "defaultValue": ""
        },
        "managedIdentity": {
            "type": "object",
            "defaultValue": {}
        },
        "initialConsulVersion": {
            "type": "string",
            "defaultValue": "v1.11.2"
        },
        "storageAccountName": {
            "type": "string",
            "defaultValue": "[concat('storage', uniqueString(resourceGroup().id, deployment().name))]"
        },
        "blobContainerName": {
            "type": "string",
            "defaultValue": "[concat('blob', uniqueString(resourceGroup().id, deployment().name))]"
        },
        "identityName": {
            "type": "string",
            "defaultValue": "[concat(parameters('clusterName'), '-identity')]"
        },
        "clusterMode": {
            "type": "string",
            "defaultValue": "PRODUCTION",
            "allowedValues": [
                "PRODUCTION",
                "DEVELOPMENT"
            ]
        },
        "clusterName": {
            "type": "string",
            "defaultValue": "cluster"
        },
        "consulDataCenter": {
            "type": "string",
            "defaultValue": "dc1"
        },
        "numServers": {
            "type": "string",
            "defaultValue": "3"
        },
        "numServersDevelopment": {
            "type": "string",
            "defaultValue": "1"
        },
        "automaticUpgrades": {
            "type": "string",
            "defaultValue": "disabled"
        },
        "consulConnect": {
            "type": "string",
            "defaultValue": "enabled"
        },
        "externalEndpoint": {
            "type": "string",
            "defaultValue": "enabled"
        },
        "snapshotInterval": {
            "type": "string",
            "defaultValue": "1d"
        },
        "snapshotRetention": {
            "type": "string",
            "defaultValue": "1m"
        },
        "consulVnetCidr": {
            "type": "string",
            "defaultValue": "172.25.16.0/24"
        },
        "providerBaseURL": {
            "defaultValue": "https://ama-api.hashicorp.cloud/consulama/2021-04-23",
            "type": "String",
            "metadata": {
                "description": "The URI of the custom provider API"
            }
        },
        "email": {
            "type": "string"
        },
        "federationToken": {
            "type": "string",
            "defaultValue": ""
        },
        "sourceChannel": {
            "type": "string",
            "defaultValue": "azure-portal"
        },
        "auditLoggingEnabled": {
            "type": "string",
            "defaultValue": "disabled",
            "allowedValues": [
                "enabled",
                "disabled"
            ]
        },
        "auditLogStorageContainerURL": {
            "type": "string",
            "defaultValue": ""
        }
    },
    "variables": {
    },
    "resources": [
        {
            "type": "Microsoft.Solutions/applications",
            "apiVersion": "2017-09-01",
            "name": "[parameters('applicationResourceName')]",
            "location": "[parameters('location')]",
            "kind": "MarketPlace",
            "identity": "[if(empty(parameters('managedIdentity')),json('null'),parameters('managedIdentity'))]",
            "plan": {
                "name": "<Plan ID>",
                "product": "<Product ID>",
                "publisher": "<Publisher ID>",
                "version": "<Version>"
            },
            "properties": {
                "managedResourceGroupId": "[parameters('managedResourceGroupId')]",
                "parameters": {
                    "initialConsulVersion": {
                        "value": "[parameters('initialConsulVersion')]"
                    },
                    "storageAccountName": {
                        "value": "[parameters('storageAccountName')]"
                    },
                    "blobContainerName": {
                        "value": "[parameters('blobContainerName')]"
                    },
                    "identityName": {
                        "value": "[parameters('identityName')]"
                    },
                    "clusterMode": {
                        "value": "[parameters('clusterMode')]"
                    },
                    "clusterName": {
                        "value": "[parameters('clusterName')]"
                    },
                    "consulDataCenter": {
                        "value": "[parameters('consulDataCenter')]"
                    },
                    "numServers": {
                        "value": "[parameters('numServers')]"
                    },
                    "numServersDevelopment": {
                        "value": "[parameters('numServersDevelopment')]"
                    },
                    "automaticUpgrades": {
                        "value": "[parameters('automaticUpgrades')]"
                    },
                    "consulConnect": {
                        "value": "[parameters('consulConnect')]"
                    },
                    "externalEndpoint": {
                        "value": "[parameters('externalEndpoint')]"
                    },
                    "snapshotInterval": {
                        "value": "[parameters('snapshotInterval')]"
                    },
                    "snapshotRetention": {
                        "value": "[parameters('snapshotRetention')]"
                    },
                    "consulVnetCidr": {
                        "value": "[parameters('consulVnetCidr')]"
                    },
                    "location": {
                        "value": "[parameters('location')]"
                    },
                    "providerBaseURL": {
                        "value": "[parameters('providerBaseURL')]"
                    },
                    "email": {
                        "value": "[parameters('email')]"
                    },
                    "federationToken": {
                        "value": "[parameters('federationToken')]"
                    },
                    "sourceChannel": {
                        "value": "[parameters('sourceChannel')]"
                    },
                    "auditLoggingEnabled": {
                        "value": "[parameters('auditLoggingEnabled')]"
                    },
                    "auditLogStorageContainerURL": {
                        "value": "[parameters('auditLogStorageContainerURL')]"
                    }
                },
                "jitAccessPolicy": null
            }
        }
    ]
}

Eseguire quindi i comandi seguenti:

az group create --resource-group <Resource Group Name> --location <location>

az deployment group create --resource-group avmanagedapp100 --template-file <ARM Template JSON file> --parameters location=<location> applicationResourceName=<Resource Group Name> managedResourceGroupId=/subscriptions/<Subscription ID>/resourceGroups/<Resource Group Name>  email=<email address>

Distribuire un'app gestita di Azure da Azure Marketplace usando Terraform

Esaminare la sezione precedente che descrive come distribuire un'offerta di app gestita di Azure usando ARM poiché la distribuzione di Terraform usa lo stesso modello di Resource Manager.

Modello di soluzione da Azure Marketplace

Quando si distribuisce un modello di soluzione (non un'app gestita di Azure) da Azure Marketplace, la distribuzione è semplicemente il modello arm pubblicato con i campi dell'interfaccia utente corrispondenti passati come parametri. Per distribuire l'offerta di modello di soluzione a livello di codice, usare portale di Azure per eseguire la distribuzione, copiare il modello di Resource Manager e usarlo nelle distribuzioni successive. Poiché i modelli di soluzione non sono offerte a pagamento, non esistono termini speciali che devono essere accettati. Tuttavia, se il modello di Resource Manager del modello di soluzione fa riferimento a un'immagine di macchina virtuale da Azure Marketplace, è necessario prima accettare le condizioni dell'offerta di macchina virtuale come descritto per l'offerta di macchina virtuale.