Skip to content

Commit

Permalink
Merge pull request #10 from splunk-soar-connectors/next
Browse files Browse the repository at this point in the history
Merging next to main for release 1.2.11
  • Loading branch information
kczernik-splunk authored Dec 23, 2024
2 parents cbbe60f + 7adc73b commit 9003b8b
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 98 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
repos:
- repo: https://github.com/phantomcyber/dev-cicd-tools
rev: v1.16
rev: v1.24
hooks:
- id: org-hook
- id: package-app-dependencies
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
rev: v1.5.0
hooks:
- id: detect-secrets
args: ['--no-verify', '--exclude-files', '^awssts.json$']
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
# AWS Security Token Service

Publisher: Splunk
Connector Version: 1.2.10
Connector Version: 1.2.11
Product Vendor: AWS
Product Name: Security Token Service
Product Version Supported (regex): ".\*"
Minimum Product Version: 6.1.1
Minimum Product Version: 6.3.0

This app integrates with AWS Security Token Service and allows a user to retrieve a temporary set of credentials for some specified account

Expand Down Expand Up @@ -44,8 +44,8 @@ This is true whether the receiving action's asset is configured with the access
or if the EC2 instance role credentials are used.


### Configuration Variables
The below configuration variables are required for this Connector to operate. These variables are specified when configuring a Security Token Service asset in SOAR.
### Configuration variables
This table lists the configuration variables required to operate AWS Security Token Service. These variables are specified when configuring a Security Token Service asset in Splunk SOAR.

VARIABLE | REQUIRED | TYPE | DESCRIPTION
-------- | -------- | ---- | -----------
Expand Down
20 changes: 4 additions & 16 deletions awssts.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
"product_version_regex": ".*",
"publisher": "Splunk",
"license": "Copyright (c) 2021-2024 Splunk Inc.",
"app_version": "1.2.10",
"utctime_updated": "2023-10-31T10:18:56.000000Z",
"app_version": "1.2.11",
"utctime_updated": "2024-12-17T14:42:37.000000Z",
"package_name": "phantom_awssts",
"main_module": "awssts_connector.py",
"min_phantom_version": "6.1.1",
"min_phantom_version": "6.3.0",
"app_wizard_version": "1.0.0",
"latest_tested_versions": [
"Cloud API, September 23, 2021"
Expand All @@ -35,21 +35,9 @@
"module": "jmespath",
"input_file": "wheels/shared/jmespath-0.10.0-py2.py3-none-any.whl"
},
{
"module": "python_dateutil",
"input_file": "wheels/shared/python_dateutil-2.8.2-py2.py3-none-any.whl"
},
{
"module": "s3transfer",
"input_file": "wheels/shared/s3transfer-0.3.7-py2.py3-none-any.whl"
},
{
"module": "six",
"input_file": "wheels/shared/six-1.16.0-py2.py3-none-any.whl"
},
{
"module": "urllib3",
"input_file": "wheels/shared/urllib3-1.26.17-py2.py3-none-any.whl"
}
]
},
Expand Down Expand Up @@ -375,4 +363,4 @@
"versions": "EQ(*)"
}
]
}
}
95 changes: 46 additions & 49 deletions awssts_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,19 @@ def initialize(self):

config = self.get_config()

self._region = STS_REGION_DICT.get(config['region'])
self._region = STS_REGION_DICT.get(config["region"])
if not self._region:
return self.set_status(phantom.APP_ERROR, "Specified region is not valid")

self._proxy = {}
env_vars = config.get('_reserve_environment_variables', {})
if 'HTTP_PROXY' in env_vars:
self._proxy['http'] = env_vars['HTTP_PROXY']['value']
if 'HTTPS_PROXY' in env_vars:
self._proxy['https'] = env_vars['HTTPS_PROXY']['value']
env_vars = config.get("_reserve_environment_variables", {})
if "HTTP_PROXY" in env_vars:
self._proxy["http"] = env_vars["HTTP_PROXY"]["value"]
if "HTTPS_PROXY" in env_vars:
self._proxy["https"] = env_vars["HTTPS_PROXY"]["value"]

# Check for EC2 role creds, otherwise use the ones in the config
if config.get('use_role'):
if config.get("use_role"):
credentials = self._handle_get_ec2_role()
if not credentials:
return self.set_status(phantom.APP_ERROR, ASSUME_ROLE_CREDENTIALS_FAILURE_MSG)
Expand All @@ -87,7 +87,7 @@ def finalize(self):

return phantom.APP_SUCCESS

def _create_client(self, action_result, service='sts', new_region=None):
def _create_client(self, action_result, service="sts", new_region=None):

boto_config = None
if self._proxy:
Expand All @@ -106,17 +106,13 @@ def _create_client(self, action_result, service='sts', new_region=None):
aws_access_key_id=self._access_key,
aws_secret_access_key=self._secret_key,
aws_session_token=self._token,
config=boto_config
config=boto_config,
)

