softasap.sa_box_bootstap
Przygotuj swoją maszynę do wdrożenia
Tło
Obecnie wdrożenia przeniosły się z serwerów bare metal na szybko uruchamiane wirtualne maszyny, takie jak te dostarczane przez Amazon, Digital Ocean czy dostawców opartych na OpenStack. W związku z tym, konfiguracja maszyn przestała wymagać ręcznych kroków administracyjnych. Jedną z opcji są gotowe do użycia prekonfigurowane obrazy maszyn. Innym podejściem jest rozpoczęcie od przestarzałej instalacji systemu i skonfigurowanie go zgodnie z potrzebami projektu przy użyciu narzędzi takich jak Ansible, Chef czy Puppet.
Pierwszym krokiem w dostosowywaniu wdrożenia jest ochrona podstawowa maszyny, gdyż czasem otrzymujesz nowo zainstalowany serwer z hasłem do roota.
Podzielę się z Wami szybkim przewodnikiem na temat zabezpieczania nowej maszyny, który powinien być odpowiedni dla większości wdrożeń webowych.
Wyzwania do rozwiązania
Na końcu artykułu powinniśmy być w stanie zabezpieczyć wirtualny serwer Ubuntu 14.04 LTS.
- skonfigurować zaporę, zezwalając tylko na porty 22, 443 i 80
- zarejestrować swoje klucze publiczne dla użytkownika wdrożeniowego
- zabezpieczyć SSH, aby zezwolić tylko na autoryzację za pomocą kluczy
- uruchomić automatyczny proces, aby zbanować osoby próbujące uzyskać dostęp do portu SSH z internetu.
Rola bootstrap box
Ansible wprowadza przyjemny koncept ponownego używania fragmentów wdrożeniowych, które nazywa się rolami. Przyjrzyjmy się, co robi rola sa-box-bootstrap:
Opcje konfiguracyjne
Następujące zmienne mogą być nadpisywane:
- root_dir - wymagane, przepisy dla programistów Ansible
- option_enforce_ssh_keys_login (true|false) - czy wymusić zabezpieczenie SSH
- ufw_rules_default - domyślna polityka zapory. W większości przypadków nie jest modyfikowana
- ufw_rules_allow - zestaw reguł przychodzących do skonfigurowania
- sshd_config_lines - potrzebne zmiany w konfiguracji SSHD, aby zabezpieczyć maszynę.
- option_file2ban - jeśli prawda, dodatkowo zainstalowany zostanie pakiet file2ban
- whitelistedips - zestaw adresów IP, które są uważane za bezpieczne - brama biura, serwer budowlany itp.; aby zapobiec przypadkowemu zablokowaniu się
Krok 1: Włącz zaporę
Pierwszym krokiem jest zainstalowanie i skonfigurowanie zapory ufw:
- include: "{{root_dir}}/tasks_ufw.yml"
Domyślnie stosowane są następujące zasady zapory (wychodzące wszędzie, http, https i ssh dozwolone przychodzące):
ufw_rules_default:
- {
policy: deny,
direction: incoming
}
- {
policy: allow,
direction: outgoing
}
ufw_rules_allow:
- {
port: 80,
proto: tcp
}
- {
port: 443,
proto: tcp
}
- {
port: 22,
proto: tcp
}
Możesz nadpisać te zmienne, aby pasowały do Twoich potrzeb.
Krok 2: Utwórz użytkownika wdrożeniowego
Jeśli zamierzasz pracować i konfigurować tę maszynę, prawdopodobnie nie chcesz tego robić jako root. Drugim krokiem jest utworzenie użytkownika wdrożeniowego, autoryzowanego przez zestaw dostarczonych kluczy SSH, upoważnionego do korzystania z sudo bez hasła (podstawa dla automatycznego wdrożenia):
- include: "{{root_dir}}/use/__create_deploy_user.yml user={{deploy_user}} group={{deploy_user}} home=/home/{{deploy_user}}"
when: deploy_user is defined
- name: SSH | Autoryzuj klucze
authorized_key: user={{deploy_user}} key="{{ lookup('file', item) }}"
when: deploy_user_keys is defined
with_items: "{{deploy_user_keys}}"
sudo: yes
Możesz zdefiniować użytkownika w swoim playbooku, na przykład w ten sposób:
jenkins_user: jenkins
jenkins_authorized_keys:
- "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"
A następnie przekazać to jako parametry do roli:
roles:
- {
role: "sa-box-bootstrap",
root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
deploy_user: "{{jenkins_user}}",
deploy_user_keys: "{{jenkins_authorized_keys}}"
}
Krok 3: Zabezpiecz SSH (opcjonalnie)
- name: SSH | Wymuś zabezpieczenie kluczy SSH
lineinfile: dest=/etc/ssh/sshd_config regexp="{{item.regexp}}" line="{{item.line}}"
with_items: "{{sshd_config_lines}}"
when: option_enforce_ssh_keys_login
become: true
tags: ssh
Jeśli zmienna option_enforce_ssh_keys_login jest ustawiona na true, konfiguracja sshd jest zmieniana zgodnie z zasadami sshd_config_lines. Domyślnie używa protokołu v2, zabraniając logowania roota, zabraniając autoryzacji hasłem.
Krok 4: Zbanowanie niechcianych osób próbujących zgadnąć dostęp użytkownika SSH
Jeśli zmienna option_file2ban jest włączona, zostanie zainstalowane specjalne narzędzie file2ban. Będzie monitorować nieudane próby logowania SSH i banować intruzów. Aby zapobiec przypadkowemu zablokowaniu, dobrze jest dodać adresy IP do białej listy, zarówno pojedyncze adresy IP, jak i maski sieciowe są obsługiwane, na przykład:
whitelistedips:
- 127.0.0.1
- 127.0.0.1/8
Tworzenie własnego projektu bootstrap
Przygotujmy podstawowy projekt bootstrap, który można wykorzystać w przyszłości. Zawiera on następujące pliki:
- bootstrap.sh - instalacja ansible wraz z zależnościami.
- init.sh - inicjalizacja
- .projmodules - w pełni zgodny z .gitmodules składnią git, zawiera listę zależności, które będą używane przez playbook. W szczególności zawiera ansible - domyślnie developer_recipes (repozytorium z zestawem przydatnych przepisów instalacyjnych) oraz rolę ansible nazwaną sa-box-bootstrap, odpowiedzialną za kroki zabezpieczające maszynę.
[submodule "public/ansible_developer_recipes"]
path = public/ansible_developer_recipes
url = [email protected]:Voronenko/ansible-developer_recipes.git
[submodule "roles/sa-box-bootstrap"]
path = roles/sa-box-bootstrap
url = [email protected]:softasap/sa-box-bootstrap.git
- hosts - wprowadź tutaj dane logowania do początkowej maszyny, które zostały Ci dostarczone dla serwera.
[bootstrap]
box_bootstrap ansible_ssh_host=192.168.0.17 ansible_ssh_user=twoj_uzytkownik ansible_ssh_pass=twoje_haslo
- box_vars.yml - ustaw tutaj specyficzne nadpisania środowiskowe, takie jak preferowana nazwa użytkownika wdrożeniowego i klucze.
- box_bootstrap.yml - tutaj wpisz kroki dotyczące provisioningu maszyny. Zabezpieczanie maszyny to tylko pierwszy krok. Aby nadpisać parametry dla sa-box-bootstrap, przekaż parametry, jak w poniższym przykładzie.
- hosts: all
vars_files:
- ./box_vars.yml
roles:
- {
role: "sa-box-bootstrap",
root_dir: "{{playbook_dir}}/public/ansible_developer_recipes",
deploy_user: "{{my_deploy_user}}",
deploy_user_keys: "{{my_deploy_authorized_keys}}"
}
Przykład użycia
Kod można pobrać z repozytorium https://github.com/Voronenko/devops-bootstrap-box-template. Aby go użyć, zrób forka, dostosuj parametry do swoich potrzeb i użyj. Dostosowanie obejmuje: utworzenie pliku box_vars.yml. Możesz tam nadpisać dowolne ze wspomnianych zmiennych. Minimalny wymagany zestaw to deploy_user oraz Twoje klucze publiczne.
box_deploy_user: jenkins
box_deploy_authorized_keys:
- "{{playbook_dir}}/components/files/ssh/vyacheslav.pub"
Upewnij się, że masz zainstalowane ansible (bootstrap.sh służy do instalacji) i sklonowane katalogi ról (init.sh). Następnie uruchom setup.sh. Jeśli wszystko jest poprawnie skonfigurowane, powinieneś zobaczyć coś takiego:
PLAY [all] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [box_bootstrap]
TASK: [sa-box-bootstrap | Ustaw poprawnie nazwę hosta] ****************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | debug var="ufw_rules_allow"] ************************
ok: [box_bootstrap] => {
"var": {
"ufw_rules_allow": [
{
"port": 80,
"proto": "tcp"
},
{
"port": 443,
"proto": "tcp"
},
{
"port": 22,
"proto": "tcp"
}
]
}
}
TASK: [sa-box-bootstrap | UFW | Resetowanie] *************************************
ok: [box_bootstrap]
TASK: [sa-box-bootstrap | UFW | Konfiguracja domyślnych zasad przychodzących/wychodzących] *************
ok: [box_bootstrap] => (item={'policy': 'deny', 'direction': 'incoming'})
ok: [box_bootstrap] => (item={'policy': 'allow', 'direction': 'outgoing'})
TASK: [sa-box-bootstrap | UFW | Konfiguracja zasad zezwalających na ruch przychodzący] ****
ok: [box_bootstrap] => (item={'port': 80, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 443, 'proto': 'tcp'})
ok: [box_bootstrap] => (item={'port': 22, 'proto': 'tcp'})
TASK: [sa-box-bootstrap | UFW | Konfiguracja zasad zezwalających na ruch przychodzący od określonych hostów] ***
skipping: [box_bootstrap] => (item=ufw_rules_allow_from_hosts)
TASK: [sa-box-bootstrap | UFW | Włącz z powrotem] ************************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Monit | Sprawdzenie, czy jest zainstalowany] **********************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Monit | Zależność libssl-dev] **********************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Monit | Pobierz] ***********************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Monit | Zainstaluj] ************************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | debug msg="Tworzenie użytkownika wdrożeniowego {{my_deploy_user}}:{{my_deploy_user}} z katalogiem domowym /home/{{my_deploy_user}}"] ***
ok: [box_bootstrap] => {
"msg": "Tworzenie użytkownika wdrożeniowego jenkins:jenkins z katalogiem domowym /home/jenkins"
}
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Tworzenie grupy] ***********************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Tworzenie użytkownika] ************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Sprawdź obecność klucza] *******************
ok: [box_bootstrap]
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Kopiowanie authorized_keys z {{ansible_user_id}}] ***
skipping: [box_bootstrap]
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Ustawienie uprawnień dla authorized_keys] ****
skipping: [box_bootstrap]
TASK: [sa-box-bootstrap | Użytkownik wdrożeniowy | Zapewnienie, że sudoerzy nie będą proszeni o hasło] ****
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | SSH | Autoryzuj klucze] *******************************
changed: [box_bootstrap] => (item=/home/slavko/labs/devops-bootstrap-box-template/components/files/ssh/vyacheslav.pub)
TASK: [sa-box-bootstrap | SSH | Wymuś zabezpieczenie kluczy SSH] ********************
ok: [box_bootstrap] => (item={'regexp': '^Protocol.*', 'line': 'Protocol 2'})
changed: [box_bootstrap] => (item={'regexp': '^PermitRootLogin.*', 'line': 'PermitRootLogin no'})
ok: [box_bootstrap] => (item={'regexp': '^RSAAuthentication.*', 'line': 'RSAAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^PubkeyAuthentication.*', 'line': 'PubkeyAuthentication yes'})
ok: [box_bootstrap] => (item={'regexp': '^ChallengeResponseAuthentication.*', 'line': 'ChallengeResponseAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^PasswordAuthentication.*', 'line': 'PasswordAuthentication no'})
changed: [box_bootstrap] => (item={'regexp': '^MaxAuthTries.*', 'line': 'MaxAuthTries 3'})
TASK: [sa-box-bootstrap | SSH | Restartuj SSHD] *********************************
changed: [box_bootstrap]
TASK: [sa-box-bootstrap | Zainstaluj podstawowe pakiety Ubuntu] ***********************
changed: [box_bootstrap] => (item=unzip,mc)
PLAY RECAP ********************************************************************
box_bootstrap : ok=21 changed=13 unreachable=0 failed=0
W końcu - masz zabezpieczoną maszynę, z użytkownikiem wdrożeniowym, którego zdefiniowałeś, który może autoryzować się tylko za pomocą kluczy, które ustawiłeś. Logowanie roota jest zabronione. Tylko określone porty są dozwolone zgodnie z Twoimi zasadami.
Sprawdź przy pomocy NMap i spróbuj się zalogować:
ssh 192.168.0.17
Permission denied (publickey).
ssh -ldeploy_user 192.168.0.17
Witamy w Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-32-generic x86_64)
deploy_user@LABBOX17:~$
Punkty zainteresowania
Możesz ponownie wykorzystać ten playbook do tworzenia własnych projektów bootstrappingowych i używać roli do szybszej konfiguracji środowisk w sposób bezpieczny przy użyciu ansible.
Role to perform basic securing of fresh instance for further automated deploy
ansible-galaxy install softasap.sa_box_bootstap