Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharing variables/resources between parent and child stacks? #15

Open
kaitlynbrown opened this issue Jul 16, 2019 · 4 comments
Open

Sharing variables/resources between parent and child stacks? #15

kaitlynbrown opened this issue Jul 16, 2019 · 4 comments

Comments

@kaitlynbrown
Copy link

The documentation doesn't seem to mention anything about this. Is it possible? If so, how?

@gio-trueper
Copy link

I have a use case were I need the outputs from one stack into the next one. I'm having a hard time referencing the depended stack since its ID has a random suffix.

Is there a way to accomplish this ? getting the outputs from one nested stack into another ?

@abduncan
Copy link

abduncan commented Apr 8, 2022

Seconded @gio-trueper's issue. I am trying to reference an export from a nested stack, but cannot figure out the stack id since it is randomly generated.

@abduncan
Copy link

abduncan commented Apr 9, 2022

I have figured this out. Below are my serverless.yml and react-infrasctructure.yml (nested stack) files.

I am referencing the CloudFront Distribution Id from the nested stack in the serverless.yml file.

Notice the export of CFDistributionId in react-infrastructure.yml and it's reference in the custom section of the serverless.yml file.

serverless.yml:

service: my-service

provider:
  name: aws
  runtime: nodejs14.x
  stage: dev
  region: us-east-1


custom:

  CFDistributionId: !ImportValue ${self:service}-${self:provider.stage}-CFDistributionId

  webpack:
      webpackConfig: 'webpack.config.js'
      includeModules: true
      packager: 'npm'
      packExternalModulesMaxBuffer: 204800

  nested-stacks:
    location: devops
    stacks:
      - id: reactinfrastructure
        template: react-infrastructure.yml
        timeout: 60
        parameters:
          - ServiceName: ${self:service}
          - EnvironmentStage: ${self:provider.stage}
      # - id: vpc
      #   template: vpc.yml
      #   timeout: 60
      #   parameters:
      #     - ClassB: 10

functions:
  hello:
    handler: apps/portal-api/src/app/index.hello
    description: A function for Hello Application
    events:
      - http:
          path: /hello
          method: get
    environment:
      distributionId: ${self:custom.CFDistributionId}
plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-aws-nested-stacks

react-infrastructure.yml:

AWSTemplateFormatVersion: '2010-09-09'

Description: >
  Creates the infrastructure to host and expose a Single Page Application:
      - An Amazon S3 bucket for hosting the application
      - An Amazon CloudFront distribution to expose the application
      - An Amazon S3 bucket for hosting bucket and cloudfront access logs

Parameters:
  
  ServiceName:
    Description: 'Name of the Serverless service'
    Type: String

  EnvironmentStage:
    Description: The environment (dev, test, prod)
    Type: String
    AllowedValues:
      - dev
      - test
      - prod

