Azure API Management 인증 - 3부

12554 단어

요약



Part.2 기사에 이어 샘플 코드api-management-sample의 작동 방식에 대해 공유하고자 합니다. Key Vault를 사용한 비밀 관리는 .



  • 목차


  • API deployment

  • Subscription Key Validation vs Gateway Validation
  • Bicep
  • Azure Piplines Yaml

  • Integration test

  • API 배포

    In the deployment pipeline, it builds .NET API, generates the API documentation swagger.json , and deploys it to API Management. To generate swagger.json , the .NET project file needs to install Swashbuckle.AspNetCore.Cli package.

    Project file example AzureAdAuth.csproj

    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
    

    Program.cs에서 API 설명서를 정의해야 합니다.

    Program.cs

    builder.Services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new() { Title = "AzureAdAuthAPI", Version = "v1" });
    });
    


    .NET API 프로젝트의 경우 .NET CLI 로컬 도구를 사용할 수 있습니다. 아래 명령은 ./.config/dotnet-tools.json 를 생성합니다.

    dotnet new tool-manifest
    


    초기dotnet-tools.json 파일은 다음과 같습니다.

    {
      "version": 1,
      "isRoot": true,
      "tools": {}
    }
    


    그런 다음 아래 명령을 실행하여 Swashbuckle.AspNetCore.Cli를 설치할 수 있습니다. 위의 proejct 파일에 정의된 NugetPackage 버전과 해당 버전을 일치시켜야 합니다.

    dotnet tool install Swashbuckle.AspNetCore.Cli --version 6.3.1
    


    명령 뒤에 dotnet-tools.json 파일은 다음과 같습니다.

    {
      "version": 1,
      "isRoot": true,
      "tools": {
        "swashbuckle.aspnetcore.cli": {
          "version": "6.3.1",
          "commands": [
            "swagger"
          ]
        }
      }
    }
    


    그런 다음 아래 명령을 실행하여 swagger.json 를 생성합니다. v1는 위의 Program.cs에서 결정된 버전과 일치해야 합니다.

    dotnet swagger tofile --output swagger.json .\bin\Debug\net6.0\AzureAdAuth.dll v1
    


    위의 생성swagger.json 프로세스는 Azure Pipelines에서 실행할 수 있습니다. 아래 Yaml 파일 예시에서 작업에서 생성된 swagger.json는 API Management에 배포됩니다.

    api_pipeline.yml

    - task: DotNetCoreCLI@2
      displayName: dotnet new tool-manifest
      inputs:
        command: custom
        custom: new
        arguments: tool-manifest
        workingDirectory: $(ApiDirectory)
    - task: DotNetCoreCLI@2
      displayName: dotnet tool install
      inputs:
        command: custom
        custom: tool
        arguments: install Swashbuckle.AspNetCore.Cli --version $(SwashbuckleVersion)
        workingDirectory: $(ApiDirectory)
    - task: DotNetCoreCLI@2
      displayName: dotnet swagger tofile
      inputs:
        command: custom
        custom: swagger
        arguments: tofile --output swagger.json $(DllPath) $(SwaggerVersion)
        workingDirectory: $(ApiDirectory)
    - task: AzureCLI@2
      displayName: Deploy API to API Management
      inputs:
        azureSubscription: $(AZURE_SVC_NAME)
        scriptType: ps
        scriptLocation: inlineScript
        inlineScript: |
          az apim api import -g $(ResourceGroupName) `
            --service-name $(APIManagementName) `
            --api-id ${{AppServiceInstance.api}} `
            --path ${{AppServiceInstance.path}} `
            --specification-format OpenApiJson `
            --specification-path $(APIManagementSwaggerPath) `
            --service-url $(APIManagementServiceUrl)
    


    구독 키 유효성 검사와 게이트웨이 유효성 검사

    The architecture of Subscription Key Validation and Gateway Validation is explained in the previous articles. In this section, I am going to explain what is the code difference between two architectures for the bicep and Yaml files.

    Subscription Key Validation



    게이트웨이 검증



    이두근

    azuredeploy_subscription.bicep
    azuredeploy_gateway.bicep



    구독 키 유효성 검사
    게이트웨이 검증


    구독필수truefalse
    AzureAdAuthAPI 정책
    Azure AD에서 토큰 가져오기 및 헤더에서 구독 키 제거
    클라이언트 앱에서 Azure AD 토큰 유효성 검사

    BasicAuthAPI 정책
    사용자 이름과 비밀번호를 설정하고 헤더에서 구독 키를 제거합니다.
    기본 인증 사용자 이름 및 비밀번호 확인

    CertificateAuthAPI 정책
    Key Vault에서 인증서 가져오기 및 헤더에서 구독 키 제거
    클라이언트 인증서 유효성 검사 및 Key Vault에서 인증서 가져오기

    Azure 파이프라인 Yaml

    The only difference is which bicep file the pipeline execute, azuredeploy_subscription.bicep or azuredeploy_gateway.bicep

    iac_pipeline_subscription.yml
    iac_pipeline_gateway.yml

    통합 테스트

    The CI/CD pipeline api_pipeline.yml에는 6가지 유형의 통합 테스트, 3가지 API에 대한 구독 키 검증 및 3가지 API에 대한 게이트웨이 검증이 포함됩니다. 모든 통합 테스트는 매번 실행되며 아키텍처가 Subscription Key Validation인 경우 3개 테스트는 성공하고 나머지 3개는 실패합니다. 게이트웨이 유효성 검사 아키텍처의 경우 그 반대입니다.

    구독 키



    구독 키는 IaC 파이프라인 배포 중에 Key Vault에 저장됩니다. 파이프라인은 Key Vault에서 구독 키를 다운로드하고 헤더에 연결한 다음 API에 요청을 보냅니다.

    - task: AzurePowerShell@5
      continueOnError: true
      displayName: Integration test - Subscription key - ${{AppServiceInstance.name}}
      inputs:
        azureSubscription: $(AZURE_SVC_NAME)
        azurePowerShellVersion: latestVersion
        ScriptType: InlineScript
        Inline: |
          $subscriptionKey = Get-AzKeyVaultSecret -VaultName $env:KeyVaultName -Name $env:KVSECRET_NAME_SUBSCRIPTION_KEY -AsPlainText
          $uri = "https://$env:APIManagementName.azure-api.net/${{AppServiceInstance.name}}/Weatherforecast/RequireAuth"
          $headers = @{
            "Ocp-Apim-Subscription-Key" = $subscriptionKey
          }
          Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
    


    Azure AD 토큰


  • 응용 프로그램 ID 및 암호와 같은 모든 필수 매개 변수는 파이프라인 라이브러리 및 키 자격 증명 모음에서 가져옵니다.
  • 서비스 인증이므로 OAuth2.0 클라이언트 자격 증명 흐름을 사용합니다.

  • - task: AzurePowerShell@5
      continueOnError: true
      displayName: Integration test - Gateway validation - AzureAdAuth
      inputs:
        azureSubscription: $(AZURE_SVC_NAME)
        azurePowerShellVersion: latestVersion
        ScriptType: InlineScript
        Inline: |
          $clientSecret = Get-AzKeyVaultSecret -VaultName $env:KeyVaultName -Name $env:KVSECRET_NAME_CLIENTSECRET -AsPlainText
          $authorizeUri = "https://login.microsoftonline.com/$env:AAD_TENANTID/oauth2/v2.0/token"
          $body = 'grant_type=client_credentials' + `
          '&client_id=$(AAD_APPID_CLIENT)' + `
          '&client_secret=' + $clientSecret + `
          '&scope=api://$(AAD_APPID_BACKEND)/.default'
          $token = (Invoke-RestMethod -Method Post -Uri $authorizeUri -Body $body).access_token
          $Uri = "https://$env:APIManagementName.azure-api.net/AzureAdAuth/Weatherforecast/RequireAuth"
          $headers = @{
            "Authorization" = 'Bearer ' + $token
          }
          Invoke-RestMethod -Uri $Uri -Method Get -Headers $headers
    


    기본 인증


  • 암호가 Key Vault에서 다운로드됩니다.
  • 사용자 이름과 암호가 Base64 인코딩으로 변환됩니다.

  • - task: AzurePowerShell@5
      continueOnError: true
      displayName: Integration test - Gateway validation - BasicAuth
      inputs:
        azureSubscription: $(AZURE_SVC_NAME)
        azurePowerShellVersion: latestVersion
        ScriptType: InlineScript
        Inline: |
          $basicAuthUsername = $env:BASIC_AUTH_USER
          $basicAuthSecret = Get-AzKeyVaultSecret -VaultName $env:KeyVaultName -Name $env:KVSECRET_NAME_BASIC_PASS -AsPlainText
          $bytes = [System.Text.Encoding]::ASCII.GetBytes($basicAuthUsername + ':' + $basicAuthSecret)
          $authHeader = [Convert]::ToBase64String($bytes)
          $Uri = "https://$env:APIManagementName.azure-api.net/BasicAuth/Weatherforecast/RequireAuth"
          $headers = @{
            "Authorization" = 'Basic ' + $authHeader
          }
          Invoke-RestMethod -Uri $Uri -Method Get -Headers $headers
    


    인증서 인증


  • PFX 파일 형식으로 Key Vault에서 인증서를 다운로드합니다.
  • 다운로드한 PFX 파일이 요청에 첨부됩니다.

  • - task: AzurePowerShell@5
      continueOnError: true
      displayName: Integration test - Gateway validation - CertificateAuth
      inputs:
        azureSubscription: $(AZURE_SVC_NAME)
        azurePowerShellVersion: latestVersion
        ScriptType: InlineScript
        Inline: |
          $cert = Get-AzKeyVaultCertificate -VaultName $env:KeyVaultName -Name $env:KVCERT_NAME_API
          $secret = Get-AzKeyVaultSecret -VaultName $env:KeyVaultName -Name $cert.Name
          $secretValueText = '';
          $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret.SecretValue)
          try {
              $secretValueText = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
          } finally {
              [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
          }
          $secretByte = [Convert]::FromBase64String($secretValueText)
          $x509Cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
          $x509Cert.Import($secretByte, "", "Exportable,PersistKeySet")
          $type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
          $pfxFileByte = $x509Cert.Export($type, $password)
          [System.IO.File]::WriteAllBytes("KeyVault.pfx", $pfxFileByte)
          $parameters = @{
              Method  = "GET"
              Uri     = "https://$env:APIManagementName.azure-api.net/CertificateAuth/Weatherforecast/RequireAuth"
              Certificate  = (Get-PfxCertificate "./KeyVault.pfx")
          }
          Invoke-RestMethod @parameters
    

    좋은 웹페이지 즐겨찾기