I have created a CloudFormation template which deploys an AWS Lambda function that is called by AWS Transfer to authenticate sftp users. The Lambda function returns a policy which AWS Transfer picks up and uses to lock down the sftp users permissions.
This policy includes the variables:
transfer:HomeFolder
transfer:HomeBucket
transfer:HomeDirectory
For documentation about what these variables do, see: Editing User Configuration - AWS Transfer for SFTP
When I try to deploy my CloudFormation template I get the following error:
An error occurred (ValidationError) when calling the CreateChangeSet operation: Template format error: Unresolved resource dependencies [transfer:HomeFolder, transfer:HomeBucket, transfer:HomeDirectory] in the Resources block of the template.
Is it possible to override the CloudFormation parameters for the policy variables: transfer:HomeFolder
, transfer:HomeBucket
, transfer:HomeDirectory
?
Here is the Lambda part of my CloudFormation template:
GetUserConfigLambda:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile:
Fn::Sub: |
'use strict';
const https = require('https');
exports.handler = (event, context, callback) => {
const data = JSON.stringify({
username: event.username,
password: event.password
});
const options = {
hostname: '${Url}',
path: '/api/v1.0/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
var policy = {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::${transfer:HomeBucket}"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"${transfer:HomeFolder}/*",
"${transfer:HomeFolder}"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObjectVersion",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::${transfer:HomeDirectory}*"
},
{
"Action":[
"s3:PutObject"
],
"Effect":"Deny",
"Resource":"arn:aws:s3:::${transfer:HomeDirectory}/*/"
}
]
}
var req = https.request(options, (res) => {
console.log("Status code: ", res.statusCode);
let data = '';
res.on('data', (chunk) => {
data += chunk;
}).on('end', () => {
let response = JSON.parse(data);
let lambdaResponse = {};
if('data' in response &&
'name' in response['data']) {
lambdaResponse = {
// Required.
Role: 'arn:aws:iam::669858054894:role/${UserRole}',
// JSON blob which further restrict this user's permissions.
Policy: JSON.stringify(policy),
// Home directory is a concatenation of home bucket and integration name.
HomeDirectory: "/${SftpS3Bucket}/" + response['data']['name'],
// Name of home bucket.
HomeBucket: "${SftpS3Bucket}"
}
}
callback(null, lambdaResponse);
});
}).on("error", (err) => {
console.log("Error: ", err.message);
callback(null, {});
});
req.end(data);
};