詳細検索

출력 bash history syslog, jenkins 빌드

아바타
글쓴이 komi

출력 bash history syslog, jenkins 빌드
日本語에서 번역 • 원문 보기

안녕하세요. 코미야입니다. 최근 보안 관련 업무에서 "실행 명령 기록"에 대한 요청이 많이 있었습니다. 여러 가지 방법이 있다고 생각하지만, 이번에는 시간을 bash_history에 입력하고 하나의 로그로 요약하고 싶습니다.

이 작업을 해본 후 편리한 점은 유지보수 중 작업 시간을 보고할 때 grep로 로그를 해결할 수 있다는 점입니다.

Jenkins와 함께 빌드하는 것은 최근 스피어의 지속적 통합이었습니다. 처음에는 심리적인 장벽이 있었지만, 시도해보니 꽤 쉽고 따라야 할 단계가 없어서 좋다고 생각했습니다. 취약점을 해결하기 위해 여러 번 빌드해야 했지만, 젠킨스 직업이 편리했습니다.

CentOS 6.5. 젠킨스의 역할은 다음과 같습니다. 단순히 매개변수가 있는 셸을 실행하는 것입니다.

#!/빈/쾅
topdir="${HOME}/rpmbuild" 
rpmdir="${topdir}/RPMS/x86_64" 

만약 [ -f ${HOME}/.rpmmacros ]; 그렇다면
  echo "%_topdir ${Topdir}" > "${HOME}/.rpmmacros" 
  echo "%_signature GPG" >> "${HOME}/.rpmmacros" 
  echo "%_gpg_name D279xxxx" >> "${HOME}/.rpmmacros" 
Fi
만약 [ -d ${HOME}/rpmbuild ]; 그렇다면
  mv ${HOME}/rpmbuild{,.'date +%Y%m%d.%H%M'}
  mkdir -p ${HOME}/rpmbuild/SRPM
Fi

케이스 "${TARGET}"
 *.src.rpm) rpm -Uvh "${TARGET}" 
  CP -p ${topdir}/SPECS/bash.spec{,.org}
  sed -i 's/make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS 'getconf LFS_CFLAGS'"/make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS 'getconf LFS_CFLAGS' -DSYSLOG_HISTORY"/g' ${topdir}/SPECS/bash.spec
  sed -i 's/Release: 29%{?dist}/Release: 29%{?dist}_isao_5/g' ${topdir}/SPECS/bash.spec
  sed -i '108s/^$/\n/g' ${topdir}/SPECS/bash.spec
  sed -i '109s/^$/Patch145: bash-syslog_facirity.patch\n/g' ${topdir}/SPECS/bash.spec
  sed -i '181s/^$/%patch145 -p1\n/g' ${topdir}/SPECS/bash.spec
  CD ${HOME}/rpmbuild/SOURCES/ 
  타르 XZF bash-4.1.tar.gz
  CP -rp bash-4.1{,.org}
  sed -i 's/# 정의 SYSLOG_FACILITY LOG_USER/# define SYSLOG_FACILITY LOG_LOCAL6/g' ${HOME}/rpmbuild/SOURCES/bash-4.1/config-top.h
  sed -i 's! (SYSLOG_FACILITY| SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line)! (SYSLOG_FACILITY| SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, line)!g' ${HOME}/rpmbuild/SOURCES/bash-4.1/bashhist.c
  sed -i 's! (SYSLOG_FACILITY| SYSLOG_LEVEL, "히스토리 (트런케이트): PID=%d UID=%d %s", getpid(), current_user.uid, trunc)! (SYSLOG_FACILITY| SYSLOG_LEVEL, "히스토리 (트런케이트): PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, trunc)!g' ${HOME}/rpmbuild/SOURCES/bash-4.1/bashhist.c
  diff -crN bash-4.1.org bash-4.1 > ${HOME}/rpmbuild/SOURCES/bash-syslog_facirity.patch
  rpmbuild -ba ${topdir}/SPECS/bash.spec
 ;; 
 *) 에코 '환경 변수 TARGET은 반드시 설정되어야 한다.'; 출구 1;; 
ESAC

