演習 - Shared Access Signature を使用して Azure Storage へのアクセスを委任する

完了

Azure Storage を使用して、共有キー、Shared Access Signature (SAS)、または Microsoft Entra ID によるファイルへのアクセスを承認できます。 SAS を使用すると、クライアントがファイルを使用して実行できることと、その期間を制御できます。

あなたの会社の画像診断システムは、共有キーを使用して内部で患者の画像にアクセスします。 サード パーティによる診断画像へのアクセスを許可するには、API を作成する必要があります。 Web アプリにテスト ページを作成して、サード パーティ クライアントに安全なアクセスを許可するために、SAS がどのように役立つかを確認します。

この演習では、ストレージ アカウントを作成し、患者のサンプル画像をいくつかアップロードします。 チームの既存の Web アプリをデプロイし、それがストレージにアクセスできることをテストします。 最後のステップでは、画像を安全に表示するため、必要に応じて SAS トークンを生成する C# と JavaScript のコードを追加します。

Screenshot of your company's patient diagnostic image system showing three images.

ストレージ アカウントを作成して画像をアップロードする

  1. Azure Cloud Shell を使用して、次のコードを入力して、患者の画像用のストレージ アカウントを作成します。 このコードでストレージ アカウント名が生成されます。

    export STORAGENAME=medicalrecords$RANDOM
    
    az storage account create \
        --name $STORAGENAME \
        --access-tier hot \
        --kind StorageV2 \
        --resource-group "<rgn>[sandbox resource group name]</rgn>"
    
  2. 画像を格納するために、ストレージ アカウントの下にコンテナーを作成します。

    az storage container create \
        --name patient-images \
        --account-name $STORAGENAME \
        --public-access off
    
  3. チームの既存の Web アプリをクローンします。 このリポジトリには、テストのためにチームで使用されるサンプル画像が含まれています。

    git clone https://github.com/MicrosoftDocs/mslearn-control-access-to-azure-storage-with-sas.git sas
    
  4. Azure CLI の upload-batch コマンドを使用して、画像をストレージ アカウントにアップロードします。

    az storage blob upload-batch \
        --source sas \
        --destination patient-images \
        --account-name $STORAGENAME \
        --pattern *.jpg
    

患者の画像診断システムをテストする

  1. ストレージ アカウントの接続文字列を追加できるように、コード エディターで appsettings.json ファイルを開きます。

    code sas/appsettings.json
    
  2. Cloud Shell で次のコードを入力して、ストレージ アカウントへの接続文字列を取得します。

    az storage account show-connection-string --name $STORAGENAME
    

    応答はこの形式で表示されるはずです。

    {
      "connectionString": "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=medicalrecords3215;AccountKey=UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA=="
    }
    

    引用符を含む、connectionString 値をコピーします。

  3. コード エディターで、ConnectionString 値 "[connection string]" を、コピーした文字列に置き換えます。

  4. 接続文字列の本文の AccountName= の値をコピーします。

  5. AccountName パラメーターの値を、コピーしたアカウント名の値に置き換えます。

  6. 接続文字列の本文の AccountKey= の値をコピーします (引用符は含めない)。 必ず、値の末尾に == を含めてください。

  7. AccountKey パラメーターの値を、コピーしたアカウント キーの値に置き換えます。

  8. appsettings.json ファイルは次の出力のようになっているはずです。

    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "StorageAccount": {
        "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=medicalrecords3215;AccountKey=UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA==;EndpointSuffix=core.windows.net",
        "Container" : "patient-images",
        "AccountName":"medicalrecords3215",
        "AccountKey":"UGLNuJWUBtodz+VbhhFcMwkzDpX49Wf7FxtuQDTOHhH+LpCtSQ2LBP0Ju8TQby5CeOt7DMYBgH45SX9yFwqPvA=="
      }  
    }
    
  9. Ctrl + S キーに続けて Ctrl + Q キーを選択して、コード エディターを保存して閉じます。

  10. Cloud Shell で実行されているときに Web アプリにアクセスできるように、ポートを開きます。

    curl -X POST http://localhost:8888/openPort/8000;
    

    このコマンドにより、アプリにアクセスできる url が返されます。

    {"message":"Port 8000 is open","url":"https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/"}
    
  11. アプリを実行します。

    cd sas
    dotnet run
    

    アプリがコンパイルされると、Cloud Shell コンソールに次の例のような詳細が表示されます。

    Hosting environment: Development
    Content root path: /home/<yourusername>/sas
    Now listening on: https://localhost:8001
    Now listening on: http://localhost:8000
    Application started. Press Ctrl+C to shut down.
    
  12. ブラウザーに、先ほどの cURL コマンドによって返された URL を貼り付けます。 必ず、アドレスの末尾にスラッシュ (/) を含めてください。

    この URL は、https://gateway11.northeurope.console.azure.com/n/cc-4016c848/cc-4016c848/proxy/8000/ 形式になっている必要があります。

    サインインを求められたら、ブラウザー ウィンドウを更新します。 Lamna Healthcare という患者の画像診断システムが表示されます。

  13. [Get all patient](すべての患者を取得する) を選択して、ストレージ アカウント内のすべての画像の一覧を表示します。

