himari-aws 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +127 -14
  3. data/Rakefile +2 -0
  4. data/lambda/Dockerfile +33 -0
  5. data/lambda/Gemfile +24 -0
  6. data/{Gemfile.lock → lambda/Gemfile.lock} +61 -23
  7. data/lambda/README.md +42 -0
  8. data/lambda/entrypoint.rb +3 -0
  9. data/lambda/terraform/README.md +89 -0
  10. data/lambda/terraform/functions/aws.tf +2 -0
  11. data/lambda/terraform/functions/dynamodb.tf +18 -0
  12. data/lambda/terraform/functions/lambda_rack.tf +66 -0
  13. data/lambda/terraform/functions/lambda_secrets_rotation.tf +33 -0
  14. data/lambda/terraform/functions/outputs.tf +19 -0
  15. data/lambda/terraform/functions/variables.tf +65 -0
  16. data/lambda/terraform/functions/versions.tf +7 -0
  17. data/lambda/terraform/iam/aws.tf +2 -0
  18. data/lambda/terraform/iam/outputs.tf +3 -0
  19. data/lambda/terraform/iam/role.tf +77 -0
  20. data/lambda/terraform/iam/variables.tf +44 -0
  21. data/lambda/terraform/iam/versions.tf +7 -0
  22. data/lambda/terraform/image/aws.tf +1 -0
  23. data/lambda/terraform/image/copy.sh +5 -0
  24. data/lambda/terraform/image/copy.tf +17 -0
  25. data/lambda/terraform/image/ecr.tf +42 -0
  26. data/lambda/terraform/image/outputs.tf +9 -0
  27. data/lambda/terraform/image/variables.tf +9 -0
  28. data/lambda/terraform/image/versions.tf +7 -0
  29. data/lambda/terraform/signing_key/aws.tf +1 -0
  30. data/lambda/terraform/signing_key/outputs.tf +3 -0
  31. data/lambda/terraform/signing_key/secret.tf +18 -0
  32. data/lambda/terraform/signing_key/variables.tf +24 -0
  33. data/lambda/terraform/signing_key/versions.tf +7 -0
  34. data/lib/himari/aws/lambda_handler.rb +72 -0
  35. data/lib/himari/aws/secretsmanager_signing_key_rotation_handler.rb +23 -1
  36. data/lib/himari/aws/version.rb +1 -1
  37. metadata +48 -5
  38. data/Gemfile +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb42481e34029c9e1ae8c3594dd64995f423a53818cbc867a0fd2c65c64c3ff1
4
- data.tar.gz: 55e743a182643484f59544428a9384661a161d4a5657895bd9bed70714c19024
3
+ metadata.gz: 2cc2ae7b20fd4a41872281249587bacae7170a411651458cfab901afc08a9bfe
4
+ data.tar.gz: dc2cd99bad600b636b817c1534b5ea8c17e59bb49a9bf667b4ee7f0d41f17acd
5
5
  SHA512:
