jets 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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