みなさん、こんにちわ。プロフェッショナルサービス事業部の小松です。
最近、AppFlowを利用する機会があったのですが、CloudFormationでConnectorProfileを作成する際にいくつか躓くことがあったのでコラムにまとめようと思います。

※今回はSalesforceコネクタを利用する前提です。

マネジメントコンソールからConnectorProfile作成

まずは、マネジメントコンソール経由でSalesforce用の接続を作成してみます。

OAuthグラントタイプとして、認証コードとJWTとを選べるようになっていますが、認証コードで進めていきます。

ユーザ名とパスワードを入力するとアクセス許可の確認画面が表示されます。

ここで許可を押すとSalesforceとの接続が確立されます。

詳細を見てみると、ConnectorProfileの設定がどのようになっているかを確認することができます。

この中で赤枠で囲ったところに、接続認証情報のArnと記載されていて、SecretsManagerのArnが記載されています。
Secertの名前としてはappflow!のprefixがついていて、AppFlowが管理する自動作成されたSecretになっています。

Secretの中を確認してみると、accessTokenとrefreshTokenが格納されていました。

CloudFormationでの ConnectorProfile作成

では、次にマネジメントコンソールでの結果を元にCloudFormationでConnectorProfileを作成していきます。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  SalesforceConnectorProfile:
    Type: AWS::AppFlow::ConnectorProfile
    Properties:
      ConnectorProfileName: "komatsu_test_connector_profile"
      ConnectorType: "Salesforce"
      ConnectionMode: "Public"
      ConnectorProfileConfig:
           ConnectorProfileCredentials:
                Salesforce:
                     AccessToken: "xxxxx" 
                     RefreshToken: "xxxxx"
           ConnectorProfileProperties:
                Salesforce:
                     InstanceUrl: "https://xxxxxxxx.my.salesforce.com"
                     isSandboxEnvironment: false
                     usePrivateLinkForMetadataAndAuthorization: false

上記のテンプレートにInstanceUrlとAccessToken/RefreshTokenを入れたうえで実行すると、マネジメントコンソールで作成されたConnectorProfileと同じものを作成することができました。
※AccessToken/RefreshTokenは事前に発行してあるものを入力する必要があります。ログインID/パスワードとは異なりますのでご注意ください。

このテンプレートを実行したタイミングで、テンプレート上に定義しているAccessTokenとRefreshTokenが、マネジメントコンソールで作成したときと同様にSecrertsManagerに作成されました。めでたしめでたし。

とするわけにはいかないわけで…CloudFormationのテンプレートにTokenをベタ書きするというのは完全にNG行為なので、やはりTokenはSecretsManagerやParameterStoreなどに保管する必要がありますよね。

試したことその1

テンプレート上のAccessToken/RefreshTokenにダミー値を埋め込んだ状態でテンプレートを実行し、作成されたSecretsManagerのシークレットの値を正しく書き換える。

結果:×
ダミー値の状態でデプロイをしようとすると、リソース作成のタイミングでInvalidCredentialsエラーにてCREATE_FAILEDとなりました。
作成のタイミングで認証テストを行っているようですね…。

試したことその2

事前に自分でSecretsManagerにシークレットを作成し、accessToken/refreshTokenを定義しておき、ClientCredentialsArnでシークレットを指定してみる。

結果:×
ClientCredentialsArnはOAuth認証のClient Credentials Grant にて利用するパラメータとなっているため、refreshTokenのフローで利用することがそもそもできません。

試したことその3

事前に自分でSecretsManagerにシークレットを作成し、accessToken/refreshTokenを定義しておき、CloudFormationテンプレートのAccessToken/RefreshTokenでシークレットの値を参照するように記述する。

結果:〇
自分で作成したシークレットから参照した値を、AppFlowが作成するマネージドなシークレットに格納したうえで正常にConnectorProfileを作成することができました

まとめると

最終的には以下のようなテンプレートでリソースの作成をすることができました。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  SalesforceConnectorProfile:
    Type: AWS::AppFlow::ConnectorProfile
    Properties:
      ConnectorProfileName: "komatsu_test_connector_profile"
      ConnectorType: "Salesforce"
      ConnectionMode: "Public"
      ConnectorProfileConfig:
           ConnectorProfileCredentials:
                Salesforce:
                     AccessToken:
                      "{{resolve:secretsmanager:/MySecret:SecretString:accessToken}}"
                     RefreshToken:
                      "{{resolve:secretsmanager:/MySecret:SecretString:refreshToken}}"
                     
           ConnectorProfileProperties:
                Salesforce:
                     InstanceUrl: "https://xxxxxx.my.salesforce.com"
                     isSandboxEnvironment: false
                     usePrivateLinkForMetadataAndAuthorization: false

事前にSecrertsManagerでシークレットを作成し、値を入れ込んでおかないとこのテンプレートは実行できないため、同じテンプレート内で利用するシークレットを作成することもできない点や、シークレットが勝手に作成されることもあり1つのシークレットで完結できない点がポイントでした。

サービスマネージドなシークレットについては以下にドキュメントがありました。AppFlowだけでなく他のサービスでもこのようなことはありそうです。すこしでも参考になれば幸いです。
https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/service-linked-secrets.html