fn_aws Functions for IBM Resilient SOAR
Table of Contents
- Release Notes
- Overview
- Requirements
- Installation
- Function - AWS: create tags
- Function - AWS: Lambda invoke function
- Function - AWS: EC2 change instance status
- Function - AWS: EC2 describe Security Group
- Function - AWS: EC2 modify security groups
- Function - AWS: EC2 create snapshot
- Function - AWS: EC2 describe Instance
- Function - AWS: delete key pair
- Data Table - AWS Instances
- Data Table - AWS Security Groups
- Custom Artifact Types
- Rules
- Troubleshooting & Support
Release Notes
Version | Date | Notes |
---|---|---|
1.0.0 | 02/2021 | Initial Release |
Overview
Resilient Circuits Components for 'fn_aws'
IBM Resilient integration with AWS. Ability to orchestrate with AWS in information gathering activities such as getting data from EC2 Instances or Security Groups, as well as performing actions like stopping/terminating EC2 Instances, creating snapshots, assigning security groups, tagging objects, deleting key pairs and execution of Lambda functions. The use of specific credentials (access keys) in each action is allowed if required.
Key Features
- Retrieve comprehensive information about AWS EC2 instances and security groups affected by a security incident.
- Multiple search criteria, and many objects can be queried at once.
- Create tags for AWS resources.
- Ability to create AMI copies of an Instance, and Volume snapshots.
- Replace the assigned security groups of an instance.
- Start, Stop, Hibernate o Terminate one or more instances.
- Delete compromised key pairs.
- Execute Lambda functions synchronously, whether with input event or not.
Requirements
This app supports the IBM Resilient SOAR Platform and the IBM Cloud Pak for Security.
Resilient platform
The Resilient platform supports two app deployment mechanisms, App Host and integration server.
If deploying to a Resilient platform with an App Host, the requirements are:
- Resilient platform >=
39.0.6328
. - The app is in a container-based format (available from the AppExchange as a
zip
file).
If deploying to a Resilient platform with an integration server, the requirements are:
- Resilient platform >=
39.0.6328
. - The app is in the older integration format (available from the AppExchange as a
zip
file which contains atar.gz
file). - Integration server is running
resilient_circuits>=30.0.0
. - If using an API key account, make sure the account provides the following minimum permissions:
Name Permissions Org Data Read Function Read
The following Resilient platform guides provide additional information:
- App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
- Integration Server Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
- System Administrator Guide: provides the procedure to install, configure and deploy apps.
The above guides are available on the IBM Knowledge Center at ibm.biz/resilient-docs. On this web page, select your Resilient platform version. On the follow-on page, you can find the App Host Deployment Guide or Integration Server Guide by expanding Resilient Apps in the Table of Contents pane. The System Administrator Guide is available by expanding System Administrator.
Cloud Pak for Security
If you are deploying to IBM Cloud Pak for Security, the requirements are:
- IBM Cloud Pak for Security >= 1.4.
- Cloud Pak is configured with an App Host.
- The app is in a container-based format (available from the AppExchange as a
zip
file).
The following Cloud Pak guides provide additional information:
- App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings. From the Table of Contents, select Case Management and Orchestration & Automation > Orchestration and Automation Apps.
- System Administrator Guide: provides information to install, configure, and deploy apps. From the IBM Cloud Pak for Security Knowledge Center table of contents, select Case Management and Orchestration & Automation > System administrator.
These guides are available on the IBM Knowledge Center at ibm.biz/cp4s-docs. From this web page, select your IBM Cloud Pak for Security version. From the version-specific Knowledge Center page, select Case Management and Orchestration & Automation.
Proxy Server
The app does support a proxy server.
Installation
Install
- To install or uninstall an App or Integration on the Resilient platform, see the documentation at ibm.biz/resilient-docs.
- To install or uninstall an App on IBM Cloud Pak for Security, see the documentation at ibm.biz/cp4s-docs and follow the instructions above to navigate to Orchestration and Automation.
App Configuration
The following table provides the settings you need to configure the app. These settings are made in the app.config file. See the documentation discussed in the Requirements section for the procedure.
Config | Required | Example | Description |
---|---|---|---|
aws_access_key_id | Yes | AWS_ACCESS_KEY_ID |
Default AWS credentials to be used |
aws_secret_access_key | Yes | AWS_SECRET_ACCESS_KEY |
|
[another]_aws_access_key_id | No | AWS_ACCESS_KEY_ID |
You can use additional access_key/secret_access_key pairs. Prepend '[another-name]_' to 'aws_access_key_id' and 'aws_secret_access_key' in app.config, and then use '[another-name]' in funtion's field 'aws_access_key_name' |
[another]_aws_secret_access_key | No | AWS_SECRET_ACCESS_KEY |
|
default_region | Yes | sa-east-1 |
Default region name to be used when not other explicitly indicated in functions |
http_proxy | No | http://proxy:80 |
Indicate proxy if necessary |
https_proxy | No | http://proxy:80 |
Custom Layouts
Function - AWS: create tags
Assign Tags to resources. Multiple Tags and resources are allowed. Input multiple resources as: ami-xxx...xxx,i-xxx...xxx. If a tag key already exists, the value is overwritten with the new value.
IAM permissions required:
- ec2:CreateTags
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | - |
Where multiple values are allowed, enter them separated by commas |
aws_tag_names |
text |
Yes | "[{'Key': 'First_Tag', 'Value': 'First Value'}, {'Key': 'Second_Tag', 'Value': 'Second Value'}]" |
- |
Outputs:
results = {'success': True}
Example Pre-Process Script:
inputs.aws_resource_id = artifact.value
inputs.aws_region = 'sa-east-1'
inputs.aws_tag_names = "[{ 'Key': 'source', 'Value': 'Resilient' }, { 'Key': 'security_posture', 'Value': 'quarantine' }]"
Example Post-Process Script:
incident.addNote('Tags created')
Function - AWS: Lambda invoke function
Invokes synchronously a Lambda function.
If the function expects an input event, enter it as json in 'aws_lamdba_payload' input field.
If your Lambda function has logs output, the content of 'LogResult' of the lambda API invoke is return in results, otherwise it is return the entire response of the API for you to decide wich information is relevant (see API documentation: invoke)
IAM permissions required:
- lambda:InvokeFunction
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_lambda_function_name |
text |
Yes | - |
The lambda function name to invoke |
aws_lambda_payload |
text |
No | - |
The JSON that you want to provide to your Lambda function as input |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
Outputs:
results = {
"success": True,
"lambdaResult": "START RequestId: xx..xx Version: $LATEST\n
Received event: {}\n
...
lambda funcion output
...
END RequestId: xx..xx\n
REPORT RequestId: xx..xx\tDuration: 3051.58 ms\tBilled Duration: 3052 ms\t
Memory Size: 1024 MB\tMax Memory Used: 100 MB\tInit Duration: 585.11 ms\t\n"
}
Example Pre-Process Script:
inputs.aws_lambda_function_name = 'my-lambda-function'
inputs.aws_lambda_payload = '{"key1":"value1","key2":"value2"}'
Example Post-Process Script:
incident.addNote(str(results.lambdaResult))
Function - AWS: EC2 change instance status
A function to change the state of one or more instances. If hibernate is selected but the instances cannot hibernate successfully, a normal shutdown occurs. Terminate instances is also allowed (use with extremely careful).
IAM permissions required:
- ec2:StopInstances
- ec2:TerminateInstances
- ec2:StartInstances
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_instance_status |
select |
Yes | hibernate / stop / start / terminate |
- |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | - |
Where multiple values are allowed, enter them separated by commas |
Outputs:
results = {
"success": True,
"statusInstances": {
"StoppingInstances": [
{
"CurrentState": {
"Code": 64,
"Name": "stopping"
},
"InstanceId": "",
"PreviousState": {
"Code": 16,
"Name": "running"
}
}
],
"ResponseMetadata": {
"RequestId": "",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"x-amzn-requestid": "",
"cache-control": "",
"strict-transport-security": "",
"content-type": "",
"content-length": "",
"date": "",
"server": ""
},
"RetryAttempts": 0
}
}
}
Example Pre-Process Script:
inputs.aws_resource_id = artifact.value
inputs.aws_instance_status = 'stop'
Example Post-Process Script:
if results.success:
incident.addNote('Status change results: {}'.format(str(results.statusInstances)))
Function - AWS: EC2 describe Security Group
Gets the information of one o more Security Group listed in aws_resource_id. Searching by Security Group Id is default. Other options are available by changing aws_security_group_filter_name.
IAM permissions required:
- ec2:DescribeSecurityGroups
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | - |
Where multiple values are allowed, enter them separated by commas |
aws_security_group_filter_name |
select |
No | vpc-id / group-id / group-name |
Criteria for searching security groups |
Outputs:
results = {
"success": True,
"securityGroups": [
{
"Description": "",
"GroupName": "",
"IpPermissions": [
{
"FromPort": ,
"IpProtocol": "",
"IpRanges": [
{
"CidrIp": ""
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": ,
"UserIdGroupPairs": []
}
],
"OwnerId": "",
"GroupId": "",
"IpPermissionsEgress": [
{
"IpProtocol": "",
"IpRanges": [
{
"CidrIp": ""
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
],
"VpcId": ""
}
]
}
Example Pre-Process Script:
vpc = workflow.properties.instance_data.reservations[0]['Instances'][0]['VpcId']
inputs.aws_security_group_filter_name = 'vpc-id'
inputs.aws_resource_id = vpc
Example Post-Process Script:
# Processing if the function is a success
if(results.success):
sgs = results['securityGroups']
for inst in sgs:
# Add Row
row = incident.addRow("aws_security_groups")
row["groupname"] = inst["GroupName"]
row["sgdescription"] = inst["Description"]
row["sgownerid"] = inst["OwnerId"]
row["sggroupid"] = inst["GroupId"]
row["vpcid"] = inst["VpcId"]
Function - AWS: EC2 modify security groups
Replaces the Security Groups assigned to the Instance for those described in aws_security_groups (can be a list of security group Ids separated by comma)
IAM permissions required:
- ec2:ModifyInstanceAttribute
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | - |
Where multiple values are allowed, enter them separated by commas |
aws_security_groups |
text |
Yes | sg-03..bc,sg-01..bb |
List of security groups Ids separated by comma to set in the Instance |
Outputs:
results = {
"success": True
}
Example Pre-Process Script:
inputs.aws_resource_id = artifact.value
inputs.aws_security_groups = 'sg-032bea0e7926abfbc,sg-01e6a74a8527336bb'
Example Post-Process Script:
if results.success:
incident.addNote('Security Groups for Instance: {} were successfully changed.'.format(artifact.value))
Function - AWS: EC2 create snapshot
Creates a volume snapshot if aws_resource_id is a Volume (vol-xxx..xxx), or creates a complete image if it is an Instance Id (i-xxx...xxx)
IAM permissions required:
- ec2:CreateSnapshot
- ec2:CreateImage
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | For Volume snapshot enter: vol-xx..xx. To create AMI from Instance enter: i-xx..xx |
Where multiple values are allowed, enter them separated by commas |
Outputs:
results = {'success': True, 'snapshotId': 'ami-xx..xx'}
Example Pre-Process Script:
inputs.aws_resource_id = artifact.value
Example Post-Process Script:
if results.success:
incident.addNote('AMI from {} successfully created: {}'.format(artifact.value, results.snapshotId))
Function - AWS: EC2 describe Instance
Gets the information of one o more Instance listed in aws_resource_id. Searching by Instance Id is default. If 'image-id' is selected in aws_instances_filter_name, and one or more AMI id is entered, the output includes Instance information related to that AMI Id.
IAM permissions required:
- ec2:DescribeInstances
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_instances_filter_name |
select |
No | - |
Criteria for searching instances |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
aws_resource_id |
text |
Yes | - |
Where multiple values are allowed, enter them separated by commas |
Outputs:
results = {
"success": True,
"reservations": [
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0,
"ImageId": "",
"InstanceId": "",
"InstanceType": "",
"KeyName": "",
"LaunchTime": "",
"Monitoring": {
"State": ""
},
"Placement": {
"AvailabilityZone": "",
"GroupName": "",
"Tenancy": ""
},
"PrivateDnsName": "",
"PrivateIpAddress": "",
"ProductCodes": [],
"PublicDnsName": "",
"State": {
"Code": 80,
"Name": ""
},
"StateTransitionReason": "",
"SubnetId": "",
"VpcId": "",
"Architecture": "",
"BlockDeviceMappings": [
{
"DeviceName": "",
"Ebs": {
"AttachTime": "",
"DeleteOnTermination": ,
"Status": "",
"VolumeId": ""
}
}
],
"ClientToken": "",
"EbsOptimized": ,
"EnaSupport": ,
"Hypervisor": "",
"NetworkInterfaces": [
{
"Attachment": {
"AttachTime": "",
"AttachmentId": "",
"DeleteOnTermination": ,
"DeviceIndex": 0,
"Status": ""
},
"Description": "",
"Groups": [
{
"GroupName": "",
"GroupId": ""
}
],
"Ipv6Addresses": [],
"MacAddress": "",
"NetworkInterfaceId": "",
"OwnerId": "",
"PrivateDnsName": "",
"PrivateIpAddress": "",
"PrivateIpAddresses": [
{
"Primary": ,
"PrivateDnsName": "",
"PrivateIpAddress": ""
}
],
"SourceDestCheck": ,
"Status": "",
"SubnetId": "",
"VpcId": "",
"InterfaceType": ""
}
],
"RootDeviceName": "",
"RootDeviceType": "",
"SecurityGroups": [
{
"GroupName": "",
"GroupId": ""
}
],
"SourceDestCheck": ,
"StateReason": {
"Code": "",
"Message": ""
},
"Tags": [
{
"Key": "",
"Value": ""
}
],
"VirtualizationType": "",
"CpuOptions": {
"CoreCount": 1,
"ThreadsPerCore": 1
},
"CapacityReservationSpecification": {
"CapacityReservationPreference": ""
},
"HibernationOptions": {
"Configured":
},
"MetadataOptions": {
"State": "",
"HttpTokens": "",
"HttpPutResponseHopLimit": 1,
"HttpEndpoint": ""
},
"EnclaveOptions": {
"Enabled":
}
}
],
"OwnerId": "",
"ReservationId": ""
}
]
}
Example Pre-Process Script:
inputs.aws_resource_id = artifact.value
inputs.aws_region = 'sa-east-1'
Example Post-Process Script:
# Processing if the function is a success
if(results.success):
reservations = results.reservations
for rsv in reservations:
instances = rsv['Instances']
for inst in instances:
# Add Row
row = incident.addRow("aws_instances")
row["instanceid"] = inst["InstanceId"]
row["imageid"] = inst["ImageId"]
row["instancetype"] = inst["InstanceType"]
row["keyname"] = inst["KeyName"]
row["launchtime"] = inst["LaunchTime"]
row["availabilityzone"] = inst["Placement"]["AvailabilityZone"]
row["privatednsname"] = inst["PrivateDnsName"]
row["publicdnsname"] = inst["PublicDnsName"]
row["instance_state"] = inst["State"]["Name"]
row["vpcid"] = inst["VpcId"]
row["securitygroups"] = ('\n'.join(list(map(lambda x : x['GroupName']+' ('+x['GroupId']+')', inst["SecurityGroups"]))) if "SecurityGroups" in inst.keys() else '')
row["instance_tags"] = ('\n'.join(list(map(lambda x : x['Key']+': '+x['Value'], inst["Tags"]))) if "Tags" in inst.keys() else '')
Function - AWS: delete key pair
Deletes the specified key pair, by removing the public key from Amazon EC2.
Use with extremely careful.
The output shows the status prior to deletion.
IAM permissions required:
- ec2:DeleteKeyPair
- ec2:DescribeKeyPairs
Inputs:
Name | Type | Required | Example | Tooltip |
---|---|---|---|---|
aws_access_key_name |
text |
No | - |
OPTIONAL to use different access key than default's. If not present, "aws_access_key_id" and "aws_secret_access_key" pair from app.config are used. |
aws_key_name |
text |
Yes | frontend_dev |
key name |
aws_region |
text |
No | - |
If not present, "default_region" region from app.config is used |
Outputs:
results = {
"success": True,
"deletedKeyPair": {
"KeyPairId": "key-xx..xx",
"KeyFingerprint": "57:::::::::::::::::::52",
"KeyName": "frontend_dev",
"Tags": [
{
"Key": "origin",
"Value": "resilient"
}
]
}
}
Data Table - AWS Instances
API Name:
aws_instances
Columns:
Column Name | API Access Name | Type |
---|---|---|
AvailabilityZone | availabilityzone |
text |
ImageId | imageid |
text |
State | instance_state |
text |
InstanceId | instanceid |
text |
InstanceType | instancetype |
text |
KeyName | keyname |
text |
LaunchTime | launchtime |
text |
PrivateDnsName | privatednsname |
text |
PublicDnsName | publicdnsname |
text |
SecurityGroups | securitygroups |
textarea |
Tags | instance_tags |
textarea |
VpcId | vpcid |
text |
Data Table - AWS Security Groups
API Name:
aws_security_groups
Columns:
Column Name | API Access Name | Type |
---|---|---|
GroupName | groupname |
text |
Description | sgdescription |
text |
GroupId | sggroupid |
text |
OwnerID | sgownerid |
text |
VpcId | vpcid |
text |
Custom Artifact Types
Display Name | API Access Name |
---|---|
AWS Instance ID | aws_instance_id |
Rules
Rule Name | Object | Workflow Triggered |
---|---|---|
Example: AWS Describe instance | artifact | example_aws_describe_instance |
Example: AWS Describe Security Groups | artifact | example_aws_describe_security_groups |
Example: AWS Take an AMI snapshot and Terminate | artifact | example_aws_take_an_ami_snapshot_and_terminate |
Example: AWS Invoke lambda function | incident | example_aws_invoke_lamba_function |
Example: AWS Change Security Groups | artifact | example_aws_change_security_groups |
Example: AWS Tag instance | artifact | example_aws_tag_instance_as_quarantined |
Troubleshooting & Support
Refer to the documentation listed in the Requirements section for troubleshooting information.
For Support
This is a IBM Community provided App. Please search the Community https://ibm.biz/resilientcommunity for assistance.