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

Automate creating a postgres user for DB scanning #765

Merged
merged 3 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions backend/env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dev:
REGION: us-east-1

staging-cd:
IS_DMZ: 1
REGION: us-east-1
ENDPOINT_TYPE: REGIONAL
COGNITO_URL: https://cognito-idp.us-east-1.amazonaws.com
Expand All @@ -24,6 +25,8 @@ staging-cd:
MDL_USERNAME: ${ssm:/crossfeed/staging/MDL_USERNAME}
MDL_PASSWORD: ${ssm:/crossfeed/staging/MDL_PASSWORD}
MDL_NAME: ${ssm:/crossfeed/staging/MDL_NAME}
POSTGRES_SCAN_USER: ${ssm:/crossfeed/staging/POSTGRES_SCAN_USER}
POSTGRES_SCAN_PASSWORD: ${ssm:/crossfeed/staging/POSTGRES_SCAN_PASSWORD}
MI_ACCOUNT_NAME: ${ssm:/readysetcyber/staging/MI_ACCOUNT_NAME}
MI_PASSWORD: ${ssm:/readysetcyber/staging/MI_ACCOUNT_PASSWORD}
PE_DB_NAME: ${ssm:/crossfeed/staging/PE_DB_NAME}
Expand Down Expand Up @@ -78,6 +81,7 @@ staging-cd:
REACT_APP_COGNITO_CALLBACK_URL: https://staging-cd.crossfeed.cyber.dhs.gov/okta-callback

integration:
IS_DMZ: 1
REGION: us-east-1
ENDPOINT_TYPE: REGIONAL
COGNITO_URL: https://cognito-idp.us-east-1.amazonaws.com
Expand All @@ -95,6 +99,8 @@ integration:
MDL_USERNAME: ${ssm:/crossfeed/integration/MDL_USERNAME}
MDL_PASSWORD: ${ssm:/crossfeed/integration/MDL_PASSWORD}
MDL_NAME: ${ssm:/crossfeed/integration/MDL_NAME}
POSTGRES_SCAN_USER: ${ssm:/crossfeed/integration/POSTGRES_SCAN_USER}
POSTGRES_SCAN_PASSWORD: ${ssm:/crossfeed/integration/POSTGRES_SCAN_PASSWORD}
MI_ACCOUNT_NAME: ${ssm:/readysetcyber/integration/MI_ACCOUNT_NAME}
MI_PASSWORD: ${ssm:/readysetcyber/integration/MI_ACCOUNT_PASSWORD}
JWT_SECRET: ${ssm:/crossfeed/integration/APP_JWT_SECRET}
Expand Down Expand Up @@ -142,6 +148,7 @@ integration:
ELASTICACHE_ENDPOINT: ${ssm:/crossfeed/integration/ELASTICACHE_ENDPOINT}

staging:
IS_DMZ: 0
REGION: us-gov-east-1
ENDPOINT_TYPE: PRIVATE
COGNITO_URL: https://cognito-idp.us-gov-west-1.amazonaws.com
Expand All @@ -157,6 +164,8 @@ staging:
DB_NAME: ${ssm:/crossfeed/staging/DATABASE_NAME}
DB_USERNAME: ${ssm:/crossfeed/staging/DATABASE_USER}
DB_PASSWORD: ${ssm:/crossfeed/staging/DATABASE_PASSWORD}
POSTGRES_SCAN_USER: ${ssm:/crossfeed/staging/POSTGRES_SCAN_USER}
POSTGRES_SCAN_PASSWORD: ${ssm:/crossfeed/staging/POSTGRES_SCAN_PASSWORD}
JWT_SECRET: ${ssm:/crossfeed/staging/APP_JWT_SECRET}
JWT_ALGORITHM: ${ssm:/crossfeed/staging/JWT_ALGORITHM}
JWT_TIMEOUT_HOURS: ${ssm:/crossfeed/staging/JWT_TIMEOUT_HOURS}
Expand Down Expand Up @@ -204,6 +213,7 @@ staging:
ELASTICACHE_ENDPOINT: ${ssm:/crossfeed/staging/ELASTICACHE_ENDPOINT}

