Java'da Dinamik Kod Değerlendirme - Akıllı mı, Özensiz mi?


30

Uygulamam için Java'da esnek bir ACL çerçevesi oluşturmaya çalışıyorum.

Birçok ACL çerçevesi, bir kuralın sahip: eylem: kaynak biçiminde olduğu bir beyaz kural listesine dayanır . Örneğin,

  • "JOHN, FOOBAR-1 kaynağını görüntüleyebilir"
  • "MARY FOOBAR-1 kaynağını görüntüleyebilir"
  • "MARY FOOBAR-1 kaynağını DÜZENLEDİ"

Bu caziptir çünkü kurallar kolayca veritabanına serileştirilebilir / kalıcı hale getirilebilir. Ancak başvurumun karmaşık bir iş mantığı var. Örneğin,

  • "Bölüm 1’deki 5 yıldan fazla kıdeme sahip tüm kullanıcılar FOOBAR-1 kaynağını görebilir, yetkili değil"
  • "Bölüm 2'deki tüm kullanıcılar, tarih 15.05.2016 tarihinden sonraysa, FOOBAR-2 kaynağını görebilir, yetkili değil"

İlk düşünce üzerine, bunlar gibi sonsuz karmaşık kuralları kaldırabilecek bir veritabanı şeması tasarlamak bir kabus olurdu. Bu nedenle, derlenmiş uygulamaya bunları "pişirmem", her kullanıcı için değerlendirme yapmam ve daha sonra sahibini yaratmam gerekecek gibi görünüyor : değerlendirme sonucunda değerlendirme : kaynak kuralları. Mantığı derlenmiş uygulamaya yerleştirmekten kaçınmak istiyorum.

Bu yüzden, bir kuralı yüklem şeklinde göstermeyi düşünüyordum : action: resource , yüklemin bir kullanıcının izin verilip verilmeyeceğini belirleyen bir boolean ifade olduğu. Öngörü, Java'nın Rhino motoru tarafından değerlendirilebilecek bir JavaScript ifadesinin bir dizisi olacaktır. Örneğin,

  • return user.getDept() == 1 && user.seniority > 5;

Bunu yaparken, yüklemler veritabanına kolayca devam ettirilebilir.

Bu akıllıca mı? Bu özensiz mi? Bu numara mı? Bu aşırı mühendislik yapılmış mı? Bu güvenli midir (görünüşe göre, Java, Rhino motorunu sandbox yapabilir).


8
Bu iş kurallarını mantığı derlenen uygulamaya koymak yerine bir veritabanına zorlamaya çalışmanın faydası nedir?
Winston Ewert

6
@WinstonEWert Kuralların dışlanması, bir kuralın değiştirilmesi, eklenmesi veya kaldırılması durumunda uygulamanın yeniden derlenmesi ve yeniden dağıtılması gereğini ortadan kaldırır.
Twittopher


2
İlginç soru! Güvenliğe çok fazla odaklanmayan bir cevap görmek istiyorum, bunun yerine böyle bir çözümün bakımı, güvenilirliği ve kullanım kolaylığı konularında.
oliver

6
Bu , aslında kullanıcı tarafından yapılandırılabilen bir kural motoru olan Outlook e-posta kurallarına benzer .

Yanıtlar:


37

Dinamik verileri uygulama dilinizin bir tercümanına pipetlemek genellikle kötü bir fikirdir, çünkü veri bozulma olasılığını kötü amaçlı bir uygulama ele geçirme potansiyeline yükseltir. Başka bir deyişle, bir kod ekleme güvenlik açığı oluşturma yolundan çıkıyorsunuz .

Sorununuz bir kural motoru veya belki bir alana özgü dil (DSL) ile daha iyi çözülebilir . Bu kavramlara bakın, tekerleği yeniden icat etmeye gerek yok.


16
Fakat JavaScript burada DSL benzeri bir betik dili olarak kullanılmaz mı? Gerekli verileri (salt okunur) ayarladık, pasajı bir işleve sardık ve güvenli bir şekilde değerlendirdik. Kod bir boolean döndürmek dışında hiçbir şey yapamadığından, burada kötü amaçlı bir fırsat olmazdı.
amon

6
@Twittopher Bazı tahminleri değerlendirmek için bütün bir JavaScript motorunu sürüklemek hala 1) eksiksiz overkill, 2) riskli ve 3) hataya meyilli gibi görünüyor. Tipik bir örnek, kullandığınız ==yerine ===sizin örnekte. Tüm kuralların tartışmalı bir şekilde daima sona ermesi gerektiğinde, gerçekten turing eksiksizliği sağlamak ister misiniz ? Java ve JavaScript arasındaki tüm etkileşimlerin koşut olduğundan emin olmak için çemberlerin içine atlamak yerine, neden Kilian'ın önerdiği gibi basit bir çözümleyici ve tercüman yazmıyorsunuz? İhtiyaçlarınıza göre şekillendirmek ve güvenceye almak çok daha kolay olacaktır. ANTLR veya başka bir şey kullanın.
Doval

