Skip to content

Commit cbd4d9a

Browse files
authored
chore: merge pull request #638 from awslabs/release/v1.8.0
Release/v1.8.0
2 parents a2c6954 + 2335939 commit cbd4d9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+6177
-53
lines changed

DEVELOPMENT_GUIDE.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,23 @@ Install snakeviz `pip install snakeviz`
8181
```
8282
python -m cProfile -o sam_profile_results bin/sam-translate.py translate --input-file=tests/translator/input/alexa_skill.yaml --output-file=cfn-template.json
8383
snakeviz sam_profile_results
84+
```
85+
86+
Verifying transforms
87+
--------------------
88+
89+
If you make changes to the transformer and want to verify the resulting CloudFormation template works as expected, you can transform your SAM template into a CloudFormation template using the following process:
90+
91+
```shell
92+
# Optional: You only need to run the package command in certain cases; e.g. when your CodeUri specifies a local path
93+
# Replace MY_TEMPLATE_PATH with the path to your template and MY_S3_BUCKET with an existing S3 bucket
94+
aws cloudformation package --template-file MY_TEMPLATE_PATH/template.yaml --output-template-file output-template.yaml --s3-bucket MY_S3_BUCKET
95+
96+
# Transform your SAM template into a CloudFormation template
97+
# Replace "output-template.yaml" if you didn't run the package command above or specified a different path for --output-template-file
98+
bin/sam-translate.py --input-file=output-template.yaml
99+
100+
# Deploy your transformed CloudFormation template
101+
# Replace MY_STACK_NAME with a unique name each time you deploy
102+
aws cloudformation deploy --template-file cfn-template.json --capabilities CAPABILITY_NAMED_IAM --stack-name MY_STACK_NAME
84103
```

bin/sam-translate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def main():
5757
except InvalidDocumentException as e:
5858
errorMessage = reduce(lambda message, error: message + ' ' + error.message, e.causes, e.message)
5959
print(errorMessage)
60-
errors = map(lambda cause: {'errorMessage': cause.message}, e.causes)
60+
errors = map(lambda cause: cause.message, e.causes)
6161
print(errors)
6262

6363

docs/conf.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
3232
# ones.
3333
extensions = ['sphinx.ext.todo',
34-
'sphinx.ext.ifconfig',
35-
'sphinx.ext.viewcode',
36-
'sphinx.ext.githubpages']
34+
'sphinx.ext.ifconfig',
35+
'sphinx.ext.viewcode',
36+
'sphinx.ext.githubpages']
3737

3838
# Add any paths that contain templates here, relative to this directory.
3939
templates_path = ['_templates']
@@ -85,25 +85,29 @@
8585
# The theme to use for HTML and HTML Help pages. See the documentation for
8686
# a list of builtin themes.
8787
#
88-
html_theme = 'alabaster'
88+
html_theme = 'sphinx_rtd_theme'
8989

9090
# Theme options are theme-specific and customize the look and feel of a theme
9191
# further. For a list of options available for each theme, see the
9292
# documentation.
9393
#
94+
9495
html_theme_options = {
95-
'description': "Define your serverless infrastructure as a simple YAML file",
96-
'logo': 'logo.png',
97-
'logo_name': True,
98-
'logo_text_align': 'center',
99-
'github_user': 'awslabs',
100-
'github_repo': 'serverless-application-model',
101-
'github_button': True,
102-
'github_type': 'star',
103-
'github_banner': True,
104-
'sidebar_collapse': True,
10596
}
10697

98+
# html_theme_options = {
99+
# 'description': "Define your serverless infrastructure as a simple YAML file",
100+
# 'logo': 'logo.png',
101+
# 'logo_name': True,
102+
# 'logo_text_align': 'center',
103+
# 'github_user': 'awslabs',
104+
# 'github_repo': 'serverless-application-model',
105+
# 'github_button': True,
106+
# 'github_type': 'star',
107+
# 'github_banner': True,
108+
# 'sidebar_collapse': True,
109+
# }
110+
107111
# Add any paths that contain custom static files (such as style sheets) here,
108112
# relative to this directory. They are copied after the builtin static files,
109113
# so a file named "default.css" will overwrite the builtin "default.css".
@@ -116,9 +120,9 @@
116120
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
117121
html_sidebars = {
118122
'**': [
119-
'about.html',
120-
'navigation.html',
121-
'relations.html'
123+
'about.html',
124+
'navigation.html',
125+
'relations.html'
122126
]
123127
}
124128

