Skip to content

Commit

Permalink
workflows get rid of mysql_ssl_rsa_setup
Browse files Browse the repository at this point in the history
Generate certificates manually using openssl as the mysql_ssl_rsa_setup
is deprecated.
  • Loading branch information
silverqx committed Jun 9, 2024
1 parent 32c1e93 commit cd006e6
Show file tree
Hide file tree
Showing 3 changed files with 387 additions and 25 deletions.
127 changes: 119 additions & 8 deletions .github/workflows/clang-cl-qt6.yml
Original file line number Diff line number Diff line change
Expand Up @@ -270,28 +270,137 @@ jobs:
run: |
mysqld.exe --initialize-insecure --console
- name: MySQL generate SSL certificates
# We can't generate certificates first and then initialize MySQL data folder, MySQL throws
# error, it also generates all keys and certificates so we have remove them to generate are own
- name: MySQL SSL certificates remove
working-directory: ${{ env.TinyMySQLDataPath }}
run: >-
Remove-Item ./ca.pem, ./ca-key.pem, ./server-cert.pem, ./server-key.pem,
./client-cert.pem, ./client-key.pem
- name: MySQL SSL certificates initialize
id: openssl-initialize-mysql-certificates
run: |
$folderPath = Join-Path -Path '${{ env.TinyRunnerWorkPath }}' `
-ChildPath 'tiny-mysql-certificates'
# Create an empty folder for generating certificates
New-Item -Type Directory $folderPath
"FolderPath=$folderPath" >> $env:GITHUB_OUTPUT
# This hash invalidates the MySQL certificates cache every month
$hash = Get-Date -Format 'yyyyMM'
"Hash=$hash" >> $env:GITHUB_OUTPUT
- name: MySQL SSL certificates restore cache
uses: actions/cache/restore@v3
id: openssl-cache-mysql-certificates
with:
path: |
${{ env.folder_path }}/*.pem
key: ${{ runner.os }}-openssl-${{ env.cache_name }}-${{ env.cache_hash }}
env:
# This hash invalidates this certificates cache every month
cache_hash: ${{ steps.openssl-initialize-mysql-certificates.outputs.Hash }}
cache_name: mysql-certificates
folder_path: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}

- name: MySQL SSL certificates generate
if: steps.openssl-cache-mysql-certificates.outputs.cache-hit != 'true'
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
Write-Output '::group::Print openssl version'
openssl.exe version -a
Write-Output '::endgroup::'
Write-Output '::group::Create .rnd file'
openssl.exe rand -out ./.rnd -writerand ./.rnd
Write-Output '::endgroup::'
Write-Output '::group::CA certificate'
# -days 32 is important, -days 30 is not enough
openssl.exe req -new -x509 -nodes -subj $env:DB_MYSQL_SSL_SUBJECT_CA -days 32 `
-keyout ./ca-key.pem -out ./ca.pem
Write-Output '::endgroup::'
Write-Output '::group::Server certificate'
openssl.exe req -new -nodes -subj $env:DB_MYSQL_SSL_SUBJECT_SERVER -keyout ./server-key.pem `
-out ./server-req.pem
$env:OPENSSL_SAN = "DNS:${env:DB_MYSQL_HOST}"
openssl.exe x509 -req -CA ./ca.pem -CAkey ./ca-key.pem -days 32 -set_serial 01 `
-extfile $env:extfile -in ./server-req.pem -out ./server-cert.pem
Write-Output '::endgroup::'
Write-Output '::group::Client certificate'
openssl.exe req -new -nodes -subj $env:DB_MYSQL_SSL_SUBJECT_CLIENT `
-keyout ./client-key.pem -out client-req.pem
$env:OPENSSL_SAN = "DNS:${env:DB_MYSQL_HOST_CLIENT}"
openssl.exe x509 -req -CA ./ca.pem -CAkey ./ca-key.pem -days 32 -set_serial 02 `
-extfile $env:extfile -in ./client-req.pem -out ./client-cert.pem
Write-Output '::endgroup::'
env:
extfile: ${{ github.workspace }}/.github/resources/openssl/usr_cert.cnf
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SSL }}
DB_MYSQL_HOST_CLIENT: ${{ secrets.DB_MYSQL_HOST_CLIENT_SSL }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}
DB_MYSQL_SSL_SUBJECT_SERVER: ${{ secrets.DB_MYSQL_SSL_SUBJECT_SERVER }}