제가 TARGET으로 선택한 매개변수는 다음과 같습니다: 'http://vault.centos.org/6.5/updates/Source/SPackages/bash-4.1.2-15.el6_5.2.src.rpm'

업그레이드할 때 다음과 같이 변경되었습니다. 각 버전마다 작업이 별도로 나뉘어 있습니다. 'http://vault.centos.org/6.6/os/Source/SPackages/bash-4.1.2-29.el6.src.rpm'

'${HOME}'는 '/var/lib/jenkins'입니다.

흐름은 소스 RPM을 드롭한 상태로 넣고, 소스 아카이브를 압축 해제한 뒤 sed, 패치를 만들고, 만든 패치를 적용할 수 있도록 스펙 파일을 sed한 뒤 빌드하는 것입니다. diff에서 전체 디렉터리를 패치하는 옵션이 -crN이라는 것을 알게 되었습니다. 패치를 업로드할 용기가 있다면 다음과 같습니다.

# 캣 배쉬-syslog_facirity.패치
diff -crN bash-4.1.org/bashhist.c bash-4.1/bashhist.c
bash-4.1.org/bashhist.c 2009-08-15 04:33:02.0000000000 +0900
--- bash-4.1/bashhist.c 2014-12-16 19:13:45.272586470 +0900
***************
*** 705,716 **** 
    차르 트런[SYSLOG_MAXLEN]; 

    만약 (strlen(line) < SYSLOG_MAXLEN)
!     syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
    else
      {
        strncpy (trunc, line, SYSLOG_MAXLEN);
        trunc[SYSLOG_MAXLEN - 1] = '';
!       syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
      }
  }
  #endif
--- 705,716 ----
    char trunc[SYSLOG_MAXLEN];

    if (strlen(line) < SYSLOG_MAXLEN)
!     syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, line);
    else
      {
        strncpy (trunc, line, SYSLOG_MAXLEN);
        trunc[SYSLOG_MAXLEN - 1] = '';
!       syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, trunc);      }
  }
  #endif
diff -crN bash-4.1.org/config-top.h bash-4.1/config-top.h
*** bash-4.1.org/config-top.h   2009-12-23 05:29:39.000000000 +0900
--- bash-4.1/config-top.h       2014-12-16 19:07:53.607579557 +0900
***************
*** 103,109 **** 
     bash_add_history()는 syslog()로 전송됩니다. */ 
  /* #define SYSLOG_HISTORY */ 
  #if 정의 (SYSLOG_HISTORY)
! # 정의SYSLOG_FACILITY LOG_USER
  # 정의해SYSLOG_LEVEL LOG_INFO
  #endif

--- 103,109 ---- 
     bash_add_history()는 syslog()로 전송됩니다. */ 
  /* #define SYSLOG_HISTORY */ 
  #if 정의 (SYSLOG_HISTORY)
! # 정의SYSLOG_FACILITY LOG_LOCAL6
  # 정의해SYSLOG_LEVEL LOG_INFO
  #endif

로그 형식이 변경되어 이 URL을 참조한 부모 프로세스 ID와 SU PID가 포함되어 있습니다. (감사가 더 쉬울 것 같았습니다)

시설이 local6로 변경됩니다. 'rsyslog.conf'에서 다음과 같은 작업을 한다고 가정해 봅시다:

*.info; mail.none; authpriv.none; cron.none; local6.none /var/log/messages
# bash_history 로그에
local6.* /var/log/bash_history

저는 yum 업데이트 대상에서 bash를 별도로 제거하는 것이 필요하다고 생각합니다. ('yum-updatesd'가 유효하다면, 나중에 'yum.conf'에서 'exclude=bash*' 등) 나중에 하지 않으면 레시피를 실행할 때 커스텀 배시로 업데이트되지 않으니 주의하세요. Chef(yum)에 입력할 때 'options "--disablerepo=base,updates'를 입력해야 했습니다. 이는 다른 저장소의 패키지에서 업데이트되지 않는 것을 방지하기 위한 대응책입니다. 또한, Chef에서 레시피를 흐름할 때 런_list 순서에 커스텀 저장소를 넣는 레시피로 시작하지 않으면, 저장소가 사용 불가능하다고 판단되어 설치나 업그레이드가 이루어지지 않을 수 있습니다.

