2010-02-14 8 views
7

ho appologise in anticipo per la lunghezza di questo post ....Memorizzazione credenziali di Amazon S3 in .bashrc variabili Environemental provoca applicazione Rails a fallire

Sto sviluppando un'applicazione che utilizza rais graffetta per memorizzare roba su Amazon S3. L'app è ospitata su Heroku. Sto sviluppando su Ubuntu Karmic.

Il problema che sto per descrivere si verifica in fase di sviluppo (sul mio localhost) e produzione (su Heroku).


Il metodo standard di passare creds S3 di graffetta è mettendoli in config/s3.yml in questo modo:

access_key_id: 12345678 
secret_access_key: 903490409fdf09fshsfdoif/43432 

Quando faccio questo, tutto funziona bene. Ma questo rende difficile condividere il mio codice con altri, quindi Heroku suggerisce un metodo alternativo - http://docs.heroku.com/config-vars.

consigliano che si dovrebbe mettere il S3_KEY e S3_SECRET nel vostro .bashrc in questo modo:

S3_KEY=12345678 
export S3_KEY 
S3_SECRET=903490409fdf09fshsfdoif/43432 
export S3_SECRET 

Hanno poi suggeriscono di creare config/inizializzatori/s3.yml (nota del percorso leggermente diverso) e mettere il seguente in quel file:

AWS::S3::Base.establish_connection!(
    :access_key_id  => ENV['S3_KEY'], 
    :secret_access_key => ENV['S3_SECRET'] 
) 

ma quando faccio questo, graffetta getta un disco oscillante e sputa fuori il seguente messaggio di errore:

undefined method `stringify_keys' for #<String:0xb6d6c3f4> 

/vendor/plugins/paperclip/lib/paperclip/storage.rb:176:in `parse_credentials' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:138:in `extended' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `instance_eval' 
/vendor/plugins/paperclip/lib/paperclip/storage.rb:137:in `extended' 

.... other stuff 

Così chiaramente tutto sta iniziando nel modulo storage.rb. Facendo un passo attraverso l'analisi dello stack:

Il metodo parse_credentials sulla linea 176 viene valutato - ecco la chiamata come appare nel codice:

def parse_credentials creds 
    creds = find_credentials(creds).stringify_keys 
    (creds[RAILS_ENV] || creds).symbolize_keys 
end 

Il metodo parse_credentials tenta di chiamare un altro metodo, find_credentials, e questo è dove credo che il problema risieda. Ecco il codice per find_credentials:

def find_credentials creds 
    case creds 
    when File 
     YAML::load(ERB.new(File.read(creds.path)).result) 
    when String 
     YAML::load(ERB.new(File.read(creds)).result) 
    when Hash 
     creds 
    else 
     raise ArgumentError, "Credentials are not a path, file, or hash." 
    end 
end 

non riesco a vedere come il metodo find_credentials è in grado di leggere i valori dal mio file .bashrc. Ha due casi in cui può leggere da YAML e uno in cui cerca un hash.

Il mio modello fa riferimento le credenziali in questo modo:

has_attached_file :photo, 
       (some code removed) 
       :s3_credentials => "#{RAILS_ROOT}/config/initializers/s3.yml", 

Se rimuovo il: s3_credentials hash dal modello, l'errore stringify_keys va via e la console rotaie lancia il messaggio di errore che appare alla fine del metodo find_credentials: ovvero "Le credenziali non sono un percorso, un file o un hash".

Quindi sono perplesso. Mi rendo conto che questa è probabilmente una domanda per i ragazzi di Heroku (che in realtà invierò a questo link per posta elettronica con la speranza che possano rispondere) ed è anche una domanda per i doods di thoughtbot, ma ho pensato che StackOverflow potrebbe essere il posto migliore per chiedere questo come è dimostrato di essere un forum abbastanza affidabile per me in passato.

Come ho detto all'inizio, la mia app funziona bene quando prendo l'approccio standard di attaccare la mia chiave e il segreto in config/s3.yml, ma preferirei usare il metodo suggerito da Heroku perché rende le cose WAY più facile per me e significa che posso memorizzare il mio repository sulla mia pagina Github pubblica affinché altri possano usarli senza dover scrivere alcun driver di unione dei clienti in Git per mantenere le mie chiavi API fuori dal pubblico dominio.

Ancora una volta, mi dispiace per il lungo post, e se sei arrivato fino a qui, ti applaudo. Qualcuno ha qualche idea?

Ho provato ad attaccare le variabili ENV in etc/bash.bashrc e ~/.bashrc e dopo il riavvio, ho ancora lo stesso problema. I problemi si verificano sulla macchina di sviluppo e su Heroku. Ho fatto in modo di spingere anche i miei config-vars a Heroku.

Sono stato a questo per 8 ore di fila !! Vado a guardare il calcio ora.

risposta

13

Dopo molte ricerche ho trovato la risposta qui - http://tammersaleh.com/posts/managing-heroku-environment-variables-for-local-development

Il trucco è quello di rimuovere il file del tutto il S3.rb e solo fare riferimento alle variabili ENV nel modello in questo modo:

has_attached_file :photo, 
        #... 
        :storage  => :s3, 
        :bucket   => ENV['S3_BUCKET'], 
        :s3_credentials => { :access_key_id  => ENV['S3_KEY'], 
             :secret_access_key => ENV['S3_SECRET'] } 

Comunque , David, grazie per il tuo suggerimento. Non so se si desidera aggiornare i documenti di Heroku per dire che alcuni utenti hanno dovuto farlo in questo modo. Grazie ancora però.

2

Rinominare il file config/initializers/s3.yml a config/initializers/s3.rb e provarlo.

+0

Penso che questo sia il motivo! – klew

+0

scusa gente, non funziona. stesso problema, stesso messaggio di errore. So che il file viene letto quando ottengo un errore di file non trovato se cambio il suo nome. So anche che le variabili ENV vengono lette mentre ottengo un'eccezione se cambio il nome della chiave in S3.rb. In ogni caso, non è la fine del mondo e penso che passerò da qui e lascerò stare. Significa solo che dovrò stare molto attento quando metto le cose su GitHub ma posso conviverci. Grazie per l'aiuto. Se lo faccio funzionare, te lo farò sapere. Anche – stephenmurdoch

+0

- puts ENV ['S3_KEY'] dalla console di rails funziona bene - quindi penso che potrebbe essere solo un problema di graffetta - grazie comunque – stephenmurdoch

1

Ecco il problema:

:bucket   => ENV['S3_BUCKET'], 

deve essere

:bucket   => <%= ENV['S3_BUCKET'] %>, 

cioè le assegnazioni non vengono interpretati.