자식 리포지토리에서 암호를 다루는 가장 좋은 방법은 무엇입니까?


225

특정 상황에서 트위터에 액세스하고 Growl 알림을 팝업하는 데 사용하는 작은 Bash 스크립트가 있습니다. 스크립트로 비밀번호 저장을 처리하는 가장 좋은 방법은 무엇입니까?

이 스크립트를 git repo에 커밋하고 GitHub에서 사용할 수 있도록하고 싶지만,이 작업을 수행하는 동안 내 로그인 / 비밀번호를 비공개로 유지하는 가장 좋은 방법이 궁금합니다. 현재 비밀번호는 스크립트 자체에 저장되어 있습니다. 모든 이전 커밋에 비밀번호가 포함되므로 푸시하기 직전에 제거 할 수 없습니다. 비밀번호없이 개발하는 것은 옵션이 아닙니다. 외부 구성 파일에 암호를 저장해야한다고 생각하지만, 시도하고 무언가를 모으기 전에이를 처리 할 수있는 확실한 방법이 있는지 확인하려고 생각했습니다.

답변:


256

이를 수행하는 일반적인 방법은 구성 파일에서 비밀번호 정보를 읽는 것입니다. 구성 파일이 foobar.config이면 foobar.config.example샘플 데이터를 포함 하는 파일 을 리포지토리에 커밋합니다 . 프로그램을 실행하려면 실제 비밀번호 데이터로 호출 된 로컬 (추적되지 않은) 파일 foobar.config을 작성하십시오 .

이전 커밋에서 기존 비밀번호를 필터링하려면 민감한 데이터 제거 의 GitHub 도움말 페이지를 참조하십시오 .


4
Btw에서는 예제 foobar.config를 저장소에 추가 한 다음 foobar.config를 .ignore 파일에 추가 할 수 있습니다. 이런 식으로 예제 foobar.config가 복제 될 때 나타나고 실제 암호는 저장소에 추가되지 않습니다.
Mr_Chimp

16
@Mr_Chimp : .gitignore파일이 이미 리포지토리 있는 추적 된 파일에는 적용되지 않습니다 . 예를 들어, git add -u파일이 이미있는 경우에도 변경된 파일을 추가합니다 .gitignore.
Greg Hewgill

1
보충으로, 실수로 구성 파일을 추가하고 git history에서 삭제하려는 경우 흥미로운 링크가 있습니다. help.github.com/articles/remove-sensitive-data
Loïc Lopes

