tseki blog

my study room

curl で AWS の SigV4 署名ができるようになったらしいのでやってみた

きっかけ

Tori さんのツイートを見て試してみたくなったのでやってみます。
HTTP API に IAM 認証を設定し、curl でアクセスしてみます。

HTTP API の作成

HTTP API を作成します。

# HTTP API の作成
$ aws apigatewayv2 create-api \
    --name sigv4-test-api \
    --protocol-type HTTP
{
    "ApiEndpoint": "https://jdbexbtvta.execute-api.ap-northeast-1.amazonaws.com",
    "ApiId": "jdbexbtvta",
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "CreatedDate": "2021-09-08T18:33:27+00:00",
    "DisableExecuteApiEndpoint": false,
    "Name": "sigv4-test-api",
    "ProtocolType": "HTTP",
    "RouteSelectionExpression": "$request.method $request.path"
}

# 統合の作成
# jsonplaceholder の Web API を叩きます
$ aws apigatewayv2 create-integration \
    --api-id jdbexbtvta \
    --integration-type HTTP_PROXY \
    --integration-method GET \
    --integration-uri "https://jsonplaceholder.typicode.com/todos/1" \
    --payload-format-version "1.0"
{
    "ConnectionType": "INTERNET",
    "IntegrationId": "06cdxab",
    "IntegrationMethod": "GET",
    "IntegrationType": "HTTP_PROXY",
    "IntegrationUri": "https://jsonplaceholder.typicode.com/todos/1",
    "PayloadFormatVersion": "1.0",
    "TimeoutInMillis": 30000
}

# ルートの作成
$ aws apigatewayv2 create-route \
    --api-id jdbexbtvta \
    --route-key "ANY /" \
    --authorization-type AWS_IAM \
    --target "integrations/06cdxab"
{
    "ApiKeyRequired": false,
    "AuthorizationType": "AWS_IAM",
    "RouteId": "v4slx93",
    "RouteKey": "ANY /",
    "Target": "integrations/06cdxab"
}

# ステージへデプロイ
$ aws apigatewayv2 create-stage \
    --api-id jdbexbtvta \
    --stage-name '$default' \
    --auto-deploy
{
    "AutoDeploy": true,
    "CreatedDate": "2021-09-08T18:50:53+00:00",
    "DefaultRouteSettings": {
        "DetailedMetricsEnabled": false
    },
    "LastUpdatedDate": "2021-09-08T18:50:53+00:00",
    "RouteSettings": {},
    "StageName": "$default",
    "StageVariables": {},
    "Tags": {}
}

試しに、curl で作成した API を呼び出してみます。

$ curl -i -XGET https://jdbexbtvta.execute-api.ap-northeast-1.amazonaws.com
HTTP/2 403
date: Wed, 08 Sep 2021 18:58:05 GMT
content-type: application/json
content-length: 23
apigw-requestid: FW4lmg-ntjMEP0w=

{"message":"Forbidden"}

ステータスコードは 403 となり、IAM 認証が有効になっています。

curl でアクセスする

curl 7.75.0 での新機能とのことでしたので、
こちらのコンテナイメージを使用することにしました。

https://hub.docker.com/r/curlimages/curl

まずは sigV4 署名を行わずにリクエストを送信してみます。

$ docker run --rm curlimages/curl \
>     -si -XGET https://jdbexbtvta.execute-api.ap-northeast-1.amazonaws.com/
HTTP/2 403
date: Wed, 08 Sep 2021 19:11:53 GMT
content-type: application/json
content-length: 23
apigw-requestid: FW6nAhZhtjMENVw=

{"message":"Forbidden"}

先ほどと同じレスポンスが返ることが確認できました。

次にsigV4 署名を行ってリクエストを送信してみます。

$ docker run --rm curlimages/curl \
>     --aws-sigv4 "aws:amz:ap-northeast-1:execute-api" \
>     --user "$(aws configure get aws_access_key_id):$(aws configure get aws_secret_access_key)" \
>     -si -XGET https://jdbexbtvta.execute-api.ap-northeast-1.amazonaws.com/
HTTP/2 200
date: Wed, 08 Sep 2021 19:14:12 GMT
content-type: application/json; charset=utf-8
content-length: 83
server: cloudflare
apigw-requestid: FW68wjY9NjMEJvg=
x-powered-by: Express
x-ratelimit-limit: 1000
x-ratelimit-remaining: 999
x-ratelimit-reset: 1631127178
vary: Origin, Accept-Encoding
access-control-allow-credentials: true
cache-control: max-age=43200
pragma: no-cache
expires: -1
x-content-type-options: nosniff
etag: W/"53-hfEnumeNh6YirfjyjaujcOPPT+s"
via: 1.1 vegur
cf-cache-status: HIT
age: 1331
accept-ranges: bytes
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=sbLIYFBbtzTVHKMSDkcB%2FC6EOWYc8w20q4PL6K3YzF25RmCUWrPHBDZpkxUemzCjJgyARLlp3346fLDdnTmGYrIydEsNFhwuvALEEF6h2txISOpUYIf3S9Dabvg2Vur9AC506VvDFsqTCMqj2VOG"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
cf-ray: 68ba7f9d8a472061-NRT
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400, h3-28=":443"; ma=86400, h3-27=":443"; ma=86400

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

jsonplaceholder の Web API からレスポンスが返りました。

--aws-sigv4 オプションについて

こちらのページに説明が記載されていました。

https://curl.se/libcurl/c/CURLOPT_AWS_SIGV4.html

provider1, provider2 (="aws:amz") は、
AWS sigV4 署名をするために必要な定数みたいですね。