API 키와 같은 비밀 정보를 소스 제어에서 제외시키는 전략?


217

사용자가 Twitter, Google 등의 OAuth 자격 증명을 사용하여 로그인 할 수있는 웹 사이트에서 작업하고 있습니다. 이렇게하려면이 다양한 제공 업체에 등록하고 내가 가지고있는 비밀 보안 키를 가져와야합니다 다양한 신체 부위에 대한 서약으로 보호합니다. 내 키가 ank되면 부품이 k니다.

API 키는 런타임에 인증 요청을 수행하는 데 사용되므로 소스와 함께 이동해야합니다. 필자의 경우 키는 응용 프로그램 내 구성 파일의 코드 또는 코드 자체에 있어야합니다. 단일 컴퓨터에서 빌드하고 게시 할 때 문제가되지 않습니다. 그러나 소스 컨트롤을 믹스에 넣으면 상황이 더 복잡해집니다.

나는 싼 놈이기 때문에 클라우드 또는 GitHub에서 TFS와 같은 무료 소스 제어 서비스를 사용하는 것을 훨씬 선호합니다. 이것은 나에게 약간의 수수께끼를 남긴다.

API 키가 코드에 있고 공용 저장소에서 코드를 사용할 수있을 때 어떻게 내 몸을 그대로 유지할 수 있습니까?

나는 이것을 처리하는 여러 가지 방법을 생각할 수 있지만 그중 어느 것도 만족스럽지 않습니다.

  • 코드에서 모든 개인 정보를 제거하고 배포 후 다시 편집 할 수 있습니다. 이것은 구현하기가 매우 어려울 수 있으며 (여러 가지 방법을 자세히 설명하지는 않음) 옵션이 아닙니다.
  • 암호화 할 수있었습니다. 그러나 암호를 해독해야하므로 소스를 가진 사람은 누구나 그렇게하는 방법을 알 수 있습니다. 무의미한.
  • 개인 소스 제어 비용을 지불 할 수 있습니다. LOL J / K는 돈을 쓰나요? 부디.
  • 언어 기능을 사용하여 민감한 정보를 나머지 소스와 분리하여 소스 제어에서 벗어날 수 있습니다. 이것이 내가 지금하고있는 일이지만 실수로 비밀 파일을 체크인하여 쉽게 망칠 수 있습니다.

나는 개발, 디버깅 및 배포를 통해 원활하게 작동하고 완벽하게 작동하는 개인과 세계 (스냅 채팅 제외)를 공유하지 않는 보장 된 방법을 찾고 있습니다. 이것은 완전히 비현실적입니다. 그래서 현실적으로 무엇을 할 수 있습니까?

기술적 세부 사항 : VS2012, C # 4.5, 소스 제어는 TF 서비스 또는 GitHub입니다. 현재 부분 제어를 사용하여 민감한 키를 소스 제어에 추가되지 않는 별도의 .cs 파일로 분리합니다. gitgitore를 사용하여 부분 클래스 파일이 체크인되지 않도록 할 수 있기 때문에 GitHub의 이점이 있다고 생각하지만 이전에는 문제를 해결했습니다. "오, 일반적인 문제, 이것이 당신이하는 방법입니다"를 기대하고 있지만 "가능한 한 많이 빨지 않습니다", : /


6
API 키를 보유한 구성 파일이 소스 제어 디렉토리에 있지 않으므로 처음부터 체크인 할 수 없습니다.
David Sergey

22
BitBucket.org에는 무제한 개인 저장소가 있습니다. 비어 있는. 그리고 gitHub 리포지토리 가져 오기 (기록 유지)
Rob van der Veer

4
@Dainius 개발자를 알고 있기 때문에 개발자를 신뢰하지 않습니다. 친밀하게. 사실, 나는 적어도 내 자신과 친밀합니다 ... 아니, 나는 그 사람이 거짓말하게 할 것입니다. 그러나 나는 나사를 조이는 것이 얼마나 쉬운 지, 그리고 나사의 역사를 닦는 것이 얼마나 어려운지 안다.

