R'da Paket Kurulumu

R’a eklenti olarak paket kurmak oldukça kolay. Öncelikle ihtiyacınız olan analizlere ilişkin paketleri R’ın sitesinden bulabilirsiniz:

http://cran.ncc.metu.edu.tr/web/packages/available_packages_by_date.html

Örneğin benim analiz etmek istediğim interrater reliability olduğu için Kappa analizine yönelik paketlere ihtiyaç duyuyorum. Sayfada CTRL+F ile arama yaparak kendinize uygun paketler bulabilirsiniz. Toplamda 5 tane paket kuracağım ve kuracağım paketler şunlar:

  1. ICC: Facilitating Estimation of the Intraclass Correlation Coefficient
  2. KappaV: Calculates “vectorial Kappa”, an index of congruence between patchy mosaics
  3. irr: Various Coefficients of Interrater Reliability and Agreement
  4. raters: A Modification of Fleiss’ Kappa in Case of Nominal and Ordinal Variables
  5. KappaGUI: GUI for Cohen’s and Fleiss’ Kappa

Paket isimleri şu şekilde: ICC, KappaV, irr, raters ve KappaGUI.

Gelelim kuruluma. R konsolunu açtıktan sonra “install.packages” komutu ile paketleri kurabiliyorsunuz. “install.packages” fonksiyonu R’da ki diğer fonksiyonlar gibi vektör kabul ediyor. Yani bu fonksiyon içerisinde birden çok paketin kurulmasını söyleyebilirsiniz. Örneğin tek bir paket:

veya birden çok paket:

Bazı paketler uzun zamandır güncellenmediği için kullandığınız R sürümüyle uyumlu olmayabilirler. Bu durumda şöyle bir hata mesajı alırsınız:

Ek olarak R paketlerinin dependency olarak tanımlanmış paketleri de otomatik kurduğunu belirteyim. Yani örneğin irr’yi kullanabilmek için ICC’ye ihtiyaç duyuluyorsa R bunu da otomatik olarak kuracaktır.

Her şey yolunda gittiyse paketleriniz kurulmuş olmalı. R’da kurmuş olduğunuz paketleri kullanabilmek için ise mevcut oturumda o paketleri çağırmanız da gerekmekte. Bunu da şu şekilde yapabilirsiniz:

Herhangi bir paketi mevcut oturumdan kaldırmak içini ise detach komutu kullanılıyor:

Kolaylıklar.

İki Veri Arasında ki Benzerliğin Hesaplanması – Ruby

Bir RoR projesinde, iki farklı veritabanında bulunan ad-soyad ve kimlik numarası verilerinin birbirlerine ne kadar benzediğinin hesaplanması ve farklı veri setlerinin birbiriyle aynı olma olasılığının tespiti gibi bir ihtiyacım olmuştu.

Örneğin aşağıda ki iki veri birbirine ne kadar benziyor, bu kişiler gerçekten aynı kişiler olabilir mi hesaplamam gerekiyordu:

Bu hesaplamayı yapabilmek için Elasticsearch ve Ruby’nin marifetleri yeterli oldu. Elasticsearch’ün Ruby için sağladığı “records.each_with_hit” metodu ile herhangi iki veri birbirlerine ne kadar benziyor (yakınsıyor) kontrol edebilir ve benzerlik oranını 0-2 aralığında matematiksel olarak alabilirsiniz.

Örnek betik şu şekilde:

Betikte bulunan “1.2” değeri, tamamen benim istediğim yakınlık derecesini ifade etmekte. Daha yüksek yakınlığa sahip verileri tespit etmek için bu değeri arttırabilir, daha geniş bir aralık almak için azaltabilirsiniz. Betik çalıştıktan sonra şöyle bir çıktı veriyor:

Kolaylıklar.

Ruby on Rails ve Güvenlik – CSRF ve API Talepleri

CSRF ve Authenticity Token

Rails’te herhangi bir formdan POST request yaparken authenticity_token parametresi de gönderilmekte. Bu parametre CSRF saldırılarına karşı Rails’in kullandığı default savunma mekanizmasının bileşenlerinden biri. Aşağıda POST işlemi yapan örnek bir form bulunuyor, hidden field olarak authenticity_token gönderildiğini görebilirsiniz.

