From bc765138cab4039ae21f2f0657439f1bc2bec14a Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 11 Jun 2018 18:08:36 +0100 Subject: [PATCH 01/11] Add basic pack structure --- .gitignore | 1 - icon.png | Bin 0 -> 3850 bytes pack.yaml | 27 +++++++++++++++++++++++++++ requirements.txt | 3 +++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100755 icon.png create mode 100755 pack.yaml create mode 100755 requirements.txt diff --git a/.gitignore b/.gitignore index 260ff8d..a76c9cc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ dist/ downloads/ eggs/ .eggs/ -./lib/ lib64/ parts/ sdist/ diff --git a/icon.png b/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..8deb0c4b64314a63d135afce178229885eeac998 GIT binary patch literal 3850 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 SH^IAqr)Xmfqe27M$bSK;n4;GJ literal 0 HcmV?d00001 diff --git a/pack.yaml b/pack.yaml new file mode 100755 index 0000000..5120fdb --- /dev/null +++ b/pack.yaml @@ -0,0 +1,27 @@ +--- +ref: aws_boto3 +name : aws_boto3 +description : st2 content pack containing Amazon Web Services integrations using boto3. +keywords: + - aws + - amazon web services + - amazon + - boto3 + - ec2 + - sqs + - sns + - route53 + - cloud + - iam + - vpc + - s3 + - CloudFormation + - RDS + - SQS + - lambda + +version : 0.2.0 +author : StackStorm, Inc. +email : info@stackstorm.com +contributors: + - Jon Middleton diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..1492ac2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +six +boto3>=1.3.1,<1.4 +flask>=0.10.1 From 958c5972b035b54d669ebaff9afd1aaf3c1e31ce Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 11 Jun 2018 18:30:37 +0100 Subject: [PATCH 02/11] Files don't need to be +x --- icon.png | Bin pack.yaml | 0 requirements.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 icon.png mode change 100755 => 100644 pack.yaml mode change 100755 => 100644 requirements.txt diff --git a/icon.png b/icon.png old mode 100755 new mode 100644 diff --git a/pack.yaml b/pack.yaml old mode 100755 new mode 100644 diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 From 010426005ce1b116438ba0d55961033f6e7288fd Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Fri, 15 Jun 2018 12:53:56 +0100 Subject: [PATCH 03/11] Extra entries for .idea / editor saces in .gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index a76c9cc..624b1ce 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,10 @@ ENV/ # Rope project settings .ropeproject + +# PyCharm settings +.idea + +# Editor saves +*~ +*- From ad595f420767d312e51a3ae852457abca8412fb1 Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Fri, 15 Jun 2018 12:55:39 +0100 Subject: [PATCH 04/11] Add requirements-tests.txt --- requirements-tests.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 requirements-tests.txt diff --git a/requirements-tests.txt b/requirements-tests.txt new file mode 100644 index 0000000..e69de29 From 0deb04abc85b8151c855cdcc7fccd106d33170c5 Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Fri, 15 Jun 2018 12:56:21 +0100 Subject: [PATCH 05/11] Copy over actions from aws packs boto branch --- actions/assume_role.py | 33 +++++++++++++++++++++++++++++++++ actions/assume_role.yaml | 32 ++++++++++++++++++++++++++++++++ actions/boto3action.py | 32 ++++++++++++++++++++++++++++++++ actions/boto3action.yaml | 27 +++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 actions/assume_role.py create mode 100644 actions/assume_role.yaml create mode 100644 actions/boto3action.py create mode 100644 actions/boto3action.yaml diff --git a/actions/assume_role.py b/actions/assume_role.py new file mode 100644 index 0000000..4a307e3 --- /dev/null +++ b/actions/assume_role.py @@ -0,0 +1,33 @@ +import json +import boto3 + +from st2common.runners.base_action import Action + +from lib.util import json_serial + + +# pylint: disable=too-few-public-methods +class Boto3AssumeRoleRunner(Action): + def run( + self, role_arn, role_session_name, policy, + duration, external_id, serial_number, token_code): + client = boto3.client('sts') + kwargs = {} + kwargs['RoleArn'] = role_arn + kwargs['RoleSessionName'] = role_session_name + kwargs['DurationSeconds'] = duration + if policy is not None: + kwargs['Policy'] = policy + + if external_id is not None: + kwargs['ExternalId'] = external_id + + if serial_number is not None: + kwargs['SerialNumber'] = serial_number + + if token_code is not None: + kwargs['TokenCode'] = token_code + + response = client.assume_role(**kwargs) + response = json.loads(json.dumps(response, default=json_serial)) + return (True, response) diff --git a/actions/assume_role.yaml b/actions/assume_role.yaml new file mode 100644 index 0000000..12574c2 --- /dev/null +++ b/actions/assume_role.yaml @@ -0,0 +1,32 @@ +--- +name: "assume_role" +runner_type: "python-script" +description: "Assume a role to use with boto3action" +enabled: true +entry_point: "assume_role.py" +pack: "aws" +parameters: + role_arn: + type: "string" + description: "ARN of the role" + required: true + role_session_name: + type: "string" + description: "Name for the session" + default: "DefaultAssumeSession" + policy: + type: "string" + description: "Policy document" + duration: + type: integer + description: "Duration for the session" + default: 3600 + external_id: + type: "string" + description: "External Id" + serial_number: + type: "string" + description: "Serial number of the MFA" + token_code: + type: "string" + description: "Token code from the MFA" diff --git a/actions/boto3action.py b/actions/boto3action.py new file mode 100644 index 0000000..e93ae8d --- /dev/null +++ b/actions/boto3action.py @@ -0,0 +1,32 @@ +import json +import boto3 + +from st2common.runners.base_action import Action +from lib.util import json_serial + + +# pylint: disable=too-few-public-methods +class Boto3ActionRunner(Action): + def run(self, service, region, action_name, credentials, params): + client = None + response = None + + if credentials is not None: + session = boto3.Session( + aws_access_key_id=credentials['Credentials']['AccessKeyId'], + aws_secret_access_key=credentials['Credentials']['SecretAccessKey'], + aws_session_token=credentials['Credentials']['SessionToken']) + client = session.client(service, region_name=region) + else: + client = boto3.client(service, region_name=region) + + if client is None: + return (False, 'boto3 client creation failed') + + if params is not None: + response = getattr(client, action_name)(**params) + else: + response = getattr(client, action_name)() + + response = json.loads(json.dumps(response, default=json_serial)) + return (True, response) diff --git a/actions/boto3action.yaml b/actions/boto3action.yaml new file mode 100644 index 0000000..71932f3 --- /dev/null +++ b/actions/boto3action.yaml @@ -0,0 +1,27 @@ +--- +name: "boto3action" +runner_type: "python-script" +description: "Run any boto3 action" +enabled: true +entry_point: "boto3action.py" +pack: "aws" +parameters: + service: + type: "string" + description: "Name of the service to create client" + required: true + region: + type: "string" + description: "Region where action is performed" + required: true + action_name: + type: "string" + description: "Name of the action to run" + required: true + credentials: + type: "object" + description: "Response from assume role" + params: + type: object + description: "Parameters for the action" + From 6182cafb0b062a937b71b9303a8c74cdc764ca37 Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 18 Jun 2018 13:34:53 +0100 Subject: [PATCH 06/11] Add required lib file --- actions/lib/__init__.py | 0 actions/lib/util.py | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100755 actions/lib/__init__.py create mode 100644 actions/lib/util.py diff --git a/actions/lib/__init__.py b/actions/lib/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/actions/lib/util.py b/actions/lib/util.py new file mode 100644 index 0000000..cdcecc9 --- /dev/null +++ b/actions/lib/util.py @@ -0,0 +1,9 @@ +from datetime import date, datetime + + +# pylint: disable=too-few-public-methods +def json_serial(obj): + if isinstance(obj, (datetime, date)): + serial = obj.isoformat() + return serial + raise TypeError("Type %s not serializable" % type(obj)) From 9c3c4d424f224e846274a654f66f15f1f41f88b7 Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 18 Jun 2018 13:40:23 +0100 Subject: [PATCH 07/11] Correct pack name --- actions/assume_role.yaml | 2 +- actions/boto3action.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/assume_role.yaml b/actions/assume_role.yaml index 12574c2..42958ae 100644 --- a/actions/assume_role.yaml +++ b/actions/assume_role.yaml @@ -4,7 +4,7 @@ runner_type: "python-script" description: "Assume a role to use with boto3action" enabled: true entry_point: "assume_role.py" -pack: "aws" +pack: "aws_boto3" parameters: role_arn: type: "string" diff --git a/actions/boto3action.yaml b/actions/boto3action.yaml index 71932f3..3ebcc08 100644 --- a/actions/boto3action.yaml +++ b/actions/boto3action.yaml @@ -4,7 +4,7 @@ runner_type: "python-script" description: "Run any boto3 action" enabled: true entry_point: "boto3action.py" -pack: "aws" +pack: "aws_boto3" parameters: service: type: "string" From 5d89e2d1792957246777df4a3fd0c5cee63ebcf8 Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 18 Jun 2018 14:38:31 +0100 Subject: [PATCH 08/11] Add unit tests --- tests/test_action_assume_role.py | 31 +++++++++++++++++++++++++++++++ tests/test_action_boto3action.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/test_action_assume_role.py create mode 100644 tests/test_action_boto3action.py diff --git a/tests/test_action_assume_role.py b/tests/test_action_assume_role.py new file mode 100644 index 0000000..0df1204 --- /dev/null +++ b/tests/test_action_assume_role.py @@ -0,0 +1,31 @@ +# Licensed to the StackStorm, Inc ('StackStorm') under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and + +# from mock import MagicMock + +from st2tests.base import BaseActionTestCase + +from assume_role import Boto3AssumeRoleRunner + +__all__ = [ + 'Boto3AssumeRoleRunner' +] + + +class AssumeRoleTestCase(BaseActionTestCase): + action_cls = Boto3AssumeRoleRunner + + def test_run_is_instance(self): + action = self.get_action_instance(self.full_config) + self.assertIsInstance(action, self.action_cls) diff --git a/tests/test_action_boto3action.py b/tests/test_action_boto3action.py new file mode 100644 index 0000000..6ae3d54 --- /dev/null +++ b/tests/test_action_boto3action.py @@ -0,0 +1,31 @@ +# Licensed to the StackStorm, Inc ('StackStorm') under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and + +# from mock import MagicMock + +from st2tests.base import BaseActionTestCase + +from boto3action import Boto3ActionRunner + +__all__ = [ + 'Boto3ActionRunner' +] + + +class AssumeRoleTestCase(BaseActionTestCase): + action_cls = Boto3ActionRunner + + def test_run_is_instance(self): + action = self.get_action_instance(self.full_config) + self.assertIsInstance(action, self.action_cls) From ccad57114002d26b352648b3b076f5c8dc18c52e Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 18 Jun 2018 14:42:28 +0100 Subject: [PATCH 09/11] These actions have no config --- tests/test_action_assume_role.py | 2 +- tests/test_action_boto3action.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_action_assume_role.py b/tests/test_action_assume_role.py index 0df1204..15893e0 100644 --- a/tests/test_action_assume_role.py +++ b/tests/test_action_assume_role.py @@ -27,5 +27,5 @@ class AssumeRoleTestCase(BaseActionTestCase): action_cls = Boto3AssumeRoleRunner def test_run_is_instance(self): - action = self.get_action_instance(self.full_config) + action = self.get_action_instance() self.assertIsInstance(action, self.action_cls) diff --git a/tests/test_action_boto3action.py b/tests/test_action_boto3action.py index 6ae3d54..53a613d 100644 --- a/tests/test_action_boto3action.py +++ b/tests/test_action_boto3action.py @@ -27,5 +27,5 @@ class AssumeRoleTestCase(BaseActionTestCase): action_cls = Boto3ActionRunner def test_run_is_instance(self): - action = self.get_action_instance(self.full_config) + action = self.get_action_instance() self.assertIsInstance(action, self.action_cls) From e22fd24491f2ad04af232262c92d1105f879f41e Mon Sep 17 00:00:00 2001 From: Jon Middleton Date: Mon, 18 Jun 2018 17:58:30 +0100 Subject: [PATCH 10/11] An README that covers that this pack only has two actions --- README.md | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0ff0f3 --- /dev/null +++ b/README.md @@ -0,0 +1,295 @@ +# AWS Integration Pack + +The StackStorm AWS_boto3 integration pack boto3 actions in stackstorm dynamically. It has following features. + +- Uses boto3 configurations. Find more information on boto3 configuration in [boto3 documentation](http://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration). +- Ability to run cross region actions +- Ability to run cross account actions. + +## Prerequisites + +AWS and Stackstorm, up and running. + +## Boto3 documentation + +Boto3 contains detailed documentation and examples on each service. Follow link to find out about available services http://boto3.readthedocs.io/en/latest/reference/services/index.html + +## Setup + +### Install AWS_boto3 pack on StackStorm + +1. Install the [AWS_boto3 pack](https://github.com/stackstorm-exchange/stackstorm-aws_boto3): + + ``` + # Install AWS + st2 pack install aws_boto3 + + # Check it + st2 action list -p aws_boto3 + ``` + +### Configuration + +This pack currently has no configuration ([See issue #4](https://github.com/StackStorm-Exchange/stackstorm-aws_boto3/issues/4)). + + +The simplest way to configure and test boto3 is to use awscli. + +``` +pip install awscli +aws configure +aws ec2 describe-vpcs --region "us-west-1" +``` + +Then go ahead and install aws pack. `aws_boto3.boto3action` is ready to use, without additional configurations. + +``` +st2 run aws.boto3action service="ec2" action_name="describe_vpcs" region="us-west-1" +``` + +In addition, let’s assume these is a boto3 profile name `production`. Use `production` profile as follows. Boto3 documentation has more information on profiles. http://boto3.readthedocs.io/en/latest/guide/configuration.html#shared-credentials-file + +``` +st2 run aws_boto3.boto3action service="ec2" action_name="describe_vpcs" region="us-west-1" env="AWS_PROFILE=production" +``` + +## Example workflow - Create VPC + +action/create_vpc.yaml + +```yaml +name: "create_vpc" +runner_type: "mistral-v2" +description: "Create VPC with boto3action" +enabled: true +entry_point: "workflows/create_vpc.yaml" +parameters: + cidr_block: + type: "string" + description: "VPC CIDR block" + required: true + region: + type: "string" + description: "Region to create VPC" + required: true + subnet_cidr_block: + type: "string" + description: "Subnet CIDR block" + required: true + availability_zone: + type: "string" + description: "Availability zone to create subnet" + required: true + +``` + +action/workflows/create_vpc.yaml + + +```yaml +--- +version: '2.0' +aws.create_vpc: + type: direct + description: "Create VPC with boto3action" + input: + - cidr_block + - region + - subnet_cidr_block + - availability_zone + tasks: + create_vpc: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_vpc + region: <% $.region %> + params: <% dict(CidrBlock => $.cidr_block, InstanceTenancy => "default") %> + publish: + vpc_id: <% task(create_vpc).result.result.Vpc.VpcId %> + on-success: + - create_subnet + - create_igw + + create_subnet: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_subnet + region: <% $.region %> + params: <% dict(AvailabilityZone => $.availability_zone, CidrBlock => $.subnet_cidr_block, VpcId => $.vpc_id) %> + publish: + subnet_id: <% task(create_subnet).result.result.Subnet.SubnetId %> + on-success: + - create_route_table + + create_igw: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_internet_gateway + region: <% $.region %> + publish: + igw_id: <% task(create_igw).result.result.InternetGateway.InternetGatewayId %> + on-success: + - attach_igw + + attach_igw: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: attach_internet_gateway + region: <% $.region %> + params: <% dict(VpcId => $.vpc_id, InternetGatewayId => $.igw_id) %> + on-success: + - create_route_igw + + create_route_table: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_route_table + region: <% $.region %> + params: <% dict(VpcId => $.vpc_id) %> + publish: + route_table_id: <% task(create_route_table).result.result.RouteTable.RouteTableId %> + on-success: + - attach_route_tables + + attach_route_tables: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: associate_route_table + region: <% $.region %> + params: <% dict(SubnetId => $.subnet_id, RouteTableId => $.route_table_id) %> + on-success: + - create_route_igw + + create_route_igw: + join: 2 + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_route + region: <% $.region %> + params: <% dict(RouteTableId => $.route_table_id, GatewayId => $.igw_id, DestinationCidrBlock => '0.0.0.0/0') %> +``` + +Use this workflow as follows, + +``` +st2 run aws_boto3.create_vpc cidr_block="172.18.0.0/16" region="us-west-2" availability_zone="us-west-2b" subnet_cidr_block="172.18.0.0/24" +``` + +# Create VPC workflow with assume_role + + Let’s assume we have two aws accounts. First aws account, 123456, is already configured to use boto3. Second aws account, 456789, has a `IAM` role `st2_role`. We can assume this role, then use `create_vpc` workflow to create vpc in aws account 456789. + +action/workflows/create_vpc.yaml + +```yaml +--- +version: '2.0' +aws_boto3.create_vpc: + type: direct + description: "Create VPC with boto3action" + input: + - cidr_block + - region + - subnet_cidr_block + - availability_zone + tasks: + assume_role: + action: aws_boto3.assume_role + input: + role_arn: “arn:aws:iam:456789:role/st2_role” + publish: + credentials: <% task(assume_role).result.result %> + on-success: + - create_vpc + + create_vpc: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_vpc + region: <% $.region %> + params: <% dict(CidrBlock => $.cidr_block, InstanceTenancy => "default") %> + credentials: <% $.credentials %> + publish: + vpc_id: <% task(create_vpc).result.result.Vpc.VpcId %> + on-success: + - create_subnet + - create_igw + + create_subnet: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_subnet + region: <% $.region %> + params: <% dict(AvailabilityZone => $.availability_zone, CidrBlock => $.subnet_cidr_block, VpcId => $.vpc_id) %> + credentials: <% $.credentials %> + publish: + subnet_id: <% task(create_subnet).result.result.Subnet.SubnetId %> + on-success: + - create_route_table + + create_igw: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_internet_gateway + region: <% $.region %> + credentials: <% $.credentials %> + publish: + igw_id: <% task(create_igw).result.result.InternetGateway.InternetGatewayId %> + on-success: + - attach_igw + + attach_igw: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: attach_internet_gateway + region: <% $.region %> + params: <% dict(VpcId => $.vpc_id, InternetGatewayId => $.igw_id) %> + credentials: <% $.credentials %> + on-success: + - create_route_igw + + create_route_table: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_route_table + region: <% $.region %> + params: <% dict(VpcId => $.vpc_id) %> + credentials: <% $.credentials %> + publish: + route_table_id: <% task(create_route_table).result.result.RouteTable.RouteTableId %> + on-success: + - attach_route_tables + + attach_route_tables: + action: aws_boto3.boto3action + input: + service: ec2 + action_name: associate_route_table + region: <% $.region %> + params: <% dict(SubnetId => $.subnet_id, RouteTableId => $.route_table_id) %> + credentials: <% $.credentials %> + on-success: + - create_route_igw + + create_route_igw: + join: 2 + action: aws_boto3.boto3action + input: + service: ec2 + action_name: create_route + region: <% $.region %> + params: <% dict(RouteTableId => $.route_table_id, GatewayId => $.igw_id, DestinationCidrBlock => '0.0.0.0/0') %> + credentials: <% $.credentials %> +``` From 82ec017327865fadc43bd14a17656889682776f4 Mon Sep 17 00:00:00 2001 From: Lindsay Hill Date: Mon, 18 Jun 2018 12:14:12 -0700 Subject: [PATCH 11/11] README cleanup --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c0ff0f3..e29b215 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # AWS Integration Pack -The StackStorm AWS_boto3 integration pack boto3 actions in stackstorm dynamically. It has following features. +This pack uses boto3 actions in StackStorm dynamically. It has the following features: - Uses boto3 configurations. Find more information on boto3 configuration in [boto3 documentation](http://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration). -- Ability to run cross region actions +- Ability to run cross region actions. - Ability to run cross account actions. ## Prerequisites @@ -12,7 +12,7 @@ AWS and Stackstorm, up and running. ## Boto3 documentation -Boto3 contains detailed documentation and examples on each service. Follow link to find out about available services http://boto3.readthedocs.io/en/latest/reference/services/index.html +Boto3 contains detailed documentation and examples on each service. See more about available services here: http://boto3.readthedocs.io/en/latest/reference/services/index.html ## Setup @@ -32,8 +32,7 @@ Boto3 contains detailed documentation and examples on each service. Follow link This pack currently has no configuration ([See issue #4](https://github.com/StackStorm-Exchange/stackstorm-aws_boto3/issues/4)). - -The simplest way to configure and test boto3 is to use awscli. +The simplest way to configure and test boto3 is to use `awscli`. ``` pip install awscli @@ -47,12 +46,15 @@ Then go ahead and install aws pack. `aws_boto3.boto3action` is ready to use, wit st2 run aws.boto3action service="ec2" action_name="describe_vpcs" region="us-west-1" ``` -In addition, let’s assume these is a boto3 profile name `production`. Use `production` profile as follows. Boto3 documentation has more information on profiles. http://boto3.readthedocs.io/en/latest/guide/configuration.html#shared-credentials-file +Let’s assume there is a boto3 profile name `production`. Use it like this: ``` st2 run aws_boto3.boto3action service="ec2" action_name="describe_vpcs" region="us-west-1" env="AWS_PROFILE=production" ``` +See the Boto3 documentation for more [information on profiles](http://boto3.readthedocs.io/en/latest/guide/configuration.html#shared-credentials-file). + + ## Example workflow - Create VPC action/create_vpc.yaml @@ -176,15 +178,15 @@ aws.create_vpc: params: <% dict(RouteTableId => $.route_table_id, GatewayId => $.igw_id, DestinationCidrBlock => '0.0.0.0/0') %> ``` -Use this workflow as follows, +Run it: ``` st2 run aws_boto3.create_vpc cidr_block="172.18.0.0/16" region="us-west-2" availability_zone="us-west-2b" subnet_cidr_block="172.18.0.0/24" ``` -# Create VPC workflow with assume_role +## Create VPC workflow with assume_role - Let’s assume we have two aws accounts. First aws account, 123456, is already configured to use boto3. Second aws account, 456789, has a `IAM` role `st2_role`. We can assume this role, then use `create_vpc` workflow to create vpc in aws account 456789. +Let’s assume we have two aws accounts. First aws account, 123456, is already configured to use boto3. Second aws account, 456789, has a `IAM` role `st2_role`. We can assume this role, then use `create_vpc` workflow to create vpc in aws account 456789. action/workflows/create_vpc.yaml