-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c9f0de4
Showing
9 changed files
with
407 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.bundle | ||
vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
2.3.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
# A sample Gemfile | ||
source "https://rubygems.org" | ||
|
||
# gem "rails" | ||
gem "sinatra" | ||
gem "google-api-client" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
addressable (2.5.1) | ||
public_suffix (~> 2.0, >= 2.0.2) | ||
declarative (0.0.9) | ||
declarative-option (0.1.0) | ||
faraday (0.12.1) | ||
multipart-post (>= 1.2, < 3) | ||
google-api-client (0.11.2) | ||
addressable (>= 2.5.1) | ||
googleauth (~> 0.5) | ||
httpclient (>= 2.8.1, < 3.0) | ||
mime-types (>= 3.0) | ||
representable (~> 3.0) | ||
retriable (>= 2.0, < 4.0) | ||
googleauth (0.5.1) | ||
faraday (~> 0.9) | ||
jwt (~> 1.4) | ||
logging (~> 2.0) | ||
memoist (~> 0.12) | ||
multi_json (~> 1.11) | ||
os (~> 0.9) | ||
signet (~> 0.7) | ||
httpclient (2.8.3) | ||
jwt (1.5.6) | ||
little-plugger (1.1.4) | ||
logging (2.2.2) | ||
little-plugger (~> 1.1) | ||
multi_json (~> 1.10) | ||
memoist (0.15.0) | ||
mime-types (3.1) | ||
mime-types-data (~> 3.2015) | ||
mime-types-data (3.2016.0521) | ||
multi_json (1.12.1) | ||
multipart-post (2.0.0) | ||
mustermann (1.0.0) | ||
os (0.9.6) | ||
public_suffix (2.0.5) | ||
rack (2.0.3) | ||
rack-protection (2.0.0) | ||
rack | ||
representable (3.0.4) | ||
declarative (< 0.1.0) | ||
declarative-option (< 0.2.0) | ||
uber (< 0.2.0) | ||
retriable (3.0.2) | ||
signet (0.7.3) | ||
addressable (~> 2.3) | ||
faraday (~> 0.9) | ||
jwt (~> 1.5) | ||
multi_json (~> 1.10) | ||
sinatra (2.0.0) | ||
mustermann (~> 1.0) | ||
rack (~> 2.0) | ||
rack-protection (= 2.0.0) | ||
tilt (~> 2.0) | ||
tilt (2.0.7) | ||
uber (0.1.0) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
google-api-client | ||
sinatra | ||
|
||
BUNDLED WITH | ||
1.14.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2017 Andy Geers. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
## How do you encrypt a Firebase database? | ||
|
||
I've written a blog post [here](http://www.geero.net/2017/05/how-to-encrypt-a-google-firebase-realtime-database/) and this is the backend auth service described there. | ||
|
||
Firebase Keysafe is a super-simple back end service designed to be deployed to Google App Engine Flexible Environment and Cloud Endpoints, to protect the encryption keys of mobile users authenticated using Google Firebase | ||
by means of Google Cloud KMS. | ||
|
||
To configure: | ||
|
||
1. Make sure you edit openapi.yaml and replace <YOUR_APPENGINE_APP_ID_HERE> with the name of your App Engine app, and <YOUR_FIREBASE_PROJECT_ID> with the Project ID that houses your Firebase Auth. | ||
2. Do the same in app.yaml | ||
3. Plug in values for <USE_A_SECURE_RANDOM_PASSWORD_HERE>, <KMS_KEYRING_NAME> and <KMS_KEY_ID> in app.rb | ||
3. Deploy the configuration to Google Cloud Endpoints: | ||
|
||
gcloud service-management deploy openapi.yaml | ||
|
||
4. You will then be given a config_id that you can plug in to app.yaml. | ||
5. Deploy to App Engine: | ||
|
||
bundle install | ||
gcloud app deploy | ||
|
||
To run in development mode: | ||
|
||
bundle install | ||
bundle exec ruby app.rb -p 8080 | ||
|
||
(caveat: I couldn't actually get my local development machine to work properly with Cloud KMS - I always got permission denied errors.) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
# Copyright 2017 Andy Geers. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to deal | ||
# in the Software without restriction, including without limitation the rights | ||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
# copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. | ||
|
||
# [START app] | ||
require "sinatra" | ||
require "google/apis/cloudkms_v1" | ||
require "openssl" | ||
|
||
# Your Google Cloud Platform project ID | ||
project_id = "prayermate-auth-service" | ||
|
||
# Lists keys in the "global" location. | ||
location = "global" | ||
|
||
# Instantiate the client | ||
Cloudkms = Google::Apis::CloudkmsV1 # Alias the module | ||
kms_client = Cloudkms::CloudKMSService.new | ||
|
||
# Set the required scopes to access the Key Management Service API | ||
# @see https://developers.google.com/identity/protocols/application-default-credentials#callingruby | ||
kms_client.authorization = Google::Auth.get_application_default( | ||
"https://www.googleapis.com/auth/cloud-platform" | ||
) | ||
|
||
parent = "projects/#{project_id}/locations/#{location}" | ||
|
||
keyring_name = "<KMS_KEYRING_NAME>" | ||
key_id = "<KMS_KEY_ID>" | ||
|
||
# The resource name of the location associated with the Key rings | ||
key_name = "#{parent}/keyRings/#{keyring_name}/cryptoKeys/#{key_id}" | ||
|
||
class AuthorizationException < Exception; end | ||
|
||
def auth_info | ||
# This will only be defined when in App Engine production and if Cloud Endpoints is configured correctly | ||
encoded_info = request.env["HTTP_X_ENDPOINT_API_USERINFO"] | ||
|
||
if encoded_info | ||
info_json = Base64.decode64 encoded_info | ||
user_info = JSON.parse info_json | ||
|
||
raise AuthorizationException if user_info['id'].nil? || user_info['id'].length == 0 | ||
|
||
return user_info | ||
else | ||
raise AuthorizationException | ||
end | ||
end | ||
|
||
post "/key" do | ||
content_type 'application/json' | ||
|
||
begin | ||
# Generate a random key | ||
pass = "<USE_A_SECURE_RANDOM_PASSWORD_HERE>" | ||
salt = OpenSSL::Random.random_bytes(16) | ||
iter = 20000 | ||
key_len = 16 | ||
|
||
auth = auth_info | ||
user_id = auth['id'] | ||
|
||
raw_key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len) | ||
|
||
# Request list of key rings | ||
encrypt_request_object = Google::Apis::CloudkmsV1::EncryptRequest.from_json({ | ||
"plaintext": Base64.urlsafe_encode64(user_id + "|" + Base64.urlsafe_encode64(raw_key).sub(/==\n?$/, "")) | ||
}.to_json) | ||
response = kms_client.encrypt_crypto_key(key_name, encrypt_request_object) | ||
|
||
{ | ||
"key": Base64.urlsafe_encode64(raw_key).sub(/==\n?$/, ""), | ||
"encrypted": Base64.urlsafe_encode64(response.ciphertext).sub(/==\n?$/, "") | ||
}.to_json | ||
|
||
rescue AuthorizationException => e | ||
status 401 | ||
return { | ||
"success": false, | ||
"error": "Not authorised" | ||
}.to_json | ||
|
||
rescue => e | ||
|
||
error = nil | ||
|
||
begin | ||
error = { | ||
"body": e.body, | ||
"header": e.header, | ||
"status_code": e.status_code | ||
} | ||
rescue => e2 | ||
error = e | ||
end | ||
|
||
return { | ||
"success": false, | ||
"error": error | ||
}.to_json | ||
end | ||
|
||
#Google::Apis::CloudkmsV1::EncryptResponse | ||
|
||
|
||
end | ||
|
||
get "/decrypt" do | ||
content_type 'application/json' | ||
|
||
input = params[:value] | ||
|
||
begin | ||
auth = auth_info | ||
user_id = auth['id'] | ||
|
||
# Request list of key rings | ||
decrypt_request_object = Google::Apis::CloudkmsV1::DecryptRequest.from_json({ | ||
"ciphertext": input | ||
}.to_json) | ||
response = kms_client.decrypt_crypto_key(key_name, decrypt_request_object) | ||
|
||
components = response.plaintext.split("|", 2) | ||
|
||
unless components.first == user_id | ||
$stderr.puts "Auth failure comparing user IDs #{components.first} with #{user_id}" | ||
raise AuthorizationException | ||
end | ||
|
||
{ | ||
"key": components.last.sub(/==\n?$/, "") | ||
}.to_json | ||
|
||
rescue AuthorizationException => e | ||
status 401 | ||
return { | ||
"success": false, | ||
"error": "Not authorised" | ||
}.to_json | ||
|
||
rescue => e | ||
return { | ||
"success": false, | ||
"input": input, | ||
"error": { | ||
"body": e.body, | ||
"header": e.header, | ||
"status_code": e.status_code | ||
} | ||
}.to_json | ||
end | ||
end | ||
|
||
get "/_ah/health" do | ||
{ "success": true }.to_json | ||
end | ||
# [END app] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
entrypoint: bundle exec ruby app.rb | ||
env: flex | ||
runtime: ruby | ||
endpoints_api_service: | ||
name: <YOUR_APPENGINE_APP_ID_HERE>.appspot.com | ||
config_id: 2017-01-01r0 |
Oops, something went wrong.