jets 3.2.0 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3693cb1f3b4143b90f9f41b3325d12c86a5095615c7fe843aa7a044561fa535
4
- data.tar.gz: 0650ebb86666eac0779c167e4f926076c88b05481d8379f8ea7adaa2d6e35130
3
+ metadata.gz: 12689dd61b554f0b5a049ee578cf14566593788a3a2ebb7353ea26a5f7bd803c
4
+ data.tar.gz: c54ebb36356ac71a8e9d211eb9187e761eba9aca2c650abd50e55ffdbf14f6d3
5
5
  SHA512:
6
- metadata.gz: b8887e1a8af4cac8f4617aa422bc64daa52300d14abecfb130c074e27a45d35bafd4ba3090490d75de3cc091b4580450b03f39f27f815439d7cd31f34cb91ae7
7
- data.tar.gz: 0c463af7c1675eb7658689eaec0d4026341db788e0c31c82f078b80963cce7a8939914bcf59f7c4434552bb7433536756375c1b8d582dc1166f29f3b337f9bca
6
+ metadata.gz: 9834c8acaa032e002820e7ba7855f62f318160942287e2c1d23b31f4746d62cbb92253c97097bc94ca6d463044b95d7ef97f5030c6c8105682155ec6d568941d
7
+ data.tar.gz: 707f58aae8c4b8730db0a6e160830eea8a45fc840300a1f1e2a79ffb656118774446e24f1b91722e974bd0f5126a1b755c68eaea6147a8403d2aad76cfc4e697
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.5
1
+ 2.7.7
data/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [3.2.2] - 2023-05-19
7
+ - [#640](https://github.com/boltops-tools/jets/pull/640) Base path mapping CloudFormation custom resource and lambda function hardening
8
+
9
+ ## [3.2.1] - 2023-05-03
10
+ - [#637](https://github.com/boltops-tools/jets/pull/637) Readme: Replace "splat out" with "had" a baby
11
+ - [#638](https://github.com/boltops-tools/jets/pull/638) feature: update an array of reserved variables in aws lambda
12
+ - [#639](https://github.com/boltops-tools/jets/pull/639) fix assets upload during deploy
13
+
6
14
  ## [3.2.0] - 2022-12-03
7
15
  - [#631](https://github.com/boltops-tools/jets/pull/631) Implement vpc_endpoint_ids configuration
8
16
  - [#634](https://github.com/boltops-tools/jets/pull/634) Custom domain messaging
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <a href="http://rubyonjets.com"><img src="http://rubyonjets.com/img/logos/jets-logo-full.png" /></a>
3
3
  </div>
4
4
 
5
- Ruby and Lambda splat out a baby and that child's name is [Jets](http://rubyonjets.com/).
5
+ Ruby and Lambda had a baby and that child's name is [Jets](http://rubyonjets.com/).
6
6
 
7
7
  ![Build Status](https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiZ08vK2hjOHczQUVoUDhSYnBNNUU4T0gxQWJuOTlLaXpwVGQ1NjJ3NnVDY1dSdFVXQ3d2VXVSQzRFcU1qd1JPMndFZlByRktIcTUrZm5GWlM5dHpjM1ZrPSIsIml2UGFyYW1ldGVyU3BlYyI6Imluc1Qrd25GanhUdHlidjUiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
8
8
  [![CircleCI](https://circleci.com/gh/boltops-tools/jets.svg?style=svg)](https://circleci.com/gh/boltops-tools/jets)
@@ -16,10 +16,6 @@ Please **watch/star** this repo to help grow and support the project.
16
16
 
17
17
  **Upgrading**: If you are upgrading Jets, please check on the [Upgrading Notes](http://rubyonjets.com/docs/extras/upgrading/).
18
18
 
19
- ## Sponsors
20
-
21
- [![](https://img.boltops.com/boltops/tools/jets/sponsors/arist.png)](https://arist.co/)
22
-
23
19
  ## What is Ruby on Jets?
24
20
 
25
21
  Jets is a Ruby Serverless Framework. Jets allows you to create serverless applications with a beautiful language: Ruby. It includes everything required to build an application and deploy it to AWS Lambda.
data/backers.md CHANGED
@@ -11,10 +11,5 @@ Funds donated via Patreon go directly to support Tung Nguyen's full-time work on
11
11
  <h2 align="center">Backers via Patreon</h2>
12
12
 
13
13
  <!--10 start-->
14
- - Erlend Finvåg
15
- - Nate Clark
16
- - Hirokatsu Endo
17
- - Michael Choi
18
- - Phan Lam
19
14
  - Theron Welch
20
15
  <!--10 end-->
@@ -26,7 +26,26 @@ module Jets::Cfn::Builders
26
26
  add_description("Jets: #{Jets.version} Code: #{Util::Source.version}")
27
27
 
28
28
  # Initial s3 bucket, used to store code zipfile and templates Jets generates
29
+ #
30
+ # AWS changed the default behavior of s3 buckets to block public access
31
+ # https://aws.amazon.com/blogs/aws/amazon-s3-block-public-access-another-layer-of-protection-for-your-accounts-and-buckets/
32
+ # https://github.com/aws-amplify/amplify-cli/issues/12503
33
+ #
34
+ # Jets uploads assets to s3 bucket with acl: "public-read" here
35
+ # https://github.com/boltops-tools/jets/blob/c5858ec2706a606665a92c3ada3f16ae4c753372/lib/jets/cfn/upload.rb#L97
36
+ #
37
+ # Use minimal s3 bucket policy to allow public read access to assets.
38
+ # Leave the other options as comments to help document the default behavior.
29
39
  resource = Jets::Resource::S3::Bucket.new(logical_id: "s3_bucket",
40
+ PublicAccessBlockConfiguration: {
41
+ BlockPublicAcls: false,
42
+ # BlockPublicPolicy: false,
43
+ # IgnorePublicAcls: false,
44
+ # RestrictPublicBuckets: false
45
+ },
46
+ OwnershipControls: {
47
+ Rules: [{ObjectOwnership: "ObjectWriter"}]
48
+ },
30
49
  bucket_encryption: {
31
50
  server_side_encryption_configuration: [
32
51
  server_side_encryption_by_default: {
@@ -1,13 +1,49 @@
1
- require 'bundler/setup'
1
+ begin
2
+ require 'bundler/setup'
3
+ # When require bundler/setup fails, AWS Lambda won't be able to load base_path_mapping
4
+ # So we'll require base_path_mapping within begin/rescue block so that it does not also
5
+ # fail the entire lambda function.
6
+ require 'jets/internal/app/functions/jets/base_path_mapping'
7
+ rescue Exception => e
8
+ # Note: rescue LoadError is not enough in AWS Lambda environment
9
+ # Actual exceptions:
10
+ # require bundler/setup: Ruby exception "Bundler::GemNotFound"
11
+ # require base_path_mappnig: AWS Lambda reported error "errorType": "Init<LoadError>"
12
+ # Will use a generic rescue Exception though in case error changes in the future.
13
+ puts "WARN: #{e.class} #{e.message}"
14
+ puts <<~EOL
15
+ Could not require bundler/setup.
16
+ This can happen for weird timeout missing error. Example:
17
+
18
+ Could not find timeout-0.3.2 in locally installed gems
19
+
20
+ Happens when the gem command is out-of-date on old versions of ruby 2.7.
21
+ See: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
22
+ EOL
23
+ end
2
24
  require 'cfn_response'
3
- require 'jets/internal/app/functions/jets/base_path_mapping'
4
25
 
5
26
  STAGE_NAME = "<%= @stage_name %>"
6
27
 
7
28
  def lambda_handler(event:, context:)
8
29
  cfn = CfnResponse.new(event, context)
9
30
  cfn.response do
10
- mapping = BasePathMapping.new(event, STAGE_NAME)
31
+ # Super edge case: mapping is nil when require bundler/setup fails
32
+ begin
33
+ mapping = BasePathMapping.new(event, STAGE_NAME)
34
+ rescue NameError => e
35
+ puts "ERROR: #{e.class} #{e.message}"
36
+ puts error_message
37
+ end
38
+
39
+ # This is the "second pass" of CloudFormation when it tries to delete the BasePathMapping during rollback
40
+ if mapping.nil? && event['RequestType'] == "Delete"
41
+ cfn.success # so that CloudFormation can continue the delete process from a rollback
42
+ delay
43
+ return
44
+ end
45
+
46
+ # Normal behavior when mapping is not nil when bundler/setup loads successfully
11
47
  case event['RequestType']
12
48
  when "Create", "Update"
13
49
  mapping.update
@@ -16,3 +52,57 @@ def lambda_handler(event:, context:)
16
52
  end
17
53
  end
18
54
  end
55
+
56
+ def delay
57
+ puts "Delaying 60 seconds to allow user some time to see lambda function logs."
58
+ 60.times do
59
+ puts Time.now
60
+ sleep 1
61
+ end
62
+ end
63
+
64
+ def error_message
65
+ <<~EOL
66
+ This is ultimately the result of require bundler/setup failing to load.
67
+ On the CloudFormation first pass, the BasePathMapping fails to CREATE.
68
+ CloudFormation does a rollback and tries to delete the BasePathMapping.
69
+
70
+ Jets will send a success response to CloudFormation so it can continue and delete
71
+ BasePathMapping on the rollback. Otherwise, CloudFormation ends up in the terminal
72
+ UPDATE_FAILED state and the CloudFormation console provides 3 options:
73
+
74
+ 1) retry 2) update 3) rollback.
75
+
76
+ The only option that seems to work is rollback to get it out of UPDATE_FAILED to
77
+ UPDATE_ROLLBACK_COMPLETE. But then, if we `jets deploy` again without fixing the
78
+ require bundler/setup issue, we'll end back up in the UPDATE_FAILED state.
79
+
80
+ Will handle this error so we can continue the stack because we do not want it to fail
81
+ and never be able to send the CfnResponse. Then we have to wait hours for a CloudFormation timeout.
82
+ Sometimes deleting the APP-dev-ApiDeployment20230518230443-EXAMPLEY8YQP0 stack
83
+ allows the cloudformation stacks to continue, but usually, it'll only just slightly speed up the rollback.
84
+
85
+ Some examples of actual rollback times:
86
+
87
+ When left alone, the rollback takes about 2.5 hours.
88
+
89
+ 2023-05-19 05:39:25 User Initiated
90
+ 2023-05-19 08:01:48 UPDATE_ROLLBACK_COMPLETE
91
+
92
+ When deleting the APP-dev-ApiDeployment20230518230443-EXAMPLEY8YQP0 stack, it takes about 1.5 hours.
93
+
94
+ 2023-05-19 06:25:41 User Initiated
95
+ 2023-05-19 07:47:03 UPDATE_ROLLBACK_COMPLETE
96
+
97
+ Rescuing and handling the error here allows the CloudFormation stack to continue and finish the rollback process.
98
+ It takes the rollback time down to about 3 minutes. Example:
99
+
100
+ 2023-05-19 16:34:19 User Initiated
101
+ 2023-05-19 16:37:34 UPDATE_ROLLBACK_COMPLETE
102
+
103
+ Note: The first cloudformation CREATE pass sends FAILED Status to CloudFormation,
104
+ and the second cloudformation DELETE pass sends SUCCESS Status to CloudFormation.
105
+
106
+ Related: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
107
+ EOL
108
+ end
@@ -28,8 +28,28 @@ class BasePathMapping
28
28
  # Cannot use update_base_path_mapping to update the base_mapping because it doesnt
29
29
  # allow us to change the rest_api_id. So we delete and create.
30
30
  def update
31
- delete(true)
32
- create
31
+ puts "BasePathMapping update"
32
+ if rest_api_changed?
33
+ delete(true)
34
+ create
35
+ else
36
+ puts "BasePathMapping update: rest_api_id #{rest_api_id} did not change. Skipping."
37
+ end
38
+
39
+ puts "BasePathMapping update complete"
40
+ end
41
+
42
+ def rest_api_changed?
43
+ puts "BasePathMapping checking if rest_api_id changed"
44
+ mapping = current_base_path_mapping
45
+ return true unless mapping
46
+ mapping.rest_api_id != rest_api_id
47
+ end
48
+
49
+ def current_base_path_mapping
50
+ resp = apigateway.get_base_path_mapping(base_path: "(none)", domain_name: domain_name)
51
+ rescue Aws::APIGateway::Errors::NotFoundException
52
+ return nil
33
53
  end
34
54
 
35
55
  # Dont delete the newly created base path mapping unless this is an operation
@@ -39,10 +59,14 @@ class BasePathMapping
39
59
  end
40
60
 
41
61
  def delete(fail_silently=false)
42
- apigateway.delete_base_path_mapping(
62
+ puts "BasePathMapping delete"
63
+ options = {
43
64
  domain_name: domain_name, # required
44
65
  base_path: base_path.empty? ? '(none)' : base_path,
45
- )
66
+ }
67
+ puts "BasePathMapping delete options #{options.inspect}"
68
+ apigateway.delete_base_path_mapping(options)
69
+ puts "BasePathMapping delete complete"
46
70
  # https://github.com/tongueroo/jets/issues/255
47
71
  # Used to return: Aws::APIGateway::Errors::NotFoundException
48
72
  # Now returns: Aws::APIGateway::Errors::InternalFailure
@@ -52,12 +76,41 @@ class BasePathMapping
52
76
  end
53
77
 
54
78
  def create
55
- apigateway.create_base_path_mapping(
79
+ puts "BasePathMapping create"
80
+ options = {
56
81
  domain_name: domain_name, # required
57
82
  base_path: base_path,
58
83
  rest_api_id: rest_api_id, # required
59
84
  stage: @stage_name,
60
- )
85
+ }
86
+ puts "BasePathMapping create options #{options.inspect}"
87
+ apigateway.create_base_path_mapping(options)
88
+ puts "BasePathMapping create complete"
89
+ rescue Aws::APIGateway::Errors::ServiceError => e
90
+ puts "ERROR: #{e.class}: #{e.message}"
91
+ puts "BasePathMapping create failed"
92
+ if e.message.include?("Invalid domain name identifier specified")
93
+ puts <<~EOL
94
+ This super edge case error seems to happen when the cloudformation stack does a rollback
95
+ because the BasePathMapping custom resource fails. This has happened with a strange combination of
96
+ ruby 2.7 and the timeout gem not being picked up in the AWS Lambda runtime environment
97
+ Specifically, when jets deploy was used with a rubygems install that is out-of-date.
98
+ See: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
99
+
100
+ The new base path mapping is not created correctly and the old base path mapping is not properly deleted.
101
+ The old ghost base mapping interferes with the new base path mapping.
102
+ The workaround solution seems to require removing all the config.domain settings and deploying again. Example:
103
+
104
+ config/application.rb
105
+
106
+ config.domain.cert_arn = "arn:aws:acm:us-west-2:111111111111:certificate/EXAMPLE1-a3de-4fe7-b72e-4cc153c5303e"
107
+ config.domain.hosted_zone_name = "example.com"
108
+
109
+ Comment out those settings, deploy, then uncomment and deploy again.
110
+ If there's a better workaround, please let us know.
111
+ EOL
112
+ end
113
+ raise(e)
61
114
  end
62
115
 
63
116
  def deployment_stack
@@ -110,3 +163,9 @@ class BasePathMapping
110
163
  options
111
164
  end
112
165
  end
166
+
167
+ if __FILE__ == $0
168
+ event = JSON.load(File.read(ARGV[0]))
169
+ context = nil # stub out
170
+ BasePathMapping.new(event, context).update
171
+ end
@@ -36,21 +36,23 @@ class Jets::Resource::Lambda::Function
36
36
  exit 1
37
37
  end
38
38
 
39
- # https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html#lambda-environment-variables
39
+ # https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
40
40
  def reserved_variables
41
41
  %w[
42
42
  _HANDLER
43
+ AWS_DEFAULT_REGION
43
44
  AWS_REGION
44
45
  AWS_EXECUTION_ENV
45
46
  AWS_LAMBDA_FUNCTION_NAME
46
47
  AWS_LAMBDA_FUNCTION_MEMORY_SIZE
47
48
  AWS_LAMBDA_FUNCTION_VERSION
49
+ AWS_LAMBDA_INITIALIZATION_TYPE
48
50
  AWS_LAMBDA_LOG_GROUP_NAME
49
51
  AWS_LAMBDA_LOG_STREAM_NAME
52
+ AWS_ACCESS_KEY
50
53
  AWS_ACCESS_KEY_ID
51
54
  AWS_SECRET_ACCESS_KEY
52
55
  AWS_SESSION_TOKEN
53
- TZ
54
56
  LAMBDA_TASK_ROOT
55
57
  LAMBDA_RUNTIME_DIR
56
58
  AWS_LAMBDA_RUNTIME_API
data/lib/jets/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jets
2
- VERSION = "3.2.0"
2
+ VERSION = "3.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jets
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-03 00:00:00.000000000 Z
11
+ date: 2023-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -1103,7 +1103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1103
1103
  - !ruby/object:Gem::Version
1104
1104
  version: '0'
1105
1105
  requirements: []
1106
- rubygems_version: 3.3.10
1106
+ rubygems_version: 3.4.13
1107
1107
  signing_key:
1108
1108
  specification_version: 4
1109
1109
  summary: Ruby Serverless Framework