1. 개요
안전한 소스 코드 기법은 소스 코드의 보안을 개선하는 데 사용할 수 있는 일련의 관행입니다. 이러한 기술은 소스 코드의 취약점을 식별하고 수정하며, 소스 코드에 대한 무단 액세스를 방지하고 소스 코드의 수정 방지에 도움이 됩니다.
일반적인 보안 소스 코드 기법은 다음과 같습니다.
- Linting: Linting은 소스 코드에서 오류와 스타일 문제를 확인하는 프로세스입니다. 이는 소스 코드를 분석하고 잠재적인 문제를 식별하는 프로그램인 린트 도구를 사용하여 실행됩니다. 린트 도구를 사용하면 문법 오류, 의미 오류, 스타일 오류, 보안 취약점 등 다양한 오류를 확인할 수 있습니다.
- 정적 애플리케이션 보안 테스트 (SAST): SAST는 소스 코드, 바이너리 코드 또는 바이트 코드를 분석하여 보안 취약점을 식별하는 보안 테스트 유형입니다. SAST 도구를 사용하면 Go, Java, Python, C++, C# 등 다양한 프로그래밍 언어의 취약점을 찾을 수 있습니다.
- 라이선스 스캔: 라이선스 스캔은 소프트웨어 애플리케이션에 사용된 서드 파티 소프트웨어 구성요소의 라이선스를 식별하는 프로세스입니다. 이는 애플리케이션이 라이선스 약관을 준수하도록 하는 데 도움이 되므로 중요하며, 법적 문제를 방지하는 데 도움이 될 수 있습니다.
이러한 기법은 소프트웨어 개발 수명 주기의 모든 단계에서 소스 코드의 보안을 개선하는 데 사용할 수 있습니다. 린팅을 사용하여 개발 프로세스 초기에 오류를 식별하고, SAST를 사용하여 코드가 컴파일되거나 배포되기 전에 취약점을 찾고, 라이선스 스캔을 사용하여 애플리케이션이 라이선스 약관을 준수하는지 확인할 수 있습니다.
이러한 기법을 사용하면 소스 코드의 보안을 개선하고 보안 침해 위험을 줄일 수 있습니다.
학습할 내용
이 실습에서는 소프트웨어 소스 코드를 보호하는 도구와 기법에 중점을 둡니다.
- 린트 작업
- 정적 애플리케이션 보안 테스트
- 라이선스 스캔
이 실습에서 사용되는 모든 도구와 명령어는 Cloud Shell에서 실행됩니다.
2. 설정 및 요구사항
자습형 환경 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.



- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로
PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다. - 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 전체 프로젝트를 삭제하면 됩니다. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.
Cloud Shell 편집기 시작
이 실습은 Google Cloud Shell 편집기에서 사용하도록 설계되고 테스트되었습니다. 편집기에 액세스하려면 다음 단계를 따르세요.
- https://console.cloud.google.com에서 Google 프로젝트에 액세스합니다.
- 오른쪽 상단에서 Cloud Shell 편집기 아이콘을 클릭합니다.

- 창 하단에 새 창이 열립니다.
- 편집기 열기 버튼을 클릭합니다.

