2013年7月20日土曜日

Cyberduck から S3 へアップロード時のパーミッション

Cyberduck から S3 へファイルをアップロードした際に、自動的に Everyone へ閲覧許可が設定されてしまい、Bucket Policies でアクセス制限をコントロールしたい場合に、不便に感じていました。

例えば Bucket Policies で、特定のIPアドレスからのみアクセスを許可していても、ファイルに Everyone の閲覧許可がされていると、そちらが優先されてしまいます。

アップロード時のパーミッション設定が、Cyberduck の環境設定には見つからなかったのですが、ドキュメントに説明がありました。
$ defaults write ch.sudo.cyberduck s3.bucket.acl.default private

上記の設定をすることで、Everyone への閲覧許可が自動的に設定されなくなります。

2013年1月12日土曜日

EC2 のインスタンスで chef-client が UndefinedConversionError

EC2 のインスタンスに chef-client をインストールして使っていたのですが、user-data を設定したインスタンスだけ、chef-client がエラーになってしまいます。

エラーメッセージは以下のようなもの。
FATAL: Encoding::UndefinedConversionError: "\x8B" from ASCII-8BIT to UTF-8

確認してみたところ、json への変換部分でエラーになっている模様。
lib/chef/node.rb

    # Serialize this object as a hash
    def to_json(*a)
      result = {
        "name" => name,
        "chef_environment" => chef_environment,
        'json_class' => self.class.name,
        "automatic" => automatic_attrs,
        "normal" => normal_attrs,
        "chef_type" => "node",
        "default" => default_attrs,
        "override" => override_attrs,
        #Render correctly for run_list items so malformed json does not result
        "run_list" => run_list.run_list.map { |item| item.to_s }
      }
      result["_rev"] = couchdb_rev if couchdb_rev
      result.to_json(*a)
    end
