Python 如何在云计算环境中安全地分发凭据?

Python 如何在云计算环境中安全地分发凭据?,python,security,Python,Security,我正在从事一个python项目,该项目涉及安全地检索信息,并将其存储在互联网可访问的位置,如数据库和存储桶。根据各种因素,我可能在本地机器上运行代码,也可能在Amazon AWS或Google Compute Engine的数百台虚拟机上运行代码 我使用Github repo来维护版本控制,并方便这些虚拟机访问代码。我不希望在存储库中的平面文件中存储凭据(如密码),即使存储库是私有的。但是,我不知道如何为所有需要它们的各种机器自动提供必要的凭据。在虚拟机映像中存储凭据是次优的,因为我不想在凭据更

我正在从事一个python项目,该项目涉及安全地检索信息,并将其存储在互联网可访问的位置,如数据库和存储桶。根据各种因素,我可能在本地机器上运行代码,也可能在Amazon AWS或Google Compute Engine的数百台虚拟机上运行代码

我使用Github repo来维护版本控制,并方便这些虚拟机访问代码。我不希望在存储库中的平面文件中存储凭据(如密码),即使存储库是私有的。但是,我不知道如何为所有需要它们的各种机器自动提供必要的凭据。在虚拟机映像中存储凭据是次优的,因为我不想在凭据更改时创建新映像


有没有一种轻量级的解决方案可以将这种类型的凭证分发到不同的计算环境中?

当访问任何计算机集合的人需要访问S3上的设施时,我使用了带有长密码的对称密码来实现这类功能。全自动,我怀疑这一切都是非常安全的。更多的是人为干预

有一个纯文本文件
.s3cfg
包含工具
s3cmd
所需的Amazon S3凭据。我们希望将其备份到密文文件
.gpgs3
,并在不同的地方提供它,以及一些脚本,以便非gpg用户在知道密码的情况下更容易将其转换为所需的
.s3cfg
文件

我将用于加密的gpg命令放在一些简短的脚本中

加密脚本
s3lock.sh

 #!/bin/bash
 umask 077
 gpg --symmetric <~/.s3cfg >~/.gpgs3
 #!/bin/bash
 umask 077
 gpg --decrypt ~/.gpgs3 >~/.s3cfg 2>/dev/null
 #!/bin/bash
 # remove the plain text file
 rm -f ~/.s3cfg
整理脚本
s3off.sh

 #!/bin/bash
 umask 077
 gpg --symmetric <~/.s3cfg >~/.gpgs3
 #!/bin/bash
 umask 077
 gpg --decrypt ~/.gpgs3 >~/.s3cfg 2>/dev/null
 #!/bin/bash
 # remove the plain text file
 rm -f ~/.s3cfg
这种方法还没有经过任何同行的审查,但我还没有遇到问题

