Amazon RDS for OracleのS3統合(S3_INTEGRATION)の通信はどこを通っているのか

2024.06.19

初めに

Amazon RDS for OracleではS3統合(S3_INTEGRATION)を利用することでS3バケットと通信をしデータをやりとりすることが可能です。

設定も非常に手軽でオプショングループでS3_INTEGRATIONを有効化、IAMロールもしくはバケットポリシーに必要な権限を割り当てた上でS3統合で利用するIAMロールをRDSに割り当てるだけです。

そう、たったこれだけで良いのです。例えインスタンスがプライベートサブネット上かつNAT GatewayやVPCエンドポイントが用意されていなくともS3バケットとやりとりができます。

特にVPCエンドポイントが不要な点は先のURLに明記されています。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/oracle-s3-integration.html
DB インスタンスが Amazon S3 バケットにアクセスできる必要があります。DB インスタンスで使用される Amazon VPC は Amazon S3 エンドポイントへのアクセスを提供する必要はありません。

...いったいどうやってAmazon S3と通信しているのでしょうか。

ログを見てみる

以下の2つの情報を確認してみます

  • VPCフローログにおけるRDSインスタンスのIPをソースとする宛先443番ポートの通信
    • 少なくともS3にアップロードするためにどこかとは通信してるはず
    • Amazon S3宛であればS3のAPI(HTTPS)を呼んでいるはず
  • 宛先S3バケットで発生したデータイベント
    • 終端となる部分のログを見ることで少なくともその直前の通信は確認可能

いずれも別途取得の設定が必要ですが具体的な設定方法はここではは割愛します。データイベントに関するログははCloudTrailはデフォルトでは取得しないため忘れがちではあるので注意しましょう。

データアップロードは以下を参考に実施しました(Oracle DB何もわからない...)。

VPCフローログ

S3に通信しているのであればAWS APIはHTTPSによる通信となるためひとまずそちらで絞り込みをかけてみましょう(+大体の実行時刻で絞り込みかけてます)。

RDSのIPは192.168.2.30、サブネットの指定的に192.168.2.0/24(もしくはもう片側のAZの192.168.1.0/24)に所属するはずなのでこの辺りから出ているはずなのですが..見当たりません。
他に見えているIPも検証時に起動しているEC2のものとなります。

% dig database-1.xxxxxx.ap-northeast-1.rds.amazonaws.com +short
192.168.2.30

もう少し広げて該当VPC全体(192.168.0.0/16)をソースとして調べてみましたが何か別のもので出ているということもなく、RDSからの通信はSQLを実行するためのEC2間との接続のみとなりました。

つまりのところRDS上のストレージのデータの取り出しはVPC内から行われていないようです。

データイベント

アップロードした際のデータイベントを抽出したところ以下のようなイベントが取得できました。

    {
      "eventVersion": "1.09",
      "userIdentity": {
        "type": "AssumedRole",
        "principalId": "xxxxxxxxx",
        "arn": "arn:aws:sts::xxxxxxx:assumed-role/rds-xxxxxxx-role/dbi-role-mem-id-30659407",
        "accountId": "xxxxxxxxx",
        "accessKeyId": "xxxxxxxxxxxx",
        "sessionContext": {
          "sessionIssuer": {
            "type": "Role",
            "principalId": "xxxxxx",
            "arn": "arn:aws:iam::xxxxxx:role/xxxxxx-role",
            "accountId": "xxxxxxxxx",
            "userName": "rds-xxxxxxxxx-role"
          },
          "attributes": {
            "creationDate": "2024-06-13T06:48:47Z",
            "mfaAuthenticated": "false"
          }
        },
        "invokedBy": "rds.amazonaws.com"
      },
      "eventTime": "2024-06-13T06:54:59Z",
      "eventSource": "s3.amazonaws.com",
      "eventName": "PutObject",
      "awsRegion": "ap-northeast-1",
      "sourceIPAddress": "rds.amazonaws.com",
      "userAgent": "rds.amazonaws.com",
      "requestParameters": {
        "bucketName": "xxxxxxxx",
        "Host": "xxxxxxt.s3.ap-northeast-1.amazonaws.com",
        "key": "dbfiles/exp.log"
      },
      "responseElements": {
        "x-amz-server-side-encryption": "AES256"
      },
      "additionalEventData": {
        "SignatureVersion": "SigV4",
        "CipherSuite": "TLS_AES_128_GCM_SHA256",
        "bytesTransferredIn": 80,
        "SSEApplied": "Default_SSE_S3",
        "AuthenticationMethod": "AuthHeader",
        "x-amz-id-2": "xxxxxxx==",
        "bytesTransferredOut": 0
      },
      "requestID": "xxxxxx",
      "eventID": "xxxxxx",
      "readOnly": false,
      "resources": [
        {
          "type": "AWS::S3::Object",
          "ARN": "arn:aws:s3:::xxxxxx/dbfiles/exp.log"
        },
        {
          "accountId": "xxxxxx",
          "type": "AWS::S3::Bucket",
          "ARN": "arn:aws:s3:::xxxxxx"
        }
      ],
      "eventType": "AwsApiCall",
      "managementEvent": false,
      "recipientAccountId": "xxxxxx",
      "eventCategory": "Data"
    },

