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

Create RDS database snapshot before executing alembic migrations #1267

Merged
merged 7 commits into from
May 16, 2024

Conversation

dlpzx
Copy link
Contributor

@dlpzx dlpzx commented May 14, 2024

Feature or Bugfix

  • Feature

Detail

Alembic migrations can get complex and in some cases we are using alembic for not only schema migrations but also data migrations. When moving columns with data from one table to another we might accidentally make a mistake in a migration script. We strive to test all migration scripts and avoid bugs in such sensitive operations, but to protect users from the catastrophic situation in which there is a bug, a service issue or any other exceptional situation this PR introduces the creation of manual database snapshots before running alembic migration scripts.

This PR modifies the db_migration handler that is triggered with every backendStack update. It checks if there are new migration scripts (if the current head in the database is different from the new head in the code). If True, it will create a cluster snapshot.

Remarks:

  • Snapshots cannot be created when the cluster in not available, the PR introduces a check to wait for this condition. If the Lambda timeout is reached waiting for the cluster, then the CICD pipeline will fail and will need to be retried
  • During the creation of an snapshot we can still run alembic migration scripts
  • Snapshots are incremental, the first time will take a long time, but new snapshots will be faster

Relates

Security

Please answer the questions below briefly where applicable, or write N/A. Based on
OWASP 10.

  • Does this PR introduce or modify any input fields or queries - this includes
    fetching data from storage outside the application (e.g. a database, an S3 bucket)?
    • Is the input sanitized?
    • What precautions are you taking before deserializing the data you consume?
    • Is injection prevented by parametrizing queries?
    • Have you ensured no eval or similar functions are used?
  • Does this PR introduce any functionality or component that requires authorization?
    • How have you ensured it respects the existing AuthN/AuthZ mechanisms?
    • Are you logging failed auth attempts?
  • Are you using or adding any cryptographic features?
    • Do you use a standard proven implementations?
    • Are the used keys controlled by the customer? Where are they stored?
  • Are you introducing any new policies/roles/users?
    • Have you used the least-privilege principle? How?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@dlpzx dlpzx requested a review from petrkalos May 14, 2024 12:35
@dlpzx dlpzx marked this pull request as ready for review May 14, 2024 13:26
@dlpzx
Copy link
Contributor Author

dlpzx commented May 14, 2024

⚠️ I need to test it in AWS!

@dlpzx
Copy link
Contributor Author

dlpzx commented May 15, 2024

Tested in AWS!

  • backend stack gets updated with new IAM policies for the custom resource execution role
  • If no new migration script is found, then no snapshot is created
  • If new migration scripts need to be run, an snapshot is created

backend/dbmigrations_handler.py Outdated Show resolved Hide resolved
backend/dbmigrations_handler.py Outdated Show resolved Hide resolved
backend/dbmigrations_handler.py Outdated Show resolved Hide resolved
backend/dbmigrations_handler.py Outdated Show resolved Hide resolved
@dlpzx dlpzx requested a review from petrkalos May 15, 2024 12:41
dlpzx added 3 commits May 15, 2024 15:23
…lembic' into feat/create-db-snapshot-before-alembic

# Conflicts:
#	deploy/stacks/backend_stack.py
@dlpzx dlpzx merged commit ee53816 into main May 16, 2024
10 checks passed
dlpzx added a commit that referenced this pull request May 17, 2024
…te DatasetBase db model and S3Dataset model) (#1258)

### Feature or Bugfix
⚠️ This PR should be merged after #1257.
- Feature
- Refactoring

### Detail
As explained in the design for #1123 we are trying to implement a
generic `datasets_base` module that can be used by any type of datasets
in a generic way.

**This PR does**:
- Adds a generic `DatasetBase` model in datasets_base.db that is used in
s3_datasets.db to build the `S3Dataset` model using joined table
inheritance in
[sqlalchemy](https://docs.sqlalchemy.org/en/20/orm/inheritance.html)
- Rename all usages of Dataset to S3Dataset (in the future some will be
returned to DatasetBase, but for the moment we will keep them as
S3Dataset)
- Add migration script that backfills `datasets` table and renames
`s3_datasets` ---> ⚠️ In the process of migrating we are doing some
"scary" operations on the dataset table, if for any reason the migration
encounters any issue it could result in catastrophic loss of information
--> for this reason this
[PR](#1267) implements RDS
snapshots on migrations.

**This PR does not**:
- Feed registration stays as:
`FeedRegistry.register(FeedDefinition('Dataset', S3Dataset))` using
`Dataset` with the `S3Dataset` resource type. It is out of the scope of
this PR to migrate the Feed definition.
- Exactly the same for the GlossaryRegistry registration. We keep
`object_type='Dataset'` to avoid backwards compatibility issues.
- It does not change the resourceType for permissions. We keep using a
generic `Dataset` as target for S3 permissions. If we are to split
permissions into DatasetBase permissions and S3Dataset permissions we
would do it on a different PR

#### Remarks
Inserting new items of S3Dataset does not require any changes. SQL
Alchemy joined inheritance automatically inserts data in the parent
table and then another one to the child table as explained in this
stackoverflow
[link](https://stackoverflow.com/questions/39926937/sqlalchemy-how-to-insert-a-joined-table-inherited-class-instance-when-the-pare)
(I was not able to find it in the official docs)


### Relates
- #1123 
- #955 
- #1267

### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.
@dlpzx dlpzx deleted the feat/create-db-snapshot-before-alembic branch May 22, 2024 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants