Teil 4: Beispiel für die Hauptanwendungsimplementierung

Vorheriger Teil: API-Implementierung von Drittanbietern

Die Haupt-App in diesem Szenario ist eine einfache Flask-App, die Sie für Azure App Service bereitstellen. Die App stellt einen öffentlichen API-Endpunkt namens "/api/v1/getcode" bereit, der einen Code für einen anderen Zweck in der App generiert (z. B. mit zweistufiger Authentifizierung für menschliche Benutzer). Die Haupt-App bietet auch eine einfache Startseite, auf der ein Link zum API-Endpunkt angezeigt wird.

Das Bereitstellungsskript des Beispiels führt die folgenden Schritte aus:

  1. Erstellen Sie den App Service-Host, und stellen Sie den Code mithilfe des Befehls Azure CLI bereit. az webapp up

  2. Erstellen Sie mithilfe von az storage account create ein Azure Storage-Konto für die Haupt-App.

  3. Erstellen Sie eine Warteschlange im Speicherkonto namens "Codeanforderungen" mithilfe von az storage queue create.

  4. Um sicherzustellen, dass die App in die Warteschlange schreiben kann, verwenden Sie az role assignment create, um der App die Rolle Storage Queue Data Contributor zuzuweisen. Weitere Informationen zu Rollen finden Sie unter Zuweisen von Rollenberechtigungen mithilfe der Azure CLI.

Der Haupt-App-Code lautet wie folgt. Erläuterungen wichtiger Details werden in den nächsten Teilen dieser Reihe erläutert.

from flask import Flask, request, jsonify
import requests, random, string, os
from datetime import datetime
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential
from azure.storage.queue import QueueClient

app = Flask(__name__)
app.config["DEBUG"] = True

number_url = os.environ["THIRD_PARTY_API_ENDPOINT"]

# Authenticate with Azure. First, obtain the DefaultAzureCredential
credential = DefaultAzureCredential()

# Next, get the client for the Key Vault. You must have first enabled managed identity
# on the App Service for the credential to authenticate with Key Vault.
key_vault_url = os.environ["KEY_VAULT_URL"]
keyvault_client = SecretClient(vault_url=key_vault_url, credential=credential)

# Obtain the secret: for this step to work you must add the app's service principal to
# the key vault's access policies for secret management.
api_secret_name = os.environ["THIRD_PARTY_API_SECRET_NAME"]
vault_secret = keyvault_client.get_secret(api_secret_name)

# The "secret" from Key Vault is an object with multiple properties. The key we
# want for the third-party API is in the value property. 
access_key = vault_secret.value

# Set up the Storage queue client to which we write messages
queue_url = os.environ["STORAGE_QUEUE_URL"]
queue_client = QueueClient.from_queue_url(queue_url=queue_url, credential=credential)


@app.route('/', methods=['GET'])
def home():
    return f'Home page of the main app. Make a request to <a href="./api/v1/getcode">/api/v1/getcode</a>.'


def random_char(num):
       return ''.join(random.choice(string.ascii_letters) for x in range(num))


@app.route('/api/v1/getcode', methods=['GET'])
def get_code():
    headers = {
        'Content-Type': 'application/json',
        'x-functions-key': access_key
        }

    r = requests.get(url = number_url, headers = headers)
    
    if (r.status_code != 200):       
        return "Could not get you a code.", r.status_code

    data = r.json()
    chars1 = random_char(3)
    chars2 = random_char(3)
    code_value = f"{chars1}-{data['value']}-{chars2}"
    code = { "code": code_value, "timestamp" : str(datetime.utcnow()) }

    # Log a queue message with the code for, say, a process that invalidates
    # the code after a certain period of time.
    queue_client.send_message(code)

    return jsonify(code)


if __name__ == '__main__':
    app.run()