invokedByの値がrds.amazonaws.comなので別のサービスを経由しているということもなくあくまでRDSが実行したという形になりそうです。

https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/how-cloudtrail-works.html
CloudTrail ユーザーが直接行ったアクション、またはユーザーに代わってサービスが行ったアクションをキャプチャします。 AWS たとえば、 AWS CloudFormation CreateStack呼び出しによって、Amazon EC2、Amazon RDS、Amazon EBS、またはテンプレートで要求されるその他のサービスへの追加の AWS CloudFormation API 呼び出しが発生する可能性があります。この動作は正常であり、想定されています。 AWS アクションがサービスによって実行されたかどうかは、invokedbyイベントのフィールドで確認できます。

結局のところ

詳細については公開情報がなく曖昧な情報となっているのですが、VPC外部の通信ではあるものの(VPCフローログに出力なし)、AWSサービス間の通信で完結している(S3のデータイベントより)と見ることができます。

冷静に考えるとRDSのログのCloudWatch Logsへの出力も同様にVPCエンドポイントやインターネットへの経路がなくとも通信できるため、推測とはなりますが処理の起点自体はインスタンスの中とはなるものの取り出しの仕組みについてはこれと似たようなところがあるのかもしれません。

https://aws.amazon.com/jp/vpc/faqs/?nc1=h_ls
2 つのインスタンスがパブリック IP アドレスを使用して通信する場合、またはインスタンスがパブリックな AWS のサービスエンドポイントと通信する場合、トラフィックはインターネットを経由しますか? いいえ。パブリック IP アドレスを使用する場合、AWS でホストされているインスタンスとサービス間のすべての通信は AWS のプライベートネットワークを使用します。AWS ネットワークから発信され、AWS ネットワーク上の送信先を持つパケットは、AWS 中国リージョンとの間のトラフィックを除いて、AWS グローバルネットワークにとどまります。

さらに、データセンターとリージョンを相互接続する AWS グローバルネットワークを流れるすべてのデータは、安全性が保証された施設を離れる前に、物理レイヤーで自動的に暗号化されます。すべての VPC クロスリージョンピアリングトラフィックや、カスタマーまたはサービス間のトランスポート層セキュリティ (TLS) 接続などといった追加の暗号化レイヤーもあります。

いずれにしてもAWSでホストされているシステムに関しては仮にパブリックIPが付与されていたとしてもAWS管理ネットワークを通る仕様となっておりますのでとなっており、RDS・S3間のサービス間通信となる今回も同様に少なくともインターネットを通らずAWS管理ネットワークで完結する形となります。

またS3への通信自体に関してもAWS APIで実行されていますが("eventType": "AwsApiCall")、AWS APIは現状最低TLSv1.2以上のHTTPS通信が必須要件となっている関係で通信の暗号化強度も一定は保証されております。

終わりに

ユーザ側から見れるログ部分としては情報が少なく検証としてはやや消化不良感のあるような形にはなってしまいましたが、VPC内部にあるリソースではあるものの一種のマネージドサービス(機能)と捉えるとユーザの関与する部分ではないものですし少し納得のいくような感じはします。

経路としてはインターネットに出るようなことはなく、一定以上の暗号強度もは保証されているので基本的には安心してご利用いただいて良いところとはなりそうです(求められる要件は環境により異なるため必ずではない)。

どうしても個人情報が直接含まれる部分のでもう少し経路を明確にしつつでも外部ストレージ間とインポート・エクスポートを...となると現時点では19c限定とはなりますがEFS統合を一つの選択肢として考えても良さそうです。