Resources:
  # The Amazon S3 bucket into which our Single Page Application build files must be deployed
  S3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub '${ServiceName}-react-app-${EnvironmentStage}'
      PublicAccessBlockConfiguration:
        BlockPublicAcls : true
        BlockPublicPolicy : true
        IgnorePublicAcls : true
        RestrictPublicBuckets : true
      LoggingConfiguration:
        DestinationBucketName: !Ref LoggingBucket
        LogFilePrefix: s3-access-logs
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'

  # The Amazon S3 bucket policy for securing the bucket hosting the application
  BucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PolicyForCloudFrontPrivateContent
            Effect: Allow
            Principal:
              CanonicalUser: !GetAtt CFOriginAccessIdentity.S3CanonicalUserId
            Action: 's3:GetObject*'
            Resource: !Join 
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket
                - /*
      Bucket: !Ref S3Bucket

  # The Amazon S3 bucket into which access logs from S3 (for the application) and CloudFront will be put
  LoggingBucket:
    #checkov:skip=CKV_AWS_18: "This bucket is private and only for storing logs"
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub '${ServiceName}-react-app-${EnvironmentStage}-logs'
      PublicAccessBlockConfiguration:
        BlockPublicAcls : true
        BlockPublicPolicy : true
        IgnorePublicAcls : true
        RestrictPublicBuckets : true
      AccessControl: LogDeliveryWrite
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'
    DeletionPolicy: Delete

  # The Amazon CloudFront distribution exposing our Single Page Application
  CFDistribution:
    #checkov:skip=CKV_AWS_68: "For demo purposes and to reduce cost, no WAF is configured"
    Type: 'AWS::CloudFront::Distribution'
    DependsOn:
      - CFOriginAccessIdentity
    Properties:
      DistributionConfig:
        Origins:
        - DomainName: !GetAtt S3Bucket.RegionalDomainName
          Id: myS3Origin
          S3OriginConfig:
            OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CFOriginAccessIdentity}"
        Enabled: 'true'
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
          - GET
          - HEAD
          - OPTIONS
          TargetOriginId: myS3Origin
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized
          OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf # CORS-S3Origin
          ViewerProtocolPolicy: redirect-to-https
        PriceClass: PriceClass_All
        Logging:
          Bucket: !GetAtt LoggingBucket.RegionalDomainName
          Prefix: 'cloudfront-access-logs'

  # The Amazon CloudFront origin access identity
  CFOriginAccessIdentity:
    Type: 'AWS::CloudFront::CloudFrontOriginAccessIdentity'
    DependsOn:
      - S3Bucket
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: !Sub 'access-identity-${ServiceName}-react-app-${EnvironmentStage}'

Outputs:
  ReactBucketName:
    Value: !Sub "${ServiceName}-react-app-${EnvironmentStage}-${CFOriginAccessIdentity}"
  CFDistributionId:
    Value: !Ref CFDistribution
    Export:
      Name: !Sub "${ServiceName}-${EnvironmentStage}-CFDistributionId"

@gio-trueper

@arleyyap
Copy link

arleyyap commented Sep 9, 2022

I have figured this out. Below are my serverless.yml and react-infrasctructure.yml (nested stack) files.

I am referencing the CloudFront Distribution Id from the nested stack in the serverless.yml file.

Notice the export of CFDistributionId in react-infrastructure.yml and it's reference in the custom section of the serverless.yml file.

serverless.yml:

service: my-service

provider:
  name: aws
  runtime: nodejs14.x
  stage: dev
  region: us-east-1


custom:

  CFDistributionId: !ImportValue ${self:service}-${self:provider.stage}-CFDistributionId

  webpack:
      webpackConfig: 'webpack.config.js'
      includeModules: true
      packager: 'npm'
      packExternalModulesMaxBuffer: 204800

  nested-stacks:
    location: devops
    stacks:
      - id: reactinfrastructure
        template: react-infrastructure.yml
        timeout: 60
        parameters:
          - ServiceName: ${self:service}
          - EnvironmentStage: ${self:provider.stage}
      # - id: vpc
      #   template: vpc.yml
      #   timeout: 60
      #   parameters:
      #     - ClassB: 10

functions:
  hello:
    handler: apps/portal-api/src/app/index.hello
    description: A function for Hello Application
    events:
      - http:
          path: /hello
          method: get
    environment:
      distributionId: ${self:custom.CFDistributionId}
plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-aws-nested-stacks

react-infrastructure.yml:

AWSTemplateFormatVersion: '2010-09-09'

Description: >
  Creates the infrastructure to host and expose a Single Page Application:
      - An Amazon S3 bucket for hosting the application
      - An Amazon CloudFront distribution to expose the application
      - An Amazon S3 bucket for hosting bucket and cloudfront access logs

Parameters:
  
  ServiceName:
    Description: 'Name of the Serverless service'
    Type: String

  EnvironmentStage:
    Description: The environment (dev, test, prod)
    Type: String
    AllowedValues:
      - dev
      - test
      - prod

Resources:
  # The Amazon S3 bucket into which our Single Page Application build files must be deployed
  S3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub '${ServiceName}-react-app-${EnvironmentStage}'
      PublicAccessBlockConfiguration:
        BlockPublicAcls : true
        BlockPublicPolicy : true
        IgnorePublicAcls : true
        RestrictPublicBuckets : true
      LoggingConfiguration:
        DestinationBucketName: !Ref LoggingBucket
        LogFilePrefix: s3-access-logs
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'

  # The Amazon S3 bucket policy for securing the bucket hosting the application
  BucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PolicyForCloudFrontPrivateContent
            Effect: Allow
            Principal:
              CanonicalUser: !GetAtt CFOriginAccessIdentity.S3CanonicalUserId
            Action: 's3:GetObject*'
            Resource: !Join 
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket
                - /*
      Bucket: !Ref S3Bucket

  # The Amazon S3 bucket into which access logs from S3 (for the application) and CloudFront will be put
  LoggingBucket:
    #checkov:skip=CKV_AWS_18: "This bucket is private and only for storing logs"
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub '${ServiceName}-react-app-${EnvironmentStage}-logs'
      PublicAccessBlockConfiguration:
        BlockPublicAcls : true
        BlockPublicPolicy : true
        IgnorePublicAcls : true
        RestrictPublicBuckets : true
      AccessControl: LogDeliveryWrite
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'
    DeletionPolicy: Delete

  # The Amazon CloudFront distribution exposing our Single Page Application
  CFDistribution:
    #checkov:skip=CKV_AWS_68: "For demo purposes and to reduce cost, no WAF is configured"
    Type: 'AWS::CloudFront::Distribution'
    DependsOn:
      - CFOriginAccessIdentity
    Properties:
      DistributionConfig:
        Origins:
        - DomainName: !GetAtt S3Bucket.RegionalDomainName
          Id: myS3Origin
          S3OriginConfig:
            OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CFOriginAccessIdentity}"
        Enabled: 'true'
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
          - GET
          - HEAD
          - OPTIONS
          TargetOriginId: myS3Origin
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized
          OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf # CORS-S3Origin
          ViewerProtocolPolicy: redirect-to-https
        PriceClass: PriceClass_All
        Logging:
          Bucket: !GetAtt LoggingBucket.RegionalDomainName
          Prefix: 'cloudfront-access-logs'

  # The Amazon CloudFront origin access identity
  CFOriginAccessIdentity:
    Type: 'AWS::CloudFront::CloudFrontOriginAccessIdentity'
    DependsOn:
      - S3Bucket
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: !Sub 'access-identity-${ServiceName}-react-app-${EnvironmentStage}'

Outputs:
  ReactBucketName:
    Value: !Sub "${ServiceName}-react-app-${EnvironmentStage}-${CFOriginAccessIdentity}"
  CFDistributionId:
    Value: !Ref CFDistribution
    Export:
      Name: !Sub "${ServiceName}-${EnvironmentStage}-CFDistributionId"

@gio-trueper

Hi, I'm new to serverless and I'm still learning. I have the need for an ALB and a nat gateway to be shared so that other stacks that are going to have some lambdas can use them. I think your answer could be my guide but how do you command execute when deploying? Serverless automatically detects that the serverless.yml file needs react-infrasctructure.yml ?. really appreciate your help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants