Slide 1

Slide 1 text

Inside of awspec -AWSをテストする⽅法。そしてその中のはなし- Kenʼichiro Oyama Fusic Co.,Ltd. 2016.10.22 1 JAWS Festa 2016

Slide 2

Slide 2 text

Who 2 JAWS Festa 2016

Slide 3

Slide 3 text

k1LoW   Kenʼichiro Oyama   @k1LoW   Fusic Co.,Ltd. エンジニア   基盤ユニット テックリード   フクオカ カラ キマシタ   JAWS-UG福岡に出没します   GitHub organizations   fukuokarb / dotcake / emacs-jp / etc.   好きなAWSサービス 3 JAWS Festa 2016

Slide 4

Slide 4 text

AWSをテストする 4 JAWS Festa 2016

Slide 5

Slide 5 text

の前に 5 JAWS Festa 2016

Slide 6

Slide 6 text

AWS”で”テストする話を 6 JAWS Festa 2016

Slide 7

Slide 7 text

CM 7 JAWS Festa 2016

Slide 8

Slide 8 text

ٙࣅσʔλͰ*P5։ൃΛՃ଎͢Δ ࣄલЌొ࿥ड෇த IUUQTNPDLNPDLDPNQSF

Slide 9

Slide 9 text

/CM 9 JAWS Festa 2016

Slide 10

Slide 10 text

10 JAWS Festa 2016

Slide 11

Slide 11 text

awspec   AWSリソースの構成テストツール   http://github.com/k1LoW/awspec   構築したAWSリソースをRSpecなDSLでテストが可能 11 JAWS Festa 2016

Slide 12

Slide 12 text