else:
self.debug_print("Creating boto3 client without API keys")

self._client = client(
'sts',
region_name=self._region,
config=boto_config
)
self._client = client("sts", region_name=self._region, config=boto_config)
except Exception as e:
return action_result.set_status(phantom.APP_ERROR, "Could not create boto3 client: {0}".format(e))

Expand Down Expand Up @@ -163,7 +159,7 @@ def _handle_test_connectivity(self, param):
if not self._create_client(action_result):
return action_result.get_status()

ret_val, resp_json = self._make_boto_call(action_result, 'get_caller_identity')
ret_val, resp_json = self._make_boto_call(action_result, "get_caller_identity")

if phantom.is_fail(ret_val):
self.save_progress("Test Connectivity Failed.")
Expand All @@ -178,35 +174,35 @@ def _handle_assume_role(self, param):

action_result = self.add_action_result(ActionResult(dict(param)))

role_session_name = param.get('role_session_name',
DEFAULT_ROLE_SESSION_NAME)
external_id = param.get('external_id')
role_arn = param.get('role_arn')
role_session_duration = param.get('role_session_duration',
DEFAULT_ROLE_SESSION_DURATION)
region = param.get('region')
role_session_name = param.get("role_session_name", DEFAULT_ROLE_SESSION_NAME)
external_id = param.get("external_id")
role_arn = param.get("role_arn")
role_session_duration = param.get("role_session_duration", DEFAULT_ROLE_SESSION_DURATION)
region = param.get("region")
if not region:
region = self._region
for region_name, region_value in STS_REGION_DICT.items():
if region_value == region:
region = region_name

# create client
if phantom.is_fail(self._create_client(action_result, service='sts', new_region=region)):
if phantom.is_fail(self._create_client(action_result, service="sts", new_region=region)):
return action_result.get_status()

# make boto3 call
if external_id:
ret_val, resp_json = self._make_boto_call(action_result, 'assume_role',
RoleSessionName=role_session_name,
RoleArn=role_arn,
ExternalId=external_id,
DurationSeconds=role_session_duration)
ret_val, resp_json = self._make_boto_call(
action_result,
"assume_role",
RoleSessionName=role_session_name,
RoleArn=role_arn,
ExternalId=external_id,
DurationSeconds=role_session_duration,
)
else:
ret_val, resp_json = self._make_boto_call(action_result, 'assume_role',
RoleSessionName=role_session_name,
RoleArn=role_arn,
DurationSeconds=role_session_duration)
ret_val, resp_json = self._make_boto_call(
action_result, "assume_role", RoleSessionName=role_session_name, RoleArn=role_arn, DurationSeconds=role_session_duration
)
if phantom.is_fail(ret_val):
return action_result.get_status()

Expand All @@ -224,10 +220,10 @@ def handle_action(self, param):

self.debug_print("action_id", self.get_action_identifier())

if action_id == 'test_connectivity':
if action_id == "test_connectivity":
ret_val = self._handle_test_connectivity(param)

elif action_id == 'assume_role':
elif action_id == "assume_role":
ret_val = self._handle_assume_role(param)

return ret_val
Expand All @@ -249,10 +245,10 @@ def main():

argparser = argparse.ArgumentParser()

argparser.add_argument('input_test_json', help='Input Test JSON file')
argparser.add_argument('-u', '--username', help='username', required=False)
argparser.add_argument('-p', '--password', help='password', required=False)
argparser.add_argument('-v', '--verify', action='store_true', help='verify', required=False, default=False)
argparser.add_argument("input_test_json", help="Input Test JSON file")
argparser.add_argument("-u", "--username", help="username", required=False)
argparser.add_argument("-p", "--password", help="password", required=False)
argparser.add_argument("-v", "--verify", action="store_true", help="verify", required=False, default=False)

args = argparser.parse_args()
session_id = None
Expand All @@ -265,28 +261,29 @@ def main():

# User specified a username but not a password, so ask
import getpass

password = getpass.getpass("Password: ")

if username and password:
try:
login_url = AwsSecureTokenServiceConnector._get_phantom_base_url() + '/login'
login_url = AwsSecureTokenServiceConnector._get_phantom_base_url() + "/login"

print("Accessing the Login page")
r = requests.get(login_url, verify=verify, timeout=DEFAULT_TIMEOUT)
csrftoken = r.cookies['csrftoken']
csrftoken = r.cookies["csrftoken"]

data = dict()
data['username'] = username
data['password'] = password
data['csrfmiddlewaretoken'] = csrftoken
data["username"] = username
data["password"] = password
data["csrfmiddlewaretoken"] = csrftoken

headers = dict()
headers['Cookie'] = 'csrftoken=' + csrftoken
headers['Referer'] = login_url
headers["Cookie"] = "csrftoken=" + csrftoken
headers["Referer"] = login_url

