From 18696e1af8d50ed009e57cd03ca041fa9ce6fd87 Mon Sep 17 00:00:00 2001 From: "timothy.spencer" Date: Wed, 11 Sep 2024 21:03:58 +0000 Subject: [PATCH 1/3] This is to get an image that we can use in kubernetes-land in a production-like way. * Add prod pivcac image * Make sure image is largely read-only to the app user * Add RDS cert bundle * Add nginx image * make prod pivcac image and nginx images be built automatically by gitlab --- .gitlab-ci.yml | 80 +++++++++++++++++++ Dockerfile | 79 ++++++++++++++++-- Gemfile.lock | 2 +- k8.Dockerfile | 8 +- k8files/nginx-prod.conf | 172 ++++++++++++++++++++++++++++++++++++++++ k8files/update-ips.sh | 21 +++++ nginx.Dockerfile | 11 +++ prod.Dockerfile | 153 +++++++++++++++++++++++++++++++++++ 8 files changed, 513 insertions(+), 13 deletions(-) create mode 100644 k8files/nginx-prod.conf create mode 100755 k8files/update-ips.sh create mode 100644 nginx.Dockerfile create mode 100644 prod.Dockerfile diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b34e26e7..2d4d55bda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -210,6 +210,86 @@ build-pivcac-image: --compressed-caching=false --build-arg "http_proxy=${http_proxy}" --build-arg "https_proxy=${https_proxy}" --build-arg "no_proxy=${no_proxy}" +# Build a container image async, and don't block CI tests +# Cache intermediate images for 1 week (168 hours) +build-prod-pivcac-image: + stage: review + needs: [] + interruptible: true + variables: + BRANCH_TAGGING_STRING: "" + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + variables: + BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/review:main" + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH + - if: $CI_PIPELINE_SOURCE != "merge_request_event" + when: never + tags: + - build-pool + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [''] + script: + - mkdir -p /kaniko/.docker + - |- + KANIKOCFG="\"credsStore\":\"ecr-login\"" + if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then + KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}" + fi + KANIKOCFG="{ ${KANIKOCFG} }" + echo "${KANIKOCFG}" > /kaniko/.docker/config.json + - >- + /kaniko/executor + --context "${CI_PROJECT_DIR}" + --dockerfile "${CI_PROJECT_DIR}/prod.Dockerfile" + --destination "${ECR_REGISTRY}/identity-pivcac/pivcac:${CI_COMMIT_SHA}" + ${BRANCH_TAGGING_STRING} + --cache-repo="${ECR_REGISTRY}/identity-pivcac/pivcac/cache" + --cache-ttl=168h + --cache=true + --compressed-caching=false + --build-arg "http_proxy=${http_proxy}" --build-arg "https_proxy=${https_proxy}" --build-arg "no_proxy=${no_proxy}" + +build-prod-nginx-image: + stage: review + needs: [] + interruptible: true + variables: + BRANCH_TAGGING_STRING: "" + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + variables: + BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/review:main" + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH + - if: $CI_PIPELINE_SOURCE != "merge_request_event" + when: never + tags: + - build-pool + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [''] + script: + - mkdir -p /kaniko/.docker + - |- + KANIKOCFG="\"credsStore\":\"ecr-login\"" + if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then + KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}" + fi + KANIKOCFG="{ ${KANIKOCFG} }" + echo "${KANIKOCFG}" > /kaniko/.docker/config.json + - >- + /kaniko/executor + --context "${CI_PROJECT_DIR}" + --dockerfile "${CI_PROJECT_DIR}/nginx.Dockerfile" + --destination "${ECR_REGISTRY}/identity-pivcac/nginx:${CI_COMMIT_SHA}" + ${BRANCH_TAGGING_STRING} + --cache-repo="${ECR_REGISTRY}/identity-pivcac/pivcac/cache" + --cache-ttl=168h + --cache=true + --compressed-caching=false + --build-arg "http_proxy=${http_proxy}" --build-arg "https_proxy=${https_proxy}" --build-arg "no_proxy=${no_proxy}" + review-app: stage: review allow_failure: true diff --git a/Dockerfile b/Dockerfile index 440c1efe0..d7613a141 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,27 @@ # Use the official Ruby image because the Rails images have been deprecated -FROM logindotgov/build as build +FROM ruby:3.3.1-slim as build + +RUN apt-get update && \ + apt-get install -y \ + git-core \ + build-essential \ + git-lfs \ + curl \ + zlib1g-dev \ + libssl-dev \ + libreadline-dev \ + libyaml-dev \ + libsqlite3-dev \ + sqlite3 \ + libxml2-dev \ + libxslt1-dev \ + libcurl4-openssl-dev \ + software-properties-common \ + libffi-dev \ + libpq-dev \ + xz-utils \ + unzip && \ + rm -rf /var/lib/apt/lists/* # Everything happens here from now on WORKDIR /pivcac @@ -9,20 +31,61 @@ COPY Gemfile* ./ RUN gem install bundler --conservative && \ bundle install --without deploy production -# Copy everything else over -COPY . . +# Generate and place SSL certificates for puma +RUN mkdir -p /pivcac/keys +RUN openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 1825 \ + -keyout /pivcac/keys/localhost.key \ + -out /pivcac/keys/localhost.crt \ + -subj "/C=US/ST=Fake/L=Fakerton/O=Dis/CN=localhost" && \ + chmod 644 /pivcac/keys/localhost.key /pivcac/keys/localhost.crt + +# Download RDS Combined CA Bundle +RUN mkdir -p /usr/local/share/aws \ + && curl https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem > /usr/local/share/aws/rds-combined-ca-bundle.pem \ + && chmod 644 /usr/local/share/aws/rds-combined-ca-bundle.pem + # Switch to base image -FROM logindotgov/base +FROM ruby:3.3.1-slim WORKDIR /pivcac +RUN apt-get update && \ + apt-get install -y \ + curl \ + zlib1g-dev \ + libssl-dev \ + libreadline-dev \ + libyaml-dev \ + libxml2-dev \ + libxslt1-dev \ + libcurl4-openssl-dev \ + libffi-dev \ + libpq-dev && \ + rm -rf /var/lib/apt/lists/* + # Copy Gems, NPMs, and other relevant items from build layer -COPY --chown=appuser:appuser --from=build /pivcac . +COPY --from=build /pivcac . # Copy in whole source (minus items matched in .dockerignore) -COPY --chown=appuser:appuser . . +COPY . . + +# Create a new user and set up the working directory +RUN addgroup --gid 1000 app && \ + adduser --uid 1000 --gid 1000 --disabled-password --gecos "" app && \ + mkdir -p /pivcac && \ + mkdir -p /pivcac/tmp/pids && \ + mkdir -p /pivcac/log + +# make everything the proper perms after everything is initialized +RUN chown -R app:app /pivcac/tmp && \ + chown -R app:app /pivcac/log && \ + find /pivcac -type d | xargs chmod 755 + +# get rid of suid/sgid binaries +RUN find / -perm /4000 -type f | xargs chmod u-s +RUN find / -perm /2000 -type f | xargs chmod g-s -USER appuser +USER app EXPOSE 8443 -CMD ["bundle", "exec", "rackup", "config.ru", "--host", "ssl://localhost:8443?key=config/local-certs/server.key&cert=config/local-certs/server.crt"] +CMD ["bundle", "exec", "rackup", "config.ru", "--host", "ssl://0.0.0.0:3000?key=/pivcac/keys/localhost.key&cert=/pivcac/keys/localhost.crt"] diff --git a/Gemfile.lock b/Gemfile.lock index a2bb377f3..d8fbe290f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -260,7 +260,7 @@ GEM regexp_parser (2.7.0) request_store (1.5.1) rack (>= 1.4) - rexml (3.3.3) + rexml (3.3.6) strscan rgl (0.5.6) lazy_priority_queue (~> 0.1.0) diff --git a/k8.Dockerfile b/k8.Dockerfile index 250c80f46..099a8bfa6 100644 --- a/k8.Dockerfile +++ b/k8.Dockerfile @@ -21,13 +21,13 @@ ENV TZ=Etc/UTC RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # Install dependencies -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y \ build-essential \ cron \ - curl \ + curl \ gettext-base \ git-core \ - tar \ + tar \ unzip \ jq \ libcurl4-openssl-dev \ @@ -99,7 +99,7 @@ COPY --chmod=644 ./k8files/status.conf /opt/nginx/conf/sites.d/ COPY ./k8files/pivcac.conf /opt/nginx/conf/sites.d/pivcac.conftemp # Download RDS Combined CA Bundles -RUN wget -P /usr/local/share/aws/ https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem +RUN wget -P /usr/local/share/aws/ https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem # Create cron jobs RUN echo '* */4 * * * websrv flock -n /tmp/update_cert_revocations.lock -c /usr/local/bin/update_cert_revocations' > /etc/cron.d/update_cert_revocations; \ diff --git a/k8files/nginx-prod.conf b/k8files/nginx-prod.conf new file mode 100644 index 000000000..416475ba4 --- /dev/null +++ b/k8files/nginx-prod.conf @@ -0,0 +1,172 @@ +#user nginx; +worker_processes 2; +worker_rlimit_nofile 2048; +pid /var/run/nginx.pid; +daemon off; +load_module /usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so; + + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush off; + keepalive_timeout 60 50; + gzip on; + gzip_types text/plain text/css application/xml application/javascript application/json image/jpg image/jpeg image/png image/gif image/svg+xml font/woff2 woff2; + + # Timeouts definition + client_body_timeout 10; + client_header_timeout 10; + send_timeout 10; + # Set buffer size limits + client_body_buffer_size 1k; + client_header_buffer_size 1k; + client_max_body_size 20k; + large_client_header_buffers 2 20k; + # Limit connections + limit_conn addr 20; + limit_conn_status 429; + limit_conn_zone $binary_remote_addr zone=addr:5m; + # Disable sending server info and versions + server_tokens off; + more_clear_headers Server; + more_clear_headers X-Powered-By; + # Prevent clickJacking attack + add_header X-Frame-Options SAMEORIGIN; + # Disable content-type sniffing + add_header X-Content-Type-Options nosniff; + # Enable XSS filter + add_header X-XSS-Protection "1; mode=block"; + + # Enables nginx to check multiple set_real_ip_from lines + real_ip_recursive on; + + real_ip_header X-Forwarded-For; + + # Exclude all private IPv4 space from client source calculation when + # processing the X-Forewarded-For header + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 100.64.0.0/10; + set_real_ip_from 172.16.0.0/12; + set_real_ip_from 192.168.0.0/16; + # TODO - IPv6 CIDR for VPCs will require autoconfiguration + + # Add CloudFront source address ranges to trusted CIDR range for real ip computation + include /etc/nginx/cloudfront-ips.conf; + + # logging + access_log /dev/stdout; + error_log /dev/stdout info; + + # Specify a key=value format useful for machine parsing + log_format kv escape=json + '{' + '"time": "$time_local", ' + '"hostname": "$host", ' + '"dest_port": "$server_port", ' + '"dest_ip": "$server_addr", ' + '"src": "$remote_addr", ' + '"src_ip": "$realip_remote_addr", ' + '"user": "$remote_user", ' + '"protocol": "$server_protocol", ' + '"http_method": "$request_method", ' + '"status": "$status", ' + '"bytes_out": "$body_bytes_sent", ' + '"bytes_in": "$request_length", ' + '"http_referer": "$http_referer", ' + '"http_user_agent": "$http_user_agent", ' + '"nginx_version": "$nginx_version", ' + '"http_cloudfront_viewer_address": "$http_cloudfront_viewer_address", ' + '"http_cloudfront_viewer_http_version": "$http_cloudfront_viewer_http_version", ' + '"http_cloudfront_viewer_tls": "$http_cloudfront_viewer_tls", ' + '"http_cloudfront_viewer_country": "$http_cloudfront_viewer_country", ' + '"http_cloudfront_viewer_country_region": "$http_cloudfront_viewer_country_region", ' + '"http_x_forwarded_for": "$http_x_forwarded_for", ' + '"http_x_amzn_trace_id": "$http_x_amzn_trace_id", ' + '"response_time": "$upstream_response_time", ' + '"request_time": "$request_time", ' + '"request": "$request", ' + '"tls_protocol": "$ssl_protocol", ' + '"tls_cipher": "$ssl_cipher", ' + '"uri_path": "$uri", ' + '"uri_query": "$query_string",' + '"log_filename": "nginx_access.log"' + '}'; + + # Get $status_reason variable, a human readable version of $status + include status-map.conf; + + # Set HSTS header only if not already set by app. Some clients get unhappy if + # you set multiple Strict-Transport-Security headers. + # https://serverfault.com/a/598106 + map $upstream_http_strict_transport_security $sts_value { + '' "max-age=31536000; preload"; + } + + # Always add a HSTS header - This is still inside the http block, so will not + # conflict with headers set in nginx.conf + add_header Strict-Transport-Security $sts_value always; + + server { + listen 8443 ssl; + server_name _; + access_log /dev/stdout kv; + + ssl_certificate /keys/tls.crt; + ssl_certificate_key /keys/tls.key; + ssl_client_certificate /etc/nginx/ficam_bundle.pem; + ssl_verify_client optional_no_ca; # on; + ssl_verify_depth 10; + + ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!ECDHE-RSA-AES256-SHA384:!ECDHE-RSA-AES256-SHA:!DHE-RSA-AES256-SHA256:!DHE-RSA-AES256-SHA'; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + ssl_prefer_server_ciphers on; + ssl_protocols TLSv1.2; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + proxy_buffer_size 32k; + proxy_buffers 8 32k; + proxy_busy_buffers_size 64k; + + location ~* \.(html|txt|ico|png|json)$ { + root "/srv"; + try_files $uri @backend; + } + + location / { + proxy_pass https://0.0.0.0:3000; + + proxy_set_header X-Real-Host $host; + proxy_set_header X-Real-Ip $remote_addr; + proxy_set_header X-Real-Proto https; + proxy_set_header X-Client-Verify $ssl_client_verify; + proxy_set_header X-Client-S-Dn $ssl_client_s_dn; + proxy_set_header X-Client-I-Dn $ssl_client_i_dn; + proxy_set_header X-Client-Serial $ssl_client_serial; + proxy_set_header X-Client-Fingerprint $ssl_client_fingerprint; + proxy_set_header X-Client-Cert $ssl_client_escaped_cert; + } + + location @backend { + proxy_pass https://0.0.0.0:3000; + + proxy_set_header X-Real-Host $host; + proxy_set_header X-Real-Ip $remote_addr; + proxy_set_header X-Real-Proto https; + proxy_set_header X-Client-Verify $ssl_client_verify; + proxy_set_header X-Client-S-Dn $ssl_client_s_dn; + proxy_set_header X-Client-I-Dn $ssl_client_i_dn; + proxy_set_header X-Client-Serial $ssl_client_serial; + proxy_set_header X-Client-Fingerprint $ssl_client_fingerprint; + proxy_set_header X-Client-Cert $ssl_client_escaped_cert; + } + } +} diff --git a/k8files/update-ips.sh b/k8files/update-ips.sh new file mode 100755 index 000000000..102c2ee86 --- /dev/null +++ b/k8files/update-ips.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# This script updates the ips.conf file so that we have +# up-to-date cloudfront IP information. +# +set -e + +IPS_CONF="/etc/nginx/cloudfront-ips.conf" +echo "Updating $IPS_CONF" + +rm -f "$IPS_CONF" +echo '# cloudfront IP ranges' > $IPS_CONF +echo '# ' >> $IPS_CONF + +curl -s https://ip-ranges.amazonaws.com/ip-ranges.json | jq -r '.prefixes[] | select(.service=="CLOUDFRONT_ORIGIN_FACING") | .ip_prefix' | while read i ; do + echo "set_real_ip_from $i;" >> $IPS_CONF +done + +curl -s https://ip-ranges.amazonaws.com/ip-ranges.json | jq -r '.ipv6_prefixes[] | select(.service=="CLOUDFRONT") | .ipv6_prefix' | while read i ; do + echo "set_real_ip_from $i;" >> $IPS_CONF +done diff --git a/nginx.Dockerfile b/nginx.Dockerfile new file mode 100644 index 000000000..c79e52043 --- /dev/null +++ b/nginx.Dockerfile @@ -0,0 +1,11 @@ +FROM public.ecr.aws/docker/library/alpine:3 + +RUN apk add --no-cache jq curl nginx nginx-mod-http-headers-more + +COPY ./k8files/update-ips.sh /update-ips.sh +COPY ./k8files/nginx-prod.conf /etc/nginx/nginx.conf +COPY ./k8files/status-map.conf /etc/nginx/ +COPY ./config/cert_bundles/ficam_bundle.pem /etc/nginx/ +RUN /update-ips.sh + +ENTRYPOINT ["/usr/sbin/nginx"] diff --git a/prod.Dockerfile b/prod.Dockerfile new file mode 100644 index 000000000..b6e740240 --- /dev/null +++ b/prod.Dockerfile @@ -0,0 +1,153 @@ +# this part builds everything +FROM ruby:3.3.4-slim-bullseye as builder + +# Set environment variables +ENV RAILS_ROOT /app +ENV RAILS_ENV production +ENV BUNDLE_PATH /app/vendor/bundle +ENV NGINX_VERSION 1.22.0 + +# Install dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + curl \ + gettext-base \ + git-core \ + tar \ + unzip \ + jq \ + libcurl4-openssl-dev \ + libjemalloc-dev \ + libpcre3 \ + libpcre3-dev \ + libssl-dev \ + libpq-dev \ + patch \ + python3 \ + python3-pip \ + python3-venv \ + util-linux \ + wget \ + && rm -rf /var/lib/apt/lists/* + +# Download RDS Combined CA Bundle +RUN mkdir -p /usr/local/share/aws \ + && curl https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem > /usr/local/share/aws/rds-combined-ca-bundle.pem \ + && chmod 644 /usr/local/share/aws/rds-combined-ca-bundle.pem + +# Create working directory +WORKDIR $RAILS_ROOT + +# do a bundle install +COPY .ruby-version $RAILS_ROOT/.ruby-version +COPY Gemfile $RAILS_ROOT/Gemfile +COPY Gemfile.lock $RAILS_ROOT/Gemfile.lock +RUN bundle config build.nokogiri --use-system-libraries +RUN bundle config set --local deployment 'true' +RUN bundle config set --local path $BUNDLE_PATH +RUN bundle config set --local without 'deploy development doc test' +RUN bundle install --jobs $(nproc) +RUN bundle binstubs --all + + + +##################################################### +# here is where the actual image gets built +FROM ruby:3.3.4-slim-bullseye + +SHELL ["/bin/bash", "-c"] + +# Set environment variables +ENV RAILS_ROOT /app +ENV RAILS_ENV production +ENV BUNDLE_PATH /app/vendor/bundle + +# Prevent documentation installation +RUN echo 'path-exclude=/usr/share/doc/*' > /etc/dpkg/dpkg.cfg.d/00_nodoc && \ + echo 'path-exclude=/usr/share/man/*' >> /etc/dpkg/dpkg.cfg.d/00_nodoc && \ + echo 'path-exclude=/usr/share/groff/*' >> /etc/dpkg/dpkg.cfg.d/00_nodoc && \ + echo 'path-exclude=/usr/share/info/*' >> /etc/dpkg/dpkg.cfg.d/00_nodoc && \ + echo 'path-exclude=/usr/share/lintian/*' >> /etc/dpkg/dpkg.cfg.d/00_nodoc && \ + echo 'path-exclude=/usr/share/linda/*' >> /etc/dpkg/dpkg.cfg.d/00_nodoc + +# Setup timezone data +ENV TZ=Etc/UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Install dependencies +RUN apt-get update && apt-get install -y \ + gettext-base \ + git-core \ + curl \ + libcurl4-openssl-dev \ + libjemalloc-dev \ + libpcre3 \ + libpcre3-dev \ + libssl-dev \ + libpq-dev \ + patch \ + util-linux \ + postgresql-contrib \ + && rm -rf /var/lib/apt/lists/* + +# Create user and setup working directory +RUN addgroup --gid 1000 app && \ + adduser --uid 1000 --gid 1000 --disabled-password --gecos "" app && \ + mkdir -p $RAILS_ROOT && \ + mkdir -p $RAILS_ROOT/tmp/pids && \ + mkdir -p $RAILS_ROOT/log + +# copy rds cert from builder +COPY --from=builder /usr/local/share/aws/rds-combined-ca-bundle.pem /usr/local/share/aws/rds-combined-ca-bundle.pem + +# Copy bundle in +COPY --from=builder $RAILS_ROOT $RAILS_ROOT + +COPY package.json $RAILS_ROOT/package.json + +WORKDIR $RAILS_ROOT + +# Copy Application Code +COPY ./lib ./lib +COPY ./app ./app +COPY ./config ./config +COPY ./config.ru ./config.ru +COPY ./db ./db +COPY ./bin ./bin +COPY ./public ./public +COPY ./spec ./spec +COPY ./vendor ./vendor +COPY ./Rakefile ./Rakefile +COPY ./Makefile ./Makefile +COPY ./Procfile ./Procfile +COPY ./log ./log +COPY ./tmp ./tmp +RUN mkdir -p ${RAILS_ROOT}/keys; chmod -R 0755 ${RAILS_ROOT}/keys; \ + mkdir -p ${RAILS_ROOT}/tmp/cache; chmod -R 0755 ${RAILS_ROOT}/tmp/cache; \ + mkdir -p ${RAILS_ROOT}/tmp/pids; chmod -R 0755 ${RAILS_ROOT}/tmp/pids; \ + mkdir -p ${RAILS_ROOT}/tmp/sockets; chmod -R 0755 ${RAILS_ROOT}/tmp/sockets; \ + mkdir -p ${RAILS_ROOT}/config/puma; chmod -R 0755 ${RAILS_ROOT}/config/puma; +COPY --chmod=644 ./k8files/newrelic.yml ./config/newrelic.yml + +# set bundler up +RUN bundle config build.nokogiri --use-system-libraries +RUN bundle config set --local deployment 'true' +RUN bundle config set --local path $BUNDLE_PATH +RUN bundle config set --local without 'deploy development doc test' + +# make everything the proper perms after everything is initialized +RUN chown -R app:app $RAILS_ROOT/tmp && \ + chown -R app:app $RAILS_ROOT/log && \ + find $RAILS_ROOT -type d | xargs chmod 755 + +# get rid of suid/sgid binaries +RUN find / -perm /4000 -type f | xargs chmod u-s +RUN find / -perm /2000 -type f | xargs chmod g-s + +# Expose port the app runs on +EXPOSE 443 + +USER app + +# The keys here are getting mapped in from a secret in the deployment. +CMD ["bundle", "exec", "rackup", "config.ru", "--host", "ssl://0.0.0.0:3000?key=/app/keys/tls.key&cert=/app/keys/tls.crt"] From 2c55673a82517ac31fb8e20c8c913434b12b31cf Mon Sep 17 00:00:00 2001 From: "stephen.shelton" Date: Tue, 24 Sep 2024 22:16:51 +0000 Subject: [PATCH 2/3] Updating BRANCH_TAGGING_STRING to match each build * Updating BRANCH_TAGGING_STRING to match each build --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2d4d55bda..7116148f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -221,7 +221,7 @@ build-prod-pivcac-image: rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH variables: - BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/review:main" + BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/pivcac:main" - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE != "merge_request_event" when: never @@ -260,7 +260,7 @@ build-prod-nginx-image: rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH variables: - BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/review:main" + BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-pivcac/nginx:main" - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE != "merge_request_event" when: never From e59b0ea206e99d950cf10a23a3630226a192b080 Mon Sep 17 00:00:00 2001 From: "mitchell.henke" Date: Fri, 27 Sep 2024 14:26:50 +0000 Subject: [PATCH 3/3] Upgrade to Rails 7.1 * update gems * remove unused gems * remove configs with only comments * remove secrets.yml * set secret key base * update puma * update brakeman * ruby * remove tzinfo-data * move secret_key_base to config * gems * add csv to Gemfile * Add redis gem back after Bloomfilter upgrade removed it * empty commit to trigger pipeline * Update to include all timezones * Add allow_other_hosts attribute to safe redirect * Remove zonebie in favor of setting random timezones in test.rb * WIP Co-authored-by: davida marion See merge request lg/identity-pki!25 --- Gemfile | 15 +- Gemfile.lock | 300 +++++++++--------- app/controllers/identify_controller.rb | 3 +- config/application.rb | 8 +- config/application.yml.default | 4 +- config/environments/development.rb | 7 +- config/environments/production.rb | 25 +- config/environments/test.rb | 11 +- .../initializers/filter_parameter_logging.rb | 8 +- config/initializers/secret_token.rb | 1 + config/secrets.yml | 32 -- db/schema.rb | 29 +- spec/rails_helper.rb | 2 +- spec/spec_helper.rb | 2 - spec/support/database_cleaner.rb | 26 -- 15 files changed, 222 insertions(+), 251 deletions(-) create mode 100644 config/initializers/secret_token.rb delete mode 100644 config/secrets.yml delete mode 100644 spec/support/database_cleaner.rb diff --git a/Gemfile b/Gemfile index a5bcb2319..037238440 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" } ruby '~> 3.3' -gem 'rails', '~> 7.0.8.3' +gem 'rails', '~> 7.1.0' gem 'activerecord-import', '>= 1.0.2' # pod identity requires 3.188.0 @@ -11,6 +11,8 @@ gem 'activerecord-import', '>= 1.0.2' gem 'aws-sdk-core', '>= 3.188.0' gem 'aws-sdk-s3' gem 'bloomfilter-rb' +gem 'csv' +gem 'redis' gem 'identity-hostdata', github: '18F/identity-hostdata', tag: 'v4.0.0' gem 'identity-logging', github: '18F/identity-logging', tag: 'v0.1.0' gem 'mini_cache' @@ -23,11 +25,11 @@ gem 'redacted_struct', '~> 2.0' gem 'rgl' group :development, :test do - gem 'bullet', '~> 7.0' + gem 'bullet', '~> 7.1.2' gem 'brakeman', require: false gem 'listen' gem 'pry-byebug' - gem 'rspec-rails', '>= 3.8.3' + gem 'rspec-rails', '~> 6.0' gem 'rubocop', require: false gem 'rubocop-rails', '>= 2.19.0', require: false gem 'rubocop-performance', '~> 1.17', require: false @@ -38,18 +40,11 @@ group :development do end group :test do - gem 'axe-matchers', '~> 1.3.4' gem 'bundler-audit', require: false - gem 'database_cleaner' gem 'factory_bot_rails', '>= 5.2.0' - gem 'fakefs', require: 'fakefs/safe' gem 'rails-controller-testing', '>= 1.0.4' gem 'rspec_junit_formatter' gem 'shoulda-matchers', '~> 3.1', '>= 3.1.3', require: false gem 'simplecov', '>= 0.13.0' - gem 'timecop' gem 'webmock' - gem 'zonebie' end - -gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby] diff --git a/Gemfile.lock b/Gemfile.lock index d8fbe290f..89cbb130e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,72 +20,81 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.0.8.4) - actionpack (= 7.0.8.4) - activesupport (= 7.0.8.4) + actioncable (7.1.4) + actionpack (= 7.1.4) + activesupport (= 7.1.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8.4) - actionpack (= 7.0.8.4) - activejob (= 7.0.8.4) - activerecord (= 7.0.8.4) - activestorage (= 7.0.8.4) - activesupport (= 7.0.8.4) + zeitwerk (~> 2.6) + actionmailbox (7.1.4) + actionpack (= 7.1.4) + activejob (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.8.4) - actionpack (= 7.0.8.4) - actionview (= 7.0.8.4) - activejob (= 7.0.8.4) - activesupport (= 7.0.8.4) + actionmailer (7.1.4) + actionpack (= 7.1.4) + actionview (= 7.1.4) + activejob (= 7.1.4) + activesupport (= 7.1.4) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp - rails-dom-testing (~> 2.0) - actionpack (7.0.8.4) - actionview (= 7.0.8.4) - activesupport (= 7.0.8.4) - rack (~> 2.0, >= 2.2.4) + rails-dom-testing (~> 2.2) + actionpack (7.1.4) + actionview (= 7.1.4) + activesupport (= 7.1.4) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.8.4) - actionpack (= 7.0.8.4) - activerecord (= 7.0.8.4) - activestorage (= 7.0.8.4) - activesupport (= 7.0.8.4) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.4) + actionpack (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8.4) - activesupport (= 7.0.8.4) + actionview (7.1.4) + activesupport (= 7.1.4) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.8.4) - activesupport (= 7.0.8.4) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.4) + activesupport (= 7.1.4) globalid (>= 0.3.6) - activemodel (7.0.8.4) - activesupport (= 7.0.8.4) - activerecord (7.0.8.4) - activemodel (= 7.0.8.4) - activesupport (= 7.0.8.4) + activemodel (7.1.4) + activesupport (= 7.1.4) + activerecord (7.1.4) + activemodel (= 7.1.4) + activesupport (= 7.1.4) + timeout (>= 0.4.0) activerecord-import (1.5.0) activerecord (>= 4.2) - activestorage (7.0.8.4) - actionpack (= 7.0.8.4) - activejob (= 7.0.8.4) - activerecord (= 7.0.8.4) - activesupport (= 7.0.8.4) + activestorage (7.1.4) + actionpack (= 7.1.4) + activejob (= 7.1.4) + activerecord (= 7.1.4) + activesupport (= 7.1.4) marcel (~> 1.0) - mini_mime (>= 1.1.0) - activesupport (7.0.8.4) + activesupport (7.1.4) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) @@ -106,61 +115,55 @@ GEM aws-sigv4 (~> 1.4) aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) - axe-matchers (1.3.4) - dumb_delegator (~> 0.8) - virtus (~> 1.0) - axiom-types (0.1.1) - descendants_tracker (~> 0.0.4) - ice_nine (~> 0.11.0) - thread_safe (~> 0.3, >= 0.3.1) + base64 (0.2.0) better_errors (2.9.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) + bigdecimal (3.1.8) bloomfilter-rb (2.1.1) redis - bootsnap (1.17.0) + bootsnap (1.18.4) msgpack (~> 1.2) - brakeman (6.0.1) - builder (3.2.4) - bullet (7.0.7) + brakeman (6.2.1) + racc + builder (3.3.0) + bullet (7.1.6) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) - bundler-audit (0.9.1) + bundler-audit (0.9.2) bundler (>= 1.2.0, < 3) thor (~> 1.0) byebug (11.1.3) coderay (1.1.3) - coercible (1.0.0) - descendants_tracker (~> 0.0.1) - concurrent-ruby (1.3.1) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) crack (0.4.5) rexml crass (1.0.6) - database_cleaner (1.8.5) + csv (3.3.0) date (3.3.4) - descendants_tracker (0.0.4) - thread_safe (~> 0.3, >= 0.3.1) - diff-lcs (1.5.0) + diff-lcs (1.5.1) docile (1.4.0) - dumb_delegator (0.8.1) - equalizer (0.0.11) - erubi (1.12.0) - factory_bot (6.1.0) + drb (2.2.1) + erubi (1.13.0) + factory_bot (6.5.0) activesupport (>= 5.0.0) - factory_bot_rails (6.1.0) - factory_bot (~> 6.1.0) + factory_bot_rails (6.4.3) + factory_bot (~> 6.4) railties (>= 5.0.0) - fakefs (2.5.0) - ffi (1.17.0) + ffi (1.17.0-arm64-darwin) globalid (1.2.1) activesupport (>= 6.1) hashdiff (1.0.1) - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) - ice_nine (0.11.2) + io-console (0.7.2) + irb (1.14.1) + rdoc (>= 4.0.0) + reline (>= 0.4.2) jmespath (1.6.2) - json (2.6.3) + json (2.7.2) lazy_priority_queue (0.1.1) listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) @@ -179,13 +182,13 @@ GEM net-pop net-smtp marcel (1.0.4) - method_source (1.0.0) + method_source (1.1.0) mini_cache (1.1.0) mini_mime (1.1.5) - mini_portile2 (2.8.7) - minitest (5.23.1) + minitest (5.25.1) msgpack (1.7.2) - net-imap (0.4.12) + mutex_m (0.2.0) + net-imap (0.4.16) date net-protocol net-pop (0.1.2) @@ -195,13 +198,13 @@ GEM net-smtp (0.5.0) net-protocol newrelic_rpm (8.16.0) - nio4r (2.7.0) - nokogiri (1.16.5) - mini_portile2 (~> 2.8.2) + nio4r (2.7.3) + nokogiri (1.16.7-arm64-darwin) racc (~> 1.4) parallel (1.22.1) - parser (3.2.2.0) + parser (3.3.5.0) ast (~> 2.4.1) + racc pg (1.5.3) pry (0.14.2) coderay (~> 1.1) @@ -211,27 +214,34 @@ GEM pry (>= 0.13, < 0.15) pry-rails (0.3.9) pry (>= 0.10.4) + psych (5.1.2) + stringio public_suffix (4.0.6) - puma (6.4.2) + puma (6.4.3) nio4r (~> 2.0) - racc (1.8.0) - rack (2.2.9) + racc (1.8.1) + rack (3.1.7) + rack-session (2.0.0) + rack (>= 3.0.0) rack-test (2.1.0) rack (>= 1.3) - rails (7.0.8.4) - actioncable (= 7.0.8.4) - actionmailbox (= 7.0.8.4) - actionmailer (= 7.0.8.4) - actionpack (= 7.0.8.4) - actiontext (= 7.0.8.4) - actionview (= 7.0.8.4) - activejob (= 7.0.8.4) - activemodel (= 7.0.8.4) - activerecord (= 7.0.8.4) - activestorage (= 7.0.8.4) - activesupport (= 7.0.8.4) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.4) + actioncable (= 7.1.4) + actionmailbox (= 7.1.4) + actionmailer (= 7.1.4) + actionpack (= 7.1.4) + actiontext (= 7.1.4) + actionview (= 7.1.4) + activejob (= 7.1.4) + activemodel (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) bundler (>= 1.15.0) - railties (= 7.0.8.4) + railties (= 7.1.4) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -243,45 +253,52 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.0.8.4) - actionpack (= 7.0.8.4) - activesupport (= 7.0.8.4) - method_source + railties (7.1.4) + actionpack (= 7.1.4) + activesupport (= 7.1.4) + irb + rackup (>= 1.0.0) rake (>= 12.2) - thor (~> 1.0) - zeitwerk (~> 2.5) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.0.6) + rake (13.2.1) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) + rdoc (6.7.0) + psych (>= 4.0.0) redacted_struct (2.0.0) - redis (4.2.4) - regexp_parser (2.7.0) + redis (5.2.0) + redis-client (>= 0.22.0) + redis-client (0.22.1) + connection_pool + regexp_parser (2.9.2) + reline (0.5.10) + io-console (~> 0.5) request_store (1.5.1) rack (>= 1.4) - rexml (3.3.6) - strscan + rexml (3.3.7) rgl (0.5.6) lazy_priority_queue (~> 0.1.0) stream (~> 0.5.2) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rspec-core (3.13.1) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-mocks (3.12.6) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-rails (4.0.1) - actionpack (>= 4.2) - activesupport (>= 4.2) - railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) - rspec-support (3.12.1) + rspec-support (~> 3.13.0) + rspec-rails (6.1.5) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.13) + rspec-expectations (~> 3.13) + rspec-mocks (~> 3.13) + rspec-support (~> 3.13) + rspec-support (3.13.1) rspec_junit_formatter (0.6.0) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.50.1) @@ -313,29 +330,22 @@ GEM simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) stream (0.5.2) - strscan (3.1.0) - thor (1.2.2) - thread_safe (0.3.6) - timecop (0.9.2) + stringio (3.1.1) + thor (1.3.2) timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) uniform_notifier (1.16.0) - virtus (1.0.5) - axiom-types (~> 0.1) - coercible (~> 1.0) - descendants_tracker (~> 0.0, >= 0.0.3) - equalizer (~> 0.0, >= 0.0.9) webmock (3.14.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.8.2) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.6.11) - zonebie (0.6.1) + zeitwerk (2.6.18) PLATFORMS ruby @@ -344,16 +354,14 @@ DEPENDENCIES activerecord-import (>= 1.0.2) aws-sdk-core (>= 3.188.0) aws-sdk-s3 - axe-matchers (~> 1.3.4) better_errors (>= 2.5.1) bloomfilter-rb bootsnap (~> 1.0) brakeman - bullet (~> 7.0) + bullet (~> 7.1.2) bundler-audit - database_cleaner + csv factory_bot_rails (>= 5.2.0) - fakefs identity-hostdata! identity-logging! listen @@ -363,24 +371,22 @@ DEPENDENCIES pry-byebug pry-rails puma - rails (~> 7.0.8.3) + rails (~> 7.1.0) rails-controller-testing (>= 1.0.4) redacted_struct (~> 2.0) + redis rgl - rspec-rails (>= 3.8.3) + rspec-rails (~> 6.0) rspec_junit_formatter rubocop rubocop-performance (~> 1.17) rubocop-rails (>= 2.19.0) shoulda-matchers (~> 3.1, >= 3.1.3) simplecov (>= 0.13.0) - timecop - tzinfo-data webmock - zonebie RUBY VERSION - ruby 3.2.2p53 + ruby 3.3.4p94 BUNDLED WITH - 2.5.6 + 2.5.20 diff --git a/app/controllers/identify_controller.rb b/app/controllers/identify_controller.rb index a6c61f433..0885f0a52 100644 --- a/app/controllers/identify_controller.rb +++ b/app/controllers/identify_controller.rb @@ -18,7 +18,8 @@ def create referrer.query = "token=#{token_for_referrer}" # redirect to referer OR redirect to a preconfigured URL template - redirect_to referrer.to_s + # this is safe because we validate that it is an allowed referrer + redirect_to referrer.to_s, allow_other_host: true else render_bad_request('No referrer') end diff --git a/config/application.rb b/config/application.rb index e167df119..3711e1044 100644 --- a/config/application.rb +++ b/config/application.rb @@ -14,10 +14,7 @@ module IdentityPki class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 6.1 - config.autoloader = :zeitwerk - # Remove once 7.0 has been deployed - config.active_support.cache_format_version = 6.1 + config.load_defaults 7.0 Identity::Hostdata.load_config!( app_root: Rails.root, @@ -26,6 +23,9 @@ class Application < Rails::Application &IdentityConfig::CONFIG_BUILDER ) + # Don't generate system test files. + config.generators.system_tests = nil + # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. diff --git a/config/application.yml.default b/config/application.yml.default index 7fae4e04a..b47ce71ff 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -30,7 +30,6 @@ nonce_bloom_filter_server: 'redis://localhost/' nonce_bloom_filter_size: '100_000' nonce_bloom_filter_ttl: '300' piv_cac_verify_token_secret: '' -secret_key_base: '' token_encryption_key_pepper_old: '' token_encryption_key_salt_old: '' @@ -57,6 +56,7 @@ development: token_encryption_key_salt_old: de+hXqHqjAIIKq+mgdbUdTfvOZQP7ya1MPsUKgy1/ueEl+Yw1w7ZzaObENqDD4DhrWD3zXUgI3UQm9ZISzOwpEk8lq/azWg8Pw9lPL1yBUR2easxcgbAl6gjPB+8fAFD token_encryption_key_pepper_old: 1HkCB/IADCORWlBAUmeM9S+KBBv0eWzxJG8NM6+A1/f7K3KoVpa2HTED4pTNf8DGp834etYxOL+NdjvH88Lk1s5u401Hu3d3nPbnI11nWTfhaBCz6foOfS/3KGBd/8hz certificate_store_directory: 'config/certs' + secret_key_base: development_secret_key_base test: aws_region: 'us-east-1' @@ -70,6 +70,7 @@ test: token_encryption_key_pepper_old: 1HkCB/IADCORWlBAUmeM9S+KBBv0eWzxJG8NM6+A1/f7K3KoVpa2HTED4pTNf8DGp834etYxOL+NdjvH88Lk1s5u401Hu3d3nPbnI11nWTfhaBCz6foOfS/3KGBd/8hz certificate_store_directory: 'config/test-certs' ca_issuer_host_allow_list: 'uri1.example.com,uri2.example.com' + secret_key_base: test_secret_key_base production: @@ -83,3 +84,4 @@ production: nonce_bloom_filter_enabled: 'false' token_encryption_key_salt: '' token_encryption_key_pepper: '' + secret_key_base: diff --git a/config/environments/development.rb b/config/environments/development.rb index 827ef5f06..e642f8bea 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -7,6 +7,7 @@ # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false + config.enable_reloading = true # This allows nginx to make a request config.hosts << 'rails_upstream' @@ -26,7 +27,7 @@ config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}", + 'Cache-Control' => "public, max-age=#{2.days.to_i}", } else config.action_controller.perform_caching = false @@ -59,6 +60,6 @@ # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Uncomment if you wish to allow Action Cable access from any origin. - # config.action_cable.disable_request_forgery_protection = true + # Raise error when a before_action's only/except options reference missing action + config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/environments/production.rb b/config/environments/production.rb index 2d627c41d..c75ca5de7 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,8 +1,10 @@ +require 'active_support/core_ext/integer/time' Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. config.cache_classes = true + config.enable_reloading = false # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers @@ -24,21 +26,19 @@ config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' + # config.asset_host = 'http://assets.example.com' # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - # Mount Action Cable outside main process or domain - # config.action_cable.mount_path = nil - # config.action_cable.url = 'wss://example.com/cable' - # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true - config.log_level = :info # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -54,12 +54,25 @@ # require 'syslog/logger' # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + config.log_level = :info + if IdentityConfig.store.log_to_stdout logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end + # Prepend all log lines with the following tags. + # config.log_tags = [ :request_id ] + # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } end diff --git a/config/environments/test.rb b/config/environments/test.rb index 4819cd667..3927989f3 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -40,6 +40,15 @@ # Tell Active Support which deprecation messages to disallow. config.active_support.disallowed_deprecation_warnings = [] + config.time_zone = ActiveSupport::TimeZone::MAPPING.keys.sample + config.active_record.default_timezone = :local + # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # cconfig.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Raise error when a before_action's only/except options reference missing actions + # config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1e7..6a02e6264 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +1,8 @@ # Be sure to restart your server when you modify this file. -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw #, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb new file mode 100644 index 000000000..833a6b1df --- /dev/null +++ b/config/initializers/secret_token.rb @@ -0,0 +1 @@ +Rails.application.config.secret_key_base = IdentityConfig.store.secret_key_base diff --git a/config/secrets.yml b/config/secrets.yml deleted file mode 100644 index 718bc8dfe..000000000 --- a/config/secrets.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key is used for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! - -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -# You can use `rails secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -# Shared secrets are available across all environments. - -# shared: -# api_key: a1B2c3D4e5F6 - -# Environmental secrets are only available for that specific environment. - -development: - secret_key_base: 8f01a81e53ddaed01a4c7aa6b920078f9701a913f826c9fa43aaf8a3dff216c7e07713ba7be10d13c540608ca4a0b41d2cbfc338438bf670d02fb54ecdcb605b - -test: - secret_key_base: 1158a3d8bb5846ed70cc384de608d9e4759f501e391dac319b6ec5c246a34df709828dbdbfb6a3ffaa2b4de086460f31dd3d0e5639db7fc53f96690330c8cf19 - -# Do not keep production secrets in the unencrypted secrets file. -# Instead, either read values from the environment. -# Or, use `bin/rails secrets:setup` to configure encrypted secrets -# and move the `production:` environment over there. - -production: - secret_key_base: <%= IdentityConfig.store.secret_key_base %> diff --git a/db/schema.rb b/db/schema.rb index 94863af40..4581949d8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,16 +2,15 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[6.1].define(version: 2018_05_23_205303) do - +ActiveRecord::Schema[7.1].define(version: 2018_05_23_205303) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,10 +18,10 @@ t.string "key", null: false t.string "dn", null: false t.string "crl_http_url" - t.datetime "valid_not_before", null: false - t.datetime "valid_not_after", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "valid_not_before", precision: nil, null: false + t.datetime "valid_not_after", precision: nil, null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "ocsp_http_url" t.index ["key"], name: "index_certificate_authorities_on_key", unique: true end @@ -30,8 +29,8 @@ create_table "certificate_revocations", force: :cascade do |t| t.bigint "certificate_authority_id", null: false t.string "serial", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["certificate_authority_id", "serial"], name: "index_certificate_revocations_on_cert_auth_id_and_serial", unique: true end @@ -48,8 +47,8 @@ t.string "crl_http_url" t.string "ocsp_url" t.string "ca_issuer_url" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["key"], name: "index_unrecognized_certificate_authorities_on_key", unique: true end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 637b9c767..2166f39c9 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -17,7 +17,7 @@ Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } RSpec.configure do |config| - config.use_transactional_fixtures = false + config.use_transactional_fixtures = true config.infer_spec_type_from_file_location! config.before(:suite) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8612ff2fd..0b5cd29be 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -35,5 +35,3 @@ require 'webmock/rspec' WebMock.disable_net_connect!(allow: [/localhost/, /127\.0\.0\.1/]) - -require 'zonebie/rspec' diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb deleted file mode 100644 index 6ce44134a..000000000 --- a/spec/support/database_cleaner.rb +++ /dev/null @@ -1,26 +0,0 @@ -RSpec.configure do |config| - config.before(:suite) do - DatabaseCleaner.clean_with(:truncation) - end - - config.before(:each) do - # set the default - DatabaseCleaner.strategy = :transaction - end - - config.before(:each, js: true) do - DatabaseCleaner.strategy = :truncation, { except: %w[app_settings service_providers] } - end - - config.before(:each, truncate: true) do - DatabaseCleaner.strategy = :truncation, { except: %w[app_settings service_providers] } - end - - config.before(:each) do - DatabaseCleaner.start - end - - config.append_after(:each) do - DatabaseCleaner.clean - end -end