やったもん勝ち

主にプログラミングのこと。生産性向上の某とかも。

python36で別のホストのmysqlに接続する。

環境

接続元

接続先

準備

MySQLサーバ

事前にDBとテーブルを作っておきます。 ユーザー、パスワードとかは特に作成せず、起動したてのままでOKです。 SQLは適当に作成します。

mysql > CREATE DATABASE testdb;
mysql > USE testdb;
mysql > CREATE TABLE employee(name varchar(20), age int, job varchar(20), salary int);
mysql > INSERT INTO employee (name, age, job, salary) VALUES ('tanaka',20,'engineer',400);
mysql > GRANT ALL PRIVIEGES ON *.* TO root@aaa.aaa.aaa.aaa;

AWS

セキュリティグループをMySQLのport3306を開けておいてください。

python

sudo pip-3.6 install pymysqlが必要です。

実装コード

import pymysql

db = pymysql.connect(
    host='xxx.xxxx.xxx.xxx',
    user='root',
    password='',
    db='testdb',
    charset='utf8',
    cursorclass=pymysql.cursors.DictCursor,
)


cur = db.cursor()
sql = "select * from employee"
cur.execute(sql)
employees = cur.fetchall()
print(employees)
[{'name': 'tanaka', 'age': 20, 'job': 'engineer', 'salary': 400}]

と、listになって返ってくるので、あとは煮るなり焼くなり好きにしてです。

sudoers.dファイルでコマンドのオプションはどこまで制限できるのか

sudoers.dで指定する、許可されるコマンドは、どこまで寛容なのか。 一字一句そのコマンドじゃなきゃいけないのか。 それとも、オプションだとかパスはよしなに指定させてくれるのか。 検証する。

# rootになっておく  
$ sudo su -
# まずは、現在のユーザー一覧を確認
$ ll /home/
合計 2
drwx------. 5 vagrant   vagrant   4096  1月 12 10:52 vagrant

# userを追加
$ useradd test-user

# ユーザー追加されたのを確認
$ ll /home

# パスワードを設定
$ passwd test-user

# test-userにログイン
$ su test-user

# sudoが必要なコマンドを実行してみます
$ yum install -y git
Loaded plugins: fastestmirror
You need to be root to perform this command.

# rootに戻ります
$ exit

# sudoers権限をいじります
$ visudo

# 下記を追加
# test-userに root権限でのyumの使用を許可します。
# /bin/yumじゃなくていいのかな?
# yumのオプションは何でも使えるのかな?
test-user   ALL=(root)     yum


編集を抜けると
visudo: >>> /etc/sudoers: syntax error near line 121 <<<
What now?
Options are:
  (e)dit sudoers file again
  e(x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)

What now? e
と、
Qをやってしまったが最後、二度とsudoを使えなくなってしまいました。
rootにログインすることも叶わなかった。。。
VM立ち上げ直した。。。


$ visudo 
# 以下のように追加
test-user    ALL=(root)      NOPASSWD: /bin/yum
:wqでちゃんと抜けられました。

# test-userにログイン
$ su test-user

# 権限を確かめる
$ sudo yum install -y tig
->OK! yumのコマンドなら全部使えるっぽい。
権限をもう少し絞ってみます。

# rootになる
$ exit

$ visudo
# 以下の設定に変更
test-user    ALL=(root)      NOPASSWD: /bin/yum install -y tig

# test-userになる
$ su test-usre


# 確かめる
$ sudo yum install -y tig
出来ました。

# 他のコマンドは使えない?
$ sudo yum install -y tree
ダメでした。

# どこまで使えるのか
$ visudo
# 次のように設定
test-user    ALL=(root)      NOPASSWD: /bin/yum install
#これでyum installなら何でも使えるかな?

# 試してみます
$ su test-user
$ sudo yum install -y tree
↓
なんかパスワード求められた。。。
なんかダメみたいだ。
なので、方法としては、
完全に決め打ちのコマンドを一つずつ書くか、
オプションは指定しないで、実行ファイルのパスだけを書くか。
のどちらかっぽい。
コマンドの処理の仕方とかもっと深く知れば「はいはい、そりゃそうだ」って言えるようになる気がする。

40秒で支度しな!AWSのEC2にpython36で最速でflask実行環境を作成する

AWSのEC2、amazon linuxです。

$ sudo yum install -y python36
$ sudo pip-3.6 install flask
$ vi ~/hello.py
# 以下の内容で作成作成
from flask import Flask
app = Flask(__name__)
 
@app.route('/')
def hello():
    return 'Hello World!'
 