15
@Dainius : 그렇습니다. 팀 코드마다 모든 단일 문자를 봅니다. 진심으로. 어쩔수없이. 눈가리개를 할 수 없습니다. 적어도 확실하지는 않습니다. 하지만 저는 팀이기 때문에 그렇습니다. 저는 TEAM의 I입니다. 한 명의 개발자가 있는데 나입니다. 내가 그 사람이야 예. 나는 그가 제대로하지 않으면 이것을 망칠 사람입니다. 나를.
Will

3
처음에 코드를 키로 컴파일하려고하는 이유는 무엇입니까? 구성 파일에 이런 종류의 것을 넣는 것이 일반적입니다.
Donal Fellows

답변:


128

비밀 정보를 코드에 넣지 마십시오. 시작할 때 코드에서 읽은 구성 파일에 넣으십시오. 구성 파일은 "공장 기본값"이 아니라면 개인 정보가 없어야 버전 관리를 할 수 없습니다.

이 작업을 수행하는 방법에 대해서는 질문 버전 제어 및 개인 구성 파일 을 참조하십시오 .


8
@RobertHarvey는 버전 관리에 넣지 않고 필요할 때 무시 규칙을 추가하여 제공합니다. 소프트웨어를 사용하는 사람은 자신의 API 키를 사용하여 자체 구성 파일을 작성해야합니다.
Philipp

10
따라서 소프트웨어 배포를 빌드하고 만들 때 구성 파일과 함께 제공되는 방법은 무엇입니까? 합리적인 기본값을 가진 파일이 없으면 일반적으로 사용자가 구성 파일을 만드는 과정을 거치는 것이 합리적이지 않습니다.
Thomas Owens

4
공장 기본값은 한 부분, "설치자"또는 "처음 실행 마법사"
johannes

6
많은 사용자가 자신의 설치를 가지고 있다면 자신의 API 키를 작성하여 사용해야합니까? 같은 키를 사용하는 여러 사이트 / 설치는 나쁜 생각 일 수 있습니다. 한 번만 설치하면 구성 파일을 사용하는 것이 번거롭지 않습니다.
Mike Weller

10
@Will, 구현 세부 정보가 실용적이지 않아서이 작업을 수행 할 수 없다면 배포에 적합한 툴링이 없다고 말하고 싶습니다. 커밋되지 않은 비밀 구성 파일을 사용한 배포는 전혀 어려움이 없습니다. C #이 아닌 Ruby 생태계에 살고 있으므로 구체적인 조언을 드릴 수 없습니다. 그러나 루비 사람들은 자동 배포에 Capistrano를 사용하는 경향이 있습니다. C #에도 자동 배포 도구가 있다고 확신하면 프로세스가 쉬워집니다.
벤 리

29

모든 개인 / 보호 키를 시스템 환경 변수로 넣을 수 있습니다. 구성 파일은 다음과 같습니다.

private.key=#{systemEnvironment['PRIVATE_KEY']}

이것이 우리가 이러한 경우를 처리하는 방법이며 코드에는 아무런 영향이 없습니다. 다른 속성 파일 및 프로필과 잘 결합됩니다. 우리는 환경마다 다른 속성 파일을 사용합니다. 로컬 개발 환경에서는 로컬 설정을 단순화하기 위해 개발 키를 속성 파일에 넣습니다.

private.key=A_DEVELOPMENT_LONG_KEY

호스팅 옵션으로 작동하게 할 수 있다면 합리적인 솔루션이 될 것입니다. 환경 변수는 아니지만 게시 후에 지워지지 않는 일부 키 / 값 구성
것입니다

실제 환경으로 배송하기 전에 해당 환경 변수를 빌드 서버에 넣는 것은 어떻습니까? 그렇게하면 프로덕션 리소스 / 구성 파일을 준비 할 수 있습니다.
Ioannis Tzikas

