さくらがIINとPLMNを取得した話

さくらインターネットがIINとPLMNを取得した話

これはさくらインターネットAdvent Calendar 2017 20日目の記事です

まえがき

 IoTチームの川畑です。この度さくらインターネットは総務省より IIN(898104)PLMN(44006) の割り当てを受けました。これにより、キャリアに紐付かない独自の番号が入ったSIMカードを製造する事や、sakura.ioで展開している端末設備にユニークな識別番号を付与することが可能になりました。お気づきかと思いますが、この番号は主にモバイルネットワークで利用されます。

 今回割り当てを受けるにあたって、始終総務省との全ての交渉を担当する非常に貴重な経験をさせて頂きました。何せ探せど探せどどこにも情報がありませんし、通常は各キャリアの中の人がやる業務です。インターネット上で番号取得の実例が公開されるのは、もしかしたらこれが史上初かもしれません。

これらの番号取得の最たる例は、携帯電話事業者による取得・運用です。皆さんが普段利用している携帯電話と番号の関係、取得までの道のりをお届けしたいと思います。

IINとは

 IINとは、Issuer Indentify Numberの略で、ICカードの固有番号(ICCID)を発行する先頭最大7桁のプレフィックスです。世界中で利用するため、この番号はITU-T(国際電気通信連合)が管理をしており、電気通信事業用途で利用する場合は総務省を通して番号の申請を行う必要があります。

割り当てられた桁にはそれぞれ以下のような意味があります。
– 89 : 電気通信用途
– 81 : 国番号(日本)。最大3桁
– 04 : 事業者コード

SIMカードはもちろんのこと、クレジットカードなどのICチップにはICCIDが付与されます。弊社におけるICCIDの番号構成は以下の通りです。
– ①ICCIDの先頭6桁にIINを利用する
– ②残りの12桁は事業者が任意の番号を付与する
– ③最後の1桁はチェックディジット

PLMNとは

 PLMNとは、Public Land Mobile Networkの略で、携帯電話事業者の国際的な識別番号です。5桁で構成され、先頭3桁はMCC(Mobile Country Code)で国ごとに番号が変わり、日本には 440441 が割り当てられています。下2桁はMNC(Mobile Network Code)で、各国内の事業者コードですね。こちらも世界中で利用される一意の番号となるため、管轄は同じくITU-Tです。

 PLMNの用途は大きく2つあり、MNOが設置する携帯電話基地局の事業者識別に用いられることと、SIMカードにICCIDとは別に付与される、IMSI(International Mobile Subscriber Identity)のプレフィックスで利用されます。

PLMNの用途1:ビーコン

 各社の携帯電話基地局が自身のPLMNを電波(ビーコン)として報知することで、利用者の端末が契約された事業者へ自動的に接続するために利用されます。docomoですと44010、auだと44050/44051、SoftBankだと44020を基地局から報知しています。自動的に、と書きましたが手動で事業者を選択することも可能です。この図はiPhone7において周辺で報知されている事業者コードをサーチした時のスクリーンショットです。

PLMNの用途2:IMSI

 PLMNの2つ目の用途として、IMSI番号の生成で利用されます。IMSIは、モバイルネットワークにおける加入者の識別番号で、ネットワーク内でのアクセス制御のキーとしても利用されます。ICCIDはICカード固有の番号ですので変わることはありませんが、IMSIはOTA(Over The Air:遠隔でカード内の情報を書き換える技術)により書き換わる可能性があります。

 日本において、IMSIは総務省により 電気通信番号 として割り当てられます。皆さんよくご存知の電話番号も、電気通信番号の1つです(モバイルの世界ではMSISDNと呼ばれています)。IINもPLMNも申請自体は総務省に行うのですが、番号の管轄はITU-Tなので、番号割り当ての審査基準を満たせば裏で代理申請を行ってくれるという形になります。次の章では、実際の割り当てに係る手続きを見ていきましょう。

