Skip to content

Commit

Permalink
Initial script creation and Readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
labbots committed Apr 24, 2020
1 parent 5a7ce0c commit 8a1ff99
Show file tree
Hide file tree
Showing 2 changed files with 312 additions and 1 deletion.
260 changes: 260 additions & 0 deletions OVPN-config-manipulator.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
#!/usr/bin/env bash

function usage() {

echo -e "\nThe script can be used to split or merge ovpn file."
echo -e "\nBasic Usage:\n $0 [options..] <ovpn-config-file> \n"
echo -e "Open VPN config file can be passed either as argument or through option (--source | -s ). \n"
echo -e "\nOptions:"
echo -e "-p | --split - flag to split ovpn file."
echo -e "-s<filepath> | --source <filepath> - Option to pass the source ovpn file."
echo -e "-d<folderpath> | --destination <folderpath> - Destination location where the newly created config to be stored. "
echo -e "-m | --merge [optional parameter : auto] - simple flag to merge file. takes a optional parameter [auto]."
echo -e "if auto is set, then the script tries to identify certificates and keys from path specified in ovpn file. This can be overridden by other options."
echo -e "--ca <filepath> - option to specify the location of the CA file. "
echo -e "--cert <filepath> - option to specify the location of the certificate file."
echo -e "--key <filepath> - option to specify the location of the key file. "
echo -e "--tls-auth <filepath> - option to specify the location of the tls-auth file."
echo -e "--dh-params <filepath> - opton to specify the location of the dh params file."
echo -e "-h | --help - Display usage instructions.\n"
echo -e "Example usage for merge:\n"
echo -e "$0 -m=auto -s home/openvpn/vpn.ovpn"
echo -e "--ca home/openvpn/vpn-ca.crt"
echo -e "-d home/openvpn/merged/ --cert home/openvpn/vpn-client.crt --key home/openvpn/vpn-client.key"
echo -e "\n\nExample usage for split:\n"
echo -e "$0 -s home/openvpn/vpn.ovpn -d home/openvpn/split/\n"
exit 0
}

shortHelp() {
echo -e "\nNo valid arguments provided, use -h/--help flag to see usage."
exit 0
}

# Print short help
[ "$#" = "0" ] && shortHelp

PROGNAME=${0##*/}
SHORTOPTS="hm::ps:d:D:"
LONGOPTS="help,merge::,split,source:,destination:,ca:,cert:,key:,tls-auth:,dh-params:"
set -o errexit -o noclobber -o pipefail

OPTS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name $PROGNAME -- "$@")
eval set -- "$OPTS"

#Base variable declaration
FILE=""
DESTINATION=""
MERGE=false
MERGEAUTO=false
SPLIT=false
CA=""
CERT=""
KEY=""
TLS_AUTH=""
DH=""

while true; do
case "$1" in
-m | --merge)
case "$2" in
"")
MERGE=true
shift 2
;;
"auto" | "=auto")
MERGE=true
MERGEAUTO=true
shift 2
;;
esac
;;
-p | --split)
SPLIT=true
shift
;;
-s | --source)
FILE="$2"
shift 2
;;
-d | --destination)
DESTINATION="$2"
shift 2
;;
-h | --help)
usage
shift
;;
--ca)
CA="$2"
shift 2
;;
--cert)
CERT="$2"
shift 2
;;
--key)
KEY="$2"
shift 2
;;
--tls-auth)
TLS_AUTH="$2"
shift 2
;;
--dh-params)
DH="$2"
shift 2
;;
--)
shift
break
;;
*) break ;;
esac
done

# if both merge and split flags are set then throw error
if [ "$MERGE" = true ] && [ "$SPLIT" = true ]; then
echo "Cannot set flag merge and split at the same time."
exit 1
fi

# if no flags are set then throw error
if [ "$MERGE" = false ] && [ "$SPLIT" = false ]; then
echo "Atlest one of the merge or split flag must be set."
exit 1
fi

# If argument is passed to the script, the source set through options is overridden by argument value.
# argument takes priority.
if [ ! -z "$1" ]; then
FILE="$1"
fi

