cfssl-helper 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #!/bin/bash
  2. log-helper level eq trace && set -x
  3. # This tool helps to generate tls certificates with cfssl
  4. # It takes cfssl configuration from environment variable.
  5. # See cfssl-default-env file
  6. PREFIX=$1
  7. CERT_FILE=$2
  8. KEY_FILE=$3
  9. CA_FILE=$4
  10. log-helper debug "cfssl-helper is launched, everybody on the floor!"
  11. # before 0.2.5 retro compatibility, will be removed.
  12. mkdir -p "${CONTAINER_SERVICE_DIR}/:cfssl/assets/default-ca"
  13. ln -sf "${CONTAINER_SERVICE_DIR}/:ssl-tools/assets/default-ca/default-ca.pem" "${CONTAINER_SERVICE_DIR}/:cfssl/assets/default-ca/default-ca.pem"
  14. if [ -z "${PREFIX}" ] || [ -z "${CERT_FILE}" ] || [ -z "${KEY_FILE}" ] || [ -z "${CA_FILE}" ]; then
  15. log-helper error "Usage: cfssl-helper prefix cert_file key_file ca_file"
  16. exit 1
  17. fi
  18. if [ ! -e "${CERT_FILE}" ] && [ ! -e "${KEY_FILE}" ]; then
  19. log-helper info "No certificate file and certificate key provided, generate:"
  20. log-helper info "${CERT_FILE} and ${KEY_FILE}"
  21. LOG_LEVEL_PARAM=""
  22. case ${CONTAINER_LOG_LEVEL} in
  23. 0 )
  24. LOG_LEVEL_PARAM="-loglevel 4";;
  25. 1 )
  26. LOG_LEVEL_PARAM="-loglevel 3";;
  27. 2 )
  28. LOG_LEVEL_PARAM="-loglevel 2";;
  29. 3 )
  30. LOG_LEVEL_PARAM="-loglevel 1";;
  31. 4 )
  32. LOG_LEVEL_PARAM="-loglevel 0";;
  33. 5 )
  34. LOG_LEVEL_PARAM="-loglevel 0";;
  35. esac
  36. # set env vars
  37. PREFIX=${PREFIX^^} # uppercase
  38. # search for prefixed env var first
  39. # set prefix variable name
  40. # example : PREFIX_CFSSL_REMOTE='MARIADB_CFSSL_REMOTE'
  41. PREFIX_CFSSL_REMOTE=${PREFIX}_CFSSL_REMOTE
  42. PREFIX_CFSSL_REMOTE_HTTPS_CA_CERT=${PREFIX}_CFSSL_REMOTE_HTTPS_CA_CERT
  43. PREFIX_CFSSL_CA_CERT=${PREFIX}_CFSSL_CA_CERT
  44. PREFIX_CFSSL_CA_KEY=${PREFIX}_CFSSL_CA_KEY
  45. PREFIX_CFSSL_CSR=${PREFIX}_CFSSL_CSR
  46. PREFIX_CFSSL_CSR_JSON=${PREFIX}_CFSSL_CSR_JSON
  47. PREFIX_CFSSL_CONFIG=${PREFIX}_CFSSL_CONFIG
  48. PREFIX_CFSSL_CONFIG_JSON=${PREFIX}_CFSSL_CONFIG_JSON
  49. PREFIX_CFSSL_HOSTNAME=${PREFIX}_CFSSL_HOSTNAME
  50. PREFIX_CFSSL_PROFILE=${PREFIX}_CFSSL_PROFILE
  51. PREFIX_CFSSL_LABEL=${PREFIX}_CFSSL_LABEL
  52. PREFIX_CFSSL_RETRY=${PREFIX}_CFSSL_RETRY
  53. PREFIX_CFSSL_RETRY_DELAY=${PREFIX}_CFSSL_RETRY_DELAY
  54. # assign CFSSL_REMOTE=${!PREFIX_CFSSL_REMOTE} if value is not empty otherwise CFSSL_REMOTE=CFSSL_REMOTE
  55. CFSSL_REMOTE=${!PREFIX_CFSSL_REMOTE:-$CFSSL_REMOTE}
  56. CFSSL_REMOTE_HTTPS_CA_CERT=${!PREFIX_CFSSL_REMOTE_HTTPS_CA_CERT:-$CFSSL_REMOTE_HTTPS_CA_CERT}
  57. CFSSL_CA_CERT=${!PREFIX_CFSSL_CA_CERT:-$CFSSL_CA_CERT}
  58. CFSSL_CA_KEY=${!PREFIX_CFSSL_CA_KEY:-$CFSSL_CA_KEY}
  59. CFSSL_CSR=${!PREFIX_CFSSL_CSR:-$CFSSL_CSR}
  60. CFSSL_CSR_JSON=${!PREFIX_CFSSL_CSR_JSON:-$CFSSL_CSR_JSON}
  61. CFSSL_CONFIG=${!PREFIX_CFSSL_CONFIG:-$CFSSL_CONFIG}
  62. CFSSL_CONFIG_JSON=${!PREFIX_CFSSL_CONFIG_JSON:-$CFSSL_CONFIG_JSON}
  63. CFSSL_HOSTNAME=${!PREFIX_CFSSL_HOSTNAME:-$CFSSL_HOSTNAME}
  64. CFSSL_PROFILE=${!PREFIX_CFSSL_PROFILE:-$CFSSL_PROFILE}
  65. CFSSL_LABEL=${!PREFIX_CFSSL_LABEL:-$CFSSL_LABEL}
  66. CFSSL_RETRY=${!PREFIX_CFSSL_RETRY:-$CFSSL_RETRY}
  67. CFSSL_RETRY_DELAY=${!PREFIX_CFSSL_RETRY_DELAY:-$CFSSL_RETRY_DELAY}
  68. source "${CONTAINER_SERVICE_DIR}/:ssl-tools/assets/cfssl-default-env"
  69. # set csr file
  70. CSR_FILE="/tmp/csr-file"
  71. if [ -n "${CFSSL_CSR_JSON}" ]; then
  72. log-helper debug "use CFSSL_CSR_JSON value as csr file"
  73. echo "${CFSSL_CSR_JSON}" > "${CSR_FILE}"
  74. elif [ -n "${CFSSL_CSR}" ]; then
  75. log-helper debug "use ${CFSSL_CSR} as csr file"
  76. cp -f "${CFSSL_CSR}" "${CSR_FILE}"
  77. # it's the default csr
  78. if [ "${CFSSL_CSR}" = "${CFSSL_DEFAULT_CSR}" ]; then
  79. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_CN }}|${CFSSL_DEFAULT_CA_CSR_CN}|g" "${CSR_FILE}"
  80. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_KEY_ALGO }}|${CFSSL_DEFAULT_CA_CSR_KEY_ALGO}|g" "${CSR_FILE}"
  81. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_KEY_SIZE }}|${CFSSL_DEFAULT_CA_CSR_KEY_SIZE}|g" "${CSR_FILE}"
  82. sed -i "s|{{ CFSSL_CERT_ORGANIZATION_UNIT }}|${CFSSL_CERT_ORGANIZATION_UNIT}|g" "${CSR_FILE}"
  83. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_ORGANIZATION }}|${CFSSL_DEFAULT_CA_CSR_ORGANIZATION}|g" "${CSR_FILE}"
  84. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_ORGANIZATION_UNIT }}|${CFSSL_DEFAULT_CA_CSR_ORGANIZATION_UNIT}|g" "${CSR_FILE}"
  85. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_LOCATION }}|${CFSSL_DEFAULT_CA_CSR_LOCATION}|g" "${CSR_FILE}"
  86. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_STATE }}|${CFSSL_DEFAULT_CA_CSR_STATE}|g" "${CSR_FILE}"
  87. sed -i "s|{{ CFSSL_DEFAULT_CA_CSR_COUNTRY }}|${CFSSL_DEFAULT_CA_CSR_COUNTRY}|g" "${CSR_FILE}"
  88. fi
  89. else
  90. log-helper error "error: no csr file provided"
  91. log-helper error "CFSSL_CSR_JSON and CFSSL_CSR are empty"
  92. exit 1
  93. fi
  94. # generate cert
  95. CONFIG_FILE="/tmp/config-file"
  96. CERT_NAME="cert"
  97. REMOTE_PARAM=""
  98. CA_CERT_PARAM=""
  99. CA_KEY_PARAM=""
  100. CONFIG_PARAM=""
  101. HOSTNAME_PARAM=""
  102. PROFILE_PARAM=""
  103. LABEL_PARAM=""
  104. if [ -n "${CFSSL_REMOTE}" ]; then
  105. REMOTE_PARAM="-remote=${CFSSL_REMOTE}"
  106. # add remote https ca cert to known certificates if not empty
  107. if [ -n "${CFSSL_REMOTE_HTTPS_CA_CERT}" ]; then
  108. if [ -e "${CFSSL_REMOTE_HTTPS_CA_CERT}" ]; then
  109. [[ ! -d "/etc/ssl/certs/" ]] && mkdir -p /etc/ssl/certs/
  110. cat "${CFSSL_REMOTE_HTTPS_CA_CERT}" >> /etc/ssl/certs/ca-certificates.crt
  111. else
  112. log-helper error "error: remote https ca cert file ${CFSSL_REMOTE_HTTPS_CA_CERT} not found"
  113. fi
  114. fi
  115. else
  116. # files path with : may cause issue with cfssl tools due to :
  117. # ReadBytes - https://github.com/cloudflare/cfssl/blob/master/helpers/helpers.go#L573
  118. # : is used to split env from file path
  119. # so we copy ca cert and key to tmp
  120. if [ -n "${CFSSL_CA_CERT}" ]; then
  121. CFSSL_CA_CERT_FILE="/tmp/ca-cert-file"
  122. cp -f "${CFSSL_CA_CERT}" "${CFSSL_CA_CERT_FILE}"
  123. chmod 644 "${CFSSL_CA_CERT_FILE}"
  124. CA_CERT_PARAM="-ca ${CFSSL_CA_CERT_FILE}"
  125. fi
  126. if [ -n "${CFSSL_CA_KEY}" ]; then
  127. CFSSL_CA_KEY_FILE="/tmp/ca-key-file"
  128. cp -f "${CFSSL_CA_KEY}" "${CFSSL_CA_KEY_FILE}"
  129. chmod 600 "${CFSSL_CA_CERT_FILE}"
  130. CA_KEY_PARAM="-ca-key ${CFSSL_CA_KEY_FILE}"
  131. fi
  132. fi
  133. if [ -n "${CFSSL_CONFIG_JSON}" ]; then
  134. log-helper debug "use CFSSL_CONFIG_JSON value as config file"
  135. echo "${CFSSL_CONFIG_JSON}" > "${CONFIG_FILE}"
  136. CONFIG_PARAM="-config ${CONFIG_FILE}"
  137. elif [ -n "${CFSSL_CONFIG}" ]; then
  138. log-helper debug "use ${CFSSL_CONFIG} as config file"
  139. cp -f "${CFSSL_CONFIG}" "${CONFIG_FILE}"
  140. CONFIG_PARAM="-config ${CONFIG_FILE}"
  141. fi
  142. if [ -n "$ADDITIONAL_HOSTNAMES" ]; then
  143. log-helper debug "additional hostnames found"
  144. CFSSL_HOSTNAME="${CFSSL_HOSTNAME},${ADDITIONAL_HOSTNAMES}"
  145. fi
  146. [[ -n "${CFSSL_HOSTNAME}" ]] && HOSTNAME_PARAM="-hostname ${CFSSL_HOSTNAME}"
  147. [[ -n "${CFSSL_PROFILE}" ]] && PROFILE_PARAM="-profile ${CFSSL_PROFILE}"
  148. [[ -n "${CFSSL_LABEL}" ]] && LABEL_PARAM="-label ${CFSSL_LABEL}"
  149. retry=0
  150. while [ $retry -lt "${CFSSL_RETRY}" ]; do
  151. log-helper debug "cfssl gencert ${LOG_LEVEL_PARAM} ${REMOTE_PARAM} ${CA_CERT_PARAM} ${CA_KEY_PARAM} ${CONFIG_PARAM} ${HOSTNAME_PARAM} ${PROFILE_PARAM} ${LABEL_PARAM} ${CSR_FILE} | cfssljson -bare /tmp/${CERT_NAME}"
  152. eval cfssl gencert "${LOG_LEVEL_PARAM}" "${REMOTE_PARAM}" "${CA_CERT_PARAM}" "${CA_KEY_PARAM}" "${CONFIG_PARAM}" "${HOSTNAME_PARAM}" "${PROFILE_PARAM}" "${LABEL_PARAM}" "${CSR_FILE}" | cfssljson -bare "/tmp/${CERT_NAME}" && break
  153. sleep "${CFSSL_RETRY_DELAY}"
  154. ((retry++))
  155. done
  156. # move generated files
  157. [[ ! -e "/tmp/${CERT_NAME}.pem" ]] && exit 1
  158. log-helper debug "move /tmp/${CERT_NAME}.pem to ${CERT_FILE}"
  159. mv "/tmp/${CERT_NAME}.pem" "${CERT_FILE}"
  160. log-helper debug "move /tmp/${CERT_NAME}-key.pem to ${KEY_FILE}"
  161. mv "/tmp/${CERT_NAME}-key.pem" "${KEY_FILE}"
  162. # if ca file don't exists
  163. if [ ! -e "${CA_FILE}" ]; then
  164. if [ -n "${CFSSL_REMOTE}" ]; then
  165. log-helper debug "Get CA certificate from ${CFSSL_REMOTE}"
  166. retry=0
  167. while [ $retry -lt "${CFSSL_RETRY}" ]; do
  168. log-helper debug "cfssl info ${LOG_LEVEL_PARAM} ${REMOTE_PARAM} ${CONFIG_PARAM} ${PROFILE_PARAM} ${LABEL_PARAM}"
  169. eval cfssl info "${LOG_LEVEL_PARAM}" "${REMOTE_PARAM}" "${CONFIG_PARAM}" "${PROFILE_PARAM}" "${LABEL_PARAM}" | sed -e "s/.*certificate\":\"\(.*-----\)\".*/\1/g" | sed 's/\\n/\n/g' > "${CA_FILE}" && log-helper debug "CA certificate returned save as ${CA_FILE}" && break
  170. sleep "${CFSSL_RETRY_DELAY}"
  171. ((retry++))
  172. done
  173. [[ ! -e "${CA_FILE}" ]] && exit 1
  174. elif [ -n "${CFSSL_CA_CERT}" ]; then
  175. log-helper info "Link ${CFSSL_CA_CERT} to ${CA_FILE}"
  176. ln -sf "${CFSSL_CA_CERT}" "${CA_FILE}"
  177. fi
  178. fi
  179. # delete tmp files
  180. rm -f /tmp/${CERT_NAME}.csr ${CONFIG_FILE} "${CSR_FILE}"
  181. [[ -e "${CFSSL_CA_CERT_FILE}" ]] && rm "${CFSSL_CA_CERT_FILE}"
  182. [[ -e "${CFSSL_CA_KEY_FILE}" ]] && rm "${CFSSL_CA_KEY_FILE}"
  183. log-helper debug "done :)"
  184. elif [ ! -e "${KEY_FILE}" ]; then
  185. log-helper error "Certificate file ${CERT_FILE} exists but not key file ${KEY_FILE}"
  186. exit 1
  187. elif [ ! -e "${CERT_FILE}" ]; then
  188. log-helper error "Key file ${KEY_FILE} exists but not certificate file ${CERT_FILE}"
  189. exit 1
  190. else
  191. log-helper debug "Files ${CERT_FILE} and ${KEY_FILE} exists, fix files permissions"
  192. chmod 644 "${CERT_FILE}"
  193. chmod 600 "${KEY_FILE}"
  194. fi