番号申請

 電気通信番号の管理は、総務本省の番号企画室が担当しています。(実は番号の申請を行おうにも全くアテが無い中、ふだん電気通信事業者の関係でお世話になっている担当官に紹介頂きました)

 ひとまず部内数名でお伺いし、概要をお伝えするところから始まりました。お渡しした資料を精査頂くのですが、不明点は逐一電話等で連絡が入ります。お伺いしてから約1~2週間で番号申請と審査に入りました。IINはITU-Tの規則に基づく審査、PLMNは電気通信番号規則に基づく審査ですので、それぞれ別々の申請用紙に記入を行います。

IIN

 ITUの基準に沿って総務省が代理審査を行います。通常IINは直接ITU申請なのですが、電気通信用途に限っては各国の省庁(日本は総務省)を通して申請を行う必要があります。申請書は以下の2枚です。

  • 1.ITU Registration Form
  • 2.IIN割り当て依頼文書

1の書式は公開文書ですので、こちらから参照して下さい。蛇足ですが、IINの申請にはITUへ手数料として80スイスフラン支払う必要があります。

2は総務省独自の文書ですが、内容はISOで定められたIIN割り当ての承認・拒否基準についての日本語回答です。基準は公開されており、こちらの4.3.1(承認基準)と4.3.2(拒絶基準)に回答します。

IINの申請は書類作成に約3週間、割り当てまで約2ヶ月かかりました。

PLMN

 電気通信番号規則に基づき、電気通信番号申請書への記入を行います。事項書の内容は以下の通りです。

  • 1.電気通信番号を必要とする理由
  • 2.必要とする電気通信番号の数及びその根拠となる需要の見込み
  • 3.必要とする電気通信番号の数に係る電気通信役務の提供の計画
  • 4.電気通信番号を管理する方法
  • 5.ネットワーク構成図
  • 6.別表第2に規定する要件を確認できる事項
  • 7.別表第3に規定する要件を確認できる事項
  • 8.その他電気通信番号の指定のために特に必要な事項

書式を見たい方は電気通信番号申請書で誰でも申請書を閲覧することが可能です。

補足:電気通信番号の概要と割り当てフローはこちらを参照。

ここからひたすらトライアンドエラーです。番号の申請内容に付随して、電気通信番号を利用する端末が、技術基準に適合している旨の証明、責任分界点の細かな設定・説明が必要です。このように、他の規則(端末設備等規則)や法令(電波法)に係る情報も求められます。
申請内容へのツッコミ・他の法令に係る確認等で、PLMN取得にまるまる3ヶ月要しました。

番号の割り当て

往訪から取得まで約3ヶ月の道のりでしたが、無事に番号を取得することができました。

最後に

番号の概要と、その取得の道のりについて書いてきました。興味のある人にとって、普段見られない事業者の裏側が垣間見れる記事は非常に新鮮でわくわくするものがあると思うのですが、いかがでしょうか。ITUによって取得内容は公示されますし、あえて隠す必要も無いので、せっかくですからIoTチーム活動の軌跡の1つとして書かせてもらいました。 また、自分自身が感じた 全く情報が無くて困った 事もあり、同じく番号取得をお考えの他の事業者の参考にもなれば良いなという気持ちです。

さくらインターネットは、今後はこの番号を活用し、更なるサービス価値の向上を目指します。

番号取得は、まだまだ序章に過ぎません。

(追記:PLMNとIINの取得にあたり、ITUより申請者の情報が公開されるのですが、まさかこのような形で自分の名前がインターネットに残るとは思ってもみませんでした。)

加筆・修正

2018/6/15 読者にご指摘を頂き、 IINの下二桁=MNC という誤った表現を削除しました。

Continue Reading

IchigoJam BASIC RPiでsakura.ioを使う

さくらインターネット Advent Calendar 2017の8日目の記事です。

こんにちは、こたまごです。

今日は、IchigoJam BASIC RPiの紹介と、sakura.ioと組み合わせてみて動いた報告をします。

IchigoJam

