diff --git a/help/osx-ssl-certs.md b/help/osx-ssl-certs.md new file mode 100644 index 0000000000..32d21fc0c3 --- /dev/null +++ b/help/osx-ssl-certs.md @@ -0,0 +1,49 @@ +# OSX OpenSSL Certificates handling. + +## Synopsis + + rvm osx-ssl-certs status [|all] + rvm [--silent] osx-ssl-certs update [|all] + rvm osx-ssl-certs cron [status|install|uninstall] + +## Description + +Apple OS X comes with old version of OpenSSL, to keep you secure RVM installs newer version. +RVM also allows specifying custom version of OpenSSL and binary rubies linked to custom locations. +Taken this all into account most likely your Ruby is using outdated certificates. +To solve this problem `rvm osx-ssl-certs` will find all locations for certificates. +You can check status, update certificates manually or schedule an automated update. + +## Arguments +`rvm osx-ssl-certs`: + +* `status` => Show certificates status for current Ruby, + * `` => Status of a specific Ruby certificates, + * `all` => Status of all installed Rubies certificate paths. +* `update` => Update SSL certificates for current Ruby, + * `` => Update a specific Ruby certificates, + * `all` => Update all installed Rubies certificate paths. +* `cron` => Manage cron job for daily updates, + * `status` => Show if the cron job is installed, + * `install` => Install the cron job, + * `uninstall` => Uninstall the cron job. + +## Examples + +Show the status for all installed rubies + + rvm osx-ssl-certs status all + +Update certificates for current ruby OpenSSL + + rvm osx-ssl-certs status all + +Schedule daily update of certificates + + rvm osx-ssl-certs cron install + +## Reporting bugs + +Please report issues to https://github.com/wayneeseguin/rvm/issues + +In case of security issues use rvm-internal@googlegroups.com diff --git a/scripts/cli b/scripts/cli index 0a55daa27d..a8cb5b4b5a 100755 --- a/scripts/cli +++ b/scripts/cli @@ -248,7 +248,7 @@ __rvm_parse_args() rvm_remove_flag=1 ;; - rtfm|RTFM|rvmrc|usage|help|inspect|list|ls|info|strings|get|current|docs|alias|rubygems|cleanup|tools|disk-usage|snapshot|repair|migrate|downgrade|upgrade|cron|group|switch|which|config-get|requirements|autolibs) + rtfm|RTFM|rvmrc|usage|help|inspect|list|ls|info|strings|get|current|docs|alias|rubygems|cleanup|tools|disk-usage|snapshot|repair|migrate|downgrade|upgrade|cron|group|switch|which|config-get|requirements|autolibs|osx-ssl-certs) case "$rvm_token" in (downgrade) rvm_action="upgrade" ;; (ls) rvm_action="list" ;; @@ -983,7 +983,8 @@ Please do one of the following: __rvm_run_script "$rvm_action" "${rvm_ruby_args[@]}" ;; - autolibs|upgrade) # file action + autolibs|osx-ssl-certs|upgrade) + # file action params __rvm_run_wrapper "$rvm_action" "$rvm_action" "${rvm_ruby_args[@]}" ;; diff --git a/scripts/functions/build b/scripts/functions/build index eff62e31e9..0aefca3613 100644 --- a/scripts/functions/build +++ b/scripts/functions/build @@ -3,6 +3,7 @@ source "$rvm_scripts_path/functions/autolibs" source "$rvm_scripts_path/functions/build_config" source "$rvm_scripts_path/functions/build_requirements" +source "$rvm_scripts_path/functions/osx-ssl-certs" # show the user selected compiler or return 1 __rvm_selected_compiler() diff --git a/scripts/functions/build_requirements b/scripts/functions/build_requirements index 3b84b22de3..4a25993de8 100755 --- a/scripts/functions/build_requirements +++ b/scripts/functions/build_requirements @@ -31,47 +31,6 @@ rvm_requiremnts_fail_or_run_action() true # for osx } -requirements_osx_update_openssl_cert_old() [[ "$cert_file" -ot /Library/Keychains/System.keychain || - "$cert_file" -ot /System/Library/Keychains/SystemRootCertificates.keychain -]] - -requirements_osx_update_openssl_cert_run() -{ - rvm_log "Updating certificates in '$cert_file'." - mkdir -p "$ssl_dir" - security find-certificate -a -p /Library/Keychains/System.keychain > "$cert_file" - security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> "$cert_file" - "${ssl_binary%/openssl}/c_rehash" "$ssl_dir" -} - -requirements_osx_update_openssl_cert() -{ - [[ "Darwin" == "$(uname)" ]] || return 0 - - case "${rvm_autolibs_flag_number}" in - (0) - rvm_debug "Skipping update of certificates in '$cert_file'." - return 0 - ;; - esac - - typeset ssl_binary ssl_dir cert_file - ssl_binary="${1:-$(which openssl)}" - ssl_dir="$( "${ssl_binary}" version -d | awk -F'"' '{print $2}' )" #' fix formating - cert_file="${ssl_dir}/cert.pem" - - if - requirements_osx_update_openssl_cert_old - then - rvm_requiremnts_fail_or_run_action 2 \ - "Skipping update of certificates in '$cert_file'." \ - requirements_osx_update_openssl_cert_run || - return $? - else - rvm_log "Certificates in '$cert_file' already are up to date." - fi -} - __rvm_requirements_load() { if diff --git a/scripts/functions/osx-ssl-certs b/scripts/functions/osx-ssl-certs new file mode 100755 index 0000000000..5615c8ea0a --- /dev/null +++ b/scripts/functions/osx-ssl-certs @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +requirements_osx_update_openssl_cert_old() [[ "$cert_file" -ot /Library/Keychains/System.keychain || + "$cert_file" -ot /System/Library/Keychains/SystemRootCertificates.keychain +]] + +requirements_osx_update_openssl_cert_run() +{ + rvm_log "Updating certificates in '$cert_file'." + mkdir -p "$ssl_dir" + security find-certificate -a -p /Library/Keychains/System.keychain > "$cert_file" + security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> "$cert_file" +} + +requirements_osx_update_openssl_cert() +{ + [[ "Darwin" == "$(uname)" ]] || return 0 + + case "${rvm_autolibs_flag_number}" in + (0) + rvm_debug "Skipping update of certificates in '$cert_file'." + return 0 + ;; + esac + + typeset ssl_binary ssl_dir cert_file + ssl_binary="${1:-$(which openssl)}" + cert_file="$( __rvm_osx_ssl_certs_file_from_openssl "${ssl_binary}" )" + ssl_dir="${cert_file%/*}" + + if + requirements_osx_update_openssl_cert_old + then + rvm_requiremnts_fail_or_run_action 2 \ + "Skipping update of certificates in '$cert_file'." \ + requirements_osx_update_openssl_cert_run || + return $? + else + rvm_log "Certificates in '$cert_file' already are up to date." + fi +} + +__rvm_osx_ssl_certs_update_for_path() +{ + typeset ssl_dir cert_file + cert_file="$( __rvm_osx_ssl_certs_file_for_ruby )" + ssl_dir="${cert_file%/*}" + + if (( ${rvm_silent_flag:-0} == 0 )) + then printf "%b" "Updating certificates for ${cert_file}: " + fi + if + requirements_osx_update_openssl_cert_old + then + if + requirements_osx_update_openssl_cert_run + then + if (( ${rvm_silent_flag:-0} == 0 )) + then printf "%b" "Updated.\n" + fi + else + typeset result=$? + if (( ${rvm_silent_flag:-0} == 0 )) + then printf "%b" "Failed.\n" + else printf "%b" "Updating certificates for ${cert_file}: Failed.\n" + fi + return $result + fi + else + if (( ${rvm_silent_flag:-0} == 0 )) + then printf "%b" "Already are up to date.\n" + fi + fi +} + +__rvm_osx_ssl_certs_status_for_path() +{ + typeset ssl_dir cert_file + cert_file="$1" + ssl_dir="${cert_file%/*}" + + printf "%b" "Certificates for ${cert_file}: " + if requirements_osx_update_openssl_cert_old + then printf "%b" "Old.\n" + else printf "%b" "Up to date.\n" + fi +} + +__rvm_osx_ssl_certs_file_for_ruby() +{ + "${1:-ruby}" -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE' +} + +__rvm_osx_ssl_certs_file_from_openssl() +{ + "${1:-openssl}" version -d | awk -F'"' '{print $2"/cert.pem"}' +} + +__rvm_cron_find() +{ + EDITOR=\cat crontab -e 2>/dev/null | GREP_OPTIONS="" \grep "$1" >/dev/null || return $? +} + +__rvm_cron_uninstall() +{ + EDITOR=\cat crontab -e 2>/dev/null | GREP_OPTIONS="" \grep -v "$1" | crontab - +} + +__rvm_cron_install() +{ + { + EDITOR=\cat crontab -e 2>/dev/null + echo "@daily $1" + } | crontab - +} + +export RVM_OSX_SSL_UPDATER="$rvm_path/bin/rvm --silent osx-ssl-certs update all" diff --git a/scripts/osx-ssl-certs b/scripts/osx-ssl-certs new file mode 100755 index 0000000000..231699d7e5 --- /dev/null +++ b/scripts/osx-ssl-certs @@ -0,0 +1,149 @@ +#!/usr/bin/env bash + +source "$rvm_scripts_path/functions/osx-ssl-certs" + +__rvm_osx_ssl_certs_run_select_rubies() +{ + case "$2" in + (all) + __rvm_read_lines __rubies < <( + __rvm_cd "$rvm_rubies_path" + find . -maxdepth 1 -mindepth 1 -type d 2>/dev/null | cut -c 3- + ) + ;; + (*,*) + __rvm_custom_separated_array __rubies , "$2" + ;; + ("") + __rubies=( "${GEM_HOME##*/}" ) + ;; + (*) + __rubies=( "$2" ) + ;; + esac +} + +__rvm_osx_ssl_certs_run_filter_and_run() +{ + for __ruby in "${__rubies[@]}" + do + rvm_debug "${__ruby} # getting cert file" + __path="$( __rvm_with "${__ruby}" "__rvm_osx_ssl_certs_file_for_ruby" )" + [[ " ${__paths[*]} " =~ " ${__path} " ]] || __paths+=( "${__path}" ) + done + + for __path in "${__paths[@]}" + do + rvm_debug "${__path} # updating certs" + "$1" "${__path}" + done +} + +__rvm_osx_ssl_certs_run() +{ + typeset __ruby __path + typeset -a __rubies __paths + __rubies=() + __paths=() + + __rvm_osx_ssl_certs_run_select_rubies "$@" + __rvm_osx_ssl_certs_run_filter_and_run "$@" +} + +__rvm_osx_ssl_certs_status() +{ + __rvm_osx_ssl_certs_run __rvm_osx_ssl_certs_status_for_path "$1" +} + +__rvm_osx_ssl_certs_update() +{ + __rvm_osx_ssl_certs_run __rvm_osx_ssl_certs_update_for_path "$1" +} + +__rvm_osx_ssl_certs_cron_status() +{ + if __rvm_cron_find "$RVM_OSX_SSL_UPDATER" + then rvm_log "Automatic certs updating installed." + else rvm_warn "Automatic certs updating not installed." + fi +} + +__rvm_osx_ssl_certs_cron_install() +{ + if + __rvm_cron_find "$RVM_OSX_SSL_UPDATER" + then + __rvm_cron_uninstall "$RVM_OSX_SSL_UPDATER" || + { + typeset result=$? + rvm_error "Automatic certs updating failed uninstalling." + return $result + } + fi + if + __rvm_cron_install "$RVM_OSX_SSL_UPDATER" + then + rvm_log "Automatic certs updating installed." + else + typeset result=$? + rvm_error "Automatic certs updating failed installing." + return $result + fi +} + +__rvm_osx_ssl_certs_cron_uninstall() +{ + if + __rvm_cron_find "$RVM_OSX_SSL_UPDATER" + then + if + __rvm_cron_uninstall "$RVM_OSX_SSL_UPDATER" + then + rvm_log "Automatic certs updating uninstalled." + else + typeset result=$? + rvm_error "Automatic certs updating failed uninstalling." + return $result + fi + else + rvm_log "Automatic certs updating already uninstalled." + fi +} + +__rvm_osx_ssl_certs_cron() +{ + typeset cron_action="${1:-status}" + shift 1 + case "${cron_action}" in + (status|install|uninstall) + __rvm_osx_ssl_certs_cron_${cron_action} + ;; + (help) + rvm_help osx-ssl-certs cron "$@" + ;; + (*) + rvm_error_help "Unknown subcommand '$*' for osx-ssl-certs cron" osx-ssl-certs cron "$@" + return 1 + ;; + esac +} + +__rvm_osx_ssl_certs() +{ + typeset action="${1:-status}" + shift 1 + case "${action}" in + (status|update|cron) + __rvm_osx_ssl_certs_${action} "$@" + ;; + (help) + rvm_help osx-ssl-certs "$@" + ;; + (*) + rvm_error_help "Unknown subcommand '$*' for osx-ssl-certs" osx-ssl-certs "$@" + return 1 + ;; + esac +} + +__rvm_osx_ssl_certs "${args[@]}"