├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── sample-code ├── __init__.py ├── lambda.py └── requirements.txt └── template.yaml /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## parameters-secrets-lambda-extension-sample 2 | 3 | This project contains source code and supporting files for deploying resources described in following blog: 4 | [Using the AWS Parameter and Secrets Lambda extension to cache parameters and secrets](https://aws.amazon.com/blogs/compute/using-the-aws-parameter-and-secrets-lambda-extension-to-cache-parameters-and-secrets/) 5 | 6 | - sample-code - Code for the sample Lambda function. 7 | - template.yaml - A template that defines the AWS resources used in the example. 8 | 9 | ## Deployment instructions 10 | 11 | ``` 12 | git clone https://github.com/aws-samples/parameters-secrets-lambda-extension-sample.git 13 | sam build 14 | sam deploy --guided 15 | ``` 16 | 17 | The deploy command will package and deploy your application to AWS, with a series of prompts as seen below: 18 | 19 | ``` 20 | Setting default arguments for 'sam deploy' 21 | 22 | ================================ 23 | 24 | Stack Name [sam-app]: parameter-secrets-extension-blog-stack 25 | AWS Region [us-east-1]: 26 | Parameter pVpcCIDR [172.31.0.0/16]: 27 | Parameter pPublicSubnetCIDR [172.31.3.0/24]: 28 | Parameter pPrivateSubnetACIDR [172.31.2.0/24]: 29 | Parameter pPrivateSubnetBCIDR [172.31.1.0/24]: 30 | Parameter pDatabaseName [DemoAppDatabase]: 31 | Parameter pDatabaseUsername [myadmin]: 32 | Parameter pDBEngineVersion [5.7]: 33 | #Shows you resources changes to be deployed and require a 'Y' to initiate deploy 34 | Confirm changes before deploy [y/N]: y 35 | #SAM needs permission to be able to create roles to connect to the resources in your template 36 | Allow SAM CLI IAM role creation [Y/n]: y 37 | #Preserves the state of previously provisioned resources when an operation fails 38 | Disable rollback [y/N]: N 39 | Save arguments to configuration file [Y/n]: y 40 | SAM configuration file [samconfig.toml]: 41 | SAM configuration environment [default]: 42 | 43 | Looking for resources needed for deployment: 44 | Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-9cqpewwuywgs 45 | A different default S3 bucket can be set in samconfig.toml 46 | 47 | Saved arguments to config file 48 | Running 'sam deploy' for future deployments will use the parameters saved above. 49 | The above parameters can be changed by modifying samconfig.toml 50 | ``` 51 | ## Security 52 | 53 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 54 | 55 | ## License 56 | 57 | This library is licensed under the MIT-0 License. See the LICENSE file. 58 | 59 | -------------------------------------------------------------------------------- /sample-code/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/parameters-secrets-lambda-extension-sample/4cf00c01401f184306615d9ca35c3bd33cac4748/sample-code/__init__.py -------------------------------------------------------------------------------- /sample-code/lambda.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | import urllib3 3 | import os 4 | import json 5 | 6 | ### Load in Lambda environment variables 7 | port = os.environ['PARAMETERS_SECRETS_EXTENSION_HTTP_PORT'] 8 | aws_session_token = os.environ['AWS_SESSION_TOKEN'] 9 | env = os.environ['ENV'] 10 | app_config_path = os.environ['APP_CONFIG_PATH'] 11 | creds_path = os.environ['CREDS_PATH'] 12 | full_config_path = '/' + env + '/' + app_config_path 13 | 14 | ### Define function to retrieve values from extention local HTTP server cachce 15 | def retrieve_extension_value(url): 16 | http = urllib3.PoolManager() 17 | url = ('http://localhost:' + port + url) 18 | headers = { "X-Aws-Parameters-Secrets-Token": os.environ.get('AWS_SESSION_TOKEN') } 19 | response = http.request("GET", url, headers=headers) 20 | response = json.loads(response.data) 21 | return response 22 | 23 | def lambda_handler(event, context): 24 | 25 | ### Load Parameter Store values from extension 26 | print("Loading AWS Systems Manager Parameter Store values from " + full_config_path) 27 | parameter_url = ('/systemsmanager/parameters/get/?name=' + full_config_path) 28 | config_values = retrieve_extension_value(parameter_url)['Parameter']['Value'] 29 | print("Found config values: " + json.dumps(config_values)) 30 | 31 | ### Load Secrets Manager values from extension 32 | print("Loading AWS Secrets Manager values from " + creds_path) 33 | secrets_url = ('/secretsmanager/get?secretId=' + creds_path) 34 | secret_string = json.loads(retrieve_extension_value(secrets_url)['SecretString']) 35 | #print("Found secret values: " + json.dumps(secret_string)) 36 | 37 | rds_host = secret_string['host'] 38 | rds_db_name = secret_string['dbname'] 39 | rds_username = secret_string['username'] 40 | rds_password = secret_string['password'] 41 | 42 | 43 | ### Connect to RDS MySQL database 44 | try: 45 | conn = pymysql.connect(host=rds_host, user=rds_username, passwd=rds_password, db=rds_db_name, connect_timeout=5) 46 | except: 47 | raise Exception("An error occurred when connecting to the database!") 48 | 49 | return "DemoApp sucessfully loaded config " + config_values + " and connected to RDS database " + rds_db_name + "!" 50 | -------------------------------------------------------------------------------- /sample-code/requirements.txt: -------------------------------------------------------------------------------- 1 | pymysql -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones along with other VPC resources such as NAT Gateway, route tables etc. It deploys an Multi-AZ RDS instance, SSM Parameter and a Secret Manager secret. 4 | Parameters: 5 | pVpcCIDR: 6 | Description: Enter the IP range (CIDR notation) for the VPC 7 | Type: String 8 | Default: 172.31.0.0/16 9 | AllowedPattern: '^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$' 10 | pPublicSubnetCIDR: 11 | Description: Please enter the IP range (CIDR notation) for the public subnet 12 | Type: String 13 | Default: 172.31.3.0/24 14 | pPrivateSubnetACIDR: 15 | Description: Please enter the IP range (CIDR notation) for the private subnet A 16 | Type: String 17 | Default: 172.31.2.0/24 18 | AllowedPattern: '^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$' 19 | pPrivateSubnetBCIDR: 20 | Description: Please enter the IP range (CIDR notation) for the private subnet B 21 | Type: String 22 | Default: 172.31.1.0/24 23 | AllowedPattern: '^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$' 24 | pDatabaseName: 25 | Default: DemoAppDatabase 26 | Description: Database name for PROD environment 27 | Type: String 28 | AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' 29 | ConstraintDescription: Begin with a letter and use only alphanumeric characters. 30 | pDatabaseUsername: 31 | Default: myadmin 32 | Description: Database username for PROD environment 33 | Type: String 34 | MinLength: 1 35 | MaxLength: 64 36 | AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' 37 | ConstraintDescription: Begin with a letter and use only alphanumeric characters. 38 | pDBEngineVersion: 39 | Default: '5.7' 40 | Type: String 41 | Description: The version number of the database engine to use. 42 | # pParameterSecretExtensionARN: 43 | # Type: String 44 | # Description: ARN of AWS Parameter and Secrets Extension 45 | # Default: 'arn:aws:lambda:us-west-1:997803712105:layer:AWS-Parameters-and-Secrets-Lambda-Extension:2' 46 | Globals: 47 | Function: 48 | Timeout: 3 49 | Resources: 50 | rVPC: 51 | Type: AWS::EC2::VPC 52 | Properties: 53 | CidrBlock: !Ref pVpcCIDR 54 | EnableDnsSupport: true 55 | EnableDnsHostnames: true 56 | Tags: 57 | - Key: Name 58 | Value: DemoVPC 59 | rInternetGateway: 60 | Type: AWS::EC2::InternetGateway 61 | rInternetGatewayAttachment: 62 | Type: AWS::EC2::VPCGatewayAttachment 63 | Properties: 64 | InternetGatewayId: !Ref rInternetGateway 65 | VpcId: !Ref rVPC 66 | rPublicSubnet: 67 | Type: AWS::EC2::Subnet 68 | Properties: 69 | VpcId: !Ref rVPC 70 | AvailabilityZone: 71 | Fn::Select: 72 | - 0 73 | - Fn::GetAZs: "" 74 | CidrBlock: !Ref pPublicSubnetCIDR 75 | # MapPublicIpOnLaunch: true 76 | Tags: 77 | - Key: Name 78 | Value: DemoVPC-PublicSubnet 79 | rPrivateSubnetA: 80 | Type: AWS::EC2::Subnet 81 | Properties: 82 | VpcId: !Ref rVPC 83 | AvailabilityZone: 84 | Fn::Select: 85 | - 0 86 | - Fn::GetAZs: "" 87 | CidrBlock: !Ref pPrivateSubnetACIDR 88 | MapPublicIpOnLaunch: false 89 | Tags: 90 | - Key: Name 91 | Value: DemoVPC-PrivateSubnetA 92 | rPrivateSubnetB: 93 | Type: AWS::EC2::Subnet 94 | Properties: 95 | VpcId: !Ref rVPC 96 | AvailabilityZone: 97 | Fn::Select: 98 | - 1 99 | - Fn::GetAZs: "" 100 | CidrBlock: !Ref pPrivateSubnetBCIDR 101 | MapPublicIpOnLaunch: false 102 | Tags: 103 | - Key: Name 104 | Value: DemoVPC-PrivateSubnetB 105 | rNatGatewayEIP: 106 | Type: AWS::EC2::EIP 107 | DependsOn: rInternetGatewayAttachment 108 | Properties: 109 | Domain: vpc 110 | rNatGateway: 111 | Type: AWS::EC2::NatGateway 112 | Properties: 113 | AllocationId: !GetAtt rNatGatewayEIP.AllocationId 114 | SubnetId: !Ref rPublicSubnet 115 | rPublicRouteTable: 116 | Type: AWS::EC2::RouteTable 117 | Properties: 118 | VpcId: !Ref rVPC 119 | rDefaultPublicRoute: 120 | Type: AWS::EC2::Route 121 | DependsOn: rInternetGatewayAttachment 122 | Properties: 123 | RouteTableId: !Ref rPublicRouteTable 124 | DestinationCidrBlock: 0.0.0.0/0 125 | GatewayId: !Ref rInternetGateway 126 | rPublicSubnetRouteTableAssociation: 127 | Type: AWS::EC2::SubnetRouteTableAssociation 128 | Properties: 129 | RouteTableId: !Ref rPublicRouteTable 130 | SubnetId: !Ref rPublicSubnet 131 | rPrivateRouteTable: 132 | Type: AWS::EC2::RouteTable 133 | Properties: 134 | VpcId: !Ref rVPC 135 | rDefaultPrivateRoute: 136 | Type: AWS::EC2::Route 137 | Properties: 138 | RouteTableId: !Ref rPrivateRouteTable 139 | DestinationCidrBlock: 0.0.0.0/0 140 | NatGatewayId: !Ref rNatGateway 141 | rPrivateSubnetARouteTableAssociation: 142 | Type: AWS::EC2::SubnetRouteTableAssociation 143 | Properties: 144 | RouteTableId: !Ref rPrivateRouteTable 145 | SubnetId: !Ref rPrivateSubnetA 146 | rPrivateSubnetBRouteTableAssociation: 147 | Type: AWS::EC2::SubnetRouteTableAssociation 148 | Properties: 149 | RouteTableId: !Ref rPrivateRouteTable 150 | SubnetId: !Ref rPrivateSubnetB 151 | rRDSSecurityGroup: 152 | Type: AWS::EC2::SecurityGroup 153 | Properties: 154 | GroupDescription: "Security group allows inbound access to Amazon RDS" 155 | VpcId: !Ref rVPC 156 | SecurityGroupIngress: 157 | - IpProtocol: tcp 158 | FromPort: 3306 159 | ToPort: 3306 160 | CidrIp: !Ref pVpcCIDR 161 | Description: "Rule allows inbound access on port 3306" 162 | SecurityGroupEgress: 163 | - IpProtocol: tcp 164 | FromPort: 443 165 | ToPort: 443 166 | CidrIp: 0.0.0.0/0 167 | Description: "Rule allows outbound access for Lambda to connect to Parameter and secrets endpoint" 168 | - IpProtocol: tcp 169 | FromPort: 3306 170 | ToPort: 3306 171 | CidrIp: !Ref pVpcCIDR 172 | Description: "Rule allows outbound access for RDS instance" 173 | rDatabaseSecret: 174 | Type: 'AWS::SecretsManager::Secret' 175 | Properties: 176 | Description: "This secret has a dynamically generated secret password." 177 | GenerateSecretString: 178 | SecretStringTemplate: !Join [ '', [ '{"username": "', !Ref pDatabaseUsername, '"}' ] ] 179 | GenerateStringKey: "password" 180 | PasswordLength: 30 181 | ExcludeCharacters: '"@/\' 182 | rDatabaseSubnetGroup: 183 | Type: AWS::RDS::DBSubnetGroup 184 | DependsOn: rVPC 185 | Properties: 186 | DBSubnetGroupDescription: Subnets 187 | SubnetIds: 188 | - !Ref rPrivateSubnetA 189 | - !Ref rPrivateSubnetB 190 | Tags: 191 | - Key: Name 192 | 193 | Value: DemoSubnetGroup 194 | rDatabase: 195 | Type: AWS::RDS::DBInstance 196 | Properties: 197 | DBName: !Ref pDatabaseName 198 | DBInstanceIdentifier: !Ref pDatabaseName 199 | AllocatedStorage: '10' 200 | DBInstanceClass: db.t2.small 201 | Engine: MySQL 202 | EngineVersion: !Ref pDBEngineVersion 203 | MasterUsername: 204 | Fn::Sub: '{{resolve:secretsmanager:${rDatabaseSecret}:SecretString:username}}' 205 | MasterUserPassword: 206 | Fn::Sub: '{{resolve:secretsmanager:${rDatabaseSecret}:SecretString:password}}' 207 | MultiAZ: true 208 | DBSubnetGroupName: !Ref rDatabaseSubnetGroup 209 | StorageEncrypted: true 210 | DeletionProtection: false 211 | PubliclyAccessible: false 212 | VPCSecurityGroups: 213 | - !Ref rRDSSecurityGroup 214 | rDatabaseSecretUpdate: 215 | Type: "AWS::SecretsManager::SecretTargetAttachment" 216 | Properties: 217 | SecretId: !Ref rDatabaseSecret 218 | TargetId: !Ref rDatabase 219 | TargetType: AWS::RDS::DBInstance 220 | rSampleParameter: 221 | Type: AWS::SSM::Parameter 222 | Properties: 223 | DataType: text 224 | Description: "Sample dev config values for demo app" 225 | Tier: Standard 226 | Type: String 227 | Name: /dev/demoApp/app_config 228 | Value: '{"enableVersion":true,"version":1,"app":"DemoApp"}' 229 | rLambdaExecutionRole: 230 | Type: AWS::IAM::Role 231 | Properties: 232 | # RoleName: DemoAppLambdaExecutionRole 233 | AssumeRolePolicyDocument: 234 | Version: "2012-10-17" 235 | Statement: 236 | - Effect: Allow 237 | Principal: 238 | Service: 239 | - lambda.amazonaws.com 240 | Action: 241 | - 'sts:AssumeRole' 242 | Description: This role is used by the Lambda function 243 | Path: / 244 | ManagedPolicyArns: 245 | - 'arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole' 246 | Policies: 247 | - PolicyName: secretsPolicy 248 | PolicyDocument: 249 | Version: "2012-10-17" 250 | Statement: 251 | - Effect: Allow 252 | Action: 253 | - 'secretsmanager:GetSecretValue' 254 | Resource: 255 | - !Ref rDatabaseSecret 256 | - PolicyName: parametersPolicy 257 | PolicyDocument: 258 | Version: "2012-10-17" 259 | Statement: 260 | - Effect: Allow 261 | Action: 262 | - 'ssm:GetParameter' 263 | Resource: 264 | - !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${rSampleParameter}' 265 | rLambdaFunction: 266 | Type: AWS::Serverless::Function 267 | Properties: 268 | CodeUri: sample-code/ 269 | Handler: lambda.lambda_handler 270 | Runtime: python3.9 271 | Architectures: 272 | - x86_64 273 | Role: !GetAtt rLambdaExecutionRole.Arn 274 | VpcConfig: 275 | SecurityGroupIds: 276 | - !GetAtt rRDSSecurityGroup.GroupId 277 | SubnetIds: 278 | - !Ref rPrivateSubnetA 279 | - !Ref rPrivateSubnetB 280 | # Layers: 281 | # - !Ref pParameterSecretExtensionARN 282 | Environment: 283 | Variables: 284 | PARAMETERS_SECRETS_EXTENSION_HTTP_PORT: 2773 285 | CREDS_PATH: !Ref rDatabaseSecret 286 | APP_CONFIG_PATH: demoApp/app_config 287 | ENV: dev 288 | SSM_PARAMETER_STORE_TTL: 120 289 | SECRETS_MANAGER_TTL: 120 290 | Outputs: 291 | oLambdaFunction: 292 | Description: "Hello World Lambda Function ARN" 293 | Value: !GetAtt rLambdaFunction.Arn 294 | oVpcId: 295 | Description: A reference to the created rVPC 296 | Value: !Ref rVPC 297 | Export: 298 | Name: !Join ["-", [!Ref "AWS::StackName","vpc-id"]] 299 | oPublicSubnet: 300 | Description: A reference to the public subnet 301 | Value: !Ref rPublicSubnet 302 | Export: 303 | Name: !Join ["-", [!Ref "AWS::StackName","public-subnet"]] 304 | oPrivateSubnetA: 305 | Description: A reference to the private subnet A 306 | Value: !Ref rPrivateSubnetA 307 | Export: 308 | Name: !Join ["-", [!Ref "AWS::StackName","private-subnet"]] 309 | oPrivateSubnetB: 310 | Description: A reference to the private subnet A 311 | Value: !Ref rPrivateSubnetB 312 | Export: 313 | Name: !Join ["-", [!Ref "AWS::StackName","private-subnet-b"]] 314 | oRDSSecurityGroup: 315 | Description: Security group allowing access on MySQL port 316 | Value: !Ref rRDSSecurityGroup 317 | Export: 318 | Name: !Join ["-", [!Ref "AWS::StackName","rds-vpc-sg"]] 319 | oDatabaseName: 320 | Description: PROD Database name 321 | Value: !Ref pDatabaseName 322 | Export: 323 | Name: !Join ["-", [!Ref "AWS::StackName","db-name"]] 324 | oSampleParameter: 325 | Description: "SSM Parameter Store parameter with sample config " 326 | Value: !Ref rSampleParameter 327 | Export: 328 | Name: !Join ["-", [!Ref "AWS::StackName","parameter-name"]] 329 | oLambdaExecutionRole: 330 | Description: Role to be used by AWS Lambda Function 331 | Value: !GetAtt rLambdaExecutionRole.Arn 332 | Export: 333 | Name: !Join ["-", [!Ref "AWS::StackName","lambda-execution-role"]] 334 | oDatabaseSecret: 335 | Description: "Database secret with connection string" 336 | Value: !Ref rDatabaseSecret 337 | Export: 338 | Name: !Join ["-", [!Ref "AWS::StackName","database-secret"]] 339 | --------------------------------------------------------------------------------