IAM認証を使っているAWSのAPI Gatewayは、APIリクエスト時にSigV4署名が必要です。
S3にSigV4署名でアクセスする方法は、AWS公式の以下のページにJavaとC#でのサンプルがあります。
これをベースにIAM認証を使っているAPI GatewayにC#でアクセスしてみます。
Pythonならば、以前の記事(IAM認証のAWS API GatewayにPythonからSigV4署名してアクセスするには)で似たことをしました。
前提
IAMユーザのアクセスキーが ~/.aws/credentials
に設定されていて、そのIAMユーザでAPI Gatewayにアクセスするものとします。API GatewayのリソースポリシーにはそのIAMユーザからのAPIアクセスを許可してあるものとします。
動作確認した環境はUbuntu 20.04です。
C#の環境は以下の通り。
$dotnet --version3.1.402
以下は私の記事でして、このとおりC#をほとんど始めて触っています。C#の流儀と違うところがあったらごめんなさい。
サンプルコードダウンロード
AWS公式のS3アクセスのサンプルをダウンロードします。
$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 ..
$tree
.
└── tmp
├── AmazonS3SigV4_Samples_CSharp.zip
├── AWSSignatureV4-S3-Sample
│ ├── App.config
│ ├── AWSSignatureV4-S3-Sample.csproj
│ ├── GetS3ObjectSample.cs
│ ├── POSTExampleForm.html
│ ├── PostS3ObjectSample.cs
│ ├── PresignedUrlSample.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── PutS3ObjectChunkedSample.cs
│ ├── PutS3ObjectSample.cs
│ ├── Signers
│ │ ├── AWS4SignerBase.cs
│ │ ├── AWS4SignerForAuthorizationHeader.cs
│ │ ├── AWS4SignerForChunkedUpload.cs
│ │ ├── AWS4SignerForPOST.cs
│ │ └── AWS4SignerForQueryParameterAuth.cs
│ └── Util
│ └── HttpHelpers.cs
└── AWSSignatureV4-S3-Sample.sln
5 directories, 18 files
IAMユーザを使ってS3アクセスするサンプルです。今回はこのうち、Signers
と Util
というディレクトリだけ使います。
$mv tmp/AWSSignatureV4-S3-Sample/Signers ./
$mv tmp/AWSSignatureV4-S3-Sample/Util ./
$rm-r tmp
このサンプルはnamespaceが AWSSignatureV4_S3_Sample
となっています。今回はS3ではないので、適当な名前 Sample
に全置換します。(このコマンドの説明は 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'
ここまでで以下のようなディレクトリ構成になります。
$tree
.
├── Signers
│ ├── AWS4SignerBase.cs
│ ├── AWS4SignerForAuthorizationHeader.cs
│ ├── AWS4SignerForChunkedUpload.cs
│ ├── AWS4SignerForPOST.cs
│ └── AWS4SignerForQueryParameterAuth.cs
└── Util
└── HttpHelpers.cs
2 directories, 6 files
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>
必要なパッケージをダウンロードします。 AWSSDK.Core
だけで大丈夫です。今回はHTTP(S)でAPIアクセスするだけですので、API Gatewayのパッケージは不要です。
$dotnet add package AWSSDK.Core
C#のソースコード
Program.cs
は以下です。
usingSystem;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingAmazon.Runtime.CredentialManagement;usingSample.Signers;usingSample.Util;namespaceSample{classProgram{privatestaticvoidRun(){// ~/.aws/credentials からアクセスキー、シークレットキーを読み取るvarsharedFile=newSharedCredentialsFile();sharedFile.TryGetProfile("default",outCredentialProfilecredentialProfile);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"}};// 署名を作成varsigner=newAWS4SignerForAuthorizationHeader{EndpointUri=uri,HttpMethod="GET",Service="execute-api",Region="ap-northeast-1"};varauthorization=signer.ComputeSignature(headers,"",// no query parametersAWS4SignerBase.EMPTY_BODY_SHA256,credentialProfile.Options.AccessKey,credentialProfile.Options.SecretKey);// リクエストヘッダに署名を追加headers.Add("Authorization",authorization);// リクエスト実行// HttpHelpers はUtilで定義HttpHelpers.InvokeHttpRequest(uri,"GET",headers,null);}staticvoidMain(string[]args){Run();}}}
uri
はAPI GatewayのAPIのURLを入れます。
実行
以下のコマンドで実行できます。
$dotnet run
ダウンロードしたサンプルコードのSigners
とUtil
にデバッグ用出力があるので、いろいろ表示されますが、最後にAPI Gatewayからのレスポンスが表示されます。