@@ -180,7 +184,6 @@
180184
]
181185

182186

183-
184187
# -- Options for Epub output ----------------------------------------------
185188

186189
# Bibliographic Dublin Core info.
@@ -200,5 +203,3 @@
200203

201204
# A list of files that should not be packed into the epub file.
202205
epub_exclude_files = ['search.html']
203-
204-

examples/.eslintrc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extends: standard
2+
rules:
3+
prefer-promise-reject-errors: off # API Gateway expects string response from Lamdba (when using async + Promise.reject)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# API Gateway + Cognito Auth + Cognito Hosted Auth Example
2+
3+
This example shows you how to create an API Gateway API with a Cognito Authorizer using SAM.
4+
5+
## Running the example
6+
7+
Install the Node.js/NPM dependencies for your API's Lambda logic into the `src/` directory. This is necessary so that the dependencies get packaged up along with your Lambda function.
8+
9+
```bash
10+
npm install . --prefix ./src
11+
```
12+
13+
Deploy the example into your account (replace `YOUR_S3_ARTIFACTS_BUCKET` with an existing S3 bucket to store your app assets):
14+
15+
```bash
16+
# The following default values are also allowed: STACK_NAME, COGNITO_USER_POOL_CLIENT_NAME, COGNITO_USER_POOL_DOMAIN_PREFIX
17+
S3_BUCKET_NAME=YOUR_S3_ARTIFACTS_BUCKET \
18+
npm run package-deploy
19+
```
20+
21+
Cognito User Pools doesn't currently have CloudFormation support for configuring their Hosted Register/Signin UI. For now we will create these via the AWS CLI:
22+
23+
```bash
24+
npm run configure-cognito-user-pool
25+
```
26+
27+
Open the registration page created and hosted for you by Cognito in your browser. After the page loads, enter a Username and Password and click the Sign Up button.
28+
29+
```bash
30+
npm run open-signup-page
31+
32+
# Alternatively, you can open the login page by running `npm run open-login-page`
33+
```
34+
35+
After clicking Sign Up, you will be redirected to the UI client for your API.
36+
37+
To access the API UI directly as an unauthorized user (who has access to `GET /users` and `GET /users/{userId}`) you can run `npm run open-api-ui`.
38+
39+
## Additional resources
40+
41+
- https://aws.amazon.com/blogs/aws/launch-amazon-cognito-user-pools-general-availability-app-integration-and-federation/
42+
- https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
43+
- https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html
44+
- https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-invoke-api-integrated-with-cognito-user-pool.html
45+
- https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "api_cognito_auth",
3+
"version": "1.0.0",
4+
"description": "Example using API Gateway with Cognito Authorizer.",
5+
"main": "lambda.js",
6+
"license": "Apache-2.0",
7+
"dependencies": {
8+
"aws-serverless-express": "^3.3.3",
9+
"body-parser": "^1.17.1",
10+
"cors": "^2.8.3",
11+
"express": "^4.15.2",
12+
"pug": "^2.0.0-rc.1"
13+
},
14+
"scripts": {
15+
"package-deploy": "npm run set-config && npm run package && npm run deploy",
16+
"set-config": "npm config set STACK_NAME ${STACK_NAME:-sam-example-api-cognito-auth}",
17+
"package": "aws cloudformation package --template-file template.yaml --output-template-file template.packaged.yaml --s3-bucket $S3_BUCKET_NAME",
18+
"deploy": "aws cloudformation deploy --template-file ./template.packaged.yaml --stack-name $STACK_NAME --capabilities CAPABILITY_IAM",
19+
"configure-cognito-user-pool": "npm run set-cognito-user-pool-id && npm run set-cognito-user-pool-client-id && npm run set-api-id && npm run set-api-url && npm run update-user-pool-client && npm run create-user-pool-domain",
20+
"set-cognito-user-pool-id": "npm config set COGNITO_USER_POOL_ID $(aws cloudformation describe-stacks --stack-name $(npm config get STACK_NAME) --query 'Stacks[].Outputs[?OutputKey==`CognitoUserPoolId`].OutputValue' --output text)",
21+
"set-cognito-user-pool-client-id": "npm config set COGNITO_USER_POOL_CLIENT_ID $(aws cloudformation describe-stacks --stack-name $(npm config get STACK_NAME) --query 'Stacks[].Outputs[?OutputKey==`CognitoUserPoolClientId`].OutputValue' --output text)",
22+
"set-api-url": "npm config set API_URL $(aws cloudformation describe-stacks --stack-name sam-example-api-cognito-auth --query 'Stacks[].Outputs[?OutputKey==`ApiUrl`].OutputValue' --output text)",
23+
"set-api-id": "npm config set API_ID $(aws cloudformation describe-stacks --stack-name sam-example-api-cognito-auth --query 'Stacks[].Outputs[?OutputKey==`ApiId`].OutputValue' --output text)",
24+
"update-user-pool-client": "aws cognito-idp update-user-pool-client --user-pool-id $(npm config get COGNITO_USER_POOL_ID) --client-id $(npm config get COGNITO_USER_POOL_CLIENT_ID) --supported-identity-providers COGNITO --callback-urls \"[\\\"$(npm config get API_URL)\\\"]\" --allowed-o-auth-flows code implicit --allowed-o-auth-scopes openid email --allowed-o-auth-flows-user-pool-client",
25+
"create-user-pool-domain": "aws cognito-idp create-user-pool-domain --domain $(npm config get API_ID) --user-pool-id $(npm config get COGNITO_USER_POOL_ID)",
26+
"open-signup-page": "open \"https://$(npm config get API_ID).auth.us-east-1.amazoncognito.com/signup?response_type=code&client_id=$(npm config get COGNITO_USER_POOL_CLIENT_ID)&redirect_uri=$(npm config get API_URL)\"",
27+
"open-login-page": "open \"https://$(npm config get API_ID).auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=$(npm config get COGNITO_USER_POOL_CLIENT_ID)&redirect_uri=$(npm config get API_URL)\"",
28+
"open-api-ui": "open \"$(npm config get API_URL)\""
29+
}
30+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'use strict'
2+
const express = require('express')
3+
const bodyParser = require('body-parser')
4+
const cors = require('cors')
5+
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
6+
const app = express()
7+
const router = express.Router()
8+
9+
app.set('view engine', 'pug')
10+
11+
router.use(cors())
12+
router.use(bodyParser.json())
13+
router.use(bodyParser.urlencoded({ extended: true }))
14+
router.use(awsServerlessExpressMiddleware.eventContext())
15+
16+
router.get('/', (req, res) => {
17+
res.render('index', {
18+
apiId: req.apiGateway ? req.apiGateway.event.requestContext.apiId : null,
19+
apiUrl: req.apiGateway ? `https://${req.apiGateway.event.headers.Host}/${req.apiGateway.event.requestContext.stage}` : 'http://localhost:3000',
20+
cognitoUserPoolClientId: process.env.COGNITO_USER_POOL_CLIENT_ID
21+
})
22+
})
23+
24+
router.get('/users', (req, res) => {
25+
res.json(users)
26+
})
27+
28+
router.get('/users/:userId', (req, res) => {
29+
const user = getUser(req.params.userId)
30+
31+
if (!user) return res.status(404).json({})
32+
33+
return res.json(user)
34+
})
35+
36+
router.post('/users', (req, res) => {
37+
const user = {
38+
id: ++userIdCounter,
39+
name: req.body.name
40+
}
41+
users.push(user)
42+
res.status(201).json(user)
43+
})
44+
45+
router.put('/users/:userId', (req, res) => {
46+
const user = getUser(req.params.userId)
47+
48+
if (!user) return res.status(404).json({})
49+
50+
user.name = req.body.name
51+
res.json(user)
52+
})
53+
54+
router.delete('/users/:userId', (req, res) => {
55+
const userIndex = getUserIndex(req.params.userId)
56+
57+
if (userIndex === -1) return res.status(404).json({})
58+
59+
users.splice(userIndex, 1)
60+
res.json(users)
61+
})
62+
63+
const getUser = (userId) => users.find(u => u.id === parseInt(userId))
64+
const getUserIndex = (userId) => users.findIndex(u => u.id === parseInt(userId))
65+
66+
// Ephemeral in-memory data store
67+
const users = [{
68+
id: 1,
69+
name: 'Joe'
70+
}, {
71+
id: 2,
72+
name: 'Jane'
73+
}]
74+
let userIdCounter = users.length
75+
76+
app.use('/', router)
77+
78+
// Export your express server so you can import it in the lambda function.
79+
module.exports = app
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict'
2+
const awsServerlessExpress = require('aws-serverless-express')
3+
const app = require('./app')
4+
5+
const server = awsServerlessExpress.createServer(app)
6+
7+
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context)

0 commit comments

Comments
 (0)