6
@Doval Küçük bir DSL yazmak tam olarak roket bilimi değildir ve basit bir dili 3 saatten 5 güne çıkarabilirim. Fakat bu, 1) eksiksiz overkill, 2) riskli ve 3) bana yatkın gibi görünüyor. Gerçekten tam bir mini dil yazmak ister misiniz? Bazı işletme kuralları beklenenden daha karmaşıksa ve tam özellikli bir dile ihtiyaç duyuyorsa ne olur? Burada İcat Edilmedi Sendromdan mı muzdaripsiniz? Tekerleği yeniden icat etmek yerine, neden mevcut bir dili kullanmıyorsun? Savaşta test edilmiş bir dili kullanmak çok daha kolay.
amon

14
@ amon Bu olduğunda, Killian'ın dediği gibi gerçek bir kural motoru (JavaScript değil) bulursunuz. Her iki yaklaşımın risklerini eşitlemek yanıltıcıdır. Turing-komple bir dil için bir tercüman sağlama çabalarınızı mahvetmek yalnızca bir ihmali alır; Bu bir çıkarma işlemidir. Kazara küçük bir DSL'yi tehlikeli hale getirmek çok daha zor; bu bir katkı işlemidir. Yapmanız muhtemel hata türü, sözdizimi ağacını yanlış yorumlamak ve ünite test edilebilir. Muhtemelen yanlışlıkla tercümana bir yetenek formatı sabit disk vermeyeceksiniz.
Doval

4
@amon: js yan etkileri olmayabilir pasajı bile, seçebilir değil bir boolean değer döndürmek:while (true) ;
Bergi

44

Bunu yaptım ve yapmamanı tavsiye ederim.

Yaptığım şey tüm iş mantığını Lua'da yazmaktı ve bu Lua komut dosyasını bir veritabanında sakladı. Uygulamam başladığında betiği yükleyip çalıştırırdı. Bu şekilde, uygulamamın iş mantığını yeni bir ikili dosya dağıtmadan güncelleyebilirim.

Her zaman, değişiklik yaparken ikili dosyayı güncellemem gerektiğine karar verdim. Bazı değişiklikler Lua senaryosundaydı, ancak her zaman yapılması gereken değişikliklerin bir listesini yapardım ve bu yüzden neredeyse her zaman ikili dosyada bazı değişiklikler ve Lua senaryosunda bazı değişiklikler yapmak zorunda kaldım. Her zaman ikili dosyaları dağıtmaktan kaçınabileceğim hayal gücüm, basitçe ortadan kalkmadı.

Çok daha faydalı bulduğum şey, ikili dosya dağıtımını kolaylaştırmaktı. Uygulamam başlangıçta güncellemeleri otomatik olarak kontrol eder, indirir ve herhangi bir güncellemeyi yükler. Bu nedenle, kullanıcılarım her zaman istediğim en son ikili dosyalarda yer alır. İkili dosyadaki değişiklik ile senaryolardaki değişiklik arasında neredeyse hiçbir fark yoktur. Tekrar yapsaydım, güncellemeyi kesintisiz hale getirmek için daha fazla çaba sarfederdim.


3

Veritabanının kod içermesini istemezdim. Ancak, veritabanının işlev adları içermesini sağlayarak ve sonra bunları çağırmak için yansıma kullanarak benzer bir şey yapabilirsiniz. Yeni bir koşul eklediğinizde, bunu kodunuza ve veritabanınıza eklemeniz gerekir, ancak oldukça karmaşık değerlendirmeler oluşturmak için bunlara iletilen koşulları ve parametreleri birleştirebilirsiniz.

Başka bir deyişle, bölümleri numaralandırdıysanız, bir UserDepartmentI's kontrolü ve TodayIsAs kontrolünden sonra bunları bir Departman = 2 ve Today> 03 / 15/2016'e sahip olmak için birleştirmek kolaydır. Öyleyse, izninizin bitiş tarihini alabilmeniz için bir TodayIsBefore kontrolü yaptırmak istiyorsanız, TodayIsBefore işlevini yazmanız gerekir.

Bunu kullanıcı izinleri için yapmadım, ancak veri doğrulama için yaptım, ancak çalışması gerekiyor.


2

XACML, gerçekten aradığınız çözümdür. Sadece erişim kontrolüne odaklanan bir tür kural motoru. OASIS tarafından tanımlanan bir standart olan XACML, üç bölümü tanımlar:

  • mimarlık
  • Politika dili (gerçekten istediğin şey bu)
  • Bir talep / cevap şeması (bir yetkilendirme kararını nasıl istersiniz).