'RPMSign'이라는 플러그인을 사용해 gpg에 서명하고 커스텀 Yum 저장소에 SCP를 넣습니다. 플러그인에 'SSH 플러그인'도 넣었습니다.

시스템 설정에서 gpg 키와 패스프레이즈를 설정하고, 작업에서 키를 선택한 후 명령어 라인 옵션에 서명할 패키지의 전체 경로를 작성하세요(와일드카드 허용).

통나무가 실제로 생산되는 방법은 다음과 같습니다.

8월 21일 11:11:54 localhost -bash: HISTORY: PID=18837 PPID=18836 SID=18837 User=komiyay UID=501 CMD=sudo su - 
8월 21일 11:44:55 localhost bash: HISTORY: PID=19298 PPID=18864 SID=18837 User=root UID=0 CMD=knife solo data bag edit ssl nginx

SCP와 Yum 저장소 메타데이터 사이에 차이를 만들기 위해 별도의 작업을 만들었고, 패키지가 빌드되지 않고 약간 이상한 이름이 붙으면 삭제하는 번거로움을 피하고 싶었습니다.

bash_history는 조작 위험이 있어 실시간으로 다른 서버로 전달하는 등의 조치가 여전히 필요합니다. rsyslog, syslog-ng, TD-agent 같은 방법도 있지만, 너무 길어서 생략될 예정입니다.

젠킨스는 많은 일을 자동으로 처리하고, 암묵적인 절차가 없어서 편리합니다. 많은 것을 배웠습니다. 사내 개발 담당 히라가타 씨에게 젠킨스에 대해 들었습니다. 정말 감사합니다. 당신 덕분에 심리적 장벽이 줄어들었습니다.

참고로, bash가 아닌 다른 걸 쓰고 싶고 bash만 사용하는 작업으로 커버할 수 없다면, 'psacct'(RHEL 시스템)나 'pacct'(Debian 시스템)를 추가하고, 'lastcomm'에 '--user' 같은 옵션을 추가해 각 사용자의 기록을 확인하고 다시 확인할 수 있는 방법일 것 같아요. 아마도요. 구글링을 좀 해보니 /etc/profile에서 스크립트 명령어가 자동으로 실행되는 사람을 찾았어요. 무슨 일이 있었는지 추적하는 게 편리해 보이지만, 개인적으로는 패키지로 할 수 있는 범위가 만족스러웠어요. 기본적으로 hisotry는 시간을 표시하지 않아서, 셸에서 시간을 표시하는 방법은 bash 외에도 여러 가지가 있는 것 같고, 구글링해보니 아래 링크와 같았습니다. tcsh 기록에 날짜를 입력하세요 - 명령 실행 시간을 볼 수 있도록 도구 상자 zsh 기록 - Qiita 위 방법 외에 다른 것을 사용 중이라면 본인 책임 하에 확인해 주세요. 참고로 이 시간 배시는 수정되어 syslog에 전송되므로 필요하지는 않지만, 만약 각 기록 파일에 시간을 넣고 싶다면, 3.0 이후에는 셸 변수 "HISTTIMEFORMAT"을 설정할 수 있는 것 같습니다. 또한 sh와 csh 모두 기록을 편집할 수 없는 것 같아서 시간을 설정하는 것은 불가능하다고 생각합니다. 또한, 기록 파일 조작을 감지하기 위해 감사가 필요한가요? 저는 auditd를 제대로 사용해본 적이 없는데, 규칙을 제대로 결정하고 올바른 운영을 고민하는 데 시간이 많이 걸리거나, 로그의 가독성이 좋지 않기 때문입니다.

참고: syslog 기록된 역사 - C - C 프로그램 개발 [Tech Blog vol.2] psacct 패키지를 이용한 프로세스 회계 | 기술 블로그 | 관리형 호스팅 Deenet Linux/UNIX에서 명령 실행 기록 유지하는 방법 - drk7jp 기록 명령어 결과에 날짜와 시간을 표시할 수 있게 허용 - takami_hiroki의 일기

읽어주셔서 감사합니다.

Related Articles