haijun "/haijun-api help me configure a customer-managed encryption key with Azure Key Vault"Panduan ini memandu Anda mengonfigurasi kunci Azure Key Vault sebagai customer-managed encryption key (CMEK) untuk organisasi Juglow Anda.
Warning: Mengaktifkan CMEK bersifat permanen. Jika kunci Key Vault Anda dihapus atau dinonaktifkan, Juglow tidak dapat memulihkan data yang dienkripsi dengannya. Tinjau peringatan dan batasan sebelum Anda mulai.
Prasyarat
- Sebuah Azure Key Vault dengan otorisasi RBAC diaktifkan (
enableRbacAuthorization: true) dan akses jaringan publik diizinkan. Juglow memanggil vault Anda melalui endpoint data-plane publik; private endpoint tidak didukung.
- Perlindungan purge diaktifkan (
enablePurgeProtection: true) pada vault. Tanpa itu, kunci yang dihapus dapat di-purge secara permanen selama jendela retensi soft-delete, menyebabkan kehilangan data yang dilindungi CMEK Anda secara tidak dapat dipulihkan. Perlindungan purge tidak dapat dinonaktifkan setelah diaktifkan.
- Izin untuk membuat kunci di vault dan untuk menetapkan peran RBAC padanya.
- Izin untuk membuat service principal di tenant Entra Anda (
Application Administrator,Cloud Application Administrator, atau peran kustom yang setara).
- Sebuah kunci Admin API Juglow untuk organisasi Anda.
azCLI terinstal dan terautentikasi.
- Diagnostic Settings dikonfigurasi pada vault untuk merutekan kategori log
AuditEventke Log Analytics, akun penyimpanan, atau event hub. Azure Key Vault tidak memancarkan log audit data-plane (sepertiKeyWrap,KeyUnwrap, danKeyGet) secara default, jadi tanpa ini Anda tidak mendapatkan jejak audit untuk operasi kunci Juglow.
Informasi aplikasi Juglow
Agar Juglow menggunakan kunci enkripsi Anda, Anda harus mengonfigurasi ID aplikasi multitenant Juglow dan nama tampilan. Nilai-nilai tersebut adalah:
| Field | Value |
|---|---|
| Multitenant app client ID (US) | 8635ae1a-3e5d-44e8-a4ed-e0f614466f87 |
| App display name | juglow-cmek-client-us |
Warning: Gunakan hanya client ID dan nama tampilan yang dipublikasikan ini. Jangan pernah mempercayai pengidentifikasi yang diberikan melalui email, chat, atau saluran onboarding apa pun.
Penyiapan kunci enkripsi
- Menyetujui aplikasi multitenant Juglow
Ini membuat service principal di tenant Entra Anda untuk aplikasi client CMEK Juglow. Aplikasi tidak meminta izin Microsoft Graph; aplikasi ini ada semata-mata sebagai target federasi untuk akses data-plane Key Vault.
az ad sp create --id 8635ae1a-3e5d-44e8-a4ed-e0f614466f87Dari output, tangkap field id. Ini adalah object ID service principal di tenant Anda, yang Anda gunakan saat menetapkan peran RBAC.
{
"appId": "8635ae1a-3e5d-44e8-a4ed-e0f614466f87",
"displayName": "juglow-cmek-client-us",
"id": "<sp-object-id>"
}Jika service principal sudah ada di tenant Anda (dari upaya sebelumnya atau integrasi lain), az ad sp create keluar dengan error "already exists". Ambil object ID-nya sebagai gantinya:
az ad sp show --id 8635ae1a-3e5d-44e8-a4ed-e0f614466f87 --query id -o tsvLangkah ini tidak memiliki padanan di Portal. Jika Anda tidak memiliki Azure CLI terinstal secara lokal, buka Cloud Shell dari bilah navigasi atas Portal. Setelah perintah berhasil, Anda dapat menemukan object ID service principal di Microsoft Entra ID > Enterprise applications dengan menghapus filter tipe aplikasi default dan mencari juglow-cmek-client-us.

