Cloudformation Combine Sub and Join to get a list - amazon-web-services

I am trying to create a list in my Cloudformation template.
Inspired by this post: Sub and Join on Comma-Delimited List I have gotten to this idea but it doesnt work as the !Sub line has to be a string...
Error is:
Error: Failed to create changeset for the stack: STACKNAME, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined.
Any thoughts? Is this even possible?
Accounts:
Type: CommaDelimitedList
Default: Acc1,Acc2,Acc3
pRedshiftUser:
Type: String
Default: arn:redshiftperson
...
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Split
- ','
- !Sub
- '${pRedshiftUser}/${user}'
- user: !Join
- !Sub ',${pRedshiftUser}/'
- Ref: "Accounts"
The idea being I'm trying to create this as the output:
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId:
- arn:redshiftperson/user1
- arn:redshiftperson/user2

Sadly you can't do this. Delimiter in Join must be explicit string.
For the Fn::Join delimiter, you can't use any functions. You must specify a string value.
So you can't use Sub in Delimiter.
The only way would to create a custom macro or a custom resource in CloudFormation. In both ways, you would need to develop a lambda function to handle the transformation of your data to desired format.

Related

Cloudformation: Create array of log ARNs from comma delimited list of log names

I have parameter LogNames - comma delimited list of log names:
LogNames:
Type: String
Default: >-
/aws/my-custom-log-1,/aws/my-custom-log-1
I want to use it in the IAM policy definition - Resource field:
Resource:
<array of allowed log ARNs created from LogNames parameter>
Any idea how to use functions e.g. Split, Join, Sub, ... to generate correct array of log ARNs? Single log ARN have syntax:
- !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${LogName}:*'
Its not possible without a macro or a custom resource. The only way to do it without these, is to hardcode your region and accountid and use combo of Split, Join, Sub:
Parameters:
LogNames:
Type: CommaDelimitedList
Default: >-
/aws/my-custom-log-1,/aws/my-custom-log-2,/aws/my-custom-log-3
Resource:
!Split:
- ","
- !Sub
- "arn:aws:logs:us-east-1:234234234234:log-group:${logname}"
- logname: !Join
- ",arn:aws:logs:us-east-1:234234234234:log-group:"
- !Ref LogNames

Template validation failed when using SAM syntax instead of CloudFormation syntax for step function

I have the following step function in my AWS SAM template, it was defined using the syntax in the documentation. I'm using intrinsic functions to get some pseudoparameters but something is going wrong with them.
SfdcOrderEventsStepFunction:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionSubstitutions:
Region: !Ref "AWS::Region"
AccountId: !Ref "AWS::AccountId"
EventBusPublishTarget: "order-events"
DefinitionUri: sfn-definition.asl.yml
Events:
EventBridgeEvent:
Type: EventBridgeRule
Properties:
EventBusName: sfdc-events
Pattern:
# TODO: Update pattern when the salesforce service is ready
source:
- prefix: salesforce.com
detail-type:
- Order
detail:
Payload__c:
attributes:
type:
- order
InputPath: $.detail
Name: sfdc-order-events
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/stepfunction_execution_role'
Tracing:
Enabled: true
when I try to deploy it shows me the following error:
Resource template validation failed for resource
SfdcOrderEventsStepFunction as the template has invalid properties.
Please refer to the resource documentation to fix the template.
Properties validation failed for resource SfdcOrderEventsStepFunction
with message:
#/De finitionSubstitutions/ AccountId: 2 subschemas matched instead of one
#/DefinitionSubstitutions/AccountId: expected type: Boolean, found: String
At the end it deploys without problems. The step function and all of its components run as expected and without errors, but I wanted to know if there if something I can do to fix the template.

Use Gett Function inside Sub in cloudformation

I am trying to get the value of my RDS endpoint and use it as a value in a secret-manager I am creating.
I know how to get the endpoint in the outputs:
DB1ConnectionString:
Condition: Launch1Engine
Description: The First db Connection String
Value: {"Fn::GetAtt": ["RDSDBInstance1","Endpoint.Address"]}
But I can not use output inside my current stack, so I want to use the same way I got the Endpoint and use it in the secret manager.
This is what I tried:
DBStringSecret1:
Condition: Launch1Engine
Type: 'AWS::SecretsManager::Secret'
Properties:
Name: !Ref DBStringSecret1Name
SecretString: !Sub '{"repository":!GetAtt RDSDBInstance1.Endpoint.Address,"username":"MasterUsername","password":"${SafeMineDBPassword1}"}'
But I get a literal string as the "repository value and not the RDS endpoint,
Is there a way to use the "!GetAtt" inside the "!Sub"?
Or am I doing it all wrong and I can define a new parameter that will build the value I want using Join?
!Sub 'jdbc://{!GetAtt RDSDBInstance1.Endpoint.Address}:3306/<SCHEMA>?'
Expected result:
jdbc://endpoint:3306/?
You have to use join function in this case:
SecretString: !Join
- ''
- - '{"repository": "'
- !GetAtt RDSDBInstance1.Endpoint.Address
- '","username":"MasterUsername","password":"'
- !Ref SafeMineDBPassword1
- '"}'

Aws cloudformation join and sub together

I'm trying to generate list of ARNs using list of account ids. Below is the code ,
Principal:
Service: lambda.amazonaws.com
AWS:
!Split
- ','
- !Sub
- 'arn:${AWS::Partition}:iam::${acc_id}:root'
- acc_id: !Join
- !Sub ':root,arn:${AWS::Partition}:iam::'
- !Ref AccountIds
But getting an error "botocore.exceptions.ClientError: An error occurred (ValidationError) when calling the UpdateStack operation: Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined."
I'm not understanding what's wrong in above code. Can someone help ?

How use Sub function wth GetAtt in serverless?

Consider the following code:
EventRule:
Type: AWS::Events::Rule
Properties:
Description: "ny trigger"
ScheduleExpression: "rate(1 minute)"
State: "DISABLED"
Targets:
-
Arn: !GetAtt MyFunctionLambdaFunction.Arn
Id: "someId"
Input:
Fn::Sub:
- '{"arn":"#{arn}"}'
- arn: !GetAtt MyStateMachine.Arn
This gives me en error:
Error: The CloudFormation template is invalid: Template error: One or more Fn::Sub
intrinsic functions don't specify expected arguments. Specify a string as first argument,
and an optional second argument to specify a mapping of values to replace in the string
You don't need GetAtt in Sub here. Sub can resolve things like MyStateMachine.Arn. So you can just do something like:
Input: !Sub
- |-
{ "arn": "${MyStateMachine.Arn}" }
In some cases you might still need to pass in parameters (for instance when you need to call functions like ImportValue). For instance, if your state machine is defined in a different stack and is exported via other-stack-MyStateMachine-Arn output, you can do the following:
Input: !Sub
- |-
{ "arn": "${MyStateMachineArn}" }
- MyStateMachineArn: !ImportValue
'Fn::Sub': 'other-stack-MyStateMachine-Arn'