いんふら女子めも

備忘録です

「AWS IAMのマニアックな話」を読んでIAMについて勉強した

最近、IAMをどのように管理するのがベストなのか悩んでいたので「AWS IAMのマニアックな話」を読みました。全部で126ページの薄い本ではありますが、内容はIAMについて分かりやすく丁寧に書かれているし、チュートリアルもあるので手を動かしながら理解を深められる良本だと思いました。
IAMについての説明は公式ドキュメントだったりクラスメソッドさんの記事にもまとまっていますが、どのようにIAMポリシーをデザインして運用していくのかについての知見は中々得られないので勉強になりました。
booth.pm

全部読んでみて

この本を通して筆者が言いたいのは、「IAMベストプラクティスをよく読んで理解し、実践すること」だと感じました。そのために、IAMのベストプラクティスについて分かりやすく解説されているのがこの本なのかなと思います。
IAMベストプラクティス
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.htmldocs.aws.amazon.com

AWSセキュリティインシデントの大半は、アクセスキーやシークレットアクセスキーの漏洩などのIAM関連だそうです。この本では、Capital Oneの不正アクセスによる情報流出の事件を例にとって、どのようにIAMポリシーを設定すればよかったのかを説明されています。セキュリティ関連のインシデントは心臓に悪いのでできるだけ遭遇したくないですね。
筆者はインシデントを回避するためにもできるだけアクセスキーを発行しないで済む運用を推奨しています。今ではほとんどのケースでアクセスキー発行しなくても代替できるようになっているようなので、アクセスキーを使っているものは再度見直しして最小限したいと思いました。

勉強になったところ

  • IAMポリシーのデザインパターン
    • ホワイトリスト(許可したい権限のみ付与する)、ブラックリスト(許可しない権限のみを剥奪する)、ハイブリットの3つのパターンがある。
    • 普段ホワイトリストパターンでしか運用してなかったので、ブラックリストやハイブリットパターンも用途によっては使うのあり。
    • 確かにホワイトリストだと許可する権限を細かく設計しないといけないので、ちょっと大変さはあるのは分かる。。
  • IAMとセキュリティ
    • IAMベストプラクティス全部は実践できていないのでもう一度見直したい
    • AWSアカウント(ルートユーザー)で操作しない!MFA使う!最小権限の付与!
    • Lambdaの権限は盲点。FullAccess権限はつけないこと
      • AWSリソースのアクセス権をコントロールできてしまうから
  • IAMの運用
    • 役割と責任範囲を明確にする(誰が使ってどんな操作ができるようになっているのか洗い出す)
    • IAMユーザーは人だけではなく使っているツールやプログラムも洗い出しておく
    • 定期的にIAMユーザーの見直し、不要になったらすぐ消す
    • 人間は必ずミスする
      • 最小権限を付与することで影響を最小限にする
      • AWSマネージドサービスを使う(CloudTail, Config, GuardDutyなど)
    • MFA強制ポリシーよさそう(MFA認証しないとIAM以外の権限を拒否するポリシー)

めも

勉強のためにIAM周りのめもをしました

f:id:akngo22:20191231193922p:plain
認証と認可
f:id:akngo22:20191231194009p:plain
AWSアカウントとIAMユーザー
f:id:akngo22:20191231194057p:plain
IAMロールとIAMポリシー

AmazonLinux2でyumが使えなくなったとき

Amazon Linux2を使ってEC2インスタンスを立てていたのですが、突然yumが使えなくなり戸惑ったのでその対処法について書きます。

エラー内容

遭遇したエラーは下記。
yum updateしようとすると、HTTPエラーが発生しアクセス許可されていないと言われてしまいました。

$ yum update -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Could not retrieve mirrorlist http://amazonlinux.ap-northeast-1.amazonaws.com/2/core/latest/x86_64/mirror.list error was
14: HTTP Error 403 - Forbidden


 One of the configured repositories failed (Unknown),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Run the command with the repository temporarily disabled
            yum --disablerepo=<repoid> ...

     4. Disable the repository permanently, so yum won't use it by default. Yum
        will then just ignore the repository until you permanently enable it
        again or use --enablerepo for temporary usage:

yum-config-manager --disable <repoid>
        or
            subscription-manager repos --disable=<repoid>

     5. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true

Cannot find a valid baseurl for repo: amzn2-core/2/x86_64

原因

EC2インスタンスからS3にアクセスするためにインターネットを経由せず、VPCエンドポイントを使うように対象サブネットを紐づけしていたのですが、ポリシーを特定のバケットのみにしていたためyumレポジトリにアクセスできなくなっていたことが原因でした。
AmazonLinuxのyumレポジトリはS3上に置いてあるので、VPCエンドポイントのポリシーを特定のバケットのみに制限したことによってyumコマンドを実行してもS3上のレポジトリにアクセスすることができず、エラーとなりました。

デフォルトの設定だと、EC2インスタンスからS3のバケットへアクセスするには一旦インターネットを経由する必要がありました。しかし、VPCエンドポイントを作成し対象サブネットを紐づけすることによって、S3へのアクセスがインターネット経由ではなくVPCエンドポイント経由でできるようになります。そのため、yumでupdateしたりinstallしたりするときVPCエンドポイントを経由してS3にアクセスしようとするので、ポリシーの設定でyumレポジトリが配置されているバケットへのトラフィックを許可しておく必要があります。

対処法

ポリシーの編集は、[VPC]>[Endpoint]>[Policy]>[Edit]から行います。

