[RUBY] Faites attention au moment d'initialisation lors de l'utilisation de MessageEncryptor avec Rails 5.2 / 6.0

Depuis Rails 5.2, la méthode de cryptage par défaut pour ʻActiveSupport :: MessageEncryptor est passée de ʻaes-256-cbc à ʻaes-256-gcm`. Cependant, en fonction du moment d'initialisation, une méthode de cryptage involontaire peut être utilisée, nous allons donc l'introduire.

Rails 5.2

Vérifiez avec les versions suivantes:

Défaut

Tout d'abord, vérifiez la méthode de cryptage par défaut avec rails console.

irb> encryptor = ActiveSupport::MessageEncryptor.new 'key'
=> #<ActiveSupport::MessageEncryptor:0x0000561c2eae8940 @secret="key", @sign_secret=nil, @cipher="aes-256-gcm", @aead_mode=true, @verifier=ActiveSupport::MessageEncryptor::NullVerifier, @serializer=Marshal, @options={}, @rotations=[]>
irb> encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

Il s'avère que c'est certainement ʻaes-256-gcm`.

Illustration

Dans une application réelle, il peut être utilisé en l'ayant dans un modèle.

app/models/some_model.rb


class SomeModel < ApplicationRecord
  class << self
    attr_reader :encryptor

    def set_key(key)
      @encryptor = ActiveSupport::MessageEncryptor.new key
    end
  end

  set_key 'x' * 32
end

Vérifiez cela de la même manière.

irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

Semble bien.

Exemple de problème

Cependant, si le moment d'initialisation de MessageEncryptor est trop tôt, la méthode de cryptage sera différente. Par exemple, si la constante SomeModel est référencée dans le rappel ʻafter_initialize, elle sera automatiquement chargée à ce moment et un MessageEncryptor` sera généré.

config/application.rb


class Application < Rails::Application
  config.load_defaults 5.2
  config.after_initialize do
    SomeModel
  end
end
irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-cbc"

Il est devenu ʻaes-256-cbc au lieu de ʻaes-256-gcm.

Cause

Le problème est le moment de refléter les paramètres de Rails.application.config.active_support.use_authenticated_message_encryption. Ce paramètre est fourni pour la compatibilité avec les versions précédentes, et vous pouvez le redéfinir sur ʻaes-256-cbcen le définissant surfalse. Cette valeur de paramètre est la valeur par défaut «true» pour Rails 5.2, mais il semble que cette valeur de paramètre n'ait pas encore été reflétée au moment de l'exécution de «config.after_initialize». Par conséquent, s'il est initialisé à ce moment, il deviendra la valeur par défaut de MessageEncryptor lui-même, ʻaes-256-cbc.

Le code correspondant se trouve ici.

https://github.com/rails/rails/blob/v5.2.4.3/activesupport/lib/active_support/message_encryptor.rb#L88

Exemple de solution

Le problème étant que l'initialisation est trop précoce, il est possible de la retarder jusqu'au moment réel d'utilisation.

app/models/some_model2.rb


class SomeModel2 < ApplicationRecord
  class << self
    def set_key(key)
      @key = key
    end

    def encryptor
      @encryptor ||= ActiveSupport::MessageEncryptor.new @key
    end
  end

  set_key 'x' * 32
end

config/application.rb


config.after_initialize do
  SomeModel2
end

Vous pouvez maintenant utiliser ʻaes-256-gcm` dans la plupart des cas.

irb> SomeModel2.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"

Cependant, si le timing lui-même lorsque vous voulez utiliser MessageEncryptor est avant que le réglage de ʻuse_authenticated_message_encryptionne soit reflété, cela ne résout pas le problème. Dans ce cas, il est préférable de spécifier l'optioncipher:dansMessageEncryptor.new`.

Rails 6

J'ai enquêté à nouveau avec la version suivante, mais il semble que la situation soit la même.

Un peu différent de 5.2 est que le chargeur automatique par défaut est Zeitwerk et il est déconseillé de charger automatiquement chaque modèle avec config / initializers / *. Rb. Par conséquent, si vous vous référez par inadvertance au modèle avec config / initializers / *. Rb, il peut être détecté avec un message d'avertissement. Cependant, comme dans l'exemple de cet article, il ne semble y avoir aucun avertissement dans config.after_initialize.

Rails charge chaque fichier selon les besoins, mais le timing peut parfois être déroutant. Sachez que la synchronisation du chargement peut causer des problèmes.

Recommended Posts

Faites attention au moment d'initialisation lors de l'utilisation de MessageEncryptor avec Rails 5.2 / 6.0
[Rails] Lorsque vous utilisez ajax, faites attention aux "mesures CSRF".
Soyez prudent lorsque vous utilisez plusieurs articles
Moment d'initialisation de la variable membre avec la valeur finale
Soyez prudent avec les demandes et les réponses lors de l'utilisation de Serverless Framework avec Java
[Java10] Veillez à utiliser ensemble var et génériques
Comment définir des variables d'environnement lors de l'utilisation de Payjp avec Rails
Japaneseize en utilisant i18n avec Rails
Résumé du travail initial lors de la création d'une application avec Rails
Erreur lors de l'utilisation des rails capybara
[Rails] Où faire attention dans la description de la validation
Conseils détaillés lors de l'utilisation de Rails
[Rails] Localisation japonaise du message d'erreur lors de l'utilisation de l'objet Form
Points à prendre en compte lors de la mise à niveau de Tomcat sur un système Web utilisant Oracle
[Rails] Implémentation de la fonction coupon (avec fonction de suppression automatique par traitement par lots)
Paramètres à définir lors de l'exploitation d'un environnement de production avec Rails
[Rails] "Pry-rails" qui peuvent être utilisés lors de l'enregistrement avec la méthode create
Une collection de méthodes souvent utilisées lors de la manipulation du temps avec TimeWithZone of Rails
Visualisez le temps de traitement du serveur Rails à l'aide de la synchronisation du serveur
[Rails] Les messages ne peuvent pas être supprimés lorsqu'ils sont commentés! ??
Remarques sur l'utilisation de FCM avec Ruby on Rails
Utilisation du type caché lors du PUT avec Thymeleaf
Utiliser SSIServlet avec Tomcat intégré SpringBoot 2.2.4
Faites attention à l'heure d'été lors de l'inscription / référence de l'anniversaire d'un utilisateur
Problème de lenteur de traitement lors de l'utilisation d'Active Storage avec le stockage cloud (GCS, S3, etc.)