Membuat proksi API untuk GeoCatalog menggunakan Azure API Management

Artikel ini memandu Anda menyiapkan Azure API Management (APIM) sebagai proksi API di depan Microsoft Planetary Computer Pro GeoCatalog. Dengan konfigurasi ini Anda dapat:

  • Aktifkan akses anonim: penelepon tidak memerlukan kredensial Microsoft Entra mereka sendiri. APIM mengautentikasi ke GeoCatalog atas nama mereka menggunakan identitas terkelola.
  • Autentikasi Non-Entra: penelepon dapat mendukung metode autentikasi berbasis non-Entra. APIM mengautentikasi ke GeoCatalog atas nama mereka menggunakan identitas terkelola.
  • Terapkan kontrol akses tingkat koleksi: batasi koleksi Spatiotemporal Access Catalog (STAC) mana yang terlihat melalui proksi, meskipun GeoCatalog tidak secara asli mendukung kontrol akses berbasis peran tingkat koleksi (RBAC).

Diagram berikut mengilustrasikan arsitektur sebelum dan sesudah menambahkan proksi APIM:

Sebelum Setiap penelepon mengautentikasi langsung ke GeoCatalog:

caller ──(Entra token)──► GeoCatalog

Setelah APIM berada di antara penelepon dan GeoCatalog, menangani autentikasi dan kontrol akses:

caller ──(anonymous / APIM Subscription Keys)──► APIM ──(managed identity token)──► GeoCatalog

Prasyarat

Menetapkan identitas terkelola ke APIM

Sebelum APIM dapat mengautentikasi ke GeoCatalog Anda, Anda perlu mengaitkan identitas terkelola yang ditetapkan pengguna dengan instans APIM.

  1. Di portal Azure, navigasikan ke instance Manajemen API Anda.
  2. Pilih Identitas dari bilah sisi kiri.
  3. Pilih tab Pengguna yang ditetapkan.
  4. Pilih Tambahkan, lalu pilih identitas terkelola yang ditetapkan pengguna yang memiliki peran Pembaca GeoCatalog di GeoCatalog Anda.
  5. Pilih Tambahkan untuk mengonfirmasi.

Membuat API di APIM

