Spring BootのWARをTomcatにデプロイ後、lombok.extern.log4j.Log4j2のログがTomcatのlogファイルに表示されない

f:id:ts0818:20211218151246j:plain

gigazine.net

Javaのログ出力ライブラリであるLog4jで、任意のコードをリモート実行される深刻な脆弱(ぜいじゃく)性・CVE-2021-44228、通称「Log4Shell」が発見されました。Log4jを提供するApacheソフトウェア財団(ASF)は、さらに新たな脆弱性CVE-2021-45046が発覚したと報告しており、Log4jをバージョン2.16.0以降にアップデートするように呼びかけています。

JavaのLog4jライブラリで「Log4Shell」に加えて新たな脆弱性「CVE-2021-45046」が発覚、アップデートで対応可能 - GIGAZINE

これまでLog4Shellエクスプロイトの回避策として、「log4j2.noFormatMsgLookup」をTrueに設定する方法が紹介されていましたが、CVE-2021-45046はこの無効設定を回避して攻撃できる可能性があったことがわかりました。

JavaのLog4jライブラリで「Log4Shell」に加えて新たな脆弱性「CVE-2021-45046」が発覚、アップデートで対応可能 - GIGAZINE

⇧ う~ん、1週間で新たな脆弱性が見つかるってのは芳しくないことではあるけど、被害が広がる前に早期に見つけてくれたことはありがたいですね。

ただ、対策がアップデートするしかないってのは、アップデートによってアプリケーションが動かなくなるリスクもあるのが辛いけども...

2021年12月19日(日)追記:↓ ここから

なんか、新たな脆弱性が見つかった模様...

logging.apache.org

Important: Security Vulnerability CVE-2021-45105

The Log4j team has been made aware of a security vulnerability, CVE-2021-45105, that has been addressed in Log4j 2.17.0 for Java 8 and up.

https://logging.apache.org/log4j/2.x/

⇧バージョンを上げるしかないのだけど、Java 8で動いてる「アプリケーション」であれば、バージョンアップで動かなくなるってことはないのかな?

「Spring Boot」ブログでも、

spring.io

⇧「CVE-2021-45105」の対応について言及されてますね。

しばらくは、動向を確認しておいたほうが良いのかね...

2021年12月19日(日)追記:↑ ここまで

そもそも、「Spring Boot 」+「Lombok」において利用される「Log4j2」は、どの「Log4j」を利用しているのかがいまいち判然としないんですよね、教えて偉い人...。

2021年12月19日(日)追記:↓ ここから

なんか、「Spring Boot 」+「Lombok」において利用される「Log4j2」は、

stackoverflow.com

In case you have the following in your pom.xml:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.15.0</version>
</dependency>

make sure that both have the same version. I forgot it for one (left the old version) and saw the same error.

https://stackoverflow.com/questions/70312144/lombok-log4j2-annotation-doesnt-work-with-latest-version-of-log4j-v2-15-0

⇧「log4j-core」も使ってるっぽいってことなのかな...

Eclipse」の「Spring Boot」プロジェクトの「プロジェクトと外部の依存関係」を確認してみて、

f:id:ts0818:20211219142659p:plain

⇧「spring-boot-2.6.0.jar」の中に「log4j2.springboot」ってファイルがあって「See SpringBootConfigurationFactory」って書かれていて、

spring.pleiades.io

github.com

⇧ 説明とか見てみたけど、よく分からん...

ただ、自分の「Spring Boot」プロジェクトの「Spring Boot」のバージョンが「2.6.0」で「ビルドツール」に「gradle」を使ってるんですが、

github.com

⇧ 確認してみたところ、

plugins {
	id "java-library"
	id "org.jetbrains.kotlin.jvm"
	id "org.springframework.boot.conventions"
	id "org.springframework.boot.configuration-properties"
	id "org.springframework.boot.deployed"
	id "org.springframework.boot.optional-dependencies"
}
...省略
dependencies {
	annotationProcessor("org.apache.logging.log4j:log4j-core")
...省略
	optional("org.apache.logging.log4j:log4j-api")
	optional("org.apache.logging.log4j:log4j-core")
...省略
	tomcatDistribution("org.apache.tomcat:tomcat:${tomcatVersion}@zip")
}

⇧ とあったんだけど、

qiita.com

Optionalの依存関係

Spring BootのリファレンスのB.3 Generating your own meta-data using the annotation processor に記載があります。

Gradle 4.4の初歩的な仕組み、使い方を学ぶ - Qiita

