diff --git a/.github/ISSUE_TEMPLATE/sub-issue.yml b/.github/ISSUE_TEMPLATE/sub-issue.yml new file mode 100644 index 000000000..e0b98e3d7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/sub-issue.yml @@ -0,0 +1,36 @@ +name: Sub-issue +description: Describe an idea, problem, or feature that is related to a parent issue. + +body: + - type: markdown + id: title-help + attributes: + value: | + > Titles should be short, descriptive, and compelling. Use sentence case (don't capitalize unnecessarily). + - type: textarea + id: description + attributes: + label: Sub-issue description + description: | + Describe the issue so that someone who wasn't present for its discovery can understand why it matters. Use full sentences, plain language, and [good formatting](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax). + + For stories, use the user story format (e.g., As a user, I want, So that). + validations: + required: true + - type: textarea + id: acceptance-criteria + attributes: + label: Acceptance criteria + description: If known, share 1-3 statements that would need to be true for this issue to be considered resolved. Use a [task list](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists#creating-task-lists) if appropriate. + placeholder: "- [ ]" + - type: textarea + id: additional-context + attributes: + label: Additional context + description: "Share any other thoughts, like how this might be implemented or fixed. Screenshots and links to documents/discussions are welcome." + - type: markdown + id: note + attributes: + value: | + > We may edit the text in this issue to document our understanding and clarify the product work. + diff --git a/docs/developer/adding-feature-flags.md b/docs/developer/adding-feature-flags.md index dc51b9e85..c4e6eda89 100644 --- a/docs/developer/adding-feature-flags.md +++ b/docs/developer/adding-feature-flags.md @@ -16,6 +16,14 @@ We use [django-waffle](https://waffle.readthedocs.io/en/stable/) for our feature 4. (Important) Set the field `Everyone` to `Unknown`. This field overrides all other settings when set to anything else. 5. Configure the settings as you see fit. +## Enabling a feature flag with portfolio permissions +1. Go to file `context_processors.py` +2. Add feature flag name to the `porfolio_context` within the `portfolio_permissions` method. +3. For the conditional under `if portfolio`, add the feature flag name, and assign the appropiate permission that are in the `user.py` model. + +#### Note: +- If your use case includes non org, you want to add a feature flag outside of it, you can just update the portfolio context outside of the if statement. + ## Using feature flags as boolean values Waffle [provides a boolean](https://waffle.readthedocs.io/en/stable/usage/views.html) called `flag_is_active` that you can use as you otherwise would a boolean. This boolean requires a request object and the flag name. diff --git a/docs/operations/runbooks/add_secrets_to_existing_sandbox.md b/docs/operations/runbooks/add_secrets_to_existing_sandbox.md new file mode 100644 index 000000000..411f9c90a --- /dev/null +++ b/docs/operations/runbooks/add_secrets_to_existing_sandbox.md @@ -0,0 +1,73 @@ +# HOWTO Add secrets to an existing sandbox + + +### Check if you need to add secrets +Run this command to get the environment variables from a sandbox: + +```sh +cf env +``` +For example `cf env getgov-development` + +Check that these environment variables exist: +``` +{ + "DJANGO_SECRET_KEY": "EXAMPLE", + "DJANGO_SECRET_LOGIN_KEY": "EXAMPLE", + "AWS_ACCESS_KEY_ID": "EXAMPLE", + "AWS_SECRET_ACCESS_KEY": "EXAMPLE", + "REGISTRY_KEY": "EXAMPLE, + ... +} +``` + +If those variable are not present, use the following steps to set secrets by creating a new `credentials-.json` file and uploading it. +(Note that many of these commands were taken from the [`create_dev_sandbox.sh`](../../../ops/scripts/create_dev_sandbox.sh) script and were tested on MacOS) + +### Create a new Django key +```sh +django_key=$(python3 -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())') +``` + +### Replace the existing certificate +Create a certificate: +```sh +openssl req -nodes -x509 -days 365 -newkey rsa:2048 -keyout private-.pem -out public-.crt +``` + +Fill in the following for the prompts: + +Note: for "Common Name" you should put the name of the sandbox and for "Email Address" it should be the address of who owns that sandbox (such as the developer's email, if it's a developer sandbox, or whoever ran this action otherwise) + +```sh +Country Name (2 letter code) [AU]: US +State or Province Name (full name) [Some-State]: DC +Locality Name (eg, city) []: DC +Organization Name (eg, company) [Internet Widgits Pty Ltd]: DHS +Organizational Unit Name (eg, section) []: CISA +Common Name (e.g. server FQDN or YOUR name) []: +Email Address []: +``` +Go to https://dashboard.int.identitysandbox.gov/service_providers/2640/edit to remove the old certificate and upload the new one. + +### Create the login key +```sh +login_key=$(base64 -i private-.pem) +``` + +### Create the credentials file +```sh +jq -n --arg django_key "$django_key" --arg login_key "$login_key" '{"DJANGO_SECRET_KEY":$django_key,"DJANGO_SECRET_LOGIN_KEY":$login_key}' > credentials-.json +``` + +Copy `REGISTRY_*` credentials from another sandbox into your `credentials-.json` file. Also add your `AWS_*` credentials if you have them, otherwise also copy them from another sandbox. You can either use the cloud.gov dashboard or the command `cf env ` to find other credentials. + +### Update the `getgov-credentials` service tied to your environment. +```sh +cf uups getgov-credentials -p credentials-.json +``` + +### Restage your application +```sh +cf restage getgov- --strategy rolling +``` \ No newline at end of file diff --git a/ops/scripts/create_dev_sandbox.sh b/ops/scripts/create_dev_sandbox.sh index 6cbad9c4f..1796817a8 100755 --- a/ops/scripts/create_dev_sandbox.sh +++ b/ops/scripts/create_dev_sandbox.sh @@ -136,6 +136,7 @@ then fi cf service-key github-cd-account github-cd-key | sed 1,2d | jq -r '[.username, .password]|@tsv' | + while read -r username password; do gh secret --repo cisagov/getgov set CF_${upcase_name}_USERNAME --body $username gh secret --repo cisagov/getgov set CF_${upcase_name}_PASSWORD --body $password diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 93ba60dfe..050950c9b 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -824,7 +824,9 @@ SESSION_COOKIE_SAMESITE = "Lax" SESSION_COOKIE_SECURE = True # session engine to cache session information -SESSION_ENGINE = "django.contrib.sessions.backends.cache" +SESSION_ENGINE = "django.contrib.sessions.backends.db" + +SESSION_SERIALIZER = "django.contrib.sessions.serializers.PickleSerializer" # ~ Set by django.middleware.clickjacking.XFrameOptionsMiddleware # prevent clickjacking by instructing the browser not to load diff --git a/src/registrar/management/commands/load_transition_domain.py b/src/registrar/management/commands/load_transition_domain.py index c2dd66f55..c39856c00 100644 --- a/src/registrar/management/commands/load_transition_domain.py +++ b/src/registrar/management/commands/load_transition_domain.py @@ -295,7 +295,6 @@ class Command(BaseCommand): except Exception as err: logger.error(f"Could not load additional TransitionDomain data. {err}") raise err - # TODO: handle this better...needs more logging def handle( # noqa: C901 self, diff --git a/src/registrar/management/commands/master_domain_migrations.py b/src/registrar/management/commands/master_domain_migrations.py index 9cb469078..7f702e047 100644 --- a/src/registrar/management/commands/master_domain_migrations.py +++ b/src/registrar/management/commands/master_domain_migrations.py @@ -29,9 +29,6 @@ logger = logging.getLogger(__name__) class Command(BaseCommand): help = """ """ # TODO: update this! - # ====================================================== - # ================== ARGUMENTS =================== - # ====================================================== def add_arguments(self, parser): """ OPTIONAL ARGUMENTS: diff --git a/src/registrar/tests/test_reports.py b/src/registrar/tests/test_reports.py index d801ce76a..cafaff7b1 100644 --- a/src/registrar/tests/test_reports.py +++ b/src/registrar/tests/test_reports.py @@ -874,18 +874,26 @@ class MemberExportTest(MockDbForIndividualTests, MockEppLib): "Email,Organization admin,Invited by,Joined date,Last active,Domain requests," "Member management,Domain management,Number of domains,Domains\n" # Content + "big_lebowski@dude.co,False,help@get.gov,2022-04-01,Invalid date,None," + "Viewer,True,1,cdomain1.gov\n" + "cozy_staffuser@igorville.gov,True,help@get.gov,2022-04-01,2024-02-01," + "Viewer,Viewer,False,0,\n" + "icy_superuser@igorville.gov,True,help@get.gov,2022-04-01,2024-02-01," + "Viewer Requester,Manager,False,0,\n" "meoward@rocks.com,False,big_lebowski@dude.co,2022-04-01,Invalid date,None," 'Manager,True,2,"adomain2.gov,cdomain1.gov"\n' - "big_lebowski@dude.co,False,help@get.gov,2022-04-01,Invalid date,None,Viewer,True,1,cdomain1.gov\n" - "tired_sleepy@igorville.gov,False,System,2022-04-01,Invalid date,Viewer,None,False,0,\n" - "icy_superuser@igorville.gov,True,help@get.gov,2022-04-01,2024-02-01,Viewer Requester,Manager,False,0,\n" - "cozy_staffuser@igorville.gov,True,help@get.gov,2022-04-01,2024-02-01,Viewer,Viewer,False,0,\n" - "nonexistentmember_1@igorville.gov,False,help@get.gov,Unretrieved,Invited,None,Manager,False,0,\n" - "nonexistentmember_2@igorville.gov,False,help@get.gov,Unretrieved,Invited,None,Viewer,False,0,\n" - "nonexistentmember_3@igorville.gov,False,help@get.gov,Unretrieved,Invited,Viewer,None,False,0,\n" - "nonexistentmember_4@igorville.gov,True,help@get.gov,Unretrieved," - "Invited,Viewer Requester,Manager,False,0,\n" - "nonexistentmember_5@igorville.gov,True,help@get.gov,Unretrieved,Invited,Viewer,Viewer,False,0,\n" + "nonexistentmember_1@igorville.gov,False,help@get.gov,Unretrieved,Invited," + "None,Manager,False,0,\n" + "nonexistentmember_2@igorville.gov,False,help@get.gov,Unretrieved,Invited," + "None,Viewer,False,0,\n" + "nonexistentmember_3@igorville.gov,False,help@get.gov,Unretrieved,Invited," + "Viewer,None,False,0,\n" + "nonexistentmember_4@igorville.gov,True,help@get.gov,Unretrieved,Invited," + "Viewer Requester,Manager,False,0,\n" + "nonexistentmember_5@igorville.gov,True,help@get.gov,Unretrieved,Invited," + "Viewer,Viewer,False,0,\n" + "tired_sleepy@igorville.gov,False,System,2022-04-01,Invalid date,Viewer," + "None,False,0,\n" ) # Normalize line endings and remove commas, # spaces and leading/trailing whitespace diff --git a/src/registrar/utility/csv_export.py b/src/registrar/utility/csv_export.py index 2758375b1..97feae20c 100644 --- a/src/registrar/utility/csv_export.py +++ b/src/registrar/utility/csv_export.py @@ -414,8 +414,11 @@ class MemberExport(BaseExport): ) .values(*shared_columns) ) - - return convert_queryset_to_dict(permissions.union(invitations), is_model=False) + # Adding a order_by increases output predictability. + # Doesn't matter as much for normal use, but makes tests easier. + # We should also just be ordering by default anyway. + members = permissions.union(invitations).order_by("email_display") + return convert_queryset_to_dict(members, is_model=False) @classmethod def get_invited_by_query(cls, object_id_query): diff --git a/src/zap.conf b/src/zap.conf index 7b878fb90..65468773a 100644 --- a/src/zap.conf +++ b/src/zap.conf @@ -74,6 +74,7 @@ 10038 OUTOFSCOPE http://app:8080/permissions 10038 OUTOFSCOPE http://app:8080/suborganization/ 10038 OUTOFSCOPE http://app:8080/transfer/ +10038 OUTOFSCOPE http://app:8080/prototype-dns # This URL always returns 404, so include it as well. 10038 OUTOFSCOPE http://app:8080/todo # OIDC isn't configured in the test environment and DEBUG=True so this gives a 500 without CSP headers