- 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
Version | Date | Notes |
---|---|---|
1.0.0 | 02/2021 | Initial Release |
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.
- 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.
This app supports the IBM Resilient SOAR Platform and the IBM Cloud Pak for Security.
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.
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.
The app does support a proxy server.
- 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.
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 |
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.
- 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')
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)
- 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))
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).
- 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)))
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.
- 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"]
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)
- 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))
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)
- 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))
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.
- 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 '')
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.
- 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"
}
]
}
}
aws_instances
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 |
aws_security_groups
Column Name | API Access Name | Type |
---|---|---|
GroupName | groupname |
text |
Description | sgdescription |
text |
GroupId | sggroupid |
text |
OwnerID | sgownerid |
text |
VpcId | vpcid |
text |
Display Name | API Access Name |
---|---|
AWS Instance ID | aws_instance_id |
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 |
Refer to the documentation listed in the Requirements section for troubleshooting information.
This is a IBM Community provided App. Please search the Community https://ibm.biz/resilientcommunity for assistance.