16
해당 비밀번호를 팀과 공유하는 방법은 무엇입니까? 하나는 로컬 사본 (
레포지토리에

2
@dangonfast와 같은 질문이 있습니다. 큰 팀에게는 실용적이지 않은 것 같습니다.
Jacob Stamm

25

환경 변수를 사용하여 비밀번호 (또는 API 키)를 설정하는 방법이 있습니다. 따라서이 비밀번호는 개정판 제어를 벗어납니다.

Bash를 사용하면 다음을 사용하여 환경 변수를 설정할 수 있습니다

export your_env_variable='your_password'

이 접근 방식은 Travis 와 같은 지속적인 통합 서비스와 함께 사용할 수 있으며 , GitHub 리포지토리 에 저장된 코드 (비밀번호 없음)는 Travis (환경 변수를 사용하여 비밀번호 설정)로 실행할 수 있습니다.

Bash를 사용하면 다음을 사용하여 환경 변수의 값을 얻을 수 있습니다.

echo "$your_env_variable"

Python을 사용하면 다음을 사용하여 환경 변수의 가치를 얻을 수 있습니다.

import os
print(os.environ['your_env_variable'])

추신 : 아마 약간 위험 할 수 있습니다 (그러나 일반적인 관행입니다) https://www.bleepingcomputer.com/news/security/javascript-packages-caught-stealing-environment-variables/

PS2 : "API 키를 안전하게 저장하는 방법"dev.to 이라는 제목의 기사 를 읽는 것이 흥미로울 수 있습니다.


1
잠재적 인 "안전하지 않은"코드 꿀벌 빌드가 환경 변수의 내용을 읽지 못하게하는 방법은 무엇입니까?
gorootde


16

무엇 그렉 말했다 그러나 나는 그것이 파일을 체크하는 것이 좋습니다 것을 추가 할 것입니다 foobar.config-TEMPLATE.

예제 이름, 비밀번호 또는 기타 구성 정보가 포함되어야합니다. 그런 다음 값을 표시해야하는 모든 코드 foobar.config와 형식을 확인 하지 않고도 실제 foobar.config에 포함 할 내용이 매우 분명합니다 .

데이터베이스 연결 문자열 및 이와 유사한 것과 같이 구성 값이 명확하지 않은 경우가 종종 있습니다.


7

리포지토리에서 암호를 처리하는 것은 정확한 문제가 무엇인지에 따라 다른 방식으로 처리됩니다.

1.하지 마십시오.

그리고 피하는 방법은 .gitignore, config.example 등의 일부 답변에서 다룹니다.

또는 2. 허가 된 사람 만 리포지토리에 액세스 할 수 있도록합니다.

즉, 비밀번호를 알고있는 사람들입니다. chmod사용자 그룹이 떠 오릅니다. 리포지토리 또는 서버를 외부에서 호스팅하는 경우 Github 또는 AWS 직원이 볼 수있는 것과 같은 문제가 있습니까?

또는 3. 민감한 데이터를 암호화합니다 (이 회신의 목적)

민감한 정보 (예 : 비밀번호)가 포함 된 구성 파일을 공개 위치에 저장하려면 암호화해야합니다. 저장소에서 복구 할 때 파일을 해독하거나 암호화 된 형식에서 바로 사용할 수도 있습니다.

암호화 된 구성 데이터를 사용하는 예제 자바 스크립트 솔루션은 다음과 같습니다.

const fs = require('fs');
const NodeRSA = require('node-rsa');

let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));
const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');

console.log('decrypted: ', config);

해독 된 구성 파일

따라서 몇 줄의 Javascript 만 작성하여 암호화 된 구성 파일을 복구 할 수 있습니다.

파일 config.RSA을 git 저장소에 넣으면 효과적으로 파일을 이진 파일로 만들 수 있으므로 Git과 같은 많은 이점 (예 : 변경 사항을 체리 선택하는 기능)을 잃게됩니다.

이에 대한 해결책은 키 값 쌍 또는 아마도 값을 암호화하는 것입니다. 예를 들어 민감한 정보를위한 별도의 파일이있는 경우 모든 값을 암호화하거나 한 파일에 모든 값이있는 경우 민감한 값만 암호화 할 수 있습니다. (아래 참조)

위의 예제는 테스트를 원하거나 RSA 키와 암호화 된 구성 파일이 있다고 가정 할 때 시작하려는 사람에게는 약간 쓸모가 없습니다 config.RSA.

RSA 키와 구성 파일을 생성하기 위해 추가 된 코드가 있습니다.

const fs = require('fs');
const NodeRSA = require('node-rsa');

/////////////////////////////
// Generate some keys for testing
/////////////////////////////

const examplekey = new NodeRSA({b: 2048});

fs.writeFileSync('private.key', examplekey.exportKey('pkcs8-private'));
fs.writeFileSync('public.key', examplekey.exportKey('pkcs8-public'));

/////////////////////////////
// Do this on the Machine creating the config file
/////////////////////////////

const configToStore = {Goodbye: 'Cruel world'};

let publickey = new NodeRSA();
publickey.importKey(fs.readFileSync('public.key', 'utf8'));

fs.writeFileSync('config.RSA', publickey.encrypt(configToStore, 'base64'), 'utf8');

/////////////////////////////
// Do this on the Machine consuming the config file
/////////////////////////////

let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));

const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');
console.log('decrypted: ', config);

값만 암호화

fs.writeFileSync('config.RSA', JSON.stringify(config,null,2), 'utf8');

여기에 이미지 설명을 입력하십시오

이와 같은 방법으로 암호화 된 값으로 구성 파일을 해독 할 수 있습니다.

const savedconfig = JSON.parse(fs.readFileSync('config.RSA', 'utf8'));
let config = {...savedconfig};
Object.keys(savedconfig).forEach(key => {
    config[key] = privatekey.decrypt(savedconfig[key], 'utf8');
});

