Skip to content

Instantly share code, notes, and snippets.

@labbots
Last active May 28, 2022 07:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save labbots/42ef27ba90c427d9b5bc396095c007fb to your computer and use it in GitHub Desktop.
Save labbots/42ef27ba90c427d9b5bc396095c007fb to your computer and use it in GitHub Desktop.
Open VPN Config file with inline certificate and keys does not load in network-manager. So here is a simple script to automate the config creation. The script can be used to both merge and split ovpn config files. https://labbots.com/open-vpn-config-file-split-and-merge-bash/
#!/bin/bash
#https://bugs.launchpad.net/ubuntu/+source/network-manager-openvpn/+bug/606365
#http://howto.praqma.net/ubuntu/vpn/openvpn-access-server-client-on-ubuntu
#!/bin/bashset -e
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 specify 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 specify to merge file. takes a optional parameter [auto]."
echo -e "if auto is set, then the script tries to identify certificates and keys from ovpn file. This can be overridded 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;
}
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
@tribals
Copy link

tribals commented Sep 15, 2017

Hi there! Thank you a lot for this script, it rescued me in the right time. Here is addition which adds support for dh-params: https://gist.github.com/tribals/54032978177dbf12cb65ea7495931113. Can you merge it please, so I can delete my forked gist?

@labbots
Copy link
Author

labbots commented Oct 20, 2017

@tribals thank you for your contribution. I have updated the gist now.

@labbots
Copy link
Author

labbots commented Apr 24, 2020

The script is now maintained in the following repository https://github.com/labbots/OVPN-Config-Manipulator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment