Let’s Encrypt 免費讓你的網站升級成 SSL ready

Our Commitment to Protecting Your Information by Marissa Mayer, Yahoo CEO

2013 年底時,美國方面爆出政府直接拉線路進 Yahoo 機房偷取使用者資料,所以在2014 年初時 Yahoo 宣布全面使用 SSL 連線來保護連線資料。但買一個 SSL 憑證實在是太貴了,如果一堆 domain 的話,更是負擔不起。所以在自已用的小站通常都用 self-sigh 來解決這個問題,只是使用時會一直被 Browser 靠腰說你的 SSL 是不合法的。

時至今日, Internet Security Research Group (ISRG) 組織為了網路安全,提供了免費的 SSL 申請服務 - Letsencrypt ,主要有下列幾項特色:

  • Free: Anyone who owns a domain name can use Let’s Encrypt to obtain a trusted certificate at zero cost.
  • Automatic: Software running on a web server can interact with Let’s Encrypt to painlessly obtain a certificate, securely configure it for use, and automatically take care of renewal.
  • Secure: Let’s Encrypt will serve as a platform for advancing TLS security best practices, both on the CA side and by helping site operators properly secure their servers.
  • Transparent: All certificates issued or revoked will be publicly recorded and available for anyone to inspect.
  • Open: The automatic issuance and renewal protocol will be published as an open standard that others can adopt.
  • Cooperative: Much like the underlying Internet protocols themselves, Let’s Encrypt is a joint effort to benefit the community, beyond the control of any one organization.

這項服務在 2015/12/3 已經 Open Beta 了,任何人可以直接使用,不需申請。

Install

使用方法也很簡單到 github 下載 letsencrypt client 後,直接執行 ./letsencrypt-auto --help all 就可以看到所有的說明和使用方法。

Renew

預設的 SSL 90 天後就會過期,所以我就排個 cron 每天去跑一次。
這個 Script 會刮出所有 apache2 底下有開 443 port 的 servername 去 renew SSL。其中 --renew-by-default--agree-tos 開啟後 CLI 介面不會問東問西的選項。

#!/bin/sh
/usr/sbin/apachectl stop

/home/whatup/letsencrypt/letsencrypt-auto certonly -a  standalone --renew-by-default --agree-tos `grep -ih servername /etc/apache2/sites-enabled/*|grep 44
3 | sed 's/:443//g' | sed 's/ServerName/-d/g' `  --email whatup.tw@gmail.com

/usr/sbin/apachectl start

Rate Limit

流量限制如下,自已要多加注意,要不然會被檔掉。

  • Registrations per IP is 10 registrations per 3 hour window.
  • Certificates per name is 10 certificates per 59 days.
  • Pending registrations per account is 300 per 1 week.

Result

看到綠色合法的 SSL Icon 就是開心!
Screen Shot 2015-12-03 at 9.47.04 AM

Screen Shot 2015-12-07 at 10.24.43 AM
Screen Shot 2015-12-07 at 10.25.09 AM
Screen Shot 2015-12-07 at 10.25.30 AM
Screen Shot 2015-12-07 at 10.24.56 AM

[php] grapheme_strlen vs mb_strlen vs strlen

前言

小時候在寫 PHP 時要看字串長度,常常不懂事的用 strlen 來作判斷,但是在遇到中日韓這種會把 2 bytes 當一個字的長度時,這時候字串的長度又不準了。這時學會了使用 mb_strlen 這個 function,感覺長度這樣用,就準了。但有趣的事是,竟然近期又出現了 grapheme_strlen 。崩潰,不過就是算個長度而已,為什麼有這麼多的方法。

讓我們來寫個小程式來實驗一下

<?php
$str = "這是中文 english 混合測試";
var_dump($str);
var_dump(
    mb_strlen($str, 'UTF-8'),
    grapheme_strlen($str),
    strlen($str)
);
?>

結果如下:

$ php /tmp/test.php
string(33) "這是中文 english 混合測試"
int(17)
int(17)
int(33)

看起來很合理啊,用 strlen 結果是 33 個字元,因為他是算 bytes。mb_strlen 17 個字,即使是中英文混合,看起來算字數也是沒問題的!mb_strlen 和 grapheme_strlen 目前看起來結果是一樣的。

接下來再一個小實驗

<?php
$str = json_decode('"e\u0301 = \u00E9"');
var_dump($str);
var_dump(
    mb_strlen($str, 'UTF-8'),
    grapheme_strlen($str),
    strlen($str)
);
?>

結果如下:

$ php /tmp/test.php
string(8) "é = é"
int(6)
int(5)
int(8)

WTF,竟然有三個不同的數字,畫面上來看,明明就只有五個字,為什麼 mb_strlen 會算出來六個字呢!

原來是 Grapheme Cluster 在作怪

Grapheme Cluster 就類似中文一樣,會把二個字當作一個字。所以畫面上看起來是一個字,但實際上在 unicode 是可以用二個字來表示,所以可以看見範例二中顯示的字是一樣,但 unicode 是不同的。而這樣就會造成 mutlibyte 的 function 計算長度有問題。

結論就是....

如果有考慮中日韓以外的語系的話,可以使用 grapheme_strlen 。另外必須要注意,如果傳進來的參數不是 utf8 的字的話,他的回傳值是 null ,而這部份與 mb_strlen 的結果不一致。

