LoginSignup
4
4

More than 5 years have passed since last update.

golangを使って、1クリックでGCP上のWindowsにリモートデスクトップ接続する

Posted at

TL;DR

ダブルクリックで指定したGCP上のwindowsインスタンスにリモートデスクトップ接続を開始するツールを作りました。

mpppk/connect-to-gce-win: Tool for connect to Windows on Google Compute Engine via Remote Desktop

connect-to-gce-win2-compressor.gif

クリックすると以下の処理が自動で行われます。

  1. 最初にwindowsインスタンスの一覧を取得し、どのインスタンスに接続するかを表示します。
    • (上のgifの例では、設定ファイルで接続するインスタンスを指定しているので、チェックなしで接続を開始します)
  2. 指定されたインスタンスがTERMINATEDであれば、起動します。
  3. インスタンスのパスワードがリセットされ、新しいパスワードがクリップボードに保存されます。
  4. インスタンスに接続するためのRDPファイルを生成し、OSでファイルに紐づけられているRDPクライアントを自動で開きます。
  5. RDPクライアントがパスワードを聞いてきたら、クリップボードに保存されたパスワードをペーストするだけでログインできます。

(本当はRDPファイルにパスワードを含めることもできるっぽいのですが、めんどくさそうだったのでやってません)

背景

私はmacしか持っていないのですが、たまにwindowsでしかプレイできないゲームをやりたくなることがあります。
とはいえそんなに長時間やるわけではないので、そのためだけにそこそこハイスペックなwindows機を買うのも気が引けます。
で、よく考えると、動きの少ないカードゲーム等であれば、リモートでも十分プレイ可能では?ということで、やりたくなった時だけGCP上のwindowsインスタンスを立ち上げることにしました。
お値段も東京リージョン/8CPU/10GBメモリで$0.379/hourと、新しくWindows PCを買うことを考えれば大変お安いです。
(これは異常にCPUリソースを消費するMagic Arenaというゲームでの例なので8CPUという豪華な構成ですが、他のほとんどのゲームであればもっと安く済むと思います。n1-standard-2(2CPU/7.5GBメモリ)なら$0.1220/hですね。)

GCP上のwindowsへ接続するまでの手順

通常、GCPのwindowsを立ち上げるには以下のステップを踏みます。
(インスタンスの作成とRDPクライアントのインストールは済んでいるものとします)

  1. GCEのダッシュボードを開き、起動したいインスタンスの右側の「起動」を選択

gce-dashboard.png

  1. 起動したらパスワードをリセットして、新しいパスワードをコピーしておく
    • ローカルにパスワードを保存しておくより、毎回リセットした方が安全なので

gce-reset-windows-password.png

  1. 同じメニューからRDPファイルをダウンロード
  2. RDPクライアントで先ほどダウンロードしたRDPファイルを開く
  3. パスワードを聞かれたら、先ほどコピーしたパスワードを入力
  4. ゲームが終わったらインスタンスを落とす

本当は静的IPアドレスを振っておけば同じRDPファイルを使い回せるのですが、インスタンスを落としている間もお金がかかってしまうので、毎回新しくRDPファイルをダウンロードしています。
まあこれでも十分お手軽なので、ゲームをプレイする前に毎回上記の手順を行なっていたのですが、怠惰な人間なのでもっと楽に接続したくなってきました。

golangで一連の処理を行う

GCPの起動やパスワードのリセットは全てAPI経由でも操作可能ですので、自動化できそうです。言語は何でも良いですが、今回はgolangで書いていくことにします。
パッと調べた感じ、GCEのgolang SDKは以下の2種類が使えそうです。

それぞれでしかできないことがあったりするので、今回は2つを併用しています。

クライアントを生成

daisyは以下のようにimportしている前提です。

import daisyCompute "github.com/GoogleCloudPlatform/compute-image-tools/daisy/compute"
ctx := context.Background()

// google apiのクライアント生成
googleDefaultClient, err := google.DefaultClient(ctx)
gceClient, err := compute.New(googleDefaultClient)

// daisyのクライアント生成
daisyClient, err := daisyCompute.NewClient(ctx)

指定したインスタンスを取得

daisyClient.GetInstanceで指定した名前のインスタンスの情報を取得できます。

instance := daisyClient.GetInstance(c.project, c.zone, instanceName)
fmt.Println(instance) // => e.g. "TERMINATED"

インスタンスの一覧を取得

gceCompute.ListInstanceで指定した名前のインスタンスの情報を取得できます。

instances, err := gceClient.ListInstances()

インスタンスを起動

daisyClient.StartInstanceで指定した名前のインスタンスを起動し、STATUSが"RUNNING"になるまでブロックします。
gceClientでも起動はできるのですが、起動完了を知るためにGetInstanceを定期的に叩いてSTATUSをチェックしなければならないので、daisyの方が楽です。

err := daisyClient.StartInstance(instance.Name)

パスワードをリセット

パスワードのリセットは特にAPIが用意されているわけではなく、Metadatawindows-keysという項目へ暗号化した新たなパスワードを追加します。
オフィシャルドキュメントで詳しい方法が解説されているので、こちらをご覧ください。
Windows パスワード生成の自動化  |  Compute Engine ドキュメント  |  Google Cloud

RDPファイルを生成

RDPファイルは単に以下のフォーマットで書かれたテキストファイルです。

full address:s:[target_ip_address]
username:s:[your_username]

というわけで、インスタンスからIPアドレスを取得して、ファイルを生成します。

func extractNatIpFromInstance(instance *compute.Instance) (string, error) {
    if len(instance.NetworkInterfaces) == 0 {
        return "", errors.New("no NetworkInterfaces found")
    }
    accessConfigs := instance.NetworkInterfaces[0].AccessConfigs
    if len(accessConfigs) == 0 {
        return "", errors.New("no AccessConfigs found")
    }
    return accessConfigs[0].NatIP, nil
}

func generateRDPFile(filePath, ip, userName string) error {
    contents := "full address:s:" + ip + "\n" + "username:s:" + userName
    return ioutil.WriteFile(filePath, []byte(contents), 0644)
}

natIP, err := extractNatIpFromInstance(instance)
err = generateRDPFile("test.rdp", natIP, "your_username")

RDPファイルを開く

skratchdot/open-golangでRDPファイルを開けば、OSで紐づけられたクライアントが起動します。

err := open.Run("test.rdp")

実際の実装

これらの処理を実際に書いている部分が、connect-to-gce-win/cmd/root.goです。
実際に動作するコードを確認したい方はこちらをご覧ください。

これで、GCP上のWindowsに一瞬で接続できるようになりました。
Windows PC持ってない方はぜひご検討ください٩(●˙▿˙●)۶

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4