つぶやきテック

日々のつぶやきアウトプット

つぶやきSSO【ユーザ認証】

SSOとは

  • Single Sign-On の略で、一度ユーザ認証をするだけで関連するサーバへのアクセスについても認証する技術です。
  • ユーザの利便性の向上が期待できます。

SSOの実装方式

Cookie型

  • 認証情報を含めたCookie情報を使ってSSOを行います。

リバースプロキシ型

  • リバースプロキシにアクセスを集約します。
  • リバースプロキシで認証に成功すると、プロキシはサーバに代理アクセスし、結果をユーザに返します。

SAML(Security Assertion Markup Language)型

  • 認証情報に加え、属性情報とアクセス制御情報を異なるドメインに伝達します。
  • 同一ドメインに留まらない大規模なサイトにおいてもSSOの仕組みを導入できます。

SAMLコードの例

こちらからお借りしました。

 1: <saml:Assertion
 2:   xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
 3:   Version="2.0" IssueInstant="2005-01-31T12:00:00Z">

 4:   <saml:Issuer Format=urn:oasis:names:SAML:2.0:nameid-format:entity> ... Nature of the assertion.
 5:     http://idp.example.org
 6:   </saml:Issuer>

 7:   <saml:Subject> ... Subject of the assertion.
 8:     <saml:NameID
 9:       Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
10:       j.doe@example.com
11:     </saml:NameID>
12:   </saml:Subject>

13:   <saml:Conditions ... Additional conditions of period.
14:     NotBefore="2005-01-31T12:00:00Z"
15:     NotOnOrAfter="2005-01-31T12:10:00Z">
16:   </saml:Conditions>

17:   <saml:AuthnStatement ... Authentication statement
18:     AuthnInstant="2005-01-31T12:00:00Z" SessionIndex="67775277772">

19:     <saml:AuthnContext>
20:       <saml:AuthnContextClassRef>
21:         urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
22:       </saml:AuthnContextClassRef>
23:     </saml:AuthnContext>

24:   </saml:AuthnStatement>
25: </saml:Assertion>

つぶやきCookie

属性:Cookieとは?

  • WebブラウザとWebサーバとの間で、セッション管理を行うための情報です
  • 1994年にネットスケープコミュニケーションズ社によって提案されました

機能:Cookieは何をする?

  • ステートレス(それぞれの通信の内容をいちいち持っておかない)なプロトコルであるHTTPの上で、前回通信した状態を保持し、次のセッションに引き継ぎます
  • Webサーバは、Cookieの情報によってどのブラウザからのアクセスか識別できるようになります

要素:Cookieを支える概念・技術

Set-Cookieフィールド

  • サーバからのHTTPレスポンスヘッダ中のフィールドです
  • ブラウザを識別するためのセッションIDなどを記述します

例:

Set-Cookie: Session_id=xxx, Expires=yyy, Domain=aaa.com, Path=bbb

Cookieフィールド

  • サーバへのHTTPリクエストヘッダ中のフィールドです
  • Set-Cookieフィールドの情報を記述して返します

Secure属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • 記述されていると、HTTPS通信の場合のみCookie情報をブラウザからサーバへ送信します

Domain属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieを送信するドメインを指定します。ここで指定したドメインのサブドメインも送信範囲に含まれます

Path属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieを送信するURLディレクトリを指定します

Expires属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieの有効期限を指定します。未指定のとき、有効期限はブラウザ終了時までです

HttpOnly属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookie情報をJavaScriptコードが利用することを禁止します

つぶやきOSPF

OSPF(Open Shortest Path First)

  • LSA(Link State Advertisement)という情報をもとに、ルーティング情報を作成していくプロトコルです。
  • ネットワークに接続されたリンクをコストに換算し、そのコストが最小になるようにルーティングテーブルを作成していきます。
  • このルーティングアルゴリズムはリンクステートアルゴリズムと呼ばれます。

ルーティングテーブルの例*1

Router#show ip ospf route
============ OSPF network routing table ============
N     10.1.1.0/24         [10] area: 0.0.0.1
                          directly attached to port-channel0