⇧ 上記サイト様の説明にあるSpring Bootのリファレンスを参照したところ、

docs.spring.io

B.3 Generating your own meta-data using the annotation processor

You can easily generate your own configuration meta-data file from items annotated with @ConfigurationProperties by using the spring-boot-configuration-processor jar. The jar includes a Java annotation processor which is invoked as your project is compiled. To use the processor, simply include spring-boot-configuration-processor as an optional dependency, for example with Maven you would add:

https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#configuration-metadata-annotation-processor

⇧ バージョンは旧いのですが、「依存関係」が追加されるって解釈で良いかと。

そうなると、「Spring Boot」は、

を「依存関係」として含むということになり、「stackoverflow」で「Lombok」の「@Log4j2」は、「log4j-api」と「log4j-core」の両方の「依存関係」のバージョンを上げて動くようになったと言ってたので、「lombok.extern.log4j.Log4j2」は「log4j-core」を使ってるということになり、「CVE-2021-45105」の脆弱性の対象になるってことなんかな?と思ったけど、

logging.apache.org

Note that only the log4j-core JAR file is impacted by this vulnerability. Applications using only the log4j-api JAR file without the log4j-core JAR file are not impacted by this vulnerability.

https://logging.apache.org/log4j/2.x/security.html#CVE-2021-45105

spring.io

Spring Boot users are only affected by this vulnerability if they have switched the default logging system to Log4J2. The log4j-to-slf4j and log4j-api jars that we include in spring-boot-starter-logging cannot be exploited on their own. Only applications using log4j-core and including user input in log messages are vulnerable.

https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot

⇧「Spring Boot」を使ったアプリケーションの場合、「ログ」でユーザーからのInputを受け付けてなければ影響は無いようです。

それにしても「log4j-core」を使ってるかどうかを調べる方法について、もう少し情報が欲しい気がしますな...

2021年12月19日(日)追記:↑ ここまで

というわけで、いま何かと話題の「Log4j2」も絡んでいる話です。

レッツトライ~。

Spring BootのWARをTomcatにデプロイ後、lombok.extern.log4j.Log4j2のログがTomcatのlogファイルに表示されない

ということで、

qiita.com

組み込み Tomcat で起動していた Spring Boot アプリケーションを、諸事情により war 化して Tomcat サーバーにデプロイすることになった。
しかし、その際 java.util.logging (以下 JUL)のロガーを使って出力してたログがアプリのログに出力されなくなり、代わりに Tomcat のログファイル(catalina.log)に出力されるようになるという問題が発生した。

Spring Boot アプリを war にして Tomcat にデプロイしたら JUL を使ったログがアプリのログに出力されなくなった場合の対処方法 - Qiita

⇧ 上記サイト様とは異なり、Spring Bootのプロジェクトで、Eclipseの「コンソール」とかに表示されてた「ログ」が、WARにして展開した先のTomcatの「ログファイル(catalina.log、catalina.out)」に表示されないという事象が起きてるんですが、具体的には「バッチ処理」において「lombok.extern.log4j.Log4j2」で出力してる「ログ」が表示されませんと。

www.codejava.net

qiita.com

f:id:ts0818:20211217233210p:plain

つまり、アプリケーションから見るとSLF4Jはロギング実装のインターフェースの役割を担い、LogbackLog4Jはロギング実装そのものになります。

SLF4J、Logback、Log4Jの関係を挙動とともに整理する - Qiita

⇧ 上記サイト様によりますと、「Log4j2」も実装ということらしいのですが、「Eclipse」で作成していた「Spring Boot」プロジェクト(「ビルドツール」は「Gradle」を使用)の「プロジェクトと外部の依存関係」を確認してみると、

f:id:ts0818:20211217234233p:plain

⇧「java.util.logging」と違って、「Log4j2」には、「SLF4J」と橋渡しするような「BridgeHandler」みたいな機能が無さそうですと。

「Spring Boot」を使ってる場合は、

spring.pleiades.io

Spring Boot は、すべての内部ロギングに Commons Logging: Apache (英語)  を使用しますが、基礎となるログ実装はオープンなままです。Java Util Logging (標準 Javadoc)  Log4J2: Apache (英語)  Logback (英語)  のデフォルト構成が提供されています。いずれの場合も、ロガーはコンソール出力を使用するように事前設定されており、オプションのファイル出力も利用できます。

https://spring.pleiades.io/spring-boot/docs/current/reference/html/features.html#features.logging

