gitリポジトリに何が保存されているか知っていますか?何百ものコミットの中に、誤ってそこに到達した製品サーバーからのパスワードはありますか?
しかし、公開時にansibleスクリプトがクラッシュし、ログ内のパスワードが強調表示された場合はどうなりますか?
このようなチェックを自動化する方法とその結果について説明します。
こんにちは、Habr!
私の名前はオレグです。ロシア連邦のかなり大きな銀行で、IT部門のIT部門で働いています。
(OPS) (ansible) .
2 git ( , ), , , , OPS .
, master OPS.
? git ( ) OPS. Jenkins git - ( ) OPS.
git? ?
, . secret management, HashiCorp Vault, CyberArk Conjur .
, .
, pull request .
, !
?
3 , :
---
dev_ssh_username1: "admin"
dev_ssh_password1: "admin123"
- .
shell command ansible
- name: Deploy
hosts: all
tasks:
- name: Update
shell: "update.sh --user={{ update_user }} --password={{ update_password }}"
, playbook -v .
$ ansible-playbook deploy.yml -i env/DEV/hosts -v
TASK [Update] ******************************************************************
changed: [192.168.1.2] => {"changed": true, "cmd": "/home/dev/update.sh --user=secret_user --password=secret_password", "delta": "0:00:05.056532", "end": "2020-11-06 09:53:09.397355", "rc": 0, "start": "2020-11-06 09:53:04.340823", "stderr": "", "stderr_lines": [], "stdout": "Update SUCCESS", "stdout_lines": ["Update SUCCESS"]}
, playbook ( -v)
$ ansible-playbook deploy.yml -i env/DEV/hosts
TASK [Update] ******************************************************************
fatal: [192.168.1.2]: FAILED! => {"changed": true, "cmd": "/home/dev/update.sh --user=secret_user --password=secret_password", "delta": "0:00:00.018710", "end": "2020-11-06 10:14:30.642419", "msg": "non-zero return code", "rc": 127, "start": "2020-11-06 10:14:30.623709", "stderr": "/bin/sh: /home/dev/update.sh: ", "stderr_lines": ["/bin/sh: /home/dev/update.sh: "], "stdout": "", "stdout_lines": []}
environment, :
- name: Deploy
hosts: all
tasks:
- name: Update
shell: "/home/dev/update.sh $AUTH_DATA"
environment:
AUTH_DATA: "--user={{ update_user }} --password={{ update_password }}"
credentials . no_log.
withCredentials
Jenkins, credentials withCredentials. pipeline credential, , . Jenkins .
, , :
node {
stage('Jenkins Credentials | Decrypt Secret File') {
withCredentials([file(credentialsId: 'credentials-id', variable: 'secretFile')]) {
sh 'cat $secretFile'
}
}
}
, , . , secretFile withCredentials.
, . ( ).
- SonarQube Hard-coded credentials are security-sensitive
C Checkmarx - . ( Application Security ). , :
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@RequestMapping("/show_me_creds")
public @ResponseBody String show_me_creds() {
String thisIsMyLittleSecret = "qwerty12345";
return thisIsMyLittleSecret;
}
}
opensource . google "find secrets in git" :
https://github.com/awslabs/git-secrets/blob/master/README.rst
https://github.com/dxa4481/truffleHog/blob/dev/README.md
https://github.com/Yelp/detect-secrets
https://github.com/zricethezav/gitleaks
Gitleaks, :
regexp, ;
;
json;
;
.
- toml , :
[[rules]]
description = "generic secret regex"
regex = '''secret(.{0,20})([0-9a-zA-Z-._{}$\/\+=]{20,120})'''
tags = ["secret", "example"]
, :
[[rules]]
description = "entropy and regex example"
regex = '''secret(.{0,20})([0-9a-zA-Z-._{}$\/\+=]{20,120})'''
[[rules.Entropies]]
Min = "4.5"
Max = "4.7"
:
➜ ~ gitleaks --repo=gitleaks --repo=https://github.com/gitleakstest/gronit.git --verbose --pretty
INFO[2020-04-28T13:00:34-04:00] cloning... https://github.com/gitleakstest/gronit.git
Enumerating objects: 135, done.
Total 135 (delta 0), reused 0 (delta 0), pack-reused 135
{
"line": "const AWS_KEY = \"AKIALALEMEL33243OLIAE\"",
"offender": "AKIALALEMEL33243OLIA",
"commit": "eaeffdc65b4c73ccb67e75d96bd8743be2c85973",
"repo": "gronit.git",
"rule": "AWS Manager ID",
"commitMessage": "remove fake key",
"author": "Zachary Rice",
"email": "zricethezav@users.noreply.github.com",
"file": "main.go",
"date": "2018-02-04T19:43:28-06:00",
"tags": "key, AWS"
}
...
...
WARN[2020-04-28T13:00:35-04:00] 6 leaks detected. 33 commits audited in 77 milliseconds 738 microseconds
, gitleaks - .
- whitelist , :
[[rules]]
description = "entropy and regex example"
regex = '''secret(.{0,20})['|"]([0-9a-zA-Z-._{}$\/\+=]{20,120})['|"]'''
[[rules.Entropies]]
Min = "4.5"
Max = "4.7"
[[rules.whitelist]]
regex = '''secret.some_value_that_match_regexp_but_not_really_a_secret'''
description = "ignore that string"
- pull request webhook Jenkins, , gitleaks - NEED WORK.
, , gitleaks ( ).
ansible
, , playbook, Jenkins .
- name: Deploy
hosts: all
tasks:
- name: Update
shell: "update.sh --user={{ update_user }} --password={{ update_password }}"
, Ansible Lint.
Ansible, " " , .
2 :
;
playbook. , .
- python , id, short description, description tags ( Ansible Lint ) match matchtask, . .
matchtask, task, .
class CommandsInsteadOfModulesRule(AnsibleLintRule):
id = '303'
shortdesc = 'Using command rather than module'
description = (
'Executing a command when there is an Ansible module '
'is generally a bad idea'
)
severity = 'HIGH'
tags = ['command-shell', 'resources', 'ANSIBLE0006']
_commands = ['command', 'shell']
_modules = {
'apt-get': 'apt-get',
# ,
'yum': 'yum',
}
def matchtask(self, file, task):
if task['action']['__ansible_module__'] not in self._commands:
return
first_cmd_arg = get_first_cmd_arg(task)
if not first_cmd_arg:
return
executable = os.path.basename(first_cmd_arg)
if executable in self._modules and \
boolean(task['action'].get('warn', True)):
message = '{0} used in place of {1} module'
return message.format(executable, self._modules[executable])
- task command shell _modules - .
- (password/pass/login ) command shell .
no_log, . no_log - .
, Gitleaks Ansible Lint, . , .. ( ).
withCredentials
, Jenkinsfile , ( ).
node {
stage('Jenkins Credentials | Decrypt Secret File') {
withCredentials([file(credentialsId: 'credentials-id', variable: 'secretFile')]) {
sh 'cat $secretFile'
}
}
}
.
Jenkinsfile groovy, Abstract Syntax Tree . AstBuilder , withCredentials, withCredentials. , .
, secretFile - stage, secretFile .
1000 , , .
, pipeline Pipeline model definition plugin, pipeline json . - .
?
, 1000 pull request. 3% gitleaks, , ansible.
, OPS .
, :
-
https://www.shellcheck.net/ - shell .
https://github.com/PyCQA/bandit - security linter python.
https://twitter.com/leak_scavenger は、github、pastebin、ghostbinで秘密、クレジットカード、秘密鍵などをスキャンする興味深いTwitterボットです。もちろん、情報源は入手可能です。