Amazon EC2 AMI 的 root volume 可以直接抽換了

這個功能等了十年以上總算是出現了,Amazon EC2 的 AMI 總算是能直接抽換 root volume,不用先停掉機器:「Amazon EC2 enables easier patching of guest operating system and applications with Replace Root Volume」。

Starting today, Amazon EC2 supports the replacement of instance root volume using an updated AMI without requiring customers to stop their instance. This allows customers to easily update their applications and guest operating system, while retaining the instance store data, networking and IAM configuration.

算是 pre-container 時代會遇到的問題,後來大家都把 workaround 變成 practice 了:每次需要時候都是直接整包重新打包 (像是 Packer 這類的工具),然後用工具更新 AMI id 改開新的機器,這樣就能夠避開需要先停掉現有機器的問題...

怎麼會突然想到要回來支援這個功能 XD

PHP Composer 的安全性問題

ComposerPHP 上新一代的套件管理軟體。

Composer 與之前各種方案不同的地方在於,後面掛了 Packagist 這個 PHP package archivist,讓使用者很方便的取得套件 (以及更新)。

其中有一個功能是 replace,表示我所開發的這個套件「宣稱」可以取代其他套件 (通常是 API compatible)。

看到這個功能的時候,以為是要讓 Packagist 能夠串起連結。畢竟偶而會發生「這個套件最新版是 2008 年了,到底有沒有後續維護啊」的情況。如果 Packagist 官方網站可以串起連結,可以節省開發者時間,而且也可以利用 Packagist 上的熱門度來決定要用哪一個後繼者。

但實際上與預期的不同,Composer 的預設值是會「自動」尋找更新並且真的使用,也就是前幾天被丟出來的議題:「Composer is wide open with a massive security vulnerability」。

攻擊者只要在 Packagist 上面上傳一堆含有惡意程式碼的套件 (並且利用 replace 宣稱可以取代 ZF2 或是 Laravel),受害者在 composer update 的時候就有機會抓到這些有惡意程式碼的套件。

而最糟糕的是,主要開發者認為這不是問題,還寫了一大篇文章顧左右而言他之後說「錯覺啦~」:「Composer: Replace, Conflict & Forks Explained」:

Replace is not a bug. Don’t run composer update in automated systems. Forks are allowed on Packagist. Don’t be an idiot when publishing a fork. Got an unexpected fork on update? Your dependencies conflict with the original package. Use conflict (syntax like require) in your composer.json to blacklist the fork and see an explanation of the dependency issue.

於是發現問題的人就爆炸了。

依照往例,vendor 不覺得是問題的安全漏洞,只能把事情弄大爆出來逼 vendor 修。

修正在「Limit Replace / Provides to packages required by name in root package or any dep」這裡。最新版的 Composer 裡已經納入這個修正了。

UPSERT

維基百科對 UPSERT 的說明:(取自「Merge (SQL)」條目)

A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether or not a condition matches.

MySQL 裡的兩種語法其實就是在實做這個需求:

  • REPLACE INTO ...
  • INSERT INTO ... ON DUPLICATE KEY UPDATE ...

而前者其實是後者的一個特例 (當 INSERT 發現有 dupe key 時把現有的 record 改成與 INSERT 時相同的條件)。

而計數器是後者常見的 case 之一:當 record 不存在的時候塞一筆進去,並且將 counter 設為 1;當 record 存在的時候對 counter 加一更新。像是這樣的 SQL query:

INSERT INTO my_table SET id = ?, num = 1 ON DUPLICATE KEY UPDATE num = num + 1;

由於這是常見的需求,使得這個語法是目前少數 MySQL 比 PostgreSQL 好用的地方。

在「A Case for Upserts」這篇就看到抱怨 PostgreSQL 不實做這個功能...

不過我覺得作者寫得有點誇張,INSERT INTO ... ON DUPLICATE KEY UPDATE ... 應該是可以模擬出來的功能:當 INSERT 失敗後再跑 UPDATE。而 REPLACE INTO ... 是特例,也就當然可以模擬出來。