Splunk SOAR(이하 Phantom 으로 지칭) 에서 제공하는 AWS 관련 app을 보면 아래와 같이 2가지 방법으로 Phantom 과 AWS를 연결할 수 있다.

첫번째, Access Key / Secret Key 를 입력하는 방법.

두번재, EC2에서 현재 Phantom 을 실행할때 연결된 role 을 사용하는 방법.

위 두가지 방법 중 두번째 방법을 보면 체크 박스에 체크를 하는것만으로도 AWS App 의 Test connectivity 가 정상적으로 Pass가 되는걸 볼수가 있다. (Phantom이 EC2에 실행이 되어야 하고 role을 사용해야 함.) 어떻게 key 또는 ID / PWD가 없이 연결이 되는거지? 라는 의문이 들었다. 해당 의문에 대해서는 다음과 같은 사이트에서 이해할 수 있었다. (https://cloudguardians.medium.com/ec2-instance-metadata-보안-edd23f56b64c)

메타데이터를 이용해 EC2에 대한 정보를 가져올수가 있는데 아래와 같이 curl을 던지면 사용 가능한 meta-data정보 리스트를 확인해볼수 있다.

/iam/security-credentials/ 정보를 체크해보면

해당 Phantom이 설치된 EC2 인스턴스는 bob_role이라는 role을 사용하고 있다는걸 알수 있다. bob_role 를 통해 임시보안자격증명을 하려면 아래와 같이 임시로 쓸수 있는 key와 만료시간을 전달받을 수가 있다.


임시로 쓰는 키지만…다 보여드리기 기분이 좀 그래서 가림..ㅎㅎ
다시 돌아와 Phantom app 에서 use_role을 체크한다면 아래와 같은 boto3를 이용한 소스가 실행되 key 값을 받게된다.

from boto3 import Session, client, resource

if config.get('use_role'):
		credentials = self._handle_get_ec2_role()
		if not credentials:
		    return self.set_status(phantom.APP_ERROR, EC2_ROLE_CREDENTIALS_FAILURE_MSG)
		self._access_key = credentials.access_key
		self._secret_key = credentials.secret_key
		self._session_token = credentials.token
		
		return phantom.APP_SUCCESS
	
self._access_key = config.get(EC2_JSON_ACCESS_KEY)
self._secret_key = config.get(EC2_JSON_SECRET_KEY)

def _handle_get_ec2_role(self):
	  session = Session(region_name=self._region)
	  credentials = session.get_credentials()
	  return credentials

하지만 현재 사용하고 있는 role 이 아닌 다른 role 접근을 하려면 STS를 사용해야 한다.우선 권한이 필요하다. (https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/id_credentials_temp_control-access_enable-create.html) bob_role 에서 bob_role2 연결을 하려면 아래와 같은 권한이 필요하다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com",
                "AWS": "arn:aws:iam::[bob Account]:role/bob_role"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

권한 부여가 되었으면 python에서 STS를 사용하면 된다.

def _assume_a_role(self, param):
		boto_config = None
		if self._proxy:
		    boto_config = Config(proxies=self._proxy)
		
		self.debug_print("Creating boto3 STS client assuming given role")
		sts_client = client(
		    'sts',
		    region_name=self._region,
		    aws_access_key_id=self._access_key,
		    aws_secret_access_key=self._secret_key,
		    aws_session_token=self._session_token,
		    config=boto_config)
		response = sts_client.assume_role(
		    RoleArn=param['role_arn'],
		    RoleSessionName="AssumeRoleSession2"
	)
	# self._access_key = response['Credentials']['AccessKeyId']
	# self._secret_key = response['Credentials']['SecretAccessKey']
	# self._session_token = response['Credentials']['SessionToken']
	return response['Credentials']


# 사용 예시
if param and 'role_arn' in param:
		try:
		    temp_credentials = self._assume_a_role(param) # ast.literal_eval(param['credentials'])
		    self._access_key = temp_credentials.get('AccessKeyId', '')
		    self._secret_key = temp_credentials.get('SecretAccessKey', '')
		    self._session_token = temp_credentials.get('SessionToken', '')
		
		    self.save_progress("Using temporary assume role credentials for action")
		except Exception as e:
		    return action_result.set_status(phantom.APP_ERROR,
		                                    "Failed to get temporary credentials:{0}".format(e))

 

실행 결과

Status : success 가 나오는걸 확인할 수 있다.

Phantom의 AWS 관련 앱에서 어떻게 key가 없이 연결이 되는지 라는 물음에서 많은 공부가 되었다. 해당 문제를 해결하려면 기본적인 AWS IAM 을 이해해야 해서 관련 문서를 보면 많은 도움이 된다.

잘못되거나 수정해야 할 내용이 있으면 알려주길 바란다.

+ Recent posts