diff --git a/.circleci/deployment/commands.yml b/.circleci/deployment/commands.yml index 43adb60e3..347f119b5 100644 --- a/.circleci/deployment/commands.yml +++ b/.circleci/deployment/commands.yml @@ -79,12 +79,24 @@ frontend-appname: default: tdp-frontend type: string + kibana-appname: + default: tdp-kibana + type: string + proxy-appname: + default: tdp-elastic-proxy + type: string cf-space: default: tanf-dev type: string steps: - get-app-deploy-strategy: appname: <> + - run: + name: Install dependencies + command: | + sudo apt update + sudo add-apt-repository ppa:rmescandon/yq + sudo apt-get install yq - run: name: Deploy backend application command: | @@ -92,6 +104,8 @@ $DEPLOY_STRATEGY \ <> \ <> \ + <> \ + <> \ <> deploy-clamav: @@ -115,6 +129,9 @@ frontend-appname: default: tdp-frontend type: string + kibana-appname: + default: tdp-kibana + type: string # So the frontend knows what space its in for the banner. # I am unclear if the domain is a reliable metric to make this function # It seems like it might not be working @@ -136,6 +153,7 @@ $DEPLOY_STRATEGY \ <> \ <> \ + <> \ <> \ <> diff --git a/.gitconfig b/.gitconfig index 4c46daac8..2b2b988bc 100644 --- a/.gitconfig +++ b/.gitconfig @@ -7,6 +7,7 @@ allowed = [A-Z]+_KEY=..echo \".{S3_CREDENTIALS}\" [|] jq -r .+ allowed = ./tdrs-backend/.env.example:.* allowed = ./tdrs-backend/docker-compose.yml:57:.* + allowed = ./tdrs-backend/manifest.proxy.yml:* allowed = regexes.json:.* allowed = ./scripts/copy-login-gov-keypair.sh:14:JWT_KEY=.* allowed = scripts/deploy-backend.sh:.+:DJANGO_SECRET_KEY=..python -c .from secrets import token_urlsafe. print.token_urlsafe..* diff --git a/scripts/deploy-backend.sh b/scripts/deploy-backend.sh index 6e46fe93a..0dc5ba5b4 100755 --- a/scripts/deploy-backend.sh +++ b/scripts/deploy-backend.sh @@ -10,7 +10,9 @@ DEPLOY_STRATEGY=${1} #The application name defined via the manifest yml for the frontend CGAPPNAME_FRONTEND=${2} CGAPPNAME_BACKEND=${3} -CF_SPACE=${4} +CGAPPNAME_KIBANA=${4} +CGAPPNAME_PROXY=${5} +CF_SPACE=${6} strip() { # Usage: strip "string" "pattern" @@ -20,8 +22,14 @@ strip() { env=$(strip $CF_SPACE "tanf-") backend_app_name=$(echo $CGAPPNAME_BACKEND | cut -d"-" -f3) +# Update the Kibana and Elastic proxy names to include the environment +CGAPPNAME_KIBANA="${CGAPPNAME_KIBANA}-${backend_app_name}" +CGAPPNAME_PROXY="${CGAPPNAME_PROXY}-${backend_app_name}" + echo DEPLOY_STRATEGY: "$DEPLOY_STRATEGY" echo BACKEND_HOST: "$CGAPPNAME_BACKEND" +echo KIBANA_HOST: "$CGAPPNAME_KIBANA" +echo ELASTIC_PROXY_HOST: "$CGAPPNAME_PROXY" echo CF_SPACE: "$CF_SPACE" echo env: "$env" echo backend_app_name: "$backend_app_name" @@ -49,6 +57,7 @@ set_cf_envs() "DJANGO_SETTINGS_MODULE" "DJANGO_SU_NAME" "FRONTEND_BASE_URL" + "KIBANA_BASE_URL" "LOGGING_LEVEL" "REDIS_URI" "JWT_KEY" @@ -86,6 +95,36 @@ generate_jwt_cert() cf set-env "$CGAPPNAME_BACKEND" JWT_KEY "$(cat key.pem)" } +update_kibana() +{ + cd tdrs-backend || exit + + # Run template evaluation on manifest + yq eval -i ".applications[0].services[0] = \"es-${backend_app_name}\"" manifest.proxy.yml + yq eval -i ".applications[0].env.CGAPPNAME_PROXY = \"${CGAPPNAME_PROXY}\"" manifest.kibana.yml + + if [ "$1" = "rolling" ] ; then + # Do a zero downtime deploy. This requires enough memory for + # two apps to exist in the org/space at one time. + cf push "$CGAPPNAME_PROXY" --no-route -f manifest.proxy.yml -t 180 --strategy rolling || exit 1 + cf push "$CGAPPNAME_KIBANA" --no-route -f manifest.kibana.yml -t 180 --strategy rolling || exit 1 + else + cf push "$CGAPPNAME_PROXY" --no-route -f manifest.proxy.yml -t 180 + cf push "$CGAPPNAME_KIBANA" --no-route -f manifest.kibana.yml -t 180 + fi + + cf map-route "$CGAPPNAME_PROXY" apps.internal --hostname "$CGAPPNAME_PROXY" + cf map-route "$CGAPPNAME_KIBANA" apps.internal --hostname "$CGAPPNAME_KIBANA" + + # Add network policy allowing Kibana to talk to the proxy and to allow the backend to talk to Kibana + cf add-network-policy "$CGAPPNAME_KIBANA" "$CGAPPNAME_PROXY" --protocol tcp --port 8080 + cf add-network-policy "$CGAPPNAME_BACKEND" "$CGAPPNAME_KIBANA" --protocol tcp --port 5601 + cf add-network-policy "$CGAPPNAME_FRONTEND" "$CGAPPNAME_KIBANA" --protocol tcp --port 5601 + cf add-network-policy "$CGAPPNAME_KIBANA" "$CGAPPNAME_FRONTEND" --protocol tcp --port 80 + + cd .. +} + update_backend() { cd tdrs-backend || exit @@ -189,6 +228,8 @@ else FRONTEND_BASE_URL="$DEFAULT_FRONTEND_ROUTE" fi +KIBANA_BASE_URL="http://$CGAPPNAME_KIBANA.apps.internal" + # Dynamically generate a new DJANGO_SECRET_KEY DJANGO_SECRET_KEY=$(python3 -c "from secrets import token_urlsafe; print(token_urlsafe(50))") @@ -208,6 +249,7 @@ if [ "$DEPLOY_STRATEGY" = "rolling" ] ; then # Perform a rolling update for the backend and frontend deployments if # specified, otherwise perform a normal deployment update_backend 'rolling' + update_kibana 'rolling' elif [ "$DEPLOY_STRATEGY" = "bind" ] ; then # Bind the services the application depends on and restage the app. bind_backend_to_services @@ -216,15 +258,20 @@ elif [ "$DEPLOY_STRATEGY" = "initial" ]; then # for it to work. the app will fail to start once, have the services bind, # and then get restaged. update_backend + update_kibana bind_backend_to_services elif [ "$DEPLOY_STRATEGY" = "rebuild" ]; then # You want to redeploy the instance under the same name # Delete the existing app (with out deleting the services) # and perform the initial deployment strategy. cf delete "$CGAPPNAME_BACKEND" -r -f + cf delete "$CGAPPNAME_KIBANA" -r -f + cf delete "$CGAPPNAME_PROXY" -r -f update_backend + update_kibana bind_backend_to_services else # No changes to deployment config, just deploy the changes and restart update_backend + update_kibana fi diff --git a/scripts/deploy-frontend.sh b/scripts/deploy-frontend.sh index 96af218f2..2638b0d6e 100755 --- a/scripts/deploy-frontend.sh +++ b/scripts/deploy-frontend.sh @@ -8,14 +8,21 @@ DEPLOY_STRATEGY=${1} #The application name defined via the manifest yml for the frontend CGHOSTNAME_FRONTEND=${2} CGHOSTNAME_BACKEND=${3} -CF_SPACE=${4} -ENVIRONMENT=${5} +CGAPPNAME_KIBANA=${4} +CF_SPACE=${5} +ENVIRONMENT=${6} + +backend_app_name=$(echo $CGHOSTNAME_BACKEND | cut -d"-" -f3) + +# Update the Kibana name to include the environment +KIBANA_BASE_URL="${CGAPPNAME_KIBANA}-${backend_app_name}.apps.internal" update_frontend() { echo DEPLOY_STRATEGY: "$DEPLOY_STRATEGY" echo FRONTEND_HOST: "$CGHOSTNAME_FRONTEND" echo BACKEND_HOST: "$CGHOSTNAME_BACKEND" + echo KIBANA_BASE_URL: "$KIBANA_BASE_URL" cd tdrs-frontend || exit if [ "$CF_SPACE" = "tanf-prod" ]; then @@ -44,6 +51,7 @@ update_frontend() fi cf set-env "$CGHOSTNAME_FRONTEND" BACKEND_HOST "$CGHOSTNAME_BACKEND" + cf set-env "$CGHOSTNAME_FRONTEND" KIBANA_BASE_URL "$KIBANA_BASE_URL" npm run build:$ENVIRONMENT unlink .env.production diff --git a/tdrs-backend/clamav-router/nginx.conf b/tdrs-backend/clamav-router/nginx.conf index 35e95e7a7..bec070813 100644 --- a/tdrs-backend/clamav-router/nginx.conf +++ b/tdrs-backend/clamav-router/nginx.conf @@ -1,8 +1,9 @@ -events { worker_connections 1024; +events { + worker_connections 1024; } - # This opens a route to clamav prod http{ + resolver {{nameservers}} valid=10s; server { client_max_body_size 100m; listen {{port}}; @@ -21,4 +22,4 @@ http{ proxy_pass_request_headers on; } } -} +} \ No newline at end of file diff --git a/tdrs-backend/docker-compose.yml b/tdrs-backend/docker-compose.yml index 6a09c3944..e6636e14d 100644 --- a/tdrs-backend/docker-compose.yml +++ b/tdrs-backend/docker-compose.yml @@ -46,40 +46,15 @@ services: - ../scripts/localstack-setup.sh:/docker-entrypoint-initaws.d/localstack-setup.sh kibana: - image: elastic/kibana:7.17.10 + image: docker.elastic.co/kibana/kibana-oss:7.4.2 ports: - 5601:5601 environment: - - xpack.security.encryptionKey=${KIBANA_ENCRYPTION_KEY:-something_at_least_32_characters} - - xpack.security.session.idleTimeout="1h" - - xpack.security.session.lifespan="30d" - volumes: - - ./kibana.yml:/usr/share/kibana/config/kibana.yml - depends_on: - - elastic - - # This task only needs to be performed once, during the *initial* startup of - # the stack. Any subsequent run will reset the passwords of existing users to - # the values defined inside the '.env' file, and the built-in roles to their - # default permissions. - # - # By default, it is excluded from the services started by 'docker compose up' - # due to the non-default profile it belongs to. To run it, either provide the - # '--profile=elastic_setup' CLI flag to Compose commands, or "up" the service by name - # such as 'docker compose up elastic_setup'. - elastic_setup: - profiles: - - elastic_setup - build: - context: elastic_setup/ - args: - ELASTIC_VERSION: "7.17.6" - init: true - environment: - ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:-changeme} - KIBANA_SYSTEM_PASSWORD: ${KIBANA_SYSTEM_PASSWORD:-changeme} - OFA_ADMIN_PASSWORD: ${OFA_ADMIN_PASSWORD:-changeme} - ELASTICSEARCH_HOST: ${ELASTICSEARCH_HOST:-elastic} + - ELASTICSEARCH_HOSTS="http://elastic:9200" + - SERVER_HOST=kibana + - SERVER_BASEPATH=/kibana + - SERVER_SECURITYRESPONSEHEADERS_REFERRERPOLICY=no-referrer + - CSP_WARNLEGACYBROWSERS=false depends_on: - elastic @@ -88,12 +63,7 @@ services: environment: - discovery.type=single-node - logger.discovery.level=debug - - xpack.security.enabled=true - - xpack.security.authc.anonymous.username="ofa_admin" - - xpack.security.authc.anonymous.roles="ofa_admin" - - xpack.security.authc.anonymous.authz_exception=true - - ELASTIC_PASSWORD=${ELASTIC_PASSWORD:-changeme} - - KIBANA_SYSTEM_PASSWORD=${KIBANA_SYSTEM_PASSWORD:-changeme} + - xpack.security.enabled=false ports: - 9200:9200 - 9300:9300 diff --git a/tdrs-backend/kibana.yml b/tdrs-backend/kibana.yml deleted file mode 100644 index e98d2438d..000000000 --- a/tdrs-backend/kibana.yml +++ /dev/null @@ -1,12 +0,0 @@ -elasticsearch.hosts: ["http://elastic:9200"] -server.host: kibana -elasticsearch.username: kibana_system -elasticsearch.password: changeme -xpack.security.authc.providers: - anonymous.anonymous1: - order: 0 - description: "OFA Admin Login" - hint: "" - credentials: - username: "ofa_admin" - password: "changeme" diff --git a/tdrs-backend/manifest.kibana.yml b/tdrs-backend/manifest.kibana.yml new file mode 100644 index 000000000..181b29ec0 --- /dev/null +++ b/tdrs-backend/manifest.kibana.yml @@ -0,0 +1,16 @@ +version: 1 +applications: + - name: tdp-kibana + memory: 2G + disk_quota: 2G + instances: 1 + env: + CGAPPNAME_PROXY: {{ proxy_hostname }} + SERVER_BASEPATH: /kibana + SERVER_SECURITYRESPONSEHEADERS_REFERRERPOLICY: no-referrer + CSP_WARNLEGACYBROWSERS: false + docker: + image: docker.elastic.co/kibana/kibana-oss:7.4.2 + command: | + export ELASTICSEARCH_HOSTS=http://$CGAPPNAME_PROXY.apps.internal:8080 && + /usr/local/bin/dumb-init -- /usr/local/bin/kibana-docker diff --git a/tdrs-backend/manifest.proxy.yml b/tdrs-backend/manifest.proxy.yml new file mode 100644 index 000000000..7ef739c4f --- /dev/null +++ b/tdrs-backend/manifest.proxy.yml @@ -0,0 +1,15 @@ +version: 1 +applications: +- name: tdp-elastic-proxy + memory: 64M + disk_quota: 64M + instances: 1 + services: + - {{ service_0 }} + docker: + image: elipe17/aws-es-proxy:latest + command: | + export ENDPOINT=$(echo $VCAP_SERVICES | grep -Eo 'host[^,]*' | grep -Eo '[^:]*$' | tr -d '"' | sed -e 's/^/https:\/\//') && + export AWS_ACCESS_KEY_ID=$(echo $VCAP_SERVICES | grep -Eo 'access_key[^,]*' | grep -Eo '[^:]*$' | tr -d '"') && + export AWS_SECRET_ACCESS_KEY=$(echo $VCAP_SERVICES | grep -Eo 'secret_key[^,]*' | grep -Eo '[^:]*$' | tr -d '"') && + /usr/local/bin/aws-es-proxy -endpoint $ENDPOINT -listen 0.0.0.0:8080 -verbose -debug diff --git a/tdrs-backend/tdpservice/search_indexes/documents/document_base.py b/tdrs-backend/tdpservice/search_indexes/documents/document_base.py index ea377b283..67903e7e2 100644 --- a/tdrs-backend/tdpservice/search_indexes/documents/document_base.py +++ b/tdrs-backend/tdpservice/search_indexes/documents/document_base.py @@ -13,6 +13,11 @@ class DocumentBase(Document): 'version': fields.IntegerField(), 'quarter': fields.TextField(), 'year': fields.IntegerField(), + 'stt': fields.ObjectField(properties={ + 'name': fields.TextField(), + 'type': fields.TextField(), + 'stt_code': fields.TextField() + }) }) def get_instances_from_related(self, related_instance): diff --git a/tdrs-backend/tdpservice/settings/common.py b/tdrs-backend/tdpservice/settings/common.py index 108586c80..7d9126716 100644 --- a/tdrs-backend/tdpservice/settings/common.py +++ b/tdrs-backend/tdpservice/settings/common.py @@ -340,10 +340,19 @@ class Common(Configuration): # The number of seconds to wait for socket response from clamav-rest AV_SCAN_TIMEOUT = int(os.getenv('AV_SCAN_TIMEOUT', 30)) + # Elastic/Kibana + ELASTICSEARCH_DSL = { + 'default': { + 'hosts': os.getenv('ELASTIC_HOST', 'elastic:9200'), + }, + } + KIBANA_BASE_URL = os.getenv('KIBANA_BASE_URL', 'http://kibana:5601') + BYPASS_KIBANA_AUTH = os.getenv("BYPASS_KIBANA_AUTH", False) + s3_src = "s3-us-gov-west-1.amazonaws.com" CSP_DEFAULT_SRC = ("'none'") - CSP_SCRIPT_SRC = ("'self'", s3_src) + CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'", s3_src, KIBANA_BASE_URL) CSP_IMG_SRC = ("'self'", "data:", s3_src) CSP_FONT_SRC = ("'self'", s3_src) CSP_CONNECT_SRC = ("'self'", "*.cloud.gov") @@ -351,7 +360,7 @@ class Common(Configuration): CSP_OBJECT_SRC = ("'none'") CSP_FRAME_ANCESTORS = ("'none'") CSP_FORM_ACTION = ("'self'") - CSP_STYLE_SRC = ("'self'", s3_src, "'unsafe-inline'") + CSP_STYLE_SRC = ("'self'", "'unsafe-inline'", s3_src, KIBANA_BASE_URL) #################################### @@ -465,14 +474,4 @@ class Common(Configuration): } } - # Elastic/Kibana - ELASTICSEARCH_DSL = { - 'default': { - 'hosts': os.getenv('ELASTIC_HOST', 'elastic:9200'), - 'http_auth': ('elastic', os.getenv('ELASTIC_PASSWORD', 'changeme')) - }, - } - KIBANA_BASE_URL = os.getenv('KIBANA_BASE_URL', 'http://localhost:5601') - BYPASS_KIBANA_AUTH = strtobool(os.getenv("BYPASS_KIBANA_AUTH", "no")) - CYPRESS_TOKEN = os.getenv('CYPRESS_TOKEN', None) diff --git a/tdrs-backend/tdpservice/urls.py b/tdrs-backend/tdpservice/urls.py index 368314c92..ee4c37701 100755 --- a/tdrs-backend/tdpservice/urls.py +++ b/tdrs-backend/tdpservice/urls.py @@ -52,7 +52,7 @@ urlpatterns = [ path("v1/", include(urlpatterns)), path("admin/", admin.site.urls, name="admin"), - path("kibana/", KibanaAuthorizationCheck.as_view(), name="kibana-authorization-check"), + path("kibana_auth_check/", KibanaAuthorizationCheck.as_view(), name="kibana-authorization-check"), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # TODO: Supply `terms_of_service` argument in OpenAPI Info once implemented diff --git a/tdrs-backend/tdpservice/users/api/authorization_check.py b/tdrs-backend/tdpservice/users/api/authorization_check.py index 76afeecb1..191e80055 100644 --- a/tdrs-backend/tdpservice/users/api/authorization_check.py +++ b/tdrs-backend/tdpservice/users/api/authorization_check.py @@ -8,7 +8,7 @@ from rest_framework.response import Response from rest_framework.views import APIView from ..serializers import UserProfileSerializer -from django.http import HttpResponseRedirect +from django.http import HttpResponse from django.conf import settings logger = logging.getLogger(__name__) @@ -66,6 +66,8 @@ def get(self, request, *args, **kwargs): user_in_valid_group = user.is_ofa_sys_admin if (user.hhs_id is not None and user_in_valid_group) or settings.BYPASS_KIBANA_AUTH: - return HttpResponseRedirect(settings.KIBANA_BASE_URL) + logger.debug(f"User: {user} has correct authentication credentials. Allowing access to Kibana.") + return HttpResponse(status=200) else: - return HttpResponseRedirect(settings.FRONTEND_BASE_URL) + logger.debug(f"User: {user} has incorrect authentication credentials. Not allowing access to Kibana.") + return HttpResponse(status=401) diff --git a/tdrs-frontend/.env b/tdrs-frontend/.env index 882a4aafa..11902ac81 100644 --- a/tdrs-frontend/.env +++ b/tdrs-frontend/.env @@ -36,6 +36,9 @@ REACT_APP_DEBOUNCE_TIME=30000 # 60 seconds == 60 * 1000 == 60000 REACT_APP_EVENT_THROTTLE_TIME=60000 +# Enable the Kibana tab for dev purposes. +# REACT_APP_DEV_KIBANA=true + # Setup SCSS: # The following makes it possible to import SASS modules # without relative paths. Removing this will require all @imports in diff --git a/tdrs-frontend/docker-compose.yml b/tdrs-frontend/docker-compose.yml index 23c0a0669..abfb2ba18 100644 --- a/tdrs-frontend/docker-compose.yml +++ b/tdrs-frontend/docker-compose.yml @@ -28,18 +28,19 @@ services: - NGINX_FRONTEND=tdp-frontend - BACK_END=web - LOCAL_DEV=true + - KIBANA=kibana - REACT_APP_DEVAUTH=${REACT_APP_DEVAUTH} command: > /bin/sh -c "echo 'starting nginx' && - envsubst '$${BACK_END}' < /etc/nginx/locations.conf > /etc/nginx/locations_.conf && + envsubst '$${BACK_END} $${KIBANA}' < /etc/nginx/locations.conf > /etc/nginx/locations_.conf && rm /etc/nginx/locations.conf && cp /etc/nginx/locations_.conf /etc/nginx/locations.conf && envsubst ' - $${BACK_END} $${NGINX_FRONTEND} $${LOCAL_DEV} + $${KIBANA} $${BACK_END} $${NGINX_FRONTEND} $${LOCAL_DEV} '< /etc/nginx/default.conf.template - > /etc/nginx/nginx.conf - && nginx -g 'daemon off;'" + > /etc/nginx/nginx.conf && + nginx -g 'daemon off;'" networks: default: diff --git a/tdrs-frontend/manifest.buildpack.yml b/tdrs-frontend/manifest.buildpack.yml index 93956849a..d8a134a87 100755 --- a/tdrs-frontend/manifest.buildpack.yml +++ b/tdrs-frontend/manifest.buildpack.yml @@ -4,7 +4,7 @@ applications: - name: tdp-frontend buildpacks: - https://github.com/cloudfoundry/nginx-buildpack.git#v1.2.6 - memory: 128M + memory: 256M instances: 1 disk_quota: 256M timeout: 180 diff --git a/tdrs-frontend/manifest.yml b/tdrs-frontend/manifest.yml index f42e7d092..d9b8ef423 100755 --- a/tdrs-frontend/manifest.yml +++ b/tdrs-frontend/manifest.yml @@ -2,7 +2,7 @@ version: 1 applications: - name: tdp-frontend - memory: 32M + memory: 256M instances: 1 disk_quota: 256M timeout: 180 diff --git a/tdrs-frontend/nginx/cloud.gov/buildpack.nginx.conf b/tdrs-frontend/nginx/cloud.gov/buildpack.nginx.conf index 4ed6804f9..514010873 100644 --- a/tdrs-frontend/nginx/cloud.gov/buildpack.nginx.conf +++ b/tdrs-frontend/nginx/cloud.gov/buildpack.nginx.conf @@ -34,6 +34,8 @@ http { limit_req_zone $binary_remote_addr zone=limitreqsbyaddr:20m rate=1000r/s; limit_req_status 444; + resolver {{nameservers}} valid=10s; + server { root public; listen {{port}}; @@ -61,9 +63,9 @@ http { set $ALLOWED_ORIGIN {{env "ALLOWED_ORIGIN"}}; set $CSP "default-src 'self';"; - set $CSP "${CSP}script-src 'self';"; - set $CSP "${CSP}script-src-elem 'self';"; - set $CSP "${CSP}script-src-attr 'self' 'unsafe-inline';"; + set $CSP "${CSP}script-src 'self' 'unsafe-eval' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; + set $CSP "${CSP}script-src-elem 'self' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; + set $CSP "${CSP}script-src-attr 'self' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; set $CSP "${CSP}img-src 'self' data:;"; set $CSP "${CSP}font-src 'self';"; set $CSP "${CSP}connect-src 'self' ${CONNECT_SRC};"; @@ -75,9 +77,9 @@ http { set $CSP "${CSP}child-src 'none';"; set $CSP "${CSP}media-src 'none';"; set $CSP "${CSP}prefetch-src 'none';"; - set $CSP "${CSP}style-src 'self' 'unsafe-inline';"; - set $CSP "${CSP}style-src-elem 'self' 'unsafe-inline';"; - set $CSP "${CSP}style-src-attr 'self' 'unsafe-inline';"; + set $CSP "${CSP}style-src 'self' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; + set $CSP "${CSP}style-src-elem 'self' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; + set $CSP "${CSP}style-src-attr 'self' 'unsafe-inline' http://{{env "KIBANA_BASE_URL"}}:5601;"; set $CSP "${CSP}worker-src 'none';"; add_header Content-Security-Policy $CSP; diff --git a/tdrs-frontend/nginx/cloud.gov/locations.conf b/tdrs-frontend/nginx/cloud.gov/locations.conf index a6c6d7b42..b7cd5517f 100644 --- a/tdrs-frontend/nginx/cloud.gov/locations.conf +++ b/tdrs-frontend/nginx/cloud.gov/locations.conf @@ -22,8 +22,43 @@ location ~ ^/(v1|admin|static/admin|swagger|redocs) { add_header Access-Control-Allow-Origin 's3-us-gov-west-1.amazonaws.com'; } -if ($request_method ~ ^(TRACE|OPTION)$) { - return 405; +location /kibana/ { + auth_request /kibana_auth_check; + auth_request_set $auth_status $upstream_status; + + proxy_pass http://{{env "KIBANA_BASE_URL"}}:5601/; + proxy_pass_header x-csrftoken; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + proxy_connect_timeout 900; + proxy_read_timeout 300; + proxy_send_timeout 300; + send_timeout 900; + proxy_buffer_size 4k; + + proxy_hide_header Referrer-Policy; +} + +location = /kibana_auth_check { + internal; + proxy_pass http://{{env "BACKEND_HOST"}}.apps.internal:8080/kibana_auth_check/; + proxy_pass_header x-csrftoken; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + proxy_connect_timeout 900; + proxy_read_timeout 300; + proxy_send_timeout 300; + send_timeout 900; +} + +if ($request_method ~ ^(TRACE|OPTION)$) { + return 405; } location = /profile { diff --git a/tdrs-frontend/nginx/local/default.conf.template b/tdrs-frontend/nginx/local/default.conf.template index c4d306340..8cf7b79ab 100644 --- a/tdrs-frontend/nginx/local/default.conf.template +++ b/tdrs-frontend/nginx/local/default.conf.template @@ -68,8 +68,8 @@ http { # CSP header options. All options are set either to none or self except set $CSP "default-src 'none';"; - set $CSP "${CSP}script-src 'self';"; - set $CSP "${CSP}style-src 'self' 'unsafe-inline' http://localhost:3000;"; + set $CSP "${CSP}script-src 'self' 'unsafe-eval' 'unsafe-inline' http://${KIBANA}:5601;"; + set $CSP "${CSP}style-src 'self' 'unsafe-inline' http://localhost:3000 http://${KIBANA}:5601;"; set $CSP "${CSP}img-src 'self' data:;"; set $CSP "${CSP}font-src 'self';"; set $CSP "${CSP}connect-src 'self' localhost:*;"; @@ -79,12 +79,11 @@ http { set $CSP "${CSP}frame-ancestors 'none';"; set $CSP "${CSP}child-src 'none';"; set $CSP "${CSP}media-src 'none';"; - set $CSP "${CSP}prefetch-src 'none';"; set $CSP "${CSP}form-action *;"; - set $CSP "${CSP}script-src-elem 'self' http://localhost:* http://www.w3.org;"; - set $CSP "${CSP}script-src-attr 'self' 'unsafe-inline';"; - set $CSP "${CSP}style-src-elem 'self' 'unsafe-inline';"; - set $CSP "${CSP}style-src-attr 'self';"; + set $CSP "${CSP}script-src-elem 'self' 'unsafe-inline' http://localhost:* http://www.w3.org http://${KIBANA}:5601;"; + set $CSP "${CSP}script-src-attr 'self' 'unsafe-inline' http://${KIBANA}:5601;"; + set $CSP "${CSP}style-src-elem 'self' 'unsafe-inline' http://${KIBANA}:5601;"; + set $CSP "${CSP}style-src-attr 'self' 'unsafe-inline' http://${KIBANA}:5601;"; set $CSP "${CSP}worker-src 'none';"; add_header Content-Security-Policy $CSP; @@ -136,7 +135,6 @@ http { set $CSP "${CSP}frame-src 'None';"; set $CSP "${CSP}child-src 'none';"; set $CSP "${CSP}media-src 'none';"; - set $CSP "${CSP}prefetch-src 'none';"; set $CSP "${CSP}style-src 'self' 'unsafe-inline';"; set $CSP "${CSP}style-src-elem 'self' 'unsafe-inline';"; set $CSP "${CSP}style-src-attr 'self' 'unsafe-inline';"; diff --git a/tdrs-frontend/nginx/local/locations.conf b/tdrs-frontend/nginx/local/locations.conf index 154cda557..e7ff75fcb 100644 --- a/tdrs-frontend/nginx/local/locations.conf +++ b/tdrs-frontend/nginx/local/locations.conf @@ -4,7 +4,7 @@ location = /nginx_status { deny all; } -location ~ ^/(v1|admin|static/admin|swagger|redocs|kibana) { +location ~ ^/(v1|admin|static/admin|swagger|redocs) { limit_req zone=limitreqsbyaddr delay=5; proxy_pass http://${BACK_END}:8080$request_uri; proxy_set_header Host $host:3000; @@ -21,6 +21,43 @@ location ~ ^/(v1|admin|static/admin|swagger|redocs|kibana) { proxy_pass_header x-csrftoken; } +location /kibana/ { + auth_request /kibana_auth_check; + auth_request_set $auth_status $upstream_status; + + proxy_pass http://${KIBANA}:5601/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + proxy_connect_timeout 300; + proxy_read_timeout 300; + proxy_send_timeout 300; + send_timeout 900; + proxy_buffer_size 4k; + + proxy_hide_header Referrer-Policy; +} + +location = /kibana_auth_check { + internal; + proxy_pass http://${BACK_END}:8080/kibana_auth_check/; + proxy_set_header Host $host:3000; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-URI $request_uri; + + proxy_connect_timeout 300; + proxy_read_timeout 300; + proxy_send_timeout 300; + send_timeout 900; + proxy_pass_header x-csrftoken; +} + location = /profile { index index.html index.htm; try_files $uri $uri/ /index.html; diff --git a/tdrs-frontend/src/components/Home/Home.jsx b/tdrs-frontend/src/components/Home/Home.jsx index e102f8acc..8d6b57e36 100644 --- a/tdrs-frontend/src/components/Home/Home.jsx +++ b/tdrs-frontend/src/components/Home/Home.jsx @@ -23,7 +23,6 @@ function Home() { const errorRef = useRef(null) const user = useSelector((state) => state.auth.user) - const role = useSelector(selectPrimaryUserRole) const [errors, setErrors] = useState({}) const [profileInfo, setProfileInfo] = useState({ diff --git a/tdrs-frontend/src/components/STTComboBox/STTComboBox.jsx b/tdrs-frontend/src/components/STTComboBox/STTComboBox.jsx index 4f8adf0f2..21da77488 100644 --- a/tdrs-frontend/src/components/STTComboBox/STTComboBox.jsx +++ b/tdrs-frontend/src/components/STTComboBox/STTComboBox.jsx @@ -3,7 +3,6 @@ import PropTypes from 'prop-types' import { useDispatch, useSelector } from 'react-redux' import { fetchSttList } from '../../actions/sttList' import ComboBox from '../ComboBox' -import Button from '../Button' import Modal from '../Modal' /** @@ -38,8 +37,6 @@ function STTComboBox({ selectStt, selectedStt, handleBlur, error }) { } }, [dispatch, sttListRequest.sttList, numTries, reachedMaxTries]) - const modalRef = useRef() - const headerRef = useRef() const onSignOut = () => { window.location.href = `${process.env.REACT_APP_BACKEND_URL}/logout/oidc` } diff --git a/tdrs-frontend/src/selectors/auth.js b/tdrs-frontend/src/selectors/auth.js index ab962e275..eac564a09 100644 --- a/tdrs-frontend/src/selectors/auth.js +++ b/tdrs-frontend/src/selectors/auth.js @@ -62,4 +62,6 @@ export const accountCanViewAdmin = (state) => export const accountCanViewKibana = (state) => accountStatusIsApproved(state) && - ['Developer', 'OFA System Admin'].includes(selectPrimaryUserRole(state)?.name) + (selectUser(state)?.email?.includes('@acf.hhs.gov') || + process.env.REACT_APP_DEV_KIBANA) && + ['OFA System Admin'].includes(selectPrimaryUserRole(state)?.name)