빌드 서버는 개발 시스템 이므로이 정보가 실수로 소스 제어에 체크인되는 것이 염려됩니다.
Will

이 문제는 서버의 모든 사람이 환경을 읽을 수 있다는 것입니다.
JasonG

사용자의 envvar는 사용자 또는 루트 만 읽을 수 있습니다. (그러나 고대 리눅스와 AIX는 이것을하지 않았다)
Neil McGuigan

27

순수한 힘내 방법

  • .gitignore 개인 데이터가 포함 된 파일
  • 있는 당신이 대체 로컬 브랜치를 사용 TEMPLATE하여DATA
  • (로컬) 필터의 스크립트가 양방향 교체를 수행하는 얼룩 / 청소 필터 사용 TEMPLATE<->DATA

머큐리 웨이

  • 대체 더미 코드의 상단에 MQ-패치 (들) TEMPLATE과은 DATA(체인지가 공개되어, 패치는 개인입니다)
  • 특수하게 설계된 키워드를 사용하는 키워드 확장 ( 작업 디렉토리 에서만 확장 )

SCM에 구애받지 않는 방식

  • 빌드 / 배포 프로세스의 일부로 키워드 교체

흠 ... 자식 조언이 좋고, 당신의 불가지론 조언이 나에게 좋은 아이디어를줍니다 ... 빌드 이벤트를 사용하여 파일을 게시 프로세스에 도입 한 다음 제거하여 파일이 아닌지 확인하는 데 도움이됩니다. 실수로 소스 제어에 추가됩니다.
Will

7
아니, 아니 다시 한번-아니! 파일을 무시하는 것은 프로세스 또는 무언가를 구축하기 위해 매우 특정한 사용자 정의를 추가하는 데 좋지만 안전한 데이터를 저장하는 데 사용해서는 안됩니다. 보안 데이터는 무시하더라도 저장소에 저장하지 마십시오.
shabunc

11
@shabunc-RTFM! 저장소에 저장되지 않은 무시 된 파일
Lazy Badger

9
@LazyBadger-무시된다는 것을 잘 알고 있습니다. 나는 또한 repo에 있으면서 누군가가 실수없이 그것을 repo에 추가 할 가능성이 항상 있다는 것을 알고 있습니다. 일부 외부 구성 경로가 더 좋습니다.
shabunc

4
@ shabunc-SCM 경로에서 구성을 유지하는 것이 좋습니다. 예를 들어 Postgres를 사용하면 비밀번호를 파일에 넣어 비밀번호 확인을 우회 할 수 있습니다. 그러나 암호 파일을 ~ / .pgpass에 넣어야합니다. 소스 제어를 확인하기에 매우 편리한 위치는 아닙니다. 그들은, 자동화, 그들은 당신에게 총을주고 알고 있지만 그것으로 스스로 발을 사격에서 당신을 유지하기 위해 최선을 다하고 있습니다 ..
스티브 Midgley

14

암호화 된 파일에 비밀을 넣은 다음 커밋합니다. 암호 문구는 시스템이 시작될 때 제공되거나 커밋하지 않은 작은 파일에 저장됩니다. Emacs가 암호화 된 파일을 즐겁게 관리하게되어 기쁩니다. 예를 들어, emacs init 파일에는 다음이 포함됩니다. (load "secrets.el.gpg"), 작동합니다. 에디터를 시작할 때 드문 경우에 암호를 입력하라는 메시지가 표시됩니다. 누군가 암호화를 깨는 것에 대해 걱정하지 않습니다.