コードを追加して SAS を作成する

  1. Cloud Shell で、Ctrl + C キーを選択して Web アプリを停止します。

  2. PatientRecordController クラスを拡張してオンデマンド SAS を作成し、それを Web アプリのフロント エンドに返しましょう。

  3. 次のコードを入力し、コード エディターで PatientRecordController.cs ファイルを開きます。

    code Controllers/PatientRecordController.cs
    
  4. 次のコードを GET PatientRecord/patient-nnnnnn メソッドのクラスの最後に追加します。

    // GET PatientRecord/patient-nnnnnn/secure
    [HttpGet("{Name}/{secure}")]
    public PatientRecord Get(string name, string flag)
    {
        BlobClient blob = _container.GetBlobClient(name);
        return new PatientRecord { name=blob.Name, imageURI=blob.Uri.AbsoluteUri, sasToken=GetBlobSas(blob) };
    }
    

    このメソッドは、要求された患者の画像と、それにアクセスするために使用できる SAS を返します。

  5. BLOB 用の SAS を作成するメソッドを追加します。

    // Build a SAS token for the given blob
    private string GetBlobSas(BlobClient blob)
    {
        // Create a user SAS that only allows reading for a minute
        BlobSasBuilder sas = new BlobSasBuilder 
        {
            BlobContainerName = blob.BlobContainerName,
            BlobName = blob.Name,
            Resource = "b",
            ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1)
        };
        // Allow read access
        sas.SetPermissions(BlobSasPermissions.Read);
    
        // Use the shared key to access the blob
        var storageSharedKeyCredential = new StorageSharedKeyCredential(
            _iconfiguration.GetValue<string>("StorageAccount:AccountName"),
            _iconfiguration.GetValue<string>("StorageAccount:AccountKey")
        );
    
        return '?' + sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
    }
    

    このメソッドでは、渡された BlobClient オブジェクトを使用して BlobSasBuilder が作成され、読み取り専用で 1 分後に有効期限が切れる SAS が生成されます。

  6. Ctrl + S キーを選択してファイルを保存してから、Ctrl + Q キーを選択してエディターを終了します。

SAS を使用するコードを追加する

Web ページにコードを追加して、画像の SAS を要求しましょう。

  1. 次のコマンドを入力して external.cshtml ページを編集します。

    code Pages/external.cshtml
    
    
  2. ファイルの末尾付近にある #btn-submit のクリック リスナーで、$.get 行を変更して + '/secure' を追加します。

    $('#btn-submit').click(function(){
        $('#result').empty();
        $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) {
            var imageURL = data.imageURI + $('#sasKey').val();
            $('#result').html('<img id="patientScan" class="alert alert-success" src="' + imageURL + '" alt="patient scan" onerror="this.classList.remove(\'alert-success\'); this.classList.add(\'alert-danger\')"//>');
        }, 'json');
    });
    
  3. ファイルの下部で、#btn-submit クリック リスナー関数の下、</script> タグの上に、次のコードを追加します。

    $('#btn-getKey').click(function(){
        $.get('api/PatientRecords/' + $('#patientID').val() + '/secure', function (data) {
            $('#sasKey').val(data.sasToken);
        }, 'json');
    });
    

    この jQuery コードは、btn-getKey ボタンにクリック リスナーを追加します。 このコードは、指定された画像ファイルの新しいセキュリティで保護された URL に対して Ajax 呼び出しを実行します。 返されるときに、キー入力ボックスに SAS が設定されます。

  4. Ctrl + S キーを選択して変更を保存してから、Ctrl + Q キーを選択してエディターを終了します。

変更をテストする

  1. 更新したアプリを実行します。

    dotnet run
    
  2. ブラウザーで、Web サイトのタブを更新します。 [Get all patients](すべての患者を取得) を選択し、いずれかの画像ファイル名をコピーします。

  3. Web ページの上部にあるメニューで、[External companies](外部企業) を選択します。

  4. [Patient image filename](患者の画像ファイル名) フィールドにファイル名を貼り付けます。

  5. [View scan](スキャンの表示) を選択します。 SAS を作成していないので、患者のスキャン画像にアクセスできません。

    注意

    ブラウザーでコンソールを表示している場合は、Web サーバーから 404 エラー コード メッセージが返されたのがわかります。

  6. [キーの取得] を選択します。これにより、[キー] フィールドに SAS が設定されます。

  7. [View scan](スキャンの表示) を選択します。 患者の診断画像が表示されます。

    Screenshot of API for external companies showing a patient's image.

  8. ブラウザーで画像を右クリックし、画像のアドレスをコピーします。

  9. 新しいブラウザー タブを開き、コピーした画像アドレスをアドレス バーに貼り付け、Enter キーを押します。 SAS を作成してから 1 分以上経過している場合は、エラー メッセージが表示されます。 1 分以内の場合は、画像が表示されます。

    注意

    場合によっては、ページを更新する必要があります。

    <Error>
        <Code>AuthenticationFailed</Code>
        <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly, including the signature.
        RequestId:03eda893-f01e-0028-2d73-c5c947000000
        Time:2021-01-07T16:02:55.3752851Z</Message>
        <AuthenticationErrorDetail>Signed expiry time [Tue, 07 Jan 2021 16:02:00 GMT] must be after signed start time [Tue, 07 Jan 2021 16:02:55 GMT]</AuthenticationErrorDetail>
    </Error>
    

    注意

    一部のブラウザーからこのエラー メッセージを表示するには、画像をキャッシュしていない新しいブラウザー ウィンドウを開く必要がある場合があります。

  10. Cloud Shell で Ctrl + C キーを選択して Web アプリを終了します。