How can I save my secret keys and password securely in my version control system?

前端 未结 17 1700
生来不讨喜
生来不讨喜 2020-11-29 14:49

I keep important settings like the hostnames and ports of development and production servers in my version control system. But I know that it\'s bad practice to kee

相关标签:
17条回答
  • 2020-11-29 15:09

    You're exactly right to want to encrypt your sensitive settings file while still maintaining the file in version control. As you mention, the best solution would be one in which Git will transparently encrypt certain sensitive files when you push them so that locally (i.e. on any machine which has your certificate) you can use the settings file, but Git or Dropbox or whoever is storing your files under VC does not have the ability to read the information in plaintext.

    Tutorial on Transparent Encryption/Decryption during Push/Pull

    This gist https://gist.github.com/873637 shows a tutorial on how to use the Git's smudge/clean filter driver with openssl to transparently encrypt pushed files. You just need to do some initial setup.

    Summary of How it Works

    You'll basically be creating a .gitencrypt folder containing 3 bash scripts,

    clean_filter_openssl 
    smudge_filter_openssl 
    diff_filter_openssl 
    

    which are used by Git for decryption, encryption, and supporting Git diff. A master passphrase and salt (fixed!) is defined inside these scripts and you MUST ensure that .gitencrypt is never actually pushed. Example clean_filter_openssl script:

    #!/bin/bash
    
    SALT_FIXED=<your-salt> # 24 or less hex characters
    PASS_FIXED=<your-passphrase>
    
    openssl enc -base64 -aes-256-ecb -S $SALT_FIXED -k $PASS_FIXED
    

    Similar for smudge_filter_open_ssl and diff_filter_oepnssl. See Gist.

    Your repo with sensitive information should have a .gitattribute file (unencrypted and included in repo) which references the .gitencrypt directory (which contains everything Git needs to encrypt/decrypt the project transparently) and which is present on your local machine.

    .gitattribute contents:

    * filter=openssl diff=openssl
    [merge]
        renormalize = true
    

    Finally, you will also need to add the following content to your .git/config file

    [filter "openssl"]
        smudge = ~/.gitencrypt/smudge_filter_openssl
        clean = ~/.gitencrypt/clean_filter_openssl
    [diff "openssl"]
        textconv = ~/.gitencrypt/diff_filter_openssl
    

    Now, when you push the repository containing your sensitive information to a remote repository, the files will be transparently encrypted. When you pull from a local machine which has the .gitencrypt directory (containing your passphrase), the files will be transparently decrypted.

    Notes

    I should note that this tutorial does not describe a way to only encrypt your sensitive settings file. This will transparently encrypt the entire repository that is pushed to the remote VC host and decrypt the entire repository so it is entirely decrypted locally. To achieve the behavior you want, you could place sensitive files for one or many projects in one sensitive_settings_repo. You could investigate how this transparent encryption technique works with Git submodules http://git-scm.com/book/en/Git-Tools-Submodules if you really need the sensitive files to be in the same repository.

    The use of a fixed passphrase could theoretically lead to brute-force vulnerabilities if attackers had access to many encrypted repos/files. IMO, the probability of this is very low. As a note at the bottom of this tutorial mentions, not using a fixed passphrase will result in local versions of a repo on different machines always showing that changes have occurred with 'git status'.

    0 讨论(0)
  • 2020-11-29 15:09

    Encrypt the passwords file, using for example GPG. Add the keys on your local machine and on your server. Decrypt the file and put it outside your repo folders.

    I use a passwords.conf, located in my homefolder. On every deploy this file gets updated.

    0 讨论(0)
  • 2020-11-29 15:09

    You could use EncFS if your system provides that. Thus you could keep your encrypted data as a subfolder of your repository, while providing your application a decrypted view to the data mounted aside. As the encryption is transparent, no special operations are needed on pull or push.

    It would however need to mount the EncFS folders, which could be done by your application based on an password stored elsewhere outside the versioned folders (eg. environment variables).

    0 讨论(0)
  • 2020-11-29 15:12

    I ask the question generally, but in my specific instance I would like to store secret keys and passwords for a Django/Python site using git and github.

    No, just don't, even if it's your private repo and you never intend to share it, don't.

    You should create a local_settings.py put it on VCS ignore and in your settings.py do something like

    from local_settings import DATABASES, SECRET_KEY
    DATABASES = DATABASES
    
    SECRET_KEY = SECRET_KEY
    

    If your secrets settings are that versatile, I am eager to say you're doing something wrong

    0 讨论(0)
  • 2020-11-29 15:13

    I suggest using configuration files for that and to not version them.

    You can however version examples of the files.

    I don't see any problem of sharing development settings. By definition it should contain no valuable data.

    0 讨论(0)
  • 2020-11-29 15:13

    No, private keys and passwords do not fall under revision control. There is no reason to burden everyone with read access to your repository with knowing sensitive service credentials used in production, when most likely not all of them should have access to those services.

    Starting with Django 1.4, your Django projects now ship with a project.wsgi module that defines the application object and it's a perfect place to start enforcing the use of a project.local settings module that contains site-specific configurations.

    This settings module is ignored from revision control, but it's presence is required when running your project instance as a WSGI application, typical for production environments. This is how it should look like:

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.local")
    
    # This application object is used by the development server
    # as well as any WSGI server configured to use this file.
    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    

    Now you can have a local.py module who's owner and group can be configured so that only authorized personnel and the Django processes can read the file's contents.

    0 讨论(0)
提交回复
热议问题