- Membuat kunci RSA di vault Anda
Azure Key Vault tidak mendukung pembungkusan kunci simetris, jadi kunci harus berupa RSA (3072-bit atau lebih besar) dengan wrapKey dan unwrapKey dalam operasi yang diizinkannya.
Opsi --tags menambahkan tag organisasi, juglow-org- dengan nilai true, di mana adalah ID organisasi Juglow Anda dalam huruf kecil. Tag ini diperlukan agar Juglow dapat memvalidasi kunci.
Note: Menemukan ID organisasi Anda: Salin field Organization ID di bawah Settings > Organization di Haijun Console, atau di bawah Organization settings > Organization di haijun.ai, atau baca field
iddari endpoint Organization Info. Gunakan UUID polos, bukan ID berawalanorg_.
az keyvault key create \
--vault-name <VAULT_NAME> \
--name <KEY_NAME> \
--kty RSA --size 3072 \
--ops wrapKey unwrapKey \
--tags juglow-org-<ORGANIZATION_UUID>=trueUntuk kunci yang didukung HSM, gunakan --kty RSA-HSM (memerlukan vault Premium-SKU). Kunci RSA yang dilindungi perangkat lunak dapat diterima untuk integrasi ini.
Dari Portal, buka Key Vault Anda, pilih Keys, lalu Generate/Import. Atur tipe kunci ke RSA dan ukuran ke 3072 atau lebih besar. Untuk membatasi kunci hanya untuk wrap dan unwrap, buka versi kunci, gulir ke Permitted operations, dan hapus centang semuanya kecuali Wrap Key dan Unwrap Key.
Pada halaman Create a key, tambahkan juga tag organisasi di bawah Tags.
diatur ke true."> 

Untuk berbagi satu kunci di antara beberapa organisasi Juglow, tambahkan satu tag semacam itu untuk setiap organisasi. Sebuah versi kunci dapat membawa paling banyak 15 tag, termasuk milik Anda sendiri.
Note: Untuk menambahkan tag ke kunci yang sudah Anda miliki, buka versi kunci saat ini di Portal, pilih tautan di sebelah Tags, tambahkan tag, dan klik Save. Dengan Azure CLI, jalankan
az keyvault key set-attributes --vault-name. Opsi--name --tags juglow-org- =true --tags-nya menggantikan tag versi, jadi masukkan juga setiap tag yang sudah dimiliki versi tersebut di--tags, sebagainame=value. Untuk kunci di Managed HSM, gunakan--hsm-namealih-alih--vault-name.
- Memberikan service principal Juglow akses ke kunci Anda
Tetapkan peran Key Vault Crypto User ke service principal dari langkah pertama, dengan cakupan ke kunci individual alih-alih seluruh vault.
VAULT_ID=$(az keyvault show --name <your-vault-name> --query id -o tsv)
az role assignment create \
--role "Key Vault Crypto User" \
--assignee-object-id <sp-object-id> \
--assignee-principal-type ServicePrincipal \
--scope "${VAULT_ID}/keys/<your-key-name>"Peran bawaan Key Vault Crypto User memberikan operasi kriptografi kunci (encrypt, decrypt, wrap, unwrap, sign, verify) ditambah pembacaan kunci pada cakupan yang ditetapkannya. Pembatasan --ops wrapKey unwrapKey yang Anda atur pada kunci di langkah sebelumnya lebih lanjut mempersempit operasi mana dari operasi tersebut yang dapat berhasil terhadap kunci ini, sehingga dalam praktiknya Juglow hanya dapat melakukan wrap dan unwrap.
Dari Portal, buka kunci (bukan vault), pilih tab Access control (IAM)-nya, klik Add > Add role assignment, pilih Key Vault Crypto User, dan tetapkan ke service principal juglow-cmek-client-us.
Note: Alternatif vault khusus: Microsoft merekomendasikan vault khusus per aplikasi dengan peran yang ditetapkan pada cakupan vault. Jika Anda menyediakan vault yang hanya menyimpan kunci CMEK Juglow ini, Anda dapat menetapkan peran pada cakupan vault sebagai gantinya dan efeknya identik. Cakupkan ke kunci individual ketika kunci berada di vault bersama.