N     20.1.1.0/24         [20] area: 0.0.0.1
                          via 10.1.1.2, port-channel0
N     30.1.1.0/24         [20] area: 0.0.0.1
                          via 10.1.1.2, port-channel0
N IA  40.1.1.0/24         [10] area: 0.0.0.1
                          via 10.1.1.3, port-channel0
N IA  40.1.2.0/24         [10] area: 0.0.0.1
                          via 10.1.1.3, port-channel0

============ OSPF router  routing table =============
R    192.168.30.4         [10] area: 0.0.0.1, ABR, ASBR
                          via 10.1.1.3, port-channel0

============ OSPF external routing table ===========
N E1  50.1.1.0/24         [20] tag: 0
                          via 10.1.1.3, port-channel0

DR, BDR

  • OSPFを適用するネットワークでは、そのセグメントの中で最も高いプライオリティ値をもつルータがDR(Designated Router: 指名ルータ、代表ルータ)として選出されます。
  • 次に高いプライオリティ値をもつルータはBDR(Backup DR)となります。
  • ネットワーク内の各ルータは、代表ルータに対してルータLSAを送信し、代表ルータはそれをもとにネットワーク全体の情報(ネットワークLSA)を作成します。

エリア

  • OSPFにおいて、LSAを交換する範囲をエリアと呼びます。
  • エリア0はとくにバックボーンエリアと呼ばれます。

5種類のパケット*2

タイプ1:Hello

  • ネイバー(論理的に隣接したルータ)を検出するためのパケットです。
  • ネイバー検出後、キープアライブ(生存確認)にも使われます。
  • マルチキャストで送信されます(224.0.0.5)*3
  • このHelloパケットを出さないように設定された機器はパッシブインターフェースと呼ばれます。

タイプ2:DBD

  • 自身のLSDB(Link State DataBase)に含まれているLSAのリスト一覧が載っています。
  • ネイバーとこのパケットを交換することで、自身のLSDBに不足しているLSAを認識します。

タイプ3:LSR

  • 自身のLSDBに不足があった場合、ネイバーにそのLSAを要求するために使用されます。

タイプ4:LSU

  • LSRによりネイバーから要求されたLSAを送信するために使用されます。

タイプ5:LSAck

  • LSUを受信したことを通知する確認応答として利用されます。

5種類のLSA

エリア内部のみに伝播するLSA

Router-LSA

  • そのルータがどのネットワークに接続されているかを表します。
  • IPアドレス、リンクの種類、ルータID、コストなどが含まれます。

Network-LSA

  • そのネットワークにはどのルータが接続されているかを表します。
  • 同一リンク内にあるルータの内DR(代表ルータ)が生成します。

ASBR-Summary-LSA

  • AS境界ルータのIDとそこに到達するためのコスト情報を表します。
  • ABR(エリア境界ルータ)が作成します。

エリア内部とバックボーンエリアに伝播するLSA

Network-Summary-LSA

  • 他のエリアの情報を要約したものです。
  • ABR(エリア境界ルータ)が作成します。

OSPFドメイン全体に伝播するLSA

AS-External-LSA

  • ASの外側にあるネットワーク情報を表します。
  • ASBR(AS境界ルータ)が作成します。

*1:https://www.furukawa.co.jp/fitelnet/f/man/60/command-show/show/show_ip_ospf_route.htm

*2:https://www.infraexpert.com/study/ospfz5.html

*3:過去のネスペ試験で、「OSPFはマルチキャスト通信だからIPsecでカプセル化できないよ。GRE over IPsecを使おうね」という問題が出てました^^

つぶやきBGP

BGP (Border Gateway Protocol)

  • AS(1つまたは複数のISPで構成されるネットワーク)間のルーティングを担うプロトコルです。
  • ASから他のASへ至る経路のうち、経由するASのパスの数が最小となるようなルートを選択するパスベクタ方式を用いています。
  • 静的な経路制御と比べて、自動で回線断や機器障害を検知し、トラフィックを迂回できるという利点があります。

