Swift

ついに公開されたAPIをSwfitから利用する(SSH公開鍵を取得する)

TECH
中津川 篤司

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。 そこで今回はSwiftを使ってAPI操作を行う方法を解説します。処理内容としては、コントロールパネルで設定した公開鍵を取得します。 必要なソフトウェア、ライブラリ 今回必要なソフトウェア、ライブラリは以下の通りです。 Xcode Ruby(CocoaPods用) cocoapods-keys CocoaPods HydraAsync SwiftyJSON APIキーを取得する まずはCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。 一度パスワードを入力する必要があります。 そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。 Xcodeで新しいプロジェクトを作成する 最初にXcodeでiOSプロジェクトを作成します。作成したら、一旦終了します。 Gemfileを作成する クライアントIDなどを隠すため、 cocoapods-keys をインストールします。以下の内容で Gemfile を作成します。 source 'https://rubygems.org' gem 'cocoapods-keys' そしてbundlerを実行します。 $ bundle Podfileを作成する 次にCocoaPodsで必要なライブラリをインストールします。 Podfile の内容は次の通りです。 {YOUR_PROJECT} は自分のプロジェクト名に置き換えてください。インストールするのはSwiftでasync/awaitを利用するHydraAsync、そしてJSONを扱いやすくするSwiftyJSONです。cocoapods-keysの設定も行っています。 # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target '{YOUR_PROJECT}' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! pod 'HydraAsync' pod 'SwiftyJSON' # Pods for ncmbPush target '{YOUR_PROJECT}Tests' do inherit! :search_paths # Pods for testing end target '{YOUR_PROJECT}UITests' do inherit! :search_paths # Pods for testing end end plugin 'cocoapods-keys', { :project => "{YOUR_PROJECT}", :keys => [ "clientId", "clientSecret" ]} これをインストールした状態で pod install を実行すると、clientIdとclientSecretの入力が求められます。先ほどCloudGarageのコントロールパネルで取得したものをそれぞれ指定してください。 $ pod install CocoaPods-Keys has detected a keys mismatch for your setup. What is the key for clientId > ylk...t1P Saved clientId to cloudgarage. What is the key for clientSecret > iIG...oUo Saved clientSecret to cloudgarage. Analyzing dependencies Fetching podspec for `Keys` from `Pods/CocoaPodsKeys` Downloading dependencies Using HydraAsync (1.2.1) Using Keys (1.0.1) Using SwiftyJSON (4.2.0) Generating Pods project Integrating client project Sending stats Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed. Xcodeでの作業 .xcworkspace という拡張子のファイルが生成されているので、それを開きます。Xcodeで、新しいヘッダーファイルを作成します。名前は任意ですが BridgeHeader.h などとします。 内容は次の通りです。 CloudgarageKeys.h というファイル名はそれぞれ変わりますが、PodsプロジェクトのDevelopment Pods/Keysの中にあるヘッダーファイルが対象です。 #ifndef BridgeHeader_h #define BridgeHeader_h #import "Keys/CloudgarageKeys.h" #endif /* BridgeHeader_h */ そして作成したXcodeプロジェクトのBuild SettingsにあるObjective-C Bridging Headerにて作成した BridgeHeader.h ファイルを指定します。例えば cloudgarage/BridgeHeader.h といった具合です。 Swiftによる開発 では準備ができましたので実際にコードを書いてみます。まず全体像です。HydraAsyncを使って非同期処理をasync/await化しています。 let baseUrl = "https://api.cloudgarage.jp" async({ _ -> Int in // トークンを取得 let token:String = try await(self.getToken(baseUrl: baseUrl)) // 公開鍵一覧を取得 let keyPairs = try await(self.getKeyPairs(baseUrl: baseUrl, token: token)) as! JSON // 公開鍵の詳細情報を取得 let keyPair = try await(self.getKeyPair(baseUrl: baseUrl, token: token, id: keyPairs[0]["id"].int ?? 0)) // デバッグ出力 print(keyPair) return 0 }).then({stats in print(stats) }) .catch {error in print("Error") print(error) } トークンの取得 まずトークンの取得です。CloudgarageKeysを使ってキーを取得しています。そしてPOSTリクエストを行った後、token.idがあるのかを確認してトークンを返します。 func getToken(baseUrl: String) -> Promise<String> { return Promise<String>(in: .background, {resolve, reject, _ -> Void in let keys = CloudgarageKeys.init() let url = "\(baseUrl)/tokens" let request = NSMutableURLRequest(url: URL(string: url)!) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") let params:[String:Any] = [ "client_id": keys.clientId, "client_secret": keys.clientSecret ] request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted) do { let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in if error != nil { reject(error ?? NSError(domain: "Request error", code: 1)) } else { let json = try? JSON(data: data!) if let token = json?["token"]["id"].string { resolve(token) } return reject(NSError(domain: "Parse error", code: 1)) } } task.resume() } catch let error as NSError { reject(error) } }) } 公開鍵の一覧を取得 続いて公開鍵の一覧を取得します。get処理を関数化し、一覧を取得する処理自体短くしています。トークンを取得していますので、それを X-Auth-Token ヘッダーに適用して実行します。 func getKeyPairs(baseUrl: String, token: String) -> Promise<Any> { return Promise<Any>(in: .background, {resolve, reject, _ -> Void in let url = "\(baseUrl)/keypairs" self.get(url: url, token: token) .then {json in if json["keypairs"].array != nil { return resolve(json["keypairs"]) } else { return reject(NSError(domain: "Parse error on getKeyPairs \(json)", code: 1)) } } .catch{error in return reject(error) } }) } // GET処理を関数化 func get(url: String, token: String) -> Promise<JSON> { return Promise<JSON>(in: .background, {resolve, reject, _ -> Void in let request = NSMutableURLRequest(url: URL(string: url)!) request.httpMethod = "GET" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue(token, forHTTPHeaderField: "X-Auth-Token") let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in if error != nil { reject(error ?? NSError(domain: "Request error", code: 1)) } else { let json = try? JSON(data: data!) return resolve(json!) } } task.resume() }) } 公開鍵の詳細を取得 取得した公開鍵のID(数値)を使って公開鍵詳細を取得します。ここは先ほどのget処理を使って行います。 func getKeyPair(baseUrl: String, token: String, id: Int) -> Promise<Any> { return Promise<Any>(in: .background, {resolve, reject, _ -> Void in let url = "\(baseUrl)/keypairs/\(id)" self.get(url: url, token: token) .then {json in if json["keypair"].dictionary != nil { resolve(json["keypair"]) } else { return reject(NSError(domain: "Parse error on getKeyPair \(json)", code: 1)) } } .catch{error in reject(error) } }) } 結果として以下のような公開鍵情報が得られます。 { "keypair_created_time" : "2018\/09\/03 13:44:29.684", "publicKey" : "ssh-rsa AAA...F+w== nakatsugawa@macpro.local", "name" : "macpro", "id" : 1217 } SwiftはiOSやmacOSアプリの開発はもちろん、サーバサイドでも利用できる言語となっています。静的型付けながら、スクリプト言語のような書き方ができるのが特徴です。ぜひiOSアプリからCloudGarage Public APIを呼び出してみてください! APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

ページトップへ