Partager via


Partie 4 : Exemple d’implémentation d’application principale

Partie précédente : Implémentation d’API tierce

L’application principale de notre scénario est une application Flask simple déployée sur Azure App Service. L’application fournit un point de terminaison d’API public nommé /api/v1/getcode, qui génère un code à d’autres fins dans l’application (par exemple, avec l’authentification à deux facteurs pour les utilisateurs humains). L’application principale fournit également une page d’accueil simple qui affiche un lien vers le point de terminaison de l’API.

Le script d’approvisionnement de l’exemple effectue les étapes suivantes :

  1. Créez l’hôte App Service et déployez le code avec la commande Azure CLI. az webapp up

  2. Créez un compte de stockage Azure pour l’application principale (à l’aide de az storage account create).

  3. Créez une file d’attente dans le compte de stockage nommé « code-requests » (à l’aide de az storage queue create).

  4. Pour vous assurer que l’application est autorisée à écrire dans la file d’attente, utilisez az role assignment create pour affecter à l’application le rôle de « Contributeur aux données de file d’attente de stockage ». Pour plus d’informations sur les rôles, consultez Comment attribuer des autorisations de rôle à l’aide d’Azure CLI.

Le code d’application principal est le suivant : les explications d’informations importantes sont fournies dans les prochaines parties de cette série.

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()