6
- metadata.gz: fc863a5752789f4b83b030c5bb44fc6de47d52acdc44225baf74d97e04f4c2de6ff3b3e1a4fb03bde80b377c956bd70137c8dc0d2cdb2c2e33238d107644c4c1
7
- data.tar.gz: d5093ed3e72bae790f76b9709443b37bf97be5686b53b676cb35fc1d01568685c93d228a1c9825157480328439d6c638e8846afb746a522f9a24320fe61239d8
6
+ metadata.gz: 5f0fdb41114958bf5330173fd12de1db680f77ef8719d84e0fc1724ea9bb0311c8d7d63363111ec9490ee4a39227d91acff8224f601a5ae055e1199a239a7f64
7
+ data.tar.gz: 2ee76e5b556d477ee37d51a92a5a4fb03d8c751c5e877d295c46970bb073cfb6bf6b7f4a70611b4ade5890caec4e15f42a98a6d94fb81a02553df6cf2815a8ff
data/README.md CHANGED
@@ -1,24 +1,137 @@
1
- # Himari::Aws
1
+ # himari-aws: AWS related plugins for Himari
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ - DynamoDB storage backend
4
+ - Secrets Manager automatic rotation Lambda function for signing keys
5
+ - Secrets Manager signing key provider
6
+ - Lambda container image to host Himari itself (TODO)
4
7
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/himari/aws`. To experiment with that code, run `bin/console` for an interactive prompt.
8
+ ## Deploy on Lambda with Terraform
6
9
 
7
- ## Installation
8
-
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
- Install the gem and add to the application's Gemfile by executing:
10
+ - See [./lambda/terraform/](./lambda/terraform/) for quick deployment using Terraform modules.
12
11
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
-
15
- If bundler is not being used to manage dependencies, install the gem by executing:
12
+ ## Installation
16
13
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+ ```ruby
15
+ gem 'himari'
16
+ gem 'himari-aws'
17
+ gem 'nokogiri'
18
+ ```
19
+
20
+ ### IAM policy
21
+
22
+ ```json
23
+ {
24
+ "Version": "2012-10-17",
25
+ "Statement": [
26
+ {
27
+ "Effect": "Allow",
28
+ "Action": [
29
+ "dynamodb:DeleteItem",
30
+ "dynamodb:Query",
31
+ "dynamodb:UpdateItem"
32
+ ],
33
+ "Resource": "arn:aws:dynamodb:[REGION]:[ACCOUNTID]:table/himari_*"
34
+ },
35
+ {
36
+ "Effect": "Allow",
37
+ "Action": [
38
+ "secretsmanager:DescribeSecret",
39
+ "secretsmanager:GetSecretValue",
40
+ "secretsmanager:PutSecretValue",
41
+ "secretsmanager:UpdateSecretVersionStage"
42
+ ],
43
+ "Resource": "arn:aws:secretsmanager:[REGION]:[ACCOUNTID]:secret:himari_*"
44
+ }
45
+ ]
46
+ }
47
+ ```
18
48
 
19
49
  ## Usage
20
50
 
21
- TODO: Write usage instructions here
51
+ ### Secrets Manager Rotation Handler
52
+
53
+ 1. Deploy [./lib/himari/aws/secretsmanager_signing_key_rotation_handler.rb]() as a Lambda function. This file works standalone.
54
+
55
+ - Refer to the [./lambda](./lambda) for prebuilt container image
56
+
57
+ 2. Grant secrets manager a `lambda:InvokeFunction` to the function.
58
+ 3. Create a secrets manager secret and set up rotation.
59
+
60
+ You can tag a secret with `HimariKey` key and the following value to customize key types:
61
+
62
+ - RSA 2048-bit: `kty=rsa,len=2048`
63
+ - RSA 4096-bit: `kty=rsa,len=4096`
64
+ - EC P-256: `kty=ec,len=256`
65
+
66
+ _you may also specify in base64'd json_
67
+
68
+ ### config.ru
69
+
70
+ ```ruby
71
+ # config.ru
72
+ require 'himari'
73
+ require 'himari/aws'
74
+ require 'json'
75
+ require 'omniauth'
76
+ require 'open-uri'
77
+ require 'rack/session/cookie'
78
+
79
+ use(Rack::Session::Cookie,
80
+ path: '/',
81
+ expire_after: 3600,
82
+ secure: true,
83
+ secret: ENV.fetch('SECRET_KEY_BASE'),
84
+ )
85
+
86
+ use OmniAuth::Builder do
87
+ provider :developer, fields: %i(login), uid_field: :login
88
+ end
89
+
90
+ use(Himari::Middlewares::Config,
91
+ issuer: 'https://idp.example.net',
92
+ providers: [
93
+ { name: :github, button: 'Log in with GitHub' },
94
+ ],
95
+ storage: Himari::Aws::DynamodbStorage.new(table_name: 'himari'),
96
+ )
97
+
98
+ # Signing key from Secrets Manager. For rotation deployment, read
99
+ use(Himari::Aws::SecretsmanagerSigningKeyProvider,
100
+ secret_id: 'arn:aws:secretsmanager:ap-northeast-1:...:secret:himari-xxx',
101
+ group: nil,
102
+ kid_prefix: 'asm1',
103
+ )
104
+
105
+ # Add clients as many as you need
106
+ use(Himari::Middlewares::Client,
107
+ name: 'awsalb',
108
+ id: '...',
109
+ secret_hash: '...', # sha384 hexdigest of secret
110
+ # secret: '...' # or in cleartext
111
+ redirect_uris: %w(https://app.example.net/oauth2/idpresponse),
112
+ )
113
+
114
+ use(Himari::Middlewares::ClaimsRule, name: 'developer-initialize') do |context, decision|
115
+ next decision.skip!("provider not in scope") unless context.provider == 'developer'
116
+ decision.initialize_claims!(
117
+ sub: "dev_#{Digest::SHA256.hexdigest(context.auth[:uid])}",
118
+ name: context.auth[:info][:login],
119
+ preferred_username: context.auth[:info][:login],
120
+ )
121
+ decision.continue!
122
+ end
123
+
124
+ use(Himari::Middlewares::AuthenticationRule, name: 'always-allow') do |context, decision|
125
+ next decision.skip!("provider not in scope") unless context.provider == 'developer'
126
+ decision.allow!
127
+ end
128
+
129
+ use(Himari::Middlewares::AuthorizationRule, name: 'always-allow') do |context, decision|
130
+ decision.allow!
131
+ end
132
+
133
+ run Himari::App
134
+ ```
22
135
 
23
136
  ## Development
24
137
 
@@ -28,7 +141,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
141
 
29
142
  ## Contributing
30
143
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/himari-aws.
144
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sorah/himari.
32
145
 
33
146
  ## License
34
147
 
data/Rakefile CHANGED
@@ -5,4 +5,6 @@ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ Bundler::GemHelper.tag_prefix = "himari-aws/"
9
+
8
10
  task default: :spec
data/lambda/Dockerfile ADDED
@@ -0,0 +1,33 @@
1
+ # context must be repository root
2
+ FROM public.ecr.aws/lambda/ruby:2.7 as builder
3
+ RUN yum install -y gcc gcc-c++ make pkg-config git
4
+
5
+ COPY ./himari/himari.gemspec ${LAMBDA_TASK_ROOT}/app/himari/himari.gemspec
6
+ COPY ./himari/lib/himari/version.rb ${LAMBDA_TASK_ROOT}/app/himari/lib/himari/version.rb
7
+ COPY ./himari-aws/himari-aws.gemspec ${LAMBDA_TASK_ROOT}/app/himari-aws/himari-aws.gemspec
8
+ COPY ./himari-aws/lib/himari/aws/version.rb ${LAMBDA_TASK_ROOT}/app/himari-aws/lib/himari/aws/version.rb
9
+ COPY ./himari-aws/lambda/Gemfile* ${LAMBDA_TASK_ROOT}/app/himari-aws/lambda/
10
+ WORKDIR ${LAMBDA_TASK_ROOT}/app
11
+
12
+ ENV BUNDLE_GEMFILE ${LAMBDA_TASK_ROOT}/app/himari-aws/lambda/Gemfile
13
+ ENV BUNDLE_PATH ${LAMBDA_TASK_ROOT}/vendor/bundle
14
+ ENV BUNDLE_DEPLOYMENT 1
15
+ ENV BUNDLE_JOBS 16
16
+ ENV HIMARI_LAMBDA_IMAGE 1
17
+ RUN bundle install
18
+
19
+ COPY . ${LAMBDA_TASK_ROOT}/app
20
+
21
+ FROM public.ecr.aws/lambda/ruby:2.7
22
+
23
+ COPY --from=builder ${LAMBDA_TASK_ROOT}/vendor ${LAMBDA_TASK_ROOT}/vendor
24
+ COPY . ${LAMBDA_TASK_ROOT}/app
25
+
26
+ COPY ./himari-aws/lambda/entrypoint.rb ${LAMBDA_TASK_ROOT}/himari_lambda_entrypoint.rb
27
+
28
+ WORKDIR ${LAMBDA_TASK_ROOT}/app
29
+ ENV BUNDLE_GEMFILE ${LAMBDA_TASK_ROOT}/app/himari-aws/lambda/Gemfile
30
+ ENV BUNDLE_PATH ${LAMBDA_TASK_ROOT}/vendor/bundle
31
+ ENV BUNDLE_DEPLOYMENT 1
32
+ ENV HIMARI_LAMBDA_IMAGE 1
33
+ CMD [ "himari_lambda_entrypoint.Himari::Aws::LambdaHandler.rack_handler" ]
data/lambda/Gemfile ADDED
@@ -0,0 +1,24 @@
1
+ source 'https://rubygems.org'
2
+
3
+ root = File.join('..', '..')
4
+
5
+ gem 'himari', path: File.join(root, 'himari')
6
+ gem 'himari-aws', path: File.join(root, 'himari-aws')
7
+ gem 'nokogiri'
8
+ #gem 'apigatewayv2_rack', git: 'https://github.com/sorah/apigatewayv2_rack'
9
+ gem 'apigatewayv2_rack', '>= 0.1.3'
10
+
11
+ # contribs
12
+ gem 'omniauth-oauth2'
13
+ gem 'omniauth-saml'
14
+ #gem 'omniauth-twitter'
15
+ gem 'omniauth-github'
16
+ gem 'omniauth-auth0'
17
+ #gem 'omniauth-shibboleth'
18
+ gem 'omniauth-gitlab'
19
+ #gem 'omniauth-kerberos'
20
+ gem 'omniauth-google-oauth2'
21
+ gem 'omniauth-discord'
22
+ gem 'omniauth-apple'
23
+ # gem 'omniauth-ldap' # omniauth < 2
24
+ #gem 'omniauth-slack'# omniauth-oauth2 version constraints does not match with omniauth-github
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: ../himari
2
+ remote: ../../himari
3
3
  specs:
4
- himari (0.1.0)
4
+ himari (0.2.0)
5
5
  addressable
6
6
  omniauth (>= 2.0)
7
7
  openid_connect
@@ -10,9 +10,10 @@ PATH
10
10
  sinatra (>= 3.0)
11
11
 
12
12
  PATH
13
- remote: .
13
+ remote: ..
14
14
  specs:
15
- himari-aws (0.1.0)
15
+ himari-aws (0.2.0)
16
+ apigatewayv2_rack
16
17
  aws-sdk-dynamodb
17
18
  aws-sdk-secretsmanager
18
19
  himari
@@ -30,9 +31,11 @@ GEM
30
31
  addressable (2.8.1)
31
32
  public_suffix (>= 2.0.2, < 6.0)
32
33
  aes_key_wrap (1.1.0)
34
+ apigatewayv2_rack (0.1.3)
35
+ rack
33
36
  attr_required (1.0.1)
34
37
  aws-eventstream (1.2.0)
35
- aws-partitions (1.730.0)
38
+ aws-partitions (1.732.0)
36
39
  aws-sdk-core (3.170.1)
37
40
  aws-eventstream (~> 1, >= 1.0.2)
38
41
  aws-partitions (~> 1, >= 1.651.0)
@@ -49,7 +52,6 @@ GEM
49
52
  bindata (2.4.15)
50
53
  concurrent-ruby (1.2.2)
51
54
  date (3.3.3)
52
- diff-lcs (1.5.0)
53
55
  faraday (2.7.4)
54
56
  faraday-net_http (>= 2.0, < 3.1)
55
57
  ruby2_keywords (>= 0.0.4)
@@ -66,6 +68,7 @@ GEM
66
68
  bindata
67
69
  faraday (~> 2.0)
68
70
  faraday-follow_redirects
71
+ jwt (2.7.0)
69
72
  mail (2.8.1)
70
73
  mini_mime (>= 0.1.1)
71
74
  net-imap
@@ -74,6 +77,7 @@ GEM
74
77
  mini_mime (1.1.2)
75
78
  mini_portile2 (2.8.1)
76
79
  minitest (5.18.0)
80
+ multi_xml (0.6.0)
77
81
  mustermann (3.0.0)
78
82
  ruby2_keywords (~> 0.0.1)
79
83
  net-imap (0.3.4)
@@ -88,10 +92,43 @@ GEM
88
92
  nokogiri (1.14.2)
89
93
  mini_portile2 (~> 2.8.0)
90
94
  racc (~> 1.4)
95
+ oauth2 (2.0.9)
96
+ faraday (>= 0.17.3, < 3.0)
97
+ jwt (>= 1.0, < 3.0)
98
+ multi_xml (~> 0.5)
99
+ rack (>= 1.2, < 4)
100
+ snaky_hash (~> 2.0)
101
+ version_gem (~> 1.1)
91
102
  omniauth (2.1.1)
92
103
  hashie (>= 3.4.6)
93
104
  rack (>= 2.2.3)
94
105
  rack-protection
106
+ omniauth-apple (1.3.0)
107
+ json-jwt
108
+ omniauth-oauth2
109
+ omniauth-auth0 (3.1.0)
110
+ omniauth (~> 2)
111
+ omniauth-oauth2 (~> 1)
112
+ omniauth-discord (1.0.0)
113
+ omniauth
114
+ omniauth-oauth2
115
+ omniauth-github (2.0.1)
116
+ omniauth (~> 2.0)
117
+ omniauth-oauth2 (~> 1.8)
118
+ omniauth-gitlab (4.1.0)
119
+ omniauth (~> 2.0)
120
+ omniauth-oauth2 (~> 1.8.0)
121
+ omniauth-google-oauth2 (1.1.1)
122
+ jwt (>= 2.0)
123
+ oauth2 (~> 2.0.6)
124
+ omniauth (~> 2.0)
125
+ omniauth-oauth2 (~> 1.8.0)
126
+ omniauth-oauth2 (1.8.0)
127
+ oauth2 (>= 1.4, < 3)
128
+ omniauth (~> 2.0)
129
+ omniauth-saml (2.1.0)
130
+ omniauth (~> 2.0)
131
+ ruby-saml (~> 1.12)
95
132
  openid_connect (2.2.0)
96
133
  activemodel
97
134
  attr_required (>= 1.0.0)
@@ -117,26 +154,19 @@ GEM
117
154
  rack (>= 2.1.0)
118
155
  rack-protection (3.0.5)
119
156
  rack
120
- rake (13.0.6)
121
- rspec (3.12.0)
122
- rspec-core (~> 3.12.0)
123
- rspec-expectations (~> 3.12.0)
124
- rspec-mocks (~> 3.12.0)
125
- rspec-core (3.12.1)
126
- rspec-support (~> 3.12.0)
127
- rspec-expectations (3.12.2)
128
- diff-lcs (>= 1.2.0, < 2.0)
129
- rspec-support (~> 3.12.0)
130
- rspec-mocks (3.12.4)
131
- diff-lcs (>= 1.2.0, < 2.0)
132
- rspec-support (~> 3.12.0)
133
- rspec-support (3.12.0)
157
+ rexml (3.2.5)
158
+ ruby-saml (1.15.0)
159
+ nokogiri (>= 1.13.10)
160
+ rexml
134
161
  ruby2_keywords (0.0.5)
135
162
  sinatra (3.0.5)
136
163
  mustermann (~> 3.0)
137
164
  rack (~> 2.2, >= 2.2.4)
138
165
  rack-protection (= 3.0.5)
139
166
  tilt (~> 2.0)
167
+ snaky_hash (2.0.1)
168
+ hashie
169
+ version_gem (~> 1.1, >= 1.1.1)
140
170
  swd (2.0.2)
141
171
  activesupport (>= 3)
142
172
  attr_required (>= 0.0.5)
@@ -152,6 +182,7 @@ GEM
152
182
  validate_url (1.0.15)
153
183
  activemodel (>= 3.0.0)
154
184
  public_suffix
185
+ version_gem (1.1.2)
155
186
  webfinger (2.1.2)
156
187
  activesupport
157
188
  faraday (~> 2.0)
@@ -161,11 +192,18 @@ PLATFORMS
161
192
  ruby
162
193
 
163
194
  DEPENDENCIES
195
+ apigatewayv2_rack (>= 0.1.3)
164
196
  himari!
165
197
  himari-aws!
166
198
  nokogiri
167
- rake (~> 13.0)
168
- rspec (~> 3.0)
199
+ omniauth-apple
200
+ omniauth-auth0
201
+ omniauth-discord
202
+ omniauth-github
203
+ omniauth-gitlab
204
+ omniauth-google-oauth2
205
+ omniauth-oauth2
206
+ omniauth-saml
169
207
 
170
208
  BUNDLED WITH
171
- 2.4.8
209
+ 2.3.21
data/lambda/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Himari Lambda Container Image
2
+
3
+ ## Deploy
4
+
5
+ - See [./terraform/](./terraform/) for quick deployment using Terraform modules.
6
+
7
+ ## Image
8
+
9
+ ### Prebuilt image
10
+
11
+ - https://gallery.ecr.aws/sorah/himari-lambda
12
+ - `public.ecr.aws/sorah/himari-lambda`
13
+
14
+ Images are tagged with commit SHA.
15
+
16
+ ### Build an image
17
+
18
+ Run the following at the repository root:
19
+
20
+ ```
21
+ docker build -f himari-aws/lambda/Dockerfile .
22
+ ```
23
+
24
+ ### Usage
25
+
26
+ The same container image supports multiple handlers:
27
+
28
+ #### Rack app for API Gateway v2, Function URL, ALB target
29
+
30
+ - Handler: `himari_lambda_entrypoint.Himari::Aws::LambdaHandler.rack_handler`
31
+
32
+ Served through [apigatewayv2_rack](https://github.com/sorah/apigatewayv2_rack).
33
+
34
+ This handler reads `config.ru` from:
35
+
36
+ - `${LAMBDA_TASK_ROOT}/config.ru` in a container image
37
+ - DynamoDB Table item (pk=`rack`, sk=`rack:${HIMARI_RACK_DIGEST}`, file=config.ru content) on table `$HIMARI_RACK_DYNAMODB_TABLE`
38
+ - where HIMARI_RACK_DIGEST must be [base64'd sha256 hash](https://developer.hashicorp.com/terraform/language/functions/base64sha256) of `file` attribute
39
+
40
+ #### Secrets Manager automatic rotation handler
41
+
42
+ - Handler: `himari_lambda_entrypoint.Himari::Aws::LambdaHandler.secrets_rotation_handler`
@@ -0,0 +1,3 @@
1
+ # BUNDLE_GEMFILE is defined at Dockerfile
2
+ require 'bundler/setup'
3
+ require 'himari/aws/lambda_handler'
@@ -0,0 +1,89 @@
1
+ # Himari Terraform modules for AWS Lambda
2
+
3
+ himari-aws/lambda/terraform provides the following modules:
4
+
5
+ - **iam:** to establish IAM role
6
+ - **image:** to copy prebuilt container image for Lambda from ECR Public
7
+ - **functions:** to deploy Lambda function
8
+ - **signing_key:** to create a secret with auto rotation enabled on Secrets Manager
9
+
10
+ ## iam
11
+
12
+ Provisions IAM role for Lambda functions.
13
+
14
+ ```terraform
15
+ module "himari_iam" {
16
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/iam"
17
+
18
+ role_name = "HimariRole"
19
+
20
+ # for policy hardening
21
+ secrets_rotation_function_arn = module.himari_functions.secrets_rotation_function_arn
22
+
23
+ # Add grants
24
+ dynamodb_table_arn = module.himari_functions.dynamodb_table_arn
25
+ secret_arns = toset([module.himari_signing_key.secret_arn])
26
+ }
27
+ ```
28
+
29
+ ## image
30
+
31
+ Create ECR private repository then mirror specified image tag from https://gallery.ecr.aws/sorah/himari-lambda
32
+
33
+ ```terraform
34
+ module "himari_image" {
35
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/image"
36
+
37
+ repository_name = "himari-lambda"
38
+ source_image_tag = "" # Replace with image tag
39
+ }
40
+ ```
41
+
42
+ - Uses null_resource with `docker` command to perform pull, retag and push to ECR private locally
43
+ - Prebuilt image tag is based on git commit SHA: https://github.com/sorah/himari/commits/main
44
+
45
+ ## functions
46
+
47
+ Deploy lambda functions and DynamoDB table
48
+
49
+ ```terraform
50
+ module "himari_functions" {
51
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/functions"
52
+
53
+ iam_role_arn = module.himari_iam.role_arn
54
+ image_url = module.himari_image.image.url
55
+
56
+ dynamodb_table_name = "himari"
57
+ function_name_prefix = "himari"
58
+
59
+ config_ru = file("${path.module}/config.ru")
60
+
61
+ environment = {
62
+ HIMARI_SIGNING_KEY_ARN = module.himari_signing_key.secret_arn
63
+ HIMARI_SECRET_PARAMS_ARN = aws_secretsmanager_secret.params.arn
64
+ }
65
+ }
66
+ ```
67
+
68
+ ## signing_key
69
+
70
+ ```terraform
71
+ module "himari_signing_key" {
72
+ source = "github.com/sorah/himari//himari-aws/lambda/terraform/signing_key"
73
+
74
+ secret_name = "himari-prd-signing-key"
75
+
76
+ rotation_function_arn = module.himari_functions.secrets_rotation_function_arn
77
+ rotate_automatically_after_days = 20
78
+ }
79
+ ```
80
+
81
+ ## misc (not modules)
82
+
83
+ Use secrets manager to store additional secrets like upstream client secrets and SECRET_KEY_BASE...
84
+
85
+ ```terraform
86
+ resource "aws_secretsmanager_secret" "params" {
87
+ name = "himari-secret-params"
88
+ }
89
+ ```
@@ -0,0 +1,2 @@
1
+ data "aws_region" "current" {}
2
+ data "aws_caller_identity" "current" {}
@@ -0,0 +1,18 @@
1
+ resource "aws_dynamodb_table" "table" {
2
+ count = var.create_dynamodb_table ? 1 : 0
3
+
4
+ name = var.dynamodb_table_name
5
+ billing_mode = "PAY_PER_REQUEST"
6
+ hash_key = "pk"
7
+ range_key = "sk"
8
+
9
+ attribute {
10
+ name = "pk"
11
+ type = "S"
12
+ }
13
+
14
+ attribute {
15
+ name = "sk"
16
+ type = "S"
17
+ }
18
+ }
@@ -0,0 +1,66 @@
1
+ resource "aws_lambda_function" "rack" {
2
+ count = var.deploy_rack ? 1 : 0
3
+
4
+ function_name = "${var.function_name_prefix}-rack"
5
+
6
+ package_type = "Image"
7
+ image_uri = var.image_url
8
+ architectures = var.architectures
9
+
10
+ image_config {
11
+ command = ["himari_lambda_entrypoint.Himari::Aws::LambdaHandler.rack_handler"]
12
+ }
13
+
14
+ role = var.iam_role_arn
15
+
16
+ memory_size = var.rack_memory_size
17
+ timeout = 20
18
+
19
+ environment {
20
+ variables = merge({
21
+ HIMARI_RACK_DYNAMODB_TABLE = var.dynamodb_table_name
22
+ HIMARI_DYNAMODB_TABLE = var.dynamodb_table_name
23
+
24
+ # dependency trick. see below
25
+ HIMARI_RACK_DIGEST = nonsensitive(jsondecode(aws_dynamodb_table_item.config_ru[local.config_ru_dgst].item)["dgst"]["S"])
26
+
27
+ RACK_ENV = "production"
28
+ }, var.environment)
29
+ }
30
+
31
+ depends_on = [aws_dynamodb_table_item.config_ru]
32
+ }
33
+
34
+ resource "aws_lambda_function_url" "rack" {
35
+ count = (var.deploy_rack && var.enable_function_url) ? 1 : 0
36
+ function_name = aws_lambda_function.rack[0].function_name
37
+ authorization_type = "NONE"
38
+ }
39
+
40
+ resource "aws_dynamodb_table_item" "config_ru" {
41
+ # Employing dependency trick to make sure a previous config_ru item removed after the function environment value update.
42
+ # By using for_each every updates will be a new resource and is referred by aws_lambda_function as a dependency, old item will be removed after updating the function completes.
43
+ for_each = { "${local.config_ru_dgst}" = var.config_ru }
44
+
45
+ table_name = var.dynamodb_table_name
46
+ hash_key = "pk"
47
+ range_key = "sk"
48
+
49
+ # using sensitive to supress unwanted diff, and diff is useful as we use for_each here
50
+ item = sensitive(jsonencode({
51
+ "pk" = { "S" = "rack" },
52
+ "sk" = { "S" = "rack:${each.key}" },
53
+ "dgst" = { "S" = each.key },
54
+ "file" = { "S" = each.value },
55
+ }))
56
+
57
+ lifecycle {
58
+ create_before_destroy = true
59
+ }
60
+
61
+ depends_on = [aws_dynamodb_table.table]
62
+ }
63
+
64
+ locals {
65
+ config_ru_dgst = base64sha256(var.config_ru)
66
+ }
@@ -0,0 +1,33 @@
1
+ resource "aws_lambda_function" "secrets_rotation" {
2
+ count = var.deploy_secrets_rotation ? 1 : 0
3
+
4
+ function_name = "${var.function_name_prefix}-secrets-rotation"
5
+
6
+ package_type = "Image"
7
+ image_uri = var.image_url
8
+ architectures = var.architectures
9
+
10
+ image_config {
11
+ command = ["himari_lambda_entrypoint.Himari::Aws::LambdaHandler.secrets_rotation_handler"]
12
+ }
13
+
14
+ role = var.iam_role_arn
15
+
16
+ memory_size = 128
17
+ timeout = 20
18
+
19
+ environment {
20
+ variables = merge({
21
+ }, var.environment)
22
+ }
23
+ }
24
+
25
+ resource "aws_lambda_permission" "secrets_rotation_secretsmanager" {
26
+ count = var.deploy_secrets_rotation ? 1 : 0
27
+
28
+ statement_id = "secretsmanager"
29
+ action = "lambda:InvokeFunction"
30
+ function_name = aws_lambda_function.secrets_rotation[0].function_name
31
+ principal = "secretsmanager.amazonaws.com"
32
+ source_account = data.aws_caller_identity.current.account_id
33
+ }
@@ -0,0 +1,19 @@
1
+ output "dynamodb_table_name" {
2
+ value = var.dynamodb_table_name
3
+ }
4
+
5
+ output "dynamodb_table_arn" {
6
+ value = var.create_dynamodb_table ? aws_dynamodb_table.table[0].arn : null
7
+ }
8
+
9
+ output "function_url" {
10
+ value = (var.deploy_rack && var.enable_function_url) ? aws_lambda_function_url.rack[0].function_url : null
11
+ }
12
+
13
+ output "rack_function_arn" {
14
+ value = var.deploy_rack ? aws_lambda_function.rack[0].arn : null
15
+ }
16
+
17
+ output "secrets_rotation_function_arn" {
18
+ value = var.deploy_secrets_rotation ? aws_lambda_function.secrets_rotation[0].arn : null
19
+ }
@@ -0,0 +1,65 @@
1
+ variable "iam_role_arn" {
2
+ type = string
3
+ description = "IAM role arn for functions"
4
+ }
5
+
6
+ variable "image_url" {
7
+ type = string
8
+ description = "Image url for deploy"
9
+ }
10
+
11
+ variable "dynamodb_table_name" {
12
+ type = string
13
+ description = "dynamodb table name to use"
14
+ }
15
+
16
+ variable "create_dynamodb_table" {
17
+ type = bool
18
+ description = "Create dynamodb table"
19
+ default = true
20
+ }
21
+
22
+ variable "function_name_prefix" {
23
+ type = string
24
+ description = "function name prefix"
25
+ }
26
+
27
+ variable "deploy_rack" {
28
+ type = bool
29
+ description = "Deploy rack function"
30
+ default = true
31
+ }
32
+
33
+ variable "rack_memory_size" {
34
+ type = number
35
+ default = 256
36
+ }
37
+
38
+ variable "deploy_secrets_rotation" {
39
+ type = bool
40
+ description = "Deploy secrets rotation function"
41
+ default = true
42
+ }
43
+
44
+ variable "enable_function_url" {
45
+ type = bool
46
+ description = "Enable function URL"
47
+ default = true
48
+ }
49
+
50
+ variable "config_ru" {
51
+ type = string
52
+ description = "File content of config.ru"
53
+ default = "raise 'empty config_ru'\n"
54
+ }
55
+
56
+ variable "environment" {
57
+ type = map(any)
58
+ description = "Additional environment variables"
59
+ default = {}
60
+ }
61
+
62
+ variable "architectures" {
63
+ type = list(string)
64
+ default = ["x86_64"]
65
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,2 @@
1
+ data "aws_region" "current" {}
2
+ data "aws_caller_identity" "current" {}
@@ -0,0 +1,3 @@
1
+ output "role_arn" {
2
+ value = aws_iam_role.role.arn
3
+ }
@@ -0,0 +1,77 @@
1
+ resource "aws_iam_role" "role" {
2
+ name = var.role_name
3
+ description = var.role_description
4
+ assume_role_policy = data.aws_iam_policy_document.role-trust.json
5
+ permissions_boundary = var.role_permissions_boundary
6
+ }
7
+
8
+ data "aws_iam_policy_document" "role-trust" {
9
+ statement {
10
+ effect = "Allow"
11
+ actions = ["sts:AssumeRole"]
12
+ principals {
13
+ type = "Service"
14
+ identifiers = [
15
+ "lambda.amazonaws.com"
16
+ ]
17
+ }
18
+ }
19
+ }
20
+
21
+ resource "aws_iam_role_policy_attachment" "role-AWSLambdaBasicExecutionRole" {
22
+ role = aws_iam_role.role.name
23
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
24
+ }
25
+
26
+ resource "aws_iam_role_policy" "role-dynamodb" {
27
+ count = local.dynamodb_table_arn != null ? 1 : 0
28
+ role = aws_iam_role.role.name
29
+ policy = data.aws_iam_policy_document.role-dynamodb.json
30
+ }
31
+
32
+ data "aws_iam_policy_document" "role-dynamodb" {
33
+ statement {
34
+ effect = "Allow"
35
+ actions = [
36
+ "dynamodb:DeleteItem",
37
+ "dynamodb:Query",
38
+ "dynamodb:UpdateItem",
39
+ ]
40
+ resources = [local.dynamodb_table_arn]
41
+ }
42
+ }
43
+
44
+ resource "aws_iam_role_policy" "role-secretsmanager" {
45
+ count = length(var.secret_arns) > 0 ? 1 : 0
46
+ role = aws_iam_role.role.name
47
+ policy = data.aws_iam_policy_document.role-secretsmanager.json
48
+ }
49
+
50
+ data "aws_iam_policy_document" "role-secretsmanager" {
51
+ statement {
52
+ effect = "Allow"
53
+ actions = [
54
+ "secretsmanager:DescribeSecret",
55
+ "secretsmanager:GetSecretValue",
56
+
57
+ ]
58
+ resources = toset(var.secret_arns)
59
+ }
60
+ statement {
61
+ effect = "Allow"
62
+ actions = [
63
+ "secretsmanager:PutSecretValue",
64
+ "secretsmanager:UpdateSecretVersionStage",
65
+ ]
66
+ dynamic "condition" {
67
+ for_each = var.secrets_rotation_function_arn != null ? { hardening = true } : {}
68
+ content {
69
+ test = "StringEquals"
70
+ variable = "lambda:SourceFunctionArn"
71
+ values = [var.secrets_rotation_function_arn]
72
+ }
73
+ }
74
+ resources = toset(var.secret_arns)
75
+ }
76
+
77
+ }
@@ -0,0 +1,44 @@
1
+ variable "role_name" {
2
+ type = string
3
+ description = "IAM Role name to create"
4
+ }
5
+
6
+ variable "role_description" {
7
+ type = string
8
+ description = "IAM Role description to specify"
9
+ default = "sorah/himari lambda function role"
10
+ }
11
+
12
+ variable "role_permissions_boundary" {
13
+ type = string
14
+ description = "IAM Role permissions boundary to specify"
15
+ default = null
16
+ }
17
+
18
+ variable "dynamodb_table_arn" {
19
+ type = string
20
+ description = "DynamoDB Table ARN"
21
+ default = null
22
+ }
23
+
24
+ variable "dynamodb_table_name" {
25
+ type = string
26
+ description = "DynamoDB Table name"
27
+ default = null
28
+ }
29
+
30
+ variable "secret_arns" {
31
+ type = set(string)
32
+ description = "Secrets Manager secret ARNs"
33
+ default = null
34
+ }
35
+
36
+ variable "secrets_rotation_function_arn" {
37
+ type = string
38
+ description = "ARN of rotation function. If set, it will be used to harden the write action policy"
39
+ default = null
40
+ }
41
+
42
+ locals {
43
+ dynamodb_table_arn = coalesce(var.dynamodb_table_arn, var.dynamodb_table_name != null ? "arn:aws:dynamodb:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/${var.dynamodb_table_name}" : null)
44
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ data "aws_region" "current" {}
@@ -0,0 +1,5 @@
1
+ #!/bin/bash -xe
2
+ aws ecr get-login-password | docker login --username AWS --password-stdin "${REPOSITORY_URL}"
3
+ docker pull "public.ecr.aws/sorah/himari-lambda:${SOURCE_IMAGE_TAG}"
4
+ docker tag "public.ecr.aws/sorah/himari-lambda:${SOURCE_IMAGE_TAG}" "${REPOSITORY_URL}:${SOURCE_IMAGE_TAG}"
5
+ docker push "${REPOSITORY_URL}:${SOURCE_IMAGE_TAG}"
@@ -0,0 +1,17 @@
1
+ resource "null_resource" "copy-image" {
2
+ triggers = {
3
+ region = data.aws_region.current.name
4
+ repository_url = aws_ecr_repository.repo.repository_url
5
+ source_image_tag = var.source_image_tag
6
+ }
7
+ provisioner "local-exec" {
8
+ command = "cd ${path.module} && ./copy.sh"
9
+ environment = {
10
+ AWS_REGION = data.aws_region.current.name
11
+ AWS_DEFAULT_REGION = data.aws_region.current.name
12
+
13
+ REPOSITORY_URL = aws_ecr_repository.repo.repository_url
14
+ SOURCE_IMAGE_TAG = var.source_image_tag
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,42 @@
1
+ resource "aws_ecr_repository" "repo" {
2
+ name = var.repository_name
3
+ }
4
+
5
+ resource "aws_ecr_repository_policy" "repo-lambda" {
6
+ repository = aws_ecr_repository.repo.name
7
+ policy = data.aws_iam_policy_document.repo-lambda.json
8
+ }
9
+
10
+ data "aws_iam_policy_document" "repo-lambda" {
11
+ statement {
12
+ effect = "Allow"
13
+ principals {
14
+ type = "Service"
15
+ identifiers = ["lambda.amazonaws.com"]
16
+ }
17
+ actions = [
18
+ "ecr:BatchGetImage",
19
+ "ecr:GetDownloadUrlForLayer"
20
+ ]
21
+ }
22
+ }
23
+
24
+ resource "aws_ecr_lifecycle_policy" "repo" {
25
+ repository = aws_ecr_repository.repo.name
26
+ policy = jsonencode({
27
+ rules = [
28
+ {
29
+ rulePriority = 10
30
+ description = "expire old images"
31
+ selection = {
32
+ tagStatus = "any"
33
+ countType = "imageCountMoreThan"
34
+ countNumber = 10
35
+ }
36
+ action = {
37
+ type = "expire"
38
+ }
39
+ }
40
+ ]
41
+ })
42
+ }
@@ -0,0 +1,9 @@
1
+ output "image" {
2
+ value = {
3
+ url = "${aws_ecr_repository.repo.repository_url}:${var.source_image_tag}"
4
+
5
+ repository_url = aws_ecr_repository.repo.repository_url
6
+ repository_arn = aws_ecr_repository.repo.arn
7
+ }
8
+ depends_on = [null_resource.copy-image]
9
+ }
@@ -0,0 +1,9 @@
1
+ variable "repository_name" {
2
+ type = string
3
+ description = "Repository name to create on your AWS account"
4
+ }
5
+
6
+ variable "source_image_tag" {
7
+ type = string
8
+ description = "Image tag for public.ecr.aws/sorah/himari-lambda. You can use Git commit hash on https://github.com/sorah/himari"
9
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ data "aws_region" "current" {}
@@ -0,0 +1,3 @@
1
+ output "secret_arn" {
2
+ value = aws_secretsmanager_secret.signing_key.arn
3
+ }
@@ -0,0 +1,18 @@
1
+ resource "aws_secretsmanager_secret" "signing_key" {
2
+ name = var.secret_name
3
+
4
+ tags = {
5
+ HimariKey = base64encode(jsonencode(var.keygen_params))
6
+ }
7
+ }
8
+
9
+ resource "aws_secretsmanager_secret_rotation" "signing_key" {
10
+ secret_id = aws_secretsmanager_secret.signing_key.id
11
+ rotation_lambda_arn = var.rotation_function_arn
12
+
13
+ # XXX: https://github.com/hashicorp/terraform-provider-aws/issues/22969
14
+ rotation_rules {
15
+ automatically_after_days = 16
16
+ }
17
+
18
+ }
@@ -0,0 +1,24 @@
1
+ variable "secret_name" {
2
+ type = string
3
+ description = "Secret name to create"
4
+ }
5
+
6
+ variable "rotation_function_arn" {
7
+ type = string
8
+ description = "Lambda function ARN to handle secret rotation"
9
+ }
10
+
11
+ variable "rotate_automatically_after_days" {
12
+ type = number
13
+ description = "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_rotation#automatically_after_days"
14
+ default = 16
15
+ }
16
+
17
+ variable "keygen_params" {
18
+ type = object({ kty = string, len = string })
19
+ description = "keygen params"
20
+ default = {
21
+ "kty" = "rsa"
22
+ "len" = 2048
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,72 @@
1
+ require 'himari'
2
+ require 'himari/aws/secretsmanager_signing_key_rotation_handler'
3
+
4
+ require 'digest/sha2'
5
+ require 'aws-sdk-dynamodb'
6
+ require 'apigatewayv2_rack'
7
+
8
+ $stdout.sync = true
9
+
10
+ module Himari
11
+ module Aws
12
+ module LambdaHandler
13
+ def self.app
14
+ @app ||= make_app()
15
+ end
16
+
17
+ def self.config_ru
18
+ a = Time.now
19
+ retval = config_ru_from_task_root || config_ru_from_dynamodb
20
+ b = Time.now
21
+ $stdout.puts(JSON.generate(config_ru: {ts: b, elapsed_time: b-a}))
22
+ retval
23
+ end
24
+
25
+ def self.config_ru_from_task_root
26
+ return nil unless ENV['LAMBDA_TASK_ROOT']
27
+ File.read(File.join(ENV['LAMBDA_TASK_ROOT'], 'config.ru'))
28
+ rescue Errno::ENOENT, Errno::EPERM
29
+ nil
30
+ end
31
+
32
+ def self.config_ru_from_dynamodb
33
+ dgst = ENV.fetch('HIMARI_RACK_DIGEST')
34
+ table_name = ENV.fetch('HIMARI_RACK_DYNAMODB_TABLE')
35
+ pk, sk = "rack", "rack:#{dgst}"
36
+
37
+ ddb = ::Aws::DynamoDB::Client.new()
38
+ item = ddb.query(
39
+ table_name: table_name,
40
+ select: 'ALL_ATTRIBUTES',
41
+ limit: 1,
42
+ key_condition_expression: 'pk = :pk AND sk = :sk',
43
+ expression_attribute_values: {":pk" => pk, ":sk" => sk},
44
+ ).items.first
45
+
46
+ unless item
47
+ raise "item not found (pk=#{pk.inspect}, sk=#{sk.inspect}) on dynamodb table #{table_name} for config.ru"
48
+ end
49
+
50
+ content = item.fetch('file')
51
+ content_dgst = Digest::SHA256.digest(content)
52
+ raise "config.ru item content digest mismatch" if content_dgst != Base64.decode64(dgst)
53
+
54
+ content
55
+ end
56
+
57
+ def self.make_app
58
+ require 'rack'
59
+ require 'rack/builder'
60
+ Rack::Builder.new_from_string(config_ru)
61
+ end
62
+
63
+ def self.rack_handler(event:, context:)
64
+ Apigatewayv2Rack.handle_request(event: event, context: context, app: app)
65
+ end
66
+
67
+ def self.secrets_rotation_handler(event:, context:)
68
+ Himari::Aws::SecretsmanagerSigningKeyRotationHandler.handler(event: event, context: context)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -71,7 +71,8 @@ module Himari
71
71
  end
72
72
 
73
73
  def self.generate_secret(req, _current)
74
- param = JSON.parse(req.secret.tags.find { |t| t.name == ENV.fetch('HIMARI_KEYGEN_PARAM_TAG_KEY', 'HimariKey') }&.value || ENV.fetch('HIMARI_KEYGEN_PARAM_DEFAULT', '{"kty": "rsa", "len": 2048}'), symbolize_names: true)
74
+ param_raw = req.secret.tags&.find { |t| t.key == ENV.fetch('HIMARI_KEYGEN_PARAM_TAG_KEY', 'HimariKey') }&.value || ENV.fetch('HIMARI_KEYGEN_PARAM_DEFAULT', '{"kty": "rsa", "len": 2048}')
75
+ param = parse_keygen_param(param_raw)
75
76
  puts "createSecret: generate_secret with #{param.inspect}"
76
77
 
77
78
  case param.fetch(:kty, 'rsa').downcase
@@ -93,6 +94,27 @@ module Himari
93
94
  end
94
95
  end
95
96
 
97
+ # Scan k=v,k2=v2
98
+ def self.parse_keygen_param(str)
99
+ begin
100
+ ary = str.scan(/(.+?)=(.+?)(?:,|$)/)
101
+ unless ary.empty?
102
+ return ary.to_h.transform_keys(&:to_sym)
103
+ end
104
+ end
105
+
106
+ if str.start_with?('eyJ')
107
+ return JSON.parse(Base64.decode64(str), symbolize_names: true)
108
+ end
109
+
110
+ begin
111
+ return JSON.parse(str, symbolize_names: true)
112
+ rescue JSON::ParserError
113
+ end
114
+
115
+ raise "cannot parse keygen param #{str.inspect}"
116
+ end
117
+
96
118
  def self.set_secret(req)
97
119
  _check = @secretsmanager.get_secret_value(secret_id: req.id, version_id: req.token, version_stage: 'AWSPENDING')
98
120
  puts "setSecret: do nothing for #{req.token} @ #{req.id}"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Himari
4
4
  module Aws
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: himari-aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sorah Fukumori
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-20 00:00:00.000000000 Z
11
+ date: 2023-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: himari
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: apigatewayv2_rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description:
56
70
  email:
57
71
  - her@sorah.jp
@@ -60,14 +74,43 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - ".rspec"
63
- - Gemfile
64
- - Gemfile.lock
65
77
  - LICENSE.txt
66
78
  - README.md
67
79
  - Rakefile
80
+ - lambda/Dockerfile
81
+ - lambda/Gemfile
82
+ - lambda/Gemfile.lock
83
+ - lambda/README.md
84
+ - lambda/entrypoint.rb
85
+ - lambda/terraform/README.md
86
+ - lambda/terraform/functions/aws.tf
87
+ - lambda/terraform/functions/dynamodb.tf
88
+ - lambda/terraform/functions/lambda_rack.tf
89
+ - lambda/terraform/functions/lambda_secrets_rotation.tf
90
+ - lambda/terraform/functions/outputs.tf
91
+ - lambda/terraform/functions/variables.tf
92
+ - lambda/terraform/functions/versions.tf
93
+ - lambda/terraform/iam/aws.tf
94
+ - lambda/terraform/iam/outputs.tf
95
+ - lambda/terraform/iam/role.tf
96
+ - lambda/terraform/iam/variables.tf
97
+ - lambda/terraform/iam/versions.tf
98
+ - lambda/terraform/image/aws.tf
99
+ - lambda/terraform/image/copy.sh
100
+ - lambda/terraform/image/copy.tf
101
+ - lambda/terraform/image/ecr.tf
102
+ - lambda/terraform/image/outputs.tf
103
+ - lambda/terraform/image/variables.tf
104
+ - lambda/terraform/image/versions.tf
105
+ - lambda/terraform/signing_key/aws.tf
106
+ - lambda/terraform/signing_key/outputs.tf
107
+ - lambda/terraform/signing_key/secret.tf
108
+ - lambda/terraform/signing_key/variables.tf
109
+ - lambda/terraform/signing_key/versions.tf
68
110
  - lib/himari-aws.rb
69
111
  - lib/himari/aws.rb
70
112
  - lib/himari/aws/dynamodb_storage.rb
113
+ - lib/himari/aws/lambda_handler.rb
71
114
  - lib/himari/aws/secretsmanager_signing_key_provider.rb
72
115
  - lib/himari/aws/secretsmanager_signing_key_rotation_handler.rb
73
116
  - lib/himari/aws/version.rb
@@ -93,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
136
  - !ruby/object:Gem::Version
94
137
  version: '0'
95
138
  requirements: []
96
- rubygems_version: 3.4.0.dev
139
+ rubygems_version: 3.1.6
97
140
  signing_key:
98
141
  specification_version: 4
99
142
  summary: AWS related plugins for Himari
data/Gemfile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- gemspec path: '../himari'
6
- # Specify your gem's dependencies in himari-aws.gemspec
7
- gemspec
8
-
9
- gem 'nokogiri'
10
-
11
- gem "rake", "~> 13.0"
12
- gem "rspec", "~> 3.0"