Closed mcrowley-axcess closed 6 months ago
This has been fixed in release v0.7.0. You can upgrade with pip install -U cf2tf
Here is your converted template:
data "aws_caller_identity" "current" {}
data "aws_partition" "current" {}
data "aws_region" "current" {}
locals {
CreateServer = var.create_server == "true"
NotCreateServer = !local.CreateServer
SecretsManagerRegionProvided = !var.secrets_manager_region == ""
TransferVPCEndpoint = var.transfer_endpoint_type == "VPC"
stack_id = uuidv5("dns", "testing")
}
variable create_server {
description = "Whether this stack creates an AWS Transfer endpoint or not. If the endpoint is created as part of the stack, the custom identity provider is automatically associated with it."
type = string
default = "true"
}
variable secrets_manager_region {
description = "(Optional) The region the secrets are stored in. If this value is not provided, the region this stack is deployed in will be used. Use this field if you are deploying this stack in a region where SecretsManager is not available."
type = string
}
variable transfer_endpoint_type {
description = "Select PUBLIC if you want a public facing AWS Transfer endpoint or VPC if you want a VPC based endpoint. Note that only SFTP and FTPS are supported on public endpoints."
type = string
default = "PUBLIC"
}
variable transfer_subnet_i_ds {
description = "Required if launching a VPC endpoint. Comma-separated list of subnets that you would like the AWS Transfer endpoint to be provisioned into."
type = string
}
variable transfer_vpcid {
description = "Required if launching a VPC endpoint. The VPC ID that you would like the AWS Transfer endpoint to be provisioned into."
type = string
}
resource "aws_transfer_server" "transfer_server" {
count = local.CreateServer ? 1 : 0
endpoint_type = var.transfer_endpoint_type
endpoint_details {
// CF Property(InvocationRole) = aws_iam_role.transfer_identity_provider_role.arn
// CF Property(Url) = join("", ["https://", aws_api_gateway_rest_api.custom_identity_provider_api.arn, ".execute-api.", data.aws_region.current.name, ".", data.aws_partition.current.dns_suffix, "/", aws_api_gateway_stage.api_stage.arn])
}
identity_provider_type = "API_GATEWAY"
logging_role = aws_iam_role.transfer_cw_logging_role.arn
}
resource "aws_iam_role" "transfer_cw_logging_role" {
count = local.CreateServer ? 1 : 0
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = [
"transfer.amazonaws.com"
]
}
Action = [
"sts:AssumeRole"
]
}
]
}
managed_policy_arns = [
"arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSTransferLoggingAccess"
]
}
resource "aws_api_gateway_rest_api" "custom_identity_provider_api" {
name = "Transfer Family Secrets Manager Integration API"
description = "API used for Transfer Family to access user information in Secrets Manager"
fail_on_warnings = true
endpoint_configuration {
types = [
"REGIONAL"
]
}
}
resource "aws_iam_role" "lambda_execution_role" {
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = [
"lambda.amazonaws.com"
]
}
Action = [
"sts:AssumeRole"
]
}
]
}
managed_policy_arns = [
"arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
force_detach_policies = [
{
PolicyName = "LambdaSecretsPolicy"
PolicyDocument = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"secretsmanager:GetSecretValue"
]
Resource = "arn:${data.aws_partition.current.partition}:secretsmanager:${local.SecretsManagerRegionProvided ? var.secrets_manager_region : data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:secret:aws/transfer/*"
}
]
}
}
]
}
resource "aws_iam_role" "api_cloud_watch_logs_role" {
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = [
"apigateway.amazonaws.com"
]
}
Action = [
"sts:AssumeRole"
]
}
]
}
force_detach_policies = [
{
PolicyName = "ApiGatewayLogsPolicy"
PolicyDocument = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:DescribeQueries",
"logs:FilterLogEvents",
"logs:GetLogEvents",
"logs:GetLogGroupFields",
"logs:GetLogRecord",
"logs:GetQueryResults",
"logs:PutLogEvents",
"logs:StartQuery",
"logs:StopQuery"
]
Resource = "*"
}
]
}
}
]
}
resource "aws_api_gateway_account" "api_logging_account" {
cloudwatch_role_arn = aws_iam_role.api_cloud_watch_logs_role.arn
}
resource "aws_api_gateway_stage" "api_stage" {
deployment_id = aws_api_gateway_deployment.api_deployment202008.id
// CF Property(MethodSettings) = [
// {
// DataTraceEnabled = false
// HttpMethod = "*"
// LoggingLevel = "INFO"
// ResourcePath = "/*"
// }
// ]
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
stage_name = "prod"
}
resource "aws_api_gateway_deployment" "api_deployment202008" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
}
resource "aws_iam_role" "transfer_identity_provider_role" {
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "transfer.amazonaws.com"
}
Action = [
"sts:AssumeRole"
]
}
]
}
force_detach_policies = [
{
PolicyName = "TransferCanInvokeThisApi"
PolicyDocument = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"execute-api:Invoke"
]
Resource = "arn:${data.aws_partition.current.partition}:execute-api:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:${aws_api_gateway_rest_api.custom_identity_provider_api.arn}/prod/GET/*"
}
]
}
},
{
PolicyName = "TransferCanReadThisApi"
PolicyDocument = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"apigateway:GET"
]
Resource = "*"
}
]
}
}
]
}
resource "aws_emrserverless_application" "get_user_config_lambda" {
// CF Property(CodeUri) = "src/"
// CF Property(Description) = "A function to lookup and return user data from AWS Secrets Manager."
// CF Property(Handler) = "index.lambda_handler"
// CF Property(Role) = aws_iam_role.lambda_execution_role.arn
// CF Property(Runtime) = "python3.11"
// CF Property(Environment) = {
// Variables = {
// SecretsManagerRegion = local.SecretsManagerRegionProvided ? var.secrets_manager_region : data.aws_region.current.name
// }
// }
}
resource "aws_lambda_permission" "get_user_config_lambda_permission" {
action = "lambda:invokeFunction"
function_name = aws_emrserverless_application.get_user_config_lambda.arn
principal = "apigateway.amazonaws.com"
source_arn = "arn:${data.aws_partition.current.partition}:execute-api:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:${aws_api_gateway_rest_api.custom_identity_provider_api.arn}/*"
}
resource "aws_api_gateway_resource" "servers_resource" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
parent_id = aws_api_gateway_rest_api.custom_identity_provider_api.root_resource_id
path_part = "servers"
}
resource "aws_api_gateway_resource" "server_id_resource" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
parent_id = aws_api_gateway_resource.servers_resource.id
path_part = "{serverId}"
}
resource "aws_api_gateway_resource" "users_resource" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
parent_id = aws_api_gateway_resource.server_id_resource.id
path_part = "users"
}
resource "aws_api_gateway_resource" "user_name_resource" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
parent_id = aws_api_gateway_resource.users_resource.id
path_part = "{username}"
}
resource "aws_api_gateway_resource" "get_user_config_resource" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
parent_id = aws_api_gateway_resource.user_name_resource.id
path_part = "config"
}
resource "aws_api_gateway_method" "get_user_config_request" {
authorization = "AWS_IAM"
http_method = "GET"
// CF Property(Integration) = {
// Type = "AWS"
// IntegrationHttpMethod = "POST"
// Uri = join("", ["arn:", data.aws_partition.current.partition, ":apigateway:", data.aws_region.current.name, ":lambda:path/2015-03-31/functions/", aws_emrserverless_application.get_user_config_lambda.arn, "/invocations"])
// IntegrationResponses = [
// {
// StatusCode = 200
// }
// ]
// RequestTemplates = {
// application/json = "{
// "username": "$util.urlDecode($input.params('username'))",
// "password": "$util.escapeJavaScript($input.params('Password')).replaceAll("\\'","'")",
// "protocol": "$input.params('protocol')",
// "serverId": "$input.params('serverId')",
// "sourceIp": "$input.params('sourceIp')"
// }
// "
// }
// }
request_parameters = {
method.request.header.Password = false
}
resource_id = aws_api_gateway_resource.get_user_config_resource.id
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
// CF Property(MethodResponses) = [
// {
// StatusCode = 200
// ResponseModels = {
// application/json = "UserConfigResponseModel"
// }
// }
// ]
}
resource "aws_api_gateway_model" "get_user_config_response_model" {
rest_api_id = aws_api_gateway_rest_api.custom_identity_provider_api.arn
content_type = "application/json"
description = "API response for GetUserConfig"
name = "UserConfigResponseModel"
schema = {
$schema = "http://json-schema.org/draft-04/schema#"
title = "UserUserConfig"
type = "object"
properties = {
HomeDirectory = {
type = "string"
}
Role = {
type = "string"
}
Policy = {
type = "string"
}
PublicKeys = {
type = "array"
items = {
type = "string"
}
}
}
}
}
output "server_id" {
value = aws_transfer_server.transfer_server.id
}
output "stack_arn" {
value = local.stack_id
}
output "transfer_identity_provider_url" {
description = "URL to pass to AWS Transfer CreateServer call as part of optional IdentityProviderDetails"
value = join("", ["https://", aws_api_gateway_rest_api.custom_identity_provider_api.arn, ".execute-api.", data.aws_region.current.name, ".", data.aws_partition.current.dns_suffix, "/", aws_api_gateway_stage.api_stage.arn])
}
output "transfer_identity_provider_invocation_role" {
description = "IAM Role to pass to AWS Transfer CreateServer call as part of optional IdentityProviderDetails"
value = aws_iam_role.transfer_identity_provider_role.arn
}
Thank you! :) I manually rewrote the cf to tf for this one, but I will definitely keep this in my back pocket for the next one.
Template: https://s3.amazonaws.com/aws-transfer-resources/custom-idp-templates/aws-transfer-custom-idp-secrets-manager-sourceip-protocol-support-apig.zip
Environment: Python 3.10.12
Traceback (most recent call last): File "/home/localuser1/.local/bin/cf2tf", line 8, in
sys.exit(cli())
File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in call
return self.main(args, kwargs)
File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, ctx.params)
File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
return __callback(args, **kwargs)
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/app.py", line 44, in cli
config = TemplateConverter(tmpl_path.stem, cf_template, search_manger).convert()
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 97, in convert
tf_resources = self.convert_to_tf(self.manifest)
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 144, in convert_to_tf
tf_resources.extend(converter(resources))
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 344, in convert_resources
resolved_values = self.resolve_values(
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 176, in resolve_values
data[key] = self.resolve_values(
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 206, in resolve_values
value = self.resolve_values(
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 217, in resolve_values
resolved_list_values = [
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 218, in
self.resolve_values(item, allowed_func, prev_func) for item in data
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 176, in resolve_values
data[key] = self.resolve_values(
File "/home/localuser1/.local/lib/python3.10/site-packages/cf2tf/convert.py", line 204, in resolve_values
raise ValueError(f"{key} not allowed to be nested in {prev_func}.")
ValueError: Fn::Split not allowed to be nested in None.