result の中身で "\x8B" が入っているところを探すと、userdata の部分にありました。
{ ... "userdata"=>"\x1F\x8B ... }

どうやら、user-data を作成する際に圧縮をしていたため、userdata にバイナリのデータが入っていたことが原因のようです。

CloudInit のページを参考に、user-data を圧縮していたのですが、16KB のサイズ制限を超えているわけでもないので、圧縮しないことで回避することにしました。

user-data の内容は、Node の Attribute に含まれていて、chef-server で Attribute を表示するためなどの目的で、json へ変換しているのですね。

2012年12月1日土曜日

Amazon Linux で起動時にホスト名を設定する

Amazon Linux で起動時にホスト名を設定したいと思い、調べてみたところ CloudInit というものがあることが分かりました。

CloudInit とは、cloud-platform(EC2 や Openstack など)の Ubuntu でインスタンスの初期化を扱うためのものです。Amazon Linux では、CloudInit が使用可能になっているんですね。

サンプルを参考に、以下の内容をインスタンス起動時に渡してみましたが、うまくいきません。

cloudinit: /doc/examples/cloud-config.txt
$ cat cloud-config.txt
--------------------------------------
#cloud-config
hostname: myhostname
--------------------------------------
$ ec2-run-instances ami-4e6cd34f -g [GROUP] -k [KEYPAIR] -t [INSTANCE_TYPE] -f cloud-config.txt

Ubuntu の AMI を使用すると、うまくホスト名が設定できるので もう少し調べてみたところ、このフォーラムにたどり着きました。

Amazon AMI w/ #cloud-config - struggling with the basics
For your question as to why setting the hostname isn't working, it is because the version of cloud-init found in the Amazon Linux AMI does not currently support those options.

今の Amazon Linux では、hostname のオプションは使えないそう。フォーラムには、別の方法での設定例があって、以下の方法でも実現できるんですね。
#cloud-config
runcmd:
 - [ echo, 'Setting custom hostname' ]
 - [ sed, -i, 's/^HOSTNAME=[a-zA-Z0-9\.\-]*$/HOSTNAME=MyName/g', /etc/sysconfig/network ]
 - [ hostname, 'MyName' ]

2012年9月9日日曜日

Amazon S3 上の Web サイトへのアクセス制限

Amazon S3 上のバケットは、Web サイトとして設定することができます。

Hosting Websites on Amazon S3

また、Bucket Policies を使用することで、アクセスの制限をすることも可能です。例えば、特定のIPアドレスからのみアクセスを許可・拒否したい場合は、以下のように設定します。

Example Cases for Amazon S3 Bucket Policies
{
    "Version": "2008-10-17",
    "Id": "S3PolicyId1",
    "Statement": [
        {
            "Sid": "IPAllow",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::bucket/*",
            "Condition" : {
                "IpAddress" : {
                    "aws:SourceIp": "192.168.143.0/24"
                },
                "NotIpAddress" : {
                    "aws:SourceIp": "192.168.143.188/32"
                }
            }
        }
    ]
}
この例では、192.168.143.* からのアクセスを許可しますが、例外として 192.168.143.188 からの アクセスは拒否されます。

各要素の説明は、Element Descriptions に記載されています。

2012年9月1日土曜日

Auto Scaling から起動するインスタンスに Security Group を設定する

Auto Scaling を使ってインスタンスを起動する場合、Security Group を指定しないと default が設定されます。

Security Group を指定したい場合は、Launch Configuration を作成する時に group を設定します。
$ as-create-launch-config --help
…
   --group VALUE1,VALUE2,VALUE3...
       Security groups with which to associate the Amazon EC2 instances. Note
       that Amazon VPC security groups and Amazon EC2 security groups are
       mutually exclusive and can't be used together. Either all group names or
       all group ids are acceptable, but not both.

Auto Scaling Developer Guide には詳しく書いてなくて、色々調べた後に、コマンドのヘルプに書いてあることを知った。最初にココを見るべきだった。

command line tool のオプションは API と対応しているから、API Reference を参照して、まずオプションの有無を調べてみるのもいいかもしれない。

Auto Scaling API Reference - CreateLaunchConfiguration
SecurityGroups.member.N

The names of the security groups with which to associate Amazon EC2 or Amazon VPC instances. Specify Amazon EC2 security groups using security group names, such as websrv. Specify Amazon VPC security groups using security group IDs, such as sg-12345678. 

2012年8月26日日曜日

Amazon ELB からのみアクセスを許可する Security Group の設定

ELB の配下に設置しているインスタンスは、セキュリティを考慮すると ELB からのみアクセスを許可するようにしたいですね(管理用のアクセスは別として)。

ELB に用意されている特別な Security Group を使って、これを実現できます。

まず最初に ELB の API Tools を使用して、Source Security Group の名前を確認します。
$ elb-describe-lbs [LoadBalancerName] --show-long --headers
... ,"{owner-alias=example-elb,group-name=example-elb-sg}", ...
次に ELB 配下のインスタンスが所属する Security Group に、確認した名前を設定します。
$ ec2-authorize [group_name] -u example-elb -o example-elb-sg
もし、より制限の低いルールが設定されていた場合は、そのルールを削除します。
(以下の例は、tcp 80番へのアクセスを全て許可するルールが設定されていた場合)
$ ec2-revoke [group_name] -P tcp -p 80 -s 0.0.0.0/0

2012年8月5日日曜日

boto を使って Amazon S3 へのアップロード

boto を使って S3 へアップロードする時、東京リージョンなど、US Standard 以外のリージョンのバケットへのアップロードが失敗するという事象に遭遇しました。エラー内容は Broken pipe 。
>>> from boto.s3.connection import S3Connection
>>> conn = S3Connection()
>>> bucket = conn.get_bucket('mybucket')
>>> k = Key(bucket)
>>> k.set_contents_from_filename('myfile')
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
...
    857             raise BotoServerError(response.status, response.reason, body)
    858         elif e:
--> 859             raise e
    860         else:
    861             msg = 'Please report this exception as a Boto Issue!'

error: [Errno 32] Broken pipe
しかも、50KBぐらいのファイルだと問題ないのに、500KBくらいになるとダメ。東京リージョンのサーバから実行してるから、US の方が距離的に遠いし、時間がかかってタイムアウトとは考えにくい。しかも、500KBってそんなに大きいサイズではないし。 

同じ事象で困っている人がいて、以下のページが参考になりました。

 broken pipe error, non US-Standard region

解決方法としては、Connection を作成する時に、host を指定すること。
>>> from boto.s3.connection import S3Connection
>>> conn = S3Connection(host='s3-ap-northeast-1.amazonaws.com')

指定するエンドポイントは、ここから参照できます。

Amazon Web Services Glossary - Regions and Endpoints