# Check if the file parameter is not empty
if [ -z "$FILE" ]; then
echo "Filepath of openvpn config is mandatory."
exit 1
fi

# If Destination folder is specified then we check whether the folder is there, if not the folder is created.
if [ ! -z "$DESTINATION" ] && [ ! -d "$DESTINATION" ]; then
mkdir -p $DESTINATION
if [ $? -ne 0 ]; then
echo "Creating destination directory failed."
exit 1
fi
DESTINATION="$(readlink -f $DESTINATION)"

fi

if [ ! -z "$DESTINATION" ] && [ -d "$DESTINATION" ]; then

DESTINATION="$(readlink -f $DESTINATION)"
fi

# If Destination is empty then create files in the same directory as of source file
if [ -z "$DESTINATION" ]; then

DESTINATION="$(dirname "$(readlink -f $FILE)")"
fi

if [ ! -f "$FILE" ]; then
echo "Invalid file name : $FILE"
exit 1
fi

FULLFILENAME=$(basename $FILE)
FILENAME="${FULLFILENAME%.*}"
EXTENSION="${FULLFILENAME##*.}"

if [ ! -z "$SPLIT" ] && [ "$SPLIT" = true ]; then

if [ $(echo $EXTENSION | tr [:upper:] [:lower:]) = $(echo "conf" | tr [:upper:] [:lower:]) ] || [ $(echo $EXTENSION | tr [:upper:] [:lower:]) = $(echo "ovpn" | tr [:upper:] [:lower:]) ]; then

NEWPATH=${DESTINATION}/${FILENAME}-
NEWFILE=${NEWPATH}updated.ovpn
cp $FILE $NEWFILE

if grep -q "<ca>" "$FILE"; then
sed '1,/<ca>/d;/<\/ca>/,$d' $FILE > ${NEWPATH}ca.crt
sed -i "/<ca>/,/<\/ca>/c\ca ${NEWPATH}ca.crt" ${NEWFILE}
fi
if grep -q "<cert>" "$FILE"; then
sed '1,/<cert>/d;/<\/cert>/,$d' $FILE > ${NEWPATH}client.crt
sed -i "/<cert>/,/<\/cert>/c\cert ${NEWPATH}client.crt" ${NEWFILE}
fi
if grep -q "<key>" "$FILE"; then
sed '1,/<key>/d;/<\/key>/,$d' $FILE > ${NEWPATH}client.key
sed -i "/<key>/,/<\/key>/c\key ${NEWPATH}client.key" ${NEWFILE}
fi
if grep -q "<tls-auth>" "$FILE"; then
sed '1,/<tls-auth>/d;/<\/tls-auth>/,$d' $FILE > ${NEWPATH}ta.key
sed -i "/<tls-auth>/,/<\/tls-auth>/c\tls-auth ${NEWPATH}ta.key" ${NEWFILE}
fi
if grep -q "<dh>" "$FILE"; then
sed '1,/<dh>/d;/<\/dh>/,$d' $FILE > ${NEWPATH}dh.pem
sed -i "/<dh>/,/<\/dh>/c\dh ${NEWPATH}dh.pem" ${NEWFILE}
fi

else
echo "Invalid open vpn file extension"
exit 1
fi

fi

if [ ! -z "$MERGE" ] && [ "$MERGE" = true ]; then
NEWFILE=${DESTINATION}/${FILENAME}-merged.ovpn
cp $FILE $NEWFILE

# if merge auto is set then try to find the certificate/key path from the source ovpn file
if [ "$MERGEAUTO" = true ]; then
for tagname in ca cert key tls_auth dh; do
VAR=$(echo "$tagname" | tr '[:lower:]' '[:upper:]')
VARVAL="${!VAR}"
if [ -z "$VARVAL" ]; then
tagname=$(echo "$tagname" | sed "s/_/-/")
path="$(sed -n -e "s/^$tagname //p" $NEWFILE | xargs readlink -f)"
if [ ! -z "$path" ]; then
declare $VAR=$path
fi
fi
done
fi

if [ -z "$CA" ] && [ -z "$CERT" ] && [ -z "$KEY" ] && [ -z "$TLSAUTH" ]; then
echo "Atleast one option (ca,cert,key,tls-auth) parameter is required."
exit 1
fi