İşin hikayesi ise şöyle; Rails POST request’leri için user’ın session bilgisini temel alarak rastgele bir hash oluşturup bunu form içerisinde hidden field olarak ekliyor ve request esnasında gönderiyor. Oluşturulan token form submit edildiğinde diğer parametrelerle birlikte gönderiliyor ve web uygulaması tarafından işleniyor.

POST request’in akabinde web sunucumuz gönderilen token ile mevcut kullanıcının session bilgisini kıyaslıyor ve eşleşmeyen bir durum bulunduğunda bunu saldırı olarak kabul ediyor. Eğer Rails’in default davranışını değiştirmediyseniz request’in hataya düşmesi gerekiyor. Aşağıda POST işlemi yapan bir form görebilirsiniz. Henüz token’ı kurcalamadık.

POST işlemi yapan form
POST işlemi yapan form

Session’a erişme şansı olmayan bir saldırgan gibi davranıp token’ı değiştirelim ve neler olduğunu inceleyelim (Token’ın son 2 karakteri olan “==” karakterlerini “??” olarak değiştirdim):

Parametreleri değiştirilmiş form.
Parametreleri değiştirilmiş form.

Sonuç olarak beklendiği üzere uygulama exception’a düştü ve hata verdi =>

Rails CSRF protection

Uygulamanın bu davranışı göstermesini sağlayan ise application_controller’da bulunan “protect_from_forgery” metodu.

Kod aslında yaptığı işi açıkça söylüyor. Diğer bir yandan da API’lar için null_session kullanmamızı öneriyor. Eğer uygulamanız içerisinde bir API barındıracaksanız protect_from_forgery with: :exception yaptığınız request’leri hataya düşürecek çünkü Rails authenticity_token’ı sizin request’iniz içerisine eklemeyecek. Deneyelim:

Konfigürasyon: 

API Request:

API Request Sonucu:

with: :exception ile uygulamayı hataya düşürme davranışına alternatif olarak reset_session ve null_session seçeneklerini de kullanabilirsiniz:

  • :reset_session – Oturumu sıfırlar.
  • :null_session – Request esnasında yeni boş bir oturum sağlar ancak mevcut oturumu sıfırlamaz.

Detaylardan bir kaç ilginç nokta:

  1. Yeni bir Rails uygulaması oluşturduğunuzda “protect_from_forgery” metodu with: :exception ayarlı olarak geliyor.
  2. Rails 4’te => “protect_from_forgery” metodunu tek başına çağırdığınızda default davranışı “reset_session” şeklinde. Bknz: source.
  3. Rails 3’te => “protect_from_forgery” metodunu tek başına çağırdığınızda default davranışı “null_session” şeklinde.

GET mi – POST mu?

protect_from_forgery metodu sadece POST metodu için çalışmakta. Diğer bir değişle GET request’i için CSRF koruması uygulanmıyor. Bu durum Rails kaynak kodu içerisinde şu şekilde ifade ediliyor:

“GET requests are not protected since they don’t have side effects like writing to the database and don’t leak sensitive information.”

Sonuç olarak GET request’lerine hassas bilgiler döndürmemek ve GET request’lerinden gelen parametreleri veritabanına yazmamak önem taşıyor. Eğer hatalı bir kurgu izlemiş ve veritabanı ile olan ilişkilerinizi GET üzerine kurmuşsanız öncelikle bu hatalı kurguyu değiştirmeniz gerekiyor.

API Uygulamaları ve CSRF

Web uygulamanız içerisinde API sunma niyetindeyseniz yukarıda bahsettiğim şekilde “with: :exception” API request’lerinizi hataya düşürecektir çünkü browser üzerinden yapılmayan request’lerde Rails authenticity_token parametresini request’e ekleyemeyecek. O halde hem API  request’lerini hemde normal uygulama request’lerini aynı anda nasıl güvende tutacağız?

1) JSON request’lerini protect_from_forgery’den muaf tut

Request =>

Response =>

Response içerisinde CSRF token’ın doğrulanamadığını söylüyor ancak :exception çalıştırmadığımız için ve default davranış “reset_session” olduğu için API requestimiz başarıyla çalışıyor ve yanıtını alıyor. Bu uyarı sadece loglanıyor ve client’ın sorgularına engel olmuyor. Diğer bir yandan form üzerinden POST yaparken token’ı değiştirirsek uygulama session’ı sıfırlayacak ve POST request’imiz iptal edilecek.