if __name__ == '__main__':
    app.run(host='0.0.0.0')
$ python36 hello.py
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

localhost:5000をcurlしてみる。

$ curl http://127.0.0.1:5000
127.0.0.1 - - [20/Feb/2018 16:20:52] "GET / HTTP/1.1" 200 -
Hello World!

いい感じです。

これをブラウザから確認したい。
xxx.xxx.xxx.xxx:5000

Hello World!

が表示されました。

当然セキュリティグループから、アクセスしようとしているIPの5000番ポートを開けておく必要がありやす。

どうでしょう。40秒で支度できましたか?
f:id:benzenetarou:20180221014836j:plain

pythonのboto3でのエラーハンドリング

問題

pythonのboto3で以下のようなコードを書いていて、

try:
    hoge()
except:
    print("error")

flake8にdo not use bare except'と怒られた。
pythonのエラーの書き方をちゃんと調べてみると、エラーの種類をexceptで指定しておかないと、エラーメッセージを表示する際に、実際のエラーの原因とは違うエラーメッセージを表示してしまい、バグのもとになるとのことで、かっちり書くことにしてみた。

ここで言うエラーの種類は、ZeroDivisionErrorとかNameErrorとかValueErrorとかだそうだ。

このhoge()で発生しているエラーがなんの種類のエラーなのか調べてみる。

try:
    hoge()
except:
    print(sys.exc_info())

をやってみると、

