diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..effaf2e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM alpine:3.8 + +WORKDIR / + +RUN apk add -U openssl openssl-dev bash curl tar wget nano build-base ca-certificates automake gcc abuild binutils \ + && apk add python openssh-client libtool intltool autoconf libxml2-dev krb5-dev lz4 lz4-dev linux-headers py2-lxml py2-requests git \ + && rm -rf /var/cache/apk/* + +RUN git clone https://github.com/dlenski/openconnect.git +RUN mkdir -p /usr/local/sbin +RUN wget http://git.infradead.org/users/dwmw2/vpnc-scripts.git/blob_plain/HEAD:/vpnc-script -O /usr/local/sbin/vpnc-script +ADD vpnc-script-os /usr/local/sbin/vpnc-script +RUN chmod +x /usr/local/sbin/vpnc-script + +WORKDIR /openconnect + +RUN ./autogen.sh +RUN ./configure --with-vpnc-script=/usr/local/bin/vpnc-script +RUN make check +RUN make + +CMD ["/openconnect/gp-okta/gp-okta.py", "/openconnect/gp-okta/gp-okta.conf"] \ No newline at end of file diff --git a/README.md b/README.md index 981a343..745fa16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pan-globalprotect-okta -Command-line client for PaloAlto Networks' GlobalProtect VPN, integrated with OKTA. +Command-line client for PaloAlto Networks' GlobalProtect VPN, integrated with OKTA. This utility will do the _authentication dance_ with OKTA to retrieve `portal-userauthcookie`, which will be passed to [OpenConnect with PAN GlobalProtect support](https://github.com/dlenski/openconnect) for creating actual VPN connection. @@ -23,6 +23,20 @@ is also required. ./gp-okta.py gp-okta.conf ``` +## docker + +Build image +``` +docker build -t openconnect . +``` +Fill gp-okta.conf with information you want to provide + +launch docker with: +``` +sh launch.sh +``` +it will ask for username/password/second auth if not filled in gp-okta.conf + ## configuration Configuration file should be self-explanatory. Options can be overridden with diff --git a/launch.sh b/launch.sh new file mode 100644 index 0000000..86ea6e8 --- /dev/null +++ b/launch.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +conf_username=`grep username gp-okta.conf | awk -F \= '{print $2}' | tr -d " "` +conf_password=`grep password gp-okta.conf | awk -F \= '{print $2}' | tr -d " "` +totp_okta=`grep totp.okta gp-okta.conf | awk -F \= '{print $2}' | tr -d " "` +totp_google=`grep totp.google gp-okta.conf | awk -F \= '{print $2}' | tr -d " "` + +haystack="okta google" + +if [[ -z "${totp_okta}" && -z "${totp_google}" ]]; then + read -p "Enter Second auth numbers (okta or google), (prepend with needed provider e.g okta_1234): " totp + if [[ "${totp}" ]]; then + totp_choice=`echo ${totp} | awk -F _ '{ print $1 }'` + totp_numbers=`echo ${totp} | awk -F _ '{ print $2 }'` + if [[ -n "echo $haystack|grep $totp_choice" ]]; then + echo "${totp_choice}" + if [[ "${totp_numbers}" && ${totp_choice} ]]; then + sed -i "s/totp.${totp_choice}.*/totp.${totp_choice} = ${totp_numbers}/g" gp-okta.conf + fi + else + echo "Unsupported second auth choosed" + exit 1 + fi + + else + echo "Something failed with parsing second auth" + exit 1 + fi + +fi + +### detect where username is filled in +if [[ "${conf_username}" ]]; then + GP_USERNAME=${conf_username} +fi + +if [[ -z "${conf_username}" && -z "${GP_USERNAME}" ]]; then + read -p "Enter Okta username: " GP_USERNAME +fi + +### detect where password is filled in +if [[ "${conf_password}" ]]; then + GP_PASSWORD=${conf_password} +fi + +if [[ -z "${conf_password}" && -z "${GP_PASSWORD}" ]]; then + read -s -p "Enter Okta password: " GP_PASSWORD +fi + +echo + + +docker run \ + -d \ + --rm \ + --privileged \ + --net=host \ + --cap-add=NET_ADMIN \ + --device /dev/net/tun \ + -e GP_PASSWORD=${GP_PASSWORD} \ + -e GP_USERNAME=${GP_USERNAME} \ + -v /etc/resolv.conf:/etc/resolv.conf \ + -v ${PWD}:/openconnect/gp-okta \ + openconnect \ No newline at end of file diff --git a/vpnc-script-wrapper.sh b/vpnc-script-wrapper.sh index 59829bb..012a3b4 100755 --- a/vpnc-script-wrapper.sh +++ b/vpnc-script-wrapper.sh @@ -23,15 +23,16 @@ _split() { } _get_unbound() { - command -v /usr/local/sbin/unbound-control >/dev/null 2>&1 \ - && echo "/usr/local/sbin/unbound-control" && return 0 - command -v unbound-control >/dev/null 2>&1 \ - && echo "unbound-control" && return 0 - return 1 + command -v /usr/local/sbin/unbound-control >/dev/null 2>&1 \ + && echo "/usr/local/sbin/unbound-control" && return 0 + command -v unbound-control >/dev/null 2>&1 \ + && echo "unbound-control" && return 0 + return 1 } output_routes() { + [ X"${reason}" != X"connect" ] && return if [ -n "${CISCO_SPLIT_INC}" ]; then _i=0 while [ ${_i} -lt ${CISCO_SPLIT_INC} ] ; do @@ -57,6 +58,9 @@ adjust_routes() export CISCO_SPLIT_INC_${_i}_ADDR="${_addr}" export CISCO_SPLIT_INC_${_i}_MASK="${_mask}" export CISCO_SPLIT_INC_${_i}_MASKLEN="${_masklen}" + if [ X"${reason}" = X"connect" ]; then + echo "new.route: ${_addr}/${_masklen}" + fi _i=$(expr ${_i} + 1) done export CISCO_SPLIT_INC=${_i} @@ -65,6 +69,7 @@ adjust_routes() output_dns() { + [ X"${reason}" != X"connect" ] && return echo "orig.dns: ${INTERNAL_IP4_DNS}" echo "orig.domain: ${CISCO_DEF_DOMAIN}" } @@ -72,10 +77,11 @@ output_dns() adjust_dns() { _dns="${INTERNAL_IP4_DNS}" + [ -z "${_dns}" ] && return + _unbound=$(_get_unbound) || \ + { echo "warn: unbound not found" >&2 && return; } unset CISCO_DEF_DOMAIN unset INTERNAL_IP4_DNS - [ -z "${_dns}" ] && return - _unbound=$(_get_unbound) || { echo "err: unbound not found" >&2 && exit 1; } IFS=$NLIFS for _line in ${_DOMAINS}; do _split "${_line}" ' ' _domain _insecure _ @@ -104,4 +110,3 @@ output_dns adjust_dns ${_VPNC_SCRIPT} $@ -