Request =>

Response =>

Bir önce ki POST request ile bu POST request arasında fark, ilk request’in /query yoluna yapılmış, ikinci request’in ise /query.json yoluna yapılmış olması. Dolayısıyla request bir JSON isteği olduğu için uygulama artık loglara token doğrulanamadı hatasıda basmıyor.

Dezavantaj => Eğer  :exception kullanmak istiyorsanız /query yolunun default davranışından fedakarlık etmeniz gerekecek çünkü uygulama bu yolda hata verecek.

Sonuç olarak vardığım en sağlıklı sonuç şu konfigürasyon ile oldu =>

2) API controller’larını protect_from_forgery’den muaf tut

Eğer API request’lerini idare eden controller sadece JSON sunuyorsa callback’lerden faydalanabiliriz. Eğer controller hem bir template render ediyor hemde JSON sunuyorsa CSRF korumasını kapatmak güvenlik zaafiyetine yol açacaktır.

Sadece index action’unu muaf tut =>

Controller’ı muaf tut =>

Diğer detaylar için metodun kaynak kodunu okuyabilirsiniz:

https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/request_forgery_protection.rb

 

Ruby on Rails ve Güvenlik – Routes

Rails uygulamalarında route’ların güvenliğini sağlarken Devise gibi authentication GEM’lerinin sağladığı helper’lardan ve lambda metodundan yararlanabilirsiniz. Örneğin sadece super_admin rolüne sahip kullanıcılara açık olmasını istediğiniz route’ları şu şekilde tanımlayabilirsiniz:

Artık admin/resque, admin/ip_lists ve admin/token_users yolları sadece super_admin’ler için erişilebilir olacak.

Model tarafında ise is_super_admin? metodunu şu şekilde tanımlı:

Selamlar.

ElasticSearch HQ Eklentisi Kurulumu

Elasticsearch plugin’lerinin kurulacağı yer:

HQ eklentisini kurmak için:

Eklentiye ulaşmak ve çalıştırmak için:

ElasticSearch Temel Bilgiler

Temel Bilgiler

Cluster

Cluster verilerin tümünün tutan bir yada birden çok node’un (server’ın) kümelenmiş halidir. Cluster’lar eşsiz isimlere sahiptir ve default isimleri “elasticsearch”tür. Bu isim önemli çünkü bir node sadece – isimle belirlenmiş olan, katılmasının mümkün olduğu cluster’a katılabilir. Production’da özel bir isim koymak faydalı olacaktır. Ayrıca içerisinde tek bir node bulunan bir cluster kullanmanın da herhangi bir sakıncası olmadığı gibi, her biri eşsiz isimlere sahip birden çok cluster’da kullanılabilir.

Node

Node, bir cluster’ın parçası olan tek bir server’dır. Node’lar verileri tutar ve cluster’ın indexleme ve arama becerilerine katkıda bulunur. Aynı cluster’lar gibi node’larda isimlere sahiptir (rastgele bir Marvel karakterinin adı) ve bu isim node başlatıldığı anda atanır. İsteğe bağlı olarak node’ların isimleri değiştirilebilmektedir. Bu sayede, mantıklı isimler vererek hangi node’un hangi cluster’da olduğu anlaşılabilir.

Bir node cluster ismi ile, belirlenmiş özel bir cluster’a katılmak üzere konfigüre edilebilir. Default olarak her node oluşturulduğu anda, “elasticsearch” ismindeki cluster’a katılma davranışı gösterir. Tek bir cluster içerisinde istenilen miktarda node oluşturulabilir. Eğer networkte çalışan başka bir node yoksa, bir node oluşturulduğunda aynı zamanda “elasticsearch” isminde bir cluster oluşturur.

Index

Bir index benzer özelliklere sahip belgeler topluluğudur. Örneğin müşteri bilgilerinin tutulduğu, ürünlerin tutulduğu, siparişlerin tutulduğu ayrı ayrı index’ler olabilir. Index’ler tümü küçük harften oluşan isimler ile tanımlanır.

Type