Tentukan API baru di APIM yang memproksi permintaan ke backend GeoCatalog Anda.

  1. Di instans APIM Anda, pilih API dari bilah sisi kiri.

  2. Pilih + Tambahkan API>HTTP.

  3. Konfigurasikan API dengan pengaturan berikut:

    Setting Nilai
    Nama tampilan Nama deskriptif (misalnya, GeoCatalog API)
    URL layanan web Titik akhir GeoCatalog Anda (misalnya, https://<name>.<id>.<region>.geocatalog.spatio.azure.com)
    Skema URL HTTPS
    Akhiran URL API Biarkan kosong (jalur akar)
    Langganan diperlukan Tidak, untuk akses Anonim; Ya, untuk akses berbasis Kunci Langganan
  4. Pilih Buat.

Menentukan operasi API

Tambahkan operasi berikut agar sesuai dengan permukaan API GeoCatalog. Operasi wildcard (/*) meneruskan semua permintaan yang cocok ke backend. Operasi pengumpulan eksplisit memungkinkan Anda menerapkan kebijakan khusus koleksi nanti untuk kontrol akses.

Nama tampilan Metode Templat URL
DAPATKAN DAPATKAN /*
Mendapatkan item koleksi DAPATKAN /stac/collections/{collection_id}/items
Dapatkan koleksi tunggal DAPATKAN /stac/collections/{collection_id}
Dapatkan sub-sumber daya koleksi DAPATKAN /stac/collections/{collection_id}/*
POST POST /*

Untuk menambahkan setiap operasi:

  1. Pilih API yang Anda buat.
  2. Pilih + Tambahkan operasi.
  3. Masukkan Nama tampilan, Metode, dan Templat URL dari tabel sebelumnya.
  4. Pilih Simpan.

Mengonfigurasi kebijakan tingkat API

Kebijakan tingkat API menangani autentikasi dan penulisan ulang URL untuk seluruh API. Kebijakan ini memperoleh token dari identitas terkelola yang ditetapkan pengguna dan melampirkannya ke setiap permintaan yang diteruskan ke backend GeoCatalog.

  1. Pilih API yang Anda buat, lalu pilih Semua operasi.
  2. Di bagian Pemrosesan masuk , pilih <ikon /> (editor kode).
  3. Ganti konten kebijakan dengan kebijakan berikut:
<policies>
    <inbound>
        <base />
        <authentication-managed-identity
            resource="https://geocatalog.spatio.azure.com"
            client-id="<managed-identity-client-id>" />
        <set-header name="Accept-Encoding"
            exists-action="delete" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
        <find-and-replace
            from="https://<name>.<id>.<region>.geocatalog.spatio.azure.com"
            to="https://<apim-name>.azure-api.net" />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Ganti tempat penampung berikut:

Placeholder Nilai
<managed-identity-client-id> ID klien dari identitas terkelola yang ditugaskan pengguna untuk APIM
<name>.<id>.<region> Komponen titik akhir GeoCatalog Anda
<apim-name> Nama instans APIM Anda

Tabel berikut ini menjelaskan setiap elemen kebijakan:

Elemen kebijakan Kegunaan
authentication-managed-identity Memperoleh token untuk audien https://geocatalog.spatio.azure.com menggunakan identitas terkelola yang ditentukan dan melampirkannya ke permintaan yang keluar.
set-header (hapus Accept-Encoding) Menghapus header Accept-Encoding dari permintaan masuk. Lihat Mengapa menghapus Accept-Encoding.
find-and-replace Menulis ulang URL backend GeoCatalog dalam isi respons ke URL gateway APIM. Tanpa penulisan ulang ini, tautan STAC (self, , rootparent, dan sebagainya) mengekspos URL backend ke pemanggil.

Mengapa menghapus Accept-Encoding

Klien seperti Python requests dan httpx mengirim Accept-Encoding: gzip, deflate secara default. Ketika backend menerima header ini, backend mengembalikan respons terkompresi. Kebijakan keluar APIM seperti find-and-replace beroperasi pada badan respons mentah dan tidak dapat mendekompresinya, sehingga mereka secara diam-diam tidak melakukan apa pun. Menghapus header memaksa backend untuk mengembalikan respons yang tidak dikompresi yang dapat diproses oleh kebijakan keluar.

Note

curl dan wget jangan kirim Accept-Encoding secara default. Ini berarti kebijakan pengiriman tampaknya berfungsi dengan benar ketika Anda menguji dengan alat-alat tersebut. Inkonsistensi hanya muncul dengan klien yang meminta kompresi.

Menerapkan kontrol akses tingkat koleksi data

Secara default, GeoCatalog mengekspos semua koleksinya ke pemanggil yang diautentikasi. Untuk membatasi koleksi mana yang terlihat melalui APIM, terapkan kebijakan tingkat operasi yang memblokir penemuan STAC luas dan menerapkan daftar izin.

Tentukan koleksi yang diizinkan

Buat nilai bernama di APIM untuk menyimpan daftar ID koleksi yang diizinkan:

  1. Di instans APIM Anda, pilih Nilai bernama dari bilah sisi kiri.
  2. Pilih + Tambahkan.
  3. Atur Nama ke allowed-collections.
  4. Atur Nilai ke daftar ID koleksi yang diizinkan yang dipisahkan koma (misalnya, sentinel-2-l2a,landsat-8-c2-l2).
  5. Pilih Simpan.

Memblokir halaman arahan dan daftar koleksi

Blokir rute yang mengungkapkan koleksi-koleksi dalam katalog. Tambahkan operasi berikut dan lampirkan kebijakan yang segera dikembalikan 404 :

Nama tampilan Metode Templat URL
Blokir akar DAPATKAN /
Blokir koleksi DAPATKAN /stac/collections

Terapkan kebijakan tingkat operasi berikut ke kedua operasi:

<policies>
    <inbound>
        <base />
        <return-response>
            <set-status code="404" reason="Not Found" />
        </return-response>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Titik akhir STAC /stac/search menerima collections parameter - sebagai string kueri pada GET atau di isi JSON di POST. Tanpa pagar pembatas, pemanggil dapat mencari di setiap koleksi dalam katalog. Kebijakan berikut memvalidasi bahwa hanya koleksi dari set yang diizinkan yang diminta.

Tambahkan dua operasi:

Nama tampilan Metode Templat URL
Pencarian GET DAPATKAN /stac/search
Pencarian POST POST /stac/search

GET /stac/search policy

Kebijakan ini memvalidasi collections parameter kueri. Setiap nilai yang dipisahkan koma harus berada dalam set yang diizinkan. Permintaan tanpa collections parameter ditolak dengan 403 Forbidden.

Terapkan kebijakan berikut ke operasi pencarian GET :

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var raw = context.Request.Url.Query
                    .GetValueOrDefault("collections", "");
                if (string.IsNullOrWhiteSpace(raw)) {
                    return true;
                }
                foreach (var c in raw.ToLower().Split(
                    new [] { "," },
                    StringSplitOptions.RemoveEmptyEntries))
                {
                    if (!c.Trim().Equals(allowed)) {
                        return true;
                    }
                }
                return false;
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Note

Ekspresi kebijakan APIM berjalan di lingkungan C# terbatas. Gunakan condition='@{...}' (atribut yang menggunakan tanda kutip tunggal) agar tanda kutip ganda berfungsi di dalam ekspresi. Hindari parameter jenis generik (misalnya, GetValueOrDefault<string>) dan lambda LINQ - gunakan cast dan foreach perulangan eksplisit sebagai gantinya.

KEBIJAKAN POST /stac/search

Kebijakan ini mengurai isi JSON dan memvalidasi collections array. Permintaan tanpa collections parameter ditolak dengan 403 Forbidden.

Terapkan kebijakan berikut ke operasi pencarian POST :

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <set-variable name="requestBody"
            value="@(context.Request.Body
                .As&lt;string&gt;(
                    preserveContent: true))" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var body = (string)context
                    .Variables["requestBody"];
                var json = Newtonsoft.Json.Linq
                    .JObject.Parse(body);
                var arr = json["collections"]
                    as Newtonsoft.Json.Linq.JArray;
                if (arr == null || arr.Count == 0) {
                    return true;
                }
                foreach (var token in arr) {
                    if (!token.ToString().Trim()
                        .ToLower().Equals(allowed))
                    {
                        return true;
                    }
                }
                return false;
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Menerapkan koleksi yang diizinkan pada titik akhir pengumpulan

Tanpa adanya operasi eksplisit, permintaan seperti GET /stac/collections/sentinel-2-l2a atau GET /stac/collections/sentinel-2-l2a/items diteruskan ke wildcard GET /* dan mencapai backend tanpa pemeriksaan level koleksi. Terapkan kebijakan parameter jalur yang memvalidasi collection_id terhadap {{allowed-collections}} operasi berikut yang Anda buat dalam Menentukan operasi API:

Nama tampilan Metode Templat URL
Dapatkan koleksi tunggal DAPATKAN /stac/collections/{collection_id}
Ambil sub-sumber daya koleksi DAPATKAN /stac/collections/{collection_id}/*
Mendapatkan item koleksi DAPATKAN /stac/collections/{collection_id}/items

Terapkan kebijakan berikut ke ketiga operasi:

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var collectionId = (string)context
                    .Request.MatchedParameters[
                        "collection_id"];
                return !collectionId.Trim()
                    .ToLower().Equals(allowed);
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Terapkan pembatasan koleksi yang diizinkan pada jalur token SAS

GEOCatalog SAS API memungkinkan penelepon menghasilkan token penyimpanan dan menandatangani HREF aset. Tanpa batasan, penelepon dapat memperoleh token untuk koleksi apa pun. Kebijakan berikut memastikan bahwa hanya koleksi yang diizinkan yang dapat diakses.

Tambahkan operasi berikut:

Nama tampilan Metode Templat URL
DAPATKAN token SAS DAPATKAN /sas/token/{collection_id}
Tanda SAS blokir DAPATKAN /sas/sign

404 Terapkan kebijakan pemblokiran (sama dengan blok akar dan koleksi) ke operasi tanda tangan Block SAS. Penelepon harus menggunakan /sas/token/{collection_id} untuk mendapatkan token SAS tingkat koleksi sebagai gantinya.

Terapkan kebijakan berikut ke operasi token GET SAS :

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var collectionId = (string)context
                    .Request.MatchedParameters[
                        "collection_id"];
                return !collectionId.Trim()
                    .ToLower().Equals(allowed);
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Menerapkan koleksi yang diizinkan pada rute data

Titik /data/mosaic/ akhir menyediakan penyajian petak peta, pemotongan kotak pembatas, dan pendaftaran pencarian. Diperlukan dua grup kebijakan:

  1. Daftarkan pencarian - validasi collections array di isi JSON.
  2. Semua rute koleksi lainnya - validasi collectionId parameter jalur.

Tambahkan operasi berikut:

Nama tampilan Metode Templat URL
Pencarian untuk register POST POST /data/mosaic/register
Pengumpulan data GET DAPATKAN /data/mosaic/collections/{collectionId}/*

POST /data/mosaic/daftarkan kebijakan

Kebijakan ini memvalidasi collections array dalam isi JSON terhadap set yang diizinkan. Permintaan tanpa collections parameter ditolak.

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <set-variable name="requestBody"
            value="@(context.Request.Body
                .As&lt;string&gt;(
                    preserveContent: true))" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var body = (string)context
                    .Variables["requestBody"];
                var json = Newtonsoft.Json.Linq
                    .JObject.Parse(body);
                var arr = json["collections"]
                    as Newtonsoft.Json.Linq.JArray;
                if (arr == null || arr.Count == 0) {
                    return true;
                }
                foreach (var token in arr) {
                    if (!token.ToString().Trim()
                        .ToLower().Equals(allowed))
                    {
                        return true;
                    }
                }
                return false;
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

KEBIJAKAN GET /data/mosaic/collections/{collectionId}/*

Kebijakan ini memvalidasi collectionId parameter path terhadap set yang diizinkan. Terapkan kebijakan ini ke kedua operasi pengumpulan data GET .

<policies>
    <inbound>
        <base />
        <set-variable name="allowedCsv"
            value="{{allowed-collections}}" />
        <choose>
            <when condition='@{
                var allowed = ((string)context
                    .Variables["allowedCsv"])
                    .Trim().ToLower();
                var collectionId = (string)context
                    .Request.MatchedParameters[
                        "collectionId"];
                return !collectionId.Trim()
                    .ToLower().Equals(allowed);
            }'>
                <return-response>
                    <set-status code="403"
                        reason="Forbidden" />
                    <set-body>
                        Collection not allowed.
                    </set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Tanya jawab umum

Bagaimana cara memperbarui daftar koleksi yang diizinkan?

Edit nilai bernama allowed-collections dalam instans APIM. Tidak diperlukan perubahan kebijakan.

Apa yang terjadi jika penelepon menghilangkan parameter koleksi?

Permintaan ditolak dengan 403 Forbidden. Penelepon harus selalu menentukan koleksi mana yang ingin mereka cari.