set setting reset

脂肪と糖にはたらくやつ

powershell で X-ASPNET-VERSION ヘッダを削除する

サーバ全体で無効化する方法がないか調べてみたところ msdn ブログがヒットしました。

MSDN Blogs

方法は 2 種類あって、web.config に追加する方法と、サーバレベルでサーバ変数を利用した rewrite を行う方法があるようです。
ただし、後者は ヘッダそのものではなく、ヘッダの値を隠蔽 するというものになっています。

web.config での方法

以下の 3 行をトップレベルの web.config に追記します。

  <system.web>
      <httpRuntime enableVersionHeader="false" />
  </system.web>

または下記コマンドを実行します。

c:\windows\system32\inetsrv\appcmd.exe set config -section:system.web/httpRuntime -enableVersionHeader:false /commit:webroot /clr:4

.NET2 の場合は /clr:2 とします。
すると ROOT である C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\Web.config に上記内容が追加されます。

IISフォーラム先生ありがとうございます。
System.Web in Applicationhost.config not working anymore (IIS8.5) : The Official Microsoft IIS Forums

applicationHost.config での方法

IIS 8 からは applicationHost.config での system.web セクションは廃止されたとのこと。

rewrite での方法

Please note that it will not remove the header all together but it will remove the value of it.

f:id:rriifftt:20151027162807p:plain

あまり意味はなさそうですが、とりあえずやってみようということで、サイト内の手順に沿って IIS マネージャから設定したところ、 applicationHost.config に設定が追加されてしまいました。

    <system.webServer>
        <rewrite>
            <allowedServerVariables>
                <add name="RESPONSE_X-ASPNET-VERSION" />
            </allowedServerVariables>
            <outboundRules>
                <rule name="RESPONSE_X-ASPNET-VERSION">
                    <match serverVariable="RESPONSE_X-ASPNET-VERSION" pattern=".+" />
                    <action type="Rewrite" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>

powershell でできないか調べてみたところ、いくつかのコマンドレットを使うとよさそうです。

Get-WebConfigurationProperty
Add-WebConfigurationProperty
Set-WebConfiguration

スクリプトは以下のようになりました。
if 文があるのは無駄に chef で実行されることを想定したのでちょっとだけ冪等性を考えたためです。

# add allowedServerVariables
$asv = Get-WebConfigurationProperty `
       -filter "//rewrite/allowedServerVariables/add"`
       -name name

if ($asv -eq $null)
{
  Add-WebConfigurationProperty `
    -Filter "//rewrite/allowedServerVariables" `
    -PSPath "IIS:\" `
    -Name "Collection" `
    -Value @{name="RESPONSE_X-ASPNET-VERSION"}
}

# add rule
$rule = Get-WebConfigurationProperty `
          -filter "//rewrite/outboundRules/rule[@name='REMOVE_X-ASPNET-VERSION']/match"`
          -name serverVariable

if ($rule -eq $null)
{
  Add-WebConfigurationProperty `
    -Filter "//rewrite/outboundRules" `
    -PSPath "IIS:\" `
    -Name "Collection" `
    -Value @{name="REMOVE_X-ASPNET-VERSION"}

  Set-WebConfiguration `
    -Filter "//rewrite/outboundRules/rule[@name='REMOVE_X-ASPNET-VERSION']/match" `
    -PSPath "IIS:\" `
    -Value @{serverVariable="RESPONSE_X-ASPNET-VERSION";pattern=".+"}
  
  Set-WebConfiguration `
    -Filter "//rewrite/outboundRules/rule[@name='REMOVE_X-ASPNET-VERSION']/action" `
    -PSPath "IIS:\" `
    -Value @{type="Rewrite"}
}

ていうか、カスタムエラーページのハンドリングをちゃんとしないと。。。

ubuntu に vagrant 環境をつくる

余った PC に ubuntu-mate をインストールしたのでついでに vagrant 環境を作ってみました。

環境

PC OS
thinkpad X1 ubuntu 15.04

VT-X の有効化

BIOS から VT-X を有効化します。 thinkpad X1 の BIOS 起動手順はこちら

Security -> Virtualization -> Intel VT に進み、Intel Virtualization TechnologyEnabled にして再起動します。

Virtual Box のインストール

普通に公式から deb パッケージをインストールしただけだと不足パッケージがあるようで、仮想マシンがうまく動作しませんでした。
冒頭で紹介させていただいたサイトに記載のリポジトリを追加して apt-get します。

sudo echo "deb http://download.virtualbox.org/virtualbox/debian raring contrib" > /etc/apt/sources.list
sudo wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -
sudo apt-get update
sudo apt-get install virtualbox

vagrant のインストール

公式サイト から deb パッケージをダウンロードしてインストールします。

mkdir ~/src
cd ~/src
wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_i686.deb
sudo dpkg --install vagrant_1.7.2_i686.deb

仮想環境を起動する