- Memverifikasi konfigurasi vault Anda
az keyvault show --name <your-vault-name> \
--query "{rbac:properties.enableRbacAuthorization, purge:properties.enablePurgeProtection, pub:properties.publicNetworkAccess, net:properties.networkAcls.defaultAction, ipRules:properties.networkAcls.ipRules, uri:properties.vaultUri, tenantId:properties.tenantId}"Konfirmasikan bahwa:
rbacadalahtrue.
purgeadalahtrue. Jikafalseataunull, aktifkan perlindungan purge pada vault sebelum melanjutkan. Tanpa itu, kunci yang di-soft-delete dapat di-purge secara permanen selama jendela retensi, membuat data yang dilindungi CMEK Anda tidak dapat dipulihkan.
pubadalah"Enabled". Jika"Disabled", Juglow tidak dapat menjangkau vault melalui endpoint data-plane publiknya dan validasi gagal.
netadalah"Allow", atau, jika"Deny", bahwaipRulesmenyertakan rentang egress Juglow (hubungi Juglow untuk daftar terkini).
uriadalah URI vault yang Anda gunakan saat mendaftarkan kunci.
tenantIdadalah tenant yang mengatur vault. Gunakan nilai ini sebagaitenant_idsaat Anda mendaftarkan kunci, bukan tenant dari langganan yang sedang aktif saat ini (keduanya dapat berbeda dalam penyiapan lintas-tenant).
Mendaftarkan kunci dengan Juglow
Cara Anda mendaftarkan kunci bergantung pada produk mana yang Anda gunakan.
Haijun Platform
Anda dapat menyiapkan kunci di Haijun Console atau melalui Admin API, dengan hasil yang sama.
- Mendaftarkan kunci dengan Juglow
Di Haijun Console, buka Settings > Encryption keys dan klik Add key. Masukkan nama tampilan, pilih Azure Key Vault, dan klik Continue. Isi Vault URI, Key name, dan Tenant ID, lalu klik Add.
Langkah detail kunci menampilkan tag organisasi. Tambahkan ke kunci, seperti yang dijelaskan langkah pembuatan, sebelum Anda klik Add.
- Memvalidasi kunci
Pada halaman Encryption keys, klik Verify di sebelah kunci. Connected muncul ketika pemeriksaan lolos. Jika gagal, sebuah pesan memberikan alasannya.
- Melampirkan kunci ke workspace
Di Haijun Console, buka Manage > Security dan pilih workspace di pemilih workspace di bagian atas sidebar. Di bawah Encryption key, pilih kunci, klik Save, dan konfirmasikan. Melampirkan kunci tidak dapat dibatalkan. Untuk workspace yang sudah menerima permintaan, kunci dapat memerlukan hingga satu hari untuk berlaku.
API
- Mendaftarkan kunci dengan Juglow
Buat konfigurasi kunci eksternal melalui Admin API.
curl -sS "https://haijun.my.id/v1/organizations/external_keys" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"display_name": "<friendly-name>",
"geo": "us",
"provider_config": {
"type": "azure",
"vault_uri": "https://<your-vault-name>.vault.azure.net/",
"key_name": "<your-key-name>",
"tenant_id": "<your-tenant-id>"
}
}' ant beta:organization:external-keys create <<'YAML'
display_name: "<friendly-name>"
geo: us
provider_config:
type: azure
vault_uri: "https://<your-vault-name>.vault.azure.net/"
key_name: "<your-key-name>"
tenant_id: "<your-tenant-id>"
YAML client = juglow.Juglow()
external_key = client.beta.organization.external_keys.create(
display_name="<friendly-name>",
geo="us",
provider_config={
"type": "azure",
"vault_uri": "https://<your-vault-name>.vault.azure.net/",
"key_name": "<your-key-name>",
"tenant_id": "<your-tenant-id>",
},
)
print(f"id: {external_key.id}")
print(f"display_name: {external_key.display_name}") const client = new Juglow();
const externalKey = await client.beta.organization.externalKeys.create({
display_name: "<friendly-name>",
geo: "us",
provider_config: {
type: "azure",
vault_uri: "https://<your-vault-name>.vault.azure.net/",
key_name: "<your-key-name>",
tenant_id: "<your-tenant-id>"
}
});
console.log(`id: ${externalKey.id}`);
console.log(`display_name: ${externalKey.display_name}`); using Juglow.Models.Beta.Organization.ExternalKeys;
JuglowClient client = new();
var externalKey = await client.Beta.Organization.ExternalKeys.Create(new()
{
DisplayName = "<friendly-name>",
Geo = Geo.Us,
ProviderConfig = new BetaAzureExternalKeyConfigParam
{
VaultUri = "https://<your-vault-name>.vault.azure.net/",
KeyName = "<your-key-name>",
TenantID = "<your-tenant-id>"
}
});
Console.WriteLine($"id: {externalKey.ID}");
Console.WriteLine($"display_name: {externalKey.DisplayName}"); client := juglow.NewClient()
externalKey, err := client.Beta.Organization.ExternalKeys.New(context.Background(), juglow.BetaOrganizationExternalKeyNewParams{
DisplayName: juglow.String("<friendly-name>"),
Geo: juglow.BetaOrganizationExternalKeyNewParamsGeoUs,
ProviderConfig: juglow.BetaOrganizationExternalKeyNewParamsProviderConfigUnion{
OfAzure: &juglow.BetaAzureExternalKeyConfigParam{
VaultURI: "https://<your-vault-name>.vault.azure.net/",
KeyName: "<your-key-name>",
TenantID: "<your-tenant-id>",
},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", externalKey.ID)
fmt.Printf("display_name: %s\n", externalKey.DisplayName) import com.juglow.models.beta.organization.externalkeys.BetaAzureExternalKeyConfigParam;
import com.juglow.models.beta.organization.externalkeys.ExternalKeyCreateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = ExternalKeyCreateParams.builder()
.displayName("<friendly-name>")
.geo(ExternalKeyCreateParams.Geo.US)
.providerConfig(BetaAzureExternalKeyConfigParam.builder()
.vaultUri("https://<your-vault-name>.vault.azure.net/")
.keyName("<your-key-name>")
.tenantId("<your-tenant-id>")
.build())
.build();
var externalKey = client.beta().organization().externalKeys().create(params);
IO.println("id: " + externalKey.id());
IO.println("display_name: " + externalKey.displayName().orElseThrow());
} use Juglow\Beta\Organization\ExternalKeys\ExternalKeyCreateParams\Geo;
// ...
$client = new Client();
$externalKey = $client->beta->organization->externalKeys->create(
displayName: '<friendly-name>',
geo: Geo::US,
providerConfig: [
'type' => 'azure',
'vaultURI' => 'https://<your-vault-name>.vault.azure.net/',
'keyName' => '<your-key-name>',
'tenantID' => '<your-tenant-id>',
],
);
echo "id: {$externalKey->id}\n";
echo "display_name: {$externalKey->displayName}\n"; client = Juglow::Client.new
external_key = client.beta.organization.external_keys.create(
display_name: "<friendly-name>",
geo: :us,
provider_config: {
type: :azure,
vault_uri: "https://<your-vault-name>.vault.azure.net/",
key_name: "<your-key-name>",
tenant_id: "<your-tenant-id>"
}
)
puts "id: #{external_key.id}"
puts "display_name: #{external_key.display_name}"Respons berisi ID kunci eksternal:
{
"type": "external_key",
"id": "ekey_<id>",
"display_name": "<friendly-name>"
}- Memvalidasi kunci
Picu round-trip encrypt dan decrypt terhadap kunci Anda. Ini mengonfirmasi bahwa Juglow dapat mengautentikasi ke tenant Anda dan melakukan operasi wrap dan unwrap.
curl -sS -X POST "https://haijun.my.id/v1/organizations/external_keys/ekey_<id>/validate" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:external-keys validate --external-key-id "ekey_<id>" client = juglow.Juglow()
validation = client.beta.organization.external_keys.validate("ekey_<id>")
print(f"status: {validation.status}")
print(f"error: {validation.error}") const client = new Juglow();
const validation = await client.beta.organization.externalKeys.validate("ekey_<id>");
console.log(`status: ${validation.status}`);
console.log(`error: ${validation.error}`); JuglowClient client = new();
var validation = await client.Beta.Organization.ExternalKeys.Validate("ekey_<id>");
Console.WriteLine($"status: {validation.Status.Raw()}");
Console.WriteLine($"error: {validation.Error}"); client := juglow.NewClient()
validation, err := client.Beta.Organization.ExternalKeys.Validate(context.Background(), "ekey_<id>")
if err != nil {
log.Fatal(err)
}
fmt.Printf("status: %s\n", validation.Status)
fmt.Printf("error: %s\n", validation.Error) JuglowClient client = JuglowOkHttpClient.fromEnv();
var validation = client.beta().organization().externalKeys().validate("ekey_<id>");
IO.println("status: " + validation.status().asString());
IO.println("error: " + validation.error().orElse("")); $client = new Client();
$validation = $client->beta->organization->externalKeys->validate(
externalKeyID: 'ekey_<id>',
);
echo "status: {$validation->status}\n";
echo "error: {$validation->error}\n"; client = Juglow::Client.new
validation = client.beta.organization.external_keys.validate("ekey_<id>")
puts "status: #{validation.status}"
puts "error: #{validation.error}"Respons yang berhasil terlihat seperti ini:
{ "type": "external_key_validation", "status": "success", "error": null }Jika validasi gagal, field error menjelaskan masalahnya. Penyebab umum adalah:
- Penundaan propagasi RBAC: penetapan peran dapat memerlukan beberapa menit untuk berlaku. Tunggu dan coba lagi.
- Network ACL memblokir Juglow: konfirmasikan akses jaringan publik dan
ipRulesseperti yang dijelaskan dalam langkah verifikasi.
- Kebijakan conditional access pada workload identity: jika tenant Anda memiliki kebijakan conditional access yang menargetkan service principal, kecualikan service principal Juglow atau tambahkan rentang egress Juglow ke named location kebijakan.
- Melampirkan kunci ke workspace
Setelah kunci divalidasi, lampirkan ke workspace baru sebelum Anda mengirim permintaan apa pun ke workspace tersebut. Untuk workspace yang sudah menerima permintaan, kunci dapat memerlukan hingga satu hari untuk berlaku.
curl -sS -X POST "https://haijun.my.id/v1/organizations/workspaces/<workspace-id>" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"external_key_id": "ekey_<id>"
}' ant beta:organization:workspaces update \
--workspace-id "<workspace-id>" \
--external-key-id "ekey_<id>" client = juglow.Juglow()
workspace = client.beta.organization.workspaces.update(
"<workspace-id>", external_key_id="ekey_<id>"
)
print(f"id: {workspace.id}")
print(f"external_key_id: {workspace.external_key_id}") const client = new Juglow();
const workspace = await client.beta.organization.workspaces.update("<workspace-id>", {
external_key_id: "ekey_<id>"
});
console.log(`id: ${workspace.id}`);
console.log(`external_key_id: ${workspace.external_key_id}`); JuglowClient client = new();
var workspace = await client.Beta.Organization.Workspaces.Update("<workspace-id>", new()
{
ExternalKeyID = "ekey_<id>"
});
Console.WriteLine($"id: {workspace.ID}");
Console.WriteLine($"external_key_id: {workspace.ExternalKeyID}"); client := juglow.NewClient()
workspace, err := client.Beta.Organization.Workspaces.Update(
context.Background(),
"<workspace-id>",
juglow.BetaOrganizationWorkspaceUpdateParams{
ExternalKeyID: juglow.String("ekey_<id>"),
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", workspace.ID)
fmt.Printf("external_key_id: %s\n", workspace.ExternalKeyID) import com.juglow.models.beta.organization.workspaces.WorkspaceUpdateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = WorkspaceUpdateParams.builder()
.externalKeyId("ekey_<id>")
.build();
var workspace = client.beta().organization().workspaces().update("<workspace-id>", params);
IO.println("id: " + workspace.id());
IO.println("external_key_id: " + workspace.externalKeyId().orElseThrow());
} $client = new Client();
$workspace = $client->beta->organization->workspaces->update(
workspaceID: '<workspace-id>',
externalKeyID: 'ekey_<id>',
);
echo "id: {$workspace->id}\n";
echo "external_key_id: {$workspace->externalKeyID}\n"; client = Juglow::Client.new
workspace = client.beta.organization.workspaces.update(
"<workspace-id>",
external_key_id: "ekey_<id>"
)
puts "id: #{workspace.id}"
puts "external_key_id: #{workspace.external_key_id}"Di haijun.ai > Organization settings > Data and privacy, buka Encryption keys, lalu klik Add key. Pilih Azure, masukkan URI vault, nama kunci, dan tenant ID dari langkah verifikasi, lalu klik Continue. Juglow memvalidasi kunci dengan round-trip encrypt dan decrypt. Setelah ditampilkan sebagai terverifikasi, organisasi Anda dilindungi CMEK mulai dari titik itu.
Pada Haijun Enterprise, CMEK berlaku untuk seluruh organisasi, jadi tidak ada langkah lampiran workspace terpisah, dan sebuah organisasi hanya dapat memiliki satu kunci.
Terraform
Untuk deployment infrastructure-as-code, langkah-langkah yang sama dipetakan ke provider azurerm dan azuread.