ec2  describe ec2('my-ec2-tag-name') do   it { should be_running }   its(:instance_id) { should eq 'i-ec12345a' }   its(:instance_type) { should eq ’t2.small' }   its(:public_ip_address) { should eq '123.0.456.789' }   it { should have_security_group('my-sg-name') }   it { should belong_to_vpc('my-vpc') }   it { should belong_to_subnet('subnet-1234a567') }   it { should have_eip('123.0.456.789') }   it { should be_disabled_api_termination }  end 12 JAWS Festa 2016

Slide 13

Slide 13 text

route53_hosted_zone  describe route53_hosted_zone('example.com.') do   it { should exist }   its(:resource_record_set_count) { should eq 5 }   it { should have_record_set('example.com.').a('123.456.7.890') }   it { should have_record_set('example.com.').mx('10 mail.example.com') }   it { should have_record_set('mail.example.com.').a('123.456.7.890').ttl(3600) }   ns = 'ns-123.awsdns-45.net.  ns-6789.awsdns-01.org.  ns-2345.awsdns-67.co.uk.  ns-890.awsdns-12.com.'   it { should have_record_set('example.com.').ns(ns) }   it { should have_record_set('s3.example.com.').alias('s3-website-us- east-1.amazonaws.com.', 'Z2ABCDEFGHIJKL') }  end 13 JAWS Festa 2016

Slide 14

Slide 14 text

Resource Types (v.0.57.1)   ami   autoscaling_group   cloudtrail   cloudwatch_alarm   cloudwatch_event   directconnect_virtual   nterface   ebs   ec2   elasticache   elasticache_cache_par ameter_group   elasticsearch   elb   iam_group   iam_policy   iam_role   iam_user   kms   lambda   launch_configuration   nat_gateway   network_acl   network_interface   rds   rds_db_cluster_para meter_group   rds_db_parameter_gr oup   route53_hosted_zone   route_table   s3_bucket   security_group   ses_identity   subnet   vpc   cloudfront_distributio n   elastictranscoder_pipe line   waf_web_acl 14 JAWS Festa 2016

Slide 15

Slide 15 text

has 36 resource types 15 JAWS Festa 2016

Slide 16

Slide 16 text

awspec generate  ~ > awspec generate  Commands:   awspec generate cloudwatch_alarm # Generate cloudwatch_alarm spec   awspec generate cloudwatch_event # Generate cloudwatch_event spec   awspec generate directconnect # Generate directconnect spec   awspec generate ebs # Generate attached ebs spec   awspec generate ec2 [vpc_id] # Generate ec2 spec from VPC ID (or VPC "Name" tag)   awspec generate elasticsearch # Generate elasticsearch spec   awspec generate elb [vpc_id] # Generate elb spec from VPC ID (or VPC "Name" tag)   awspec generate help [COMMAND] # Describe subcommands or one specific subcommand   awspec generate iam_group # Generate iam_group spec   awspec generate iam_policy # Generate attached iam_policy spec   awspec generate iam_role # Generate iam_role spec   awspec generate iam_user # Generate iam_user spec   awspec generate kms # Generate kms spec   awspec generate lambda # Generate lambda spec   awspec generate nat_gateway [vpc_id] # Generate nat_gateway spec from VPC ID (or VPC "Name" tag)   awspec generate network_acl [vpc_id] # Generate network_acl spec from VPC ID (or VPC "Name" tag)   awspec generate network_interface [vpc_id] # Generate network_interface spec from VPC ID (or VPC "Name" tag)   awspec generate rds [vpc_id] # Generate rds spec from VPC ID (or VPC "Name" tag)   awspec generate route53_hosted_zone [example.com.] # Generate route53_hosted_zone spec from Domain name   awspec generate route_table [vpc_id] # Generate route_table spec from VPC ID (or VPC "Name" tag)   awspec generate s3_bucket [backet_name] # Generate s3_bucket spec from S3 bucket name. if NO args, Generate all.   awspec generate security_group [vpc_id] # Generate security_group spec from VPC ID (or VPC "Name" tag)   awspec generate subnet [vpc_id] # Generate subnet spec from VPC ID (or VPC "Name" tag)   awspec generate vpc [vpc_id] # Generate vpc spec from VPC ID (or VPC "Name" tag) 16 JAWS Festa 2016

Slide 17

Slide 17 text

can generate 23 type spec 17 JAWS Festa 2016

Slide 18

Slide 18 text

Inside of awspec 18 JAWS Festa 2016

Slide 19

Slide 19 text

19 JAWS Festa 2016

Slide 20

Slide 20 text

awspec written by Ruby   aws-sdk-rubyの開発が活発だった   re:Invent中の発表とSDKの新機能リリースがほぼリアル タイム   Serverspecの良さを感じていた   Serverspec本も相当勉強になる   同じようなDSLでテストをしたかった   Fukuoka.rbがあった   事実、内部実装でかなり助けてもらった   http://k1low.hatenablog.com/entry/2015/12/11/185728 20 JAWS Festa 2016

Slide 21

Slide 21 text

tree -d awspec/ !"" bin !"" doc # $"" _resource_types !"" exe !"" lib # $"" awspec # !"" command # !"" ext # !"" generator # # !"" doc # # # $"" type # # $"" spec # !"" helper # # $"" finder # !"" matcher # !"" stub # $"" type $"" spec 21 JAWS Festa 2016

Slide 22

Slide 22 text

awspec toolbox 22 JAWS Festa 2016

Slide 23

Slide 23 text

bundle exec bin/toolbox template ec2 23 JAWS Festa 2016

Slide 24

Slide 24 text

bundle exec bin/toolbox template   awspecに新しいリソースタイプを追加するときに利⽤ するコマンド   $ bundle exec bin/toolbox template redshift   リソースタイプ作成に最低限必要なファイルが⽣成される   ⽣成されたファイルを他のリソースタイプの書き⽅をマネて 修正すればだいたいOK 24 JAWS Festa 2016

Slide 25

Slide 25 text

bundle exec bin/toolbox docgen 25 JAWS Festa 2016

Slide 26

Slide 26 text

bundle exec bin/toolbox docgen   awspecのソースコードからドキュメントを作成するコ マンド   awspecはドキュメントジェネレータまで内包している っ!!   Awspec::Generator::Doc::Type:*   doc/_resource_types/*.md   ドキュメントもプログラムで⽣成することでaws-sdk- rubyのリリーススピードについていく 26 JAWS Festa 2016

Slide 27

Slide 27 text

つまり 27 JAWS Festa 2016

Slide 28

Slide 28 text

I want your contribution!! 28 JAWS Festa 2016

Slide 29

Slide 29 text

“AWS”をテストする 29 JAWS Festa 2016

Slide 30

Slide 30 text

“AWS”をテストするわけではない   “AWS上で⾃分たちが構築したリソース構成”をテスト する   意図した構成で構築できているか?   リソース構成   セキュリティ   運⽤中も意図した構成のままでいるか?   リソース構成に対しての外形監視に近い   チェック 30 JAWS Festa 2016

Slide 31

Slide 31 text

AWSのリソース構成を チェックする⽅法 31 JAWS Festa 2016

Slide 32

Slide 32 text

AWS Config / AWS Config Rules 32 JAWS Festa 2016

Slide 33

Slide 33 text

AWS Config / AWS Config Rules AWS Config は完全マネージド型のサービスで、セキュリティとガバナンス のため、AWS リソースインベントリ、設定履歴、および設定変更通知とい った機能が⽤意されています。Config Rules を使⽤して、AWS Config によ って記録された AWS リソース設定を⾃動的にチェックするルールを作成で きます。(AWS公式サイトより)   AWS謹製!   AWS Configの対応リソース   ALB、ACM、EC2、RDS、S3、VPC、IAM、EBS、 CloudTrail   アカウントにつき最⼤25のルール 33 JAWS Festa 2016

Slide 34

Slide 34 text

Codenize.tools 34 JAWS Festa 2016

Slide 35

Slide 35 text

Codenize.tools   “Codenize.tools manege any services by DSL.”   独⾃のDSLでべき等性を担保した形で構成を構築・管 理できる   リソースの種類ごとにツールが分かれている   チェックだけではなく、構築ができる。むしろ構築⽤   --dry-runでDSLの内容と構築済の構成を⽐較チェック   AWS版のChefやAnsibleに近い   既存の構成からDSLをエクスポートができる   対応リソース   Route53、Security Groups、ELB、IAM、CloudFormation、EIP、 CloudWatch Alarm、CloudWatch Logs、VPC Route table、S3 Bucket Policy、ECR Repository Policy、CloudFront 35 JAWS Festa 2016

Slide 36

Slide 36 text

Terraform 36 JAWS Festa 2016

Slide 37

Slide 37 text

Terraform   HashiCorp社が提供するオーケストレーションツール   対象はAWSだけではない   チェックだけではなく、構築ができる。むしろ構築⽤   terraform planでDSLの内容と構築済の構成を⽐較チェッ ク   既存の構成からDSLをエクスポートができる   さらにterraformingという強⼒なexport gemもある   対応リソース   多すぎて数えたくない 37 JAWS Festa 2016

Slide 38

Slide 38 text

私的使い分け表 ※個⼈の⾒解です! 38 JAWS Festa 2016 ⽤途 エクスポー ト AWSリソー スを操作す るか AWS Config AWS Config Rules AWSマネージドで監視したいとき。 構成変更のイベントトリガーで動か したいとき - しない Codenize.tools AWSリソース1種類について⼀括し て管理したいとき(特にIAM、 Route53など) ◯ する Terraform 構成新規構築時(リソースの種類が 全てある場合) ◯ する awspec ⼿動で作った環境のチェック リソース構成が多い環境での外形監 視 ◯ しない

Slide 39

Slide 39 text

実際は? テストしているの?どんなときにするの? どうやっているの?どうなの?なんなの? 39 JAWS Festa 2016

Slide 40

Slide 40 text

わかりません。。 AWSリソース構成の監視管理事例とかでてこない。。 40 JAWS Festa 2016

Slide 41

Slide 41 text

awspecのPull Requestからみる AWSリソース構成テストの ユースケース 41 JAWS Festa 2016

Slide 42

Slide 42 text

Pull Request   Pull Request(PR)… (ざっくり⾔うと)機能追加申請   AWSリソース構成のテスト⽬的を主とするawspecの PRを⾒れば「どういうところで使いたいのか」「どう いうユースケースで使っているのか」が⾒えてくるの ではないか?   PRをウォッチしているとできそう   あ、ちょうどawspecの作者でした   awspecの中(機能追加)と使う⼈の頭の中(ユースケ ース)(想像)を同時にご紹介 42 JAWS Festa 2016

Slide 43

Slide 43 text

Add tag matching support. 43 JAWS Festa 2016

Slide 44

Slide 44 text

Add tag matching support 44 JAWS Festa 2016   各リソースにおいて、タグの保持をテストするマッチ ャの追加   #119 PR by igorlg  describe ec2('my-ec2') do   it { should have_tag('Name').value('my-ec2') }  end

Slide 45

Slide 45 text

Add ability to search for network interface by name 45 JAWS Festa 2016

Slide 46

Slide 46 text

Add ability to search for network interface by name 46 JAWS Festa 2016   Network Interfaceリソースでもタグの保持をできるよ うにする修正   #191 PR by mdolian  describe network_interface(’eni-12ab3cde') do   it { should have_tag('Name').value('my-eni') }  end

Slide 47

Slide 47 text

タグの活⽤   みんなタグを活⽤しているっぽい   役割(ロール)でわけたり   設定を記述したり   AMIバックアップ頻度設定とか   network_interfaceのhave_tagとか忘れていた   タグが重要だからタグの保持のチェックをしたいので は? 47 JAWS Festa 2016

Slide 48

Slide 48 text

Add opened_only matcher for security groups. 48 JAWS Festa 2016

Slide 49

Slide 49 text

Add opened_only matcher for security groups. JAWS Festa 2016 49   Security Groupの「このポートだけオープンしている こと」をテストするマッチャの追加   #121 PR by ceaess  describe security_group('my-sg') do   its(:outbound) do should be_opened_only(50_000)   .protocol('tcp')   .for(%w(100.456.789.012/32 200.567.890.123/32))   end  end

Slide 50

Slide 50 text

過不⾜ないかを確認したい   セキュリティグループの「ポートが開いている」だけ のテストでは⼼もとない   セキュリティの設定数のカウントのチェックとの組み合わせ で上記を満たすことはできていたが、⾒やすさという点で欲 しかったのでは? 50 JAWS Festa 2016

Slide 51

Slide 51 text

Add ec2 `have_event()` and `have_events()`. 51 JAWS Festa 2016

Slide 52

Slide 52 text

Add ec2 `have_event()` and `have_events()` 52 JAWS Festa 2016   EC2にイベント(再起動イベントなど)があるか確認 するマッチャの追加   #131 PR by k1LoW  describe ec2('my-ec2') do   it { should have_event('system-reboot') }  end  describe ec2(’other-ec2') do   it { should_not have_events }  end

Slide 53

Slide 53 text

イベント通知怖い   AWSから通知されるスケジュールイベント   メール⾒過ごしていきなりリブートは怖い   イベント通知が「無いこと」を確認しておきたい   should_not   弊社では⼀部CIで外形監視として利⽤している   他に気楽な⽅法があれば知りたい。。。 53 JAWS Festa 2016

Slide 54

Slide 54 text

Add ec2 `have_classiclink_security_group()` 54 JAWS Festa 2016

Slide 55

Slide 55 text

Add ec2 `have_classiclink_security_group()` 55 JAWS Festa 2016   EC2-ClassicがClassicLink先のSecurity Groupをもっ ているかどうかを確認するマッチャの追加   #150 PR by matsuzj  describe ec2('my-classic-ec2') do   it { should have_classiclink_security_group('sg-2a3b4cd5') }   it { should have_classiclink_security_group('my-vpc-security- group-name') }  end

Slide 56

Slide 56 text

EC2-Classicからの脱却   おそらく移⾏時のTDD的な活⽤⽅法では?   EC2-ClassicをEC2 on VPCへ   コードで管理されていない⼿動で作られた構成 にテストの恩恵を 56 JAWS Festa 2016

Slide 57

Slide 57 text

Add CloudTrail support to check if logging is enabled. 57 JAWS Festa 2016

Slide 58

Slide 58 text

Add CloudTrail support to check if logging is enabled. 58 JAWS Festa 2016   CloudTrailでロギングが有効になっているかをテストす るマッチャの追加   #164 PR by arimbun  describe cloudtrail('my-trail') do   it { should be_logging }  end

Slide 59

Slide 59 text

そもそも   CloudTrailが動いていればAPIコールは管理で きる   「そもそも」そのCloudTrailが動いていなかっ たら?   ⼼配はつきない 59 JAWS Festa 2016

Slide 60

Slide 60 text

Add shared_context to specify region by context 60 JAWS Festa 2016

Slide 61

Slide 61 text

Add shared_context to specify region by context 61 JAWS Festa 2016   複数のリージョンをまたいだテストができるようにす る修正   #187 PR by takaishi  describe ec2('my-ec2’), region: 'us-east-1' do   it { should exist }  end

Slide 62

Slide 62 text

Tokyoリージョンにない(なかった)サービス   AWSのサービスのリリースはだいたい北⽶か ら   その時から稼働しているus-east-1のサービス とap-northeast-1のサービス両⽅共管理した い 62 JAWS Festa 2016

Slide 63

Slide 63 text

Pull Requestを⾒た感想 •  awspecを使ってでも「しっかり」テストしたいんだろ うなということがにじみ出ていました •  かつてより、より⼤きく複雑な構成のものがAWS上に展 開されているんだろうな。。。 •  構成要素は多いのに求められる管理体制もより厳しく •  既に職⼈芸は通⽤しないっぽい 63 JAWS Festa 2016

Slide 64

Slide 64 text

今後やりたいこと 64 JAWS Festa 2016

Slide 65

Slide 65 text

AWSアカウント⾃体のテスト •  awspecは基本的に1つのインスタンス、1つのVPCなどAWS リソース1つ1つに対してテストが可能 •  最近はさらに上位のレベルでテストを書いておきたいことが 多発している •  「このリージョンで起動しているRDSインスタンスは5台」 •  「EC2のスケジュールドイベントは現在0件」 •  「このアカウントではIAMの数は4つ」 •  なぜ作らないのか? •  具体的な実装デザインが決まっていない •  リソースタイプ名が決まらない(aws? account? resources?) •  だれか決めて欲しい 65 JAWS Festa 2016

Slide 66

Slide 66 text

なぜawspecなのか 66 JAWS Festa 2016

Slide 67

Slide 67 text

awspecの存在意義 •  Codenize.toolsやTerraformなど、使いやすい構成管理 ツールが出てきたため、AWSリソース⾃体がコードで管 理されるようになってきた •  わざわざ別にテストいらない •  「⼿作業で構築したAWSリソースの管理にはawspecが 良い」 •  http://inokara.hateblo.jp/entry/2016/02/21/120657 •  AWSのリソース構成をいじらないという安⼼感で、カジ ュアルにspecをgenerateしてチェック •  Yet Another AWS Config Rules 67 JAWS Festa 2016

Slide 68

Slide 68 text

さらに今後やりたいこと 68 JAWS Festa 2016

Slide 69

Slide 69 text

 $ cat < Gemfile  source "https://rubygems.org"  gem "awspec"  EOF  $ bundle install --path=vendor/bundle --binstubs=bundle_bin  ...  Bundle complete! 1 Gemfile dependency, 25 gems now installed.  Bundled gems are installed into ./vendor/bundle.  $ du -mcs ./  22 ./  22 total 69 JAWS Festa 2016

Slide 70

Slide 70 text

22MB 70 JAWS Festa 2016

Slide 71

Slide 71 text

わかりますよね? 71 JAWS Festa 2016

Slide 72

Slide 72 text

72 JAWS Festa 2016

Slide 73

Slide 73 text

awspec on AWS Lambda(切望)   RubyがAWS Lambdaで動けばawspecも動くはず   CloudTrail -> S3 -> AWS Lambda -> awspec   Rubyistにとって使いやすいAWS Config Rules   CI for AWS on AWS   2回⽬の訴え 73 JAWS Festa 2016

Slide 74

Slide 74 text

まとめ   awspecを作っています   AWSのリソース構成管理について試⾏錯誤中で す。   みなさんのAWSのリソース構成管理⼿法事例を 是⾮聞きたいです   特に形式⼿法でAlloyを採⽤して実戦投⼊して幸せになっている事 例が聞きたいです 74 JAWS Festa 2016

Slide 75

Slide 75 text

Thank you!  Fusicはテクノロジーが  好きなエンジニアを募集しています  https://fusic.github.io 75 JAWS Festa 2016

Slide 76

Slide 76 text

Omake Deep Dive 76 JAWS Festa 2016

Slide 77

Slide 77 text

aws-sdk-ruby 77 JAWS Festa 2016

Slide 78

Slide 78 text

aws-sdk-ruby •  リソースを操作するクラスは、以下の2種類 •  Seahorse::Client::Baseを継承したAws::*::Client •  (Aws::EC2::Clientなど) •  Resources::Resourceを継承したAws::*::Somename •  (Aws::EC2::Instanceなど) •  Clientはaws-cliのコマンド名とメソッド名が似ている •  Clientのほうが早くSDKに実装される •  Resourceのほうがリソースをオブジェクトとして綺麗に操作 できる 78 JAWS Festa 2016

Slide 79

Slide 79 text

awspecはClientベース •  できるだけ多くのAWSリソースを実装できたほうがよい •  awspecはリソースのREADが基本なのでそこまで難しいこ とはしていないのでいける •  でも、Resourceも使いたいよね •  でも、Resourceにはリソースの操作(READ以外)もあるの で安易に組み込めない •  「awspec使ったら書き⽅間違えてインスタンスが削除され た」は洒落にならない 79 JAWS Festa 2016

Slide 80

Slide 80 text

80 Awspec::ResourceReader JAWS Festa 2016

Slide 81

Slide 81 text

Awspec::ResourceReader •  awspecは内部でResourceを呼び出すときは必ず Awspec::ResourceReaderを経由する •  Awspec::ResourceReaderでAWSリソースを操作しそ うなメソッドを潰している •  ブラックリスト⽅式 •  これでほぼ安全にawspecが使える •  Resourceが使えるawspecのリソースタイプはドキュメント に”Advanced Use”の節がある 81 JAWS Festa 2016

Slide 82

Slide 82 text

vpc  describe vpc('vpc-ab123cde') do   it { should exist }   its(:resource) { should be_an_instance_of(Awspec::ResourceReader) }   its('resource.route_tables.first.route_table_id') { should eq 'rtb-a12bcd34' }   its('route_tables.first.route_table_id') { should eq 'rtb-a12bcd34' }  end 82 JAWS Festa 2016

Slide 83

Slide 83 text

aws-cliとかのprofileの管理 •  .aws/configと.aws/credentialsに分かれている •  なぜ?歴史的な理由? •  環境変数も使える •  awspecもaws-cliと同じようにprofileやENVを利⽤したい •  AWSなコマンドを⾃作する際もaws-cliと同じようにprofile やENVを利⽤したい 83 JAWS Festa 2016

Slide 84

Slide 84 text

awsecrets 84 JAWS Festa 2016

Slide 85

Slide 85 text

awsecrets •  Ruby製コマンドラインツール内でaws-cliと同じように認証 情報をAws.configに設定することを⽬指しているgem •  awspecとkumomeで利⽤ •  kumome: CloudWatchメトリクスをCLIでみれるツール •  http://k1low.hatenablog.com/entry/2016/02/01/083747 •  正直aws-sdk-rubyでやって欲しいし、Issueが上がっていたはず 85 JAWS Festa 2016  #!/usr/bin/env ruby  require 'awsecrets'  Awsecrets.load  ec2_client = Aws::EC2::Client.new  puts ec2_client   .describe_instances({ instance_ids: [ARGV.first] })   .reservations.first.instances.first