diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 0000000..d977d21 --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,30 @@ +--- + +### +### Lints all generic and json files in the whole git repository +### + +name: linting +on: + pull_request: + push: + branches: + - master + tags: + +jobs: + lint: + runs-on: ubuntu-latest + strategy: + fail-fast: False + matrix: + target: + - Linting + name: "[ ${{ matrix.target }} ]" + steps: + - name: Checkout repository + uses: actions/checkout@master + + - name: Lint files + run: | + make lint diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml new file mode 100644 index 0000000..4e2e5d2 --- /dev/null +++ b/.github/workflows/test-linux.yml @@ -0,0 +1,30 @@ +--- +name: test-linux +on: + pull_request: + push: + branches: + - master + tags: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: False + + name: "[test] [linux]" + steps: + # ------------------------------------------------------------ + # Setup + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + + # ------------------------------------------------------------ + # Tests: Behaviour + # ------------------------------------------------------------ + - name: test + shell: bash + run: | + make test diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml new file mode 100644 index 0000000..df5493e --- /dev/null +++ b/.github/workflows/test-macos.yml @@ -0,0 +1,30 @@ +--- +name: test-macos +on: + pull_request: + push: + branches: + - master + tags: + +jobs: + test: + runs-on: macos-latest + strategy: + fail-fast: False + + name: "[test] [macos]" + steps: + # ------------------------------------------------------------ + # Setup + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + + # ------------------------------------------------------------ + # Tests: Behaviour + # ------------------------------------------------------------ + - name: test + shell: bash + run: | + make test diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 0000000..911d841 --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,30 @@ +--- +name: test-windows +on: + pull_request: + push: + branches: + - master + tags: + +jobs: + test: + runs-on: windows-latest + strategy: + fail-fast: False + + name: "[test] [windows]" + steps: + # ------------------------------------------------------------ + # Setup + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + + # ------------------------------------------------------------ + # Tests: Behaviour + # ------------------------------------------------------------ + - name: test + shell: bash + run: | + make test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4a38cb7..0000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- - -### -### Enable sudo (required for docker service) -### -sudo: required - - -### -### Language -### -language: minimal - - -### -### What operating systems to test on -### -os: - - linux - - osx - - -### -### Install requirements -### -install: - - retry() { - for ((n=0; n<60; n++)); do - echo "[${n}] ${*}"; - if eval "${*}"; then - return 0; - fi; - sleep 1; - done; - return 1; - } - - -### -### Linting -### -before_script: - - if [ "$TRAVIS_OS_NAME" != "osx" ]; then - retry make lint; - fi - - -### -### Testing -### -script: - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - retry make test; - else - retry make test ARGS=1; - fi diff --git a/README.md b/README.md index d47251a..ce2459e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # cert-gen -[![Build Status](https://travis-ci.org/devilbox/cert-gen.svg?branch=master)](https://travis-ci.org/devilbox/cert-gen) -[![Discord](https://img.shields.io/discord/1051541389256704091?color=8c9eff&label=Discord&logo=discord)](https://discord.gg/2wP3V6kBj4) ![Tag](https://img.shields.io/github/tag/devilbox/cert-gen.svg) +[![Discord](https://img.shields.io/discord/1051541389256704091?color=8c9eff&label=Discord&logo=discord)](https://discord.gg/2wP3V6kBj4) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) +[![linting](https://github.com/devilbox/cert-gen/workflows/linting/badge.svg)](https://github.com/devilbox/cert-gen/actions/workflows/linting.yml) +[![test-linux](https://github.com/devilbox/cert-gen/workflows/test-linux/badge.svg)](https://github.com/devilbox/cert-gen/actions/workflows/test-linux.yml) +[![test-macos](https://github.com/devilbox/cert-gen/workflows/test-macos/badge.svg)](https://github.com/devilbox/cert-gen/actions/workflows/test-macos.yml) +[![test-windows](https://github.com/devilbox/cert-gen/workflows/test-windows/badge.svg)](https://github.com/devilbox/cert-gen/actions/workflows/test-windows.yml) + Easily create your own CA and self-signed certificates. The generated CA can be imported into Chrome, Firefox or Internet Explorer for local development. diff --git a/bin/ca-gen b/bin/ca-gen index 9650440..09bcab2 100755 --- a/bin/ca-gen +++ b/bin/ca-gen @@ -5,6 +5,8 @@ set -u set -o pipefail NAME="ca-gen" +VERSION="v0.9" +DATE="2022-12-18" # Generate default options DEF_KEYSIZE=2048 @@ -22,10 +24,28 @@ DEF_EMAIL= # Verbosity DEF_VERBOSE= +log() { + local type="${1}" # err, warn, info + local message="${2}" # message to log + + if [ "${type}" = "err" ]; then + printf "%s: [ERROR] %s\n" "${NAME}" "${message}" 1>&2 # stdout -> stderr + fi + if [ "${type}" = "warn" ]; then + printf "%s: [WARN] %s\n" "${NAME}" "${message}" 1>&2 # stdout -> stderr + fi + if [ "${DEF_VERBOSE:-}" = "1" ]; then + if [ "${type}" = "info" ]; then + printf "%s: [INFO] %s\n" "${NAME}" "${message}" + fi + fi +} print_version() { - echo "${NAME} v0.8" + echo "${NAME}: Version ${VERSION} (${DATE}) by cytopia" + echo "https://github.com/devilbox/cert-gen/" } + print_help() { echo "USAGE: ${NAME} -n CN [-kdcslouev] " echo " ${NAME} --help" @@ -75,7 +95,7 @@ while [ ${#} -gt 0 ]; do -k) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -k requires an argument." + log "err" "Usage: -k requires an argument." exit 1 fi DEF_KEYSIZE="${1}" @@ -84,7 +104,7 @@ while [ ${#} -gt 0 ]; do -d) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -d requires an argument." + log "err" "Usage: -d requires an argument." exit 1 fi DEF_DAYS="${1}" @@ -93,7 +113,7 @@ while [ ${#} -gt 0 ]; do -c) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -c requires an argument." + log "err" "Usage: -c requires an argument." exit 1 fi DEF_COUNTRY="${1}" @@ -102,7 +122,7 @@ while [ ${#} -gt 0 ]; do -s) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -s requires an argument." + log "err" "Usage: -s requires an argument." exit 1 fi DEF_STATE="${1}" @@ -111,7 +131,7 @@ while [ ${#} -gt 0 ]; do -l) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -l requires an argument." + log "err" "Usage: -l requires an argument." exit 1 fi DEF_CITY="${1}" @@ -120,7 +140,7 @@ while [ ${#} -gt 0 ]; do -o) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -o requires an argument." + log "err" "Usage: -o requires an argument." exit 1 fi DEF_ORG="${1}" @@ -129,7 +149,7 @@ while [ ${#} -gt 0 ]; do -u) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -u requires an argument." + log "err" "Usage: -u requires an argument." exit 1 fi DEF_UNIT="${1}" @@ -138,7 +158,7 @@ while [ ${#} -gt 0 ]; do -n) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -n requires an argument." + log "err" "Usage: -n requires an argument." exit 1 fi DEF_CN="${1}" @@ -147,7 +167,7 @@ while [ ${#} -gt 0 ]; do -e) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -e requires an argument." + log "err" "Usage: -e requires an argument." exit 1 fi DEF_EMAIL="${1}" @@ -159,7 +179,7 @@ while [ ${#} -gt 0 ]; do break ;; -*) # Unknown option - >&2 echo "${NAME}: Error: Unknown option: ${1}" + log "err" "Usage: Unknown option: ${1}" exit 1 ;; *) # No more options @@ -174,12 +194,12 @@ done ################################################################################ if [ -z "${DEF_CN}" ]; then - >&2 echo "${NAME}: Error: -n is required. See --help for help." + log "err" "Usage: -n is required. See --help for help." exit 1 fi if [ "${#}" -lt "2" ]; then - >&2 echo "${NAME}: Error: and are required. See --help for help." + log "err" "Usage: and are required. See --help for help." exit 1 fi @@ -235,17 +255,12 @@ cmd="openssl genrsa \ # Trim newlines/whitespaces cmd="$( echo "${cmd}" | tr -s " " )" -# Debug -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "\$ ${cmd}" -fi # Execute +log "info" "Create CA KEY file: ${CA_KEY_FILE}" if ! out="$( eval "${cmd}" 2>&1 )"; then - if [ -z "${DEF_VERBOSE}" ]; then - echo "\$ ${cmd}" - fi - >&2 echo "${out}" + log "err" "Command: ${cmd}" + log "err" "Output: ${out}" exit 1 fi @@ -294,17 +309,12 @@ cmd="openssl req \ # Trim newlines/whitespaces cmd="$( echo "${cmd}" | tr -s " " )" -# Debug -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "\$ ${cmd}" -fi # Execute +log "info" "Create CA CRT file: ${CA_CRT_FILE}" if ! out="$( eval "${cmd}" 2>&1 )"; then - if [ -z "${DEF_VERBOSE}" ]; then - echo "\$ ${cmd}" - fi - >&2 echo "${out}" + log "err" "Command: ${cmd}" + log "err" "Output: ${out}" exit 1 fi @@ -312,18 +322,14 @@ fi ### ### 4. Validate ### +log "info" "Verify CA CRT file: ${CA_CRT_FILE}" if ! out="$( openssl x509 -in "${CA_CRT_FILE}" -text )"; then - echo "${out}" + log "err" "CA CRT verification failed: ${out}" exit 1 fi -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "${out}" -fi +log "info" "Verify CA CRT issuer" if ! out="$( openssl x509 -noout -subject -issuer -in "${CA_CRT_FILE}" )"; then - echo "${out}" + log "err" "CA CRT issuer failed: ${out}" exit 1 fi -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "${out}" -fi diff --git a/bin/cert-gen b/bin/cert-gen index ee1e9eb..ada054f 100755 --- a/bin/cert-gen +++ b/bin/cert-gen @@ -5,6 +5,8 @@ set -u set -o pipefail NAME="cert-gen" +VERSION="v0.9" +DATE="2022-12-18" # Generate default options DEF_KEYSIZE=2048 @@ -26,10 +28,28 @@ DEF_ALT_IP_NAME= # Verbosity DEF_VERBOSE= +log() { + local type="${1}" # err, warn, info + local message="${2}" # message to log + + if [ "${type}" = "err" ]; then + printf "%s: [ERROR] %s\n" "${NAME}" "${message}" 1>&2 # stdout -> stderr + fi + if [ "${type}" = "warn" ]; then + printf "%s: [WARN] %s\n" "${NAME}" "${message}" 1>&2 # stdout -> stderr + fi + if [ "${DEF_VERBOSE:-}" = "1" ]; then + if [ "${type}" = "info" ]; then + printf "%s: [INFO] %s\n" "${NAME}" "${message}" + fi + fi +} print_version() { - echo "${NAME} v0.8" + echo "${NAME}: Version ${VERSION} (${DATE}) by cytopia" + echo "https://github.com/devilbox/cert-gen/" } + print_help() { echo "USAGE: ${NAME} -n CN [-kdcsloueav] " echo " ${NAME} --help" @@ -84,7 +104,7 @@ while [ ${#} -gt 0 ]; do -k) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -k requires an argument." + log "err" "Usage: -k requires an argument." exit 1 fi DEF_KEYSIZE="${1}" @@ -93,7 +113,7 @@ while [ ${#} -gt 0 ]; do -d) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -d requires an argument." + log "err" "Usage: -d requires an argument." exit 1 fi DEF_DAYS="${1}" @@ -102,7 +122,7 @@ while [ ${#} -gt 0 ]; do -c) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -c requires an argument." + log "err" "Usage: -c requires an argument." exit 1 fi DEF_COUNTRY="${1}" @@ -111,7 +131,7 @@ while [ ${#} -gt 0 ]; do -s) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -s requires an argument." + log "err" "Usage: -s requires an argument." exit 1 fi DEF_STATE="${1}" @@ -120,7 +140,7 @@ while [ ${#} -gt 0 ]; do -l) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -l requires an argument." + log "err" "Usage: -l requires an argument." exit 1 fi DEF_CITY="${1}" @@ -129,7 +149,7 @@ while [ ${#} -gt 0 ]; do -o) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -o requires an argument." + log "err" "Usage: -o requires an argument." exit 1 fi DEF_ORG="${1}" @@ -138,7 +158,7 @@ while [ ${#} -gt 0 ]; do -u) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -u requires an argument." + log "err" "Usage: -u requires an argument." exit 1 fi DEF_UNIT="${1}" @@ -147,7 +167,7 @@ while [ ${#} -gt 0 ]; do -n) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -n requires an argument." + log "err" "Usage: -n requires an argument." exit 1 fi DEF_CN="${1}" @@ -156,7 +176,7 @@ while [ ${#} -gt 0 ]; do -e) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -e requires an argument." + log "err" "Usage: -e requires an argument." exit 1 fi DEF_EMAIL="${1}" @@ -165,7 +185,7 @@ while [ ${#} -gt 0 ]; do -a) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -a requires an argument." + log "err" "Usage: -a requires an argument." exit 1 fi DEF_ALT_NAME="${1}" @@ -174,7 +194,7 @@ while [ ${#} -gt 0 ]; do -i) shift if [ -z "${1:-}" ]; then - >&2 echo "${NAME}: Error: -i requires an argument." + log "err" "Usage: -i requires an argument." exit 1 fi DEF_ALT_IP_NAME="${1}" @@ -186,7 +206,7 @@ while [ ${#} -gt 0 ]; do break ;; -*) # Unknown option - >&2 echo "${NAME}: Error: Unknown option: ${1}" + log "err" "Usage: Unknown option: ${1}" exit 1 ;; *) # No more options @@ -201,12 +221,12 @@ done ################################################################################ if [ -z "${DEF_CN}" ]; then - >&2 echo "${NAME}: Error: -n is required. See --help for help." + log "err" "Usage: -n is required. See --help for help." exit 1 fi if [ "${#}" -lt "5" ]; then - >&2 echo "${NAME}: Error: and are required. See --help for help." + log "err" "Usage: and are required. See --help for help." exit 1 fi @@ -217,11 +237,11 @@ CSR_FILE="${4}" CRT_FILE="${5}" if [ ! -f "${CA_KEY_FILE}" ]; then - >&2 echo "${NAME}: Error: file does not exist in: ${CA_KEY_FILE}" + log "err" "Usage: file does not exist in: ${CA_KEY_FILE}" exit 1 fi if [ ! -f "${CA_CRT_FILE}" ]; then - >&2 echo "${NAME}: Error: file does not exist in: ${CA_CRT_FILE}" + log "err" "Usage: file does not exist in: ${CA_CRT_FILE}" exit 1 fi @@ -313,17 +333,12 @@ cmd="openssl req \ # Trim newlines/whitespaces cmd="$( echo "${cmd}" | tr -s " " )" -# Debug -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "\$ ${cmd}" -fi # Execute +log "info" "Create CSR file: ${CSR_FILE}" if ! out="$( eval "${cmd}" 2>&1 )"; then - if [ -z "${DEF_VERBOSE}" ]; then - echo "\$ ${cmd}" - fi - >&2 echo "${out}" + log "err" "Command: ${cmd}" + log "err" "Output: ${out}" exit 1 fi @@ -349,17 +364,12 @@ cmd="openssl x509 \ # Trim newlines/whitespaces cmd="$( echo "${cmd}" | tr -s " " )" -# Debug -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "\$ ${cmd}" -fi # Execute +log "info" "Create CRT file: ${CRT_FILE}" if ! out="$( eval "${cmd}" 2>&1 )"; then - if [ -z "${DEF_VERBOSE}" ]; then - echo "\$ ${cmd}" - fi - >&2 echo "${out}" + log "err" "Command: ${cmd}" + log "err" "Output: ${out}" exit 1 fi @@ -367,18 +377,14 @@ fi ### ### 4. Validate ### +log "info" "Verify CRT file: ${CRT_FILE}" if ! out="$( openssl x509 -in "${CRT_FILE}" -text -noout )"; then - echo "${out}" + log "err" "CRT verification failed: ${out}" exit 1 fi -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "${out}" -fi +log "info" "Verify CRT against CA file: ${CA_CRT_FILE}" if ! out="$( openssl verify -verbose -CAfile "${CA_CRT_FILE}" "${CRT_FILE}" )"; then - echo "${out}" + log "err" "CA verification failed: ${out}" exit 1 fi -if [ "${DEF_VERBOSE}" = "1" ]; then - echo "${out}" -fi