3
이것은 훌륭한 해결책입니다. 더 많은 투표권이 없다는 것에 놀랐습니다. 저는 미국에서 연방 규제를받는 학생 데이터를 다루는 회사와 협력하므로 자격 증명과 비밀에 특히주의해야합니다. 또한 대기업이므로 자격 증명을 위해 SCM을 사용해야하므로 IT 부서가 구축 한 후에 자격 증명을 찾거나 관리 할 수 ​​있습니다. 귀하의 솔루션은 정확히 그들이하는 일입니다. dev / staging / prod / etc (각각 하나의 파일)에 대한 암호 해독 키를 보유하는 암호 해독 키 파일이 있습니다. 그런 다음 모든 비밀이 암호화되어 파일로 체크인됩니다. 암호 해독 파일은 각 환경에서 파일을 가져 오는 데 사용됩니다.
Steve Midgley

7
글쎄, 어떤 의미에서 비밀을 암호화하면 (이 경우 API 키) 비밀 데이터커밋하지 않는 것에서 패스 문구를 커밋하지 않는 것 (지금은 비밀 데이터가 됨 )으로 문제를 이동시킵니다 . 물론 시스템을 시작할 때 요청하는 것이 좋습니다.
siegi

나는이 해결책을 좋아한다. 커밋 한 암호화 된 파일 종류는 KeePass 파일 일 수 있습니다. notes필드를 사용 하여 .env 파일의 내용을 저장하는 각 환경에 대한 항목이 있습니다 . 몇 달 전에 나는 keepass 파일을 읽고 notes항목 의 필드를 사용하여 .env 파일을 만들 수있는 도구를 작성했습니다 . require('switchenv').env()Node.js 프로그램 상단에서 수행 하고 NODE_ENV 또는 이와 유사한 항목을 기반으로 process.env 변수를 만들 수있는 기능을 추가하려고합니다 . -> github.com/christiaanwesterbeek/switchenv
Christiaan Westerbeek

14

이것은 Android / Gradle에 따라 다르지만 gradle.properties에 위치한 전역 파일 에서 키를 정의 할 수 있습니다 user home/.gradle/. 또한 buildType 또는 플레이버에 따라 다른 속성 (예 : dev의 API 및 릴리스의 다른 속성)을 사용할 수 있으므로 유용합니다.

gradle.properties

MY_PRIVATE_API_KEY=12356abcefg

build.gradle

buildTypes {
        debug{
            buildConfigField("String", "GOOGLE_VERIFICATION_API_KEY", "\"" + MY_PRIVATE_API_KEY +"\"")
            minifyEnabled false
            applicationIdSuffix ".debug"
            }
        }

코드에서는 다음과 같이 참조합니다

String myAPI = BuildConfig.GOOGLE_VERIFICATION_API_KEY;

BuildConfig는 해당 소스 파일로 변환되므로 apk의 간단한 리버스 엔지니어링을 통해 BuildConfig에 넣은 모든 키와 비밀을 알 수 있습니다
Dmitri Livotov

1
사실, 유효한 포인트입니다. 그러나 문제는 바이너리 키가 아닌 소스 코드에서 API 키를 유지하는 방법에 관한 것입니다.
scottyab

11

해당 키를 애플리케이션과 함께 배포하거나 소스 코드 저장소에 저장한다고 가정하지 마십시오. 이 질문은 그렇게하는 방법을 묻고 있으며 일반적으로 수행되는 것은 아닙니다.

모바일 웹 애플리케이션

Android / iPhone의 경우 앱을 처음 실행할 때 기기가 자체 웹 서비스에서 키를 요청해야합니다. 그런 다음 키는 안전한 위치에 저장됩니다. 게시자가 키를 변경하거나 취소해야합니다. 웹 서비스는 새 키를 게시 할 수 있습니다.

호스팅 된 웹 응용 프로그램

소프트웨어 라이센스를 사용하는 고객은 소프트웨어를 처음 구성 할 때 키를 수동으로 입력해야합니다. 모든 사람에게 동일한 키, 다른 키를 주거나 자신의 키를 얻을 수 있습니다.

게시 된 소스 코드