별도의 행 (예를 들어, 각 구성 항목으로 Hello하고 Goodbye위), 힘내는 파일에 무슨 일이 일어나고 있는지 잘 인식하고 오히려 전체 파일보다 차이 등의 정보의 항목에 대한 변경 사항을 저장합니다. Git은 또한 병합 및 체리 픽 등을 더 잘 관리 할 수 ​​있습니다.

그러나 민감한 정보의 변경 사항을 버전 관리할수록 SAFE REPOSITORY 솔루션 (2)으로 이동하고 암호화 된 정보 (3) 솔루션에서 멀어집니다.


3

Vault 를 사용 하여 토큰, 비밀번호, 인증서, API 키 등에 대한 액세스를 보호, 저장 및 제어 할 수 있습니다. 예를 들어 Ansible 은 Playbook에서 사용되는 비밀번호 또는 인증서를 처리 하는 Ansible Vault 를 사용합니다.


Ansible Vault가 예제 구성 파일을 만드는 것보다 확실히 복잡하다는 것을 알았습니다.
icc97

@ icc97 그래, 슬프다. 그러나 우리는이 가능성에 대해 언급 할 필요가 있습니다. 제 생각에는 단일 사용자 환경을 위해 몇 개의 암호를 저장하는 것보다 복잡한 작업의 경우 처음부터 특수 솔루션을 사용하는 것이 좋습니다.
El Ruso

2
미래 독자를 돕기 위해 : Vault와 Ansible Vault는 비슷한 이름을 가진 관련이없는 프로젝트입니다.
bltavares

2

내가 사용하는 기술은 다음과 같습니다.

내 홈 폴더에 다음과 같은 폴더를 만듭니다. .config

해당 폴더에 암호 및 키를 외부화하려는 여러 가지 구성 파일을 배치합니다.

나는 일반적으로 다음과 같은 역 도메인 이름 구문을 사용합니다.

com.example.databaseconfig

그런 다음 bash 스크립트에서 다음을 수행하십시오.

#!/bin/bash
source $HOME/.config/com.example.databaseconfig ||exit 1

|| exit 1이 설정 파일을로드 할 수없는 경우 출구 스크립트됩니다.

bash, python 및 ant 스크립트에 해당 기술을 사용했습니다.

나는 편집증이며 .gitignore 파일이 부주의 한 체크인을 방지하기에 충분히 강력하다고 생각하지 않습니다. 또한 모니터링하는 것이 없으므로 체크인이 발생하면 아무도 처리하지 않습니다.

특정 응용 프로그램에 둘 이상의 파일이 필요한 경우 단일 파일이 아닌 하위 폴더를 만듭니다.


1

레일에 루비를 사용하는 경우 피가로 보석은 매우 우수하고 쉽고 안정적입니다. 프로덕션 환경에서도 두통이 적습니다.


4
그 보석이하는 일에 대해 좀 더 자세히 설명해 주시겠습니까? 그렇게하면 (잠재적으로) 여러 언어에 적용 할 수있는 '연습'으로 간주 될 수 있습니다.
mattumotu

medium.com/@MinimalGhost/… 개요가 있습니다. 기본적으로 구성 파일에서 항목을 가져 오는 것을 관리하는 것 같습니다
tripleee

0

신뢰하지만 확인하십시오.

여기서 .gitignorerepo에서 "secure"디렉토리를 제외시킵니다.

secure/

그러나 @ Michael Potter 의 편집증을 공유 합니다. 따라서 .gitignore를 확인하기 위해이 "보안"디렉토리가 체크인 된 경우 klaxon을 발생 시키는 Python 단위 테스트 가 있습니다. 검사를 확인하기 위해 합법적 인 디렉토리도 테스트합니다.

def test_github_not_getting_credentials(self):
    safety_url = 'https://github.com/BobStein/fliki/tree/master/static'
    danger_url = 'https://github.com/BobStein/fliki/tree/master/secure'

    self.assertEqual(200, urllib.request.urlopen(safety_url).status)

    with self.assertRaises(urllib.error.HTTPError):
        urllib.request.urlopen(danger_url)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.