Mimari aşağıdaki gibidir:

  • Politika Karar Noktası (PDP) mimarinin temel parçasıdır. Bilinen bir politika kümesine karşı gelen yetkilendirme isteklerini değerlendiren bileşendir
  • Politika Uygulama Noktası (PEP), uygulamanızı / API / hizmetinizi koruyan kod parçasıdır. PEP iş talebini durdurur, bir XACML yetkilendirme talebi oluşturur, PDP'ye gönderir, bir geri cevap alır ve cevabın içindeki kararı uygular.
  • Politika Bilgi Noktası (PIP), PDP'yi harici bir veri kaynağına, örneğin bir LDAP'ye, bir veritabanına veya bir web servisine bağlayabilen bileşendir. PEP bir istek gönderdiğinde işe yarar. Örneğin, "Alice, # 12 belgesini görebilir mi?" PDP, kullanıcının yaşını gerektiren bir politikaya sahiptir. PDP, PIP'e "bana Alice'in yaşını ver" diyecek ve daha sonra politikaları işleyebilecek.
  • Politika Yönetim Noktası (PAP), tüm XACML çözümünü yönettiğiniz yerdir (özellikleri tanımlama, politikaları yazma ve PDP'yi yapılandırma).

eXtensible Access Control Markup Language - XACML Mimarisi

İlk kullanım durumunuz şöyle görünüyor:

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

İkinci kullanım durumunuz:

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

Referansları kullanarak her iki kullanım durumunu da tek bir politikada birleştirebilirsiniz:

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

Ve bitti!

XACML ve ALFA ile ilgili daha fazla bilgiyi aşağıdaki adresten okuyabilirsiniz:


0

Burada gerçekten istediğiniz şey XACML . Neredeyse istediğini tam olarak verir. Tüm mimariyi tüm rollerin birbirinden tamamen ayrılmasıyla uygulamak zorunda değilsiniz ... yalnızca tek bir uygulamanız varsa, PDP ve PEP'i balana ile uygulamanıza entegre etmekten muhtemelen kurtulabilirsiniz ve PIP ne olursa olsun mevcut kullanıcı veritabanınız

Şimdi, uygulamanızın herhangi bir yerinde bir şey yetkilendirmeniz gerekir, kullanıcının, eylemin ve içeriğin bulunduğu bir XACML isteği oluşturursunuz ve XACML motoru, yazdığınız XACML ilke dosyalarını temel alarak karar verir. Bu ilke dosyaları veritabanında veya dosya sisteminde veya yapılandırmayı saklamak istediğiniz yerde saklanabilir. Axiomatics, ham XML'den okuması biraz daha kolay olan ALFA adlı XACML XML sunumuna ve ALFA politikalarından XACML XML oluşturmak için bir Eclipse eklentisine hoş bir alternatif sunar.


1
Bu soruyu soruyu nasıl cevaplıyor?
gnat

Özellikle harici olarak yapılandırılmış bir yetkilendirme sistemi uygulamaya çalışıyor. XACML, kendi özel kullanım durumunu çok iyi kapsayan, harici olarak yapılandırılmış bir yetkilendirme sistemine gitmeye hazırdır. Bunun daha genel dinamik kod yürütme sorusuna iyi bir cevap olmayabileceğini itiraf edeceğim, ancak bu onun özel sorusuna iyi bir çözüm.
gregsymons

0

Bunu şu anki şirketimde yaptık ve sonuçlardan çok memnunuz.

İfadelerimiz js olarak yazılmıştır ve kullanıcıların ElasticSearch'ü sorgulamaktan elde edebileceği sonuçları sınırlamak için bile kullanırız.

İşin püf noktası, karar vermek için yeterli bilginin mevcut olduğundan emin olmaktır, böylece kod değişiklikleri olmadan istediğiniz izinleri gerçekten yazabilirsiniz, ancak aynı zamanda hızlı şekilde tutarsınız.

İzinleri sisteme saldırmaya gerek duymayanlar tarafından yazıldığından kod enjeksiyon saldırıları konusunda endişeli değiliz. Aynısı while(true)örnek gibi DOS saldırıları için de geçerlidir . Sistem yöneticilerinin bunu yapmasına gerek yok, herkesin izinlerini kaldırabilirlerdi ...

Güncelleştirme:

XACML gibi bir şey bir kuruluş için merkezi bir kimlik doğrulama yönetimi noktası olarak daha iyi görünüyor. Kullanım durumumuz biraz da olsa müşterilerimiz tipik olarak bunların hepsini yürütecek bir BT departmanına sahip değiller. Kendi kendine yeten bir şeye ihtiyacımız vardı ancak mümkün olduğunca esnekliği korumaya çalıştık.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.