作業用ディレクトリを作成して、その中で作業します。 今回は公式の centos/7 を利用します。

mkdir -p ~/vagrant/centos7
cd ~/vagrant/centos7
vagrant init centos/7

init 完了後、作成された VagrantFile を1行だけ編集します。

# 29行目をコメントアウト
config.vm.network "private_network", ip: "192.168.33.10"

新しめの vagrant コマンドでは公式の box ならば(?) vagrant up のみでダウンロードから始まるので vagrant box add しなくていいみたいです。

vagrant up --provier virtualbox

--provider virtualbox はなくてもOKでした。

その後、vagrant 起動中に自動で yum update が実行され、host / guest 間でのファイル共有のための rsync フォルダが作成され、そのまま centos が起動しました。

box にも追加されています。

$  vagrant box list
centos/7             (virtualbox, 1509.01)

ssh ログインしてバージョンを確認してみます。

$  vagrant ssh
[vagrant@localhost ~]$ cat /etc/centos-release
CentOS Linux release 7.1.1503 (Core)

ログインできました^^


こちらを参考にさせていただきました。 Ubuntu 15.04にVirtualbox、Vagrantをインストール

postgresql で trigger とその trigger が動作するテーブルの一覧を取得する

SELECT event_object_schema,
       event_object_table,
       trigger_schema,
       trigger_name
FROM information_schema.triggers

結果

 event_object_schema |     event_object_table      | trigger_schema |               trigger_name
---------------------+-----------------------------+----------------+-------------------------------------------
 schema              | user_table                  | schema         | user_trigger

* だと action_timingevent_manipulation も取得できます。information_schema 便利です。

\d information_schema.triggers
                     View "information_schema.triggers"
           Column           |                Type                | Modifiers
----------------------------+------------------------------------+-----------
 trigger_catalog            | information_schema.sql_identifier  |
 trigger_schema             | information_schema.sql_identifier  |
 trigger_name               | information_schema.sql_identifier  |
 event_manipulation         | information_schema.character_data  |
 event_object_catalog       | information_schema.sql_identifier  |
 event_object_schema        | information_schema.sql_identifier  |
 event_object_table         | information_schema.sql_identifier  |
 action_order               | information_schema.cardinal_number |
 action_condition           | information_schema.character_data  |
 action_statement           | information_schema.character_data  |
 action_orientation         | information_schema.character_data  |
 action_timing              | information_schema.character_data  |
 action_reference_old_table | information_schema.sql_identifier  |
 action_reference_new_table | information_schema.sql_identifier  |
 action_reference_old_row   | information_schema.sql_identifier  |
 action_reference_new_row   | information_schema.sql_identifier  |
 created                    | information_schema.time_stamp      |

vpc endpoint から s3 へのアクセス制御 (bucket policy)

公式ドキュメント

  • vpc endpoint を作成時にできる vpce-id を使って許可、拒否ができる
  • 他のアカウント / vpc に対しても制御可能

記載された vpceIPアドレスのみ許可する設定例です。

{
    "Version": "2012-10-17",
    "Id": "vpce-restrict",
    "Statement": [{
        "Sid": "Allow-VPCE",
        "Action": "s3:*",
        "Principal": {
            "AWS": "*"
        },
        "Effect": "Allow",
        "Resource": [
            "arn:aws:s3:::bucket-name*",
            "arn:aws:s3:::bucket-name/*",
        ],
        "Condition": {
            "StringEquals": {
                "aws:sourceVpce": [
                    "vpce-********"
                ]
            }
        }
    }, {
        "Sid": "IPAddress-restrict",
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:*",
        "Resource": [
            "arn:aws:s3:::bucket-name*",
            "arn:aws:s3:::bucket-name/*",
        ],
        "Condition": {
            "IpAddress": {
                "aws:SourceIp": [
                    "***.***.***.***/**"
                ]
            }
        }
    }]
}

この場合、StringEquals だと許可、 StringNotEquals だと拒否になりますので、うまいぐあいに使い分けができます。
というか、これに気づかなくてハマってしまった・・・

apache で URL を case insensitive にする

↓ の状態で

# ls /var/www/html/healthcheck.html
/var/www/html/healthcheck.html

↓ のように 404 となったので

[Fri Oct 16 13:59:53 2015] [error] [client ***.***.***.***] File does not exist: /var/www/html/HealthCheck.html

産業追記して reload

LoadModule speling_module modules/mod_speling.so
CheckSpelling on
CheckCaseOnly on

そして HealthCheck.html でアクセスすると

***.***.***.*** - - [16/Oct/2015:13:58:47 +0900] "GET /healthcheck.html HTTP/1.1" 200

200 OK となりました

stackoverflow.com

サポートケースを作成するための iam ポリシー

どうやって制御するんだろうと調べていたら iam policy の中にありました。

IAM > Policies > AWSSupportAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "support:*"
            ],
            "Resource": "*"
        }
    ]
}

というだけの記事でした。

