maxer

Condividi contenuti
Rantoli di un SysAdmin
Aggiornato: 45 min 52 sec fa

ActiveRecord: random

Gio, 11/04/2013 - 11:19

ActiveRecord non mette a disposizione uno strumento semplice per estrarre un insieme random di elementi. Normalmente si aggiunge alla query, nella clausola ‘order’ o RAND() o RANDOM() in base al database utilizzato. Questa soluzione non è molto pulita, quindi è preferibile utilizzare una gemma come randumb, che si occupa di inserire automaticamente la giusta funzione.

Una volta inserita nel file Gemfile e eseguita l’installazione con un

bundle install

sarà sufficiente appendere .random(x) alla nostra query, come da esempio:

Artist.random # un artista a caso Artist.random(3) # un array di artisti casuali Artist.random(1) # un array contenente solo un artista casuale
Categorie: planet

Rails: caricare i parametri da un file di configurazione yml

Gio, 04/04/2013 - 08:52

Per l’interfacciamento con un gateway di pagamento con carta di credito mi sono trovato a dover gestire credenziali diverse per l’ambiente di staging e di produzione. Se il primo approccio, più semplice e immediato, è quello di inserire i dati nel codice, all’interno di un if che controlla in che ambiente strano, conviene fare le cose fatte bene e spostare i parametri in un file esterno, che verrà caricato all’avvio dell’applicazione.

Supponiamo di avere un file chiamato bank.yml posizionato all’interno della directory config/, con il seguente contenuto:

development: username: 478881 password: c8e79387bb3e signature: 2178614 staging: username: 4788c81 password: c8e7c9387bb3e signature: 217c8614 test: username: 478b881 password: c8eb79387bb3e signature: 21b78614 production: username: 47a8881 password: 8ea79387bb3e signature: 21a78614

come possiamo vedere, per ogni ambiente abbiamo una tripletta diversa, che verrà usata per gestire l’integrazione con la banca.

Ora creiamo un file, bank.rb, in config/initializers/ con il seguente contenuto:

module Bank CONFIG = YAML.load_file(Rails.root.join("config/bank.yml"))[Rails.env] USERNAME = CONFIG['username'] PASSWORD = CONFIG['password'] SIGNATURE = CONFIG['signature'] end

Riavviando la nostra applicazione avremo a disposizione le seguenti costanti: Bank::USERNAME, Bank::PASSWORD, Bank::SIGNATURE che conterranno i dati presenti nel nostro file di configurazione, filtrati per l’ambiente corrente.

La scelta di utilizzare un modulo per la gestione di questi parametri ci permette di evitare conflitti con altri elementi della nostra applicazione.

 

Categorie: planet

Monitorare da quale script php vengono inviate le e-mail

Mer, 03/04/2013 - 12:27

Quando un sito viene bucato e viene utilizzato per inviare tonnellate di email di spam, la prima cosa che si deve affrontare, oltre alla pulizia della coda di postfix, è l’individuazione del responsabile.

Le cose diventano difficili quando su un server sono presenti decine e decine di siti, in quanto il file colpevole dell’invio di spam non è facilmente identificabile.

Con questa piccola modifica si potrà avere un log più dettagliato delle e-mail provenienti dai vari siti, permettendoci di identificare il colpevole.

Per prima cosa creiamo due file col seguente contenuto

/usr/local/bin/sendmail-php #!/bin/sh logger -p mail.info sendmail-php: site=${HTTP_HOST}, client=${REMOTE_ADDR}, script=${SCRIPT_NAME}, filename=${SCRIPT_FILENAME}, docroot=${DOCUMENT_ROOT}, pwd=${PWD}, uid=${UID}, user=$(whoami) /usr/sbin/sendmail -t -i $* /var/www/tpl.php <?php putenv("PATH_INFO=". $_SERVER["PATH_INFO"]); putenv("SCRIPT_NAME=". $_SERVER["SCRIPT_NAME"]); putenv("SCRIPT_FILENAME=". $_SERVER["SCRIPT_FILENAME"]); putenv("REMOTE_ADDR=". $_SERVER["REMOTE_ADDR"]); putenv("HTTP_HOST=". $_SERVER["HTTP_HOST"]); ?>

Impostiamo i permessi:

chmod +x /usr/local/bin/phpsendmail chmod +rx /var/www/tpl.php