소스 코드는 공개 저장소에 저장하지만 KEY는 저장하지 않습니다. 파일 구성에서 * place key here * 행을 추가 하십시오 . 개발자가 소스 코드를 사용하면 sample.cfg파일을 복사 하고 자체 키를 추가합니다.

config.cfg개발 또는 프로덕션에 사용 된 파일을 저장소에 보관하지 마십시오 .


4
이 질문은 그 방법을 묻는 것입니다 . 사실 이러한 키는 코드로 사용되어야하고 코드로 액세스해야하며 일반적으로 코드 또는 구성 파일을 통해 서로 소스가 아닌 경우 적어도 가까이 있고 실수로 종료 될 수 있습니다. 출처. 호스팅 된 웹 앱은 불행하게도 의미가 없습니다. (가상) 페이스 북 계정을 통해 StackOverflow에 로그인하기 위해 API 키를 신청할 필요가 없었습니다. 여기서 중요한 것은 Q에 설명 된 것처럼 개발
Will

다른 많은 사람들과 마찬가지로 질문에 올바르게 대답했습니다. 그들 중 하나를 받아들이지 않았다는 사실은 이러한 키를 사용하는 방법을 이해하지 못한다는 것을 의미합니다.
Reactgular

7
그런 다음 키 게시 웹 서비스를 어떻게 보호합니까? 다른 키를 사용하십니까?
Jiangge Zhang

@JianggeZhang이 말한 내용을 Ditto – 이것은 위험한 조언입니다
David K. Hess

5

각 서버마다 변경되는 비밀 사항에 환경 변수를 사용하십시오.

http://en.wikipedia.org/wiki/Environment_variable

그것들을 사용하는 방법은 언어에 따라 다릅니다.


3
모호성을 통한 보안은 많은 사람들에게 권장되는 방법이 아닙니다. 더 명확하게 답을 정교하게 작성 하시겠습니까?

2
모호한 것은 아니며 환경 변수는 추가 한 사용자 만 사용할 수 있으므로 모든 자격 증명은 앱이 실행중인 사용자 컨텍스트와 동일한 보호 기능을 갖습니다. 환경 변수 개념을 포함하도록 답변을 업데이트했습니다. 더 명확합니까?
Filipe Giusti

4

나는 이것이 모든 사람들이 어느 시점에서 어려움을 겪고있는 문제라고 생각합니다.

내가 사용한 워크 플로는 다음과 같습니다. 그것은 gitgitore를 꼬아 서 사용합니다.

  1. 모든 구성 파일은 특수 폴더에 들어갑니다 (샘플 구성 파일 포함-옵션)
  2. 모든 구성 파일은 .gitignore에 포함되어 공개되지 않습니다.
  3. 개인 상자에 gitolite 서버 또는 선호하는 git 서버를 설정하십시오.
  4. 개인 서버의 모든 구성 파일로 저장소를 추가하십시오.
  5. 구성 파일을 기본 리포지토리의 특수 폴더에 복사하는 스크립트 추가 (선택 사항)

이제 구성 저장소를 모든 개발 및 배포 시스템에 복제 할 수 있습니다. 스크립트를 실행하여 파일을 올바른 폴더에 복사하면 완료됩니다.

여전히 모든 GitHub 캔디를 가져와 코드를 전세계와 공유하고 민감한 데이터는 절대 메인 리포지토리에 저장되지 않으므로 공개되지 않습니다. 그것들은 여전히 ​​모든 배포 시스템에서 멀어지고 사본입니다.

개인 git 서버에 15 $ / 년 상자를 사용하지만 cheapskate 요구 사항에 따라 집에서 하나를 설정할 수도 있습니다. ;-)

