#!/usr/bin/env bash # # apim_create_subscription_from_tsv.sh # TSV를 읽어 APIM product 확인/생성 -> product 범위 구독 생성 -> secondary key/만료일(expirationDate) 반영 # -> 종료 후 3초 대기 -> 이번 실행에서 생성한 product의 자동 admin 구독 일괄 삭제 # # * expirationDate는 조회 시 보이는 뷰잉용 속성이며 실제 만료 강제 기능은 없음. # # 실행 예시: # ./apim_create_subscription_from_tsv.sh -g -n -f subscriptionKey.tsv # # 사전: az login && az account set --subscription <구독> # # TSV(헤더 필수, 콤마 구분): key,subscriptionID,description,startDate,endDate # subscriptionID svc-0000-audi-gis-info -> product-audi-gis-info (svc-0000- 제거 후 product- 접두) set -uo pipefail RESOURCE_GROUP="" APIM_NAME="" TSV_FILE="" API_VERSION="2022-08-01" while [[ $# -gt 0 ]]; do case "$1" in -g) RESOURCE_GROUP="$2"; shift 2 ;; -n) APIM_NAME="$2"; shift 2 ;; -f) TSV_FILE="$2"; shift 2 ;; *) echo "알 수 없는 옵션: $1"; exit 1 ;; esac done [[ -z "$RESOURCE_GROUP" || -z "$APIM_NAME" || -z "$TSV_FILE" ]] && { echo "사용법: $0 -g -n -f "; exit 1; } [[ ! -f "$TSV_FILE" ]] && { echo "TSV 파일 없음: $TSV_FILE"; exit 1; } AZ_SUB_ID=$(az account show --query id -o tsv 2>/dev/null) [[ -z "$AZ_SUB_ID" ]] && { echo "az login 상태를 확인하세요."; exit 1; } BASE="https://management.azure.com/subscriptions/${AZ_SUB_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ApiManagement/service/${APIM_NAME}" NEW_PRODUCTS=() while IFS=',' read -r key sid desc startDate endDate; do key=$(echo "$key" | xargs); sid=$(echo "$sid" | xargs); desc=$(echo "$desc" | xargs); endDate=$(echo "$endDate" | xargs) [[ -z "$sid" ]] && continue pid="product-$(echo "$sid" | sed -E 's/^svc-[^-]+-//')" echo "==== $sid -> product=$pid ====" # product 존재 확인, 없으면 생성 # 예) az rest --method get --url "$BASE/products/$pid?api-version=$API_VERSION" if ! az rest --method get --url "$BASE/products/$pid?api-version=$API_VERSION" -o none 2>/dev/null; then echo " [product 생성]" az rest --method put --url "$BASE/products/$pid?api-version=$API_VERSION" \ --body "$(printf '{"properties":{"displayName":"%s","subscriptionRequired":true,"state":"published"}}' "$pid")" -o none \ && NEW_PRODUCTS+=("$pid") fi # 구독 생성 (product 범위) # 예) az rest --method put --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" --body '{...}' if ! az rest --method get --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" -o none 2>/dev/null; then echo " [구독 생성]" az rest --method put --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" \ --body "$(printf '{"properties":{"scope":"/products/%s","displayName":"%s","state":"active"}}' "$pid" "$desc")" -o none \ || { echo " [실패] 구독 생성"; continue; } fi # secondary key(있을 때)와 만료일(expirationDate)은 서로 무관하므로 별도 PATCH로 분리 # (과거 날짜는 Azure가 expirationDate로 거부하는데, 그 실패가 key 반영까지 막지 않도록) # 예) az rest --method patch --headers "If-Match=*" --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" --body '{"properties":{"secondaryKey":"..."}}' if [[ -n "$key" ]]; then echo " [PATCH] secondaryKey 설정" az rest --method patch --headers "If-Match=*" --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" \ --body "$(printf '{"properties":{"secondaryKey":"%s"}}' "$key")" -o none || echo " [실패] secondaryKey PATCH" fi # endDate가 오늘보다 과거면 Azure가 어차피 거부하므로 expirationDate 반영 자체를 스킵 # 예) az rest --method patch --headers "If-Match=*" --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" --body '{"properties":{"expirationDate":"..."}}' if [[ -n "$endDate" ]] && (( $(date -d "$endDate" +%s) > $(date +%s) )); then echo " [PATCH] 만료일=$endDate" az rest --method patch --headers "If-Match=*" --url "$BASE/subscriptions/$sid?api-version=$API_VERSION" \ --body "$(printf '{"properties":{"expirationDate":"%sT00:00:00Z"}}' "$endDate")" -o none || echo " [실패] expirationDate PATCH" else echo " [스킵] 만료일=$endDate 이 과거 날짜라 expirationDate 등록 생략" fi done < <(tail -n +2 "$TSV_FILE" | tr -d '\r') # product 생성 시 자동 등록되는 Administrator 소유 구독(displayName 없음) 삭제 [[ ${#NEW_PRODUCTS[@]} -eq 0 ]] && { echo "신규 product 없음. 종료."; exit 0; } echo "==== 3초 대기 후 자동 admin 구독 정리 ====" sleep 3 for pid in "${NEW_PRODUCTS[@]}"; do # 예) az rest --method get --url "$BASE/subscriptions?api-version=$API_VERSION" --query "value[?...].name" -o tsv auto=$(az rest --method get --url "$BASE/subscriptions?api-version=$API_VERSION" \ --query "value[?ends_with(properties.scope, '/products/$pid') && (properties.displayName==null || properties.displayName=='')].name" -o tsv 2>/dev/null) for s in $auto; do echo " [삭제] $s (product=$pid)" az rest --method delete --url "$BASE/subscriptions/$s?api-version=$API_VERSION" -o none || echo " [실패] 삭제 $s" done done echo "완료."