#!/bin/bash # Simple integration test. Make sure to activate virtualenv beforehand # (source venv/bin/activate) and that you are running Boulder test # instance (see ./boulder-fetch.sh). # # Environment variables: # SERVER: Passed as "certbot --server" argument. # # Note: this script is called by Boulder integration test suite! set -eux . ./tests/integration/_common.sh export PATH="$PATH:/usr/sbin" # /usr/sbin/nginx cleanup_and_exit() { EXIT_STATUS=$? if SERVER_STILL_RUNNING=`ps -p $python_server_pid -o pid=` then echo Kill server subprocess, left running by abnormal exit kill $SERVER_STILL_RUNNING fi # Dump boulder logs in case they contain useful debugging information. : "------------------ ------------------ ------------------" : "------------------ begin boulder logs ------------------" : "------------------ ------------------ ------------------" docker logs boulder_boulder_1 : "------------------ ------------------ ------------------" : "------------------ end boulder logs ------------------" : "------------------ ------------------ ------------------" exit $EXIT_STATUS } trap cleanup_and_exit EXIT common_no_force_renew() { certbot_test_no_force_renew \ --authenticator standalone \ --installer null \ "$@" } common() { common_no_force_renew \ --renew-by-default \ "$@" } export HOOK_TEST="/tmp/hook$$" CheckHooks() { EXPECTED="/tmp/expected$$" if [ $(head -n1 $HOOK_TEST) = "wtf.pre" ]; then echo "wtf.pre" > "$EXPECTED" echo "wtf2.pre" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "wtf.post" >> "$EXPECTED" echo "wtf2.post" >> "$EXPECTED" else echo "wtf2.pre" > "$EXPECTED" echo "wtf.pre" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "deploy" >> "$EXPECTED" echo "wtf2.post" >> "$EXPECTED" echo "wtf.post" >> "$EXPECTED" fi if ! cmp --quiet "$EXPECTED" "$HOOK_TEST" ; then echo Hooks did not run as expected\; got cat "$HOOK_TEST" echo Expected cat "$EXPECTED" fi rm "$HOOK_TEST" } # Checks if deploy is in the hook output and deletes the file DeployInHookOutput() { CONTENTS=$(cat "$HOOK_TEST") rm "$HOOK_TEST" grep deploy <(echo "$CONTENTS") } # Asserts that there is a saved renew_hook for a lineage. # # Arguments: # Name of lineage to check CheckSavedRenewHook() { if ! grep renew_hook "$config_dir/renewal/$1.conf"; then echo "Hook wasn't saved as renew_hook" >&2 exit 1 fi } # Asserts the deploy hook was properly run and saved and deletes the hook file # # Arguments: # Lineage name of the issued cert CheckDeployHook() { if ! DeployInHookOutput; then echo "The deploy hook wasn't run" >&2 exit 1 fi CheckSavedRenewHook $1 } # Asserts the renew hook wasn't run but was saved and deletes the hook file # # Arguments: # Lineage name of the issued cert # Asserts the deploy hook wasn't run and deletes the hook file CheckRenewHook() { if DeployInHookOutput; then echo "The renew hook was incorrectly run" >&2 exit 1 fi CheckSavedRenewHook $1 } # Cleanup coverage data coverage erase # test for regressions of #4719 get_num_tmp_files() { ls -1 /tmp | wc -l } num_tmp_files=$(get_num_tmp_files) common --csr / && echo expected error && exit 1 || true common --help common --help all common --version if [ $(get_num_tmp_files) -ne $num_tmp_files ]; then echo "New files or directories created in /tmp!" exit 1 fi common register common register --update-registration --email example@example.org common plugins --init --prepare | grep webroot # We start a server listening on the port for the # unrequested challenge to prevent regressions in #3601. python ./tests/run_http_server.py $http_01_port & python_server_pid=$! certname="le1.wtf" common --domains le1.wtf --preferred-challenges tls-sni-01 auth \ --cert-name $certname \ --pre-hook 'echo wtf.pre >> "$HOOK_TEST"' \ --post-hook 'echo wtf.post >> "$HOOK_TEST"'\ --deploy-hook 'echo deploy >> "$HOOK_TEST"' kill $python_server_pid CheckDeployHook $certname python ./tests/run_http_server.py $tls_sni_01_port & python_server_pid=$! certname="le2.wtf" common --domains le2.wtf --preferred-challenges http-01 run \ --cert-name $certname \ --pre-hook 'echo wtf.pre >> "$HOOK_TEST"' \ --post-hook 'echo wtf.post >> "$HOOK_TEST"'\ --deploy-hook 'echo deploy >> "$HOOK_TEST"' kill $python_server_pid CheckDeployHook $certname certname="le.wtf" common certonly -a manual -d le.wtf --rsa-key-size 4096 --cert-name $certname \ --manual-auth-hook ./tests/manual-http-auth.sh \ --manual-cleanup-hook ./tests/manual-http-cleanup.sh \ --pre-hook 'echo wtf2.pre >> "$HOOK_TEST"' \ --post-hook 'echo wtf2.post >> "$HOOK_TEST"' \ --renew-hook 'echo deploy >> "$HOOK_TEST"' CheckRenewHook $certname certname="dns.le.wtf" common -a manual -d dns.le.wtf --preferred-challenges dns,tls-sni run \ --cert-name $certname \ --manual-auth-hook ./tests/manual-dns-auth.sh \ --pre-hook 'echo wtf2.pre >> "$HOOK_TEST"' \ --post-hook 'echo wtf2.post >> "$HOOK_TEST"' \ --renew-hook 'echo deploy >> "$HOOK_TEST"' CheckRenewHook $certname common certonly --cert-name newname -d newname.le.wtf export CSR_PATH="${root}/csr.der" KEY_PATH="${root}/key.pem" \ OPENSSL_CNF=examples/openssl.cnf ./examples/generate-csr.sh le3.wtf common auth --csr "$CSR_PATH" \ --cert-path "${root}/csr/cert.pem" \ --chain-path "${root}/csr/chain.pem" openssl x509 -in "${root}/csr/cert.pem" -text openssl x509 -in "${root}/csr/chain.pem" -text common --domains le3.wtf install \ --cert-path "${root}/csr/cert.pem" \ --key-path "${root}/csr/key.pem" CheckCertCount() { CERTCOUNT=`ls "${root}/conf/archive/$1/cert"* | wc -l` if [ "$CERTCOUNT" -ne "$2" ] ; then echo Wrong cert count, not "$2" `ls "${root}/conf/archive/$1/"*` exit 1 fi } CheckCertCount "le.wtf" 1 # This won't renew (because it's not time yet) common_no_force_renew renew CheckCertCount "le.wtf" 1 # renew using HTTP manual auth hooks common renew --cert-name le.wtf --authenticator manual CheckCertCount "le.wtf" 2 # renew using DNS manual auth hooks common renew --cert-name dns.le.wtf --authenticator manual CheckCertCount "dns.le.wtf" 2 # This will renew because the expiry is less than 10 years from now sed -i "4arenew_before_expiry = 4 years" "$root/conf/renewal/le.wtf.conf" common_no_force_renew renew --rsa-key-size 2048 CheckCertCount "le.wtf" 3 # The 4096 bit setting should persist to the first renewal, but be overridden in the second size1=`wc -c ${root}/conf/archive/le.wtf/privkey1.pem | cut -d" " -f1` size2=`wc -c ${root}/conf/archive/le.wtf/privkey2.pem | cut -d" " -f1` size3=`wc -c ${root}/conf/archive/le.wtf/privkey3.pem | cut -d" " -f1` # 4096 bit PEM keys are about ~3270 bytes, 2048 ones are about 1700 bytes if [ "$size1" -lt 3000 ] || [ "$size2" -lt 3000 ] || [ "$size3" -gt 1800 ] ; then echo key sizes violate assumptions: ls -l "${root}/conf/archive/le.wtf/privkey"* exit 1 fi # --renew-by-default is used, so renewal should occur [ -f "$HOOK_TEST" ] && rm -f "$HOOK_TEST" common renew CheckCertCount "le.wtf" 4 CheckHooks # ECDSA openssl ecparam -genkey -name secp384r1 -out "${root}/privkey-p384.pem" SAN="DNS:ecdsa.le.wtf" openssl req -new -sha256 \ -config "${OPENSSL_CNF:-openssl.cnf}" \ -key "${root}/privkey-p384.pem" \ -subj "/" \ -reqexts san \ -outform der \ -out "${root}/csr-p384.der" common auth --csr "${root}/csr-p384.der" \ --cert-path "${root}/csr/cert-p384.pem" \ --chain-path "${root}/csr/chain-p384.pem" openssl x509 -in "${root}/csr/cert-p384.pem" -text | grep 'ASN1 OID: secp384r1' # OCSP Must Staple common auth --must-staple --domains "must-staple.le.wtf" openssl x509 -in "${root}/conf/live/must-staple.le.wtf/cert.pem" -text | grep '1.3.6.1.5.5.7.1.24' # revoke by account key common revoke --cert-path "$root/conf/live/le.wtf/cert.pem" # revoke renewed common revoke --cert-path "$root/conf/live/le1.wtf/cert.pem" # revoke by cert key common revoke --cert-path "$root/conf/live/le2.wtf/cert.pem" \ --key-path "$root/conf/live/le2.wtf/privkey.pem" # Get new certs to test revoke with a reason, by account and by cert key common --domains le1.wtf common revoke --cert-path "$root/conf/live/le1.wtf/cert.pem" \ --reason cessationOfOperation common --domains le2.wtf common revoke --cert-path "$root/conf/live/le2.wtf/cert.pem" \ --key-path "$root/conf/live/le2.wtf/privkey.pem" \ --reason keyCompromise common unregister out=$(common certificates) subdomains="le le2 dns.le newname.le must-staple.le" for subdomain in $subdomains; do domain="$subdomain.wtf" if ! echo $out | grep "$domain"; then echo "$domain not in certificates output!" exit 1; fi done cert_name="must-staple.le.wtf" common delete --cert-name $cert_name archive="$root/conf/archive/$cert_name" conf="$root/conf/renewal/$cert_name.conf" live="$root/conf/live/$cert_name" for path in $archive $conf $live; do if [ -e $path ]; then echo "Lineage not properly deleted!" exit 1 fi done # Most CI systems set this variable to true. # If the tests are running as part of CI, Nginx should be available. if ${CI:-false} || type nginx; then . ./certbot-nginx/tests/boulder-integration.sh fi coverage report --fail-under 64 -m