추신 : git 서브 모듈 ( http://git-scm.com/docs/git-submodule )을 사용할 수도 있지만 항상 명령을 잊어 버립니다.


2

암호화를 사용하지만 시작시 마스터 키를 콘솔에서 암호로 프로세스의 사용자 만 읽을 수있는 파일 또는 Mac OS 키 체인 또는 Windows 키 저장소와 같은 시스템 제공 키 저장소에서 제공하십시오.

지속적인 전달을 위해 다양한 키를 어딘가에 기록해야합니다. 구성은 코드와 구분되어야하지만 개정 관리하에 두는 것이 합리적입니다.


1

아직 언급되지 않은 3 가지 전략 (?)

체크인 또는 VCS 사전 체크인 후크

  • 엔트로피가 높은 문자열 검색, 예 -비밀 탐지
  • 정규식은 잘 알려진 API 키 패턴을 검색합니다. AWS의 AKIA * 키는 예이며 git-secrets 는이를 기반으로하는 하나의 도구입니다. 또한 상수가 할당 된 '암호'와 같은 변수 이름.
  • 알려진 비밀 검색-비밀을 알고 텍스트를 검색합니다. 또는 도구를 사용하여이 개념 증명을 작성했습니다 .

이미 언급 한 전략

  • 소스 트리 외부의 파일에 저장
  • 소스 트리에 있지만 VCS에 무시하도록 지시하십시오.
  • 환경 변수는 소스 트리 외부에 데이터를 저장하는 변형입니다.
  • 개발자에게 귀중한 비밀을주지 마십시오

0

개인 정보를 소스 제어에서 제외하십시오. 배포를 위해로드되지 않은 기본값을 만들고 VCS가 실제 값을 무시하도록합니다. 설치 프로세스 (수동, 구성 / 빌드 또는 마법사)는 새 파일 작성 및 채우기를 처리해야합니다. 필요한 사용자 (웹 서버?) 만 읽을 수 있도록 파일에 대한 권한을 선택적으로 수정하십시오.

혜택:

  • 개발 엔터티 == 생산 엔터티를 가정하지 않습니다
  • 모든 공동 작업자 / 코드 검토자가 신뢰할 수 있다고 가정하지는 않습니다.
  • 버전 관리에서 벗어남으로써 쉬운 실수 방지
  • QA / 빌드 용 사용자 정의 구성으로 설치 자동화 용이

이미이 작업을 수행하고 있고 실수로 체크인하는 경우 프로젝트에 추가하십시오 .gitignore. 이렇게하면 다시 할 수 없게됩니다.

개인 저장소를 제공하는 무료 Git 호스트 많이 있습니다 . 자격 증명의 버전을 지정해서는 안되지만 저렴하고 개인 저장소도 가질 수 있습니다. ^ _ ^


-2

OAuth 키를 어디에서나 원시 데이터로 저장하는 대신 일부 암호화 알고리즘을 통해 문자열을 실행하여 솔트 해시로 저장하지 않는 이유는 무엇입니까? 그런 다음 구성 파일을 사용하여 런타임에 복원하십시오. 그렇게하면 키가 개발 상자에 저장 되든 서버 자체에 저장되어 있든 아무 곳에 나 키가 저장되지 않습니다.

서버가 요청에 따라 새로운 솔트 및 해시 된 API 키를 자동으로 생성하도록 API를 작성할 수도 있습니다. 이렇게하면 팀에서도 OAuth 소스를 볼 수 없습니다.

편집 : 아마도 Stanford Javascript Crypto Library를 사용해보십시오. 이는 꽤 안전한 대칭 암호화 / 암호 해독을 허용합니다.


1
해시는 일반적으로 편도 스크램블입니다. 그래도 제안한대로 대칭 암호화 알고리즘이 있습니다.

3
야, 당신은 (쉽게) 해시를 해독 할 수 없습니다. 이것이 해시의 요점입니다. ME가 다른 사람의 API를 사용하여 ME에 비밀 키를 할당하기위한 것입니다. 내 해싱은 API를 사용할 수 없도록 (빈약 한 알고리즘을 선택하고 매번 크랙하지 않는 한) 보장합니다.
Will
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.