prod:
IS_DMZ: 0
REGION: us-gov-east-1
ENDPOINT_TYPE: PRIVATE
COGNITO_URL: https://cognito-idp.us-gov-west-1.amazonaws.com
Expand All @@ -223,6 +233,8 @@ prod:
MDL_PASSWORD: ${ssm:/crossfeed/prod/MDL_PASSWORD}
DJANGO_SECRET: ${ssm:/crossfeed/prod/DJANGO_SECRECT}
MDL_NAME: ${ssm:/crossfeed/prod/MDL_NAME}
POSTGRES_SCAN_USER: ${ssm:/crossfeed/prod/POSTGRES_SCAN_USER}
POSTGRES_SCAN_PASSWORD: ${ssm:/crossfeed/prod/POSTGRES_SCAN_PASSWORD}
JWT_SECRET: ${ssm:/crossfeed/prod/APP_JWT_SECRET}
JWT_ALGORITHM: ${ssm:/crossfeed/prod/JWT_ALGORITHM}
JWT_TIMEOUT_HOURS: ${ssm:/crossfeed/prod/JWT_TIMEOUT_HOURS}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.core.management.base import BaseCommand
from xfd_api.tasks.searchSync import handler as sync_es_domains
from xfd_api.tasks.syncdb_helpers import (
create_scan_user,
drop_all_tables,
manage_elasticsearch_indices,
populate_sample_data,
Expand Down Expand Up @@ -48,7 +49,11 @@ def handle(self, *args, **options):
# Step 2: Elasticsearch Index Management
manage_elasticsearch_indices(dangerouslyforce)

# Step 3: Populate Sample Data
# Step 3: Create the scanning user if doesn't exist
self.stdout.write("Creating and configuring the scanning user...")
create_scan_user()

# Step 4: Populate Sample Data
if populate:
self.stdout.write("Populating the database with sample data...")
populate_sample_data()
Expand Down
49 changes: 49 additions & 0 deletions backend/src/xfd_django/xfd_api/tasks/syncdb_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,52 @@ def sync_es_organizations():
except Exception as e:
print(f"Error syncing organizations: {e}")
raise e


def create_scan_user():
"""Create and configure the scanning user if it does not already exist."""
# Only create if not in the DMZ
is_dmz = os.getenv("IS_DMZ", "0") == "1"

if is_dmz:
print("IS_DMZ is set to 1. Skipping creation of the scanning user.")
return

user = os.getenv("POSTGRES_SCAN_USER")
password = os.getenv("POSTGRES_SCAN_PASSWORD")
if not user or not password:
print("POSTGRES_SCAN_USER or POSTGRES_SCAN_PASSWORD is not set.")
return

db_name = settings.DATABASES["default"]["NAME"]

with connection.cursor() as cursor:
try:
# Check if the user already exists
cursor.execute("SELECT 1 FROM pg_roles WHERE rolname = %s;", [user])
user_exists = cursor.fetchone() is not None

if not user_exists:
# Create the user
cursor.execute(
"CREATE ROLE {} LOGIN PASSWORD %s;".format(user), [password]
)
print("User '{}' created successfully.".format(user))
else:
print("User '{}' already exists. Skipping creation.".format(user))

# Grant privileges (idempotent as well)
cursor.execute("GRANT CONNECT ON DATABASE {} TO {};".format(db_name, user))
cursor.execute("GRANT USAGE ON SCHEMA public TO {};".format(user))
cursor.execute(
"GRANT SELECT ON ALL TABLES IN SCHEMA public TO {};".format(user)
)
cursor.execute(
"ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO {};".format(
user
)
)

print("User '{}' configured successfully.".format(user))
except Exception as e:
print("Error creating or configuring scan user: {}".format(e))
4 changes: 4 additions & 0 deletions dev.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,7 @@ ELASTICACHE_ENDPOINT=redis
WHOIS_XML_KEY=change_me
QUALYS_USERNAME=change_me
QUALYS_PASSWORD=change_me

IS_DMZ=1
POSTGRES_SCAN_USER=
POSTGRES_SCAN_PASSWORD=
Loading