參考文章

[php] mock 有 reference parameter 的 method

前言

雖然盡量不要在 php 裡面寫 call by reference 的參數,但是有一些舊有的code 還是有人這樣寫。如果這時又想要mock 他就麻煩了,因為值並不會隨著自已想要的內容作改變。

實作

原先的 class 設計如下

<?php
class NeedToMockClass {
    function testReference(&$str) {
        // 也許會有很多很複雜的計算,不過這邊簡化成一行就好    
        $str = "test String";
        return;
    }
}
class testClass{
    function test($str) {
        $t = new NeedToMockClass();
        $t->testReference($str);
        return __METHOD__ .'->' . $str;

    }
}
// $t = new testClass();
// $str = $t->test('not a test string');
// var_dump($str);
// string(28) "testClass::test->test String"

How To Test?

如果這時我要測 testClass 我該如何測?因為我單純的只想測 testClass 裡的邏輯對不對,我不想管 NeedToMockClass 的邏輯,所以這時我該把 class mock 掉,並且讓他可以自定 $str 的 output。

首先,會先改寫 testClass 讓他可以從外面傳 NeedToMockClass 的 object 進去。

<?php
class testClass{
    private $_mockClass = null;
    
    // 由 construct 傳進來,讓他可以取代掉預設的 mockClass
    function __construct($mockClass == null) {
        if ($mockClass = null) {
            $mockClass = new NeedToMockClass();
        }
        $this->_mockClass = $mockClass;    
    }
    function test($str) {
        // 接著用mock 後的class 來執行    
        $this->_mockClass->testReference($str);
        return  __METHOD__ .'->' . $str;

    }
}

最後測試程式會用下面這個方法寫,主要是用 returnCallback 的方式來 mock:

<?php
require_once './sample.php';
class testTest extends PHPUnit_Framework_TestCase
{
    function mockTestReference(&$str)
    {
        $str = '3345678';
    }
    function testTestClass()
    {
        $mockClass = $this->getMock('NeedToMockClass', array(), array(), "" ,false);
        // 這裡是用 returnCallback 的方式呼叫 testTest::mockTestReference 這樣就可以改 $str 的內容了
        $mockClass->expects($this->any())
                  ->method('testReference')
                  ->will($this->returnCallback(array('testTest', 'mockTestReference')));
        $t = new testClass($mockClass);
        $str = 'one test';
        $ret = $t->test($str);
        // 最後會如預期的產生 testClass::test->3345678 的字樣
        $this->assertEquals('testClass::test->3345678', $ret);
    }
}

順利達成目標,其結果如下:

$ phpunit testTest.php

PHPUnit 3.7.35 by Sebastian Bergmann.

.

Time: 22 ms, Memory: 3.50Mb

OK (1 test, 2 assertions)

參考文件

在 Console 底下簡單的 Yaml syntax check Script

介紹

在編寫 yaml 檔時,如果沒有使用任何的 IDE, 或是想 automation 作檢查,勢必需要在 CLI 可以檢查的方法。Yaml 檔發生錯誤是很擾人的,尤其是一個yaml 檔可能上百行,要找一個空白空錯沒有什麼好方法。最近就遇到因為前一版 commit 設定檔的人沒有檢查語法,設定檔裡面少了一個空白,結果造成 indent 就不對,接著程式沒寫好就直接停止執行的問題。但後來想想,應該要有一些方便的 tool 在編寫 yaml 檔結束後,作一些簡單的檢查,來減少浪費大家人力來追問題。

實作方法

  • 安裝 ruby
  • 安裝 awesome_print 的 gem 檔
    # sudo gem install awesome_print
  • 執行 ruby 指令
    $ ruby -e "require 'yaml'; require 'awesome_print'; y=YAML.load_file('/tmp/example.yaml'); ap y"

在 MAC 下只要安裝一個 gem 檔,然後用內建的 ruby 指令馬上就可以看出來了,而且畫面還非常的漂亮。

DEMO

我們以 wikipedia 上的 yaml 範例檔為例:

--- receipt: Oz-Ware Purchase Invoice date: 2012-08-06 customer: given: Dorothy family: Gale items: - part_no: A4786 descrip: Water Bucket (Filled) price: 1.47 quantity: 4 - part_no: E1628 descrip: High Heeled "Ruby" Slippers size: 8 price: 100.27 quantity: 1 bill-to: &id001 street: | 123 Tornado Alley Suite 16 city: East Centerville state: FL ship-to: *id001 specialDelivery: > Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.

Result:
如果一切順利的話,可以看到下面的結果,除了可以驗證內容打的對不對之外,還可以看結構是否正確。
yaml parse result

如果結構有錯,或是語法有錯,他會顯示錯誤的行數,這樣就比較好 Debug 了。
parse error

結論

如果有 vim 的 plugin or sublime 的 plugin 在即時編寫時,就可以直接列出語法有問題的地方應該會更好更直覺。不過現在這個方法比較適合在 CI commit build 預先作檢查,減少錯誤的程式上到 production 。

參考

[1] http://stackoverflow.com/questions/3971822/yaml-syntax-validator
[2] http://stackoverflow.com/questions/17289399/how-do-i-pretty-print-a-hash-to-a-rails-view
[3] https://github.com/michaeldv/awesome_print