파일 시스템을 사용하지 않고 일시적으로 데이터 읽기 및 쓰기

파일 시스템을 사용하지 않고 일시적으로 데이터 읽기 및 쓰기

나는 데비안 상자를 관리하는 방랑 환경에서 ansible을 사용하고 있습니다. 여러 Ansible 프로비저너가 볼트 암호화된 데이터(예: 데이터베이스 루트 비밀번호)를 가지고 있으므로 첫 번째 프로비저너가 볼트 암호를 한 번 입력해야 합니다. 현재 이 비밀번호는 에 저장되고 /tmp, 각 Ansible 프로비저너의 스크립트로 읽혀지며, /dev/null마지막 프로비저너가 덮어쓰고 삭제합니다.

Ansible에는 볼트 비밀번호를 반환하는 스크립트를 호출하는 기능이 있습니다. 따라서 이 스크립트는 별도의 셸에서 실행됩니다.

공격자가 가상 ​​머신을 성공적으로 손상시키는 경우 임시 파일을 복구하고 볼트 비밀번호를 얻을 수 있습니다.

이러한 변덕스러운 환경은 프로덕션 환경에서 사용되지만 보다 안전한 접근 방식을 찾고 있습니다. 나의 첫 번째 생각은 어떻게든 메모리를 읽고 쓰는 것이었습니다. 따라서 가상 컴퓨터를 다시 시작하면 메모리가 지워집니다. 위의 데이터가 어떻게든 디스크에서 교환될 수 있다는 것을 알고 있습니다. 그런데 이 데이터를 얻는 것이 임시 파일 방식보다 더 어려운 것 같아요.

편집하다

구성자가 실패할 경우 보안 위험에 대해 언급하는 것을 잊었습니다. 그러면 마지막 구성 프로그램이 실행되지 않고 임시 파일이 파일 시스템에 남게 됩니다.


이 문제의 원인에 대한 솔루션에 관심이 있는 모든 사람을 위해 통합 솔루션을 보여주는 추가 답변을 제공했습니다.

답변1

1MB RAM 디스크를 생성하려면 다음 명령을 사용하십시오 tmpfs.

mkdir /tmp/ramdisk
mount -t tmpfs -o size=1m myramdisk /tmp/ramdisk

RAM 디스크는 스왑되지 않지만 RAM 디스크를 사용하는 동안 스왑이 발생하지 않도록 해야 하는 경우 RAM 디스크 사용 ramfs시 스왑을 끄거나 켤 수 있습니다 tmpfs. swapoff -a및 . 제거:swapon -atmpfs

umount /tmp/ramdisk

뭔가 빠졌을 수도 있지만 에 설명된 RAM 디스크의 이점은 보이지 않습니다 /etc/fstab. 그러나 다음과 같은 내용은 필요한 경우 사용자만 RAM 디스크를 사용할 수 있도록 하는 데 충분합니다 root( mode=0700).

tmpfs /tmp/ramdisk tmpfs rw,mode=0700,size=1m

답변2

@Christopher의 답변 외에도 Vagrantfile에 솔루션을 통합하여 Ansible 구성과 작동하는 방법을 보여주고 싶었습니다.

어쩌면 누군가가 이것을 우연히 발견하게 될 것입니다.

길 잃은 파일

