Let's Encrypt で証明書を自動更新する方法
certbotをclone
$ cd /usr/local/ $ git clone https://github.com/certbot/certbot
Let's Encrypt クライアントが依存するパッケージをインストール
$ cd certbot/ $ ./certbot-auto -n
証明書の取得
$ ./certbot-auto certonly --webroot \ -w /var/www/example -d example.com \ -m sample@example.com \ --agree-tos -n
オプション
certonly
証明書の取得のみを行います。デフォルト値は「run」で、証明書の取得とApache等のSSL設定もやってくれるそうですが、まだうまく動かないことが多いようです。
--webroot
ApacheなどWEBサーバのドキュメントルートに、認証用ファイルを生成します。ドキュメントルート直下に「.well-known/」というディレクトリが作成され、この中に生成されているようです。証明書の取得が終われば、この認証用ファイルは削除されます。稼働しているWEBサーバがない場合(メールサーバなど)は --standalone を指定すると良いでしょう。
-w
ドキュメントルートのパスを指定します。Apacheの場合は、DocumentRoot で指定しているパスです。
-d
証明書を取得するドメイン名を指定します。Apacheの場合は、ServerName で指定しているドメイン名です。
-m
ご自分のメールアドレスを指定します。なにかトラブルがあった場合などに Let's Encrypt との連絡用に使用されます。また、証明書の更新期限が近づくと、ここで指定したメールアドレス宛に、お知らせメールが届きます。
--agree-tos
Let's Encrypt の利用規約に同意します。事前に利用規約「https://letsencrypt.org/repository/」を確認しておきましょう。
-n
--non-interactive の省略オプションです。対話メッセージの表示や入力を求められないようにできます。
自動更新をする
$crontab -e 00 05 01 * * /usr/local/certbot/certbot-auto renew --force-renewal && nginx -s reload
PDOの説明
自分なりにPDOについて勉強したのでここにまとめます。
作成したサンプルコード
<?php
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8','user','password');
$db->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$loginid = "var";
$sql = "SELECT * from users WHERE loginid= :loginid ";
$statement = $db->prepare($sql);
$statement->bindValue(':loginid',$loginid,PDO::PARAM_STR);
$statement->execute();
while($user = $statement->fetch(PDO::FETCH_ASSOC)){
echo $user["loginid"] . "<br>";
}
PDO (PHP Data Objects)
データアクセス抽象化レイヤーと言われ、アプリケーションとDBMS(データベース管理システム)の間に入ってDBMSの違いを意識せずにアプリケーションを作成するもの。
データベースの違いを意識しないで同じ書き方で使える。
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
エミュレーションがONの場合のみ, ; 区切りで複数のSQL文を1つのクエリで実行することができる.
エミュレートの設定がONだと動的プレースホルダになり、OFFだと静的プレースホルダになる。
ユーザー入力を受け取ってSQL文を動的に生成する場合は プリペアドステートメント と プレースホルダ を使わなければならない.
プレースホルダ:
直訳すると「場所取り」.何かユーザ入力を当てはめる場所としてあらかじめ確保しておくもの.
プリペアドステートメント:
直訳すると「予約文」.文を予約したもの.通常,「予約文」は「場所取り」を使うために作られる.もし「場所取り」が無ければ普通に PDO::query などで実行するだけで十分なためである.
プレースホルダには2種類あり,疑問符プレースホルダ を使う方法と, 名前付きプレースホルダ を使う方法がある.もしこれらが混ざってしまうと
SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
が発生するので、どちらか一方のみを選択すること.
IPAの出している「安全なSQLの呼び出し方」では、
静的プレースホルダは、SQL文をデータベースエンジン側にあらかじめ送信して、実行前にSQL文の構文解析などを準備しておく方式です。 SQL 実行の段階で、実際のパラメータの値をデータ
ベースエンジン側に送信し、データベースエンジン側がバインド処理します。
動的プレースホルダは、パラメータのバインド処理をデータベースエンジン側で行うのではなく、アプリケーション側のライブラリ内で実行する方式です。
と説明されている。
参考URL
IPA 安全なSQLの呼び出し方
https://www.ipa.go.jp/files/000017320.pdf
qiita PDOの静的プレースホルダと動的プレースホルダの違いを確認する
http://qiita.com/7968/items/7ddd59b94eb5a4fb6eaf
バインド機構
SQLインジェクションを防ぐために、プログラムのソースコードでSQL文の雛(ひな)型の中に変数の場所を示す記号(プレースホルダと呼ばれる)を置いた後、実際の値を割り当てる仕組み。
入力値中の特殊記号も単なる値として渡されるためエスケープ処理なしで安全にSQL文を発行することが可能となる。
データベースシステムやプログラム言語によっては、この機構が用意されているものもありSQLインジェクション対策として有用である。
bindValue:値をバインドする 実行する前に値をバインドする
bindParam:変数をバインドする 実際に値を評価するのはexecute()の時。
基本的にbindValue推奨
理由:実行後にバインドした変数が文字列型にされる仕様もあるから
参考URL
http://qiita.com/_dozen_/items/e3c00a0a581378a4cc70
ということで値をバインドする。
$statement->bindValue(':loginid',$loginid,PDO::PARAM_STR);
参考URL
qiita bindValueとbindParamの違い
http://piyopiyocs.blog115.fc2.com/blog-entry-656.html
qiita PHPでデータベースに接続するときのまとめ
http://qiita.com/mpyw/items/b00b72c5c95aac573b71
Docker よく使うコマンド集
Dockerイメージリストの確認
$ docker images
Dockerイメージからコンテナ作成、起動
$ docker run -i -t [REPOSITRY名:TAG名] /bin/bash
Dockerコンテナからイメージを作成する
$ docker commit [コンテナid] [REPOSITRY名:TAG名]
Dockerコンテナの確認(停止中コンテナも表示する場合は -a オプションをつける)
$ docker ps -a
停止中のDockerコンテナを稼働させる
$ docker start [コンテナid]
稼働中のDockerコンテナを停止させる
$ docker stop [コンテナid]
Dockerコンテナ削除
$ docker rm [コンテナid]
Dockerイメージ削除
$ docker rmi [イメージid]
・便利なdockerコマンド
稼働しているdockerコンテナすべて停止
$docker stop `docker ps -q`
dockerコンテナすべて削除
$docker rm `docker ps -a -q`
コンテナからexitするときにコンテナ削除(使い捨て)
$docker run -ti --rm [イメージID]
centosでsystemctl start [サービス名]とするとエラーがでる場合
$ docker run --privileged -d --name http centos /sbin/init
コンテナ内で作業する
$ docker exec -it http bash
サービスを立ち上げてコンテナ起動
centos7の場合
$ docker run --privileged -d -p 80:80 --name httpd centos:centos7 /sbin/init
centos6の場合
$ docker run -p 8080:80 -d cent6_apache /usr/sbin/apachectl -DFOREGROUND
docker イメージの保管場所
まずdockerのimage ID の確認
$ cat /var/lib/docker/repositories-devicemapper
表示されたJSONをJSON Lintなどにかけて読みやすくするなどして探したいイメージファイルのIDを探す
$ ls /var/lib/docker/graph/[image ID]
作成したコンテナを別PCで動作させる方法
Dockerコンテナをファイル出力する
$ docker export [コンテナid] > [出力ファイル名]
出力したコンテナファイルを開発メンバーに渡して、メンバーは出力ファイルをインポートコマンドで叩けば、構築済みのDockerイメージを得ることができる為、docker runすることで同一環境を得ることが可能
cat [インポートファイル] | docker import - [REPOSITRY名:TAG]
docker-compose
バックグラウンドで立ち上げる
$ docker-compose up -d
Docker exec的なやつ
docker exec -it $(docker-compose ps -q httpd) bash
Docker-composeのimageをdownついでに削除
docker-compose down --rmi all
ICMPで遊ぶ
クリスマスなのでリア充っぽい機能を作成しようと思います。 ICMPリクエストのペイロードに "I love you"という文字列をのっけて送信すると
"I love you too."をペイロードに乗っけて返信してくれるサーバーを作りましょう。
iptablesでecho-requestのICMPパケットをNFQUEUEターゲットでキューに入れ、それをpythonで処理します。
from scapy.all import * from netfilterqueue import NetfilterQueue def icmp_fake(pkt): ip = IP() icmp = ICMP() ip.src = pkt[IP].dst ip.dst = pkt[IP].src icmp.type = 0 icmp.code = 0 icmp.id = pkt[ICMP].id icmp.seq = pkt[ICMP].seq print (ip.src + "=>" + ip.dst) print(pkt[ICMP].load) if pkt[ICMP].load == "I love you.": send(ip/icmp/"I love you too.") else: data = pkt[ICMP].load send(ip/icmp/data) def is_icmp(pkt): packet = IP(pkt.get_payload()) proto = packet.proto if proto == 0x01: if packet[ICMP].type == 8: icmp_fake(packet) nfqueue = NetfilterQueue() nfqueue.bind(1, is_icmp) try: nfqueue.run() except KeyboardInterrupt: print('') nfqueue.unbind()
iptablesの設定はこんな感じ
iptables -A INPUT -p icmp --icmp-type echo-request -j NFQUEUE --queue-num 1
クライアントからICMPパケット送信
$sudo scapy >>>sr1(IP(dst="192.168.11.52")/ICMP()/"I love you.") Begin emission: ..Finished to send 1 packets. ...................................................................................* Received 86 packets, got 1 answers, remaining 0 packets<IP version=4L ihl=5L tos=0x0 len=43 id=1 flags= frag=0L ttl=64 proto=icmp chksum=0x5a27 src=192.168.11.52 dst=192.168.11.50 options=[] |<ICMP type=echo-reply code=0 chksum=0x8638 id=0x0 seq=0x0 |<Raw load='I love you too.' |<Padding load='\x00\x00\x00' |>>>>
ちゃんと愛されていますね。まぁ誰にでも"I love you too."と送るようなビッチですが居ないよりはマシでしょう。
pythonでTwitterに投稿
今回はtwitter APIを取得してpythonでtweetをするプログラムを書きたいと思います。
twitter APIへアクセスするにはOAuth認証が必要です。
この4つの認証keyが必要になります。
認証keyの取得についてはこちらのページを参照してください。
それではやっていきましょう。
from requests_oauthlib import OAuth1Session
import json
import random
CK = '*******************' # Consumer Key
CS = '*******************' # Consumer Secret
AT = '*******************' # Access Token
TS = '*******************' # Access Token Secert
url = "https://api.twitter.com/1.1/statuses/update.json"
params = {"status": "Hello,world!"}
twitter = OAuth1Session(CK, CS, AT, TS)
req = twitter.post(url,params = params)
if req.status_code == 200:
print("OK")
else:
print("Error: %d" % req.status_code)