(<class 'botocore.errorfactory.LoadBalancerNotFoundException'>, LoadBalancerNotFoundException("An error occurred (LoadBalancerNotFound) when calling the DescribeLoadBalancers operation: Loa
d balancers '[fa]' not found",), <traceback object at 0x7f1eda94c708>)

と返ってくる。 なるほどと思い、

try:
    hoge()
except LoadBalancerNotFoundException:
    print("catch!")

と書くと、うまくいかぬ。 except botocore.errorfactory.LoadBalancerNotFoundExceptionとしてみても、だめ。

During handling of the above exception, another exception occurred:
.
.
.
    except botocore.errorfactory.LoadBalancerNotFoundException:
NameError: name 'botocore' is not defined

となる。さらにエラーが呼び出されてしまう。 どうやってエラーの種類を調べればいいのかは、結局分からなかったが、boto3のエラーハンドリングは以下のように書けるようだ。
stack overflowより( amazon web services - Boto3, python and how to handle errors - Stack Overflow

import boto3
from botocore.exceptions import ClientError

try:
    iam = boto3.client('iam')
    user = iam.create_user(UserName='fred')
    print "Created user: %s" % user
except ClientError as e:
    if e.response['Error']['Code'] == 'EntityAlreadyExists':
        print "User already exists"
    else:
        print "Unexpected error: %s" % e

Clientなのかぁ…解決。

知らないふり

ただ、この答えを書いてくれてる人はどうやってこれを探したんだろうか。。。 と、リファレンスも貼ってくれている。

Upgrading to Clients — botocore 1.8.34 documentation

なるほど、こういうときはライブラリのリファレンスのエラーハンドリングの章を参照すればいいのだな!

いやまて、botocoreってなんだ?boto3がラッパーしているライブラリ??
→ boto3のcoreだそうだ。

しかし、boto3のリファレンスから知らないふりして探そうとしてみても、先程のページが見つけられない。
errorとかで検索かけてみても、たくさん引っかかりすぎる。。。
う〜ん、だめだ。
一旦、これは寝かしておこう。。。

sudo rm -rf で削除できないファイルのパーミッション設定

背景

想定するのは、次のようなケース

普通にrootユーザーから削除しようと思ったら、
# rm -rf /tmp/mydir/*
を実行すればいいだけです。 と、いうことは、sudo権限を持っている一般ユーザーならば、
$ sudo rm -rf /tmp/mydir/*
とすればいいのではないか! となるのが、素直な発想。
しかし、どうやらrmに関してはそうもいかないらしい。

最終的には、mydirのパーミッションを777に変更して、
$ sudo rm -rf /tmp/mydir/*
と実行して、その後にまたパーミッションを700に戻すという愚直な方法で解決しました。

以下、動作確認の備忘録です。

環境

MacOS 10.11.6 El Capitan
Vagrant 2.0.1
CentOS 7.2.1511

動作確認

mydirの作成

まずは、mydirを作成します。 rootになります。 sudo su - mydirをはじめとするファイル群をつくります。

$ mkdir /tmp/mydir
$ mkdir /tmp/mydir/aaa /tmp/mydir/bbb
$ touch /tmp/mydir/aaa/c /tmp/mydir/aaa/d

現在のパーミッションを確認します。

$ yum install -y tree
$ tree /tmp/mydir/ -pug
mydir/
├── [drwxr-xr-x root     root    ]  aaa
│   ├── [-rw-r--r-- root     root    ]  c
│   └── [-rw-r--r-- root     root    ]  d
└── [drwxr-xr-x root     root    ]  bbb

パーミッションを変更します。
$ chmod 700 /tmp/mydir/ --recursive
確認します。

$ tree /tmp/mydir/ -pug
/tmp/mydir/
├── [drwx------ root     root    ]  aaa
│   ├── [-rwx------ root     root    ]  c
│   └── [-rwx------ root     root    ]  d
└── [drwx------ root     root    ]  bbb```

期待通り、再帰的にパーミションの変更ができました。 mydirのパーミッションも確認します。

$ ls -l /tmp/
total 0
drwx------ 4 root root 26 Jan 18 04:06 mydir

そもそもこのディレクトリに対して、rootは期待する動作を実行できるのでしょうか。

$ rm -rf /tmp/mydir/*
$ tree /tmp/mydir -pug
/tmp/mydir

0 directories, 0 files

これはOKですね。 もう一度作り直します。

$ mkdir /tmp/mydir/aaa /tmp/mydir/bbb
$ touch /tmp/mydir/aaa/c /tmp/mydir/aaa/d
$ chmod 700 /tmp/mydir/ --recursive

ユーザー作成 そのままvagrantユーザーで行っても挙動は同じだと思いますが、新しく作ってまっさらなアカウントから検証します。

$ useradd test-user
$ passwd test-user

sudo権限を付与する /etc/sudoers.dを最近覚えた!
$ visudo -f /etc/sudoers.d/test-user
以下のように設定
test-user ALL=(ALL) NOPASSWD: ALL
正常に終了できました。

test-userで作業
$ su test-user
早速削除をやってみます。

$ sudo rm -rf /tmp/mydir/*
$ sudo tree /tmp/mydir/ -pug
/tmp/mydir/
├── [drwx------ root     root    ]  aaa
│   ├── [-rwx------ root     root    ]  c
│   └── [-rwx------ root     root    ]  d
└── [drwx------ root     root    ]  bbb

2 directories, 2 files

ガッツリ残っている。 やはり、一般ユーザーからは700のrootがownerのファイルは削除できないようです。

解決策

mydirのパーミッションを変更します。

$ sudo chmod 777 /tmp/mydir/
$ ls -l /tmp/
total 0
drwxrwxrwx 4 root root 26 Jan 18 04:17 mydir

mydirのパーミッションが変更されました。 mydir以下のパーミッションは変わっていません。

$ sudo tree /tmp/mydir/ -pug
/tmp/mydir/
├── [drwx------ root     root    ]  aaa
│   ├── [-rwx------ root     root    ]  c
│   └── [-rwx------ root     root    ]  d
└── [drwx------ root     root    ]  bbb

2 directories, 2 files

と、これでrmを実行してみます。

$ sudo rm -rf /tmp/mydir/*
$ sudo tree /tmp/mydir/ -pug
/tmp/mydir/

0 directories, 0 files

これでめでたく削除できました〜 あとはmydirのパーミッションを戻しておしまいですね
$ sudo chmod 700 /tmp/mydir

本当はソースとか読んで、「はいはい、そういう仕様ね」ってやりたいんですが、それはまたの機会にしておきます。

visudoでsudoersを変更して、sudo権限を設定する

zabbixユーザーとsudo等々の権限周りでハマりました。

備忘録として開発環境で動作確認したのを残しておきます。

環境

MacOS High Sierra 10.13.1
Vagrant 2.0.1
CentOS 7.2.1511

かんたんなsudoersの知識

sudoとかの権限を設定しているのは、
/etc/sudoersというファイルです。
ちなみに/etcの下にsudoのつくファイルは以下でした。
$ ls -l /etc/ | grep sudo

-rw-r-----.  1 root root   1786 Sep 25  2012 sudo.conf
-r--r-----   1 root root   4191 Jan 16 17:27 sudoers
drwxr-x---.  2 root root     20 Jan 27  2016 sudoers.d
-rw-r-----.  1 root root   3181 Jul 25  2013 sudo-ldap.conf

よく見ると、sudoersは440で書き込みできませんね。
普通には書き込みができないのがこのsudoersファイルです。
普通に書き込みしてしまって、シンタックスエラーがある状態で保存してしまうと、二度とrootを使えなくなったりする危険なファイルです。
なので、sudoersを編集する際にはシンタックスチェックをする、安全なvisudoというコマンドを使って編集をしていきます。

一般ユーザーを作成します

rootになっておく
$ sudo su -

まずは、現在のユーザー一覧を確認
$ ls -l /home/

合計 2
drwx------. 5 vagrant   vagrant   4096  1月 12 10:52 vagrant

vagrantユーザーだけでした。

userを追加
$ useradd test-user

ユーザー追加されたのを確認
$ ll /home

total 0
drwx------  2 test-user test-user 59 Jan 16 17:01 test-user
drwx------. 3 vagrant   vagrant   90 Jan 27  2016 vagrant

test-userが作成されました。

test-userのパスワードを設定(一応)
$ passwd test-user

Changing password for user test-user.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

パスワード設定完了。

権限確認

test-userにログイン
$ su test-user
$ whoami
test-user
test-userにログインできました。

sudoが必要なコマンドを実行してみます
$ yum install -y git

Loaded plugins: fastestmirror
You need to be root to perform this command.

rootじゃないとできないみたいですね。

sudoをつけてみます。
$ sudo yum install -y git

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test-user:

やはり、パスワードがないとだめですね〜
これは当然ながらtest-userを作った管理者は知っていますが。。。

sudoers権限をいじります

rootに戻ります
$ exit

sudoersをいじります
$ visudo
以下の行をを一番下に追加します。
test-user ALL=(root) yum
test-userに root権限でのyumの使用を許可します。という意味です。
/bin/yumじゃなくていいのかな?
yumのオプションは何でも使えるのかな?
試しにやってみます。

編集を抜けると

visudo: >>> /etc/sudoers: syntax error near line 121 <<<
What now?
Options are:
  (e)dit sudoers file again
  e(x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)

What now? 

と、
何も考えずにQをやってしまったが最後、二度とsudoを使えなくなってしまいました。
rootにログインすることも叶わなかった。。。
VM立ち上げ直した。。。

これ本番でやったら偉いことになります。
めのまえがまっくらになった!状態になります。
所持金がなくなります。
そんな事故がないために、単にviだけでは編集できず、専用のsyntaxチェックをしてくれるvisudoを使うんですね~

さて、もう一度vagranをdestroyしてupして、visudoまでの操作を行います。

$ visudo

以下のように追加
test-user ALL=(root) NOPASSWD: /bin/yum
:wqでちゃんと正常に抜けられました。

動作確認

test-userにログイン
$ su test-user

権限を確かめる
$ sudo yum install -y git
->OK!
$ sudo yum history
→正常に表示されます。
yumのコマンドなら全部使えるっぽい。
権限をもう少し絞ってみます。

権限変更

とりあえず/bin/yumが使えることがわかりました。
オプション等々、どこまでsudoersファイルで制限できるのでしょうか。
試してみます。

rootになる
$ exit

$ visudo 一番下の行を以下の設定に変更 test-user ALL=(root) NOPASSWD: /bin/yum install -y tig

test-userになる
$ su test-user

確かめる
$ sudo yum install -y tig
出来ました。

他のコマンドは使えないのか確認します。
$ sudo yum install -y tree
ダメでした。パスワードを求められてしまいます。

全部決め打ちでroot権限を与えることもできるようですね。

どこまで制限できるのか

検証してみます。
$ visudo
次のように設定
test-user ALL=(root) NOPASSWD: /bin/yum install
期待する動作は、これでyum installなら何でも使えるけど、他のyumコマンドは使えない挙動!

試してみます
$ su test-user
$ sudo yum install -y tree

なんかパスワード求められた。。。
なんかダメみたいだ。

なので、方法としては、
完全に決め打ちのコマンドを一つずつ書くか、
オプションは指定しないで、実行ファイルのパスだけを書くか。
のどちらかっぽい。
コマンドの処理の仕方とかもっと深く知れば「はいはい、そりゃそうだ」って言えるようになる気がする。
けど今は一つ一つ動作を検証してみて、こういう挙動なのだとわかりました!頑張った!

あと実はファイルパスとディレクトリの権限等のこともハマったので、次回整理してまとめておきたいです。

python3でstrからdictに変換する

import ast

str = "{'name':'Taro', 'hieght':170}"

type(str)
  => <class 'str'>

dict = ast.literal_eval(str)

type(dict)
  => <class 'dict'>

他の記事でast.literal_dict(str) となっていたのですが、
AttributeError: module 'ast' has no attribute 'literal_dict'
とエラーになってしまったので、調べてみたら、literal_dictではなく、literal_evalでした。

参考ドキュメント https://docs.python.jp/3/library/ast.html