Jamf を使ったAWS VPN Client と OVPNファイル の配布_自動適用
Jamf Proを活用して「AWS VPN Client」のアプリケーションと、「AWS VPN Client」で利用する.ovpnファイルを、配布/自動適用するように環境を作ってみました。
下記リンクを参考にしましたが、何故かエラーが吐き出されたので、エラー回避した上で成功した例を記録してみます。
AWS VPN Clientアプリケーションを配布
まずは、AWS VPN Clientのインストーラを配布して、インストールしておきます。
パッケージの設定
設定 > パッケージ を開きます
「ファイル名」にて、インストーラを選択して配置します
「表示名」は「ファイル名」で設置したインストーラの名称が、そのまま反映されますので、必要に応じて任意の名称に変更してください
オプションタブを選択すると、配布する優先順位が設定できますので、配布したい順番があるようでしたら指定して「保存」をクリックします
ポリシーの設定
ポリシー > 新規 をクリックします
「トリガー」や「実行頻度」は、任意の設定となりますが、例では
トリガー:登録完了
実行頻度:Ongoing と指定しています
「パッケージ」を選択して、上記で設定したパッケージを設定します
Scopeは、配布先の設定となりますので、任意で設定頂き、最後に「保存」をクリックします
ovpnファイルの配布
エラーに関する解説は後ほど記載します。 ここでは一連の流れとして
ovpnファイルの「パッケージ」設定
ovpnファイルのパッケージ配布後の「スクリプト」実行の設定
ポリシーの設定
を話していきます。
ovpnファイルの「パッケージ」設定
AWS VPN Endpointから .ovpnファイルをダウンロードします。
Composer を使ってアクセス権を修正して、pkgで書き出します。
書き出したpkgをJamf Adminでアップロードします
上記2. のpkgで書き出す際、ovpnファイルをデプロイするデプロイ先は「/Applications/AWS VPN Client」に指定の上、Composerでpkgを作成してください。 この後使用するスクリプトでは、「/Applications/AWS VPN Client」にovpnファイルが格納されている前提で、構成されている為。
ovpnファイルのパッケージ配布後の「スクリプト」実行の設定
jamfで スクリプト を開き、下記赤枠にスクリプトを記述します。
スクリプトの内容
#!/bin/bash
#######################################
# Deploy a ovpn file for aws client vpn
# Arguments:
# $1: OpenVPN file
# e.g.) file://tmp/aws-vpn.ovpn
# $2: Profile name displayed in AWS VPN Client
# e.g.) aws-vpn
# $3: CvpnEndpointId
# e.g.) cvpn-endpoint-XXXXXXXXXXXXXXXXX
# $4: CvpnEndpointRegion
# e.g.) ap-northeast-1
# $5: CompatibilityVersion
# 1 : Use mutual authentication
# : Use Active Directory authentication
# 2 : Use Federated authentication
# $6: FederatedAuthType
# 0 : Use mutual authentication
# : Use Active Directory authentication
# 1 : Use Federated authentication
# If you do not know the Arguments, please check the following file path.
# {LOGGED_IN_USER}/.config/AWSVPNClient/ConnectionProfiles
#######################################
# TODO(enpipi) : Checking the behavior when using Active Directory authentication. (enhancement #1)
VERSION='0.2.0'
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Output info log with timestamp
print_info_log(){
local timestamp
timestamp=$(date +%F\ %T)
echo "$timestamp [INFO] $1"
}
# Output error log with timestamp
print_error_log(){
local timestamp
timestamp=$(date +%F\ %T)
echo "$timestamp [ERROR] $1"
}
# Check for the existence of aws client vpn
if [[ ! -e "/Applications/AWS VPN Client/AWS VPN Client.app" ]];then
print_error_log "It seems that the AWS VPN Clinet is not installed. Please install it and try again."
exit 1
fi
if [[ "${1}" = "/" ]];then
# Jamf uses sends '/' as the first argument
print_info_log "Shifting arguments for Jamf."
shift 3
fi
if [[ "${1:l}" = "version" ]];then
echo "${VERSION}"
exit 0
fi
if [[ ! "${1}" ]];then
print_error_log "You need to set ovpn file location."
exit 1
fi
OVPN_FILE_PATH="${1}"
# TODO(enpipi): Check .ovpn file
# print_error_log "File format is not ovpn. You need to set .ovpn file."
if [[ ! "${2}" ]];then
print_error_log "You need to set aws vpn client profile name."
exit 1
fi
PRFILE_NAME="${2}"
# TODO(enpipi): Only alphanumeric characters and " , -, _, (,)" can be used for display name.
# print_error_log "Only alphanumeric characters and " , -, _, (,)" can be used for display name."
if [[ ! "${3}" ]];then
print_error_log "You need to set CvpnEndpointId."
exit 1
fi
C_VPN_ENDPOINT_ID="${3}"
if [[ ! "${4}" ]];then
print_error_log "You need to set CvpnEndpointRegion."
exit 1
fi
C_VPN_ENDPOINT_REGION="${4}"
if [[ ! "${5}" ]];then
print_error_log "You need to set CompatibilityVersion."
exit 1
fi
COMATIBILITY_VERSION="${5}"
if [[ ! "${6}" ]];then
print_error_log "You need to set FederatedAuthType."
exit 1
fi
FEDERATED_AUTH_TYPE="${6}"
print_info_log "Start aws vpn client profile deplyment..."
# Launch and exit the application to generate the initial config file.
# If you don't do this, the application won't launch properly even if you place the ovpn file in the config.
# TODO: Find a way to get the difference when adding and not launch the application.
cd /Applications
open -j -a "AWS VPN Client"
sleep 10; osascript -e 'quit app "AWS VPN Client.app"'
# Find the loggedInUser
LOGGED_IN_USER=$(stat -f %Su /dev/console)
# Set the file path to the ConnectionProfiles file with the loggedIn user
CONNECTION_PROFILES="/Users/$LOGGED_IN_USER/.config/AWSVPNClient/ConnectionProfiles"
OPEN_VPN_CONFIGS_DIRECTORY="/Users/$LOGGED_IN_USER/.config/AWSVPNClient/OpenVpnConfigs"
# addition
OVPN_FILE="/Applications/AWS VPN Client/clientvpn.ovpn"
DELETE_FILE="/Applications/AWS VPN Client/clientvpn.ovpn"
RENAME_FILE="/Applications/AWS VPN Client"
while [ ! -e "$OVPN_FILE" ]
do
sleep 10
done
# Delete auth-federate in OVPN_FILE_PATH
print_info_log "delete auth-federate in ${OVPN_FILE}"
sed -i -e '/auth-federate/d' "$OVPN_FILE"
# Copy and rename ovpn file
print_info_log "copy and rename ovpn file from ${OVPN_FILE} to ${OPEN_VPN_CONFIGS_DIRECTORY}/${PRFILE_NAME}"
cp "$OVPN_FILE" "${OPEN_VPN_CONFIGS_DIRECTORY}/${PRFILE_NAME}"
# Get backup of ConnectionProfiles
print_info_log "Get backup of ${CONNECTION_PROFILES}"
CONNECTION_PROFILES_BACKUP="/Users/$LOGGED_IN_USER/.config/AWSVPNClient/_ConnectionProfiles"
cp "$CONNECTION_PROFILES" "$CONNECTION_PROFILES_BACKUP"
# Make the file
# TODO(enpipi): Add the profile if it already exists, or overwrite it if it doesn't.
# We need to realize this TODO with awk and sed.
# This is because we have to assume that the terminal does not have JQ installed on it.
cat <<EOF > "$CONNECTION_PROFILES"
{
"Version":"1",
"LastSelectedProfileIndex":0,
"ConnectionProfiles":[
{
"ProfileName":"${PRFILE_NAME}",
"OvpnConfigFilePath":"/Users/$LOGGED_IN_USER/.config/AWSVPNClient/OpenVpnConfigs/${PRFILE_NAME}",
"CvpnEndpointId":"${C_VPN_ENDPOINT_ID}",
"CvpnEndpointRegion":"${C_VPN_ENDPOINT_REGION}",
"CompatibilityVersion":"${COMATIBILITY_VERSION}",
"FederatedAuthType":${FEDERATED_AUTH_TYPE}
}
]
}
EOF
print_info_log "End aws vpn client profile deplyment..."
# Fix permissions
chown "$LOGGED_IN_USER" "$CONNECTION_PROFILES"
rm "$DELETE_FILE"
cd "$RENAME_FILE"
for f in *.ovpn-e
do
mv $f ${f/.ovpn-e}.ovpn
done
スクリプトの「オプション」で下記のように設定する。
Paramater Labels のパラメータ4-9に以下のテキストをコピーペーストをします。
パラメータ4 : file://private/temp/aws-vpn.ovpn
パラメータ5 : Display Name on aws vpn client
パラメータ6 : CvpnEndpointId
パラメータ7 : CvpnEndpointRegion
パラメータ8 : CompatibilityVersion
パラメータ9 : FederatedAuthType
ポリシーの設定
ポリシーを開き
トリガー:登録完了
実行頻度:Ongoing
を選択します。
パッケージ に先程アップロードした .ovpnファイルを選択します
スクリプト を選択して、引数を設定する。
pkgファイルを設置したパスを指定します
「Applications/AWS VPN Client/clientvpn.ovpn(ファイル名)」としてください
AWS VPN Clientに表示する名称を入力します
AWS VPN Endpoint IDを入力します
リージョンを指定します
e.g.) us-west-1, ap-northeast-1
Compatilibity Versionを以下の通り設定します。
1 : 相互認証, Active Directory認証
2 : SAML認証
認証のタイプを以下の通り設定します。
0 : 相互認証, Active Directory認証
1 : SAML認証
なお、本設定は AWS VPN Clientに .ovpnファイルを取り込むことで生成される以下のファイルから確認ができます。
> ローカルユーザ名/.config/AWSVPNClient/ConnectionProfiles
Jamfでの設定は以上となります。 元々使っていたスクリプトでエラーが発生してから、エラー回避した内容までを、下記で話していきます。
エラー発生時の解説
上記のJamf内での設定通り、ovpnファイルと一緒に、スクリプトを流し込みますが、流し込むスクリプトに少々変更を加えつつ、エラーを回避しました。
元々利用したスクリプト
上手くいったスクリプト内容は【ovpnファイルのパッケージ配布後の「スクリプト」実行の設定】に書き出した通りとなります。
元のスクリプトの場合、Jamf側でいくつか下記のようなエラーが出力されたので、どこを変更を加えたのか。
あくまで例となりますので、もっと効率の良い方法あるかもしれませんが、温かい目で見守ってください。。
# エラー内容:1
1> Script result: 2022-12-01 18:14:48 [INFO] Shifting arguments for Jamf.
2> 2022-12-01 18:14:48 [INFO] Start aws vpn client profile deplyment...
3> usage: sleep seconds
4> 0:29: execution error: AWS VPN Clientでエラーが起きました:
アプリケーションは実行されていません。 (-600)
5> 2022-12-01 18:14:48
[INFO] copy and rename ovpn file from Applications/AWS VPN Client/clientvpn.ovpn to /Users/hoge/.config/AWSVPNClient/OpenVpnConfigs/hoge1
6> cp: /Users/hoge/.config/AWSVPNClient/OpenVpnConfigs/hoge1:
No such file or directory
7> 2022-12-01 18:14:48
[INFO] Get backup of /Users/hoge/.config/AWSVPNClient/ConnectionProfiles
8> cp: /Users/hoge/.config/AWSVPNClient/ConnectionProfiles:
No such file or directory
9> /Library/Application Support/JAMF/tmp/ovpnfile_AWS VPN Client:
line 143: /Users/hoge/.config/AWSVPNClient/ConnectionProfiles:
No such file or directory
10> 2022-12-01 18:14:48 [INFO] End aws vpn client profile deplyment...
chown: /Users/hoge/.config/AWSVPNClient/ConnectionProfiles:
No such file or directory
エラー内容1 をザックリと説明すると
4行目:インストールされたAWS VPN Clientが起動してませんよ
6行目,8行目,10行目:コピー対象のファイルがありませんよ
AWS VPN Clientを起動してないと、初回起動時に発行されるファイル
OpenVpnConfigs
ConnectionProfiles
この辺りの設定ファイル内容を、上書きできませんよ。 と言っています。
この後配布するOvpnファイルの情報は、元々AWS VPN Clientが初回起動した後に、発行された情報を上書きするような指令になるが、そもそも対象のファイルが発行されていないと、情報の上書きが出来ない為、このような状況になっています。
エラー内容1 を回避した部分(変更箇所)
元々記載していた内容は、上記リンクにあるGithubのコードを確認してもらえればと思いますが、
# Launch and exit the application to generate the initial config file.
# If you don't do this, the application won't launch properly even if you place the ovpn file in the config.
# TODO: Find a way to get the difference when adding and not launch the application.
cd /Applications
open -j -a "AWS VPN Client"
sleep 10; osascript -e 'quit app "AWS VPN Client.app"'
上記のように記述することで「インストールされたAWS VPN Clientが起動してませんよ」というエラーは解消されました。要するに、インストールされたAWS VPN Clientが起動されるようになった。
補足:アプリケーションを起動後、10秒後にアプリケーションを終了するように指定していますが、起動してすぐに終了してしまうと、バックグラウンドの状況によっては、即反映せずに必要なファイルが生成されない可能性もあるようなので、下記記事を参考にこのように指定をしてます。
参考リンク
エラー内容2 をザックリと説明すると
# エラー内容:2
1> copy and rename ovpn file from Applications/AWS VPN Client/clientvpn.ovpn
No such file or directory
コピーして名前を変更するファイルがありません。と言っているので、「clientvpn.ovpn」のファイルが無い状況です。
よくよく確認してみると、「Applications/AWS VPN Client」には、アプリケーションが何も無く、確認しに行っているディレクトリに誤りがあることに気が付きました。 なので
# addition
OVPN_FILE="/Applications/AWS VPN Client/clientvpn.ovpn"
while [ ! -e "$OVPN_FILE" ]
do
sleep 10
done
# Delete auth-federate in OVPN_FILE_PATH
print_info_log "delete auth-federate in ${OVPN_FILE}"
sed -i -e '/auth-federate/d' "$OVPN_FILE"
# Copy and rename ovpn file
print_info_log "copy and rename ovpn file from ${OVPN_FILE} to ${OPEN_VPN_CONFIGS_DIRECTORY}/${PRFILE_NAME}"
cp "$OVPN_FILE" "${OPEN_VPN_CONFIGS_DIRECTORY}/${PRFILE_NAME}"
上記の記述を追加しつつ「$OVPN_FILE」の部分を差し替えることで、解消しました。
念のため、while値で「clientvpn.ovpn」が生成されるまで処理を繰り返すようにすることで、「clientvpn.ovpn」が生成されてから次の処理にするように付け足してます。
そしてエラーとは別に
上記で説明した通り、AWS VPN Endpointからダウンロードしたovpnファイルを、Jamfの「パッケージ」機能を活用して配布する流れとなりますが、本記事の例ではダウンロードしたovpnファイルの配布先をローカルの「/Applications/AWS VPN Client」にデプロイします。
ですが、上記で発生したエラーを解消した後の状態のスクリプトを実行すると、「/Applications/AWS VPN Client」にデプロイするovpnファイルとは別に、「~.ovpn-e」というファイルが別途新たに生成されてしまった。
正しいovpnファイルだけを「/Applications/AWS VPN Client」に残して完了としたいので、下記のスクリプトを追記して実行することで、解消しました。
# addition
DELETE_FILE="/Applications/AWS VPN Client/clientvpn.ovpn"
RENAME_FILE="/Applications/AWS VPN Client"
rm "$DELETE_FILE"
cd "$RENAME_FILE"
for f in *.ovpn-e
do
mv $f ${f/.ovpn-e}.ovpn
done
スクリプトの内容としては
不要なovpnファイルを削除 して
必要なovpnファイルのファイル名を変更して残す 流れとなります。
単純に、不要なovpnファイルだけ削除すれば良いのでは?となるかもしれませんが、必要なovpnファイルが上記で話した「~.ovpn-e」という名前のファイルな為、
不要なovpnファイルを削除(ファイル名:〜.ovpn)
必要なovpnファイル(ファイル名:〜.ovpn-e)を「〜.ovpn」というファイル名に変更
という流れでスクリプトを記述しました。 不要なファイルは極力残さずに削除することで、どのファイルが正しいファイルだっけ?と後からならないようにしたかったのです。 こちらのスクリプト内容に関しては好みの部分や考え方も様々かと思いますので、必要ない動作だなっと判断した場合は、記述を削除してスクリプト実行すれば良いと思います。
最後に
紹介は以上となりますが、あくまで一例となりますので、必要に応じて/環境に応じて適時、カスタマイズして利用頂ければと思います!