みなさま、IchigoJamはご存知でしょうか。
ご存知の通り、LPC1114で構成された、BASICでプログラミングができる教育用こどもパソコンです。

IcigoJam と sakura.io

IchigoJamでsakura.ioを接続するという利用方法は既に生みの親の福野さんから公開されています。

福野泰介の一日一創 – IchigoJamではじめるIoT sakura.io ハンズオン(データ発信編)

また、実環境でも利用されており、鯖江市のバスの運行状況もIchigoJamとsakura.ioで収集され、オープンデータとして公開されていたりします。

sakura.io x IchigoJam BASIC = かんたんIoT 〜鯖江市のバスで稼働する公共交通IoT〜

 

IchigoJam BASIC RPi

そのIchigoJamがそのままRaspberry Piでも動作する、という「IchigoJam BASIC RPi」が10月に公開されています。

モニタとキーボードを繋ぐだけでプログラミングができるという利便性をそのままにRaspberry Piでプログラミングができます。実環境ではワンチップマイコンのIchigoJamがおすすめですが、HDMIも使えて、USBキーボードも使えるので、試したい時にはおすすめです。

IchigoJam BASIC RPi と sakura.io

先日、さくらインターネットはsakura.ioとRaspberry Piを簡単に接続できるsakura.io HAT for Raspberry Piを発売しました。

sakura.io HAT for Raspberry Pi

 

Raspberry Pi HAT と IchigoJam BASIC RPiがあるということは試すしかないですよね!

ということで、やってみました。

シールドにsakura.ioモジュールを載せて、Raspberry Piに載っけるだけです。

sakura.io HAT

IchigoJam BASIC RPiのインストールはSDカードにダウンロードしたファイルをコピーするだけです。

起動したら先ほどの福野さんの記事を参考に、以下のように入力しました。

