使用 Trusted Signers 和 Node.js SDK 调试 CloudFront 签名 URL
Debugging CloudFront Signed URLs using Trusted Signers and Node.js SDK
AWS 关于错误的详细信息少得令人恼火,我发现自己陷入困境,没有明确的前进道路。
我的 Node.js 应用程序中的代码似乎同时生成签名 URL 和签名 cookie,但都不允许我访问我的私有 CloudFront 分配上的资源。这是我得到的 403 响应,而不是:
<Error>
<Code>InvalidKey</Code>
<Message>Unknown Key</Message>
</Error>
我的解决方案分布在两个 AWS 账户中。
- 主账号
- 保存我的私有内容的 S3 存储桶
- 指向 S3 存储桶的私有 CloudFront 分配
- Public key 与 Elastic Beanstalk 中使用的私钥配对
- Route53 记录,包含所有发行版(主和成员)的自定义子域 & API
- privatedistro.mydomain.com
- reactapp.mydomain.com
- api.mydomain.com
- 会员帐户
- Node.js-based API 运行 在 Elastic Beanstalk 上(这会在登录时签名和 returns cookies)
- S3 bucket 持有前端 React 应用程序
- Public CloudFront 分发服务 React 应用程序
- 我尝试在此处向 CloudFront 添加 public 密钥并也使用其 ID
使用the Elastic Beanstalk console将密钥对ID和私钥配置为环境变量。这是我的代码(执行时没有错误):
const cloudFront =
sails.config.custom.cloudfront.keyPairId &&
sails.config.custom.cloudfront.privateKey &&
new AWS.CloudFront.Signer(
sails.config.custom.cloudfront.keyPairId,
sails.config.custom.cloudfront.privateKey.replace(/\n/g, '\n') // environment variables passed through Elastic Beanstalk get altered
);
// Set Cookies after successful verification
const policy = JSON.stringify({
Statement: [
{
Resource: 'https://privatedistro.mydomain.com/*',
Condition: {
DateLessThan: {
'AWS:EpochTime':
Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // Current Time in UTC + time in seconds, (1 day)
}
}
}
]
});
cookie = cloudFront.getSignedCookie({ policy });
this.res.cookie(
'CloudFront-Key-Pair-Id',
cookie['CloudFront-Key-Pair-Id'],
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
this.res.cookie(
'CloudFront-Expires',
Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24, // Current Time in UTC + time in seconds, (60 * 60 * 24 = 1 day)
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
this.res.cookie(
'CloudFront-Signature',
cookie['CloudFront-Signature'],
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
返回的 cookie 如下所示:
- CloudFront-过期=1593487645
- CloudFront-Key-Pair-Id=K48HZXSAAM76P(不是EC2/IAM:key-0847abcde123456)
- CloudFront-Signature=[以 __ 结尾的 345 个字符的字符串]
在我的私人发行版的默认缓存行为设置中,我为限制查看者访问选择了是 ,将自己和选定的账户都选择为 Trusted Signers,并在 AWS Account Numbers 中输入成员账户的 13 位数字] 场地。在我打开 Restrict Viewer Access 之前,一切都很好,所以我认为 CloudFront 设置的其他部分没有问题。
有什么地方出错了吗?
您使用的密钥看起来不正确,要使用 CloudFront 签名 URL,您需要使用 CloudFront 密钥对,而不是下面文档中提到的 EC2 密钥对:
Generate Signed URL CloudFront
CloudFront 密钥 ID 看起来更像是 IAM 的访问密钥。
AWS 关于错误的详细信息少得令人恼火,我发现自己陷入困境,没有明确的前进道路。
我的 Node.js 应用程序中的代码似乎同时生成签名 URL 和签名 cookie,但都不允许我访问我的私有 CloudFront 分配上的资源。这是我得到的 403 响应,而不是:
<Error>
<Code>InvalidKey</Code>
<Message>Unknown Key</Message>
</Error>
我的解决方案分布在两个 AWS 账户中。
- 主账号
- 保存我的私有内容的 S3 存储桶
- 指向 S3 存储桶的私有 CloudFront 分配
- Public key 与 Elastic Beanstalk 中使用的私钥配对
- Route53 记录,包含所有发行版(主和成员)的自定义子域 & API
- privatedistro.mydomain.com
- reactapp.mydomain.com
- api.mydomain.com
- 会员帐户
- Node.js-based API 运行 在 Elastic Beanstalk 上(这会在登录时签名和 returns cookies)
- S3 bucket 持有前端 React 应用程序
- Public CloudFront 分发服务 React 应用程序
- 我尝试在此处向 CloudFront 添加 public 密钥并也使用其 ID
使用the Elastic Beanstalk console将密钥对ID和私钥配置为环境变量。这是我的代码(执行时没有错误):
const cloudFront =
sails.config.custom.cloudfront.keyPairId &&
sails.config.custom.cloudfront.privateKey &&
new AWS.CloudFront.Signer(
sails.config.custom.cloudfront.keyPairId,
sails.config.custom.cloudfront.privateKey.replace(/\n/g, '\n') // environment variables passed through Elastic Beanstalk get altered
);
// Set Cookies after successful verification
const policy = JSON.stringify({
Statement: [
{
Resource: 'https://privatedistro.mydomain.com/*',
Condition: {
DateLessThan: {
'AWS:EpochTime':
Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // Current Time in UTC + time in seconds, (1 day)
}
}
}
]
});
cookie = cloudFront.getSignedCookie({ policy });
this.res.cookie(
'CloudFront-Key-Pair-Id',
cookie['CloudFront-Key-Pair-Id'],
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
this.res.cookie(
'CloudFront-Expires',
Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24, // Current Time in UTC + time in seconds, (60 * 60 * 24 = 1 day)
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
this.res.cookie(
'CloudFront-Signature',
cookie['CloudFront-Signature'],
{
domain: '.mydomain.com',
path: '/',
httpOnly: true
}
);
返回的 cookie 如下所示:
- CloudFront-过期=1593487645
- CloudFront-Key-Pair-Id=K48HZXSAAM76P(不是EC2/IAM:key-0847abcde123456)
- CloudFront-Signature=[以 __ 结尾的 345 个字符的字符串]
在我的私人发行版的默认缓存行为设置中,我为限制查看者访问选择了是 ,将自己和选定的账户都选择为 Trusted Signers,并在 AWS Account Numbers 中输入成员账户的 13 位数字] 场地。在我打开 Restrict Viewer Access 之前,一切都很好,所以我认为 CloudFront 设置的其他部分没有问题。
有什么地方出错了吗?
您使用的密钥看起来不正确,要使用 CloudFront 签名 URL,您需要使用 CloudFront 密钥对,而不是下面文档中提到的 EC2 密钥对:
Generate Signed URL CloudFront
CloudFront 密钥 ID 看起来更像是 IAM 的访问密钥。