Ora non ci resta che modificare il file php.ini (in Debian si trova in /etc/php5/apache2/php.ini ) modificando/aggiungendo le seguenti righe:

sendmail_path = /usr/local/bin/sendmail-php -t -i auto_prepend_file = /var/www/tpl.php

Dopo aver riavviato apache, nel file mail.log, troveremo righe di questo tipo:

Mar 30 09:30:25 web1 logger: sendmail-php: site=www.xxxx.it, client=31.184.244.18, script=/includes/.cfwqkt.php, filename=/var/customers/webs/xxx/www/includes/.cfwqkt.php, docroot=/var/customers/webs/xxx/www/, pwd=/var/customers/webs/xxx/www/includes, uid=33, user=www-data

Che ci permetterà di individuare istantaneamente il colpevole

 

Fonti:

http://serverfault.com/questions/130069/find-the-php-script-thats-sending-mails

http://forum.directadmin.com/showthread.php?t=36311

Categorie: planet

Brakeman: Security Vulnerability per Ruby on Rails

Mar, 02/04/2013 - 11:47

Oggi parliamo di sicurezza: parliamo di Brakeman!

Brakeman è un Security Vulnerability Scanner per Ruby on Rails.

Dopo averlo installato con un

gem install brakeman

ed eventualmente aver fatto un rehash

rbenv rehash

disporremo del comando brakeman.

Eseguendolo all’interno della directory del proprio progetto in Rails ci verrà fornito l’output di una analisi di sicurezza e vulnerabilità della nostra applicazione.

Un esempio di output è il seguente:

