AWS SDK for JavaScriptのAPIバージョンをロックする

2020.09.10

こんにちは、CX事業本部の若槻です。

AWS SDK for JavaScriptでは、AWSサービスごとにAPIのバージョンが管理されています。既定ではSDKは最新のAPIバージョンを使用するため、AWS SDKを使用するシステムがAPI側の変更による影響を受けないようにAPIバージョンをロックすることが推奨されています。

今回は、実際にAWS SDK for JavaScriptのAPIバージョンをロックしてみました。

やってみる

環境

% node -v
v12.14.0
% npm -v
6.13.4
% npm list --depth=0
├── @types/node@14.6.4
├── aws-sdk@2.747.0
└── typescript@4.0.2

使用可能なAPIバージョンの確認

まず、AWSサービスごとに使用可能なAPIバージョンの確認は次のページから可能です。

中央もしくは左サイドメニューのサービス一覧より、どのサービスがどのAPIバージョンに対応しているかが確認できます。

例えばLambdaクラスであれば現時点(2020年9月)で2015-03-312014-11-11に対応していることが分かります。 image.png

サービス名やAPIバージョン名がURLリンクになっているので開くと、そのAPIバージョンの仕様や使用例を確認できます。 image.png

APIバージョンのロック

実際にAWS SDK for JavaScriptのうちLambdaクラスのAPIバージョンをロックして使ってみます。

まず、APIバージョンを指定しない場合のLambdaサービスオブジェクトの設定を確認してみます。

% node
> const AWS = require('aws-sdk')
> const lambda = new AWS.Lambda();
> console.log(lambda.config);
Config {
  credentials: SharedIniFileCredentials {
    expired: false,
    expireTime: null,
    refreshCallbacks: [],
    accessKeyId: 'XXXXXXXXXXXXXXX',
    sessionToken: undefined,
    filename: undefined,
    profile: 'default',
    disableAssumeRole: true,
    preferStaticCredentials: false,
    tokenCodeFn: null,
    httpOptions: null
  },
  credentialProvider: CredentialProviderChain {
    providers: [
      [Function],
      [Function],
      [Function],
      [Function],
      [Function],
      [Function],
      [Function]
    ],
    resolveCallbacks: []
  },
  region: undefined,
  logger: null,
  apiVersions: {},
  apiVersion: null,
  endpoint: 'lambda.undefined.amazonaws.com',
  httpOptions: { timeout: 120000 },
  maxRetries: undefined,
  maxRedirects: 10,
  paramValidation: true,
  sslEnabled: true,
  s3ForcePathStyle: false,
  s3BucketEndpoint: false,
  s3DisableBodySigning: true,
  s3UsEast1RegionalEndpoint: 'legacy',
  s3UseArnRegion: undefined,
  computeChecksums: true,
  convertResponseTypes: true,
  correctClockSkew: false,
  customUserAgent: null,
  dynamoDbCrc32: true,
  systemClockOffset: 0,
  signatureVersion: 'v4',
  signatureCache: true,
  retryDelayOptions: {},
  useAccelerateEndpoint: false,
  clientSideMonitoring: false,
  endpointDiscoveryEnabled: undefined,
  endpointCacheSize: 1000,
  hostPrefixEnabled: true,
  stsRegionalEndpoints: 'legacy'
}

AWS.Config内でAPIバージョンを定義するパラメータはapiVersionapiVersionsの2つがあります。既定では未指定のためそれぞれapiVersions: {}apiVersion: nullとなっています。

APIバージョンを指定してロックしてみます。指定方法は次の2通りがあるのでそれぞれ試してみます。

  • サービスオブジェクト作成時にapiVersionパラメータを直接指定する
  • AWS.Configを使用してapiVersionsパラメータをグローバルに指定する

APIバージョンを直接指定する場合

サービスオブジェクト作成時にapiVersionパラメータを直接指定する場合は次のように定義します。

var lambda = new AWS.Lambda({apiVersion: '<apiVersion>'});

LambdaサービスオブジェクトでAPIバージョン2015-03-31を指定してみます。

% node
> const AWS = require('aws-sdk')
> const lambda = new AWS.Lambda({
...  apiVersion: '2015-03-31',
...  region: 'ap-northeast-1',
... })

