11package common
22
33import (
4+ "bytes"
45 "encoding/base64"
56 "encoding/json"
67 "fmt"
@@ -22,17 +23,24 @@ type SimAPIResponse struct {
2223 Count int `json:"Count"`
2324}
2425
25- // GetUsedIPAddressesInMGW
26- // MGW 内での利用されている IP アドレス一覧を取得する
27- // 利用されている IPアドレス一覧を取得
28- func GetUsedIPAddressesInMGW (accessToken string , accessTokenSecret string , zone string , mgwID string ) (map [string ]struct {}, error ) {
29- // ベーシック認証
30- auth := fmt .Sprintf ("%s:%s" , accessToken , accessTokenSecret )
26+ // BASIC認証のAuthorizationヘッダが設定されたhttp.Header{}インスタンスを作成
27+ func createHeadersWithBasicAuth (user string , password string ) http.Header {
28+ auth := fmt .Sprintf ("%s:%s" , user , password )
3129 encodedAuth := base64 .StdEncoding .EncodeToString ([]byte (auth ))
3230 headers := http.Header {
3331 "Authorization" : []string {"Basic " + encodedAuth },
3432 }
3533
34+ return headers
35+ }
36+
37+ // GetUsedIPAddressesInMGW
38+ // MGW 内での利用されている IP アドレス一覧を取得する
39+ // 利用されている IPアドレス一覧を取得
40+ func GetUsedIPAddressesInMGW (accessToken string , accessTokenSecret string , zone string , mgwID string ) (map [string ]struct {}, error ) {
41+ // BASIC認証
42+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
43+
3644 // モバイルゲートウェイ配下のSIMを全件取得するための URL の組み立て
3745 baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/%s/api/cloud/1.1/appliance/%s/mobilegateway/sims" , zone , mgwID )
3846 queryParams := url.Values {}
@@ -152,3 +160,278 @@ func incrementIP(ip net.IP) {
152160 }
153161 }
154162}
163+
164+ type SimRegisterInfo struct {
165+ ICCID string
166+ PassCode string
167+ }
168+
169+ // SIM作成APIのレスポンス
170+ type SimCreateAPIResponse struct {
171+ CommonServiceItem struct {
172+ ID string `json:"ID"`
173+ }
174+ Success bool `json:"Success"`
175+ IsOK bool `json:"is_ok"`
176+ }
177+
178+ // APIのis_okレスポンス
179+ type SimApiIsOkResponse struct {
180+ IsOK bool `json:"is_ok"`
181+ }
182+
183+ // APIのis_fatalレスポンス
184+ type SimApiIsFatalResponse struct {
185+ IsFatal bool `json:"is_fatal"`
186+ Serial string `json:"serial"`
187+ Status string `json:"status"`
188+ ErrorCode string `json:"error_code"`
189+ ErrorMsg string `json:"error_msg"`
190+ }
191+
192+ // SIMの作成
193+ func createSim (accessToken string , accessTokenSecret string , simID string , simPasscode string ) (string , error ) {
194+ // BASIC認証
195+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
196+
197+ // SIM作成リクエストの組み立て
198+ baseURL := "https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/commonserviceitem"
199+ body := fmt .Sprintf (`
200+ {
201+ "CommonServiceItem": {
202+ "Name": "%s",
203+ "Status": {
204+ "ICCID": "%s"
205+ },
206+ "Remark": {
207+ "PassCode": "%s"
208+ },
209+ "Provider": {
210+ "Class": "sim"
211+ }
212+ }
213+ }` , simID , simID , simPasscode )
214+ bytesBody := []byte (body )
215+ bufBody := bytes .NewBuffer (bytesBody )
216+
217+ // リクエスト送信
218+ req , err := http .NewRequest ("POST" , baseURL , bufBody )
219+ if err != nil {
220+ return "" , fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
221+ }
222+ req .Header = headers
223+
224+ client := & http.Client {}
225+ resp , err := client .Do (req )
226+ if err != nil {
227+ return "" , fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
228+ }
229+ defer resp .Body .Close ()
230+
231+ // レスポンスの確認
232+ respBody , err := io .ReadAll (resp .Body )
233+ if err != nil {
234+ return "" , fmt .Errorf ("SIM作成のレスポンスの読み込みに失敗しました...%s" , err .Error ())
235+ }
236+ if resp .StatusCode != http .StatusCreated {
237+ // 認証情報の間違い
238+ if resp .StatusCode == http .StatusUnauthorized {
239+ return "" , fmt .Errorf ("アクセストークン、アクセストークンシークレットを確認してください。SIM作成に失敗しました" )
240+ }
241+
242+ // 作成済み
243+ if resp .StatusCode == http .StatusConflict {
244+ // エラーにしないけどリソースIDは空
245+ return "" , nil
246+ }
247+
248+ // 認証エラーじゃない場合
249+ var apiFatalRes SimApiIsFatalResponse
250+ err = json .Unmarshal (respBody , & apiFatalRes )
251+ if err != nil {
252+ return "" , fmt .Errorf ("SIM作成のレスポンスのパースに失敗しました...%s" , err .Error ())
253+ }
254+ // レスポンスに含まれているエラーメッセージを返す
255+ return "" , fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
256+ }
257+
258+ var apiResponse SimCreateAPIResponse
259+ err = json .Unmarshal (respBody , & apiResponse )
260+ if err != nil {
261+ return "" , fmt .Errorf ("SIM作成のレスポンスのパースに失敗しました...%s" , err .Error ())
262+ }
263+
264+ // SIMのリソースIDを返す
265+ return apiResponse .CommonServiceItem .ID , nil
266+ }
267+
268+ // SIMのIPアドレス設定
269+ func assignIPAddressToSim (accessToken string , accessTokenSecret string , simID string , ipAddress string ) error {
270+ // BASIC認証
271+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
272+
273+ // 『SIMのIPアドレス指定』のリクエストの組み立て
274+ baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/commonserviceitem/%s/sim/ip" , simID )
275+ body := fmt .Sprintf (`{
276+ "sim": {
277+ "ip": "%s"
278+ }}` , ipAddress )
279+ bytesBody := []byte (body )
280+ bufBody := bytes .NewBuffer (bytesBody )
281+
282+ // リクエスト送信
283+ req , err := http .NewRequest ("PUT" , baseURL , bufBody )
284+ if err != nil {
285+ return fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
286+ }
287+ req .Header = headers
288+
289+ client := & http.Client {}
290+ resp , err := client .Do (req )
291+ if err != nil {
292+ return fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
293+ }
294+ defer resp .Body .Close ()
295+
296+ // レスポンスの確認
297+ respBody , err := io .ReadAll (resp .Body )
298+ if err != nil {
299+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスの読み込みに失敗しました...%s" , err .Error ())
300+ }
301+ if resp .StatusCode != http .StatusOK {
302+ // 認証情報の間違い
303+ if resp .StatusCode == http .StatusUnauthorized {
304+ return fmt .Errorf ("アクセストークン、アクセストークンシークレットを確認してください。SIMのIPアドレス設定に失敗しました" )
305+ }
306+ // 認証エラーじゃない場合
307+ var apiFatalRes SimApiIsFatalResponse
308+ err = json .Unmarshal (respBody , & apiFatalRes )
309+ if err != nil {
310+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスのパースに失敗しました...%s" , err .Error ())
311+ }
312+ // レスポンスに含まれているエラーメッセージを返す
313+ return fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
314+ }
315+
316+ // 設定の成否を返す
317+ var apiOkRes SimApiIsOkResponse
318+ err = json .Unmarshal (respBody , & apiOkRes )
319+ if err != nil {
320+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスのパースに失敗しました...%s" , err .Error ())
321+ }
322+
323+ if ! apiOkRes .IsOK {
324+ return fmt .Errorf ("SIMのIPアドレス設定が失敗しました" )
325+ }
326+
327+ return nil
328+ }
329+
330+ // モバイルゲートウェイにSIMを登録
331+ func assignSimToMgw (accessToken string , accessTokenSecret string , zone string , mgwID string , simID string ) error {
332+ // BASIC認証
333+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
334+
335+ // 『モバイルゲートウェイにSIMを登録』のリクエストの組み立て
336+ baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/%s/api/cloud/1.1/appliance/%s/mobilegateway/sims" , zone , mgwID )
337+ body := fmt .Sprintf (`{
338+ "sim": {
339+ "resource_id": "%s"
340+ }}` , simID )
341+ bytesBody := []byte (body )
342+ bufBody := bytes .NewBuffer (bytesBody )
343+
344+ // リクエスト送信
345+ req , err := http .NewRequest ("POST" , baseURL , bufBody )
346+ if err != nil {
347+ return fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
348+ }
349+ req .Header = headers
350+
351+ client := & http.Client {}
352+ resp , err := client .Do (req )
353+ if err != nil {
354+ return fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
355+ }
356+ defer resp .Body .Close ()
357+
358+ // レスポンスの確認
359+ respBody , err := io .ReadAll (resp .Body )
360+ if err != nil {
361+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスの読み込みに失敗しました...%s" , err .Error ())
362+ }
363+
364+ if resp .StatusCode != http .StatusOK {
365+ // 認証情報の間違い
366+ if resp .StatusCode == http .StatusUnauthorized {
367+ return fmt .Errorf ("認証に失敗しました...%s" , err .Error ())
368+ }
369+ // 認証エラーじゃない場合
370+ var apiFatalRes SimApiIsFatalResponse
371+ err = json .Unmarshal (respBody , & apiFatalRes )
372+ if err != nil {
373+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスのパースに失敗しました...%s" , err .Error ())
374+ }
375+ // レスポンスに含まれているエラーメッセージを返す
376+ return fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
377+ }
378+
379+ // 設定の成否を返す
380+ var apiOkRes SimApiIsOkResponse
381+ err = json .Unmarshal (respBody , & apiOkRes )
382+ if err != nil {
383+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスのパースに失敗しました...%s" , err .Error ())
384+ }
385+
386+ if ! apiOkRes .IsOK {
387+ return fmt .Errorf ("SIMのIPアドレス設定が失敗しました" )
388+ }
389+
390+ return nil
391+ }
392+
393+ // リスト内のSIMを登録する
394+ func RegisterSimFromList (accessToken string , accessTokenSecret string , zone string , mgwID string , simList []SimRegisterInfo , ipList []string ) error {
395+
396+ if len (simList ) > len (ipList ) {
397+ return fmt .Errorf ("登録対象のSIM %d 枚に対して割り当て可能なIPアドレスが %d 個しかありません" , len (simList ), len (ipList ))
398+ }
399+
400+ ipListIndex := 0
401+ for _ , sim := range simList {
402+ // SIMを作成
403+ fmt .Printf ("SIM登録(ICCID: %s)" , sim .ICCID )
404+ simResourceId , err := createSim (accessToken , accessTokenSecret , sim .ICCID , sim .PassCode )
405+ if err != nil {
406+ fmt .Printf ("[FAILED]\n " )
407+ return err
408+ }
409+ if simResourceId == "" {
410+ //登録済みだからスキップ
411+ fmt .Printf ("[SKIP]\n " )
412+ continue
413+ }
414+ fmt .Printf ("[OK]" )
415+
416+ // MGWにSIMを登録
417+ fmt .Printf (", モバイルゲートウェイに追加" )
418+ err = assignSimToMgw (accessToken , accessTokenSecret , zone , mgwID , simResourceId )
419+ if err != nil {
420+ fmt .Printf ("[FAILED]\n " )
421+ return err
422+ }
423+ fmt .Printf ("[OK]" )
424+
425+ // SIMにIPアドレスを設定
426+ fmt .Printf (", IPアドレスを設定(%s)" , ipList [ipListIndex ])
427+ err = assignIPAddressToSim (accessToken , accessTokenSecret , simResourceId , ipList [ipListIndex ])
428+ if err != nil {
429+ fmt .Printf ("[FAILED]\n " )
430+ return err
431+ }
432+ fmt .Printf ("[OK]\n " )
433+
434+ ipListIndex ++
435+ }
436+ return nil
437+ }
0 commit comments