Vagrant.configure("2") do |config|

    class AnsibleVaultPassword
        def to_s
            begin
                system 'stty -echo'
                print "Enter ansible vault password: "
                pass = STDIN.gets.chomp
                ensure
                system 'stty echo'
            end
            pass
        end
    end

    config.vm.box = "vendor/box-name"
    config.vm.box_version = ">=1.0"
    config.vm.box_url = "https://vagrant.example.com/vendor/box-name.json"
    config.vm.box_download_insecure = true

    config.vm.define "vendor-server-name"
    config.vm.provider "virtualbox" do |provider|
        provider.name = "vendor-server-name"
    end

    config.vm.network "private_network", ip: "192.168.0.42"

    config.vm.synced_folder ".", "/vagrant", type: "nfs"

    config.vm.provision "Provisioning the server `server-name` with the playbook `ansible`", type: "ansible_local" do |provisioner|
        provisioner.compatibility_mode = "2.0"
        provisioner.playbook = "/vagrant/ansible/ansible.yml"
        provisioner.inventory_path = "/vagrant/ansible/inv/integration/hosts"
        provisioner.limit = "localhost"
    end

    config.vm.provision "Requesting the ansible vault password", type: "shell" do |provisioner|
        provisioner.env = { "ansibleVaultPassword" => AnsibleVaultPassword.new }
        provisioner.inline = <<-END
            [[ ! -d "/mnt/ansible-tmp" ]] \
            && mkdir "/mnt/ansible-tmp"
            mountpoint -q "/mnt/ansible-tmp" \
            || mount -t tmpfs -o size=512 ansible-tmp "/mnt/ansible-tmp"
            /vagrant/env/ansible/scripts/vault-password.sh --save "${ansibleVaultPassword}"
        END
    end

    config.vm.provision "Provisioning the server `server-name` with the playbook `environment`", type: "ansible_local" do |provisioner|
        provisioner.compatibility_mode = "2.0"
        provisioner.playbook = "/vagrant/ansible/environment.yml"
        provisioner.raw_arguments = [ "--vault-id /vagrant/ansible/scripts/vault-password.sh" ]
        provisioner.inventory_path = "/vagrant/ansible/inv/integration/hosts"
        provisioner.limit = "localhost"
    end

    config.vm.provision "Provisioning the server `server-name` with the playbook `users`", type: "ansible_local" do |provisioner|
        provisioner.compatibility_mode = "2.0"
        provisioner.playbook = "/vagrant/ansible/users.yml"
        provisioner.raw_arguments = [ "--vault-id /vagrant/ansible/scripts/vault-password.sh" ]
        provisioner.inventory_path = "/vagrant/ansible/inv/integration/hosts"
        provisioner.limit = "localhost"
    end

    config.vm.provision "Deleting the ansible vault password", type: "shell" do |provisioner|
        provisioner.inline = <<-END
            /vagrant/env/ansible/scripts/vault-password.sh --delete
            mountpoint -q "/mnt/ansible-tmp" \
            && umount "/mnt/ansible-tmp"
            [[ -d "/mnt/ansible-tmp" ]] \
            && rm -r "/mnt/ansible-tmp"
        END
    end

end

/vagrant/ansible/scripts/vault-password.sh

#!/usr/bin/env bash

passwordFile="/mnt/ansible-tmp/vault-password"
case "${1}" in
    "-s" | "--save" )
        echo "${2}" > "${passwordFile}"
        ;;
    "-d" | "--delete" )
        unlink "${passwordFile}"
        ;;
    * )
        cat "${passwordFile}"
        ;;
esac

Debian VM이지만 먼저 플레이북을 실행하고 Ubuntu 에서 Ansible 저장소를 추가 한 ansible다음 최신 ansible. (이 기사가 출판된 당시에 는 이 주장을 뒷받침하지 않았습니다.)--vault-idansible-playbookDebian Stretchansible 2.2

그런 다음 class 를 통해 볼트 비밀번호를 요청하십시오 AnsibleVaultPassword. 그런 다음 비밀번호가 생성되어 tmpfs스크립트에 전달되어 설치 시 vault-password.sh저장됩니다 .tmpfs

vault-password.sh그런 다음 Ansible은 볼트의 암호화된 데이터를 제공하는 각 플레이북의 스크립트를 통해 비밀번호를 요청합니다.

마지막으로 비밀번호가 먼저 삭제된 후 tmpfs마운트가 제거됩니다.

임시 삭제 가능한 메모리 저장소를 통해 Ansible Vault 비밀번호를 제공하는 매우 안전하고 안전한 솔루션이라고 생각합니다. 따라서 실행 중인 시스템을 구성할 수 있으며 더 이상 재부팅이 필요하지 않습니다.

관련 정보