Bir index içerisinde bir veya birden çok type tanımlanabilir. Type – herhangi bir index içerisinde ki mantıksal bir kategori/partition’ı temsil eden yapıdır. Örneğin bir blog siteniz olduğunu var sayın, bu site için tanımladığınız index’te, ortak özelliklere sahip kullanıcı bilgilerini tutan bir type, gönderileri tutan bir type ve yorumları tutan bir type tanımlayabilirsiniz.

Document

Document indexlenebilir en küçük bilgi parçasıdır. Örneğin bir döküman tek bir müşterinin bilgileri, tek bir ürünün bilgileri veya tek bir siparişin bilgilerini tutabilir. Tüm dökümanlar JSON olarak tutulmaktadır. Herhangi bir index veya type içerisinde istenilen miktarda document tutulabilir. Bir döküman index’lenebilmesi için mutlaka index içerisinde ki bir type’a atanmış olmalıdır.

Shards & Replicas

Bir index, çok fazla veri barındırdığı zaman node’un donanımsal depolama limitlerini zorlayabilecek duruma gelebilir. Örneğin, içerisinde trilyonlarca document olan tek bir index düşünün ve bu index 1TB disk alanı kaplasın. Bu boyutta bir indexin diske sığmama olasılığı olduğu gibi, bu index’te tek bir node’dan gelen arama istekleride çok yavaş ceveplanabilecektir.

Bu sorunu çözmek için elasticsearch, bir index’i birden çok parçaya bölmemize olanak tanıyan “shards” yapısını kullanmakta. Bir index oluşturduğunuzda çok kolay bir şekilde kaç tane shard kullanmak istediğinizi tanımlayabilirsiniz. Her bir shard, bir index’in sahip olduğu tüm özelliklere sahip olan ve cluster’da ki herhangi bir node’da barındırılabilen tamamen bağımsız bir indexe sahiptir.

Sharding iki sebepten ötürü önemlidir:

  1. Yığının yatak olarak bölünebilmesini ve ölçeklenebilmesini sağlar.
  2. İşlemleri shard’lar üzerinde (muhtemelen farklı node’lar üzerinde ki) bölmenize ve paralel işlemler yürütmenize olanak tanıyarak performans artışı sağlar.

Shard mekanizması ve shardların nasıl dağıtık hale getirildiği tamamen elasticsearch tarafından yönetilen – ancak kullanıcı tarafından da görülebilen süreçlerdir.

Bir ağda veya bulut ortamında herhangi bir zamanda kesinti yaşanması mümkündür. Bu yüzden de, shard’ın veya node’un devre dışı kalmasına karşı mutlaka durumun üstesinden gelecek bir kurgu yapılmalıdır. Bu amaçla elasticsearch’te – index shard’larının bir veya birden çok kopyasının oluşturulabilmesini sağlayan replica shard (replika) yapısı bulunur. Replikalar iki sebepten dolayı önemlidir:

  1. Herhangi bir shard veya node erişilemez olduğunda yüksek erişilebilirlik sağlar. Bu yüzden de, replica shard’lar asla kopyası olduğu shard ile aynı node üzerinde bulunmamalıdır!
  2. Aramalar tüm replikalar üzerinde paralel bir şekilde yürütülebildiği için, hızlı ölçeklenebilir arama sağlar.

Özetlemek gerekirse, her bir index birden çok parçaya (shard) bölünebilir. Bir index ayrıca hiç replika edilmeyebilir ve istendiği kadar da replika edilebilir. Herhangi bir index replika edildiği zaman bir tane birincil shard’ı bir tanede replika shard’ı (birincilin kopyası) oluşur. Kaç tane shard kullanılacağı ve replikaların sayısı herhangi bir index oluşturulurken tanımlanabilir. İndex oluşturulduktan sonra ise replikaların sayısı dinamik olarak değiştirilebilirken, shard’ların sayısı değiştirilemez.

Default olarak elasticsearch’te ki bir bir index 5 tane birincil shard’a ve 1 tane replikaya sahiptir. Bu da, eğer cluster’ınızda 2 tane node’unuz varsa, indexinizin 5 tane birincil shard’ının ve 5 tanede replika (yani 1 tam replika) shard’ının – yani toplamda 10 shard’ınızın olacağı anlamına gelir.

