Compare commits

...

25 Commits

Author SHA1 Message Date
Carlo Costino
71344ce079 Merge branch 'main' into update-marshmallow-deps 2025-05-02 14:59:06 -04:00
Carlo Costino
f8858c944f Fix references to TemplateType enum in the schema
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-05-02 14:56:46 -04:00
Alex Janousek
cacaedac0c Merge pull request #1682 from GSA/dependabot/pip/sqlalchemy-2.0.40
Bump sqlalchemy from 2.0.31 to 2.0.40
2025-05-02 11:23:44 -04:00
dependabot[bot]
106d938d4f Bump sqlalchemy from 2.0.31 to 2.0.40
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.31 to 2.0.40.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

---
updated-dependencies:
- dependency-name: sqlalchemy
  dependency-version: 2.0.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 15:16:57 +00:00
Alex Janousek
812ffd7b53 Merge pull request #1685 from GSA/dependabot/pip/isort-6.0.1
Bump isort from 5.13.2 to 6.0.1
2025-05-02 11:14:47 -04:00
dependabot[bot]
4bdcf2c53e Bump isort from 5.13.2 to 6.0.1
Bumps [isort](https://github.com/PyCQA/isort) from 5.13.2 to 6.0.1.
- [Release notes](https://github.com/PyCQA/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyCQA/isort/compare/5.13.2...6.0.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-version: 6.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 15:08:03 +00:00
Alex Janousek
96fb2dead9 Merge pull request #1681 from GSA/dependabot/pip/markupsafe-3.0.2
Bump markupsafe from 2.1.5 to 3.0.2
2025-05-02 11:06:00 -04:00
dependabot[bot]
333631aee2 Bump markupsafe from 2.1.5 to 3.0.2
Bumps [markupsafe](https://github.com/pallets/markupsafe) from 2.1.5 to 3.0.2.
- [Release notes](https://github.com/pallets/markupsafe/releases)
- [Changelog](https://github.com/pallets/markupsafe/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/markupsafe/compare/2.1.5...3.0.2)

---
updated-dependencies:
- dependency-name: markupsafe
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 14:59:07 +00:00
Alex Janousek
be2e3252b1 Merge pull request #1683 from GSA/dependabot/pip/beautifulsoup4-4.13.4
Bump beautifulsoup4 from 4.12.3 to 4.13.4
2025-05-02 10:57:03 -04:00
dependabot[bot]
2d42f26839 Bump beautifulsoup4 from 4.12.3 to 4.13.4
Bumps [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/) from 4.12.3 to 4.13.4.

---
updated-dependencies:
- dependency-name: beautifulsoup4
  dependency-version: 4.13.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 14:50:16 +00:00
Alex Janousek
b4a82785c3 Merge pull request #1684 from GSA/dependabot/pip/notifications-python-client-10.0.1
Bump notifications-python-client from 10.0.0 to 10.0.1
2025-05-02 10:48:09 -04:00
dependabot[bot]
00451bb56c Bump notifications-python-client from 10.0.0 to 10.0.1
Bumps [notifications-python-client](https://github.com/alphagov/notifications-python-client) from 10.0.0 to 10.0.1.
- [Changelog](https://github.com/alphagov/notifications-python-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/alphagov/notifications-python-client/compare/10.0.0...10.0.1)

---
updated-dependencies:
- dependency-name: notifications-python-client
  dependency-version: 10.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-01 21:53:46 +00:00
Alex Janousek
26a7f541a5 Merge pull request #1671 from GSA/dependabot/pip/faker-37.1.0
Bump faker from 26.3.0 to 37.1.0
2025-05-01 10:20:00 -04:00
dependabot[bot]
2bcf90584c Bump faker from 26.3.0 to 37.1.0
Bumps [faker](https://github.com/joke2k/faker) from 26.3.0 to 37.1.0.
- [Release notes](https://github.com/joke2k/faker/releases)
- [Changelog](https://github.com/joke2k/faker/blob/master/CHANGELOG.md)
- [Commits](https://github.com/joke2k/faker/compare/v26.3.0...v37.1.0)

---
updated-dependencies:
- dependency-name: faker
  dependency-version: 37.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-01 14:13:12 +00:00
Alex Janousek
d1c105447a Merge pull request #1679 from GSA/dependabot/pip/alembic-1.15.2
Bump alembic from 1.13.2 to 1.15.2
2025-05-01 10:11:05 -04:00
dependabot[bot]
cba7a712db Bump alembic from 1.13.2 to 1.15.2
Bumps [alembic](https://github.com/sqlalchemy/alembic) from 1.13.2 to 1.15.2.
- [Release notes](https://github.com/sqlalchemy/alembic/releases)
- [Changelog](https://github.com/sqlalchemy/alembic/blob/main/CHANGES)
- [Commits](https://github.com/sqlalchemy/alembic/commits)

---
updated-dependencies:
- dependency-name: alembic
  dependency-version: 1.15.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-01 14:03:09 +00:00
Alex Janousek
739a08e203 Merge pull request #1680 from GSA/dependabot/pip/setuptools-80.1.0
Bump setuptools from 75.9.1 to 80.1.0
2025-05-01 10:01:05 -04:00
dependabot[bot]
eb76f2cee8 Bump setuptools from 75.9.1 to 80.1.0
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.9.1 to 80.1.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.9.1...v80.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 80.1.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-30 21:15:51 +00:00
Andrew Shumway
9113062d98 Merge pull request #1674 from GSA/dependabot/pip/celery-5.5.2
Bump celery from 5.4.0 to 5.5.2
2025-04-30 10:51:46 -06:00
dependabot[bot]
6ef23b70a6 Bump celery from 5.4.0 to 5.5.2
Bumps [celery](https://github.com/celery/celery) from 5.4.0 to 5.5.2.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.4.0...v5.5.2)

---
updated-dependencies:
- dependency-name: celery
  dependency-version: 5.5.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-30 16:40:49 +00:00
Andrew Shumway
0ce6c6b263 Merge pull request #1675 from GSA/dependabot/pip/phonenumbers-9.0.4
Bump phonenumbers from 8.13.55 to 9.0.4
2025-04-30 10:38:29 -06:00
Cliff Hill
f1df78b4ba Merge pull request #1677 from GSA/update-rotate-creds-runbook
Expand the credential/secret rotation runbook
2025-04-29 12:39:29 -04:00
Carlo Costino
debb14d216 Updated Login.gov section
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-04-28 17:15:08 -04:00
Carlo Costino
01b9ea451a Expand the credential/secret rotation runbook
This changeset adds a bunch of new information on how to manage environment variables and credentials in our application.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-04-28 17:01:59 -04:00
dependabot[bot]
a74e5d15a4 Bump phonenumbers from 8.13.55 to 9.0.4
Bumps [phonenumbers](https://github.com/daviddrysdale/python-phonenumbers) from 8.13.55 to 9.0.4.
- [Commits](https://github.com/daviddrysdale/python-phonenumbers/compare/v8.13.55...v9.0.4)

---
updated-dependencies:
- dependency-name: phonenumbers
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-25 21:06:06 +00:00
6 changed files with 935 additions and 627 deletions

View File

@@ -112,6 +112,10 @@ test: ## Run tests and create coverage report
poetry run coverage report -m --fail-under=93
poetry run coverage html -d .coverage_cache
.PHONY: test-debug
test-debug:
poetry run pytest --pdb -x
.PHONY: py-lock
py-lock: ## Syncs dependencies and updates lock file without performing recursive internal updates
poetry lock --no-update

View File

@@ -510,6 +510,7 @@ instructions above for more details.
- [DNS and Domain Changes](./docs/all.md#-dns-and-domain-changes)
- [Exporting daily scan results for compliance monitoring](./docs/all.md#exporting-daily-scan-results-for-compliance-monitoring)
- [Reviewing daily scan results for compliance](./docs/all.md#reviewing-daily-scan-results-for-compliance)
- [Rotating environment variable secrets](./docs/all.md#rotating-environment-variable-secrets)
- [Known Gotchas](./docs/all.md#-known-gotchas)
- [User Account Management](./docs/all.md#-user-account-management)
- [SMS Phone Number Management](./docs/all.md#-sms-phone-number-management)

View File

@@ -375,6 +375,7 @@ class TemplateSchema(BaseTemplateSchema, UUIDsAsStringsMixin):
created_by = field_for(models.Template, "created_by", required=True)
process_type = field_for(models.Template, "process_type")
redact_personalisation = fields.Method("redact")
template_type = auto_field(by_value=True)
created_at = FlexibleDateTime()
updated_at = FlexibleDateTime()
@@ -419,6 +420,7 @@ class TemplateHistorySchema(BaseSchema):
reply_to = fields.Method("get_reply_to", allow_none=True)
reply_to_text = fields.Method("get_reply_to_text", allow_none=True)
process_type = field_for(models.Template, "process_type")
template_type = auto_field(by_value=True)
created_by = fields.Nested(
UserSchema, only=["id", "name", "email_address"], dump_only=True
@@ -464,7 +466,7 @@ class JobSchema(BaseSchema):
processing_started = FlexibleDateTime()
processing_finished = FlexibleDateTime()
job_status = auto_field()
job_status = auto_field(by_value=True)
scheduled_for = FlexibleDateTime()
service_name = fields.Nested(
@@ -482,7 +484,7 @@ class JobSchema(BaseSchema):
return job.template.name
def get_template_type(self, job):
return job.template.template_type
return job.template.template_type.value
@validates("scheduled_for")
def validate_scheduled_for(self, value):
@@ -597,11 +599,12 @@ class NotificationWithPersonalisationSchema(NotificationWithTemplateSchema):
created_at = auto_field()
id = auto_field()
job_row_number = auto_field()
notification_type = auto_field()
notification_type = auto_field(by_value=True)
reference = auto_field()
sent_at = auto_field()
sent_by = auto_field()
status = auto_field()
template_type = auto_field(by_value=True)
template_version = auto_field()
to = auto_field()
updated_at = auto_field()

View File

@@ -56,6 +56,7 @@
- [DNS and Domain Changes](#-dns-and-domain-changes)
- [Exporting daily scan results for compliance monitoring](#exporting-daily-scan-results-for-compliance-monitoring)
- [Reviewing daily scan results for compliance](#reviewing-daily-scan-results-for-compliance)
- [Rotating environment variable secrets](#rotating-environment-variable-secrets)
- [Known Gotchas](#-known-gotchas)
- [User Account Management](#-user-account-management)
- [SMS Phone Number Management](#-sms-phone-number-management)
@@ -1329,16 +1330,74 @@ Once you're done performing the steps above to gather all of the information, ma
Once you're done performing the steps above to gather all of the information, make a note of any new findings that need to be accounted for and remediated and create issues to track the work.
## Rotating the DANGEROUS_SALT
## Rotating environment variable secrets
1. Start API locally `make run-procfile`
2. In a separate terminal tab, navigate to the API project and run `poetry run flask command generate-salt`
3. A random secret will appear in the tab
4. Go to github->settings->secrets and variables->actions in the admin project and find the DANGEROUS_SALT secret for the admin project for staging. Open it and paste the result of #3 into the secret and save. Repeat for the API project, for staging.
5. Repeat #3 and #4 but do it for demo
6. Repeat #3 and #4 but do it for production
There are a few different ways to handle rotating environment variable secrets, depending on what the secret is.
### Secret environment variables (set directly)
The `ADMIN_CLIENT_SECRET`, `DANGEROUS_SALT`, and `SECRET_KEY` environment variables are all generated random strings of characters. To make a new value for any of these environment variables, perform the following steps:
1. Start the API locally with the command `make run-procfile`
1. In a separate terminal tab, navigate to the API project and run `poetry run flask command generate-salt` (this command is found in the [`app/commands.py` file](https://github.com/GSA/notifications-api/blob/main/app/commands.py#L1030-L1037))
1. A random secret will appear in the tab, which you will use to update the value(s) in GitHub
Next, you'll need to go into GitHub for either the [API repo environment settings](https://github.com/GSA/notifications-api/settings/environments) or [Admin repo environment settings](https://github.com/GSA/notifications-admin/settings/environments). Once there you'll see a list of all of the environments; click into the one that you're looking to update and then find the corresponding environment that you need to update. Click on the pencil icon to the right of the environment variable name to edit the value, then paste in the value you generated with the previous steps.
**NOTE:** These values must match between the API and Admin environment variables per environment (meaning, if you change the Admin repo value for any of these values in any environment, the same variable for the API in the same environment must be changed to match it!).
The important thing is to use the same secret for Admin and API on each tier -- i.e. you only generate three secrets per environment.
**NOTE:** You may also have to update these values for Dependabot as well! To do this, go into GitHub and the navigate through `Settings -> Secrets and variables -> Dependabot`, which will take you to a special page to manage environment variables specifically for Dependabot. This is more necessary in the Admin repo because of the E2E tests.
### E2E environment variables (set directly)
See the [end-to-end testing section](#end-to-end-testing).
### Service bindings for Cloud.gov-managed services
For any Cloud.gov service instance that you need to rotate credentials for, you need to run the following commands:
1. `cf unbind-service <APP NAME> <SERVICE NAME>`
1. `cf bind-service <APP NAME> <SERVICE NAME>`
Once you are done unbinding and re-binding all services you're looking to rotate credentials for, you need to restage or redeploy the application(s) for the changes to take effect. You can restage directly in the command line: `cf restage <APP NAME> --strategy rolling`
### Rotating New Relic API keys and licenses
To rotate New Relic API key, license key, and other credentials, you need access to New Relic. If you have access, sign in and then click on your name in the lower left. Click on `API keys` and you'll be taken to the management screen for all of the API keys. From there, perform these steps:
1. Create new versions of whichever key(s) you would like to rotate
1. Update the corresponding environment variable(s) in GitHub for both the [API repo environment settings](https://github.com/GSA/notifications-api/settings/environments) and the [Admin repo environment settings](https://github.com/GSA/notifications-admin/settings/environments)
1. Restage or redeploy the applications
1. Once you confirm the new key(s) in New Relic are working, delete the old keys on the API Key management screen
### Terraform state bucket key rotation
To rotate the Terraform state bucket key, run these commands in the `api/terraform/bootstrap` directory of the API repo:
```sh
# comment out prevent_destroy in terraform/bootstrap/main.tf
# update username to create in run.sh and teardown-creds.sh
$ ./run.sh plan -replace=cloudfoundry_service_key.bucket_creds
$ ./run.sh apply -replace=cloudfoundry_service_key.bucket_creds
```
Once that's done, copy the key generating to the staging, demo, and production environments of both the API and the Admin.
### Refreshing/rotating the Login.gov certificate
1. generate certificate: `openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.crt -nodes`
1. update the github secrets for staging, demo, production (contents of key.pem go in LOGIN_PEM and contents of cert.crt in LOGIN_PUB). **DO NOT RESTAGE YET**.
1. use the same certificate for staging, demo, and production
1. login to the login.gov partner app (https://portal.int.identitysandbox.gov)
1. add the new certificate to the production version of Notify in the partner app (our partner app account has sandbox and production)
1. Make a Zendesk support request for login.gov to push the new version of Notify (https://zendesk.login.gov)
1. Do not delete the old certificate, because you need things to keep working until you complete the transition.
1. When you receive an email from login.gov that the app has been pushed successfully, restage notify on the staging tier
1. If staging works, you can restage demo and production
1. Delete the old certificate in the partner app, send another zendesk request to push again. This is best practice but a lower priority, because certificates eventually expire anyway and we have changed the certificate in github secrets, so the old cert is no longer relevant.
The important thing is to use the same secret for Admin and API on each tier--i.e. you only generate three secrets.
## <a name="gotcha"></a> Known Gotchas
@@ -1575,19 +1634,3 @@ Note: better to search on space 'notify-production' rather than specifically for
#notify-admin-1505 (general login issues)
#notify-admin-1701 (wrong sender phone number)
#notify-admin-1859 (job is created with created_at being the wrong time)
### refreshing the login.gov certificate
1. generate certificate: `openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.crt -nodes`
2. update the github secrets for staging, demo, production (contents of key.pem go in LOGIN_PEM and contents of cert.crt in LOGIN_PUB).
DO NOT RESTAGE YET.
3. use the same certificate for staging, demo, and production
4. login to the login.gov partner app (https://portal.int.identitysandbox.gov)
5. add the new certificate to the production version of Notify in the partner app (our partner app account has sandbox and production)
6. Make a Zendesk support request for login.gov to push the new version of Notify (https://zendesk.login.gov)
7. Do not delete the old certificate, because you need things to keep working until you complete the transition.
8. When you receive an email from login.gov that the app has been pushed successfully, restage notify on the staging tier
9. If staging works, you can restage demo and production
10. Delete the old certificate in the partner app, send another zendesk request to push again. This is best practice but a lower
priority, because certificates eventually expire anyway and we have changed the certificate in github secrets, so the old cert is
no longer relevant.

1439
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,13 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12.2"
alembic = "==1.13.2"
alembic = "==1.15.2"
amqp = "==5.3.1"
beautifulsoup4 = "==4.12.3"
beautifulsoup4 = "==4.13.4"
boto3 = "^1.34.150"
botocore = "^1.34.159"
cachetools = "==5.4.0"
celery = {version = "==5.4.0", extras = ["redis"]}
celery = {version = "==5.5.2", extras = ["redis"]}
certifi = ">=2022.12.7"
cffi = "==1.17.1"
charset-normalizer = "^3.4.1"
@@ -39,7 +39,7 @@ lxml = "==5.3.1"
marshmallow = "^4.0.0"
marshmallow-sqlalchemy = "^1.4.2"
newrelic = "*"
notifications-python-client = "==10.0.0"
notifications-python-client = "==10.0.1"
oscrypto = { git = "https://github.com/wbond/oscrypto.git", rev = "1547f53" }
packaging = "==25.0"
poetry-dotenv-plugin = "==0.2.0"
@@ -48,13 +48,13 @@ pyjwt = "==2.10.1"
python-dotenv = "==1.0.1"
sqlalchemy = "==2.0.40"
werkzeug = "^3.0.6"
faker = "^26.0.0"
faker = "^37.1.0"
async-timeout = "^5.0.1"
bleach = "^6.1.0"
geojson = "^3.2.0"
numpy = "^2.2.5"
ordered-set = "^4.1.0"
phonenumbers = "^8.13.42"
phonenumbers = "^9.0.4"
python-json-logger = "^3.3.0"
regex = "^2024.11.6"
shapely = "^2.0.5"
@@ -64,7 +64,7 @@ blinker = "^1.9.0"
cryptography = "^44.0.1"
idna = "^3.7"
jmespath = "^1.0.1"
markupsafe = "^2.1.5"
markupsafe = "^3.0.2"
pycparser = "^2.22"
python-dateutil = "^2.9.0.post0"
pyyaml = "^6.0.2"
@@ -89,7 +89,7 @@ flake8 = "^7.2.0"
flake8-bugbear = "^24.12.12"
freezegun = "^1.5.1"
honcho = "*"
isort = "^5.13.2"
isort = "^6.0.1"
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
moto = "==5.1.4"
pip-audit = "*"
@@ -101,7 +101,7 @@ pytest-cov = "^6.1.1"
pytest-xdist = "^3.5.0"
radon = "^6.0.1"
requests-mock = "^1.11.0"
setuptools = "^75.8.0"
setuptools = "^80.1.0"
sqlalchemy-utils = "^0.41.2"
vulture = "^2.10"
detect-secrets = "^1.5.0"