⇧ という説明なのですが、「プロジェクトと外部の依存関係」を確認した感じ、

f:id:ts0818:20211217234921p:plain

⇧「logging」というパッケージのことを言っていると仮定しますか。

4.3 ファイル出力

デフォルトでは、Spring Boot はコンソールにのみログを記録し、ログファイルを書き込みません。コンソール出力に加えてログファイルを書き込む場合は、logging.file.name または logging.file.path プロパティを設定する必要があります(たとえば、application.properties で)。

https://spring.pleiades.io/spring-boot/docs/current/reference/html/features.html#features.logging

⇧ なるほど、「application.properties」のような「プロパティファイル」に「ログ」を「ファイル」として出力する設定をしていないと、そもそも「ログファイル」として出力されないですと。

イメージ的には、

⇧ 上図のような感じで、「SLF4J」の実装として、「java.util.logging(上図の例だと、『JUL』)」以外を使ってる場合であれば、「Tomcat」の出力する「ログ」には、そもそも出力されないということですかね?

www.kimullaa.com

  • warをデプロイするときは、アプリケーションからTomcatのログを制御できない
  • 組み込みTomcatのときは、アプリケーションからTomcatのログを制御できる

Spring Boot なぜ Tomcat のログをアプリケーションから管理できるのか? - SIerだけど技術やりたいブログ

組み込みTomcatの起動クラスは org.apache.catalina.startup.Tomcat

org.apache.catalina.startup.Bootstrap で起動したときとは違い、Catalina系のクラスとWEBアプリケーションのクラスが同一クラスローダに読み込まれる

そのため jul-to-slf4j.jar をクラスパスに通せば、ロガーの差し替えができる

Spring Boot なぜ Tomcat のログをアプリケーションから管理できるのか? - SIerだけど技術やりたいブログ

⇧ 上記サイト様によりますと、「アプリケーション」をどういう形で運用しているかによって変わってくるということらしい。

「JAR(Java ARchive)」を実行して、サービスみたいな状態で「アプリケーション」を運用してる場合は、「組み込みTomcat」って感じですかね。

「WAR(Web application ARchive)」をデプロイする場合は「Application Server」に展開する必要がありますと。

「WAR(Web application ARchive)」を「Tomcat」にデプロイする方式だと、

例えば、Tomcatのログをアプリケーションからコントロールするためにアダプタを設定しようとしてwarに jul-to-slf4j.jar を含めた場合でも、Tomcatのクラスを読み込んでいるクラスローダ(Common)から、WEBアプリケーションのクラスは参照できない。そのため、ログ実装をアプリケーションから差し替えることができない

Spring Boot なぜ Tomcat のログをアプリケーションから管理できるのか? - SIerだけど技術やりたいブログ

⇧ ということらしいのですが、「Spring Boot」はデフォルトだと「組み込みTomcat」の状態になっているのですが、

spring.pleiades.io

基本的に、プロジェクトを再構成して WAR ファイルを生成し、組み込みコンテナーの依存関係を "provided" として宣言する必要があります。これにより、関連する埋め込みコンテナーの依存関係が WAR ファイルに含まれないことが保証されます。

https://spring.pleiades.io/guides/gs/convert-jar-to-war/

⇧ 公式のドキュメントによると、「WAR(Web application ARchive)」の作り方によっては、「組み込みTomcat」が含まれてしまうこともあるってことですかね。

confrage.jp

上記サイト様によりますと、「Spring Boot 」を利用した「アプリケーション」で出力してるような「ログ」については、「application.properties」のような「プロパティファイル」で出力先を設定しておいたほうが良いってことですかね。

ちなみに、

qiita.com

⇧「Tomcat」の「ログファイル」については、上記サイト様がまとめてくださってます。

ちなみに、「Quartz」のような「Spring Boot」のメインスレッドとは別のスレッドで動いているような処理における「ログ」についても、

stackoverflow.com

⇧ 上記サイト様によりますと、「application.properties」で設定が読み込めるようにしたら解決されたらしいですと。

www.titanwolf.org

⇧ なんか、「依存関係」と「application.properties」の記述も合わせる必要がありそうな感じですかね...

設定を頑張れば、「Tomcat」のlogファイルに「ログ」出力できるんかな?

それとも、「Tomcat」のlogファイルとは別なlogファイルでの「ログ」出力になるんかな?

毎度モヤモヤ感が半端ない...

今回はこのへんで。