지난 글에는 단일 오펜스만 닫는 perl script를 작성하였는데

속도가 굉장히 느려서 perl의 ForkManager 모듈을 이용한 멀티 프로세스의 offense closure를 새로 코딩했습니다.

 

10 pid로 10 items 를 해결하는데 27초 걸립니다.

 

테스트 환경은 QRadar 7.4.2 2020.7.0.20201113144954 버젼 입니다.

 

use strict;
use warnings;
use Parallel::ForkManager;
my $truecount = 0;
my @offlist;
my @listcmd = "curl -S -X GET -u admin:password1! -k -H 'Range: items=0-9' -H 'Version: 15.0' -H 'Accept: application/json' 'https://<console_ip>/api/siem/offenses?fields=id&filter=status%20%3D%20%22OPEN%22'";
my $pm = Parallel::ForkManager->new(10);

$pm->run_on_start(
    sub {
        my ( $pid ) = @_; # $pid
        print "### START pid: $pid\n";
    }
);

$pm->run_on_finish(
    sub {    # must be declared before first 'start'
        my (
            $pid,
            $exit_code,
            $ident,
            $exit_signal,
            $core_dump,
            #$data,
        ) = @_; # $data exit return value
        print "## END pid: $pid\n";
        #$out{ $data->[0] } = $data->[1];
    }
);

while($truecount == 0){
	my $list = qx(@listcmd); #[{"id":85562},{"id":85561}] string
	$list =~ s/\{\[?"id":(\d+)\]?\}/$1/g;
	@offlist = split(/,/, $list); # create array
	
	foreach my $shfoff (@offlist)
	{
		$pm->start() and next; # start pid

		$shfoff =~ s/\[?(\d+)]?/$1/;
		my @closecmd = ("curl -S -X POST -u admin:password1! -k-H 'Version: 15.0' -H 'Accept: application/json' 'https://<console_ip>/api/siem/offenses/$shfoff?closing_reason_id=1&status=CLOSED'");
		system(@closecmd);

		$pm->finish(0); # stop pid
	};
	
	$pm->wait_all_children;
};

이전 스크립트 보다 훨씬 깔끔해졌습니다.

username : password 와 <console_ip>를 채워주면 되고

my $list와 $shfoff를 보면 알겠지만 단순한 id값만 뽑아내서 열려있는 모든 오펜스를 닫는 스크립트입니다.

그래서 원하는 오펜스만 자동으로 닫으시려면 @listcmd 의 filter를 바꾸고 정규표현식만 약간 바꿔주면 작동이 잘 될겁니다.

use strict;
use warnings;
my $truecount = 0;  #루프문 변수
my @offlist;  #오펜스 배열 변수
#Range는 리스트 갯수 조정
my @listcmd = "curl -S -X GET -u admin:password12! -k -H 'Range: items=0-100' -H 'Version: 15.0' -H 'Accept: application/json' 'https://<콘솔아이피>/api/siem/offenses?fields=id&filter=status%20%3D%20%22OPEN%22'";
my $arrcount;  #오펜스 배열 자리 변수
my $lenoff = 0;  #오펜스 배열 크기 변수

while($truecount == 0){
	if($lenoff == 0){
    	#[{"id":85562},{"id":85561}] => listcmd는 배열이 아닌 문자열로 저장됨
		my $list = qx(@listcmd);  #qx: 실행한 결과값 변수로 저장하는 함수
		$list =~ s/\{\[?"id":(\d+)\]?\}/$1/g;  #list내에 모든 {"id":숫자}를 숫자만으로 치환
		@offlist = split(/,/, $list);  #쉼표로 구분해서 배열로 새롭게 저장
		$lenoff = @offlist;  #배열 크기 저장
		$arrcount = 0;
	} else {
		for (my $i = 0; $i < $lenoff+1; $i++){  #1을 더해야 배열 크기가 정확함
			my $shfoff = @offlist[$arrcount];  #오펜스 배열의 숫자 불러오기
			$shfoff =~ s/\[?(\d+)]?/$1/;  #맨 처음, 뒤에 들어가는 [ 와 ] 제거
			if($shfoff =~ /\d+/ ){  #가끔 null 값을 피하기 위한 검사
				my @closecmd = ("curl -S -X POST -u admin:password12! -k -H 'Version: 15.0' -H 'Accept: application/json' 'https://<콘솔아이피>/api/siem/offenses/$shfoff?closing_reason_id=1&status=CLOSED'");
				system(@closecmd);
				$arrcount++;  #다음 배열을 가져오기 위함
			};
		};
		$lenoff = 0;  #초기화 - 새로운 리스트 받아오기
	};
};

꼬박 밤을 샜지만 재밌었다 ㅋㅋ

단점은 조금 느리다.
100개를 closing하는데 생각보다 오래 걸리는 느낌이든다.
나중에 python이나 Bash로 만들어서 API 테스트를 해봐야겠다.

과부하 테스트를 위해서 어제 펄 스크립트를 작성하여 실행하고 잤더니 결과는 대만족입니다.

소스포트를 1씩 늘려가면서 오펜스를 소스포트 기반으로 뜨게 만들었습니다.

 

use strict;
use warnings;
my $srcpt;
my $content;

for(my $i = 0; $i < 500000; $i++) {
	open (TEXT, "+<offense500k.log");
	chomp($content = <TEXT>);
	if($content =~ /srcport=(\d+)/){
		$srcpt = $1 + 1;
	};
	$content =~ s/srcport=(\d+)/srcport=$srcpt/;
	seek(TEXT,0,0);
	print "TEST log: ", $content, "!\n";
	print TEXT $content;
	close TEXT;
	system '/opt/qradar/bin/logrun.pl -u 192.168.0.10 -f offense500k.log 1';
	print "Success number", $i, "!\n";
};

일단 50만개를 만들어줄거라서 for문을 열었습니다.

 

open 함수로 샘플 로그파일을 입출력모드로 열고

샘플 로그파일이 한줄짜리라서 chomp로 변수 $content에 할당했습니다.

로그파일에 있는 소스포트를 받기위해 if문을 작성하여 변수 $srcpt에 1을 더해 저장했습니다.

 

$content 내용에서 srcport를 정규식으로 찾은 후, 아까 if문에서 1을 더한 $srcpt로 치환했습니다.

seek 함수는 입력 포인트를 처음으로 이동하게 하였습니다. (맨 끝에 추가가 아닌 덮어쓰기를 위해서)

로그가 제대로 바뀌었는지 터미널에 바뀐 로그를 출력하고

print TEXT $content; 에서 샘플 로그 파일에 바뀐 로그를 덮어씌우게 됩니다.

close로 파일을 닫고

system으로 QRadar의 logrun.pl 명령어를 작성해주면 끝입니다.

 

펄 스크립트는 처음 써봤는데 요즘은 덜 쓰는 언어이지만 간단한 명령을 실행할때 편합니다.

+ Recent posts