課題
弊社では、作業用端末としてスタッフに iPad(第10世代)を配布しています。
普段の在宅ワークでは各自のパソコンから WorkSpaces にアクセスして作業してもらっています。
iPad でも WorkSpaces クライアントアプリケーションのインストールができるので、外出先からは iPad から WorkSpaces に接続して業務をしてもらおうと考えていました。
iPad 用の Magic Keyboard で操作することを想定していましたが、WorkSpaces にログインはできるけど、矢印キーが動作しない事象に遭遇しました。
原因
調べてみても原因や同じ事象は確認できず、正直、原因は不明です。
複数の端末で発生しているので、端末側の不具合とかではなさそうですが、同じような事象の報告はネットで確認できませんでした。
ただ、以下のように回避してひとまず矢印キーの操作ができるようになったのでよしとしています。
方法
結論から言うと、RDP で WorkSpaces に接続しています。
どうやら、PCoIP での接続に原因がありそうで、RDP で WorkSpaces に接続することで矢印キーの操作ができました。
以下を参考にしました。
RDP で WorkSpace に接続するにはどうすれば良いですか?
https://repost.aws/ja/knowledge-center/connect-workspace-rdp
ただ、WorkSpaces のあるサブネットは、プライベートサブネットのままにしておきたい要件もあり、AWS Client VPN も合わせて使うこととしました。
WorkSpaces で既に Directory Service を使用しているので、そのまま AWS Client VPN の承認にも使用できます。
結構これは嬉しくて、社員は普段使っているパスワードで AWS Client VPN に接続できます。
構成は以下のような感じです。
構成の準備としては以下です。
- Route 53 プライベートホストゾーン (user.workspaces) を作成
- Client VPN エンドポイントを作成
- サーバ証明書は適当に取得していたドメインの証明書を使用
- 認証はユーザー認証で既存の Directory Service を指定
- 承認ルールは 0.0.0.0/0 を全てのユーザーに許可
(そのうち WorkSpaces のサブネット CIDR に絞るかもしれません。) - ターゲットネットワークは適当なサブネットを指定
- DNS は VPC CIDR +2 の IP アドレスを指定
(プライベートホストゾーンを使うので)
- Lambda 関数 (AWSClientVPN-ReadyWorkSpaces) を作成
- ユーザーの WorkSpaces を起動するため
- ユーザーの WorkSpaces の IP アドレスにドメイン名を割り当てるため
- それぞれに必要な権限を IAM ロールで付与
- Lambda ハンドラーを Client VPN エンドポイントに設定
- Client VPN エンドポイントから設定ファイルをダウンロードし社員に配布
WorkSpaces は起動していると結構高いので AutoStop モードで設定しています。
なので、Lambda ハンドラーでその都度起動することにします。
また、RDP を IP アドレスで指定する場合には、社員への展開が面倒なので、ドメイン名で管理することにしました。
Lambda ハンドラーが WorkSpaces の IP アドレスを Route 53 ホストゾーンに登録してくれます。
ほとんど Chat GPT に書かせましたが、Lambda 関数のコードは以下です。
AWSClientVPN-ReadyWorkSpaces のコード
import boto3
def lambda_handler(event, context):
# リソース情報
directory = '<ディレクトリ ID>'
hostedzone = '<ホストゾーン ID>'
domain = 'user.workspaces'
# イベントからユーザー名を取得
username = event.get('username')
if not username:
return {
"allow": True,
"error-msg-on-failed-posture-compliance": "Username not provided",
"posture-compliance-statuses": [],
"schema-version": "v2"
}
# WorkSpaces クライアントを作成
workspaces_client = boto3.client('workspaces')
# ユーザーの WorkSpaces を取得
response = workspaces_client.describe_workspaces(
DirectoryId=directory,
UserName=username
)
workspaces = response.get('Workspaces', [])
if not workspaces:
return {
"allow": True,
"error-msg-on-failed-posture-compliance": f'No WorkSpaces found for user {username}',
"posture-compliance-statuses": [],
"schema-version": "v2"
}
# WorkSpaces を起動
workspace_id = workspaces[0]['WorkspaceId']
workspaces_client.start_workspaces(
StartWorkspaceRequests=[
{'WorkspaceId': workspace_id}
]
)
# WorkSpaces の IP アドレスを取得
workspace_ip = workspaces[0]['IpAddress']
# Route 53 クライアントを作成
route53_client = boto3.client('route53')
# サブドメイン名を作成
subdomain = f"{username}.{domain}"
# レコードを作成
try:
route53_client.change_resource_record_sets(
HostedZoneId=hostedzone,
ChangeBatch={
'Changes': [
{
'Action': 'CREATE',
'ResourceRecordSet': {
'Name': subdomain,
'Type': 'A',
'TTL': 300,
'ResourceRecords': [{'Value': workspace_ip}]
}
}
]
}
)
except Exception as ex:
route53_client.change_resource_record_sets(
HostedZoneId=hostedzone,
ChangeBatch={
'Changes': [
{
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': subdomain,
'Type': 'A',
'TTL': 300,
'ResourceRecords': [{'Value': workspace_ip}]
}
}
]
}
)
return {
"allow": True,
"error-msg-on-failed-posture-compliance": f'Successfully started WorkSpaces for user {username}',
"posture-compliance-statuses": [],
"schema-version": "v2"
}
そして、この構成に伴い、社員には以下の内容をお願いしました。
- iPad に OpenVPN クライアントをインストール
- OpenVPN クライアントに設定ファイルをインポート(メールで配布しました。)
- iPad に RD Client をインストール
- RD Client に PC を追加
- ホスト名:<ユーザー名>.user.workspaces
社員が接続する際には、OpenVPN で Client VPN に接続して、RD Client で WorkSpaces に RDP に接続してもらうことにしました。
思ったより躓く方はおらず、展開もスムーズでした。
ひとまずこれで上手くいきそうなので、様子みようと思います。
どなたかの参考となれば幸いです。