관리가 잘 되어 있는 사이트라면 Tomcat을 root로 기동하여 운영하는 경우는 드물 것입니다. Tomcat뿐 아니라 JBoss나 WebLogic의 경우도 마찬가지일 것으로 생각합니다. 단, 일부 웹 애플리케이션 서버는 특정 작업 때문에 root 권한을 요구하는 경우가 있을 수 있습니다.
별도 관리 계정이 있는 상황에서 실수로 한 차례 root로 기동하면 골치 아픈 일이 발생합니다. 설정 파일이나 내부 관리 파일, 특히 점(.)으로 시작해 잘 보이지 않는 파일들, 그리고 로그 파일이 root 소유로 바뀌어 버리는 경우가 있기 때문입니다. 이후 원래의 관리 계정으로 다시 기동하려면 먼저 해당 파일들을 하나하나 찾아 chown해야 하는 불편함이 생깁니다.
그래서 기동 시점에 현재 기동 계정이 root인지 확인하는 로직을 별도로 넣어 사용하는 경우가 많습니다. 물론 그 방법도 좋은 방법입니다. 이와는 별개로 Tomcat 자체에서 root 사용을 막도록 설정하는 방법도 있습니다.
Tomcat에서 root 기동 차단하기
server.xml에 다음 Listener를 추가합니다.
<Listener className="org.apache.catalina.security.SecurityListener" checkedOsUsers="root" />
이후 root로 기동을 시도하면 다음과 같은 로그가 출력되면서 기동에 실패합니다.
java.lang.Error: Start attempted while running as user [root]. Running Tomcat as this user has been blocked by the Lifecycle listener org.apache.catalina.security.SecurityListener (usually configured in CATALINA_BASE/conf/server.xml)
at org.apache.catalina.security.SecurityListener.checkOsUser(SecurityListener.java:154)
at org.apache.catalina.security.SecurityListener.doChecks(SecurityListener.java:142)
at org.apache.catalina.security.SecurityListener.lifecycleEvent(SecurityListener.java:63)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:99)
at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:280)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
주의할 점
단, 이 방법에도 단점이 있습니다.
기동 과정에서 로그 파일과 GC 로그 파일이 새로 생성되는 방식이라면 해당 파일들은 root 소유로 생성될 수 있습니다. 예를 들어 기존 로그 파일을 미리 백업 디렉터리로 옮긴 뒤 최종 기동이 진행되는 방식이 이에 해당합니다. 반면 기존 관리 계정으로 생성된 파일이 이미 존재하고, 그 파일에 append되는 방식이라면 파일 소유자는 계속 기존 관리 계정으로 유지됩니다.
이유는 이 방법이 Tomcat 서버가 시작되는 과정에서 Listener를 통해 root 여부를 확인한 뒤, root라면 서버를 중지시키는 방식이기 때문입니다. 즉, 아주 이른 단계에서 차단되기는 하지만, 기동 스크립트나 JVM 옵션에 의해 먼저 생성되는 파일까지 모두 막아 주는 것은 아닐 수 있습니다.
따라서 더 확실하게 막으려면 Tomcat 설정과 함께 기동 스크립트 앞단에서도 현재 사용자가 root인지 확인하는 방어 로직을 두는 편이 좋습니다. 적용 후에는 테스트 환경에서 root로 한 번 기동을 시도해 기동이 차단되는지 확인하고, 로그 디렉터리에 root 소유 파일이 새로 생기지 않았는지도 함께 확인하는 것이 안전합니다.