BGPメッセージ5種類*1

OPEN

BGPセッション開始時に交換されるメッセージ。自AS番号、ルータID、BGPversionなどの情報を含みます。

UPDATE

BGPの経路情報の交換に使用されるメッセージ。経路の追加や削除が発生した場合に送信されます。

NOTIFICATION

BGPセッションの切断やエラーを検知した場合に送信されるメッセージです。

KEEPALIVE

生存確認を行うときに交換されるメッセージ。通常、BGPルータの間で30秒間隔でやりとりし、相手側から90秒以上このメッセージを受信しない場合は、回線もしくは機器の故障と判断して経路情報を変更します。

ROUTE-REFRESH

相手ルータに対しすべての経路情報を要求するメッセージです。

つぶやきVoIP

VoIP

  • インターネットなどのIPネットワークを利用して通信しようとする技術です。
  • より細かくみると、電話交換で行われてきた呼制御と、音声をIPパケット化する技術で成り立っています

SIP (Session Initiation Protocol)

  • マイクロソフト社が開発した、呼制御に用いられるプロトコルです。
  • アプリケーションプロトコルの1つであり、HTTPと同じように、リクエスト・レスポンスというメッセージをやりとりすることで呼制御を行います。

SIPメッセージ

  • REGISTER:電話機の位置情報登録~>DNSのAレコードを登録するみたいな感じ
  • INVITE:端末を通話へ招待
  • ACK:確認応答
  • BYE:呼の解放

INVITEメッセージの実例は下のような感じです*1

INVITE sip:bob@tokyo.com SIP/2.0
------------------------------ヘッダここから--------------------------------------------
Via: SIP/2.0/UDP pc33.sapporo.com;branch=z9hG4bKnashds8 //リクエストが辿ったパス
Max-Forwards: 70
To: Bob <sip:bob@tokyo.com>
From: Alice <sip:alice@sapporo.com>;tag=1928301774
Call-ID: a84b4c76e66710@pc33.sapporo.com
CSeq: 314159 INVITE                             // トランザクション毎にインクリメントされる値
Contact: <sip:alice@pc33.sapporo.com>
Content-Type: application/sdp 
Content-Length: 142
------------------------------ヘッダここまで--------------------------------------------
------------------------------ボディここから--------------------------------------------
v=0                                                                                      // プロトコルのバージョン
o=alice 53655765 2353687637 IN IP4 pc33.sapporo.com // 発信元及びセッション識別子
s=-                                                                                      // セッション名
t=0 0                                                                                   // セッションがアクティブな時間
c=IN IP4 pc33.sapporo.com                                               // セッション情報
m=audio 3456 RTP/AVP 0                                                  // メディア名・伝送アドレス
a=rtpmap:0 PCMU/8000                                                    // 0行以上のメディア属性行
------------------------------ボディここまで--------------------------------------------

なお、NATを通す場合、ボディに記載してあるIP情報まで変換する機能を もったNAT機器でないと、通話セッションが生成できないという問題が発生します。

Django マイグレーション関連のコマンド&エラー

基本の操作

マイグレーションファイルを作成

$ python manage.py makemigartions

マイグレーションファイルをDBに適用

$ python manage.py migrate (MIGRATION_ID)

マイグレーションの一覧を表示

$ python manage.py showmigrations (MIGRATION_ID)

よく出会うエラー

整合性不正によるエラー

エラーメッセージ例:

django.db.utils.ProgrammingError: relation "sample_user" does not exist
LINE 1: ...user"."is_active", "sample_user"."date_joined" FROM "sample_user...

このようなエラーは、主にmigrationコマンドによるマイグレーションファイルの DBへの適用時に、その適用の順番が逆転していることが原因で発生します。

上の場合であれば、先に "sample_user" を明示的に指定して先にマイグレーション することで解消することが多いです。

# sample_userを先にマイグレーション
$ python manage.py migrate sample_user

# 残りをマイグレーション
$ python manage.py migrate

参考

