Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔐 Marketplace: Encrypt Order#delivery_address! #1169

Merged
merged 2 commits into from
Mar 3, 2023

Conversation

zspencer
Copy link
Member

@zspencer zspencer commented Mar 2, 2023

So, I totally didn't think about how delivery addresses are PII and probably should not be stored in plaintext! Womp. Womp. Womp.

Now they ain't!

We'll want to delete the release:after_build bits after a prod deploy.

@zspencer zspencer added 🔐 security Relates to security vulnerabilities 🧹 refactor Includes non-behavioral changes labels Mar 2, 2023
@zspencer zspencer requested review from a team, anaulin, daltonrpruitt and KellyAH March 2, 2023 20:35
@zspencer zspencer force-pushed the marketplace/collect-delivery-address-on-cart branch from 267d6f8 to 4ef019d Compare March 2, 2023 20:38
@zspencer zspencer changed the title 🔐 Marketplace: Encrypt delivery addresses! 🔐 Marketplace: Encrypt Order#delivery_address! Mar 2, 2023
@KellyAH
Copy link
Contributor

KellyAH commented Mar 3, 2023

We'll want to delete the release:after_build bits after a prod deploy.

why? because that rake task is only temporarily needed to migrate the old prod data? And we don't need to keep it around because it won't ever be reused... right?

@KellyAH
Copy link
Contributor

KellyAH commented Mar 3, 2023

Aren't we also storing the contact person's email address too after every stripe order... is that PII (personal identifiable information) too that needs to be encrypted?

class MarketplaceEncryptOrderDeliveryAddress < ActiveRecord::Migration[7.0]
def change
rename_column :marketplace_orders, :delivery_address, :deprecated_delivery_address
add_column :marketplace_orders, :delivery_address_ciphertext, :text
Copy link
Contributor

@KellyAH KellyAH Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lockbox gem says it's possible to encrypt the existing column here.... but maybe it's statement is deceptive. It's steps looks like you'd still need to create a new column for encrypted data. migrate the data, and drop the column of unencrypted data. 🙄

Copy link
Member Author

@zspencer zspencer Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the migrating syntax is neat! I didn't realize it existed; but yea, that would save us the rename_column step and having to write the find_each!

It's also likely far safer in high-throughput cases; because you would still be able to access the delivery_address while it's being migrated; where as with this there is a moment in time where delivery_address is nil until the data migration completes.

I'll definitely do it next time!

next unless order.deprecated_delivery_address.present?

order.update(delivery_address: order.deprecated_delivery_address, deprecated_delivery_address: nil)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.. this is the prod data migration.....

So.. I assume this rake task runs BEFORE the delivery_address column is renamed in 20230302202459_marketplace_encrypt_order_delivery_address.rb

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, let me step ya through the Heroku deploy process:

  1. Heroku checks out the git repository, and starts a build which creates a new image and installs gems, node packages, etc.
  2. Heroku launches a release container using the new image, and runs the release command defined in the Procfile, which runs the rails db:migrate and release:after_build` tasks in sequence
  3. Launches new web and worker containers using the new image.
  4. Begins routing traffic to the new web containers
  5. Stops routing traffic to the old web containers
  6. Shuts down the old web and worker containers.

So the database has the new columns prior to running the rake task, and before deploying new web and worker containers. this means that the existing web and worker containers will still be running the code which references delivery_address, which could result in sql query errors. We could install strong_migrations to catch risky operations (like renames); but in this particular case I felt like it was safe enough given our traffic.

That said, there's no reason not to use the Lockbox.migrate strategy; which eliminates the risk and seems pretty dang cool!

Copy link
Contributor

@KellyAH KellyAH Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created issue #1177 to install strong_migrations.

My work team uses it and it is really handy.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah!!!!

@@ -11,7 +11,7 @@ class Order < Record
has_many :ordered_products, inverse_of: :order, foreign_key: :cart_id
has_many :products, through: :ordered_products, inverse_of: :orders

attribute :delivery_address, :string
has_encrypted :delivery_address
Copy link
Contributor

@KellyAH KellyAH Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the order of operations for everything this code change does?

Seems like in this change...

  1. :delivery_address is being renamed to deprecated_delivery_address
  2. data in deprecated_delivery_address is migrated to delivery_address_ciphertext
  3. data in deprecated_delivery_address is replaced with nil

And in later PR... I assume this happens?:
4. deprecated_delivery_address is dropped.
5. delivery_address_ciphertext is renamed delivery_address so has_encrypted :delivery_address in Order model still works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes except step 5 never happens; because the Lockbox infers that delivery_address_ciphertext is the database name for the encrypted delivery_address attribute.

@zspencer
Copy link
Member Author

zspencer commented Mar 3, 2023

We'll want to delete the release:after_build bits after a prod deploy.

why? because that rake task is only temporarily needed to migrate the old prod data? And we don't need to keep it around because it won't ever be reused... right?

Yep!

Aren't we also storing the contact person's email address too after every stripe order... is that PII (personal identifiable information) too that needs to be encrypted?

Good catch. This is part of why we have the AuthenticationMethod table, which should have encrypt the contact_location field and give it a blind_index. I don't think I want to bundle that into this PR; but I may wind up making a second one!

zspencer added 2 commits March 3, 2023 12:09
- #1136
- #831

So, I totally didn't think about how delivery addresses are PII and
probably should not be stored in plaintext! Womp. Womp. Womp.

Now they ain't!

We'll want to delete the `release:after_build` bits after a prod deploy.
@zspencer zspencer force-pushed the marketplace/collect-delivery-address-on-cart branch from 4ef019d to 2fdd8a3 Compare March 3, 2023 20:13
@zspencer zspencer requested a review from KellyAH March 3, 2023 20:14
@zspencer
Copy link
Member Author

zspencer commented Mar 3, 2023

@KellyAH - I swapped to Lockbox.migrate since it was pretty straightforward, and gives us an example of doing it "the safer way" for future.

Copy link
Contributor

@KellyAH KellyAH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚢

@zspencer zspencer merged commit aec3c30 into main Mar 3, 2023
@zspencer zspencer deleted the marketplace/collect-delivery-address-on-cart branch March 3, 2023 20:31
zspencer added a commit that referenced this pull request Mar 3, 2023
* 🔐 `Marketplace`: Step 2 of `Lockbox` migration

- #831
- #1136

Merge and deploy immediately after #1169
@zspencer zspencer removed the 🧹 refactor Includes non-behavioral changes label Mar 3, 2023
@zspencer zspencer added this to the 1.0 - Andromeda milestone May 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔐 security Relates to security vulnerabilities
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants