Hi all has anyone tried to pass dependency between...
# help
i
Hi all has anyone tried to pass dependency between two stacks in different regions as in this solution https://stackoverflow.com/questions/59774627/cloudformation-cross-region-reference/63559786#63559786 I’m trying to set it up with custom resources as in the example but I’m getting lack of permissions error: Islam-Salem-metatrust-com-met-match-service-MailReceiver failed: Received response status [FAILED] from custom resource. Message returned: User: arnawssts:0xxxxxxxxxxxxassumed-role/Islam-Salem-metatrust-com-AWS679f53fac002430cb0da5-14GZHEC5E8LWA/Islam-Salem-metatrust-com-AWS679f53fac002430cb0da5-ZKnTcwE6TYSS is not authorized to perform: ssm:GetParameter on resource: arnawsssmeu central 1072408395743:parameter/EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM because no identity-based policy allows the ssm:GetParameter action
f
Hey @Islam Salem, as a side note, CloudFormation stack export values cannot be referenced across region, so the SSM way suggested in the post is the way to go.
If u run
sst build
, go into
.build/cdk.out
, and open up the template for the
Islam-Salem-metatrust-com-met-match-service-MailReceiver
stack. Search for
GetParameter
, do u see it anywhere in the template?
i
Hi @Frank thanks for your support I did what you mentioned and yes I can see the permission in the template
Copy code
"Route53HostedZoneIdReaderCustomResourcePolicyB255EC5E": {
  "Type": "AWS::IAM::Policy",
  "Properties": {
    "PolicyDocument": {
      "Statement": [
        {
          "Action": "ssm:GetParameter",
          "Effect": "Allow",
          "Resource": "arn:aws:ssm:eu-west-1:072408395743:parameter:EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM"
        }
      ],
      "Version": "2012-10-17"
    },
    "PolicyName": "Route53HostedZoneIdReaderCustomResourcePolicyB255EC5E",
    "Roles": [
      {
        "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2"
      }
    ]
  },
  "Metadata": {
    "aws:cdk:path": "Islam-Salem-metatrust-com-met-match-service-MailReceiver/Route53HostedZoneIdReader/CustomResourcePolicy/Resource"
  }
},
and that’s the SSM parameter custom resource
Copy code
import { Construct } from 'constructs';
import { AwsCustomResource, AwsSdkCall } from 'aws-cdk-lib/custom-resources';
import * as iam from 'aws-cdk-lib/aws-iam';

interface SSMParameterReaderProps {
  parameterName: string;
  region: string;
}

export class SSMParameterReader extends AwsCustomResource {
  constructor(scope: Construct, name: string, props: SSMParameterReaderProps) {
    const { parameterName, region } = props;

    const ssmAwsSdkCall: AwsSdkCall = {
      service: 'SSM',
      action: 'getParameter',
      parameters: {
        Name: parameterName,
      },
      region,
      physicalResourceId: {
        id: Date.now().toString(), // Update physical id to always fetch the latest version
      },
    };

    super(scope, name, {
      onUpdate: ssmAwsSdkCall,
      policy: {
        statements: [
          new iam.PolicyStatement({
            resources: [
              `arn:aws:ssm:eu-west-1:072408395743:parameter:${parameterName}`,
            ],
            actions: ['ssm:GetParameter'],
            effect: iam.Effect.ALLOW,
          }),
        ],
      },
    });
  }

  public getParameterValue() {
    return this.getResponseField('Parameter.Value');
  }
}
I’m not sure if I’m using it right or not I can’t find any example on how to use custom resources
this is how the two stacks look like
Copy code
// main stack in eu-central-1
import * as sst from "@serverless-stack/resources";
import { StringParameter } from "aws-cdk-lib/aws-ssm";
import { EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM } from "./constant";

export default class MainStack extends sst.Stack {
  constructor(scope: <http://sst.App|sst.App>, id: string, props?: sst.StackProps) {
    super(scope, id, props);

    const emailHandlerFunction = new sst.Function(
      this,
      "ExposeEmailHandlerFunction",
      {
        handler: "src/expose-email-handler.removeExpose",
      }
    );

    new StringParameter(this, "EmailHandlerFunctionSSMParam", {
      parameterName: EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM,
      description: "The Expose subdomain email handler function ARN",
      stringValue: emailHandlerFunction.functionArn,
    });
  }
}



// MailReceiverStack in eu-west-1
import * as sst from '@serverless-stack/resources';
import * as ses from 'aws-cdk-lib/aws-ses';
import * as actions from 'aws-cdk-lib/aws-ses-actions';
import { VerifySesDomain } from '@seeebiii/ses-verify-identities';
import { SSMParameterReader } from './SSMParameterReader';
import { EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM } from './constant';

export default class MailReceiverStack extends sst.Stack {
  constructor(scope: <http://sst.App|sst.App>, id: string, props: sst.StackProps) {
    super(scope, id, props);

    new VerifySesDomain(this, 'SesDomainVerification', {
      domainName: '<http://expose.metatrust.net|expose.metatrust.net>',
      hostedZoneName: '<http://metatrust.net|metatrust.net>',
    });

    const ruleSet = ses.ReceiptRuleSet.fromReceiptRuleSetName(
      this,
      'DefaultRuleSet',
      'default-rule-set'
    );

    const emailHandlerFunctionArn = new SSMParameterReader(
      this,
      'Route53HostedZoneIdReader',
      {
        parameterName: EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM,
        region: 'eu-central-1',
      }
    ).getParameterValue();

    new ses.ReceiptRule(this, 'ReceiptRule', {
      ruleSet,
      recipients: ['<http://expose.metatrust.net|expose.metatrust.net>'],
      actions: [
        new actions.Lambda({
          function: sst.Function.fromFunctionArn(
            this,
            'emailHandler',
            emailHandlerFunctionArn
          ),
        }),
      ],
    });
  }
}
@Frank any idea?
f
@Islam Salem in the error message, it’s trying to access the SSM is in the
eu-central-1
Copy code
arn:aws:ssm:eu-central-1:072408395743:parameter/EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM
In the CloudFormation u shared above, the SSM is in the
eu-west-1
Copy code
arn:aws:ssm:eu-west-1:072408395743:parameter:EMAIL_HANDLER_FUNCTION_ARN_SSM_PARAM
wrong region maybe?
i
thanks @Frank appreciate your help 🙂
I tried to update the region on the given permission but it didn’t work until I did
Copy code
super(scope, name, {
      onUpdate: ssmAwsSdkCall,
      policy: {
        statements: [
          new iam.PolicyStatement({
            resources : ['*'],
            actions: ['ssm:GetParameter'],
            effect: iam.Effect.ALLOW,
          }),
        ],
      },
    });
f
Hi @Islam Salem, can you send me the new error message you are getting and the CloudFormation template snippet again?
i
Hi @Frank after trying again with another resource (s3 bucket) ARN, it seems to work with specifying the region. Thanks for your time and your helpful support 🙂
f
Oh nice! Glad u got it working