1 'sakura.io Test
20 POKE#800,#21,10,1,76,N,N>>8,0,0,0,0,0,0,N>>8^N^102
30 ?I2CR(79,#800,13,#820,3)

このプログラムでは、変数Nに入っている整数をチャンネル1としてsakura.ioに送信するというプログラムです。

その上で、以下のように入力すると送信されます。

N=10
RUN

sakura.ioのWebSocket画面でみてみると、ちゃんと届いていることがわかります。

全く同じコードでワンチップマイコンとRaspberry Piと動くのは便利ですね!

Linuxで使う場合には

Raspberry PiだからLinuxで使いたい、という方のために、Pythonのライブラリ(python-sakuraio)も公開しています。

sudo apt-get install python3-smbus
sudo pip3 install sakuraio

でインストールできるので、こちらもぜひご利用ください。

Continue Reading

babelプラグインの作り方・活用方法

さくらインターネット Advent Calendar 2017の13日目の記事です。

さくらインターネットでは、sakura.ioのコントロールパネルを始めとした、様々な管理画面が存在しています。状況に合わせた最適解を選んでいるので、様々な設計やフレームワークの利用などが行われています。その中で、最近社内でもよく使われるようになった babel について、掘り下げて調べてみました。

この記事はbabel7を参照しています。記事を書いている時点では、betaなので正式リリースの際には変更される点が有るかもしれません。

目次

  • babelの簡単なおさらい
    • パッケージ構成
    • 処理のフローの理解
  • babelプラグインの作成
    • 簡単なプラグインを作成
    • テストを実行
  • babelプラグインを使ってコード自動生成を行う
    • s2sの紹介

パッケージ構成

Babelは、JavaScriptで書かれたJavaScriptのコンパイラーです。
非常にコード量の多いプロダクトになっており、以下のようにたくさんの小さいパッケージで構成されています。

インタフェース

  • @babel/core: .babelrc 等の設定を読み込み、ソースコードに対してプラグインの適用を順次行う
  • @babel/polyfill: ブラウザなどのランタイムにて、 core-js regenerator による標準ライブラリ等の補完を行う
  • @babel/register: require をフックし、コンパイルされたファイルを返す
  • @babel/cli: コマンドラインからコンパイルするためのコマンド

@babel/plugin-*

  • Transform Plugins
    • コード→コード (AST→AST) の変換を行う
    • ex: @babel/plugin-transform-arrow-functions
  • Syntax Plugins
    • babylon内に実装された、構文解析に使用するプラグインを設定するパッケージ
    • 現時点で構文解析を拡張することは出来ない
    • ex: @babel/plugin-syntax-jsx

※AST: コンパイラが扱う構文木 Abstract Syntax Tree

@babel/preset-*

各種構文をサポートするためのプラグインを一括適用するパッケージです。
1つのパッケージを適用するだけで、複数のパッケージが導入されます。

  • @babel/preset-es2015
    • @babel/plugin-transform-arrow-functions: () => {}function () {}
    • @babel/plugin-transform-spread: [...a, 'foo'];[].concat(a, [ 'foo' ]);
    • etc…
  • @babel/preset-react
    • @babel/plugin-syntax-jsx: <JSX /> のようなコードをパースして、Babelが扱えるようにする
    • @babel/plugin-transform-react-jsx: <span>hoge</span>React.createElement('span', null, 'hoge')
  • @babel/preset-env: ターゲットブラウザ・ランタイムに対応したコードを生成するためのプラグインを自動選択

内部パッケージ

今まで紹介を行ったパッケージの内部で呼ばれるものです。
プラグインを自作する際にも使用します。

  • @babel/babylon
    • 構文解析を行う
    • デフォルトでES2017構文が有効
    • JSX, Flow, Typescriptにも対応
  • @babel/types
    • ASTのジェネレーター・バリデーター
    • プラグインなどでASTを組み立てる時に使う
  • @babel/template
    • ASTのテンプレートを作成可能
    • 文字列で書いたコード内のプレスホルダにASTを差し込める
  • @babel/traverse
    • ASTを辿り、ノードの置換・追加・削除を行う
  • @babel/generator
    • ASTをコードに変換する
  • @babel/code-frame
    • エラーをソースの場所とともに表示する

いままでのあらすじ

ここまでで紹介したパッケージの流れをざっくり図にすると、このようになっています。

ちなみに現時点でまだbetaですが、babel 7は以下のような変更が行われています。

  • Scoped Package化 babel-core@babel/core
  • TypeScriptの標準対応が入る
  • flowで書き直しているっぽい
  • 新しい構文への対応も一緒に追加される予定
    • Optional Chaining: a?.b = 42;
    • BigInt: 50000n + 60n;

Babelプラグインを作る

ここではBabelのTransform Pluginsを作成しようと思います。
処理としては、babylonで解析されたASTを編集し返すみです。
babelプラグインを作るための手順は以下のとおりです。

  1. IN/OUTの形式をコードを定義する
  2. IN/OUTのASTを読む
  3. ASTを読み込んで、OUTの形式のASTを構築するコードを書く

順に追って説明します。

今回紹介する内容は、 https://github.com/kamijin-fanta/babel-example-2017 でコードを公開しています。

IN/OUTの形式をコードを定義する

ここでは、 hoge という識別子を fuga に置き換えるプラグインを作ります。
期待されるコードは以下のとおりです。

IN:

console.log(hoge)

OUT:

console.log(fuga)

ASTを読む

上で定義したASTをそれぞれ読んでみましょう。
ASTを読むには https://astexplorer.net/ が便利です。
ここでは、言語にJavaScriptを選択し、パーサーにbabylon7を選択します。

IN側のコードを入力しました。
console.log(hoge)CallExpression として認識され、呼び出す関数は callee 配列は arguments として格納されています。

callee 側の console.log は、 MemberExpression として定義されます。 object に格納された Identifierproperty に格納された Identifier でコードを表しています。

引数である (hoge)arguments 配列の中に Identifier として定義されています。

プラグインを書く

まず、何もしない最小のプラグインを作ってみます。

$ npm i @babel/core @babel/babel-cli
$ mkdir src
$ touch src/index.js
$ cat '{ "plugins": ["./index.js"] }' > .babelrc

index.jsを編集し、以下の内容にします。

// index.js
module.exports = function({ types: t }) {
  return {
    name: 'babel-example-plugin',
    visitor: {
      Identifier(path) {
        console.log('path: ', path.node)
      }
    }
  };
};

babelを実行し、標準出力に出力される結果を読んでみましょう。

$ node_modules/.bin/babel input.js
path:  Node {
  type: 'Identifier',
  start: 0,
  end: 7,
  loc: ~~~略~~~,
  name: 'console' }
path:  Node {
  type: 'Identifier',
  start: 8,
  end: 11,
  loc: ~~~略~~~,
  name: 'log' }
path:  Node {
  type: 'Identifier',
  start: 12,
  end: 16,
  loc: ~~~略~~~,
  name: 'hoge' }

プラグインで定義している visitor オブジェクトに対して、ノードのTypeに対してのマッチングを書いていきます。再帰的に探索を行い、マッチしたvisitorを呼び出します。Type名のメソッドを定義すると、親ノード・自ノードの情報等が含まれるパスが引数に渡されます。

上の例では、 console log hoge という3つのIdentifierがマッチしました。

次に、ノードの一部を書き換えてみましょう。
path オブジェクトの node プロパティが、現在のASTを表しています。下の例では、Identifierタイプでマッチしたノードのパスがpath引数に渡されます。Identifierは、属性としてnameを持ちます。その属性を書き換えてみましょう。

// index.js
module.exports = function({ types: t }) {
  return {
    name: 'babel-example-plugin',
    visitor: {
      Identifier(path) {
        if (path.node.name === 'hoge') {
          path.node.name = 'fuga';
        }
      }
    }
  };
};

このコードの出力結果はこうなります。

console.log(fuga);

テストを行う

テストは、 jestbabel-plugin-tester を使うのが使いやすそうなので、試してみます。

単純なテスト

先程はCLIから簡単にプラグインを扱うため、 .babelrc に設定しましたが、babel-plugin-testerを使うことで不要になるので、一緒に設定を書き換えます。

$ npm i jset babel-jest babel-plugin-tester @babel/preset-env
// .babelrc
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "6.10"
      }
    }]
  ]
}