つぶやきメモーLinuxコマンド篇【随時更新】

sed:テキストファイルをフィルター処理で編集

sedコマンドとは

  • "Stream EDitor"の略です。
  • 指定したファイルをコマンドに従って処理し、標準出力へ出力します。
  • ファイル名を省略した場合は、標準入力からのデータを処理します。

書式:

sed [option]
sed [option] (スクリプトコマンド) (入力ファイル)

sed の主なオプション

オプション 長いオプション 意味
-i --in-place ファイルを直接編集する
-e --expression=(スクリプト) スクリプト(コマンド)を追加する

env:環境変数を一時的に設定しコマンド実行

envコマンドとは

  • 環境変数に特定の値を指定して、後に続くコマンドを実行します。
env (環境変数名)=(値) (コマンド)

envの主なオプション

オプション 長いオプション 意味
-i --ignore-enviroment 環境変数が設定されていない状態でコマンド実行
-u (変数名) --unset=(変数名) 指定した環境変数が設定されていない状態でコマンド実行

curl:手軽にHTTPリクエスト

curlコマンドとは

  • 様々なプロトコルを使用して、データ転送を実行できます。
curl (リクエストURL)

curlの主なオプション

オプション 意味
-X リクエストメソッドの指定
-H ヘッダの変更
-d コンテンツの変更
-v 通信詳細の出力
-f 終了コード変更*1
-o レスポンスボディの出力先のパスを指定
-L リダイレクトを有効にする

使用例:

$ curl -v -H "content-type: application/json" -X POST -d'{"gohann":"suki", "oyatsu":"daisuki"}' http://sample.org/post

*   Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to sample.org (xxx.xxx.xxx.xxx) port xx (xx)
> POST /post HTTP/1.1
> Host: sample.org
> User-Agent: curl/7.64.1
> Accept: */*
> content-type: application/json
> Content-Length: 41
> 
* upload completely sent off: 41 out of 41 bytes
< HTTP/1.1 200 OK
< Date: Mon, 30 Mar 2020 xx:xx:xx GMT
< Content-Type: application/json
< Content-Length: 486
< Connection: keep-alive
< Server: xxxxxxxx/xxxxxxxx
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< 
{
  "args": {}, 
  "data": "{\"gohann\":\"suki\", \"oyatsu\":\"daisuki\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "41", 
    "Content-Type": "application/json", 
    "Host": "sample.org", 
    "User-Agent": "curl/7.64.1", 
    "X-Amzn-Trace-Id": "Root=12345678901234567890"
  }, 
  "json": {
    "gohann": "suki", 
    "oyatsu": "daisuki"
  }, 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "http://sample.org/post"
}
* Connection #0 to host sample.org left intact
* Closing connection 0

*1:通常、curlはエラーになっても何食わぬ顔で正常終了します(終了コード0)。-fオプションをつけることで、異常終了時に終了コード22で終わるようになります。

django.db の InconsistentMigrationHistory例外に遭遇した時の対処

InconsistentMigrationHistoryとは?

  • DB内の依存関係が原因で、整合のとれたマイグレーションができなくなる 例外のよう。
  • エラーメッセージは、例えば以下のように表示されます。
django.db.migrations.exceptions.InconsistentMigrationHistory: 
Migration example_django.0001_initial is applied before its dependency sample_app.0001_initial on database 'default'.

どう対処しようか?

  • 私の場合は、settings.py の INSTALLED_APP を一時的に修正し、 マイグレーション実行後に元に戻す、という対処で解決できました。

settings.pyを一時修正

INSTALLED_APPS = [
    ...
    # 'example_django',  ←例外が発生した部分を一時的にコメントアウト
    ...
]

マイグレーションを実行

$ python manage.py makemigrations
$ python manage.py migrate

settings.py を復元

マイグレーションを再実施

  • これで整合がとれたマイグレーションができるようです。

  • 今回は こちらのサイトを参考にさせていただきました。

  • この対応でなぜ解決したのか、まだ「?」な部分も多いです。またわかったら追記していきたいと思います。