LoginSignup
1
2

More than 5 years have passed since last update.

1つのロールでホスト毎に同一ユーザーを作成し、それぞれのユーザーにバラバラなパスワードを付けたい

Posted at

例えばこんなhostsファイルがあったとして

hosts
[web]
192.0.2.1
192.0.2.2
192.0.2.3
[db]
192.0.2.4

こんな感じで共通のロールを適用する際にOSユーザーとパスワードも設定したい、ポリシー上パスワードの使い回しは厳禁なので全てユニークにしたい場合の方法

site.yml
---
- hosts: all
  roles:
    - common
   .
   .
   .

lookup pluginの作成

Jinja2で用意されてるフィルタってやつでいい感じにできるのかなと思ったけど探しても見つからなかった。
結局ansibleに用意されているlookup pluginという機能を利用することにした。
元々ansibleにはパスワード用プラグインも用意されているけど、どうも一度生成したパスワードはファイルに書き込んで、二度目以降はそのファイルの中身を参照するようになってて今回の用途には合わないので、既存のプラグインをちょっと改造
元々のコードはpassword.py

改造した部分の抜粋

password-uniq.py
    def run(self, terms, variables, **kwargs):

        ret = []

        for term in terms:
            relpath, params = _parse_parameters(term)

            # get password or create it if file doesn't exist
            path = self._loader.path_dwim(relpath)
            if not os.path.exists(path):
                pathdir = os.path.dirname(path)
                try:
                    makedirs_safe(pathdir, mode=0o700)
                except OSError as e:
                    raise AnsibleError("cannot create the path for the password lookup: %s (error was %s)" % (pathdir, str(e)))

            chars = "".join(getattr(string, c, c) for c in params['chars']).replace('"', '').replace("'", '')
            password = ''.join(random.choice(chars) for _ in range(params['length']))

            if params['encrypt'] is not None:
                salt = self.random_salt()
                content = '%s salt=%s' % (password, salt)
            else:
                content = password
            with open(path, 'a') as f:
                os.chmod(path, 0o600)
                f.write(content + '\n')

            if params['encrypt']:
                password = do_encrypt(password, params['encrypt'], salt=salt)

            ret.append(password)

        return ret

password.pyとの差分

124,125c124,125
<                 chars = "".join(getattr(string, c, c) for c in params['chars']).replace('"', '').replace("'", '')
<                 password = ''.join(random.choice(chars) for _ in range(params['length']))
---
>             chars = "".join(getattr(string, c, c) for c in params['chars']).replace('"', '').replace("'", '')
>             password = ''.join(random.choice(chars) for _ in range(params['length']))
127,134c127,129
<                 if params['encrypt'] is not None:
<                     salt = self.random_salt()
<                     content = '%s salt=%s' % (password, salt)
<                 else:
<                     content = password
<                 with open(path, 'w') as f:
<                     os.chmod(path, 0o600)
<                     f.write(content + '\n')
---
>             if params['encrypt'] is not None:
>                 salt = self.random_salt()
>                 content = '%s salt=%s' % (password, salt)
136,156c131,134
<                 content = open(path).read().rstrip()
<
<                 password = content
<                 salt = None
<
<                 try:
<                     sep = content.rindex(' salt=')
<                 except ValueError:
<                     # No salt
<                     pass
<                 else:
<                     salt = password[sep + len(' salt='):]
<                     password = content[:sep]
<
<                 if params['encrypt'] is not None and salt is None:
<                     # crypt requested, add salt if missing
<                     salt = self.random_salt()
<                     content = '%s salt=%s' % (password, salt)
<                     with open(path, 'w') as f:
<                         os.chmod(path, 0o600)
<                         f.write(content + '\n')
---
>                 content = password
>             with open(path, 'a') as f:
>                 os.chmod(path, 0o600)
>                 f.write(content + '\n')

プラグインで指定したパスに元々ファイルが存在した場合もパスワードを生成してファイルに追記するようにしただけ

これをplaybookのディレクトリにlookup_pluginsってディレクトリに「{{ 任意の名前 }}.py」として放り込んでやると「{{ 任意の名前 }}」で呼び出せる

main.yml
- name: 管理者ユーザー追加
  user: name={{ item.name }} password={{ item.user_pass }}
  with_items:
    - { name: 'admin1', user_pass: "{{ lookup('password-uniq','~/playbook/.pass/user-pass')  }}" }

これを実行するとそれぞれのユーザーのパスワードがユニークになる

TASK [common : 管理者ユーザー追加] *************************************************
changed: [192.0.2.1] => (item={u'name': u'admin1', u'user_pass': u'nyan'})
changed: [192.0.2.2] => (item={u'name': u'admin1', u'user_pass': u'wan'})
changed: [192.0.2.3] => (item={u'name': u'admin1', u'user_pass': u'caa'})
changed: [192.0.2.4] => (item={u'name': u'admin1', u'user_pass': u'chun'})

パスワードはプラグインで指定したファイルに追記されるけど、特にホスト名と紐づけされた形で書かれるわけではないので注意

元々用意されてたパスワードプラグインを改造しただけなので、引数の詳細などはここ

参考:Ansibleのlookup pluginについて調べてみた

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2