次にテストコードを書きます。codeが入力コードで、outputが出力コードです。

// src/index.test.js

import plugin from './index';
import pluginTester from 'babel-plugin-tester';

pluginTester({
  plugin,
  tests: [
    {
      title: 'example',
      code: `console.log(hoge);`,
      output: `console.log(fuga);`,
    },
  ],
});
$ node_modules/.bin/jest

 PASS  src\index.test.js
  babel-example-plugin
    √ example (6ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.603s, estimated 1s
Ran all test suites related to changed files.

スナップショットテスト

jestには、入出力の値の変化をテストするためのスナップショットテストの機能が有ります。 https://facebook.github.io/jest/docs/en/snapshot-testing.html

babel-plugin-testerはjestのスナップショットテストに対応しているため、非常に簡単にこの機能を使うことが出来ます。テストコードを書き換えて試します。 snapshot: true を設定し、outputを指定しないのがポイントです。

// src/index.test.js

import plugin from './index';
import pluginTester from 'babel-plugin-tester';

pluginTester({
  plugin,
  snapshot: true,
  tests: [
    {
      title: 'snapshot test',
      code: `console.log(hoge);`,
    },
  ],
});

テストを動かすと、 __snapshots__/index.test.js.snap ファイルが生成されます。次回このファイルと異なる値が出力された際は、エラーとなります。

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`snapshot test 1`] = `
"
console.log(hoge);

      ↓ ↓ ↓ ↓ ↓ ↓

console.log(fuga);
"
`;

こうして、スナップショットをとっておくことで、プラグインの変更を手軽に検知できるようになります。

s2sの紹介

Babalプラグインを作ることで、Babelの機能などが理解できたかと思います。基本的に行っていることがコード→コードということがよく理解できたかなと思います。そのコードからコードを生成するBabelPluginの性質に着目したのが、s2sです。

