Armazenar credenciais do Amazon S3 em variáveis ​​ambientais .bashrc causa falha no aplicativo Rails

StackOverflow https://stackoverflow.com/questions/2260957

Pergunta

Estou desenvolvendo um aplicativo Rails que usa clipe de papel para armazenar coisas no Amazon S3.O aplicativo está hospedado no Heroku.Estou desenvolvendo no Ubuntu Karmic.

O problema que estou prestes a descrever ocorre no desenvolvimento (no meu host local) e na produção (no Heroku).


A maneira padrão de passar credenciais S3 para o clipe de papel é colocá-los em config/s3.yml assim:

access_key_id: 12345678
secret_access_key: 903490409fdf09fshsfdoif/43432

Quando faço isso, tudo funciona bem.Mas isso dificulta o compartilhamento do meu código com outras pessoas, então o Heroku sugere um método alternativo - http://docs.heroku.com/config-vars.

Eles aconselham que você coloque S3_KEY e S3_SECRET em seu .bashrc assim:

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

Eles então sugerem que você crie config/initializers/s3.yml (observe o caminho ligeiramente diferente) e coloque o seguinte nesse arquivo:

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

MAS, quando faço isso, o clipe de papel oscila e cospe a seguinte mensagem de erro:

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 

Claramente, tudo está começando dentro do módulo storage.rb.Percorrendo o rastreamento de pilha:

O método parse_credentials na linha 176 está sinalizado - aqui está a chamada conforme aparece no código:

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

O método parse_credentials tenta chamar outro método, find_credentials, e é aí que acredito que esteja o problema.Aqui está o código para 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

Não consigo ver como o método find_credentials está equipado para ler valores do meu arquivo .bashrc.Tem dois casos em que pode ler YAML e um em que procura um hash.

Meu modelo faz referência às credenciais da seguinte forma:

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

Se eu remover o hash :s3_credentials do modelo, o erro stringify_keys desaparece e o console rails lança a mensagem de erro que aparece no final do método find_credentials:ou seja"Credenciais não são um caminho, arquivo ou hash".

Então estou perplexo.Eu percebo que esta é possivelmente uma pergunta para o pessoal do Heroku (para quem vou enviar este link por e-mail na esperança de que eles possam respondê-la) e também é possivelmente uma pergunta para os doods do Thoughtbot.

Como eu disse no início, meu aplicativo funciona bem quando eu adoto a abordagem padrão de inserir minha chave e segredo em config/s3.yml, mas eu preferiria usar o método sugerido pelo Heroku porque torna as coisas MUITO mais fáceis para mim e isso significa que posso armazenar meu repositório em minha página pública do github para que outros possam usá-lo, sem precisar escrever nenhum driver de mesclagem de cliente no Git para manter minhas chaves de API fora do domínio público.

Tentei inserir as variáveis ​​ENV em etc/bash.bashrc e também em ~/.bashrc e após reiniciar, ainda tenho o mesmo problema.Os problemas ocorrem tanto na máquina de desenvolvimento quanto no Heroku.Certifiquei-me de enviar meus config-vars para o Heroku também.

Foi útil?

Solução

Depois de muito pesquisar encontrei a resposta aqui - http://tammersaleh.com/posts/managing-heroku-environment-variables-for-local-development

O truque é remover completamente o arquivo S3.rb e apenas consultar as variáveis ​​ENV no modelo assim:

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

De qualquer forma, David, obrigado pela sua sugestão.Não sei se você deseja atualizar a documentação do Heroku para dizer que alguns usuários tiveram que fazer isso dessa maneira.Obrigado novamente.

Outras dicas

Renomeie o arquivo config/initializers/s3.yml para config/initializers/s3.rb e experimente.

Aqui está o seu problema:

:bucket         => ENV['S3_BUCKET'],

precisa ser

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

ou sejaas atribuições não estão sendo interpretadas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top