- 오른쪽에 탐색기가 있고 중앙 영역에 편집기가 있는 편집기가 열립니다.
- 터미널 창도 화면 하단에서 사용할 수 있습니다.
- 터미널이 열려 있지 않으면 `ctrl+`` 키 조합을 사용하여 새 터미널 창을 엽니다.
환경 설정
이 실습에서 사용되는 명령어를 간소화하기 위해 GOPATH를 단일 디렉터리로 설정합니다.
export GOPATH=$HOME/gopath
작업을 저장할 디렉터리 만들기
mkdir -p workspace
cd workspace
소스 코드 저장소 클론
git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)
3. 린트 작업
린트 작업은 일반적인 스타일 기반 실수 또는 문법 관련 결함을 확인하는 데 사용됩니다. 린팅은 여러 팀에 걸쳐 공통 구문 패턴을 제공하여 보안을 지원하므로 코드 검토, 지식 공유, 코드 명확성이 향상됩니다.
또한 린팅은 라이브러리나 핵심 API의 부적절하거나 비효율적인 사용과 같은 일반적인 취약점으로 이어질 수 있는 일반적인 구문 실수를 식별합니다.
staticcheck 연결 도구 설치
go get honnef.co/go/tools/cmd/staticcheck@latest
프로젝트 루트 디렉터리에서 Go Linter (staticcheck)를 실행합니다.
staticcheck
출력 검토
main.go:42:29: unnecessary use of fmt.Sprintf (S1039)
http.ListenAndServe()는 문자열을 허용하는데 현재 코드는 문자열에 변수를 전달하지 않고 Sprintf를 사용하므로 오류가 발생합니다.
명령어 종료 상태를 검토합니다.
echo $?
이 경우 명령어에 오류가 발생했으므로 종료 상태는 1 이상입니다. 이는 CI/CD 파이프라인에서 도구의 성공/실패를 확인하는 데 사용할 수 있는 방법 중 하나입니다.
main.go 파일을 수정하고 코드를 수정합니다.
main()메서드 내에서LINTING - Step 1아래의 줄을 주석 처리합니다(//추가).main()메서드 내LINTING - Step 2바로 아래에 있는 두 줄의 주석 처리를 삭제하여 주석을 해제합니다.
프로젝트 루트 디렉터리에서 staticcheck를 다시 실행합니다.
staticcheck
명령어는 결과를 반환하지 않아야 합니다 (즉, 빈 줄).
명령어의 종료 상태를 검사합니다.
echo $?
이 경우 명령어에서 오류가 발생하지 않았으므로 종료 상태는 0입니다.
4. 정적 애플리케이션 보안 테스트
AST/정적 보안 테스트 - 일반적인 약점과 노출 ( CWE)을 찾는 정적 코드 분석을 제공합니다.
AST 도구 설치 (gosec)
export GOSEC_VERSION="2.15.0"
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | \
sh -s -- -b $(go env GOPATH)/bin v${GOSEC_VERSION}
정책 파일을 사용하여 소스 코드에 대해 gosec 실행
gosec -conf policies/gosec-policy.json -fmt=json ./...
출력은 다음과 비슷해야 합니다.
{
"Golang errors": {},
"Issues": [
{
"severity": "HIGH",
"confidence": "LOW",
"cwe": {
"ID": "798",
"URL": "https://cwe.mitre.org/data/definitions/798.html"
},
"rule_id": "G101",
"details": "Potential hardcoded credentials",
"file": "/home/random-user-here/shift-left-security-workshop/labs/source-code-lab/main.go",
"code": "31: \t// STEP 2: Change this and the reference below to something different (ie, not \"pawsword\" or \"password\")\n32: \tvar pawsword = \"im-a-cute-puppy\"\n33: \tfmt.Println(\"Something a puppy would use: \", username, pawsword)\n",
"line": "32",
"column": "6"
}
],
"Stats": {
"files": 1,
"lines": 89,
"nosec": 0,
"found": 1
}
}
도구에서 잠재적인 문제 Potential hardcoded credentials을(를) 확인했습니다.
5. 라이선스 스캔
라이선스는 공개하고 싶지 않은 소스 코드를 공개하도록 법적으로 요구할 수 있으므로 보안에 중요합니다. 이 개념을 '카피레프트' 라이선스라고 하며, 이러한 라이선스가 있는 종속 항목을 사용하는 경우 소스 코드를 공개해야 합니다.
golicense 설치
mkdir -p /tmp/golicense
wget -O /tmp/golicense/golicense.tar.gz https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz
pushd /tmp/golicense
tar -xzf golicense.tar.gz
chmod +x golicense
mv golicense $(go env GOPATH)/bin/golicense
popd
바이너리 파일 빌드
go build
'BSD-3-Clause' 라이선스를 허용하지 않는 현재 정책 파일로 라이선스 검사를 실행합니다.
golicense policies/license-policy.hcl hello-world
참고: 다음과 비슷한 출력으로 실패해야 합니다.
🚫 rsc.io/sampler BSD 3-Clause "New" or "Revised" License 🚫 rsc.io/quote BSD 3-Clause "New" or "Revised" License 🚫 golang.org/x/text BSD 3-Clause "New" or "Revised" License
정책 파일 policies/license-policy.hcl를 수정하여 deny 목록에서 allow 목록으로 'BSD-3-Clause'를 이동합니다.
라이선스 확인 다시 실행
golicense policies/license-policy.hcl hello-world
참고: 다음과 비슷한 출력으로 성공해야 합니다.
✅ rsc.io/quote BSD 3-Clause "New" or "Revised" License
✅ rsc.io/sampler BSD 3-Clause "New" or "Revised" License
✅ golang.org/x/text BSD 3-Clause "New" or "Revised" License
6. 축하합니다
축하합니다. Codelab을 완료했습니다.
학습한 내용
- 소스 코드를 보호하는 도구 및 기술
—
최종 업데이트: 2023년 3월 23일