├── .ec2ssh ├── .editorconfig ├── .envrc.sample ├── .github └── pull_request_template.md ├── .gitignore ├── README.md ├── ansible ├── README.md ├── group_vars │ ├── all │ └── bastion ├── host_vars │ ├── PCParityPoA1a │ ├── PCParityPoA1c │ ├── PCParityPoA2a │ └── PCParityPoA2c ├── hosts.sample ├── requirements.yml ├── roles │ ├── bastion │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ │ └── .gitkeep │ ├── common │ │ ├── files │ │ │ └── config │ │ └── tasks │ │ │ └── main.yml │ └── private-chain │ │ ├── tasks │ │ └── main.yml │ │ └── templates │ │ └── .gitkeep └── site.yml ├── create_eip.sh ├── deploy.sh ├── fix_api.sh ├── logo.png ├── packer ├── ansible │ ├── README.md │ ├── group_vars │ │ └── all │ ├── hosts.sample │ ├── motd │ ├── roles │ │ └── parity │ │ │ ├── tasks │ │ │ └── main.yml │ │ │ └── templates │ │ │ ├── PCParityPoA1a_key.j2 │ │ │ ├── PCParityPoA1c_key.j2 │ │ │ ├── PCParityPoA2a_key.j2 │ │ │ ├── PCParityPoA2c_key.j2 │ │ │ ├── config.toml.j2 │ │ │ ├── node.pwds.j2 │ │ │ ├── parity.conf.j2 │ │ │ └── spec.json.j2 │ └── site.yml ├── parity-poa.json └── parity-poa.yml ├── private_chain.yml └── template.yaml /.ec2ssh: -------------------------------------------------------------------------------- 1 | path '/Users/YOU_USER_NAME_HERE/.ssh/config' 2 | aws_keys( 3 | default: { 4 | access_key_id: ENV['AWS_ACCESS_KEY_ID'], 5 | secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] 6 | }, 7 | ) 8 | regions ENV['AWS_REGION'] || ENV['AMAZON_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1' 9 | 10 | host_line < 12 | HostName <%= dns_name || public_ip_address || private_ip_address %> 13 | User ubuntu 14 | IdentityFile ~/.ssh/private-chain 15 | StrictHostKeyChecking no 16 | END 17 | 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | [*.py] 9 | indent_style = space 10 | indent_size = 4 11 | -------------------------------------------------------------------------------- /.envrc.sample: -------------------------------------------------------------------------------- 1 | # --- ALIS --- 2 | 3 | ## ALISのアプリケーションID 4 | ## すべてのサブシステムで同じ値を使う必要がある 5 | export ALIS_APP_ID=ishii 6 | 7 | # CloudFormationで生成されたAPI GatewayのAPI ID 8 | # スクリプトから各APIにIAM認証をかけるのに利用している 9 | # 現状、SAMがIAM認証をサポートしていないため 10 | # TODO: SAMがIAM認証をサポートしたらteplate.yamlに集約してこの値とスクリプトを除却する 11 | # - see: https://github.com/awslabs/serverless-application-model/issues/248 12 | export PRIVATE_CHAIN_REST_API_ID=pe6odilrre 13 | 14 | # --- AWS --- 15 | 16 | ## aws-cli 17 | ## aws-cliが依存する環境変数。 18 | ## - see: https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-environment.html 19 | ## .credentialsファイルよりもこちらの環境変数が優先される 20 | ## Cloud formationのデプロイやS3作成など重要な操作を行うため、管理者レベルの権限を持つ必要がある。 21 | export AWS_DEFAULT_REGION=ap-northeast-1 22 | export AWS_ACCESS_KEY_ID=AKIAJZCGSXXXXXXXXXX 23 | export AWS_SECRET_ACCESS_KEY=iU6/q6ls5i5pDBPxxxxxxxxxxxxxxxxxxxx 24 | 25 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## 概要 2 | * なぜこの変更をするのか、 3 | * 課題は何か、 4 | * これによってどう解決されるのか、 5 | * など、この変更に対する概要を記載 6 | 7 | ## 関連URL 8 | 9 | ## 影響範囲(ユーザ) 10 | * 影響を与えるユーザは誰か 11 | 12 | ## 影響範囲(システム) 13 | * 影響を与えるシステムはどこか 14 | 15 | - サーバレス 16 | - フロントエンド 17 | - プライベートチェーン 18 | 19 | ## 技術的変更点概要 20 | * なにをどう変更したか 21 | * ロジックがどういう手順で動くのか、 22 | * DBからどういうクエリで何をとってそれに何を処理するのか、 23 | 24 | ## 使い方 25 | * 使い方の説明 26 | * バグの場合は再現条件 27 | 28 | ## DBやDBへのクエリに対する変更 29 | 30 | * 変更されるクエリ (変更前、変更後) 31 | * 新規に追加されるクエリ 32 | * 観点: 33 | * index周りの指定は適切か 34 | * 想定される対象のデータ量 35 | * 想定されるデータ量が大量のとき大丈夫か (ダメな場合、いつまでにどうにかする予定があるのか、忘れないために別チケットを用意したか) 36 | 37 | ## ブロックチェーンへの影響 38 | 39 | * ブロックチェーンを参照するか 40 | * ブロックチェーンへのトランザクションが発生するか 41 | 42 | ## 個人情報の取り扱いに変更のあるリリースか 43 | 44 | * メールアドレスや住所情報等、個人情報にあたるものは細心の注意が必要 45 | 46 | ## ユーザの財産に関係のあるリリースか 47 | 48 | * ユーザの財産に関わる機能には細心の注意を払う必要がある 49 | 50 | ## ロギング 51 | 52 | * ロギングは考慮されているか 53 | * ログをはくとしたらいつ、どこで、どこに、どのようなログが吐かれるか 54 | 55 | ## ユニットテスト 56 | * ユニットテストが書かれているか 57 | * 書かれていない場合、妥当な理由があるか。それは何か 58 | 59 | ## テスト結果とテスト項目 60 | 61 | * [ ] テストする際の項目を、このように、チェック可能な形式で記載する。 62 | * [ ] テストしたらチェックを入れていく。 63 | 64 | 65 | ## 保留した項目とTODOリスト 66 | 67 | 箇条書きで書く。可能な限り次のチケットを作る。 68 | 69 | ## 注意点・その他 70 | 71 | * この作業で特に注意する点があれば記載する 72 | * その他、補足事項があれば記載する 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | .envrc 3 | 4 | # IDE 5 | .idea 6 | 7 | # packer, ansible 8 | *.retry 9 | hosts 10 | ansible/roles/ChromaticHQ.aws-cli/* 11 | ansible/roles/leesoh.pipenv/* 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![ALIS](./logo.png)](https://alis.to) 2 | An Ethereum private-chain environment for the [ALIS](https://alis.to) 3 | that using Parity PoA. 4 | 5 | # Prerequisite 6 | - aws-cli 7 | - packer 8 | - ansible 9 | - jq 10 | - direnv 11 | 12 | # Environment valuables 13 | 14 | ```bash 15 | # Create .envrc to suit your environment. 16 | cp -pr .envrc.sample .envrc 17 | direnv edit 18 | ``` 19 | 20 | # Preparation 21 | 22 | ## Packer 23 | Build an AMI that the nodes of Parity PoA. 24 | 25 | ### Parity resources 26 | You have to change ETH account keys when you use this in production. 27 | - `./packer/ansible/roles/parity/templates/PCParityPoA*_key.j2` 28 | 29 | Also `spec.json`. 30 | - `./packer/ansible/roles/parity/templates/spec.json.j2` 31 | 32 | ### Build 33 | ```bash 34 | cd ./packer/ 35 | packer build ./parity-poa.json 36 | ``` 37 | 38 | ## Create EC2 KeyPair 39 | ```bash 40 | aws ec2 create-key-pair --key-name private-chain 41 | ``` 42 | 43 | ## Create EIP 44 | 45 | ```bash 46 | ./create_eip.sh 47 | ``` 48 | 49 | # Set SSM valuables 50 | You have to specify SSM valuables as can as possible. 51 | Such as IAM and EIP information you created above. 52 | - See: https://github.com/AlisProject/environment 53 | 54 | 55 | # CloudFormation 56 | 57 | ## Deployment 58 | 59 | ```bash; 60 | ./deploy.sh 61 | ``` 62 | 63 | ### Fix API settings via a script 64 | 65 | ```bash 66 | # Get API ID 67 | aws apigateway get-rest-apis | jq -r --arg ALIS_API_NAME "${ALIS_APP_ID}api" '.items[] | select(.name==$ALIS_API_NAME).id' 68 | 69 | # Set API ID to PRIVATE_CHAIN_REST_API_ID in .envrc 70 | direnv edit 71 | 72 | ./fix_api.sh 73 | ``` 74 | 75 | ## After deployment 76 | 77 | ### Connect Instances via Bastion 78 | - Prerequisite: [ec2ssh](https://github.com/mirakui/ec2ssh) 79 | 80 | ```bash 81 | cp -p .ec2ssh ~/ 82 | vi ~/.ec2ssh 83 | ``` 84 | 85 | Fix some point for your environment. 86 | Then execute `ec2ssh update`. 87 | 88 | ```bash 89 | echo -e \\nHost PC*\\n ProxyCommand ssh -W %h:%p Bastion >> ~/.ssh/config 90 | ec2ssh update 91 | ``` 92 | 93 | Now you can connect: 94 | 95 | ```bash 96 | ssh PCParityPoA2a 97 | ``` 98 | 99 | Also you can use [tmuxinator](https://github.com/tmuxinator/tmuxinator). 100 | ```bash 101 | cp -p ./private_chain.yml ~/.tmuxinator/ 102 | mux private_chain 103 | ``` 104 | 105 | ### Configure servers. 106 | ```bash 107 | # You have to edit HostNames. 108 | vi ./ansible/roles/common/files/config 109 | 110 | # Also you have to specify your hosts. 111 | cd ansible 112 | cp -p hosts.sample hosts 113 | vi hosts 114 | 115 | # Run ansible 116 | ansible-galaxy install -p ./roles -r requirements.yml 117 | ansible-playbook -i hosts site.yml 118 | ``` 119 | 120 | ### Connect Parity nodes each other 121 | You can use `[parity dir]/enode.sh`. 122 | 123 | 124 | ### Migrate private chain contracts from Bastion server 125 | See: [Private chain contracts](https://github.com/AlisProject/private-chain-contracts) 126 | 127 | ### Fix template.yaml's `FIXME:` tags and deploy again 128 | Such as IAM Policies, and others. 129 | 130 | ### Set SSM valuables again 131 | - See: https://github.com/AlisProject/environment 132 | -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | # run 2 | ```bash 3 | # Add private key to ~/.ssh/private-chain 4 | 5 | # Add requirements 6 | ansible-galaxy install -p ./roles -r requirements.yml 7 | 8 | # Execute 9 | ansible-playbook -i hosts site.yml 10 | 11 | # Specify 12 | ansible-playbook -i hosts site.yml -l parity-poa --start-at "Install lsyncd" --step 13 | ansible-playbook -i hosts site.yml -l parity-poa --tags "tmp" 14 | ``` 15 | -------------------------------------------------------------------------------- /ansible/group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | parity_base_path: /root/.local/share/io.parity.ethereum 4 | parity_keys_path: /var/keys 5 | ethbase_password: YOURPASSWORDHERE 6 | supervisor_logs_path: /var/log/supervisor/jobs 7 | -------------------------------------------------------------------------------- /ansible/group_vars/bastion: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | contracts_path: /var/contracts 4 | private_chain_alis_token_address: "0x7ad8f90cfa071c8420e3f09fe0e413d0c47502e6" 5 | private_chain_main_signer_address: "0x7ad8f90cfa071c8420e3f09fe0e413d0c47502e6" 6 | 7 | erc20_bridge_path: /var/erc20-bridge 8 | -------------------------------------------------------------------------------- /ansible/host_vars/PCParityPoA1a: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | -------------------------------------------------------------------------------- /ansible/host_vars/PCParityPoA1c: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | -------------------------------------------------------------------------------- /ansible/host_vars/PCParityPoA2a: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | -------------------------------------------------------------------------------- /ansible/host_vars/PCParityPoA2c: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | -------------------------------------------------------------------------------- /ansible/hosts.sample: -------------------------------------------------------------------------------- 1 | [parity-poa:children] 2 | Parity1a 3 | Parity2a 4 | Parity1c 5 | Parity2c 6 | 7 | [bastion] 8 | Bastion ansible_python_interpreter=/usr/bin/python3 9 | 10 | [Parity1a] 11 | PCParityPoA1a 12 | [Parity2a] 13 | PCParityPoA2a 14 | [Parity1c] 15 | PCParityPoA1c 16 | [Parity2c] 17 | PCParityPoA2c 18 | -------------------------------------------------------------------------------- /ansible/requirements.yml: -------------------------------------------------------------------------------- 1 | # AWS CLI 2 | # https://github.com/leesoh/ansible-role-pipenv 3 | # https://github.com/ChromaticHQ/ansible-role-aws-cli 4 | - src: leesoh.pipenv 5 | - src: ChromaticHQ.aws-cli 6 | -------------------------------------------------------------------------------- /ansible/roles/bastion/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages 3 | apt: 4 | name: "{{ item }}" 5 | state: present 6 | update_cache: yes 7 | with_items: 8 | - build-essential 9 | - zlib1g-dev 10 | - libssl-dev 11 | 12 | - name: Create dirctries 13 | file: path={{ item }} state=directory owner=root group=root mode=0755 14 | with_items: 15 | - "{{ contracts_path }}" 16 | - "{{ erc20_bridge_path }}" 17 | 18 | - name: Clone resources 19 | git: 20 | repo: "{{ item.src }}" 21 | dest: "{{ item.dest }}" 22 | version: "{{ item.version }}" 23 | with_items: 24 | - { src: 'https://github.com/AlisProject/private-chain-contracts.git', dest: "{{ contracts_path }}", version: 'HEAD' } 25 | - { src: 'https://github.com/AlisProject/erc20-bridge.git', dest: "{{ erc20_bridge_path }}", version: 'HEAD' } 26 | - { src: 'https://github.com/riywo/ndenv', dest: "~/.ndenv", version: 'HEAD' } 27 | - { src: 'https://github.com/riywo/node-build.git', dest: "~/.ndenv/plugins/node-build", version: 'HEAD' } 28 | - { src: 'https://github.com/pyenv/pyenv.git', dest: "~/.pyenv", version: 'HEAD' } 29 | - { src: 'https://github.com/ethereum/vyper.git', dest: "~/vyper", version: 'v0.1.0-beta.7' } 30 | 31 | - name: Add lines to .bashrc 32 | lineinfile: 33 | path: ~/.bashrc 34 | line: "{{ item }}" 35 | insertbefore: EOF 36 | with_items: 37 | - 'export PATH="$HOME/.ndenv/bin:$PATH"' 38 | - 'eval "$(ndenv init -)"' 39 | - 'export PYENV_ROOT="$HOME/.pyenv"' 40 | - 'export PATH="$PYENV_ROOT/bin:$PATH"' 41 | - 'export PRIVATE_CHAIN_ALIS_TOKEN_ADDRESS={{ private_chain_alis_token_address }}' 42 | - 'export PRIVATE_CHAIN_MAIN_SIGNER_ADDRESS={{ private_chain_main_signer_address }}' 43 | 44 | - name: Install and prepare modules 45 | shell: "{{ item }}" 46 | args: 47 | chdir: "{{ contracts_path }}" 48 | with_items: 49 | - "~/.ndenv/bin/ndenv install" 50 | - "/root/.ndenv/shims/npm install -g yarn" 51 | - "~/.ndenv/bin/ndenv exec yarn" 52 | - "~/.ndenv/bin/ndenv exec yarn exec truffle -- install" 53 | 54 | - name: Prepare vyper virtual environment 55 | shell: "{{ item }}" 56 | with_items: 57 | - "/root/.pyenv/bin/pyenv install 3.6.7" 58 | - "/root/.pyenv/versions/3.6.7/bin/python -m venv ~/vyper-env" 59 | 60 | - name: Install vyper 61 | shell: "{{ item }}" 62 | with_items: 63 | - '/bin/bash -lc "source ~/vyper-env/bin/activate && cd ~/vyper && make"' 64 | 65 | - name: Install and prepare modules for erc20-bridge 66 | shell: "{{ item }}" 67 | environment: 68 | PYTHON: /root/.pyenv/versions/2.7.10/bin/python 69 | args: 70 | chdir: "{{ erc20_bridge_path }}" 71 | with_items: 72 | - "/root/.pyenv/bin/pyenv install 2.7.10" 73 | - "~/.ndenv/bin/ndenv install" 74 | - "/root/.ndenv/shims/npm install -g yarn" 75 | - "~/.ndenv/bin/ndenv exec yarn" 76 | -------------------------------------------------------------------------------- /ansible/roles/bastion/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlisProject/private-chain/76e7fcba94d3fa14c9abf04927f7c4da545a8794/ansible/roles/bastion/templates/.gitkeep -------------------------------------------------------------------------------- /ansible/roles/common/files/config: -------------------------------------------------------------------------------- 1 | # FIXME: Host names 2 | Host PCParityPoA1a 3 | StrictHostKeyChecking no 4 | UserKnownHostsFile=/dev/null 5 | HostName 10.1.0.5 6 | User ubuntu 7 | IdentityFile ~/.ssh/private-chain 8 | Host PCParityPoA1c 9 | StrictHostKeyChecking no 10 | UserKnownHostsFile=/dev/null 11 | HostName 10.1.0.22 12 | User ubuntu 13 | IdentityFile ~/.ssh/private-chain 14 | Host PCParityPoA2a 15 | StrictHostKeyChecking no 16 | UserKnownHostsFile=/dev/null 17 | HostName 10.1.0.4 18 | User ubuntu 19 | IdentityFile ~/.ssh/private-chain 20 | Host PCParityPoA2c 21 | StrictHostKeyChecking no 22 | UserKnownHostsFile=/dev/null 23 | HostName 10.1.0.20 24 | User ubuntu 25 | IdentityFile ~/.ssh/private-chain 26 | -------------------------------------------------------------------------------- /ansible/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add private key to each hosts 3 | copy: 4 | dest: "{{ item.dest }}" 5 | owner: "{{ item.owner }}" 6 | group: "{{ item.group }}" 7 | mode: 0600 8 | content: "{{ lookup('file', '~/.ssh/private-chain') }}" 9 | with_items: 10 | - { dest: "/home/ubuntu/.ssh/private-chain", owner: 'ubuntu', group: 'ubuntu' } 11 | - { dest: "/root/.ssh/private-chain", owner: 'root', group: 'root' } 12 | 13 | - name: Copy files 14 | copy: 15 | src: "{{ item.src }}" 16 | dest: "{{ item.dest }}" 17 | owner: "{{ item.owner }}" 18 | group: "{{ item.group }}" 19 | mode: 0644 20 | with_items: 21 | - { src: 'config', dest: "/home/ubuntu/.ssh/config", owner: 'ubuntu', group: 'ubuntu' } 22 | - { src: 'config', dest: "/root/.ssh/config", owner: 'root', group: 'root' } 23 | -------------------------------------------------------------------------------- /ansible/roles/private-chain/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get validator address 3 | shell: "cat {{ parity_keys_path }}/PrivateChain/{{ inventory_hostname }} | jq '.address' | sed 's/\"//g'" 4 | register: validator_address 5 | 6 | - name: Add validator to config.toml 7 | lineinfile: >- 8 | dest='{{ parity_base_path }}/config.toml' 9 | state=present 10 | backrefs=yes 11 | regexp='^{{ item.key }}.*' 12 | line='{{ item.key }} = {{ item.value }}' 13 | with_items: 14 | - { key: 'engine_signer', value: '"0x{{ validator_address.stdout }}"' } 15 | 16 | - name: Reload supervisor to start parity 17 | service: name=supervisor state=reloaded 18 | 19 | - pause: 20 | minutes: 1 21 | 22 | - name: enode tasks 23 | shell: "ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -f1 -d'/' | xargs echo" 24 | register: private_ips 25 | 26 | - shell: "curl --data '{\"jsonrpc\":\"2.0\",\"method\":\"parity_enode\",\"params\":[],\"id\":0}' -H \"Content-Type: application/json\" -X POST {{ item }}:8545 | jq '.result'" 27 | register: enodes 28 | with_items: '{{ private_ips.stdout }}' 29 | 30 | - file: path={{ parity_base_path }}/enode.sh state=touch owner=root group=root mode=0755 31 | 32 | - lineinfile: 33 | dest: '{{ parity_base_path }}/enode.sh' 34 | line: "curl --data '{\"jsonrpc\":\"2.0\",\"method\":\"parity_addReservedPeer\",\"params\":[{{ item }}],\"id\":0}' -H \"Content-Type: application/json\" -X POST localhost:8545" 35 | with_items: 36 | - '{{ enodes.results[0].stdout }}' 37 | 38 | -------------------------------------------------------------------------------- /ansible/roles/private-chain/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlisProject/private-chain/76e7fcba94d3fa14c9abf04927f7c4da545a8794/ansible/roles/private-chain/templates/.gitkeep -------------------------------------------------------------------------------- /ansible/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Parity configurations and start nodes. 4 | hosts: parity-poa 5 | remote_user: ubuntu 6 | become: yes 7 | 8 | roles: 9 | - common 10 | - private-chain 11 | 12 | - name: Bastion server configrations. 13 | hosts: bastion 14 | remote_user: ubuntu 15 | become: yes 16 | 17 | roles: 18 | - common 19 | - { role: leesoh.pipenv } 20 | - { role: ChromaticHQ.aws-cli } 21 | - bastion 22 | 23 | -------------------------------------------------------------------------------- /create_eip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # For Bastion server 4 | BASTION=EIPBastion-${ALIS_APP_ID} 5 | aws ec2 allocate-address --domain vpc \ 6 | | jq '.AllocationId' \ 7 | | xargs aws ec2 create-tags --tags Key=Name,Value=${BASTION} Key=Component,Value=PrivateChain --resources 8 | 9 | 10 | # For NAT 11 | NAT=EIPNAT-${ALIS_APP_ID} 12 | aws ec2 allocate-address --domain vpc \ 13 | | jq '.AllocationId' \ 14 | | xargs aws ec2 create-tags --tags Key=Name,Value=${NAT} Key=Component,Value=PrivateChain --resources 15 | 16 | echo "" 17 | echo "You have to specify SSM valuables of EIP:" 18 | echo "" 19 | echo ${BASTION} 20 | echo ${NAT} 21 | echo "" 22 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SSM_PARAMS_PREFIX=${ALIS_APP_ID}ssm 4 | 5 | aws cloudformation deploy \ 6 | --template-file template.yaml \ 7 | --capabilities CAPABILITY_IAM \ 8 | --parameter-overrides \ 9 | AlisAppId=${ALIS_APP_ID} \ 10 | ParityNodesAMI=${SSM_PARAMS_PREFIX}ParityNodesAMI \ 11 | BastionAllocationId=${SSM_PARAMS_PREFIX}BastionAllocationId \ 12 | NatAllocationId=${SSM_PARAMS_PREFIX}NatAllocationId \ 13 | EC2DeleteOnTermination=${SSM_PARAMS_PREFIX}EC2DeleteOnTermination \ 14 | AccountsNewRequestPassword=${SSM_PARAMS_PREFIX}AccountsNewRequestPassword \ 15 | ParityNodesInstanceType=${SSM_PARAMS_PREFIX}ParityNodesInstanceType \ 16 | ParityNodesVolumeSize=${SSM_PARAMS_PREFIX}ParityNodesVolumeSize \ 17 | PrivateChainMainSigner=${SSM_PARAMS_PREFIX}PrivateChainMainSigner \ 18 | PrivateChainAlisTokenAddress=${SSM_PARAMS_PREFIX}PrivateChainAlisTokenAddress \ 19 | PrivateChainBridgeAddress=${SSM_PARAMS_PREFIX}PrivateChainBridgeAddress \ 20 | --stack-name ${ALIS_APP_ID}privatechain 21 | -------------------------------------------------------------------------------- /fix_api.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Get resource IDs 3 | RESOURCE_IDs=`aws apigateway get-resources --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} \ 4 | | jq -r '.items[] | select(.resourceMethods).id'` 5 | 6 | # Set IAM authentications 7 | for resource_id in ${RESOURCE_IDs}; do 8 | aws apigateway update-method --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} \ 9 | --resource-id ${resource_id} \ 10 | --http-method POST \ 11 | --patch-operations \ 12 | op="replace",path="/authorizationType",value="AWS_IAM" 13 | done 14 | 15 | # Deployment 16 | aws apigateway create-deployment --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} \ 17 | --stage-name production \ 18 | --description "for enable IAM authentications" 19 | 20 | # --- 21 | 22 | # Delete unnecessary Stage "Stage" 23 | # SAM's bug? https://github.com/awslabs/serverless-application-model/issues/168 24 | aws apigateway delete-stage --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} --stage-name Stage 25 | 26 | # --- 27 | 28 | # Enable logs 29 | aws apigateway update-stage --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} --stage-name 'production' --patch-operations op=replace,path=/*/*/logging/dataTrace,value=true 30 | aws apigateway update-stage --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} --stage-name 'production' --patch-operations op=replace,path=/*/*/logging/loglevel,value=INFO 31 | aws apigateway update-stage --rest-api-id ${PRIVATE_CHAIN_REST_API_ID} --stage-name 'production' --patch-operations op=replace,path=/*/*/metrics/enabled,value=true 32 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlisProject/private-chain/76e7fcba94d3fa14c9abf04927f7c4da545a8794/logo.png -------------------------------------------------------------------------------- /packer/ansible/README.md: -------------------------------------------------------------------------------- 1 | # Edit valuables 2 | ```bash 3 | vi ./gropu_vars/all 4 | ``` 5 | 6 | # run 7 | ```bash 8 | ansible-playbook -i hosts site.yml 9 | ``` 10 | -------------------------------------------------------------------------------- /packer/ansible/group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | parity_base_path: /root/.local/share/io.parity.ethereum 4 | parity_keys_path: /var/keys 5 | ethbase_password: YOURPASSWORDHERE 6 | -------------------------------------------------------------------------------- /packer/ansible/hosts.sample: -------------------------------------------------------------------------------- 1 | [main] 2 | 192.168.0.1 3 | -------------------------------------------------------------------------------- /packer/ansible/motd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | █████╗ ██╗ ██╗███████╗ 5 | ██╔══██╗██║ ██║██╔════╝ 6 | ███████║██║ ██║███████╗ 7 | ██╔══██║██║ ██║╚════██║ 8 | ██║ ██║███████╗██║███████║ 9 | ╚═╝ ╚═╝╚══════╝╚═╝╚══════╝ 10 | 11 | - ALLIANCE & WISDOM - 12 | 13 | 14 | -------------------------------------------------------------------------------- /packer/ansible/roles/parity/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages 3 | apt: 4 | name: "{{ item }}" 5 | state: present 6 | update_cache: yes 7 | with_items: 8 | - jq 9 | - supervisor 10 | 11 | - name: Get Parity install script 12 | command: curl https://get.parity.io -kL -o /tmp/parity.sh 13 | 14 | - file: path=/tmp/parity.sh mode=0755 15 | 16 | - stat: path=/usr/bin/parity 17 | register: parity 18 | 19 | - name: Install Parity 20 | shell: /tmp/parity.sh 21 | when: not parity.stat.exists 22 | 23 | - name: Create dirctries 24 | file: path={{ item }} state=directory owner=root group=root mode=0755 25 | with_items: 26 | - "{{ parity_base_path }}" 27 | - "{{ parity_keys_path }}" 28 | - "{{ parity_keys_path }}/PrivateChain" 29 | - "/var/log/supervisor/jobs" 30 | 31 | - name: Deliver configuration files for Parity private chain 32 | template: src={{ item.src }} dest={{ parity_base_path }}/{{ item.dest }} backup=yes 33 | with_items: 34 | - { src: 'spec.json.j2', dest: 'spec.json' } 35 | - { src: 'config.toml.j2', dest: 'config.toml' } 36 | - { src: 'node.pwds.j2', dest: 'node.pwds' } 37 | 38 | - name: Deliver supervisor configuration file for Parity 39 | template: src={{ item.src }} dest=/etc/supervisor/conf.d/{{ item.dest }} backup=yes 40 | with_items: 41 | - { src: 'parity.conf.j2', dest: 'parity.conf' } 42 | 43 | - name: Deliver ETH account key files 44 | template: src={{ item.src }} dest={{ parity_keys_path }}/PrivateChain/{{ item.dest }} backup=yes mode=600 45 | with_items: 46 | - { src: 'PCParityPoA1a_key.j2', dest: 'PCParityPoA1a' } 47 | - { src: 'PCParityPoA2a_key.j2', dest: 'PCParityPoA2a' } 48 | - { src: 'PCParityPoA2c_key.j2', dest: 'PCParityPoA2c' } 49 | - { src: 'PCParityPoA1c_key.j2', dest: 'PCParityPoA1c' } 50 | 51 | - name: Add motd 52 | template: src={{ item.src }} dest={{ item.dest }} backup=yes 53 | with_items: 54 | - { src: 'motd', dest: '/etc/motd' } 55 | -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/PCParityPoA1a_key.j2: -------------------------------------------------------------------------------- 1 | {"id":"8b9f748f-a72e-04d8-4257-6918df6a235f","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"fa0383793f40476db0c4d3170de2be0c"},"ciphertext":"d1177a3c7cf76ddb76cd79f93533e8e2b90bb61cc93691a5126bcc85d4675077","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"e5dff085b7771915f5e81d1b248903b1258c6ba54bdcb93e13a450650a322802"},"mac":"1b3d28253e5a1998e1a61144adb75a98fa3b27c86e84b15bcb946f62b2e0e809"},"address":"7ad8f90cfa071c8420e3f09fe0e413d0c47502e6","name":"","meta":"{}"} -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/PCParityPoA1c_key.j2: -------------------------------------------------------------------------------- 1 | {"id":"0f3f0dd7-253b-34f8-b636-8e8e169c7a6b","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"bc61fa9ce24cc92ca8fe8d2461f17d2c"},"ciphertext":"6362fc1ef3b50925d51a81adfec4d7388be51d222533e5847e0f2b74a2c7489a","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"5212020e9c9efcd19f3e82ca1be1c016d9f452f9ba5e2dfde071c0a562da9c9a"},"mac":"0a6e7ef58ae8f5e8e332f6097d46353f02583990949f179522aae32f67d243fe"},"address":"328d7aeb026f759fa9b79add01a9a88404437904","name":"","meta":"{}"} -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/PCParityPoA2a_key.j2: -------------------------------------------------------------------------------- 1 | {"id":"fd2cf69f-147f-b07a-9e24-66356802d701","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"8a31c81209a6d23b3162dc84b22c8435"},"ciphertext":"f8254eb550f351c2bdc4e7b38a2a32fc873049342e5690ceea1408b1b0996202","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"253f7e3cc7f036f135950c386a882a2a6664437cf010f4cf71c213e9defee15a"},"mac":"cc140227f2194a9355cb5a697e10afcff4ed00f9b68a47b558063257c3e6132f"},"address":"17c59086a5a5c55f0239ca4c10bb28fef819181b","name":"","meta":"{}"} -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/PCParityPoA2c_key.j2: -------------------------------------------------------------------------------- 1 | {"id":"3b30becd-2097-0e81-25fb-d7f6488a2242","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"de17784f169185e48e1db011d08a8b5a"},"ciphertext":"ac6b8cc678b62a0c5a2cd741108dba0b63ffd81aca66dd2332c5a1e63a41d6b4","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"42607788dea8de24b5285f6780f4452141fe6841858c1bfa8c38aaf6ac7fd200"},"mac":"4352c5cd982063d30c2269fcaa48198aa6da191a32436fcc99cca7c7e46a4fff"},"address":"6cac0b0447db1ade608205f531afc2cbbffe1e96","name":"","meta":"{}"} -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/config.toml.j2: -------------------------------------------------------------------------------- 1 | [parity] 2 | mode = "active" 3 | chain = "{{ parity_base_path }}/spec.json" 4 | base_path = "{{ parity_base_path }}" 5 | keys_path = "{{ parity_keys_path }}" 6 | auto_update = "none" 7 | release_track = "stable" 8 | identity = "{{ inventory_hostname }}" 9 | [account] 10 | password = ["{{ parity_base_path }}/node.pwds"] 11 | refresh_time = 0 12 | [ui] 13 | disable = true 14 | [network] 15 | port = 30303 16 | discovery = false 17 | min_peers = 3 18 | max_peers = 3 19 | no_serve_light = true 20 | allow_ips = "private" 21 | [rpc] 22 | port = 8545 23 | apis = ["safe", "personal", "parity_set"] 24 | interface = "all" 25 | server_threads = 14 26 | processing_threads = 4 27 | [websockets] 28 | disable = true 29 | [ipc] 30 | disable = true 31 | [dapps] 32 | disable = true 33 | [ipfs] 34 | enable = false 35 | [secretstore] 36 | disable = true 37 | [mining] 38 | engine_signer = "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e" 39 | reseal_on_txs = "none" 40 | usd_per_tx = "0" 41 | tx_queue_mem_limit = 1024 42 | [footprint] 43 | cache_size_db = 1024 44 | cache_size_blocks = 1024 45 | cache_size_queue = 1024 46 | cache_size_state = 1024 47 | -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/node.pwds.j2: -------------------------------------------------------------------------------- 1 | {{ ethbase_password }} 2 | -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/parity.conf.j2: -------------------------------------------------------------------------------- 1 | [program:Parity] 2 | command=/usr/bin/parity --config {{ parity_base_path }}/config.toml 3 | user=root 4 | autorestart=true 5 | stdout_logfile=/var/log/supervisor/jobs/parity.log 6 | stdout_logfile_maxbytes=1MB 7 | stdout_logfile_backups=5 8 | stdout_capture_maxbytes=1MB 9 | redirect_stderr=true 10 | -------------------------------------------------------------------------------- /packer/ansible/roles/parity/templates/spec.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PrivateChain", 3 | "engine": { 4 | "authorityRound": { 5 | "params": { 6 | "stepDuration": "1", 7 | "validators": { 8 | "list": [ 9 | "7ad8f90cfa071c8420e3f09fe0e413d0c47502e6", 10 | "328d7aeb026f759fa9b79add01a9a88404437904", 11 | "17c59086a5a5c55f0239ca4c10bb28fef819181b", 12 | "6cac0b0447db1ade608205f531afc2cbbffe1e96" 13 | ] 14 | } 15 | } 16 | } 17 | }, 18 | "params": { 19 | "gasLimitBoundDivisor": "0x400", 20 | "maximumExtraDataSize": "0x20", 21 | "minGasLimit": "0x1388", 22 | "networkID": "0x2323" 23 | }, 24 | "genesis": { 25 | "seal": { 26 | "authorityRound": { 27 | "step": "0x0", 28 | "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 29 | } 30 | }, 31 | "difficulty": "0x20000", 32 | "gasLimit": "0x5B8D80" 33 | }, 34 | "accounts": { 35 | "0x0000000000000000000000000000000000000001": { 36 | "balance": "1", 37 | "builtin": { 38 | "name": "ecrecover", 39 | "pricing": { 40 | "linear": { 41 | "base": 3000, 42 | "word": 0 43 | } 44 | } 45 | } 46 | }, 47 | "0x0000000000000000000000000000000000000002": { 48 | "balance": "1", 49 | "builtin": { 50 | "name": "sha256", 51 | "pricing": { 52 | "linear": { 53 | "base": 60, 54 | "word": 12 55 | } 56 | } 57 | } 58 | }, 59 | "0x0000000000000000000000000000000000000003": { 60 | "balance": "1", 61 | "builtin": { 62 | "name": "ripemd160", 63 | "pricing": { 64 | "linear": { 65 | "base": 600, 66 | "word": 120 67 | } 68 | } 69 | } 70 | }, 71 | "0x0000000000000000000000000000000000000004": { 72 | "balance": "1", 73 | "builtin": { 74 | "name": "identity", 75 | "pricing": { 76 | "linear": { 77 | "base": 15, 78 | "word": 3 79 | } 80 | } 81 | } 82 | }, 83 | "7ad8f90cfa071c8420e3f09fe0e413d0c47502e6": { 84 | "balance": "10000000000000000000000000" 85 | }, 86 | "328d7aeb026f759fa9b79add01a9a88404437904": { 87 | "balance": "10000000000000000000000000" 88 | }, 89 | "17c59086a5a5c55f0239ca4c10bb28fef819181b": { 90 | "balance": "10000000000000000000000000" 91 | }, 92 | "6cac0b0447db1ade608205f531afc2cbbffe1e96": { 93 | "balance": "10000000000000000000000000" 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /packer/ansible/site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | remote_user: ubuntu 5 | become: yes 6 | 7 | roles: 8 | - parity 9 | -------------------------------------------------------------------------------- /packer/parity-poa.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", 4 | "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}" 5 | }, 6 | "builders": [ 7 | { 8 | "type": "amazon-ebs", 9 | "access_key": "{{user `aws_access_key`}}", 10 | "secret_key": "{{user `aws_secret_key`}}", 11 | "region": "ap-northeast-1", 12 | "source_ami": "ami-cbb259b4", 13 | "instance_type": "t2.micro", 14 | "ssh_username": "ubuntu", 15 | "ami_name": "private-chain {{timestamp}}" 16 | } 17 | ], 18 | "provisioners": [ 19 | { 20 | "type": "shell", 21 | "inline": [ 22 | "sudo ln -s /usr/bin/python3 /usr/bin/python" 23 | ] 24 | }, 25 | { 26 | "type": "ansible", 27 | "playbook_file": "./ansible/site.yml" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packer/parity-poa.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: yes 3 | tasks: 4 | - name: Init 5 | file: src=/usr/bin/python3 dest=/usr/bin/python owner=root group=root state=link 6 | 7 | - name: Get Parity install script 8 | get_url: url="https://get.parity.io" dest=/tmp/parity.sh mode=0755 9 | 10 | - name: Install Parity 11 | shell: /tmp/parity.sh 12 | -------------------------------------------------------------------------------- /private_chain.yml: -------------------------------------------------------------------------------- 1 | # ~/.tmuxinator/private_chain.yml 2 | 3 | name: private_chain 4 | root: /tmp/ 5 | 6 | windows: 7 | - window1: 8 | layout: tiled 9 | panes: 10 | - PCParityPoA1a: 11 | - ssh PCParityPoA1a 12 | - PCParityPoA2a: 13 | - ssh PCParityPoA2a 14 | - PCParityPoA1c: 15 | - ssh PCParityPoA1c 16 | - PCParityPoA2c: 17 | - ssh PCParityPoA2c 18 | -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Transform: AWS::Serverless-2016-10-31 3 | 4 | Parameters: 5 | AlisAppId: 6 | Type: String 7 | ParityNodesAMI: 8 | Type: 'AWS::SSM::Parameter::Value' 9 | BastionAllocationId: 10 | Type: 'AWS::SSM::Parameter::Value' 11 | NatAllocationId: 12 | Type: 'AWS::SSM::Parameter::Value' 13 | EC2DeleteOnTermination: 14 | Type: 'AWS::SSM::Parameter::Value' 15 | AccountsNewRequestPassword: 16 | Type: 'AWS::SSM::Parameter::Value' 17 | PrivateChainMainSigner: 18 | Type: 'AWS::SSM::Parameter::Value' 19 | PrivateChainAlisTokenAddress: 20 | Type: 'AWS::SSM::Parameter::Value' 21 | PrivateChainBridgeAddress: 22 | Type: 'AWS::SSM::Parameter::Value' 23 | ParityNodesInstanceType: 24 | Type: 'AWS::SSM::Parameter::Value' 25 | ParityNodesVolumeSize: 26 | Type: 'AWS::SSM::Parameter::Value' 27 | 28 | Resources: 29 | PrivateChain: 30 | Type: 'AWS::EC2::VPC' 31 | Properties: 32 | CidrBlock: 10.1.0.0/24 33 | Tags: 34 | - Key: Name 35 | Value: PrivateChain 36 | - Key: Component 37 | Value: PrivateChain 38 | PrivateChainVpcLink: 39 | Type: "AWS::ApiGateway::VpcLink" 40 | Properties: 41 | Description: VPC link for Private chain. 42 | Name: PrivateChainVpcLink 43 | TargetArns: 44 | - !Ref NLB 45 | PrivateChainVPCFlowLog: 46 | Type: 'AWS::EC2::FlowLog' 47 | Properties: 48 | DeliverLogsPermissionArn: !GetAtt 49 | - LogRole 50 | - Arn 51 | LogGroupName: PrivateChainVPCFlowLog 52 | ResourceId: !Ref PrivateChain 53 | ResourceType: VPC 54 | TrafficType: ALL 55 | NLB: 56 | Type: "AWS::ElasticLoadBalancingV2::LoadBalancer" 57 | Properties: 58 | Name: !Ref AWS::StackName 59 | Scheme: internal 60 | Subnets: 61 | - !Ref PrivateSubNet1 62 | - !Ref PrivateSubNet2 63 | Type: network 64 | Tags: 65 | - Key: Name 66 | Value: NLB 67 | - Key: Component 68 | Value: PrivateChain 69 | NlbTargetGroup: 70 | Type: "AWS::ElasticLoadBalancingV2::TargetGroup" 71 | Properties: 72 | Name: !Ref AWS::StackName 73 | Port: 8545 74 | Protocol: TCP 75 | Tags: 76 | - Key: NlbTargetGroup 77 | Value: NLB 78 | - Key: Component 79 | Value: PrivateChain 80 | Targets: 81 | - Id: !Ref PCParityPoA1a 82 | Port: 8545 83 | - Id: !Ref PCParityPoA1c 84 | Port: 8545 85 | - Id: !Ref PCParityPoA2a 86 | Port: 8545 87 | - Id: !Ref PCParityPoA2c 88 | Port: 8545 89 | TargetType: instance 90 | VpcId: !Ref PrivateChain 91 | NlbListener: 92 | Type: "AWS::ElasticLoadBalancingV2::Listener" 93 | Properties: 94 | DefaultActions: 95 | - TargetGroupArn: !Ref NlbTargetGroup 96 | Type: forward 97 | LoadBalancerArn: !Ref NLB 98 | Port: 8545 99 | Protocol: TCP 100 | # 本来はこのRoleは不要でPolicyのみ作成したいが不可能なのでRoleごと作る 101 | PrivateChainInternalAPIRole: 102 | Type: "AWS::IAM::Role" 103 | Properties: 104 | AssumeRolePolicyDocument: 105 | Version: "2012-10-17" 106 | Statement: 107 | - Effect: "Allow" 108 | Principal: 109 | Service: 110 | - "lambda.amazonaws.com" 111 | Action: 112 | - "sts:AssumeRole" 113 | Policies: 114 | - PolicyName: "PrivateChainInternalAPIPolicy" 115 | PolicyDocument: 116 | Version: "2012-10-17" 117 | Statement: 118 | - Effect: Allow 119 | Action: 120 | - execute-api:Invoke 121 | Resource: 122 | - 'arn:aws:execute-api:ap-northeast-1:*' 123 | # FIXME: リソース生成後に指定 124 | # - arn:aws:execute-api:ap-northeast-1:090169530579:ohie9qzzjj/*/POST/accounts/new 125 | API: 126 | Type: 'AWS::Serverless::Api' 127 | Properties: 128 | StageName: production 129 | DefinitionBody: 130 | swagger: "2.0" 131 | info: 132 | title: !Ref "AWS::StackName" 133 | version: 1.0.0 134 | basePath: / 135 | schemes: 136 | - https 137 | definitions: 138 | CreateAccount: 139 | type: object 140 | paths: 141 | /accounts/new: 142 | post: 143 | description: '新規アカウント作成' 144 | responses: 145 | '200': 146 | description: '新規作成されたアカウントのアドレス' 147 | schema: 148 | type: object 149 | properties: 150 | address: 151 | type: 'string' 152 | x-amazon-apigateway-integration: 153 | responses: 154 | default: 155 | statusCode: '200' 156 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 157 | httpMethod: POST 158 | type: http 159 | connectionId: !Ref PrivateChainVpcLink 160 | connectionType: VPC_LINK 161 | requestTemplates: 162 | application/json: 163 | !Sub 164 | - |- 165 | { 166 | "jsonrpc": "2.0", 167 | "method": "personal_newAccount", 168 | "params": [ 169 | "${AccountsNewRequestPassword}" 170 | ], 171 | "id": 1 172 | } 173 | - { 174 | AccountsNewRequestPassword: !Ref AccountsNewRequestPassword 175 | } 176 | /wallet/balance: 177 | post: 178 | description: 'ウォレットの残高を取得' 179 | responses: 180 | '200': 181 | description: 'ウォレットの残高' 182 | schema: 183 | type: object 184 | properties: 185 | private_eth_address: 186 | type: 'string' 187 | x-amazon-apigateway-integration: 188 | responses: 189 | default: 190 | statusCode: '200' 191 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 192 | httpMethod: POST 193 | type: http 194 | connectionId: !Ref PrivateChainVpcLink 195 | connectionType: VPC_LINK 196 | requestTemplates: 197 | application/json: 198 | !Sub 199 | - |- 200 | { 201 | "jsonrpc": "2.0", 202 | "method": "eth_call", 203 | "params": [ 204 | { 205 | "from": "${PrivateChainMainSigner}", 206 | "to": "${PrivateChainAlisTokenAddress}", 207 | "data": "0x70a08231000000000000000000000000$input.json('private_eth_address').replaceAll('\"','')" 208 | }, 209 | "latest" 210 | ], 211 | "id": 1 212 | } 213 | - { 214 | PrivateChainMainSigner: !Ref PrivateChainMainSigner, 215 | PrivateChainAlisTokenAddress: !Ref PrivateChainAlisTokenAddress 216 | } 217 | /wallet/tip: 218 | post: 219 | description: '投げ銭を行う' 220 | responses: 221 | '200': 222 | description: '投げ銭リクエスト受付結果' 223 | schema: 224 | type: object 225 | properties: 226 | from_user_eth_address: 227 | type: 'string' 228 | to_user_eth_address: 229 | type: 'string' 230 | tip_value: 231 | type: 'integer' 232 | x-amazon-apigateway-integration: 233 | responses: 234 | default: 235 | statusCode: '200' 236 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 237 | httpMethod: POST 238 | type: http 239 | connectionId: !Ref PrivateChainVpcLink 240 | connectionType: VPC_LINK 241 | requestTemplates: 242 | application/json: 243 | !Sub 244 | - |- 245 | { 246 | "jsonrpc": "2.0", 247 | "method": "personal_sendTransaction", 248 | "params": [ 249 | { 250 | "from": "$input.json('from_user_eth_address').replaceAll('\"','')", 251 | "to": "${PrivateChainAlisTokenAddress}", 252 | "value": "0x0", 253 | "data": "0xa9059cbb000000000000000000000000$input.json('to_user_eth_address').replaceAll('\"','')$input.json('tip_value').replaceAll('\"','')" 254 | }, 255 | "${AccountsNewRequestPassword}" 256 | ], 257 | "id": 1 258 | } 259 | - { 260 | AccountsNewRequestPassword: !Ref AccountsNewRequestPassword, 261 | PrivateChainAlisTokenAddress: !Ref PrivateChainAlisTokenAddress 262 | } 263 | /transaction/receipt: 264 | post: 265 | description: 'トランザクションの詳細を取得する' 266 | responses: 267 | '200': 268 | description: 'トランザクションの詳細' 269 | schema: 270 | type: object 271 | properties: 272 | transaction_hash: 273 | type: 'string' 274 | x-amazon-apigateway-integration: 275 | responses: 276 | default: 277 | statusCode: '200' 278 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 279 | httpMethod: POST 280 | type: http 281 | connectionId: !Ref PrivateChainVpcLink 282 | connectionType: VPC_LINK 283 | requestTemplates: 284 | application/json: | 285 | { 286 | "jsonrpc": "2.0", 287 | "method": "eth_getTransactionReceipt", 288 | "params": ["$input.json('transaction_hash').replaceAll('\"','')"], 289 | "id": 1 290 | } 291 | /wallet/allowance: 292 | post: 293 | description: 'allowance値の取得' 294 | responses: 295 | '200': 296 | description: 'allowance値' 297 | schema: 298 | type: object 299 | properties: 300 | allowance: 301 | type: 'string' 302 | x-amazon-apigateway-integration: 303 | responses: 304 | default: 305 | statusCode: '200' 306 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 307 | httpMethod: POST 308 | type: http 309 | connectionId: !Ref PrivateChainVpcLink 310 | connectionType: VPC_LINK 311 | requestTemplates: 312 | application/json: 313 | !Sub 314 | - |- 315 | { 316 | "jsonrpc": "2.0", 317 | "method": "eth_call", 318 | "params": [ 319 | { 320 | "from": "$input.json('from_user_eth_address').replaceAll('\"','')", 321 | "to": "${PrivateChainAlisTokenAddress}", 322 | "data": "0xdd62ed3e000000000000000000000000$input.json('owner_eth_address').replaceAll('\"','')000000000000000000000000$input.json('spender_eth_address').replaceAll('\"','')" 323 | }, 324 | "latest" 325 | ], 326 | "id": 1 327 | } 328 | - { 329 | PrivateChainAlisTokenAddress: !Ref PrivateChainAlisTokenAddress 330 | } 331 | /wallet/approve: 332 | post: 333 | description: 'トークンの認可を行う' 334 | responses: 335 | '200': 336 | description: 'トークンの認可結果' 337 | schema: 338 | type: object 339 | properties: 340 | transaction_hash: 341 | type: 'string' 342 | x-amazon-apigateway-integration: 343 | responses: 344 | default: 345 | statusCode: '200' 346 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 347 | httpMethod: POST 348 | type: http 349 | connectionId: !Ref PrivateChainVpcLink 350 | connectionType: VPC_LINK 351 | requestTemplates: 352 | application/json: 353 | !Sub 354 | - |- 355 | { 356 | "jsonrpc": "2.0", 357 | "method": "personal_sendTransaction", 358 | "params": [ 359 | { 360 | "from": "$input.json('from_user_eth_address').replaceAll('\"','')", 361 | "to": "${PrivateChainAlisTokenAddress}", 362 | "value": "0x0", 363 | "nonce": "$input.json('nonce').replaceAll('\"','')", 364 | "data": "0x095ea7b3000000000000000000000000$input.json('spender_eth_address').replaceAll('\"','')$input.json('value').replaceAll('\"','')" 365 | }, 366 | "${AccountsNewRequestPassword}" 367 | ], 368 | "id": 1 369 | } 370 | - { 371 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress, 372 | PrivateChainAlisTokenAddress: !Ref PrivateChainAlisTokenAddress 373 | } 374 | /wallet/relay: 375 | post: 376 | description: 'トークンの引出しを行う' 377 | responses: 378 | '200': 379 | description: 'トークンの引出し結果' 380 | schema: 381 | type: object 382 | properties: 383 | transaction_hash: 384 | type: 'string' 385 | x-amazon-apigateway-integration: 386 | responses: 387 | default: 388 | statusCode: '200' 389 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 390 | httpMethod: POST 391 | type: http 392 | connectionId: !Ref PrivateChainVpcLink 393 | connectionType: VPC_LINK 394 | requestTemplates: 395 | application/json: 396 | !Sub 397 | - |- 398 | { 399 | "jsonrpc": "2.0", 400 | "method": "personal_sendTransaction", 401 | "params": [ 402 | { 403 | "from": "$input.json('from_user_eth_address').replaceAll('\"','')", 404 | "to": "${PrivateChainBridgeAddress}", 405 | "value": "0x0", 406 | "nonce": "$input.json('nonce').replaceAll('\"','')", 407 | "data": "0xeeec0e24000000000000000000000000$input.json('recipient_eth_address').replaceAll('\"','')$input.json('amount').replaceAll('\"','')" 408 | }, 409 | "${AccountsNewRequestPassword}" 410 | ], 411 | "id": 1 412 | } 413 | - { 414 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress, 415 | PrivateChainAlisTokenAddress: !Ref PrivateChainAlisTokenAddress 416 | } 417 | /wallet/relay_events: 418 | post: 419 | description: 'Relayイベントのログを取得' 420 | responses: 421 | '200': 422 | description: 'Relayイベントのログ一覧' 423 | schema: 424 | type: object 425 | properties: 426 | events: 427 | type: 'string' 428 | x-amazon-apigateway-integration: 429 | responses: 430 | default: 431 | statusCode: '200' 432 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 433 | httpMethod: POST 434 | type: http 435 | connectionId: !Ref PrivateChainVpcLink 436 | connectionType: VPC_LINK 437 | requestTemplates: 438 | application/json: 439 | !Sub 440 | - |- 441 | { 442 | "jsonrpc": "2.0", 443 | "method": "eth_getLogs", 444 | "params": [ 445 | { 446 | "fromBlock": "$input.json('from_block').replaceAll('\"','')", 447 | "toBlock": "$input.json('to_block').replaceAll('\"','')", 448 | "address": "${PrivateChainBridgeAddress}", 449 | "topics": [ 450 | "0xb77c820b3a0ee4da03c984a58bfe43cb27cd3297d424e1025014ce0b7de08cc4", 451 | "0x000000000000000000000000$input.json('sender_eth_address').replaceAll('\"','')" 452 | ] 453 | } 454 | ], 455 | "id": 1 456 | } 457 | - { 458 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 459 | } 460 | /wallet/apply_relay_events: 461 | post: 462 | description: 'ApplyRelayイベントのログを取得' 463 | responses: 464 | '200': 465 | description: 'ApplyRelayイベントのログ一覧' 466 | schema: 467 | type: object 468 | properties: 469 | events: 470 | type: 'string' 471 | x-amazon-apigateway-integration: 472 | responses: 473 | default: 474 | statusCode: '200' 475 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 476 | httpMethod: POST 477 | type: http 478 | connectionId: !Ref PrivateChainVpcLink 479 | connectionType: VPC_LINK 480 | requestTemplates: 481 | application/json: 482 | !Sub 483 | - |- 484 | { 485 | "jsonrpc": "2.0", 486 | "method": "eth_getLogs", 487 | "params": [ 488 | { 489 | "fromBlock": "$input.json('from_block').replaceAll('\"','')", 490 | "toBlock": "$input.json('to_block').replaceAll('\"','')", 491 | "address": "${PrivateChainBridgeAddress}", 492 | "topics": [ 493 | "0xb114698a397e5f7a7c78e5e58f6f59d2c329c988c585a930db7bb099b3d016d6", 494 | null, 495 | "0x000000000000000000000000$input.json('recipient_eth_address').replaceAll('\"','')" 496 | ] 497 | } 498 | ], 499 | "id": 1 500 | } 501 | - { 502 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 503 | } 504 | /wallet/max_single_relay_amount: 505 | post: 506 | description: '出金額の最大値の取得' 507 | responses: 508 | '200': 509 | description: '出金額の最大値' 510 | schema: 511 | type: object 512 | properties: 513 | amount: 514 | type: 'string' 515 | x-amazon-apigateway-integration: 516 | responses: 517 | default: 518 | statusCode: '200' 519 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 520 | httpMethod: POST 521 | type: http 522 | connectionId: !Ref PrivateChainVpcLink 523 | connectionType: VPC_LINK 524 | requestTemplates: 525 | application/json: 526 | !Sub 527 | - |- 528 | { 529 | "jsonrpc": "2.0", 530 | "method": "eth_call", 531 | "params": [ 532 | { 533 | "from": "${PrivateChainMainSigner}", 534 | "to": "${PrivateChainBridgeAddress}", 535 | "data": "0x34f89513" 536 | }, 537 | "latest" 538 | ], 539 | "id": 1 540 | } 541 | - { 542 | PrivateChainMainSigner: !Ref PrivateChainMainSigner, 543 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 544 | } 545 | /wallet/min_single_relay_amount: 546 | post: 547 | description: '出金額の最小値の取得' 548 | responses: 549 | '200': 550 | description: '出金額の最小値' 551 | schema: 552 | type: object 553 | properties: 554 | amount: 555 | type: 'string' 556 | x-amazon-apigateway-integration: 557 | responses: 558 | default: 559 | statusCode: '200' 560 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 561 | httpMethod: POST 562 | type: http 563 | connectionId: !Ref PrivateChainVpcLink 564 | connectionType: VPC_LINK 565 | requestTemplates: 566 | application/json: 567 | !Sub 568 | - |- 569 | { 570 | "jsonrpc": "2.0", 571 | "method": "eth_call", 572 | "params": [ 573 | { 574 | "from": "${PrivateChainMainSigner}", 575 | "to": "${PrivateChainBridgeAddress}", 576 | "data": "0x9f29ffdf" 577 | }, 578 | "latest" 579 | ], 580 | "id": 1 581 | } 582 | - { 583 | PrivateChainMainSigner: !Ref PrivateChainMainSigner, 584 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 585 | } 586 | /wallet/relay_fee: 587 | post: 588 | description: '出金手数料の取得' 589 | responses: 590 | '200': 591 | description: '出金手数料' 592 | schema: 593 | type: object 594 | properties: 595 | amount: 596 | type: 'string' 597 | x-amazon-apigateway-integration: 598 | responses: 599 | default: 600 | statusCode: '200' 601 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 602 | httpMethod: POST 603 | type: http 604 | connectionId: !Ref PrivateChainVpcLink 605 | connectionType: VPC_LINK 606 | requestTemplates: 607 | application/json: 608 | !Sub 609 | - |- 610 | { 611 | "jsonrpc": "2.0", 612 | "method": "eth_call", 613 | "params": [ 614 | { 615 | "from": "${PrivateChainMainSigner}", 616 | "to": "${PrivateChainBridgeAddress}", 617 | "data": "0x71d30863" 618 | }, 619 | "latest" 620 | ], 621 | "id": 1 622 | } 623 | - { 624 | PrivateChainMainSigner: !Ref PrivateChainMainSigner, 625 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 626 | } 627 | /wallet/relay_paused: 628 | post: 629 | description: '出金停止中フラグの取得' 630 | responses: 631 | '200': 632 | description: '出金停止中フラグ' 633 | schema: 634 | type: object 635 | properties: 636 | paused: 637 | type: 'string' 638 | x-amazon-apigateway-integration: 639 | responses: 640 | default: 641 | statusCode: '200' 642 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 643 | httpMethod: POST 644 | type: http 645 | connectionId: !Ref PrivateChainVpcLink 646 | connectionType: VPC_LINK 647 | requestTemplates: 648 | application/json: 649 | !Sub 650 | - |- 651 | { 652 | "jsonrpc": "2.0", 653 | "method": "eth_call", 654 | "params": [ 655 | { 656 | "from": "${PrivateChainMainSigner}", 657 | "to": "${PrivateChainBridgeAddress}", 658 | "data": "0x69a08a26" 659 | }, 660 | "latest" 661 | ], 662 | "id": 1 663 | } 664 | - { 665 | PrivateChainMainSigner: !Ref PrivateChainMainSigner, 666 | PrivateChainBridgeAddress: !Ref PrivateChainBridgeAddress 667 | } 668 | /eth/block_number: 669 | post: 670 | description: '現在のブロック数を取得' 671 | responses: 672 | '200': 673 | description: '現在のブロック数' 674 | schema: 675 | type: object 676 | properties: 677 | block_number: 678 | type: 'integer' 679 | x-amazon-apigateway-integration: 680 | responses: 681 | default: 682 | statusCode: '200' 683 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 684 | httpMethod: POST 685 | type: http 686 | connectionId: !Ref PrivateChainVpcLink 687 | connectionType: VPC_LINK 688 | requestTemplates: 689 | application/json: 690 | !Sub 691 | - |- 692 | { 693 | "jsonrpc": "2.0", 694 | "method": "eth_blockNumber", 695 | "params": [ 696 | ], 697 | "id": 1 698 | } 699 | - { 700 | } 701 | /eth/get_block_by_number: 702 | post: 703 | description: '指定したブロック数のブロック情報を取得' 704 | responses: 705 | '200': 706 | description: 'ブロック情報' 707 | schema: 708 | type: object 709 | properties: 710 | block: 711 | type: 'string' 712 | x-amazon-apigateway-integration: 713 | responses: 714 | default: 715 | statusCode: '200' 716 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 717 | httpMethod: POST 718 | type: http 719 | connectionId: !Ref PrivateChainVpcLink 720 | connectionType: VPC_LINK 721 | requestTemplates: 722 | application/json: 723 | !Sub 724 | - |- 725 | { 726 | "jsonrpc": "2.0", 727 | "method": "eth_getBlockByNumber", 728 | "params": [ 729 | "$input.json('block_num').replaceAll('\"','')", 730 | false 731 | ], 732 | "id": 1 733 | } 734 | - { 735 | } 736 | /eth/get_transaction_count: 737 | post: 738 | description: 'トランザクション数の取得' 739 | responses: 740 | '200': 741 | description: 'トランザクション数' 742 | schema: 743 | type: object 744 | properties: 745 | transaction_count: 746 | type: 'integer' 747 | x-amazon-apigateway-integration: 748 | responses: 749 | default: 750 | statusCode: '200' 751 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 752 | httpMethod: POST 753 | type: http 754 | connectionId: !Ref PrivateChainVpcLink 755 | connectionType: VPC_LINK 756 | requestTemplates: 757 | application/json: 758 | !Sub 759 | - |- 760 | { 761 | "jsonrpc": "2.0", 762 | "method": "eth_getTransactionCount", 763 | "params": [ 764 | "$input.json('from_user_eth_address').replaceAll('\"','')", 765 | "latest" 766 | ], 767 | "id": 1 768 | } 769 | - { 770 | } 771 | /eth/send_raw_transaction: 772 | post: 773 | description: 'トランザクション送信' 774 | responses: 775 | '200': 776 | description: 'トランザクション送信果' 777 | schema: 778 | type: object 779 | properties: 780 | id: 781 | type: 'integer' 782 | jsonrpc: 783 | type: 'string' 784 | result: 785 | type: 'string' 786 | x-amazon-apigateway-integration: 787 | responses: 788 | default: 789 | statusCode: '200' 790 | uri: 'http://example.com:8545' # VPC Linkの場合は使用しないが定義する必要のある項目 791 | httpMethod: POST 792 | type: http 793 | connectionId: !Ref PrivateChainVpcLink 794 | connectionType: VPC_LINK 795 | requestTemplates: 796 | application/json: 797 | !Sub 798 | - |- 799 | { 800 | "jsonrpc": "2.0", 801 | "method": "eth_sendRawTransaction", 802 | "params": [ 803 | "$input.json('raw_transaction').replaceAll('\"','')" 804 | ], 805 | "id": 1 806 | } 807 | - { 808 | } 809 | PrivateSubNet1: 810 | Type: 'AWS::EC2::Subnet' 811 | Properties: 812 | VpcId: !Ref PrivateChain 813 | CidrBlock: 10.1.0.0/28 814 | AvailabilityZone: ap-northeast-1a 815 | Tags: 816 | - Key: Name 817 | Value: PrivateSubNet1 818 | - Key: Component 819 | Value: PrivateChain 820 | PrivateSubNet2: 821 | Type: 'AWS::EC2::Subnet' 822 | Properties: 823 | VpcId: !Ref PrivateChain 824 | CidrBlock: 10.1.0.16/28 825 | AvailabilityZone: ap-northeast-1c 826 | Tags: 827 | - Key: Name 828 | Value: PrivateSubNet2 829 | - Key: Component 830 | Value: PrivateChain 831 | PrivateLambdaSubNet: 832 | Type: 'AWS::EC2::Subnet' 833 | Properties: 834 | VpcId: !Ref PrivateChain 835 | CidrBlock: 10.1.0.128/25 836 | AvailabilityZone: ap-northeast-1a 837 | Tags: 838 | - Key: Name 839 | Value: PrivateLambdaSubNet 840 | - Key: Component 841 | Value: PrivateChain 842 | PrivateLambdaMultiAZ1aSubNet: 843 | # MultiAZ で Lambda を構成する場合に利用 844 | Type: 'AWS::EC2::Subnet' 845 | Properties: 846 | VpcId: !Ref PrivateChain 847 | CidrBlock: 10.1.0.48/28 848 | AvailabilityZone: ap-northeast-1a 849 | Tags: 850 | - Key: Name 851 | Value: !Sub "${AlisAppId}-PrivateLambdaMultiAZ1aSubNet" 852 | - Key: Component 853 | Value: PrivateChain 854 | PrivateLambdaMultiAZ1cSubNet: 855 | # MultiAZ で Lambda を構成する場合に利用 856 | Type: 'AWS::EC2::Subnet' 857 | Properties: 858 | VpcId: !Ref PrivateChain 859 | CidrBlock: 10.1.0.64/28 860 | AvailabilityZone: ap-northeast-1c 861 | Tags: 862 | - Key: Name 863 | Value: !Sub "${AlisAppId}-PrivateLambdaMultiAZ1cSubNet" 864 | - Key: Component 865 | Value: PrivateChain 866 | PrivateSecurityGroup: 867 | Type: 'AWS::EC2::SecurityGroup' 868 | Properties: 869 | VpcId: !Ref PrivateChain 870 | GroupName: PrivateSecurityGroup 871 | GroupDescription: Security Group for Private chain. 872 | SecurityGroupIngress: 873 | - IpProtocol: tcp 874 | FromPort: '22' 875 | ToPort: '22' 876 | CidrIp: 10.1.0.0/24 877 | Description: 'For SSH.' 878 | - IpProtocol: tcp 879 | FromPort: '30303' 880 | ToPort: '30303' 881 | CidrIp: 10.1.0.0/24 882 | Description: 'For enodes.' 883 | - IpProtocol: tcp 884 | FromPort: '8545' 885 | ToPort: '8545' 886 | SourceSecurityGroupId: !Ref PublicSecurityGroup 887 | Description: 'For RPC from Bastion.' 888 | - IpProtocol: tcp 889 | FromPort: '8545' 890 | ToPort: '8545' 891 | SourceSecurityGroupId: !Ref PrivateLambdaSecurityGroup 892 | Description: 'For RPC from lambda.' 893 | - IpProtocol: tcp 894 | FromPort: '8545' 895 | ToPort: '8545' 896 | CidrIp: 10.1.0.0/24 897 | Description: 'For health check.' 898 | Tags: 899 | - Key: Name 900 | Value: PrivateSecurityGroup 901 | - Key: Component 902 | Value: PrivateChain 903 | PrivateLambdaSecurityGroup: 904 | Type: 'AWS::EC2::SecurityGroup' 905 | Properties: 906 | VpcId: !Ref PrivateChain 907 | GroupName: PrivateLambdaSecurityGroup 908 | GroupDescription: Security Group for Private lambda. 909 | Tags: 910 | - Key: Name 911 | Value: PrivateLambdaSecurityGroup 912 | - Key: Component 913 | Value: PrivateChain 914 | FrontendSecurityGroup: 915 | # Frontend(SSR)で Lambda を実行する際に利用。IPを固定することを目的としており、他のリソースにはアクセス不可。 916 | Type: 'AWS::EC2::SecurityGroup' 917 | Properties: 918 | VpcId: !Ref PrivateChain 919 | GroupName: FrontendSecurityGroup 920 | GroupDescription: Security Group for frontend. 921 | Tags: 922 | - Key: Name 923 | Value: !Sub "${AlisAppId}-FrontendSecurityGroup" 924 | - Key: Component 925 | Value: PrivateChain 926 | PCParityPoA1a: 927 | Type: 'AWS::EC2::Instance' 928 | Properties: 929 | ImageId: !Ref ParityNodesAMI 930 | InstanceType: !Ref ParityNodesInstanceType 931 | SubnetId: !Ref PrivateSubNet1 932 | KeyName: private-chain 933 | SecurityGroupIds: 934 | - !Ref PrivateSecurityGroup 935 | IamInstanceProfile: 936 | Ref: LogRoleInstanceProfile 937 | BlockDeviceMappings: 938 | - DeviceName: "/dev/sda1" 939 | Ebs: 940 | VolumeType: "gp2" 941 | DeleteOnTermination: !Ref EC2DeleteOnTermination 942 | VolumeSize: !Ref ParityNodesVolumeSize 943 | NoDevice: {} 944 | Tags: 945 | - Key: Name 946 | Value: PCParityPoA1a 947 | - Key: Component 948 | Value: PrivateChain 949 | - Key: Backup 950 | Value: yes 951 | PCParityPoA2a: 952 | Type: 'AWS::EC2::Instance' 953 | Properties: 954 | ImageId: !Ref ParityNodesAMI 955 | InstanceType: !Ref ParityNodesInstanceType 956 | SubnetId: !Ref PrivateSubNet1 957 | KeyName: private-chain 958 | SecurityGroupIds: 959 | - !Ref PrivateSecurityGroup 960 | IamInstanceProfile: 961 | Ref: LogRoleInstanceProfile 962 | BlockDeviceMappings: 963 | - DeviceName: "/dev/sda1" 964 | Ebs: 965 | VolumeType: "gp2" 966 | DeleteOnTermination: !Ref EC2DeleteOnTermination 967 | VolumeSize: !Ref ParityNodesVolumeSize 968 | NoDevice: {} 969 | Tags: 970 | - Key: Name 971 | Value: PCParityPoA2a 972 | - Key: Component 973 | Value: PrivateChain 974 | - Key: Backup 975 | Value: yes 976 | PCParityPoA1c: 977 | Type: 'AWS::EC2::Instance' 978 | Properties: 979 | ImageId: !Ref ParityNodesAMI 980 | InstanceType: !Ref ParityNodesInstanceType 981 | SubnetId: !Ref PrivateSubNet2 982 | KeyName: private-chain 983 | SecurityGroupIds: 984 | - !Ref PrivateSecurityGroup 985 | IamInstanceProfile: 986 | Ref: LogRoleInstanceProfile 987 | BlockDeviceMappings: 988 | - DeviceName: "/dev/sda1" 989 | Ebs: 990 | VolumeType: "gp2" 991 | DeleteOnTermination: !Ref EC2DeleteOnTermination 992 | VolumeSize: !Ref ParityNodesVolumeSize 993 | NoDevice: {} 994 | Tags: 995 | - Key: Name 996 | Value: PCParityPoA1c 997 | - Key: Component 998 | Value: PrivateChain 999 | - Key: Backup 1000 | Value: yes 1001 | PCParityPoA2c: 1002 | Type: 'AWS::EC2::Instance' 1003 | Properties: 1004 | ImageId: !Ref ParityNodesAMI 1005 | InstanceType: !Ref ParityNodesInstanceType 1006 | SubnetId: !Ref PrivateSubNet2 1007 | KeyName: private-chain 1008 | SecurityGroupIds: 1009 | - !Ref PrivateSecurityGroup 1010 | IamInstanceProfile: 1011 | Ref: LogRoleInstanceProfile 1012 | BlockDeviceMappings: 1013 | - DeviceName: "/dev/sda1" 1014 | Ebs: 1015 | VolumeType: "gp2" 1016 | DeleteOnTermination: !Ref EC2DeleteOnTermination 1017 | VolumeSize: !Ref ParityNodesVolumeSize 1018 | NoDevice: {} 1019 | Tags: 1020 | - Key: Name 1021 | Value: PCParityPoA2c 1022 | - Key: Component 1023 | Value: PrivateChain 1024 | - Key: Backup 1025 | Value: yes 1026 | PublicSubnet: 1027 | Type: 'AWS::EC2::Subnet' 1028 | Properties: 1029 | VpcId: !Ref PrivateChain 1030 | AvailabilityZone: ap-northeast-1d 1031 | CidrBlock: 10.1.0.32/28 1032 | Tags: 1033 | - Key: Name 1034 | Value: PublicSubnet 1035 | - Key: Component 1036 | Value: PrivateChain 1037 | InternetGateway: 1038 | Type: 'AWS::EC2::InternetGateway' 1039 | Properties: 1040 | Tags: 1041 | - Key: Name 1042 | Value: InternetGateway 1043 | - Key: Component 1044 | Value: PrivateChain 1045 | VPCGatewayAttachment: 1046 | Type: 'AWS::EC2::VPCGatewayAttachment' 1047 | Properties: 1048 | InternetGatewayId: !Ref InternetGateway 1049 | VpcId: !Ref PrivateChain 1050 | Bastion: 1051 | Type: 'AWS::EC2::Instance' 1052 | Properties: 1053 | ImageId: ami-bec974d8 1054 | InstanceType: t2.medium 1055 | SubnetId: !Ref PublicSubnet 1056 | KeyName: private-chain 1057 | SecurityGroupIds: 1058 | - !Ref PublicSecurityGroup 1059 | IamInstanceProfile: 1060 | Ref: LogRoleInstanceProfile 1061 | BlockDeviceMappings: 1062 | - DeviceName: "/dev/sda1" 1063 | Ebs: 1064 | VolumeType: "gp2" 1065 | DeleteOnTermination: !Ref EC2DeleteOnTermination 1066 | VolumeSize: !Ref ParityNodesVolumeSize 1067 | NoDevice: {} 1068 | Tags: 1069 | - Key: Name 1070 | Value: Bastion 1071 | - Key: Component 1072 | Value: PrivateChain 1073 | - Key: Backup 1074 | Value: yes 1075 | BastionEIPAssociation: 1076 | Type: 'AWS::EC2::EIPAssociation' 1077 | Properties: 1078 | AllocationId: !Ref BastionAllocationId 1079 | InstanceId: !Ref Bastion 1080 | PublicSecurityGroup: 1081 | Type: 'AWS::EC2::SecurityGroup' 1082 | Properties: 1083 | VpcId: !Ref PrivateChain 1084 | GroupName: PublicSecurityGroup 1085 | GroupDescription: Security Group for public subnet. Enable SSH access via port 22 1086 | SecurityGroupIngress: 1087 | - IpProtocol: tcp 1088 | FromPort: '22' 1089 | ToPort: '22' 1090 | CidrIp: 0.0.0.0/0 1091 | Tags: 1092 | - Key: Name 1093 | Value: PublicSecurityGroup 1094 | - Key: Component 1095 | Value: PrivateChain 1096 | PublicRouteTable: 1097 | Type: 'AWS::EC2::RouteTable' 1098 | Properties: 1099 | VpcId: !Ref PrivateChain 1100 | Tags: 1101 | - Key: Name 1102 | Value: PublicRouteTable 1103 | - Key: Component 1104 | Value: PrivateChain 1105 | PublicRoute: 1106 | Type: 'AWS::EC2::Route' 1107 | DependsOn: VPCGatewayAttachment 1108 | Properties: 1109 | RouteTableId: !Ref PublicRouteTable 1110 | DestinationCidrBlock: 0.0.0.0/0 1111 | GatewayId: !Ref InternetGateway 1112 | PublicSubnetRouteTableAssociation: 1113 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1114 | Properties: 1115 | SubnetId: !Ref PublicSubnet 1116 | RouteTableId: !Ref PublicRouteTable 1117 | NatGateway: 1118 | Type: 'AWS::EC2::NatGateway' 1119 | Properties: 1120 | AllocationId: !Ref NatAllocationId 1121 | SubnetId: !Ref PublicSubnet 1122 | Tags: 1123 | - Key: Name 1124 | Value: NatGateway 1125 | - Key: Component 1126 | Value: PrivateChain 1127 | PrivateRouteTable: 1128 | Type: 'AWS::EC2::RouteTable' 1129 | Properties: 1130 | VpcId: !Ref PrivateChain 1131 | Tags: 1132 | - Key: Name 1133 | Value: PrivateRouteTable 1134 | - Key: Component 1135 | Value: PrivateChain 1136 | PrivateRoute: 1137 | Type: 'AWS::EC2::Route' 1138 | Properties: 1139 | RouteTableId: !Ref PrivateRouteTable 1140 | DestinationCidrBlock: 0.0.0.0/0 1141 | NatGatewayId: !Ref NatGateway 1142 | PrivateSubnetRouteTableAssociation1: 1143 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1144 | Properties: 1145 | SubnetId: !Ref PrivateSubNet1 1146 | RouteTableId: !Ref PrivateRouteTable 1147 | PrivateSubnetRouteTableAssociation2: 1148 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1149 | Properties: 1150 | SubnetId: !Ref PrivateSubNet2 1151 | RouteTableId: !Ref PrivateRouteTable 1152 | PrivateLambdaSubnetRouteTableAssociation: 1153 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1154 | Properties: 1155 | SubnetId: !Ref PrivateLambdaSubNet 1156 | RouteTableId: !Ref PrivateRouteTable 1157 | PrivateLambdaMultiAZ1aSubNetRouteTableAssociation: 1158 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1159 | Properties: 1160 | SubnetId: !Ref PrivateLambdaMultiAZ1aSubNet 1161 | RouteTableId: !Ref PrivateRouteTable 1162 | PrivateLambdaMultiAZ1cSubNetRouteTableAssociation: 1163 | Type: 'AWS::EC2::SubnetRouteTableAssociation' 1164 | Properties: 1165 | SubnetId: !Ref PrivateLambdaMultiAZ1cSubNet 1166 | RouteTableId: !Ref PrivateRouteTable 1167 | LogRole: 1168 | Type: AWS::IAM::Role 1169 | Properties: 1170 | AssumeRolePolicyDocument: 1171 | Version: '2012-10-17' 1172 | Statement: 1173 | - Effect: Allow 1174 | Principal: 1175 | Service: 1176 | - ec2.amazonaws.com 1177 | - vpc-flow-logs.amazonaws.com 1178 | Action: 1179 | - sts:AssumeRole 1180 | Path: "/" 1181 | Policies: 1182 | - PolicyName: LogRolePolicy 1183 | PolicyDocument: 1184 | Version: '2012-10-17' 1185 | Statement: 1186 | - Effect: Allow 1187 | Action: 1188 | - logs:Create* 1189 | - logs:PutLogEvents 1190 | - s3:GetObject 1191 | Resource: 1192 | - arn:aws:logs:*:*:* 1193 | - arn:aws:s3:::* 1194 | LogRoleInstanceProfile: 1195 | Type: AWS::IAM::InstanceProfile 1196 | Properties: 1197 | Path: "/" 1198 | Roles: 1199 | - Ref: LogRole 1200 | 1201 | Outputs: 1202 | PrivatChainVpcId: 1203 | Value: !Ref PrivateChain 1204 | Export: 1205 | Name: !Sub "${AlisAppId}-PrivateChainVpcId" 1206 | PrivateLambdaMultiAZ1aSubNetId: 1207 | Value: !Ref PrivateLambdaMultiAZ1aSubNet 1208 | Export: 1209 | Name: !Sub "${AlisAppId}-PrivateLambdaMultiAZ1aSubNetId" 1210 | PrivateLambdaMultiAZ1cSubNetId: 1211 | Value: !Ref PrivateLambdaMultiAZ1cSubNet 1212 | Export: 1213 | Name: !Sub "${AlisAppId}-PrivateLambdaMultiAZ1cSubNetId" 1214 | FrontendSecurityGroupId: 1215 | Value: !Ref FrontendSecurityGroup 1216 | Export: 1217 | Name: !Sub "${AlisAppId}-FrontendSecurityGroupId" 1218 | --------------------------------------------------------------------------------