redis-py で expire が付与されていない key を削除する

メモリが逼迫してきた redis で、本来存在しないはずの expire が付与されていない key を削除することになったので記録として。
key は session id として使われています。

環境

  • 作業環境

  • サーバ環境

    • centos6.4
    • redis 2.6.14

前提

  • session id は英数小文字と数字が含まれていて、規則性がない
    こんなの => csodes5b5wenrvn0llbfcmme

使ったもの

インストールは pip で一発です。

スクリプトの概要

  • 小文字と数字のランダムな文字列を生成してワイルドカードで keys をたたく

    • keys * だと負荷がちょっとこわかったため、ちょっとずつやりたかったのです
      *ランダム文字列の生成は こちら のものを使わせていただきました。
  • DELETE_COUNT の数だけ削除するが、keys コマンドでひっぱってくる数にバラつきがあるので、正確ではない

    • 現在の keys - expires で TTL のない keys 数を取得
    • TTL のない keys 数から DELETE_COUNT を引き、削除後の TTL のない keys 数を取得
    • keys で取得した key を 1 つずつ ttl コマンドで expire が付与されていないことをチェックし、なければ削除する
    • これを 削除後の TTL のない keys 数 まで繰り返す
      • DELETE 数を正確にするには削除コマンド実行前に check_delete_limit をするとよいでしょう
      • ただし、その場合はコマンド発行回数が増加するので注意(infoだけなので速いのは速いですが)

スクリプト

#!/usr/bin/env/python
# -*- coding: utf-8 -*-

import os, sys, string, random, time
import redis
from logging import getLogger
import logging

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = getLogger(os.path.basename(__file__))

# configration
HOST = sys.argv[1]
PORT = 6379
DB = 0
RANDOM_COUNT = 3
DELETE_COUNT = 200000

def connect_redis(h=HOST, p=PORT, d=DB):
    try:
        r = redis.StrictRedis(host=h, port=p, db=d)
    except redis.ConnectionError:
        logger.error("failed to connect %s" % HOST)
        logger.exception(e)
        sys.exit(1)
    except Exception, e:
        logger.exception(e)
        sys.exit(2)
    finally:
        return r

def get_redis_info(arg):
    r = connect_redis()
    info = r.info(arg)
    return info

def check_delete_limit(DB,DELETE_LIMIT):
    i = get_redis_info("keyspace")
    if i.has_key("db%s" % DB) == True:
        d = i.get("db%s" % DB)
        k = d.get("keys") - d.get("expires")
        if k <= DELETE_LIMIT:
            logger.info("limit arrived. stop process.")
            sys.exit(0)

def get_delete_limit(DB,DELETE_COUNT):
    i = get_redis_info("keyspace")
    if i.has_key("db%s" % DB) == True:
        d = i.get("db%s" % DB)
        k = d.get("keys") - d.get("expires")
        if k >= DELETE_COUNT:
            k -= DELETE_COUNT
            return k
        elif k == DELETE_COUNT:
            return k
        else:
            logger.info("nothing to delete any more.")
            sys.exit(0)

def gen_rand_str(length, chars=None):
    if chars is None:
        chars = string.digits + string.lowercase
    return ''.join([random.choice(chars) for i in range(length)])

def delete_session_keys(HOST,PORT,DB,RANDOM_COUNT,DELETE_LIMIT):
    sample_key = "*" + gen_rand_str(RANDOM_COUNT) + '*'
    # get sample keys
    r = connect_redis()
    keys = r.keys(sample_key)
    if keys is None:
        logger.info("not found expire keys from sample key.")

    for k in keys:
        # skip key "RedisSessionStateStore:LockedSessions"
        if "LockedSessions" in k:
            logger.debug("skip delete. key => %s" % k)
            continue

        # check ttl each key
        logger.debug("ttl start")
        ttl = r.ttl(k)
        logger.debug("ttl end")
        if ttl == -1:
            # delete key
            r.delete(k)
            logger.info("delete key => %s" % k)
            time.sleep(0.1)
        else:
            logger.debug("this key has ttl. key  => %s , ttl => %s" % (k, ttl))

if __name__ == '__main__':
    DELETE_LIMIT = get_delete_limit(DB,DELETE_COUNT)
    while True:
        check_delete_limit(DB, DELETE_LIMIT)
        delete_session_keys(HOST,PORT,DB,RANDOM_COUNT,DELETE_LIMIT)

実行

$  python delete_session_keys.py redisのIPアドレスなど
delete key => s5zhfytghgdq5bjmkaaqhkf2
delete key => sedhrhftw13jblpawgbvrh4k
delete key => s4rewrbhex04fdujbytp3rw5
delete key => skwcm0jigx2arwqwf52sj21n
this key has ttl. key  => uxxprmpwyjpxqeots1q334lo , ttl => 10503
this key has ttl. key  => djfw2py52croafz4gigun0l0 , ttl => 3606

以上です。