Her bir shard bir Lucene indexidir ve bir Lucene indexinde en fazla 2.147.483.519 tane document bulunabilir. Shard’ların boyutları _cat/shards API’si ile kontrol edilebilir.


Kurulum

ElasticSearch en iyi performans için Oracle Java’ya ihtiyaç duymaktadır.

ile java sürümü ve Oracle mı yoksa OpenJDK mı olduğu kontrol edilebilir.

OracleJDK

Öncelikle sisteminde OpenJDK veya OracleJDK kurulu olmalıdır. Ubuntu’da güncel OpenJDK ile sorunsuz çalışmakla birlikte, Debian 7 sürümünde Oracle JDK kurulumu gerektirdi. Yine de OracleJDK kullanmakta fayda var.

Ubuntu’da OracleJDK kurulumu:

Ubuntu’da herşey yolundaysa “java -version” çıktısı şöyle birşey olacaktır:

  • Java8 environment variable’ları otomatik olarak SET etmek için şunu da kurun:

Elasticsearch deb paketi üzerinden kurulabilir. Kurmadan önce güncel dökümana bakınız:


Cluster İşlemleri

Cluster Sağlığı

Cluster’ın sağlık durumu curl ile (veya herhangi bir HTTP client ile) kontrol edilebilir.

Cluster Durumu

Cluster Stats

Node’ların Kontrolü

“elasticsearch” cluster olarak tüm network’te broadcast yaptığı için devel vb. makinalarda görünür durumda.

Indexlerin Kontrolü

Yeni Bir Index Oluşturma

Customer adında bir index oluşturalım ve “pretty” ekleyerek JSON yanıtının güzel görünmesini söyleyelim.

Yeni oluşan customer index’i şuan yellow durumda bunun sebebi ise bazı replikaların henüz ayrılmamış olması. Çünkü elasticsearch default olarak bu indexe bir tane replika oluşturdu ve şuan çalışan bir tane node’umuz var. Bu yüzden de bir replikamız, başka bir node eklenene kadar ayrılamıyor. Bu replika, başka bir node’a ayrılana kadar sarı durumda kalacak – başka node’a gittiği zaman ise durum yeşile dönecek.

Bir Dökümanı Indexe Ekleme

Customer index’imize “external” tipinde ve 1 ID’li herhangi bir döküman eklemek için:

Eğer bir döküman olmayan bir index’e eklenmeye çalışılırsa – o index otomatik olarak oluşturulur.

Bir dökümanı ayrıca ID belirtmeden de index’e ekleyebiliriz. Bu durumda elasticsearch o döküman için otomatik olarak ID oluşturur. Dikkat edilmesi gereken nokta, ID belirtildiğinde PUT, belirtilmediğinde POST kullanılmasıdır.

  • Dökümanı Index’e ID ile ekleme =>

  • Dökümanı Index’e ID’siz ekleme =>

Index’ten Dökümanı Görüntüleme

Bir Index’i Silme

Tüm Index’leri Silme

API Yapısı

Elasticsearch sorgularının tümü RESTful bir yapıya sahiptir. Aşağıda ki yapı kavrandığında tüm işlemlere uygulanabilir:

Dökümanların Yerini Değiştirme

Bir dökümanın yerini değiştirmek için, bir dökümanı index’e ekleme işlemi aynen yapılır.

Yukarıda ki komut ID’si 1 olan John Doe kaydını – Serhat Dundar kaydı ile yer değiştirir. Aynı Ruby’de ki hash mantığı gibi – ekleme ve değiştirme aynı şekilde yapılıyor.

Dökümanları Güncelleme

Ayrıca herhangi bir document’e başka bir alanda ekleyebiliriz:

Dökümanları Silme

Tek bir dökümanı silme:

Bir kriterle eşleşen bütün dökümanları silme:

Bir Node’u Kapatma

Shard’ları Kontrol Etme

Dynamic Allocation


Konfigürasyon

  • Bir paket nereye kurulmuş görmek için:
  • Elasticsearch konfigürasyonu muhtemelen şurada olacak:

Ubuntu 14.04 R Kurulumu

R programlama ortamını Ubuntu makinenize kurmak için öncelikle CRAN mirror listesinden kendinize uygun bir sunucu seçin. Ben Türkiye lokasyon olduğu için Pamukkale Üniversitesi sunucularını kullanacağım:

