Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9749

IAM認証のAWS API GatewayにC#からIAMロールでSigV4署名してアクセスするには

$
0
0

IAM認証を使っているAWSのAPI Gatewayは、APIリクエスト時にSigV4署名が必要です。

前回の記事では、IAMユーザで認証するAPI Gateway呼び出しをC#で書きました。

今回は、EC2インスタンスにアタッチされているIAMロールでの認証です。

前提

IAMロールのアタッチされているEC2インスタンスでC#のコードを実行します。~/.aws/configに以下のようにIAMロールが指定されているものとします。

[profile default]
role_arn = arn:aws:iam::999999999999:role/ROLENAME
credential_source = Ec2InstanceMetadata

API GatewayのリソースポリシーにはこのIAMロールからのAPIアクセスを許可してあるものとします。

動作確認した環境はUbuntu 20.04です。

C#の環境は以下の通り。

$dotnet --version3.1.402

以下は私の記事でして、このとおりC#をほとんど始めて触っています。C#の流儀と違うところがあったらごめんなさい。

サンプルコードダウンロード

SigV4署名するC#のサンプルコードはAWS公式サイトにありますので、それをダウンロードし、必要なディレクトリのみ残します。

ここの手順の詳細は前回の記事を参照。

$mkdir sample
$cd sample
$mkdir tmp
$cd tmp
$wget https://docs.aws.amazon.com/AmazonS3/latest/API/samples/AmazonS3SigV4_Samples_CSharp.zip
$unzip AmazonS3SigV4_Samples_CSharp.zip
$cd ..
$mv tmp/AWSSignatureV4-S3-Sample/Signers ./
$mv tmp/AWSSignatureV4-S3-Sample/Util ./
$rm-r tmp

サンプルソースコードのnamespaceを全置換しておきます。(このコマンドの説明は sedコマンドでディレクトリ内の全ファイルをテキスト全置換するには)

$grep-rl AWSSignatureV4_S3_Sample Signers | xargs sed-i's/AWSSignatureV4_S3_Sample/Sample/g'$grep-rl AWSSignatureV4_S3_Sample Util | xargs sed-i's/AWSSignatureV4_S3_Sample/Sample/g'

C#のプロジェクト作成

dotnetコマンドでプロジェクトを作成します。

$dotnet new console

以下のようなディレクトリ構成になります。

$tree
.
├── obj
│   ├── project.assets.json
│   ├── project.nuget.cache
│   ├── sample.csproj.nuget.dgspec.json
│   ├── sample.csproj.nuget.g.props
│   └── sample.csproj.nuget.g.targets
├── Program.cs
├── sample.csproj
├── Signers
│   ├── AWS4SignerBase.cs
│   ├── AWS4SignerForAuthorizationHeader.cs
│   ├── AWS4SignerForChunkedUpload.cs
│   ├── AWS4SignerForPOST.cs
│   └── AWS4SignerForQueryParameterAuth.cs
└── Util
    └── HttpHelpers.cs

3 directories, 13 files

sample.csprojに以下のように RootNamespaceの項目を追加します。サンプルダウンロード後に全置換したnamespaceを指定します。

<ProjectSdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>netcoreapp3.1</TargetFramework><RootNamespace>Sample</RootNamespace></PropertyGroup></Project>

必要なパッケージをダウンロードします。

$dotnet add package AWSSDK.SecurityToken

C#のソースコード

Program.csは以下です。

usingSystem;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingAmazon.Runtime;usingAmazon.Runtime.CredentialManagement;usingAmazon.SecurityToken;usingAmazon.SecurityToken.Model;usingSample.Signers;usingSample.Util;namespaceSample{classProgram{privatestaticasyncTaskRun(){// ~/.aws/credentials からRoleArnを読み取るSharedCredentialsFilesharedFile=newSharedCredentialsFile();sharedFile.TryGetProfile("default",outCredentialProfilecredentialProfile);stringroleArn=credentialProfile.Options.RoleArn;// IAMロールにassumeするInstanceProfileAWSCredentialsinstanceCredentials=newInstanceProfileAWSCredentials();AmazonSecurityTokenServiceClientstsClient=newAmazonSecurityTokenServiceClient(instanceCredentials);AssumeRoleRequestassumeRoleRequest=newAssumeRoleRequest{RoleArn=roleArn,RoleSessionName="test_session",};varassumeRoleResponse=awaitstsClient.AssumeRoleAsync(assumeRoleRequest);varcredentials=assumeRoleResponse.Credentials;varuri=newUri("https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello");// 署名するためのソースとなるヘッダ情報varheaders=newDictionary<string,string>{{AWS4SignerBase.X_Amz_Content_SHA256,AWS4SignerBase.EMPTY_BODY_SHA256},{"content-type","text/plain"},{"x-amz-security-token",credentials.SessionToken},// IAMロールではこれが必要};// 署名を作成varsigner=newAWS4SignerForAuthorizationHeader{EndpointUri=uri,HttpMethod="GET",Service="execute-api",Region="ap-northeast-1"};varauthorization=signer.ComputeSignature(headers,"",// no query parametersAWS4SignerBase.EMPTY_BODY_SHA256,credentials.AccessKeyId,credentials.SecretAccessKey);// リクエストヘッダに署名を追加headers.Add("Authorization",authorization);// リクエスト実行// HttpHelpers はUtilで定義HttpHelpers.InvokeHttpRequest(uri,"GET",headers,null);}staticvoidMain(string[]args){Run().Wait();}}}

uriはAPI GatewayのAPIのURLを入れます。

実行

以下のコマンドで実行できます。

$dotnet run

ダウンロードしたサンプルコードのSignersUtilにデバッグ用出力があるので、いろいろ表示されますが、最後にAPI Gatewayからのレスポンスが表示されます。

情報源

C#でIAMロールにAssumeする方法がわからず、今回のテーマは難儀でした。わかってしまえば大したことないのですが。

参考にした情報は、前回の記事に加えて、AWS SDK for .NETのAPIレファレンスとPython boto3のソースコードと、参考としてawscurlというコマンドのソースコードです。

AWS SDK for .NETのドキュメントは、説明が少なく、メソッドのシグニチャはわかってもどう使ったらいいのかがわかりませんでした。IAMロールでの署名をしているはずのawscurlのソースコードを読み、awscurlが呼び出しているboto3のソースコードも読むことで、AWSのAPIをどう呼び出しているのかを把握し、同じことをC#で書くことで実装できました。

boto3はAWSのAPIを呼び出しているだけだと思っていましたが、使いやすいように多くの機能をPythonで実装していることを実感しました。boto3とは違って、AWS SDK for .NETは単にAWS API呼び出しをそのままメソッドにしているだけのように見えます。


Viewing all articles
Browse latest Browse all 9749

Trending Articles