for tagname in ca cert key tls_auth dh; do
#convert the tagname to upper to access the variables.
VAR=$(echo "$tagname" | tr '[:lower:]' '[:upper:]')
VARVAL="${!VAR}"
if [ ! -z "$VARVAL" ] && [ ! -f "$VARVAL" ]; then
echo "Provided ${tagname} file does not exist."
exit 1
fi
#replace underscore with hypen in tagname for searching the file
tagname=$(echo "$tagname" | sed "s/_/-/")
if [ ! -z "$VARVAL" ]; then
#If substitution exist in the config file then replace it with inline content
#else append the config file with the content of the file
if grep -qE "^${tagname}[ \t]*.*$" "$NEWFILE"; then
FULLFILENAME=$(basename $VARVAL)
sed -i "/${tagname} .*${FULLFILENAME}/c\<${tagname}>\n<\/${tagname}>" ${NEWFILE}
sed -i "/<${tagname}>/r ${VARVAL}" ${NEWFILE}
else
echo "<${tagname}>" >> ${NEWFILE}
cat ${VARVAL} >> ${NEWFILE}
echo "</${tagname}>" >> ${NEWFILE}
fi
fi

done
#preserve file timestamp from original file so if the original config is updated
#then we know that the generated one config needs to be regenerated.
filemodtime=$(stat -c%y "$FILE" | sed 's/[ ]\+/ /g')
touch -m -d "$filemodtime" "$NEWFILE"
fi
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# OVPN-Config-Manipulator
# OVPN Config Manipulator
Open VPN config file (.ovpn) contains several certificates and key files which are required for the setup. This script allows you to merge those certificates and keys into single config file. The script can also be used to split a single self-contained ovpn config file to individual config and cert files.

## Dependencies

This script does not have very many dependencies. Most of the dependencies are available by default in most linux platforms. This script requires the following packages.

- sed (Stream editor)
- grep
- awk
- getopt
- xargs

## Usage
The script can be used to merge or split OVPN file.

Basic Usage:

./OVPN-config-manipulator.sh [options..] <ovpn-config-file>

To split a OVPN file into main config file and relevant cert and key files, the script can be used as follows

./OVPN-config-manipulator.sh -p -s home/openvpn/vpn.ovpn -d home/openvpn/split/

In the above example `-p` option specifies split operation. The source file is read from location specified in `-s` option. The final split files are stored in the directory specified in `-d` option.

To merge OVPN config file and relevant certificates, the script can be used as follows

./OVPN-config-manipulator.sh -m=auto -s home/openvpn/vpn.ovpn -d home/openvpn/merged/ \
--ca home/openvpn/vpn-ca.crt \
--cert home/openvpn/vpn-client.crt \
--key home/openvpn/vpn-client.key

In the above example `-m` option indicates merge operation. The source file is loaded from file specified in `-s` option and output single merged config file is saved to destination folder specified in `-d` option. The `auto` option set to `-m` flag will make the script to auto detect ca file, certificate, key, tls-auth certificate and dh-params files from path specified within the OVPN file. If those values exists within the OVPN config file then the script automatically tries to read content from the location and link it to the file. The values can be overriden by options provided to the script. So in the above example Certificate authority file will be loaded from location provided by `--ca` option even if the path is different in the OVPN config file.

List of options available in the script are

-p | --split - flag to split ovpn file.
-s<filepath> | --source <filepath> - Option to pass the source ovpn file.
-d<folderpath> | --destination <folderpath> - Destination location where the newly created config to be stored.
-m | --merge [optional parameter : auto] - flag to merge file. takes a optional parameter [auto].
if auto is set, then the script tries to identify certificates and keys from path specified in ovpn file. This can be overridden by other options.
--ca <filepath> - option to specify the location of the CA file.
--cert <filepath> - option to specify the location of the certificate file.
--key <filepath> - option to specify the location of the key file.
--tls-auth <filepath> - option to specify the location of the tls-auth file.
--dh-params <filepath> - opton to specify the location of the dh params file.
-h | --help - Display usage instructions.

## License

MIT

0 comments on commit 8a1ff99

Please sign in to comment.