print("Logging into Platform to get the session id")
r2 = requests.post(login_url, verify=verify, data=data, headers=headers, timeout=DEFAULT_TIMEOUT)
session_id = r2.cookies['sessionid']
session_id = r2.cookies["sessionid"]
except Exception as e:
print("Unable to get session id from the platform. Error: " + str(e))
sys.exit(1)
Expand All @@ -300,14 +297,14 @@ def main():
connector.print_progress_message = True

if session_id is not None:
in_json['user_session_token'] = session_id
connector._set_csrf_info(csrftoken, headers['Referer'])
in_json["user_session_token"] = session_id
connector._set_csrf_info(csrftoken, headers["Referer"])

ret_val = connector._handle_action(json.dumps(in_json), None)
print(json.dumps(json.loads(ret_val), indent=4))

sys.exit(0)


if __name__ == '__main__':
if __name__ == "__main__":
main()
46 changes: 23 additions & 23 deletions awssts_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@
# either express or implied. See the License for the specific language governing permissions
# and limitations under the License.
STS_JSON_ACCESS_KEY = "access_key"
STS_JSON_SECRET_KEY = "secret_key"
STS_JSON_SECRET_KEY = "secret_key" # pragma: allowlist secret

STS_REGION_DICT = {
"US East (Ohio)": "us-east-1",
"US East (N. Virginia)": "us-east-2",
"US West (N. California)": "us-west-1",
"US West (Oregon)": "us-west-2",
"Canada (Central)": "ca-central-1",
"Asia Pacific (Mumbai)": "ap-south-1",
"Asia Pacific (Tokyo)": "ap-northeast-1",
"Asia Pacific (Seoul)": "ap-northeast-2",
"Asia Pacific (Singapore)": "ap-southeast-1",
"Asia Pacific (Sydney)": "ap-southeast-2",
"China (Ningxia)": "cn-northwest-1",
"EU (Frankfurt)": "eu-central-1",
"EU (Ireland)": "eu-west-1",
"EU (London)": "eu-west-2",
"South Americia (Sao Paulo)": "sa-east-1",
"US GovCloud East": "us-gov-east-1",
"US GovCloud West": "us-gov-west-1",
}
"US East (Ohio)": "us-east-1",
"US East (N. Virginia)": "us-east-2",
"US West (N. California)": "us-west-1",
"US West (Oregon)": "us-west-2",
"Canada (Central)": "ca-central-1",
"Asia Pacific (Mumbai)": "ap-south-1",
"Asia Pacific (Tokyo)": "ap-northeast-1",
"Asia Pacific (Seoul)": "ap-northeast-2",
"Asia Pacific (Singapore)": "ap-southeast-1",
"Asia Pacific (Sydney)": "ap-southeast-2",
"China (Ningxia)": "cn-northwest-1",
"EU (Frankfurt)": "eu-central-1",
"EU (Ireland)": "eu-west-1",
"EU (London)": "eu-west-2",
"South Americia (Sao Paulo)": "sa-east-1",
"US GovCloud East": "us-gov-east-1",
"US GovCloud West": "us-gov-west-1",
}

DEFAULT_TIMEOUT = 30
DEFAULT_ROLE_SESSION_DURATION = 3600
DEFAULT_ROLE_SESSION_NAME = 'Request_from_Phantom'
ASSUME_ROLE_SUCCESS_MSG = 'Successfully retrieved assume role credentials from region {}'
ASSUME_ROLE_CREDENTIALS_FAILURE_MSG = 'Failed to retrieve EC2 role credentials'
ASSUME_ROLE_BAD_ASSET_CONFIG_MSG = 'Please provide access keys or select assume role check box in asset configuration'
DEFAULT_ROLE_SESSION_NAME = "Request_from_Phantom"
ASSUME_ROLE_SUCCESS_MSG = "Successfully retrieved assume role credentials from region {}"
ASSUME_ROLE_CREDENTIALS_FAILURE_MSG = "Failed to retrieve EC2 role credentials"
ASSUME_ROLE_BAD_ASSET_CONFIG_MSG = "Please provide access keys or select assume role check box in asset configuration"
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[tool.black]
line-length = 145
target-version = ['py39']
verbose = true

[tool.isort]
line_length = 145
profile = "black"
1 change: 1 addition & 0 deletions release_notes/1.2.11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Updated dependencies to resolve security vulnerabilities [PSAAS-20398]
5 changes: 1 addition & 4 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
[flake8]
max-line-length = 145
max-complexity = 28
extend-ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292

[isort]
line_length = 145
extend-ignore = F403,E128,E126,E121,E127,E731,E201,E202,E203,E701,F405,E722,D,W503
Binary file not shown.
Binary file removed wheels/shared/six-1.16.0-py2.py3-none-any.whl
Binary file not shown.
Binary file removed wheels/shared/urllib3-1.26.17-py2.py3-none-any.whl
Binary file not shown.

0 comments on commit 9003b8b

Please sign in to comment.