https://github.com/akameco/s2s

s2sと適切なBabelPluginを組み合わせると、Redux等で大量に必要となるボイラープレートの削減を行うことができます。

基本的な動作は、このような流れです。エディタでファイルを保存すると、即時にコードが自動生成され、追記されたように見えます。

  1. ファイルが保存されたタイミングでハンドラ(babel-plugin)が起動
  2. babel-pluginはASTを受け取り、編集を行って返す
  3. 結果の文字列でファイルを上書きする

例えば、FlowでのReduxアプリケーションで使用する babel-plugin-s2s-action-types は、以下のような変換を行います。

In:

export type Action = Increment

Out:

// @flow
export const INCREMENT: "app/counter/INCREMENT" = "app/counter/INCREMENT";

export const Actions = {
  INCREMENT
};

export type Increment = {
  type: typeof INCREMENT
};

export type Action = Increment;

タイプ数が半分以下になっている事がお分かりいただけると思います。ただ、内部でやっていることは基本的に、ファイルのwatch・BabelPluginを使用したtransform・ファイルの書き込みの3点です。なので、ユーザが自由に拡張することが出来ます。

私も、babylon7がTypeScriptに対応していたので、上のプラグインのTS版のプラグインを作ってみました。非常に簡単に実装を行うことが出来ました。

https://github.com/kamijin-fanta/babel-plugins/tree/master/packages/babel-plugin-s2s-action-types-ts

まとめ

  • babel怖くない
    • babelのプラグインはASTを理解すると作れる
  • AST怖くない
    • astexplorer等、ASTの理解を助けるツールが存在する

冬休みはカスタムのBabelPluginを作ってみてはいかがでしょうか。

資料

  • https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md
    • もう少し掘り下げてプラグインを作る方法がかかれている
  • https://github.com/kamijin-fanta/babel-example-2017
    • 今回のサンプルプログラムを置いたリポジトリ
Continue Reading

fluent-plugin-sakuraio をリリースしました

sakuraio_to_fluentd

fluent-plugin-sakuraioをリリースしました。

fluent-plugin-sakuraiosakura.ioのWebSocket APIからデータを受け取るためのFluentdのInput Pluginです。

Fluentdfluent-plugin-sakuraioを使うことで、連携サービスで対応していない、S3などのデータストアや他サービスへのデータ送信、データ送信前のデータの前処理を簡単に行うことができるようになります。

この記事では、基本的な使い方とrecord_transformerプラグインを使ったデータの意味付けの手順をご紹介します。

Continue Reading

APIで使用できるドメインを追加しました

こんにちは。開発チームのt-kamijoです。
表題の通りプラットフォームを改善しましたのでお知らせします。

変更概要

  • sakura.io のドメインのエイリアスとして sakuraio.jp を導入した
    • APIを呼び出す際は、 api.sakura.io の代わりに api.sakuraio.jp を使用できる

詳細

先日2017年9月21日にgTLDである .io への名前解決が一部失敗する障害が発生しました。弊社設備の問題ではなく、ioドメインのルートネームサーバーが原因とされています。この障害は、国内外でも広く話題になっていました。

このためsakura.ioへも一部影響が有り、プラットフォームへの新規接続を行う際に失敗するケースが有りました。限定的な障害ではございますが、ご迷惑おかけして申し訳ありませんでした。

今回の障害を受け、sakura.ioでは別TLDを併用することを決定しました。変更概要に有りますように、今後はAPIの呼び出しに api.sakura.io api.sakuraio.jp の両方のドメインを使用していただけます。

.jpドメイン、.ioドメインどちらも名前解決できない障害は起こりうる可能性があります。
弊社での本対応とともに、お客様側のシステムでも片側のドメインの名前解決に失敗した場合、
もう片方のドメインでも解決を試みるように実装していただくことで、よりシステム停止の可能性をさげられることになります。

今後もsakura.ioをよろしくお願いします。

Continue Reading
Close Menu