AWSリソースを安全に共有する

記事タイトルとURLをコピーする

CDP Advent Calendar 2012の18日目を担当させていただく横倉です。

今回書かせていただく内容は 年末セキュリティ点検ウィーク ☆⌒(ゝω・)vキャピ にある
”別のAWSアカウントとの共有はIAMで賢く行なう” を詳細にした内容になります。
AWSを安全に共有するパターンです。 元ネタ
Delegating API Access to AWS Services Using IAM Roles

解決したい課題

AWSアカウントは、自分のAWSリソースであれば、問題なく自由にアクセスして操作することができます。
しかし、別のAWSアカウントのリソースにアクセスしたいとなったら、IAMユーザーを作成してもらい、IAMユーザーのログイン情報、またはアクセスキー、シークレットアクセスキーなどを送ってもらう必要がありました。 この場合はIAMユーザーのログイン情報、またはアクセスキー、シークレットキーをアカウント所有者の間で直接やり取りする必要があります。
社内などの内部でのやり取りであれば管理は容易かもしれません。
しかし、外部と連携する場合、アカウント情報の流出というリスクがある為、厳重な管理のもとIAMユーザーの定期的な再発行など、管理コストが高くなってしまうのが必然です

解決方法

IAMのRole機能を利用することで、外部AWSアカウントのIAMユーザーに対してアクセス許可することができます。
その為、AWSのリソースを共有するのにIAMユーザーをやり取りすることが不要になります。 イメージとしては、プライベートAMIを特定のAWSアカウントに共有する作業に似ています。
AWSリソースへのアクセスポリシーを特定のAWSアカウントに共有する作業になります。 例として、別アカウントのSQSにアクセスするまでを2ステップでご紹介します。

  • 1 信用するアカウント(piyo@example.com)  
    AWSのSQSへのアクセスを許可するIAM Roleを作成
     
  • 2 信用されたアカウント(hoge@example.com)
    hoge@example.comがメインアカウントのIAMユーザーにポリシーを設定

1 信用するアカウント(piyo@example.com)   
AWSのSQSへのアクセスを許可するIAM Roleを作成

piyo@example.comのアカウントでManagement Console のIAMコンソールからRolesリンクを開き、”Create New Role”をクリック、作成するRoleの名前を入力します。 ”Roles for Cross-Account Access”にチェックを入れる。 共有したいAWSアカウントのIDを入力します。 共有するポリシーを選択します。ここではSQSにアクセスできるように”Amazon SQS Full Access”を選択します。 ポリシー内容の確認後、作成するRoleの確認画面で問題なければCreate Roleをクリックします。 作成したRoleから、ARN(Amazon Resource Name)を確認します。
※ 後ほど、信用されたアカウントでポリシー作成する際に指定するものになります

2 信用されたアカウント(hoge@example.com) 
hoge@example.comがメインアカウントのIAMユーザーにポリシーを設定

hoge@example.comのアカウントでManagement Console のIAMコンソールより、UsersリンクよりIAMユーザーを選択します。
※ 事前にIAMユーザーの作成が必要になりますので、そちらは別途ご確認ください。 IAMユーザーを選択した状態で、Permissionsより”Attach User Policy”をクリック Custom Policy を選択します。 Policy Nameを入力し、ActionとResourceを入力します。
Action にはsts:AssumeRoleと記入し、Resourceには先程作成したRoleのARN(Amazon Resource Name)を入力します。 IAMユーザーはRoleにアクセスするのに、AWS STS(Security Token Service)というサービスを利用します。
AWS Security Token Service 

  • ・IAMユーザーが一時的にAWSアカウントに対して限られた権限を要求できるサービス
  • ・AssumeRoleはIAMユーザーしか使えず、AWSアカウントでは利用不可

対象のIAMユーザーにポリシーがアタッチされていることを確認してください。

SQSにアクセスする方法

AWS Java SDKを使ったサンプルコードを記載します。

import com.amazonaws.*;
import com.amazonaws.services.sqs.*;
import com.amazonaws.services.securitytoken.*;
import com.amazonaws.services.securitytoken.model.*;
import com.amazonaws.auth.*;

public class AssumeRoleDemo {

    private static final String ROLE_ARN =
            "arn:aws:iam::111122223333:role/SQS-Access-Role-for-hoge";
    private static AWSCredentials longTermCredentials_;

    private static void init() throws Exception {
        // acquire long term credentials from the properties file
        longTermCredentials_ = new PropertiesCredentials(AssumeRoleDemo.class.getResourceAsStream("AwsCredentials.properties"));
        }
    public static void main(final String[] args) throws Exception {
        init();

        // AWS Security Token Service (STS) AssumeRole APIを利用して、piyo@example.comのSQSにアクセスするため認証する

        AWSSecurityTokenServiceClient stsClient = new
            AWSSecurityTokenServiceClient(longTermCredentials_);

        AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
            .withRoleArn(ROLE_ARN)
            .withDurationSeconds(3600)
            .withRoleSessionName("demo");

        AssumeRoleResult assumeResult =
        stsClient.assumeRole(assumeRequest);

        // AssumeRoleは一時的なアクセス情報をIAMのRoleに割り当てます。

        BasicSessionCredentials temporaryCredentials =
                new BasicSessionCredentials(
                            assumeResult.getCredentials().getAccessKeyId(),
                            assumeResult.getCredentials().getSecretAccessKey(),
                            assumeResult.getCredentials().getSessionToken());

        AmazonSQS sqs = new AmazonSQSClient(temporaryCredentials);

        //東京リージョンを選択

        sqs.setEndpoint("sqs.ap-northeast-1.amazonaws.com");
        System.out.println("===========================================");
        System.out.println("Getting Started with Amazon SQS");
        System.out.println("===========================================n");

        try {

            // List queues
            System.out.println("Listing all queues in your account.n");
            for (String queueUrl : sqs.listQueues().getQueueUrls()) {
                System.out.println("  QueueUrl: " + queueUrl);
            }
            System.out.println();
        } catch (AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException, which means your request made it " +
                    "to Amazon SQS, but was rejected with an error response for some reason.");
            System.out.println("Error Message:    " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code:   " + ase.getErrorCode());
            System.out.println("Error Type:       " + ase.getErrorType());
            System.out.println("Request ID:       " + ase.getRequestId());
        } catch (AmazonClientException ace) {
            System.out.println("Caught an AmazonClientException, which means the client encountered " +
                    "a serious internal problem while trying to communicate with SQS, such as not " +
                    "being able to access the network.");
            System.out.println("Error Message: " + ace.getMessage());
        }
    }
}

まとめ

運用を考えたセキュリティ設計もクラウドならではであり、様々なパターンができると思います。
そんな中で、今回の様な安全なリソース共有方法は今後のAWSの更なる可能性を感じますね。

参考

Delegating API Access to AWS Services Using IAM Roles

AWS Identity and Access Management

AWS Security Token Service