# Always verify, regardless if certificates were newly generated or restored from the cache
- name: MySQL SSL certificates verify
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
openssl.exe verify -CAfile ./ca.pem ./server-cert.pem ./client-cert.pem
# Save the cache only if certificates were newly generated
# The actions/cache/save allows to use the Move-Item during the install step
- name: MySQL SSL certificates save cache
if: steps.openssl-cache-mysql-certificates.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: |
${{ env.folder_path }}/*.pem
key: ${{ steps.openssl-cache-mysql-certificates.outputs.cache-primary-key }}
env:
folder_path: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}

- name: MySQL SSL certificates install
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
# It's enough to remove only these three certificate-related files
Remove-Item ./ca.pem, ./server-cert.pem, ./server-key.pem
mysql_ssl_rsa_setup.exe --suffix=TinyORM
Write-Output '::group::Install CA certificate'
Move-Item -Path ./ca.pem -Destination '${{ env.TinyMySQLDataPath }}'
Write-Output '::endgroup::'
Write-Output '::group::Install server certificates'
Move-Item -Path ./server-cert.pem, ./server-key.pem `
-Destination '${{ env.TinyMySQLDataPath }}'
Write-Output '::endgroup::'
Write-Output '::group::Install client certificates'
Move-Item -Path ./client-cert.pem, ./client-key.pem `
-Destination '${{ env.TinyMySQLDataPath }}'
Write-Output '::endgroup::'
- name: MySQL service install/start
run: |
mysqld.exe --install MySQL
Start-Service MySQL
# Securing the root account even on localhost is for testing to make sure that everything
# works as expected
- name: MySQL change ${{ secrets.DB_MYSQL_ROOT_USERNAME }} password
run: >-
"alter user '$env:DB_MYSQL_ROOT_USERNAME'@'localhost'
identified with caching_sha2_password by '$env:DB_MYSQL_ROOT_PASSWORD'
require issuer '/CN=MySQL_Server_TinyORM_Auto_Generated_CA_Certificate' and
subject '/CN=MySQL_Server_TinyORM_Auto_Generated_Client_Certificate';" |
require issuer '${{ env.DB_MYSQL_SSL_SUBJECT_CA }}' and
subject '${{ env.DB_MYSQL_SSL_SUBJECT_CLIENT }}';" |
mysql.exe --user=$env:DB_MYSQL_ROOT_USERNAME --skip-password
env:
DB_MYSQL_ROOT_PASSWORD: ${{ secrets.DB_MYSQL_ROOT_PASSWORD }}
DB_MYSQL_ROOT_USERNAME: ${{ secrets.DB_MYSQL_ROOT_USERNAME }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}

- name: MySQL time zone POSIX tables initialize download
id: downloads-initialize-mysql-timezone-tables
Expand Down Expand Up @@ -389,8 +498,8 @@ jobs:
run: >-
"create user '$env:DB_MYSQL_USERNAME'@'%'
identified with caching_sha2_password by '$env:DB_MYSQL_PASSWORD'
require issuer '/CN=MySQL_Server_TinyORM_Auto_Generated_CA_Certificate' and
subject '/CN=MySQL_Server_TinyORM_Auto_Generated_Client_Certificate';
require issuer '${{ env.DB_MYSQL_SSL_SUBJECT_CA }}' and
subject '${{ env.DB_MYSQL_SSL_SUBJECT_CLIENT }}';
grant all privileges on ``tinyorm\_%``.* to '$env:DB_MYSQL_USERNAME'@'%';
grant select on ``mysql``.``time_zone_name`` to '$env:DB_MYSQL_USERNAME'@'%';
flush privileges;" |
Expand All @@ -399,6 +508,8 @@ jobs:
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD }}
DB_MYSQL_ROOT_PASSWORD: ${{ secrets.DB_MYSQL_ROOT_PASSWORD }}
DB_MYSQL_ROOT_USERNAME: ${{ secrets.DB_MYSQL_ROOT_USERNAME }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME }}

- name: MySQL add libmysql.dll on the $env:Path, INCLUDE, and LIB
Expand Down
158 changes: 149 additions & 9 deletions .github/workflows/linux-qt6.yml
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,13 @@ jobs:
pg_isready
echo '::endgroup::'
# Adding the DB_MYSQL_HOST_CLIENT isn't strictly needed (works without it too)
- name: Hosts add MySQL server hostname
run: >-
sudo -- sh -c "echo '127.0.0.1\t$DB_MYSQL_HOST' >> /etc/hosts"
sudo -- sh -c "echo '127.0.0.1\t$DB_MYSQL_HOST $DB_MYSQL_HOST_CLIENT' >> /etc/hosts"
env:
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SSL }}
DB_MYSQL_HOST_CLIENT: ${{ secrets.DB_MYSQL_HOST_CLIENT_SSL }}

- name: MySQL initialize crystal_mysqld.cnf configuration
working-directory: .github/resources/linux
Expand All @@ -300,11 +302,136 @@ jobs:
env:
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SSL }}

- name: MySQL generate SSL certificates
# Remove certificates to generate are own
- name: MySQL SSL certificates remove
run: >-
sudo --user=mysql --
rm /var/lib/mysql/{ca,ca-key,server-cert,server-key,client-cert,client-key}.pem
- name: MySQL SSL certificates initialize
id: openssl-initialize-mysql-certificates
run: |
folderPath='${{ env.TinyRunnerWorkPath }}/tiny-mysql-certificates'
# Create an empty folder for generating certificates
sudo mkdir "$folderPath"
sudo chown runner:docker "$folderPath"
echo "FolderPath=$folderPath" >> $GITHUB_OUTPUT
# This hash invalidates the MySQL certificates cache every month
hash=$(date +%4Y%2m)
echo "Hash=$hash" >> $GITHUB_OUTPUT
- name: MySQL SSL certificates restore cache
uses: actions/cache/restore@v3
id: openssl-cache-mysql-certificates
with:
path: |
${{ env.folder_path }}/*.pem
key: ${{ runner.os }}-openssl-${{ env.cache_name }}-${{ env.cache_hash }}
env:
# This hash invalidates this certificates cache every month
cache_hash: ${{ steps.openssl-initialize-mysql-certificates.outputs.Hash }}
cache_name: mysql-certificates
folder_path: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}

- name: MySQL SSL certificates generate
if: steps.openssl-cache-mysql-certificates.outputs.cache-hit != 'true'
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
echo '::group::Print openssl version'
openssl version -a
echo '::endgroup::'
echo '::group::CA certificate'
# -days 32 is important, -days 30 is not enough
openssl req -new -x509 -nodes -subj "$DB_MYSQL_SSL_SUBJECT_CA" -days 32 \
-keyout ./ca-key.pem -out ./ca.pem
echo '::endgroup::'
echo '::group::Server certificate'
openssl req -new -nodes -subj "$DB_MYSQL_SSL_SUBJECT_SERVER" -keyout ./server-key.pem -out \
./server-req.pem
OPENSSL_SAN="DNS:${DB_MYSQL_HOST}" \
openssl x509 -req -CA ./ca.pem -CAkey ./ca-key.pem -days 32 -set_serial 01 \
-extfile "$extfile" -in ./server-req.pem -out ./server-cert.pem
echo '::endgroup::'
echo '::group::Client certificate'
openssl req -new -nodes -subj "$DB_MYSQL_SSL_SUBJECT_CLIENT" -keyout ./client-key.pem \
-out ./client-req.pem
OPENSSL_SAN="DNS:${DB_MYSQL_HOST_CLIENT}" \
openssl x509 -req -CA ./ca.pem -CAkey ./ca-key.pem -days 32 -set_serial 02 \
-extfile "$extfile" -in ./client-req.pem -out ./client-cert.pem
echo '::endgroup::'
env:
extfile: ${{ github.workspace }}/.github/resources/openssl/usr_cert.cnf
DB_MYSQL_HOST: ${{ secrets.DB_MYSQL_HOST_SSL }}
DB_MYSQL_HOST_CLIENT: ${{ secrets.DB_MYSQL_HOST_CLIENT_SSL }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_SERVER: ${{ secrets.DB_MYSQL_SSL_SUBJECT_SERVER }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}

- name: MySQL SSL certificates print
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
echo '::group::CA certificate'
openssl x509 -noout -text -in ./ca.pem
echo '::endgroup::'
echo '::group::Server certificate'
openssl x509 -noout -text -in ./server-cert.pem
echo '::endgroup::'
echo '::group::Client certificate'
openssl x509 -noout -text -in ./client-cert.pem
echo '::endgroup::'
# Always verify, regardless if certificates were newly generated or restored from the cache
- name: MySQL SSL certificates verify
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
openssl verify -CAfile ./ca.pem ./server-cert.pem ./client-cert.pem
# Save the cache only if certificates were newly generated
# The actions/cache/save allows to use the Move-Item during the install step
- name: MySQL SSL certificates save cache
if: steps.openssl-cache-mysql-certificates.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: |
${{ env.folder_path }}/*.pem
key: ${{ steps.openssl-cache-mysql-certificates.outputs.cache-primary-key }}
env:
folder_path: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}

- name: MySQL SSL certificates install
working-directory: ${{ steps.openssl-initialize-mysql-certificates.outputs.FolderPath }}
run: |
# It's enough to remove only these three certificate-related files
sudo --user=mysql -- rm /var/lib/mysql/{ca,server-cert,server-key}.pem
sudo mysql_ssl_rsa_setup --suffix=TinyORM --uid=mysql
mysqlDataPath=/var/lib/mysql
echo '::group::Install CA certificate'
sudo mv --target-directory="$mysqlDataPath" ./ca.pem
sudo chmod 644 "$mysqlDataPath/ca.pem"
sudo chown mysql:mysql "$mysqlDataPath/ca.pem"
echo '::endgroup::'
echo '::group::Install server certificates'
sudo mv --target-directory="$mysqlDataPath" ./server-{cert,key}.pem
sudo chmod 640 "$mysqlDataPath/server-cert.pem"
sudo chmod 600 "$mysqlDataPath/server-key.pem"
sudo chown mysql:mysql "$mysqlDataPath"/server-{cert,key}.pem
echo '::endgroup::'
echo '::group::Install client certificates'
sudo mv --target-directory="$mysqlDataPath" ./client-{cert,key}.pem
sudo chmod 640 "$mysqlDataPath/client-cert.pem"
sudo chmod 600 "$mysqlDataPath/client-key.pem"
sudo chown mysql:mysql "$mysqlDataPath"/client-{cert,key}.pem
echo '::endgroup::'
env:
pg_data_path: ${{ steps.databases-initialize-mysql.outputs.PgDataPath }}

- name: MySQL copy SSL certificates for runner user
run: |
Expand All @@ -323,18 +450,22 @@ jobs:
run: |
sudo systemctl start mysql.service
# Securing the root account even on localhost is for testing to make sure that everything
# works as expected
- name: MySQL change ${{ secrets.DB_MYSQL_ROOT_USERNAME }} password
run: >-
echo "
alter user '$DB_MYSQL_ROOT_USERNAME'@'localhost'
identified with caching_sha2_password by '$DB_MYSQL_ROOT_PASSWORD'
require issuer '/CN=MySQL_Server_TinyORM_Auto_Generated_CA_Certificate' and
subject '/CN=MySQL_Server_TinyORM_Auto_Generated_Client_Certificate';" |
require issuer '$DB_MYSQL_SSL_SUBJECT_CA' and
subject '$DB_MYSQL_SSL_SUBJECT_CLIENT';" |
mysql --user="$DB_MYSQL_ROOT_USERNAME" --password="$DB_MYSQL_ROOT_PASSWORD_DEFAULT"
env:
DB_MYSQL_ROOT_PASSWORD: ${{ secrets.DB_MYSQL_ROOT_PASSWORD }}
DB_MYSQL_ROOT_PASSWORD_DEFAULT: ${{ secrets.DB_MYSQL_ROOT_PASSWORD_DEFAULT }}
DB_MYSQL_ROOT_USERNAME: ${{ secrets.DB_MYSQL_ROOT_USERNAME }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}

- name: MySQL populate time zone tables 👌
run: >-
Expand Down Expand Up @@ -382,8 +513,8 @@ jobs:
echo "
create user '$DB_MYSQL_USERNAME'@'%'
identified with caching_sha2_password by '$DB_MYSQL_PASSWORD'
require issuer '/CN=MySQL_Server_TinyORM_Auto_Generated_CA_Certificate' and
subject '/CN=MySQL_Server_TinyORM_Auto_Generated_Client_Certificate';
require issuer '$DB_MYSQL_SSL_SUBJECT_CA' and
subject '$DB_MYSQL_SSL_SUBJECT_CLIENT';
grant all privileges on \`tinyorm\\_%\`.* to '$DB_MYSQL_USERNAME'@'%';
grant select on \`mysql\`.\`time_zone_name\` to '$DB_MYSQL_USERNAME'@'%';
flush privileges;" |
Expand All @@ -393,6 +524,15 @@ jobs:
DB_MYSQL_ROOT_PASSWORD: ${{ secrets.DB_MYSQL_ROOT_PASSWORD }}
DB_MYSQL_ROOT_USERNAME: ${{ secrets.DB_MYSQL_ROOT_USERNAME }}
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME }}
DB_MYSQL_SSL_SUBJECT_CA: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CA }}
DB_MYSQL_SSL_SUBJECT_CLIENT: ${{ secrets.DB_MYSQL_SSL_SUBJECT_CLIENT }}

- name: MySQL test TinyORM user
run: |
mysql --user="$DB_MYSQL_USERNAME" --password="$DB_MYSQL_PASSWORD"
env:
DB_MYSQL_PASSWORD: ${{ secrets.DB_MYSQL_PASSWORD }}
DB_MYSQL_USERNAME: ${{ secrets.DB_MYSQL_USERNAME }}

- name: SQLite create TinyORM database
run: |
Expand Down
Loading

0 comments on commit cd006e6

Please sign in to comment.