此设置可能会发生以下情况:

  • 完成后,您忘记运行
    s3off.sh
    ,将纯文本文件保留在可用位置,稍后当有人打开您的框时,他们将获得S3凭据。他们花了一大笔钱,亚马逊锁定了你的东西,收款部每天都打电话给你
  • 您在脚本中放入了
    s3off.sh
    ,但是一个不耐烦的人打断了脚本,然后当有人打开您的盒子时,他们会得到S3凭据。。。并删除S3中的所有备份,以便“妥善保管”
  • 一位不满的同事注意到这是如何工作的,并在其他合法访问期间获取明文S3凭据

    • 嗯-我是新来的,但这个请求真的离题了吗?我觉得没问题

      如果您使用Python和GIT,那么我们编写了一个解决方案,使用RC4将密码(和其他配置信息)存储为常规变量。它使我们能够轻松地在dev机器上以明文形式维护密码,自动加密密码,并在每次git推送时自动分发加密版本。您需要在每台生产机器上手动安装一个私钥,但此后,生产机器上的git pull将引入一个更新的加密文件,并在运行时自动解密该文件,以便在代码中使用

      代码的一个很好的特性是,密码的解密(明文)副本永远不会,永远不会命中生产机器上的硬盘。然而,您可以在python代码中直接引用密码,大多数intellisense系统(如pyCharm)都可以在生产机器上编码时查看密码变量。更改密码也很容易——只需更新明文文件和git push即可

      我还没有为此做出任何贡献,所以我最好现在就开始。我将代码和完整的自述文件放在GitHub repo上:

      抓取security.py文件后,实现非常简单:

      import security
      for line in security.secure(): exec line in globals()
      
      github repo中有一个完整的README.md文件和helloworld.py示例。以下是实现代码,以防有人想发表评论:

      """Secure python variables: encrypt, decrypt, import into global namespace."""
      __module__    = 'security.py'
      __author__    = "Kenneth A Younge"
      __copyright__ = "Copyright (c) 2014, Kenneth A. Younge"
      __license__   = "GNU General Public License"
      __email__     = "kenyounge@gmail.com"
      
      import os
      
      def crypt(data, key):
          x = 0
          box = range(256)
          for i in range(256):
              x = (x + box[i] + ord(key[i % len(key)])) % 256
              box[i], box[x] = box[x], box[i]
          x = 0
          y = 0
          out = []
          for char in data:
              x = (x + 1) % 256
              y = (y + box[x]) % 256
              box[x], box[y] = box[y], box[x]
              out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
          return ''.join(out)
      
      def secure(file_names=('passwords.py',),
                 key_name='security.key',
                 key_path='~/',
                 pvt_path='_private/',
                 verbose=False):
          """Transform files (encrypt and/or decrypt _private files).
      
          Keyword arguments:
              filenames  --  sequence of file names to encrypt/decrypt
              key_name   --  file name of your personal rc4 encryption key
              key_path   --  location of encryption key on production machines
              pvt_path   --  location of private files and encryption key during dev
              verbose    --   print info
      
          Defaults:
              filenames  --  passwords.py    currently a tuple with one file
              key_name   --  security.key     
              key_path   --  ~/               
              pvt_path   --  _private/
              verbose    --  False
          """
      
          # Load key (try production location first)
          if os.path.exists(os.path.join(key_path, key_name)):
              key = open(os.path.join(key_path, key_name), 'r').read()
          elif os.path.exists(os.path.join(
                  os.path.dirname(__file__), pvt_path + key_name)):
              key = open(os.path.join(
                  os.path.dirname(__file__), pvt_path + key_name), 'r').read()
          else:
              key = open(os.path.join(
                  os.path.dirname(__file__), key_name), 'r').read()
      
          # secure each file
          code_lines = []
          for filename in file_names:
      
              filename_raw = os.path.join(
                  os.path.dirname(__file__), pvt_path + filename)
              filename_rc4 = os.path.join(
                  os.path.dirname(__file__),
                  os.path.basename(filename).replace('.py', '.rc4'))
      
              # Encrypt
              try:
                  if os.path.exists(filename_raw):
                      with open(filename_raw, 'r') as f:
                          text = f.read()
                      with open(filename_rc4, 'w') as f:
                          f.write(crypt(str(text).strip(), key).encode('hex'))
                      if verbose:
                          print 'Encrypted ' + filename_raw
                  else:
                      if verbose:
                          print('File (' + filename_raw + ') not found')
              except Exception as e:
                  print(str(e))
      
              # Decrypt
              try:
                  if os.path.exists(filename_rc4):
                      with open(filename_rc4, 'r') as f:
                          text = crypt(str(f.read()).strip().decode('hex'), key)
                          lines = [str(line).strip() for line in text.splitlines()]
                      if lines: code_lines.extend(lines)
                      if verbose:
                          print 'Encrypted ' + filename_rc4
                  else:
                      print('File ' + filename_rc4 + ' not found')
              except Exception as e:
                  print(str(e))
          return code_lines
      

      推荐请求已脱离主题您是否可以将证书添加到主机上的.ssh文件夹中?或者加密您的凭据,并将您的密码直接分发给您要向其分发包的人。。。。您甚至可以编写一个python脚本来解密该文件,并将其放在应用程序可以访问的地方。我不明白为什么这个问题会偏离主题。如果没有可用的解决方案,我很乐意自己实施,但我不确定最好的解决方案是什么。据我所知,在云计算中,密钥管理是一个公开的问题。我不明白为什么他不能将整个凭证文件gpg并将其放入repo。。。并将解密密钥直接分发给团队,这确实是最基本的想法。我这么做是因为在匆忙中我不想看gpg的备忘单。只要问我密码,请…这似乎是一个合理的方法,但它不是自动化的,因为我想。如果我忘记处理纯文本文件,我也希望它不可用。@RobertNeely你可以编写一个cron作业来删除纯文本文件,以防你忘记。这种方法似乎很完美。它看起来很轻,但很有效,因为我确实在启动期间从Git中提取了每个VM的代码。另外,我可以在不需要手动重新配置或移动文件的情况下更改键,这是另一个大问题。这听起来很有趣。