http://cran.pau.edu.tr/bin/linux/

R kurulumunu kolayca yapabilmek için PAÜ CRAN adresinin, kullandığınız Ubuntu sürümüne göre kaynak dosyasına eklenmesi gerekiyor. Benim sistemim 14.04 Trusty olduğu için bu sürüme yönelik adımları takip edeceğim. Öncelikle kaynak dosyasını (/etc/apt/sources.list.d/r-cran.list) oluşturalım ve PAÜ CRAN adresini ekleyelim:

Kaynağı ekledikten sonra Michael Rutter (marutter@gmail.com) tarafından E084DAB9 ID’si ile imzalanmış olan GPG anahtarını ekleyin:

Daha sonra kurulumu gerçekleştirebilirsiniz:

Herşey yolunda gittiyse R paketleri /usr/lib/R/library/ altına kurulmuş olmalıdır.

Konsolda büyük R ile R’ın çalışıp çalışmadığını kontrol edebilirsiniz:

Ubuntu için, Ubuntu Yazılım Merkezi’nden kurabileceğiniz 2 tane popüler görsel R arayüzüde bulunmakta. Bunlardan birisi RKWard, diğeri ise RStudio.

RStudio Kurulumu için: http://www.rstudio.com/products/rstudio/download/

RKWard Kurulumu için: Bknz. Ubuntu Yazılım Merkezi

Nano Konfigürasyonu ve Syntax Highlight

Öncelikle home dizininize syntax highlighter paketlerini indirin:

Home dizininize yoksa .nanorc dosyası oluşturun:

Tüm dilleri nanoya tanıtmak için:

Nano örnek konfigürasyon dosyasını şurada bulabilirsiniz:

Benim kullandığım config ise şu şekilde:

https://gist.github.com/msdundar/b753f94c80fcce1706aa

Passenger ve Nginx Konfigürasyonu

Önceki Yazılar:

Özenle hazırladığım, sorunsuz çalışan nginx konfigürasyonumu belki birileri göz atar diyerek paylaşıyorum. Yurtdışında pek çok sistem yöneticisi bu şekilde konfigürasyon dosyalarını birbirleri ile paylaşarak peer-review yapmaktalar. Bende bu review’ların pek çoğunu ve official nginx dökümanını okuyarak aşağıdaki konfigürasyonu hazırladım.

Konfigürasyon Debian 7.7 kurulu olan bir Rails sunucusu içindir. Web sunucu olarak Nginx + Passenger kullandım. Veritabanı sunucusu ise MySQL 14.14. Uygulama olarak Ruby 2.1.5 sürümü ve Rails 4.1.2 kurulu. Makinada 8 GB RAM bulunuyor ve 8 çekirdekli. Makina üzerinde sadece 1 tane Rails uygulaması koşuyor ve onunda VM boyutu 344mb. passenger-memory-stats çıktısı aşağıdaki şekilde:

passenger-memory-stats

/etc/nginx/nginx.conf dosyası:

Daha sonra:

/etc/nginx/sites-enabled/ klasörü içerisinde ais.conf isimli bir dosya oluşturun – içeriği şöyle olacak:

Nginx konfigürasyonunda hata varmı kontrol için:

Nginx'e Rails Uygulamasının Deploy Edilmesi

Phusion Passenger üzerinde bir Rails (veya herhangi bir Rack uygulaması) deploy edebilmek için uygulamanın bulunduğu dizinde üç dosyanın bulunması zorunludur:

  • config.ru dosyası
  • public/ klasörü
  • tmp/ klasörü

Yani /herhangi/bir/klasor/‘de bulunan Rack uygulamanızın minimum görünümü şu olmalıdır:

Uygulamanız çalışabilmesi için nginx konfigürasyon dosyanızı (/etc/nginx/nginx.conf) yapılandırmanız gereklidir:

Daha sonra nginx ve passenger’ı restart etmelisiniz:

En temel düzeyde bir Rails uygulaması bu şekilde deploy edilebilir. Uygulamanın kurulu için, bulunduğu dizine düşerek, aşağıdaki adımları takip edin.

Bundle et:

Uygulama config dosyasını düzenle:

Dosya izinlerini güncelle:

Uygulamayı kur:

Son olarak:

Hepsi bu kadar.