From ac809d28e39a4df84fb73edac3765f3edf26c324 Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Wed, 5 Feb 2025 16:37:04 -0800 Subject: [PATCH 1/6] replace CSP with new default, with start/end markers for auto replacement --- server/configs/application.properties | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/server/configs/application.properties b/server/configs/application.properties index 6d2dc1e758..9eac5e13a7 100644 --- a/server/configs/application.properties +++ b/server/configs/application.properties @@ -125,26 +125,15 @@ management.server.port=@@shutdownPort@@ #jsonaccesslog.condition-if=attributeName #jsonaccesslog.condition-unless=attributeName +## START OF CSP COPY BLOCK (DO NOT CHANGE THIS TEXT) + ## Define one or both of 'csp.report' and 'csp.enforce' to enable Content Security Policy (CSP) headers ## Do not use these examples for any production environment without understanding the meaning of each directive! -## Default enforce CSP for dev deployments -#useLocalBuild#csp.enforce=\ -#useLocalBuild# default-src 'self' https: http: ;\ -#useLocalBuild# connect-src 'self' localhost:* ws: ${LABKEY.ALLOWED.CONNECTIONS} ;\ -#useLocalBuild# object-src 'none' ;\ -#useLocalBuild# style-src 'self' https: 'unsafe-inline' ;\ -#useLocalBuild# img-src 'self' https: data: ;\ -#useLocalBuild# font-src 'self' http: https: data: ;\ -#useLocalBuild# script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ -#useLocalBuild# base-uri 'self' ;\ -#useLocalBuild# frame-ancestors 'self' ;\ -#useLocalBuild# report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; - -## Default report CSP for TeamCity and dev deployments +## Default CSP for LabKey Cloud deployments csp.report=\ default-src 'self' https: http: ;\ - connect-src 'self' localhost:* ws: ${LABKEY.ALLOWED.CONNECTIONS} ;\ + connect-src 'self' localhost:* ${LABKEY.ALLOWED.CONNECTIONS} ;\ object-src 'none' ;\ style-src 'self' https: 'unsafe-inline' ;\ img-src 'self' https: data: ;\ @@ -152,7 +141,23 @@ csp.report=\ script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ base-uri 'self' ;\ frame-ancestors 'self' ;\ - report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; + report-uri https://www.labkey.org/admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; + +## START OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) +# csp.enforce=\ +# default-src 'self';\ +# connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ +# object-src 'none' ;\ +# style-src 'self' 'unsafe-inline' ;\ +# img-src 'self' data: ;\ +# font-src 'self' data: ;\ +# script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}';\ +# base-uri 'self' ;\ +# upgrade-insecure-requests ;\ +# frame-ancestors 'self' ;\ +# report-uri https://www.labkey.org/admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; + +## END OF CSP COPY BLOCK (DO NOT CHANGE THIS TEXT) ## Use a custom logging configuration #logging.config=path/to/alternative/log4j2.xml From 8130f47806d0ff75255b470f44e543f2a3bb555d Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Fri, 7 Feb 2025 15:36:36 -0800 Subject: [PATCH 2/6] update w/ tc-enabled enforce block and latest changes from chef repo --- server/configs/application.properties | 47 ++++++++++++--------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/server/configs/application.properties b/server/configs/application.properties index 9eac5e13a7..1bb79f454b 100644 --- a/server/configs/application.properties +++ b/server/configs/application.properties @@ -125,39 +125,34 @@ management.server.port=@@shutdownPort@@ #jsonaccesslog.condition-if=attributeName #jsonaccesslog.condition-unless=attributeName -## START OF CSP COPY BLOCK (DO NOT CHANGE THIS TEXT) - -## Define one or both of 'csp.report' and 'csp.enforce' to enable Content Security Policy (CSP) headers -## Do not use these examples for any production environment without understanding the meaning of each directive! - -## Default CSP for LabKey Cloud deployments +## START OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) csp.report=\ - default-src 'self' https: http: ;\ - connect-src 'self' localhost:* ${LABKEY.ALLOWED.CONNECTIONS} ;\ + default-src 'self' ;\ + connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ object-src 'none' ;\ - style-src 'self' https: 'unsafe-inline' ;\ - img-src 'self' https: data: ;\ - font-src 'self' http: https: data: ;\ + style-src 'self' 'unsafe-inline' ;\ + img-src 'self' data: ;\ + font-src 'self' data: ;\ script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ base-uri 'self' ;\ frame-ancestors 'self' ;\ - report-uri https://www.labkey.org/admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; + report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; +## END OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) ## START OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) -# csp.enforce=\ -# default-src 'self';\ -# connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ -# object-src 'none' ;\ -# style-src 'self' 'unsafe-inline' ;\ -# img-src 'self' data: ;\ -# font-src 'self' data: ;\ -# script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}';\ -# base-uri 'self' ;\ -# upgrade-insecure-requests ;\ -# frame-ancestors 'self' ;\ -# report-uri https://www.labkey.org/admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; - -## END OF CSP COPY BLOCK (DO NOT CHANGE THIS TEXT) +#useLocalBuild#csp.enforce=\ +#useLocalBuild# default-src 'self' https: ;\ +#useLocalBuild# connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ +#useLocalBuild# object-src 'none' ;\ +#useLocalBuild# style-src 'self' https: 'unsafe-inline' ;\ +#useLocalBuild# img-src 'self' https: data: ;\ +#useLocalBuild# font-src 'self' data: ;\ +#useLocalBuild# script-src 'self' 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ +#useLocalBuild# base-uri 'self' ;\ +#useLocalBuild# upgrade-insecure-requests ;\ +#useLocalBuild# frame-ancestors 'self' ;\ +#useLocalBuild# report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; +## END OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) ## Use a custom logging configuration #logging.config=path/to/alternative/log4j2.xml From 01aad69c74b6d09c456b88d0f2fbf417f57fca60 Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Tue, 11 Feb 2025 06:31:10 -0800 Subject: [PATCH 3/6] remove upgrade-insecure-requests from enforce block --- server/configs/application.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/server/configs/application.properties b/server/configs/application.properties index 1bb79f454b..2a31019569 100644 --- a/server/configs/application.properties +++ b/server/configs/application.properties @@ -149,7 +149,6 @@ csp.report=\ #useLocalBuild# font-src 'self' data: ;\ #useLocalBuild# script-src 'self' 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ #useLocalBuild# base-uri 'self' ;\ -#useLocalBuild# upgrade-insecure-requests ;\ #useLocalBuild# frame-ancestors 'self' ;\ #useLocalBuild# report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; ## END OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) From 38d60252a5edffbcc90990d72f7cac2d35d73ae9 Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Fri, 14 Feb 2025 06:10:00 -0800 Subject: [PATCH 4/6] add copy_csp_blocks action --- .github/workflows/copy_csp_blocks.yml | 190 ++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 .github/workflows/copy_csp_blocks.yml diff --git a/.github/workflows/copy_csp_blocks.yml b/.github/workflows/copy_csp_blocks.yml new file mode 100644 index 0000000000..6184c9559a --- /dev/null +++ b/.github/workflows/copy_csp_blocks.yml @@ -0,0 +1,190 @@ +name: Copy CSP Blocks +# Upon merge of a PR in which 'server/configs/application.properties' was updated... +# this workflow copies the Content Security Policy blocks to other repos, as marked by: +# start: "## START OF CSP COPY BLOCK" or "## START OF CSP ENFORCE BLOCK" (to only copy and uncomment the csp.enforce section) +# end: "## END OF CSP COPY BLOCK" or "## END OF CSP ENFORCE BLOCK" +# note: if the contents between the start/end have not changed, it's a no-op, and no PRs are pushed to the target repos + +on: + pull_request: + types: + - closed + branches: + - fb_* + paths: + - server/configs/application.properties + # TODO remove 'push' later, obviously: + push: + branches: + - fb_* + paths: + - server/configs/application.properties + +jobs: + copy_csp: + # TODO: restore this: if: github.event.pull_request.merged + runs-on: ubuntu-latest + outputs: + csp_report_on: ${{ steps.cspvars.outputs.csp_report_on }} + csp_enforce_off: ${{ steps.cspvars.outputs.csp_enforce_off }} + csp_enforce_on: ${{ steps.cspvars.outputs.csp_enforce_on }} + steps: + - name: Check Out Code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Copy CSP blocks into vars + id: cspvars + run: | + # report block, fixing report-uri for non-teamcity usage: + CSP_REPORT_ON=$( awk '/## END OF CSP REPORT BLOCK/{p=0};p;/## START OF CSP REPORT BLOCK/{p=1}' server/configs/application.properties |\ + sed 's/report-uri /report-uri https:\/\/www.labkey.org/' ) + + # enforce block, fixing report-uri for non-teamcity usage, removing useLocalBuild comment, adding upgrade-insecure-requests: + CSP_ENFORCE_OFF=$( awk '/## END OF CSP ENFORCE BLOCK/{p=0};p;/## START OF CSP ENFORCE BLOCK/{p=1}' server/configs/application.properties |\ + sed 's/^#useLocalBuild#/# /' |\ + sed '/base-uri/a# upgrade-insecure-requests ;\\' |\ + sed 's/report-uri /report-uri https:\/\/www.labkey.org/' ) + + # enforce block, uncommented: + CSP_ENFORCE_ON=$( awk '/## END OF CSP ENFORCE BLOCK/{p=0};p;/## START OF CSP ENFORCE BLOCK/{p=1}' server/configs/application.properties |\ + sed 's/^#useLocalBuild#//' |\ + sed '/base-uri/a\ upgrade-insecure-requests ;\\' |\ + sed 's/report-uri /report-uri https:\/\/www.labkey.org/' ) + + # use unique delimiter for multiline outputs: https://stackoverflow.com/a/74256214 + delimiter="$(openssl rand -hex 8)" + + echo "csp_report_on<<${delimiter}" >> "${GITHUB_OUTPUT}" + echo "$CSP_REPORT_ON" >> "${GITHUB_OUTPUT}" + echo "${delimiter}" >> "${GITHUB_OUTPUT}" + + echo "csp_enforce_off<<${delimiter}" >> "${GITHUB_OUTPUT}" + echo "$CSP_ENFORCE_OFF" >> "${GITHUB_OUTPUT}" + echo "${delimiter}" >> "${GITHUB_OUTPUT}" + + echo "csp_enforce_on<<${delimiter}" >> "${GITHUB_OUTPUT}" + echo "$CSP_ENFORCE_ON" >> "${GITHUB_OUTPUT}" + echo "${delimiter}" >> "${GITHUB_OUTPUT}" + + paste_csp_into_chef_repo: + needs: copy_csp + runs-on: ubuntu-latest + env: + csp_report_on: ${{ needs.copy_csp.outputs.csp_report_on }} + csp_enforce_off: ${{ needs.copy_csp.outputs.csp_enforce_off }} + ap_file: "cookbooks/lk_appserver/templates/default/application.properties.erb" + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + repository: labkey-willm/syseng-chef-server # TODO: LabKey/syseng-chef-server + token: ${{ secrets.TERRAFORM_TOKEN }} + - name: Paste Into Chef Repo + run: | + printf "\n\n>>>> $ap_file before I change it: <<<<\n\n" + cat $ap_file + + printf "\n\n>>>> caught csp_report_on env var: <<<<\n$csp_report_on n\n" + printf "\n\n>>>> caught csp_enforce_off env var: <<<<\n$csp_enforce_off n\n" + + printf "\n\n>>>> replacing csp blocks in $ap_file <<<<\n\n" + + python <>>> updated $ap_file: <<<<\n\n" + cat $ap_file + + printf "\n\n>>>> updating chef recipe version <<<<\n\n" + NEW_VER=$(grep version cookbooks/lk_appserver/metadata.rb |cut -d '"' -f 2 |awk -F. -v OFS=. '{$NF += 1 ; print}') + sed -i 's/\(version.*\)".*"/\1"'$NEW_VER'"/' cookbooks/lk_appserver/metadata.rb + sed -i 's/\(lk_appserver .*\)([0-9]*.[0-9]*.[0-9]*)/\1('$NEW_VER')/' Berksfile.lock + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.TERRAFORM_TOKEN }} + branch: fb_update_csp_per_${{ github.sha }} + title: "update CSP to match commit ${{ github.sha }}" + body: "update CSP to match commit ${{ github.sha }}" + commit-message: "update CSP to match commit ${{ github.sha }}" + add-paths: | + ${{ env.ap_file }} + cookbooks/lk_appserver/metadata.rb + Berksfile.lock + + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "Server Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY + + paste_enforce_csp_into_dockerfile_repo: + needs: copy_csp + runs-on: ubuntu-latest + env: + csp_enforce_on: ${{ needs.copy_csp.outputs.csp_enforce_on }} + ap_file: "application.properties" + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + repository: labkey-willm/Dockerfile # TODO: Labkey/Dockerfile + token: ${{ secrets.TERRAFORM_TOKEN }} + - name: Paste Into Dockerfile Repo + run: | + printf "\n\n>>>> $ap_file before I change it: <<<<\n\n" + cat $ap_file + + printf "\n\n>>>> caught csp_enforce_on env var:<<<<\n$csp_enforce_on\n\n" + + printf "\n\n>>>> replacing csp block in $ap_file <<<<\n\n" + + python <>>> updated $ap_file: <<<<\n\n" + cat $ap_file + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.TERRAFORM_TOKEN }} + branch: fb_update_csp_per_${{ github.sha }} + title: "update CSP to match commit ${{ github.sha }}" + body: "update CSP to match commit ${{ github.sha }}" + commit-message: "update CSP to match commit ${{ github.sha }}" + add-paths: ${{ env.ap_file }} + + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "Dockerfile Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY From 9303e164338652c5fd29b12f9ab272ecbf51664f Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Fri, 14 Feb 2025 06:17:04 -0800 Subject: [PATCH 5/6] fixup todo reminders --- .github/workflows/copy_csp_blocks.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/copy_csp_blocks.yml b/.github/workflows/copy_csp_blocks.yml index 6184c9559a..e2feb23a81 100644 --- a/.github/workflows/copy_csp_blocks.yml +++ b/.github/workflows/copy_csp_blocks.yml @@ -13,16 +13,10 @@ on: - fb_* paths: - server/configs/application.properties - # TODO remove 'push' later, obviously: - push: - branches: - - fb_* - paths: - - server/configs/application.properties jobs: copy_csp: - # TODO: restore this: if: github.event.pull_request.merged + if: github.event.pull_request.merged runs-on: ubuntu-latest outputs: csp_report_on: ${{ steps.cspvars.outputs.csp_report_on }} @@ -79,7 +73,7 @@ jobs: - name: Check out repo uses: actions/checkout@v4 with: - repository: labkey-willm/syseng-chef-server # TODO: LabKey/syseng-chef-server + repository: LabKey/syseng-chef-server token: ${{ secrets.TERRAFORM_TOKEN }} - name: Paste Into Chef Repo run: | @@ -146,7 +140,7 @@ jobs: - name: Check out repo uses: actions/checkout@v4 with: - repository: labkey-willm/Dockerfile # TODO: Labkey/Dockerfile + repository: Labkey/Dockerfile token: ${{ secrets.TERRAFORM_TOKEN }} - name: Paste Into Dockerfile Repo run: | From 030773cc4eb3500ec25942b05d273e64fbc3f55a Mon Sep 17 00:00:00 2001 From: Will Mooreston Date: Fri, 14 Feb 2025 11:20:55 -0800 Subject: [PATCH 6/6] add guard against updating chef when ap file didn't change; swap back enforce/report order --- .github/workflows/copy_csp_blocks.yml | 13 ++++++++----- server/configs/application.properties | 28 +++++++++++++-------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/.github/workflows/copy_csp_blocks.yml b/.github/workflows/copy_csp_blocks.yml index e2feb23a81..3730705b03 100644 --- a/.github/workflows/copy_csp_blocks.yml +++ b/.github/workflows/copy_csp_blocks.yml @@ -106,10 +106,13 @@ jobs: printf "\n\n>>>> updated $ap_file: <<<<\n\n" cat $ap_file - printf "\n\n>>>> updating chef recipe version <<<<\n\n" - NEW_VER=$(grep version cookbooks/lk_appserver/metadata.rb |cut -d '"' -f 2 |awk -F. -v OFS=. '{$NF += 1 ; print}') - sed -i 's/\(version.*\)".*"/\1"'$NEW_VER'"/' cookbooks/lk_appserver/metadata.rb - sed -i 's/\(lk_appserver .*\)([0-9]*.[0-9]*.[0-9]*)/\1('$NEW_VER')/' Berksfile.lock + git status + if [[ $(git diff-index --name-only HEAD |grep application.properties) ]]; then + printf "\n\n>>>> changes detected, so updating chef recipe version <<<<\n\n" + NEW_VER=$(grep version cookbooks/lk_appserver/metadata.rb |cut -d '"' -f 2 |awk -F. -v OFS=. '{$NF += 1 ; print}') + sed -i 's/\(version.*\)".*"/\1"'$NEW_VER'"/' cookbooks/lk_appserver/metadata.rb + sed -i 's/\(lk_appserver .*\)([0-9]*.[0-9]*.[0-9]*)/\1('$NEW_VER')/' Berksfile.lock + fi - name: Create Pull Request id: cpr @@ -128,7 +131,7 @@ jobs: - name: Check outputs if: ${{ steps.cpr.outputs.pull-request-number }} run: | - echo "Server Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY + echo "Chef Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY paste_enforce_csp_into_dockerfile_repo: needs: copy_csp diff --git a/server/configs/application.properties b/server/configs/application.properties index 2a31019569..440252a61e 100644 --- a/server/configs/application.properties +++ b/server/configs/application.properties @@ -125,20 +125,6 @@ management.server.port=@@shutdownPort@@ #jsonaccesslog.condition-if=attributeName #jsonaccesslog.condition-unless=attributeName -## START OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) -csp.report=\ - default-src 'self' ;\ - connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ - object-src 'none' ;\ - style-src 'self' 'unsafe-inline' ;\ - img-src 'self' data: ;\ - font-src 'self' data: ;\ - script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ - base-uri 'self' ;\ - frame-ancestors 'self' ;\ - report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; -## END OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) - ## START OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) #useLocalBuild#csp.enforce=\ #useLocalBuild# default-src 'self' https: ;\ @@ -153,6 +139,20 @@ csp.report=\ #useLocalBuild# report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; ## END OF CSP ENFORCE BLOCK (DO NOT CHANGE THIS TEXT) +## START OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) +csp.report=\ + default-src 'self' ;\ + connect-src 'self' ${LABKEY.ALLOWED.CONNECTIONS} ;\ + object-src 'none' ;\ + style-src 'self' 'unsafe-inline' ;\ + img-src 'self' data: ;\ + font-src 'self' data: ;\ + script-src 'unsafe-eval' 'strict-dynamic' 'nonce-${REQUEST.SCRIPT.NONCE}' ;\ + base-uri 'self' ;\ + frame-ancestors 'self' ;\ + report-uri /admin-contentsecuritypolicyreport.api?${CSP.REPORT.PARAMS} ; +## END OF CSP REPORT BLOCK (DO NOT CHANGE THIS TEXT) + ## Use a custom logging configuration #logging.config=path/to/alternative/log4j2.xml