パッケージマネージャ使用時のOSS管理


#ちょっとコワいパッケージマネージャのお話

ちょっと釣りっぽいタイトルでした。

パッケージマネージャ使ってますか？
ライブラリ検索とかインストールとか楽だし便利だし割といろんな局面で使いますよね。

実はパッケージマネージャにはBOM(Bill of Materials: 部品表)管理やOSSのライセンス管理・遵守の観点で見落としがちなことがあるので注意が必要ですよというお話です。

この記事では **Visual Studio & NuGet** を例にとって説明します。

#パッケージマネージャNuGetについて
>NuGetとは.NET Frameworkに対応するフリー・アンド・オープンソースのパッケージマネージャである。([wikipedia](https://ja.wikipedia.org/wiki/NuGet))

Visual Studio 2012 からは標準で含まれているので便利ですよね。
JSONのシリアライズ/デシリアライズやREST APIコール等、一般的に使われまくっている汎用的な機能を今更自力でゴリゴリ書くなんて面倒ですし生産性が悪すぎるので、とりまNuGetで検索しますよね。

このNuGetを使う際に、どういう点に注意が必要なのかというところを紹介していきます。

##第一の関門
さっそくですが下の画像を見てください。
![0270FA45-CC1D-461C-B0AB-CE9AACB519E3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539510/5aa3a164-be75-3767-4274-4e3e9b13a905.png)
NuGetでMicrosoftが提供しているC++向けREST APIライブラリ "cpprestsdk" を検索したところです。

よく見ると「**ライセンス MIT**」と書いてありますね。つまりこのcpprestsdkはMITライセンスのOSSとして公開・提供されており、cpprestsdkを使って（かつ、cpprestsdkを同梱して）プログラムを配布、販売する際には、MITライセンスの条件に従う必要があるというわけです。

一方、C++開発で一般的・慣習的に同梱されたり再頒布されたりするものとして [Visual C++ 2019再頒布可能パッケージ](https://visualstudio.microsoft.com/ja/downloads/#microsoft-visual-c-redistributable) がありますが、これは、いくつか禁止事項はあるものの再頒布に際して「○○～しなければならない」という条件は特にはありません。(あくまで再頒布**時**の条件だけで見た場合です)
※EULA(End-User License Agreement: ソフトウェア使用許諾契約)を厳密に読むと、完全に条件がないというわけではないので興味ある方は読んでみてください。

##第二の関門
さて、OSSのライセンス条件に従った対応はこのMITライセンスだけで十分でしょうか？
話の流れからも分かると思いますが、勿論、他にも注意が必要な点があります。

[cpprestsdkのGitHub](https://github.com/microsoft/cpprestsdk) をよく見て見ましょう。
[ThirdPartyNotices.txt](https://github.com/microsoft/cpprestsdk/blob/master/ThirdPartyNotices.txt) というのがありますね。

```ThirdPartyNotices.txt&#x20;(抜粋)

THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize

C++ REST SDK incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.  

1.	Websocket++ (http://www.zaphoyd.com/websocketpp/)
```

どうやらcpprestsdkはWebsocket++を参照しているようです。

Websocket++は [https://github.com/microsoft/cpprestsdk/tree/master/Release/libs](https://github.com/microsoft/cpprestsdk/tree/master/Release/libs) からリンクされており、実体は [ここ](https://github.com/zaphoyd/websocketpp/tree/56123c87598f8b1dd471be83ca841ceae07f95ba) にあるようです。

Websocket++にも [COPYINGファイル](https://github.com/zaphoyd/websocketpp/blob/56123c87598f8b1dd471be83ca841ceae07f95ba/COPYING) があるので見てみましょう。

```COPYING&#x20;(抜粋)

Main Library:

Copyright (c) 2014, Peter Thorson. All rights reserved.

———————————————————————————————-（中略）———————————————————————————————-

Bundled Libraries:

****** Base 64 Library (base64/base64.hpp) ******
base64.hpp is a repackaging of the base64.cpp and base64.h files into a single header suitable for use as a header only library. This conversion was done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to the code are redistributed under the same license as the original, which is listed below.

base64.cpp and base64.h

Copyright (C) 2004-2008 René Nyffenegger

———————————————————————————————-(中略) ———————————————————————————————-

****** SHA1 Library (sha1/sha1.hpp) ******
sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1 library (http://code.google.com/p/smallsha1/) into a single header suitable for use as a header only library. This conversion was done by Peter Thorson (webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed under the same license as the original, which is listed below.

 Copyright (c) 2011, Micael Hildenborg
 All rights reserved.

———————————————————————————————-（中略）———————————————————————————————-

****** MD5 Library (common/md5.hpp) ******
md5.hpp is a reformulation of the md5.h and md5.c code from http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to function as a component of a header only library. This conversion was done by Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The changes are released under the same license as the original (listed below)

Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.

———————————————————————————————-（中略）———————————————————————————————-

****** UTF8 Validation logic (utf8_validation.hpp) ******
utf8_validation.hpp is adapted from code originally written by Bjoern Hoehrmann
<bjoern@hoehrmann.de>. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.

The original license:

Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
```

COPYINGによるとWebsocket++はどうやら以下のコンポーネントを使っているようです。


| ライブラリ名 (ファイルパス) | ライセンス |
|:-|:|
| Base 64 Library (base64/base64.hpp) | zlib License |
| SHA1 Library (sha1/sha1.hpp) | 3条項BSD License (3-Clause BSD License) |
| MD5 Library (common/md5.hpp) | zlib License |
| UTF8 Validation logic (utf8_validation.hpp) | MIT License |

そしてまた、Websocket++自身のライセンスは3条項BSD License (3-Clause BSD License)であることが分かります。

つまり、cpprestsdkを使うと、以下の参照関係にあるOSSを全て利用することになります。これら全てについてライセンス対応が必要です。（あくまで各パッケージの包含関係であってプログラムの論理的な呼び出し関係を表しているわけではありません。）

cpprestsdk (MIT License)
　└Websocket++ (3-Clause BSD License)
　　├Base 64 Library (zlib License)
　　├SHA1 Library (3-Clause BSD License)
　　├MD5 Library (zlib License)
　　└UTF8 Validation logic (MIT License)

ここで最初に見たcpprestsdkのThirdPartyNotices.txtを再度見てみましょう。
[cpprestsdkのThirdPartyNotices.txt](https://github.com/microsoft/cpprestsdk/blob/master/ThirdPartyNotices.txt) の11行目以降には、[Websocket++のCOPYING](https://github.com/zaphoyd/websocketpp/blob/56123c87598f8b1dd471be83ca841ceae07f95ba/COPYING) がまるまる転記されていますね。

##第三の関門
ここからは個々のライセンスの中身を読む作業になります。
上のライセンス名だけ見ればもう分かるという強者はサラッと読み飛ばしてください。

<details><summary>個々のライセンスを読む</summary><div>
[MIT License](https://licenses.opensource.jp/MIT/MIT.html)

```/MIT.html&#x20;(抜粋)
上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に記載するものとします。
```

[3条項BSD License (3-Clause BSD License)](https://licenses.opensource.jp/BSD-3-Clause/BSD-3-Clause.html)

```/BSD-3-Clause.html&#x20;(抜粋)
・ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項を含めること。

・バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作権表示、本条件一覧、および下記免責条項を含めること。

・書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進に、<組織> の名前またはコントリビューターの名前を使用してはならない。
```

[zlib/libpng License](https://licenses.opensource.jp/Zlib/Zlib.html)

```/Zlib.html&#x20;(抜粋)

1. 本ソフトウェアの出自について虚偽の表示をしてはなりません。あなたがオリジナルのソフトウェアを作成したと主張してはなりません。 あなたが本ソフトウェアを製品内で使用する場合、製品の文書に謝辞を入れていただければ幸いですが、必須ではありません。

2. ソースを変更した場合は、そのことを明示しなければなりません。オリジナルのソフトウェアであるという虚偽の表示をしてはなりません。

3. ソースの頒布物から、この表示を削除したり、表示の内容を変更したりしてはなりません。
```

</div></details>

つまり今回のライセンス対応としては、cpprestsdk自体のライセンスである *[license.txt](https://github.com/microsoft/cpprestsdk/blob/master/license.txt)* と、Websocket++とWebsocket++に含まれる他コンポーネントの使用、情報、ライセンスについて言及している、*[ThirdPartyNotices.txt](https://github.com/microsoft/cpprestsdk/blob/master/ThirdPartyNotices.txt)* の**2つのファイルを開発したプログラムに同梱して再頒布すればいい**ということが分かります。

#まとめ
このように、NuGetから取得してくるライブラリはそれ自体がOSSであることや、そのライブラリが他のOSSを内包していることが多々あります。これら全ての各OSSのライセンスに誠実に対応する必要があります。

もちろんNuGetに限らず、Mavenやnpm、PyPI(pip)等のパッケージマネージャでも同じことが言えます。ただし、決してこれらパッケージマネージャ自体やパッケージマネージャを使うことが悪いということではありません。

パッケージマネージャを使うと手軽に外部ライブラリを取り込むことができる反面、そのライセンスや利用許諾条件がどのようになっているのかの確認が疎かになりがちなので、外部ライブラリやその依存パッケージのライセンス・利用条件をチェックしておく必要があるということです。

##あとがき
ずいぶん前は、Microsoftの.NET系のライブラリは [MICROSOFT SOFTWARE LICENSE TERMS **MICROSOFT .NET LIBRARY**](https://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm) でバイナリのみの形で公開されているものが多くありました。(もちろん現在もそういうライブラリはあります)

このライセンスの頒布に際しての条件は「作ったアプリケーションと一緒に再頒布する（ライブラリのみの単独での再頒布はNG）」という条件があるくらいで、ライセンス文書の添付などの条件はありません。

なので、このライセンスの感覚が染み付いているとVisual Studio上での操作で簡単にOSSが取り込まれるというところに気づきづらいかもしれません。そういう意味ではもともとがOSSの世界にいるMaven、npm、PyPIと比べると若干NuGetの方が起きやすい問題なのかなぁとも思います。