Ders 13 / 19
İmzalama ve Sağlama Profilleri
Bir paketin taşıdığı yetkilerin kayıtlı listeyle karşılaştırılmasının kusurlu sürümü geçirip doğru sürümü reddettiğinin, sertifika ve profil denetimlerinin ise kör kaldığının ölçümü.
Yayın Güncelleme
Bu derste
- Sertifika, sağlama profili ve yetkilendirme dosyasının imzalamada ayrı birer rol oynadığını ayırır
- Kayıtlı listeyle eşitlik denetiminin kusurlu paketi geçirip doğru paketi reddettiğini ölçer
- Yalnız sertifikaya ya da yalnız profile bakan denetimlerin kusuru göremediğini doğrular
- Aynı imza denetiminin sayaca ve profile göre kör, gürültülü ya da ters olabildiğini gösterir
İçindekiler
Önceki derse kadar denetimler kodu okuyordu: testler, otomatik denetleyiciler, biçimlendiriciler. Bu dersle birlikte denetimler kodun paketlendikten sonraki hâline geçer. Bir paket aygıta ya da mağazaya ulaşmadan önce üç şeyle eşleştirilir. Sertifika, paketi kimin imzaladığını söyler. Sağlama profili (provisioning profile), hangi paket kimliğinin hangi yetkilerle ve hangi sertifikalarla çalışabileceğini sıralayan imzalı bir dosyadır. Yetkilendirme dosyası ise paketin kendisinin hangi yetkileri istediğini yazar. İmzalama bu üçünün tutarlı olup olmadığına bakar.
Bu kursun sorusu bir denetimin geçmesinin ya da kalmasının ne söylediği değildir. Soru, aynı denetimi doğru sürüme ve kusurlu sürüme uygulayınca iki yanıtın farklı olup olmadığıdır. Ölçü adı ayrımdır; dört kategorisi vardır: doğru sürümün geçip kusurlu sürümün kaldığı ayıran, ikisinin de geçtiği kör, ikisinin de kaldığı gürültülü ve doğru sürümün kalıp kusurlu sürümün geçtiği ters. Çıktıda bunlar ayiran, kor, gurultulu ve ters olarak görünür. Bu ders çekirdek dosyayla ölçer.
// Separation.swift — bir denetimin dogru surumu kusurlu surumden ayirip ayirmadigini siniflandirir
struct Contrast<Output: CustomStringConvertible> {
let label: String
let correct: Output
let faulty: Output
let passesCorrect: Bool
let passesFaulty: Bool
var separation: String {
switch (passesCorrect, passesFaulty) {
case (true, false): return "ayiran"
case (true, true): return "kor"
case (false, false): return "gurultulu"
case (false, true): return "ters"
}
}
func describe() -> String {
let onCorrect = passesCorrect ? "gecti" : "kaldi"
let onFaulty = passesFaulty ? "gecti" : "kaldi"
print("\(label) | dogru=\(correct)/\(onCorrect) kusurlu=\(faulty)/\(onFaulty) -> \(separation)")
return separation
}
}
func contrast<Output>(_ label: String, correct: Output, faulty: Output, check: (Output) -> Bool) -> Contrast<Output> {
Contrast(label: label, correct: correct, faulty: faulty, passesCorrect: check(correct), passesFaulty: check(faulty))
}
func countSeparations(_ results: [String]) {
for name in ["ayiran", "kor", "gurultulu", "ters"] {
print("\(name): \(results.filter { $0 == name }.count)")
}
}
Bu dersin kusuru şudur: uygulama uzak bildirim yetkisi ister, ama paket bu yetkiyi taşımaz. Yetkilendirme dosyasında tek bir giriş eksiktir ve paket yine de derlenir, imzalanır ve açılır. Eksiklik uygulama uzak bildirime kaydolmaya çalıştığında ortaya çıkar. Gerçek bir yetkilendirme dosyası şuna benzer; model yetkileri kendi adlarıyla tutar, gerçek dosyadaki anahtar adları değildir.
<dict> <key>aps-environment</key> <string>production</string> </dict>
Paketin gerçekte hangi yetkileri taşıdığı codesign -d --entitlements :- Shop.app komutuyla okunur. Bu ders komutun çıktısını ölçmez; ölçülen şey, imzalama kararının saf Swift ile kurulmuş modelidir. Model, denetimin iki sürüme ne dediğini kurar; imza aracının kendisi değildir.
İmzalamanın Modeli
Model üç değeri tutar: paketin kimliği ve yetkileri, profilin izin verdikleri ve bitiş sayacı, sertifikanın bitiş sayacı. Süre saatle değil sürüm sayacıyla modellenir: bir bitiş değeri, sayaç ona ulaştığında ya da onu geçtiğinde dolmuş sayılır. effective imzalı paketin gerçekte kullanabileceği yetkileri verir: paketin istediği ile profilin izin verdiğinin kesişimi. sign ise kararı verir ve imzası eşleşmeyen yetkiyi reddeder: paket profilde olmayan bir yetki taşıyorsa imza kabul edilmez.
// Signing.swift — paketin yetkilerini, sertifikayi ve saglama profilini modeller
struct Package {
let identifier: String
let entitlements: Set<String>
}
struct Profile {
let identifier: String
let allowed: Set<String>
let expiresAt: Int
}
struct Certificate {
let expiresAt: Int
}
func effective(_ package: Package, profile: Profile) -> [String] {
package.entitlements.intersection(profile.allowed).sorted()
}
func sign(_ package: Package, profile: Profile, certificate: Certificate, counter: Int) -> String {
if certificate.expiresAt <= counter { return "red:sertifika" }
if profile.expiresAt <= counter { return "red:profil" }
if package.identifier != profile.identifier { return "red:kimlik" }
if !package.entitlements.isSubset(of: profile.allowed) { return "red:yetki" }
return "imzali"
}
Kimlik denetimi küçük görünür ama gereklidir: açık kimlikli bir profil tek bir paket kimliğine bağlıdır ve aynı yetkileri taşıyan başka bir kimlikle paketlenmiş uygulama o profille imzalanamaz. Modelde bu red:kimlik olarak durur. Bu derste hiçbir girdi onu tetiklemez; kimlik eşleşmesi ölçüm dışında kalır ve kusur ona dokunmaz.
Dersin iki paketi aynı paket kimliğini taşır. Doğru paket iki yetki taşır, kusurlu paket yalnızca birini. Profil ikisine de izin verir ve uygulama ikisini ister.
// Shop.swift — dersin iki paketi, profili ve sertifikasi let requested: Set<String> = ["anahtar-zinciri", "uzak-bildirim"] let shopProfile = Profile(identifier: "com.example.shop", allowed: ["anahtar-zinciri", "uzak-bildirim"], expiresAt: 8) let shopCertificate = Certificate(expiresAt: 5) let correctPackage = Package(identifier: "com.example.shop", entitlements: ["anahtar-zinciri", "uzak-bildirim"]) let faultyPackage = Package(identifier: "com.example.shop", entitlements: ["anahtar-zinciri"])
DG1. Bu ölçüm sertifikanın ve profilin süresini sürüm sayacıyla verir. Gerçek bir bitiş tarihinin sayaca nasıl karşılık geldiği ölçülmedi.
Dört Denetim
Aynı iki pakete dört denetim uygulanır. İlki paketin taşıdığı yetkileri kayıtlı listeyle karşılaştırır. Kayıtlı liste, ekibin bir kez kaydedip sonra doğrulukta ölçüt saydığı yetki listesidir; bu derste o liste kusurlu derlemeden kopyalanmıştır. İkincisi imzalı paketin etkin yetkilerinin uygulamanın istediği yetkileri kapsayıp kapsamadığına bakar. Üçüncüsü yalnız profilin uygulamanın istediği yetkilere izin verip vermediğine, dördüncüsü yalnız sertifikanın sayaç için geçerli olup olmadığına bakar.
// main.swift — dort denetim, uc ayrim
let counter = 3
let registered = ["anahtar-zinciri"]
let listed = contrast("kayitli-liste-esit", correct: correctPackage.entitlements.sorted(), faulty: faultyPackage.entitlements.sorted()) { $0 == registered }.describe()
let covered = contrast("etkin-yetkiler-kapsiyor", correct: effective(correctPackage, profile: shopProfile), faulty: effective(faultyPackage, profile: shopProfile)) { requested.isSubset(of: $0) }.describe()
let profileOnly = contrast("profil-kapsiyor", correct: shopProfile.allowed.sorted(), faulty: shopProfile.allowed.sorted()) { requested.isSubset(of: $0) }.describe()
let certificateOk = contrast("sertifika-gecerli", correct: shopCertificate.expiresAt, faulty: shopCertificate.expiresAt) { $0 > counter }.describe()
countSeparations([listed, covered, profileOnly, certificateOk])
kayitli-liste-esit | dogru=["anahtar-zinciri", "uzak-bildirim"]/kaldi kusurlu=["anahtar-zinciri"]/gecti -> ters etkin-yetkiler-kapsiyor | dogru=["anahtar-zinciri", "uzak-bildirim"]/gecti kusurlu=["anahtar-zinciri"]/kaldi -> ayiran profil-kapsiyor | dogru=["anahtar-zinciri", "uzak-bildirim"]/gecti kusurlu=["anahtar-zinciri", "uzak-bildirim"]/gecti -> kor sertifika-gecerli | dogru=5/gecti kusurlu=5/gecti -> kor ayiran: 1 kor: 2 gurultulu: 0 ters: 1
Dört satır, üç kategori. etkin-yetkiler-kapsiyor kusurun değiştirdiği değere bakar: kusurlu pakette uzak bildirim etkin yetkiler arasında yoktur, denetim kalır; doğru pakette vardır, denetim geçer. Bu ayıran denetimdir. profil-kapsiyor ve sertifika-gecerli ise iki sürümde de aynı değeri görür, çünkü kusur profile de sertifikaya da dokunmaz. İki satırda da kusurlu tarafı gecti der; bu iki kör denetim yeşil bir imza hattında sık görülen güveni verir ve kusur hakkında hiçbir şey söylemez.
Eşitlik Denetiminin Tersliği
İlk satır ilginç olandır. kayitli-liste-esit doğru paketi reddeder ve kusurlu paketi kabul eder: dogru=…/kaldi, kusurlu=…/gecti, sonuç ters. Denetim kusurlu değildir; sorun beklenen değerin kaynağıdır. Kayıtlı liste kusurlu derlemeden kopyalandığı için eksik yetkiyi “doğru” saymıştır. Sonradan yetkiyi ekleyen ekip, denetimin kırmızıya döndüğünü görür ve çoğu zaman listeyi paketle birlikte günceller. Kusur o andan sonra denetimin kendisine yerleşmiş olur.
Bu, eşitlik denetimine özgü bir tuzaktır: denetim beklenen değeri bir sürümden alıyorsa, o sürümün kusurunu da alır. Eşitlik denetimi bir beklentiyi korur, ama beklentinin doğru olup olmadığını söylemez. Ayıran denetim bunu başka bir yoldan çözer. etkin-yetkiler-kapsiyor beklenen değeri hiçbir derlemeden almaz; uygulamanın istediği yetkileri kendi kaynağından, yani uygulamanın koduyla birlikte tutulan istek listesinden okur.
Kayıtlı listeyle eşitlik denetimi hiçbir işe yaramaz demek de yanlıştır. Yetkilerin sessizce artıp artmadığını yakalamak için iyi bir yoldur: kayıt doğru alındıysa fazladan yetki eklenen bir paket kalır. Bu derste ölçülen şey başka bir kusurdur, eksik yetki. Ayrım tek bir kusura göre ölçülür; aynı denetim başka bir kusura karşı başka bir kategoriye düşebilir.
DG2. Bu ölçüm profilin yetkilerinin paketin yetkilerini kapsadığında imzanın kabul edildiğini varsayar. Profilde fazladan yetki bulunmasının gerçek imza aracını nasıl etkilediği ölçülmedi.
Kör Denetimin Rahatlığı
Sertifika ve profil denetimleri neden bu kadar yaygındır? Çünkü başarısızlıkları gürültülüdür ve ekibi hemen uyarır. Süresi dolan bir sertifika paketi imzalatmaz, profili olmayan bir paket aygıta yüklenmez. Bu yüzden bu denetimler hattın başında durur ve her gün geçerek ekibe alışkanlık kazandırır. Ama yüzlerce kez yeşil olmuş bir denetim, doğru sürümle kusurlu sürüm arasında bir fark gördüğünü göstermez. İki sürüm aynı sertifikayla imzalanır ve aynı profile bağlanır; kor bu yüzden kaçınılmazdır.
Çıkarım şudur: kör bir denetimi silmek gerekmez, çünkü başka bir kusuru yakalar. Gerekli olan, onu kusuru yakalayan denetim sayıp saymadığını bilmektir. Hattın yeşil çıktısı üç kör denetim ve bir ayıran denetimden oluşuyorsa, kusur ayırandan geçmediği sürece görünmez. Pratikte bu, hat raporuna yalnız geçen denetimlerin sayısını değil, her denetimin hangi kusuru görebildiğini de yazmak demektir; sayı yüksek olabilir ve ayıran denetimlerin payı sıfıra yakın kalabilir.
Yeni Bir Denetimi Bozma Denemesiyle Sınamak
İmza hattına yeni bir denetim eklenirken sorulacak ilk soru “bu denetim bugün geçiyor mu” olmamalıdır. Bugün geçmesi yeşil bir hat verir ve bu hiçbir şey kanıtlamaz. Doğru soru şudur: paketi bilerek bozsam bu denetim kalır mı? Bu yönteme bozma denemesi denir. Burada bozma, kasıtlı olarak bir yetkiyi paketten çıkarmaktır; denetim o paketi reddetmiyorsa kördür ya da tersidir.
Dersin ölçümü bozma denemesinin küçük bir hâlidir: kusurlu paket, doğru paketten tek bir yetkinin çıkarılmasıyla elde edilmiştir ve dört denetim ona uygulanmıştır. Fark şu: bozma denemesi yalnız “yakalandı mı” diye sorar. Bu kurs doğru sürümün yanıtına da bakar, çünkü doğru paketi reddeden bir denetim, yakalama başarısı ne olursa olsun, ekibi her seferinde yanlış bir kırmızıyla meşgul eder. Gürültülü ile ters ancak iki sürümün yanıtı yan yana konunca ayrılır.
| Denetim | Neye bakar | Kusuru görür mü | Ayrım |
|---|---|---|---|
kayitli-liste-esit |
paketin yetkileri, kayıtlı liste | yalnız listenin doğru olduğu sürece | ters |
etkin-yetkiler-kapsiyor |
etkin yetkiler, uygulamanın istekleri | evet | ayıran |
profil-kapsiyor |
profil, uygulamanın istekleri | hayır | kör |
sertifika-gecerli |
sertifika, sayaç | hayır | kör |
Tablodaki üçüncü sütun bir sonucu değil, bir koşulu yazar. Birinci satırda kusuru görmek için kayıtlı listenin kusurlu derlemeden alınmamış olması gerekir. Bu koşul denetimin kendi içinde yoktur; listenin nereden geldiği denetimin dışında kalır ve yalnız onu yazan kişi bilir.
Kayıtlı Listeyi Düzeltmek
Terslik bulununca iki yol vardır. Birincisi listeyi doğru pakete göre yeniden kaydetmektir. Bu, denetimi bir sonraki kusura kadar doğru yapar, ama listeyi yine bir derlemeden almış olur; yeni derlemede bir yetki sessizce kaybolursa terslik geri döner. İkincisi beklenen değeri paketin dışından, uygulamanın istek listesinden türetmektir: etkin-yetkiler-kapsiyorun yaptığı budur. İkinci yol kayıt yenileme işini ortadan kaldırır, çünkü beklenen değer her seferinde uygulamanın kendisinden gelir.
İki yol bir arada da kurulabilir. İstek listesinden türeyen denetim eksik yetkiyi yakalar, kayıtlı listeyle eşitlik denetimi ise fazladan yetkiyi. İkisi farklı kusurlara bakar ve ders bu ikisini rakip değil, tamamlayıcı sayar.
Sınırlayıcı Ölçüm
Ayrım denetimin tek başına özelliği değildir; kusura ve girdiye göre değişir. Aşağıdaki ölçümde tek bir denetim, sign kararının imzali olması, üç girdiye uygulanır. Sayaç 3 iken sertifika da profil de geçerlidir ve iki paket de imzalanır. Sayaç 9 iken sertifika dolmuştur ve iki paket de reddedilir. Üçüncü girdide profil dar tutulmuştur ve yalnız anahtar-zinciri yetkisine izin verir: imzası eşleşmeyen yetki modelde de reddedilir, yani uzak bildirim taşıyan doğru paket reddedilir.
// main.swift — ayni imza denetimi uc girdide uc ayrim verir
let narrowProfile = Profile(identifier: "com.example.shop", allowed: ["anahtar-zinciri"], expiresAt: 8)
let early = contrast("sayac-3",
correct: sign(correctPackage, profile: shopProfile, certificate: shopCertificate, counter: 3),
faulty: sign(faultyPackage, profile: shopProfile, certificate: shopCertificate, counter: 3)) { $0 == "imzali" }.describe()
let late = contrast("sayac-9",
correct: sign(correctPackage, profile: shopProfile, certificate: shopCertificate, counter: 9),
faulty: sign(faultyPackage, profile: shopProfile, certificate: shopCertificate, counter: 9)) { $0 == "imzali" }.describe()
let narrow = contrast("dar-profil",
correct: sign(correctPackage, profile: narrowProfile, certificate: shopCertificate, counter: 3),
faulty: sign(faultyPackage, profile: narrowProfile, certificate: shopCertificate, counter: 3)) { $0 == "imzali" }.describe()
countSeparations([early, late, narrow])
sayac-3 | dogru=imzali/gecti kusurlu=imzali/gecti -> kor sayac-9 | dogru=red:sertifika/kaldi kusurlu=red:sertifika/kaldi -> gurultulu dar-profil | dogru=red:yetki/kaldi kusurlu=imzali/gecti -> ters ayiran: 0 kor: 1 gurultulu: 1 ters: 1
Aynı denetim, üç girdi, üç kategori. sayac-3te kusurlu paket de imzalanır; imza hattı yeşildir ve kusur geçer, kör. sayac-9da süre dolmuştur, iki paket de red:sertifika alır ve denetim iki sürümde de kalır, gürültülü: kalma nedeni kusur değil sertifikadır. dar-profilde ise doğru paket red:yetki ile reddedilir, çünkü uzak bildirim profilde yoktur; kusurlu paket tam profilin izin verdiği tek yetkiyi taşıdığı için imzali alır, ters. Gerçek hayatta da bir profil yetkiyi içermiyorsa doğru paket imzalanamaz; eksik yetkiyle çalışan kusurlu paket bu engele hiç takılmaz.
Bu ölçüm bir sınırı da gösterir. Üç girdide de imzali denetimi ayıran çıkmadı: bu denetim tek başına bu kusuru ayıramaz, çünkü imza kararı yalnız paketin profile uyup uymadığını söyler, uygulamanın neye ihtiyaç duyduğunu söylemez. Uygulamanın ihtiyacı requested kümesindedir ve onu okuyan tek denetim etkin-yetkiler-kapsiyordur.
DG3. Bu ölçüm imza kararının sırasını modelin sırasıyla verir: önce sertifika, sonra profil, kimlik ve yetki. Gerçek imza aracının hangi eşleşmeyi önce kontrol ettiği ölçülmedi.
Özet
- Sertifika kimin imzaladığını, sağlama profili hangi paket kimliğinin hangi yetkilerle çalışacağını, yetkilendirme dosyası paketin ne istediğini söyler; imzalama bu üçünün tutarlılığına bakar.
- Paketin yetkilerini kayıtlı listeyle karşılaştıran denetim, liste kusurlu derlemeden alındıysa doğru paketi reddeder ve kusurlu paketi geçirir: ters.
- Etkin yetkilerin uygulamanın istediklerini kapsayıp kapsamadığına bakan denetim, kusurlu paketi ayırır: ayıran.
- Yalnız sertifikaya ya da yalnız profile bakan denetimler iki sürümde de geçer: kör.
- Aynı imza denetimi sayaca ve profile göre kör, gürültülü ya da ters olabilir; ayrım denetimin değil, denetimle girdinin ortak özelliğidir.
- Bu dersin ayrımı: ters.
Sonraki Adım
İmzalanabilen bir paket hâlâ yanlış hesap yapabilir; imza kararı hesabı doğrulamaz. Sıradaki derste, Sürekli Tümleştirme, bu denetimlerin bir hat içinde art arda koştuğu ve hattın ilk kalan adımda durduğu ölçülecek.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.