다음을 통해 공유


4부: 기본 애플리케이션 구현 예제

이전 부분: 타사 API 구현

이 시나리오의 주요 앱은 Azure App Service에 배포되는 간단한 Flask 앱입니다. 앱은 /api/v1/getcode라는 공용 API 엔드포인트를 제공합니다. 이 엔드포인트는 앱의 다른 용도로 코드를 생성합니다(예: 사용자에 대한 2단계 인증 사용). 또한 주 앱은 API 엔드포인트에 대한 링크를 표시하는 간단한 홈페이지를 제공합니다.

샘플의 프로비전 스크립트는 다음 단계를 수행합니다.

  1. App Service 호스트를 만들고 Azure CLI 명령을 az webapp up사용하여 코드를 배포합니다.

  2. 주 앱(사용 az storage account create)에 대한 Azure Storage 계정을 만듭니다.

  3. 스토리지 계정에 "code-requests"(사용 az storage queue create)라는 큐를 만듭니다.

  4. 앱이 큐에 쓸 수 있도록 하려면 앱에 "스토리지 큐 데이터 기여자" 역할을 할당하는 데 사용합니다 az role assignment create . 역할에 대한 자세한 내용은 Azure CLI를 사용하여 역할 권한을 할당하는 방법을 참조하세요.

기본 앱 코드는 다음과 같습니다. 이 시리즈의 다음 부분에서는 중요한 세부 사항에 대한 설명이 제공됩니다.

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