# 公式ドキュメントより
{
  "Statement": [
    {
      "Sid": "Amazon Linux AMI Repository Access",
      "Principal": "*",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::packages.*.amazonaws.com/*",
        "arn:aws:s3:::repo.*.amazonaws.com/*"
      ]
    }
  ]
}

上記のようにレポジトリへのトラフィックを許可すれば、yumコマンドが実行できるようになっていると思います。

terraformに入門した(aws-vaultを使うver)

はじめに

terraformに入門したので、環境構築及び基本操作をまとめました。

環境

  • CentOS7.6
  • Terraform0.12.13
  • aws-cli1.16.278
  • aws-vault4.7.1

手順

1. linuxbrewのインストール

brewコマンドがないとaws-vaultをインストールできないので、事前に入れておきます。手順は公式HPに沿って進めるとインストール完了します。
docs.brew.sh

# linuxbrewコマンドのインストールに必要なものを入れる
sudo yum groupinstall 'Development Tools'
sudo yum install curl file git
# linuxbrewコマンドインストール
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
# brewコマンドを使えるようにパスを通す
test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
# brewコマンド使えるか確認
brew install hello

インストールに失敗するときは、yum updateしてみましょう。

2. aws-cliのインストール

aws-vaultコマンド使うときは、awsコマンドも使うことも多いので入っていなければインストールしましょう。
aws-cliはpipコマンドで導入することができます。pipコマンドが入っていなければ事前にインストールしておきます。
docs.aws.amazon.com
pipコマンドはpythonがインストールされていればありますが、おすすめはpyenvコマンドでpythonをインストールするようにしておくとバージョンを切り替えしやすいので良いと思います。
github.com

# pipコマンドでaws-cliコマンドをインストール
pip3 install awscli --upgrade --user
# コマンドが入っているか確認
aws --version
aws-cli/1.16.278 Python/3.6.3 Linux/3.10.0-957.10.1.el7.x86_64 botocore/1.13.14

インストールしたのにcommand not foundと表示される場合は、パスが通ってないと思うので下記コマンドを実行。

export PATH=~/.local/bin:$PATH
source ~/.bash_profile

3. aws-vaultのインストール

brewコマンドを使ってインストールします。

# aws-vaultのインストール
brew install aws-vault

インストールが終わったら、プロファイルに使うAWSのアクセスキー及びシークレットキーを登録します。
アクセスキー及びシークレットキーは、AWSのコンソールにログインし「マイセキュリティ資格情報」から「新しいアクセスキーの作成」をクリックして発行します。
f:id:akngo22:20191110190401j:plain

# プロファイルを登録する
aws-vault add [profile-name]
Enter Access Key Id: ABDCDEFDASDASF
Enter Secret Key: %%%
# aws-vaultコマンドを実行するときのパスフレーズを設定
Enter passphrase to unlock /home/vagrant/.awsvault/keys/:

設定が完了したらプロファイルが登録されているか下記コマンドで確認し、awsのコンソールにログインできるか確認します。

# プロファイルが登録されているか確認
aws-vault ls
Profile                  Credentials              Sessions
=======                  ===========              ========
my-profile               my-profile               -
# ログイン確認
aws-vault login [profile_name]

github.com
コンソール画面がブラウザで開くか、発行されたURLにアクセスしてコンソール画面には入れればOK!

4. terraformのインストール

インストールは簡単です。下記コマンドを実行します。

# terraformインストール
brew install terraform
# バージョン確認
terraform --version
Terraform v0.12.13

5. terraformを使ってみる

適当にterraform用のディレクトリを作成し、リソース定義用のファイルを作ります。

# ディレクトリ作成
mkdir terraform_test
cd terraform_test
# main.tfファイルを作成
vim main.tf

main.tfの中身はec2インスタンスを立てるための定義を書いていきます。使うAMI IDはEC2>イメージ>AMIからAMI IDを控えます。

main.tf
resource "aws_instance" "example" {
  ami = "ami-0xxxxxxxxxxxxxxxxxxx"  
  instance_type = "t2.micro"
}

コードを書いたら、terraform initしてterraformを実行するのに必要なバイナリをダウンロードします。

$ aws-vault exec my-profile -- terraform init

Initializing the backend...

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 2.35"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

successしていたらOKです。

続いて、terraform planコマンドを実行してどんなリソースを追加する予定か実行計画を表示させます。

$ aws-vault exec my-profile -- terraform plan
Enter passphrase to unlock /home/vagrant/.awsvault/keys/:
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-0axxxxxxxxxxxxxxxxx"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

+ createがリソースを追加する処理を行うことを表していて、追加される部分には"+"が表示されています。特にエラーが表示されなければterraform applyコマンドを実行し、リソースを追加します。

$ aws-vault exec my-profile -- terraform apply
Enter passphrase to unlock /home/vagrant/.awsvault/keys/:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-0axxxxxxxxxxxxxxxx"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Still creating... [21s elapsed]
aws_instance.example: Still creating... [35s elapsed]
aws_instance.example: Still creating... [45s elapsed]
aws_instance.example: Creation complete after 55s [id=i-00323c63887212062]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

リソースを更新するときは、main.tfに定義を追加し再度terraform applyを実行すればOK。ただし、追加したものによってはリソースが置き換わる(元々あったものが削除され新しくリソースが作成される)こともあるので、terraform planで変更内容を確認してから実行すると良いです。

おわり。

【めも】linuxbrewコマンドのインストールに失敗するときはアップデートすると良い

何をしていたのか

自分のLinux環境にaws-vaultを導入しようと思い、まずはlinuxbrewを公式HPを見てインストールしていたら失敗した。
実行していたコマンドは下記。

sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

docs.brew.sh

環境

  • CentOS7.6

対処法

yumのアップデートで解決。

sudo yum update
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

ubuntu環境では、build-essentialのインストールが失敗していたが、これもapt-getのアップデートで解決。

sudo apt-get update
sudo apt-get install build-essential curl file git

おわり