$ brakeman Loading scanner... [Notice] Detected Rails 3 application Processing application in /Users/claudio/Progetti/xxxxx Processing configuration... [Notice] Escaping HTML by default Processing gems... Processing initializers... Processing libs... Processing routes... Processing templates... Processing data flow in templates... Processing models... Processing controllers... Processing data flow in controllers... Indexing call sites... Running checks in parallel... - CheckBasicAuth - CheckCrossSiteScripting - CheckContentTag - CheckDefaultRoutes - CheckDigestDoS - CheckEscapeFunction - CheckEvaluation - CheckExecute - CheckFileAccess - CheckFilterSkipping - CheckForgerySetting - CheckJRubyXML - CheckJSONParsing - CheckLinkTo - CheckLinkToHref - CheckMailTo - CheckMassAssignment - CheckModelAttributes - CheckModelSerialize - CheckNestedAttributes - CheckQuoteTableName - CheckRedirect - CheckRender - CheckResponseSplitting - CheckSafeBufferManipulation - CheckSanitizeMethods - CheckSelectTag - CheckSelectVulnerability - CheckSend - CheckSendFile - CheckSessionSettings - CheckSingleQuotes - CheckSkipBeforeFilter - CheckSQL - CheckStripTags - CheckSymbolDoS - CheckTranslateBug - CheckUnsafeReflection - CheckValidationRegex - CheckWithoutProtection - CheckYAMLLoad - CheckYAMLParsing Checks finished, collecting results... Generating report... +BRAKEMAN REPORT+ Application path: /Users/claudio/Progetti/xxxxxx Rails version: 3.2.8 Brakeman version: 1.9.4 Started at 2013-03-27 21:58:02 +0100 Duration: 4.805979 seconds Checks run: BasicAuth, ContentTag, CrossSiteScripting, DefaultRoutes, DigestDoS, EscapeFunction, Evaluation, Execute, FileAccess, FilterSkipping, ForgerySetting, JRubyXML, JSONParsing, LinkTo, LinkToHref, MailTo, MassAssignment, ModelAttributes, ModelSerialize, NestedAttributes, QuoteTableName, Redirect, Render, ResponseSplitting, SQL, SafeBufferManipulation, SanitizeMethods, SelectTag, SelectVulnerability, Send, SendFile, SessionSettings, SingleQuotes, SkipBeforeFilter, StripTags, SymbolDoS, TranslateBug, UnsafeReflection, ValidationRegex, WithoutProtection, YAMLLoad, YAMLParsing +SUMMARY+ +-------------------+---------+ | Scanned/Reported | Total | +-------------------+---------+ | Controllers | 19 | | Models | 22 | | Templates | 106 | | Errors | 0 | | Security Warnings | 22 (12) | +-------------------+---------+ +-----------------------+-------+ | Warning Type | Total | +-----------------------+-------+ | Attribute Restriction | 1 | | Default Routes | 1 | | Denial of Service | 1 | | Mass Assignment | 10 | | Redirect | 2 | | Remote Code Execution | 2 | | SQL Injection | 4 | | Session Setting | 1 | +-----------------------+-------+ +SECURITY WARNINGS+ +------------+---------------------------+---------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->> | Confidence | Class | Method | Warning Type | Message >> +------------+---------------------------+---------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->> | High | | | Default Routes | All public methods in controllers are available as actions in routes.rb near line 163 >> | High | ContactController | submit | Mass Assignment | Unprotected mass assignment near line 7: ContactRequest.new(+params[:contact_request]+) >> | High | CartController | add | Redirect | Possible unprotected redirect near line 24: redirect_to(+params[:last_url]+) >> | High | Mobile::ProductController | xxxxxxxxxxxx | Redirect | Possible unprotected redirect near line 28: redirect_to(+params[:back_url]+) >> | High | | | Remote Code Execution | json gem version 1.7.5 has a remote code vulnerablity: upgrade to 1.7.7 >> | High | | | Remote Code Execution | Rails 3.2.8 has a remote code execution vulnerability: upgrade to 3.2.11 or disable XML parsing >> | High | | | SQL Injection | All versions of Rails before 3.0.18, 3.1.9, and 3.2.10 contain a SQL Injection Vulnerability: CVE-2012-5664; Upgrade to 3.2.10, 3.1.9, 3.0.18 >> | High | | | SQL Injection | All versions of Rails before 3.0.19, 3.1.10, and 3.2.11 contain a SQL Injection Vulnerability: CVE-2013-0155; Upgrade to 3.2.11, 3.1.10, 3.0.19 >> | High | CartController | remove | SQL Injection | Possible SQL injection near line 36: CartLine.where(+params[:line_id]+) >> | High | Mobile::xxxxxxxxxxxx | index | SQL Injection | Possible SQL injection near line 10: Product.where("name LIKE '%#{+params[:name]+}%' AND published = ? ", true) >> | High | | | Session Setting | Session secret should not be included in version control near line 7 >> | Medium | | | Denial of Service | Rails 3.2.8 has a denial of service vulnerability in ActiveRecord: upgrade to 3.2.13 or patch >> | Weak | Article | xxxxxxxxxxxxxxxxxxxxxxxxxx | Mass Assignment | Unprotected mass assignment near line 39: Article.new(:code => ((local row)[0]), :title => ((local row)[1]), :sku => ((local row)[2]), :size => ((local row)[3]), :published =>> | Weak | CartController | add | Mass Assignment | Unprotected mass assignment near line 18: CartLine.create(:cart_id => ((Cart.find_by_customer_id(current_customer.id) or Cart.create(:customer_id => (current_customer.id), :d>> | Weak | CartController | checkout | Mass Assignment | Unprotected mass assignment near line 49: Order.create(:date => (DateTime.now), :customer_id => (current_customer.id), :total_items => 0, :total_price => 0, :note => (+params>> | Weak | CartController | checkout | Mass Assignment | Unprotected mass assignment near line 57: OrderLine.create(:order => (+Order.create(:date => (DateTime.now), :customer_id => (current_customer.id), :total_items => 0, :total_>> | Weak | Customer | Customer.xxxxxxxxxxxxxxxxxx | Mass Assignment | Unprotected mass assignment near line 27: Customer.create(:name => ((local row)[1]), :code => ((local row)[0]), :email => (("" or ((local row)[0] + "@maw.it"))), :agent => (+>> | Weak | xxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx | Mass Assignment | Unprotected mass assignment near line 20: CustomerDiscountCategory.create(:customer => (Customer.find_by_code((local row)[0])), :discount_category => ((DiscountCategory.find_>> | Weak | Mobile::CartController | add | Mass Assignment | Unprotected mass assignment near line 30: CartLine.create(:cart_id => ((Cart.find_by_customer_id(session[:customer_id]) or Cart.create(:customer_id => (session[:customer_id])>> | Weak | Mobile::CartController | checkout | Mass Assignment | Unprotected mass assignment near line 65: OrderLine.create(:order => (+Order.create(:date => (DateTime.now), :customer_id => (session[:customer_id]), :total_items => 0, :tota>> | Weak | xxxxxxxxxxxx | SpecialPrice.xxxxxxxxxxxxxxxxxx | Mass Assignment | Unprotected mass assignment near line 20: SpecialPrice.create(:customer => (Customer.find_by_code((local row)[0])), :product => (+Article.find_by_sku((local row)[1]).product+>> +------------+---------------------------+---------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->> Model Warnings: +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------->> | Confidence | Model | Warning >> +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------->> | High | Agent, Article, Browsable, Cart, CartLine, Category, Ckeditor::Asset, Ckeditor::AttachmentFile, Ckeditor::Picture, ContactRequest, Customer, CustomerDiscountCategory, DiscountCategory, News, Order, OrderLine, Page, Product, ProductAttachment, SpecialPrice, Word | Attribut>> +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------->>

Dopo una analisi dell’output capiamo cosa effettuare per migliorare la sicurezza del nostro applicativo.

E’ possibile anche generare report in vari formati, come in html o json:

brakeman -o output.html brakeman -o output.json

Per maggiori informazioni e opzioni consultate la pagina del progetto Brakeman

Categorie: planet

Rails + Kaminari + Jquery + Infinite Ajax Pagination

Sab, 30/03/2013 - 10:49

Jquery Infinite Ajax Scroll è un plugin per jQuery che permette di implementare l’infinite scroll.

Tramite una semplice configurazione è possibile integrarlo in modo semplice con Kaminari (la gemma più usata per la paginazione).

Assegnamo al div contenente i nostri elementi l’id ‘item-list’ e agli elementi la classe ‘item’, come da esempio:

<div id="item-list"> <div class="item"><!-- contenuto --></div> <div class="item"><!-- contenuto --></div> <div class="item"><!-- contenuto --></div> </div>

Dopo la chiusura del div con id ‘item-list’ posizioniamo il codice per il pager:

<%= paginate @items %>

Il codice per far funzionare “out-of-the-box” l’infinite scroll è:

<script type="text/javascript"> jQuery.ias({ container: '#item-list', item: '.box', pagination: '.pagination', next: '.next a', loader: '<img src="/img/loader.gif"/>', history: false, triggerPageThreshold: 100 }); </script>

Ricordiamoci, ovviamente, di includere il plugin nell’header

 

Categorie: planet

Ckeditor e Capistrano: preservare i file caricati

Ven, 29/03/2013 - 09:24

La gemma ckeditor permette di aggiungere in modo semplice il comodo editor wysiwyg ai propri form. Questa integrazione, inoltre, permette all’utente di usare paperclip per caricare i file da inserire direttamente nell’editor.

Tutto funziona bene fino a quando non ci si appoggia a capistrano per gestire le fasi di deploy. Ckeditor, infatti, configura paperclip per salvare i file in una directory all’infuori di public/system, directory che capistrano non preserva durante le operazioni di deploy.

Per ovviare a questo problema è necessario apportare delle modifiche alla configurazione creata durante l’installazione di ckeditor, e in particolare ai file:

app/models/ckeditor/attachment_file.rb
app/models/ckeditor/picture.rb

Modificandoli in:

app/models/ckeditor/attachment_file.rb

class Ckeditor::AttachmentFile < Ckeditor::Asset has_attached_file :data, :url => "/system/ckeditor_assets/attachments/:id/:filename", :path => ":rails_root/public/system/ckeditor_assets/attachments/:id/:filename" validates_attachment_size :data, :less_than => 100.megabytes validates_attachment_presence :data def url_thumb @url_thumb ||= Ckeditor::Utils.filethumb(filename) end end

app/models/ckeditor/picture.rb

class Ckeditor::Picture < Ckeditor::Asset has_attached_file :data, :url => "/system/ckeditor_assets/pictures/:id/:style_:basename.:extension", :path => ":rails_root/public/system/ckeditor_assets/pictures/:id/:style_:basename.:extension", :styles => { :content => '800>', :thumb => '118x100#' } validates_attachment_size :data, :less_than => 2.megabytes validates_attachment_presence :data def url_content url(:content) end end

con questa modifica i file verranno caricati all’interno della directory public/system, che verrà preservata da capistrano, evitando di farci perdere immaigni e file ad ogni cap deploy

Categorie: planet

Installare Ruby on Rails su Mac OS X Mountain Lion

Gio, 28/03/2013 - 10:30

L’installazione di tutto quello che serve per lo sviluppo in Ruby on Rails passo passo, visto che ogni volta devo andare a pescare documenti a destra e a manca

Step1: Installare XCode

Per prima cosa è necessario installare XCode. Una volta installato, bisogna installare i “Command Line Tools” aprendo XCode, andando in XCode -> Preferences -> Downloads e premendo il tasto “Install” a fianco di “Command Line Tools”.

Una volta scaricati possiamo andare avanti.

Step2: Installare Homebrew

Homebrew è un tool fantastico: permette di installare software utilissimo, soprattutto per chi sviluppa, con un comodo comando.

L’installazione avviene inserendo il seguente comando in un terminale:

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

Una volta terminata l’installazione possiamo controllare che tutto sia andato per il meglio e aggiornare l’elenco dei pacchetti disponibili:

brew doctor

brew update

Ora possiamo passare allo step3.

Step3: Installazione di Ruby

Homebrew ci permette, come dicevo, di installare in modo semplice rbenv e ruby-build:

brew install rbenv ruby-build

Terminata l’installazione, andiamo ad aggiungere le nuove variabili di ambiente tramite il seguente comando:

echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile

Una volta terminato il processo possiamo installare la versione di ruby che vogliamo, nel mio caso la  ”1.9.3-p392″:

rbenv install  1.9.3-p392

In alternativa è possibile ottenere l’elenco di tutte le versioni di ruby disponibili tramite il comando

rbenv install --list

Al termine dell’installazione è necessario aggiornare le hash e indicare al sistema quale versione utilizzare come predefinita:

rbenv rehash rbenv global 1.9.3-p392 Step4: Installare le gemme fondamentali

Per avere un sistemam funzionante procediamo all’installazione di:

gem install rails bundle rake

Ora siamo pronti a lavorare

 

Categorie: planet

lol_dba: trovare gli indici mancanti

Mer, 27/03/2013 - 09:15

Inizia una piccola serie di articoli dedicati al tuning delle applicazioni scritte in Ruby on Raisl.

In questo post parlo di lol_dba, una gemma che ha una funzione semplice quanto comoda: analizzare il codice, controllando i modelli e indicandoci gli indici mancanti. L’output che ci restituisce può essere il codice di una migrazione o una query sql per aggiungere gli indici al database.

Il funzionamento è semplice: dopo averla installata tramite il classico

gem install lol_dba

avremo a disposizione due comandi: lol_dba db:find_indexeslol_dba db:migrate_sql .

Entrambi hanno lo stesso fine, ma varia l’output prodotto: nel primo caso verrà prodotto il contenuto da mettere dentro una migrazione che andremo a generare, come consigliato dall’output del programma, tramite:

rails g migration AddMissingIndexes

nel primo caso verrà prodotta una query sql da eseguire sul database server.

 

Categorie: planet

Rubygem: evitare l’installazione della documentazione

Mar, 26/03/2013 - 18:38

Spesso l’installazione della documentazione delle varie gemme installate, oltre ad essere superflua occupa inutilmente spazio: la documentazione viene consultata via internet e quella presente sul sistema è ignorata. Per evitare la perdita di tempo dell’installazione/compilazione della documentazione è possibile disabilitarne l’installazione tramite il seguente comando:

echo 'gem: --no-rdoc --no-ri' >> ~/.gemrc
Categorie: planet

Localeapp: migliorare le performance

Lun, 25/03/2013 - 08:59

Localeapp.com è forse il sistema più comodo per internazionalizzare le proprie applicazioni scritte in Ruby on Rails. La configurazione di Default, però, rallenta spesso in modo estenuante le performance in fase di sviluppo: ad ogni pagina richiesta viene infatti fatta una richiesta ai server di localeapp per mandare le traduzioni mancanti e scaricare quelle nuove.

Sebbene la soluzione funzioni alla perfezione “out-of-the-box” genera delle attese che spesso sono snervanti.

La soluzione per migliorare questa situazione esiste e si può applicare così:

Disabilitiamo l’invio e la ricezione delle traduzioni ad ogni pagina, modificando il file config/initializers/localeapp.rb e aggiungendo, nel blocco, le seguenti righe:

config.sending_environments = [] config.polling_environments = []

In questo modo non verranno più inviate e ricevute le traduzioni in automatico.

Il lavoro di aggiornamento delle traduzioni, infatti, verrà demandato ad un demone che lanceremo col seguente comando:

$ localeapp daemon

che si occuperà di fare il fetch in automatico ad intervalli regolari.

 

Categorie: planet