apiVersionに指定されました。(apiVersionsの方は未指定のままです)

> console.log(lambda.config.apiVersion)
2015-03-31
> console.log(lambda.config.apiVersions)
{}

作成したlambdaオブジェクトのメソッドを実行した際のリクエストを見ると、APIバージョン2015-03-31のエンドポイントにアクセスされていることが分かります。

> lambda.listFunctions({}, function(_, data) {console.log(data)})
  //...
  httpRequest: HttpRequest {
    method: 'GET',
    path: '/2015-03-31/functions/',
  //...

APIバージョンをグローバルに指定する場合

AWS.Configを使用してapiVersionsパラメータをグローバルに指定する場合は次のように定義します。

AWS.config.apiVersions = {
  lambda: '<apiVersion>',
  // other service API versions
};

LambdaサービスオブジェクトでAPIバージョン2014-11-11を指定してみます。

% node
> const AWS = require('aws-sdk')
> AWS.config.apiVersions = {
...   dynamodb: '2011-12-05',
...   lambda: '2014-11-11',
... };
{ dynamodb: '2011-12-05', lambda: '2014-11-11' }
> const lambda = new AWS.Lambda({region: 'ap-northeast-1',})

apiVersionsに指定されました。(apiVersionの方は未指定のままです)

> console.log(lambda.config.apiVersion)
null
> console.log(lambda.config.apiVersions)
{ dynamodb: '2011-12-05', lambda: '2014-11-11' }

作成したlambdaオブジェクトのメソッドを実行した際のリクエストを見ると、APIバージョン2014-11-13のエンドポイントにアクセスされていることが分かります。

> lambda.listFunctions({}, function(_, data) {console.log(data)})
  //...
  httpRequest: HttpRequest {
    method: 'GET',
    path: '/2014-11-13/functions/',
  //...

その他

apiVersionapiVersionsに異なるバージョン値が指定されている場合

apiVersionapiVersionsに異なるバージョン値が指定されている場合の動作を確認してみます。

apiVersions2014-11-11apiVersion2015-03-31を指定してみます。

% node
> const AWS = require('aws-sdk')
> AWS.config.apiVersions = {
...   lambda: '2014-11-11',
... }
{ dynamodb: '2011-12-05', lambda: '2014-11-11' }
> const lambda = new AWS.Lambda({
...  apiVersion: '2015-03-31',
...  region: 'ap-northeast-1',
... })

指定されました。

> console.log(lambda.config.apiVersion)
2015-03-31
> console.log(lambda.config.apiVersions)
{ lambda: '2014-11-11' }

作成したlambdaオブジェクトのメソッドを実行した際のリクエストを見ると、apiVersionsに指定した2014-11-13の方のエンドポイントにアクセスが行われました。

> lambda.listFunctions({}, function(_, data) {console.log(data)})
  //...
  httpRequest: HttpRequest {
    method: 'GET',
    path: '/2014-11-13/functions/',
  //...

APIバージョンの指定を逆にした場合は、apiVersionsに指定した2015-03-31の方のエンドポイントにアクセスが行われました。使用されるAPIバージョンはapiVersionsパラメータの指定が優先する動作となるようです。

対応してないAPIバージョン値が指定されている場合

対応していないAPIバージョン値2100-01-01を指定したlambdaオブジェクトのメソッドを実行してみます。

% node
> const AWS = require('aws-sdk')
> AWS.config.apiVersions = {
...   lambda: '2100-01-01',
... }
{ lambda: '2100-01-01' }
> lambda.listFunctions({}, function(_, data) {console.log(data)})
  //...
  httpRequest: HttpRequest {
    method: 'GET',
    path: '/2015-03-31/functions/',
  //...

最新の2015-03-31が使用される動作となりました。対応していないAPIバージョン値が指定されている場合は最新のAPIバージョンが使用される動作となるようです。

おわりに

AWS SDK for JavaScriptのAPIバージョンをロックしてみました。

API側の仕様の更新は、特に本番構成だとリスクになってしまうのでAPIバージョンのロックは是非とも行っておきたいですね。

参考

以上