-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgenerate-secret.sh
executable file
·137 lines (131 loc) · 4.19 KB
/
generate-secret.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/bin/bash -e
ARGS_INOUT=()
SECRET_POOL=()
ARGS_STDOUT=false
ARGS_KEYWORD=GENERATE_SECRET
ARGS_SECRET_LENGTH=48
function usage {
echo "usage: generate-secret.sh [-k keyword] [-s strength] [file1.in [file1.out]] [file2.in [file2.out]]"
echo " -k keyword Keyword for secret, default to GENERATE_SECRET"
echo " -s strength Secret length, default to 48."
echo " file.in Input template file, if no input specified, default to stdin"
echo " file.out Output file, default to stdout"
}
function parse_arguments {
local ARGS_IN=""
local ARGS_OUT=""
while getopts "hk:s:" opt; do
case ${opt} in
h)
usage
exit 0
;;
k)
ARGS_KEYWORD=$OPTARG
;;
s)
ARGS_SECRET_LENGTH=$OPTARG
;;
esac
done
shift $(expr $OPTIND - 1 )
while test $# -gt 0; do
ARGS_INOUT+=("$1::$2")
if [ -z $2 ]; then
ARGS_STDOUT=true
shift
else
shift 2
fi
done
if [ ${#ARGS_INOUT[@]} -eq 0 ]; then
ARGS_INOUT["/dev/stdin"]=""
fi
for key in "${ARGS_INOUT[@]}"; do
local infile="${key%%::*}"
local outfile="${key##*::}"
echo "[I] Input: ${infile} -> ${outfile}";
done
}
function generate_secret {
local INFILE=$1
local OUTFILE=$2
local KEYWORD=$3
local STRENGTH=$4
local TMPFILE="${OUTFILE}.tmp"
touch "${TMPFILE}"
# Mix template with current values
while IFS='' read -r LINE || [[ -n "$LINE" ]]; do
if [[ "${LINE}" =~ ^[[:space:]]*# ]]; then
echo "${LINE}" >> "${TMPFILE}"
elif [[ ${LINE} = *"="* ]]; then
KEY=${LINE%%=*}
VALUE=${LINE#*=}
if [[ ${VALUE} = *"${KEYWORD}"* ]]; then
echo "${LINE}" >> "${TMPFILE}"
else
if [ -f "${OUTFILE}" ]; then
OLD=$(grep -o "${KEY}=[^,]*" "${OUTFILE}" | sed 's/\(.*\)=\(.*\)/\2/' | tr -s "[:blank:]")
else
OLD=
fi
if [ "${OLD}" = "" ]; then
echo "${KEY}=${VALUE}" >> "${TMPFILE}"
else
echo "${KEY}=${OLD}" >> "${TMPFILE}"
fi
fi
else
echo "${LINE}" >> "${TMPFILE}"
fi
done < "${INFILE}"
# Substitute secrets
for i in $(seq 1 $(grep -c -e "${KEYWORD}\[.*\]" "${TMPFILE}")); do \
NAME=$(grep -o -m1 -e "${KEYWORD}\[.*\]" "${TMPFILE}" | sed -n "s/${KEYWORD}\[\(.*\)\]/\1/p"); \
local SAVED_SECRET=
for key in "${SECRET_POOL[@]}"; do
local secretKey="${key%%::*}"
local secretValue="${key##*::}"
if [ "${NAME}" = "${secretKey}" ]; then
SAVED_SECRET="${secretValue}"
fi
done
if [ -z ${SAVED_SECRET} ]; then
SAVED_SECRET="$(head -c 512 /dev/urandom | LC_CTYPE=C tr -cd 'a-zA-Z0-9' | head -c ${STRENGTH})"
SECRET_POOL+=("${NAME}::${SAVED_SECRET}")
fi
sed -i.bak "s/${KEYWORD}\[${NAME}\]/${SAVED_SECRET}/g" "${TMPFILE}"; \
done;
for i in $(seq 1 $(grep -c ${KEYWORD} "$TMPFILE")); do \
sed -i.bak -e "/${KEYWORD}/{s//$(head -c 512 /dev/urandom | LC_CTYPE=C tr -cd 'a-zA-Z0-9' | head -c ${STRENGTH})/;:a" -e '$!N;$!ba' -e '}' "${TMPFILE}"; \
done;
rm -f "$TMPFILE.bak"
if [ -z ${OUTFILE} ]; then
cat "${TMPFILE}" && rm -f "${TMPFILE}"
else
# backup
if [ -f "${OUTFILE}" ]; then
cp -f "${OUTFILE}" "${OUTFILE}.bak"
fi
mv "${TMPFILE}" "${OUTFILE}"
fi
}
function main {
parse_arguments $@
if [ -z ${ARGS_KEYWORD} ] || [ -z ${ARGS_SECRET_LENGTH} ]; then
usage
exit 0
fi
if [ "${ARGS_STDOUT}" != "true" ]; then
echo "== Secret Generator =="
fi
for key in "${ARGS_INOUT[@]}"; do
local infile="${key%%::*}"
local outfile="${key##*::}"
generate_secret "${infile}" "${outfile}" "${ARGS_KEYWORD}" "${ARGS_SECRET_LENGTH}"
done
if [ "${ARGS_STDOUT}" != "true" ]; then
echo "Generated secret of strength ${ARGS_SECRET_LENGTH}."
fi
}
main $@