Tämä harjoitus on tehty osana Haaga-Helian Tietojenkäsittelyn koulutusohjelman kurssia Palvelinten hallinta (ICT4TN022, kevät 2018). Kurssin pitäjänä toimii Tero Karvinen, joka on määritellyt tämän harjoituksen tehtävänkuvaukset. Tehtävien vastaukset ovat Pekka Heleniuksen (allekirjoittanut) tuottamia.
Vastaus:
Luodaan tiedosto /srv/salt/firstninja.sls seuraavalla sisällöllä (sudo nano /srv/salt/firstninja.sls):
(Tehtävänannon vaatimus täyttyy state:ssa put_my_foo_stuff)
# Author: Pekka Helenius (~Fincer), 2018
hostile_secondgroup:
group.present:
- name: foobar
- gid: 666
- system: True
hostile_user:
user.present:
- name: evilninja
- fullname: Evil Ninja
- uid: 666
- gid: 666
- shell: /bin/bash
- home: /home/foo
- groups:
- foobar
- require:
- group: hostile_secondgroup
put_my_foo_stuff:
file.managed:
- name: /foo/mysecretfoo
- source: salt://foofile
- makedirs: True
- user: 666
- group: 666
- mode: 0744
- template: jinja
- context:
supersecretfoo: 'you never know where this came from'
notsosecretbar: 'wanna beer?'
- require:
- user: hostile_user
foo_executable:
file.symlink:
- name: /usr/local/bin/mysecretfoo
- target: /foo/mysecretfoo
- require:
- file: put_my_foo_stuff
evil_nullfiles:
cmd.run:
- name: 'touch ./foo_everywhere'
- cwd: /foo
- creates: foo_everywhere
- creates: foofoo
- require:
- file: put_my_foo_stuff
identity_crisis:
cmd.run:
- name: /usr/bin/id -a
- runas: evilninja
- require:
- user: hostile_user
haha_execute:
cmd.run:
- shell: /bin/sh
- name: mysecretfoo
- require:
- user: hostile_user
- file: foo_executable
Lisätään masterille tiedosto /srv/salt/foofile seuraavalla sisällöllä (sudo nano /srv/salt/foofile):
#!/bin/sh
echo -e "{{ supersecretfoo }}\n{{ notsosecretbar }}"
Tämä tiedosto kirjoitetaan minionin/minioneiden kohteeseen /foo/mysecretfoo ja luodaan symbolinen linkki /usr/local/bin/mysecretfoo.
Testataan toimivuus harjoituksessa 1 ja 2 käytetyllä master-minion -tietokonekokoonpanolla (master: master, minion: orjakone):
sudo salt 'orjakone' state.apply firstninja
Masterilla tulostettu output:
orjakone:
----------
ID: hostile_secondgroup
Function: group.present
Name: foobar
Result: True
Comment: Group foobar is present and up to date
Started: 21:52:22.010941
Duration: 1.317 ms
Changes:
----------
ID: hostile_user
Function: user.present
Name: evilninja
Result: True
Comment: User evilninja is present and up to date
Started: 21:52:22.012741
Duration: 13.69 ms
Changes:
----------
ID: put_my_foo_stuff
Function: file.managed
Name: /foo/mysecretfoo
Result: True
Comment: File /foo/mysecretfoo is in the correct state
Started: 21:52:22.027375
Duration: 10.438 ms
Changes:
----------
ID: foo_executable
Function: file.symlink
Name: /usr/local/bin/mysecretfoo
Result: True
Comment: Created new symlink /usr/local/bin/mysecretfoo -> /foo/mysecretfoo
Started: 21:52:22.038030
Duration: 26.087 ms
Changes:
----------
new:
/usr/local/bin/mysecretfoo
----------
ID: evil_nullfiles
Function: cmd.run
Name: touch ./foo_everywhere
Result: True
Comment: Command "touch ./foo_everywhere" run
Started: 21:52:22.066037
Duration: 8.669 ms
Changes:
----------
pid:
3426
retcode:
0
stderr:
stdout:
----------
ID: identity_crisis
Function: cmd.run
Name: /usr/bin/id -a
Result: True
Comment: Command "/usr/bin/id -a" run
Started: 21:52:22.074865
Duration: 158.997 ms
Changes:
----------
pid:
3450
retcode:
0
stderr:
stdout:
uid=666(evilninja) gid=666(foobar) groups=666(foobar)
----------
ID: haha_execute
Function: cmd.run
Name: mysecretfoo
Result: True
Comment: Command "mysecretfoo" run
Started: 21:52:22.234242
Duration: 14.473 ms
Changes:
----------
pid:
3455
retcode:
0
stderr:
stdout:
-e you never know where this came from
wanna beer?
Summary for orjakone
------------
Succeeded: 7 (changed=4)
Failed: 0
------------
Total states run: 7
Total run time: 233.671 ms
Vastaus:
Luodaan master:lle tiedosto /srv/salt/first_jinjaloop.sls seuraavalla sisällöllä (sudo nano /srv/salt/first_jinjaloop.sls):
# Author: Pekka Helenius (~Fincer), 2018
{% for loplop in ['round_1', 'round_2', 'round_3', 'round_4'] %}
loopsloops_noops{{ loop.index }}:
file.managed:
- name: /tmp/loopnoops/{{ loplop }}
- source: salt://loops/jinjaninja_loop
- makedirs: True
- template: jinja
- context:
filenumber: {{ loplop }}
run_fatboy_run_{{ loop.index }}:
cmd.run:
- name: cat /tmp/loopnoops/{{ loplop }}
- require:
- file: loopsloops_noops{{ loop.index }}
{% endfor %}
Luodaan masterilla tiedosto /srv/salt/loops/jinjaninja_loop:
sudo mkdir -p /srv/salt/loops
echo "Loops loops noops {{ filenumber }}" | sudo tee /srv/salt/loops/jinjaninja_loop
Ajetaan luotu state-tiedosto masterilta orjakone-minionille:
sudo salt 'orjakone' state.apply first_jinjaloop
Masterilta saatu output:
orjakone:
----------
ID: loopsloops_noops1
Function: file.managed
Name: /tmp/loopnoops/round_1
Result: True
Comment: File /tmp/loopnoops/round_1 updated
Started: 22:15:48.402678
Duration: 22.99 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: run_fatboy_run_1
Function: cmd.run
Name: cat /tmp/loopnoops/round_1
Result: True
Comment: Command "cat /tmp/loopnoops/round_1" run
Started: 22:15:48.426279
Duration: 9.155 ms
Changes:
----------
pid:
3654
retcode:
0
stderr:
stdout:
Loops loops noops round_1
----------
ID: loopsloops_noops2
Function: file.managed
Name: /tmp/loopnoops/round_2
Result: True
Comment: File /tmp/loopnoops/round_2 updated
Started: 22:15:48.435550
Duration: 18.288 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: run_fatboy_run_2
Function: cmd.run
Name: cat /tmp/loopnoops/round_2
Result: True
Comment: Command "cat /tmp/loopnoops/round_2" run
Started: 22:15:48.454122
Duration: 5.179 ms
Changes:
----------
pid:
3656
retcode:
0
stderr:
stdout:
Loops loops noops round_2
----------
ID: loopsloops_noops3
Function: file.managed
Name: /tmp/loopnoops/round_3
Result: True
Comment: File /tmp/loopnoops/round_3 updated
Started: 22:15:48.459403
Duration: 19.723 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: run_fatboy_run_3
Function: cmd.run
Name: cat /tmp/loopnoops/round_3
Result: True
Comment: Command "cat /tmp/loopnoops/round_3" run
Started: 22:15:48.479414
Duration: 6.602 ms
Changes:
----------
pid:
3658
retcode:
0
stderr:
stdout:
Loops loops noops round_3
----------
ID: loopsloops_noops4
Function: file.managed
Name: /tmp/loopnoops/round_4
Result: True
Comment: File /tmp/loopnoops/round_4 updated
Started: 22:15:48.486128
Duration: 18.883 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: run_fatboy_run_4
Function: cmd.run
Name: cat /tmp/loopnoops/round_4
Result: True
Comment: Command "cat /tmp/loopnoops/round_4" run
Started: 22:15:48.505300
Duration: 9.609 ms
Changes:
----------
pid:
3660
retcode:
0
stderr:
stdout:
Loops loops noops round_4
Summary for orjakone
------------
Succeeded: 8 (changed=8)
Failed: 0
------------
Total states run: 8
Total run time: 110.429 ms
Vastaus:
HUOM! Koska tehtävänannossa ei pyydetty käyttämään master-koneella sijaitsevaa esimääritettyä SSHD:n konfiguraatiotiedostoa ja pyydettiin vaihtamaan pelkkä SSHD:n yhteysportti minionille/minioneille, on SLS-tiedosto rakennettu tämän esivaatimuksen pohjalta. Yleisesti voidaan haluta samat asetukset kaikille minioneille, jolloin tulee käyttää esimääritettyä SSHD:n konfiguraatiotiedostoa, joka korvaa minionilla/minioneilla olevan tiedoston.
Halusin kokeilla jinja:lla lukujen generointia tässä tehtävässä. Olisi voitu toki käyttää ennalta määriteltyä porttia, mutta hauskempaa generoida jotain satunnaista. Soveltuuko tämä käyttökohteeseen, it's up to you.
SSH-portti generoidaan väliltä 23-600. Käytetään seuraavaa sisältöä uuteen state-tiedostoon.
Luodaan masterille tiedosto srv/salt/ssh_random/init.sls (sudo mkdir -p /srv/salt/ssh_random && sudo nano /srv/salt/ssh_random/init.sls):
# Author: Pekka Helenius (~Fincer), 2018
{% set supersecret_ssh_port = range(23, 600) | random %}
check_sshd_install:
pkg.installed:
- pkgs:
- openssh-server # Ubuntu specific
check_sshd_config:
file.managed:
- name: /etc/ssh/sshd_config
- require:
- pkg: check_sshd_install
check_sshd_current_port:
cmd.run:
- name: 'echo "current SSH daemon port for $(hostname) (Salt ID: {{ grains['id'] }}) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"'
- require:
- file: check_sshd_config
prevent_if_ssh_sessions_open:
cmd.run:
- names:
- 'SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname) (Salt ID: {{ grains['id'] }}): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi'
- unset SSH_SESSIONS
- require:
- file: check_sshd_config
- cmd: check_sshd_current_port
new_ssh_port:
file.replace:
- name: /etc/ssh/sshd_config
- pattern: '^[#P]+ort [0-9][0-9]*'
- repl: 'Port {{ supersecret_ssh_port }}'
- require:
- cmd: prevent_if_ssh_sessions_open
sshd_restart:
service.running:
- name: ssh.service # Yes, this is the daemon process
- watch:
- file: new_ssh_port
ssh_new_port_inform:
cmd.run:
- name: 'echo "new SSH daemon port for $(hostname) (Salt ID: {{ grains['id'] }}) is {{ supersecret_ssh_port }}"'
- require:
- service: sshd_restart
- file: new_ssh_port
Ajetaan ssh_random -state masterilta kaikille yhteydessä oleville minioneille:
sudo salt '*' state.apply ssh_random
Masterilla saatu output minionille "orjakone":
orjakone:
----------
ID: check_sshd_install
Function: pkg.installed
Result: True
Comment: All specified packages are already installed
Started: 14:26:13.249172
Duration: 416.921 ms
Changes:
----------
ID: check_sshd_config
Function: file.managed
Name: /etc/ssh/sshd_config
Result: True
Comment: File /etc/ssh/sshd_config exists with proper permissions. No changes made.
Started: 14:26:13.668542
Duration: 1.195 ms
Changes:
----------
ID: check_sshd_current_port
Function: cmd.run
Name: echo "current SSH daemon port for $(hostname) (Salt ID: orjakone) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"
Result: True
Comment: Command "echo "current SSH daemon port for $(hostname) (Salt ID: orjakone) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"" run
Started: 14:26:13.671432
Duration: 4.479 ms
Changes:
----------
pid:
2813
retcode:
0
stderr:
stdout:
current SSH daemon port for minion (Salt ID: orjakone) is: Port 22
----------
ID: prevent_if_ssh_sessions_open
Function: cmd.run
Name: SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname) (Salt ID: orjakone): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi
Result: True
Comment: Command "SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname) (Salt ID: orjakone): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi" run
Started: 14:26:13.676350
Duration: 13.544 ms
Changes:
----------
pid:
2816
retcode:
0
stderr:
stdout:
----------
ID: prevent_if_ssh_sessions_open
Function: cmd.run
Name: unset SSH_SESSIONS
Result: True
Comment: Command "unset SSH_SESSIONS" run
Started: 14:26:13.690114
Duration: 3.341 ms
Changes:
----------
pid:
2823
retcode:
0
stderr:
stdout:
----------
ID: new_ssh_port
Function: file.replace
Name: /etc/ssh/sshd_config
Result: True
Comment: Changes were made
Started: 14:26:13.693988
Duration: 4.119 ms
Changes:
----------
diff:
---
+++
@@ -10,7 +10,7 @@
# possible, but leave them commented. Uncommented options override the
# default value.
-Port 22
+Port 199
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
----------
ID: sshd_restart
Function: service.running
Name: ssh.service
Result: True
Comment: Service restarted
Started: 14:26:13.724516
Duration: 31.875 ms
Changes:
----------
ssh.service:
True
----------
ID: ssh_new_port_inform
Function: cmd.run
Name: echo "new SSH daemon port for $(hostname) (Salt ID: orjakone) is 199"
Result: True
Comment: Command "echo "new SSH daemon port for $(hostname) (Salt ID: orjakone) is 199"" run
Started: 14:26:13.756793
Duration: 7.15 ms
Changes:
----------
pid:
2832
retcode:
0
stderr:
stdout:
new SSH daemon port for minion (Salt ID: orjakone) is 199
Summary for orjakone
------------
Succeeded: 8 (changed=6)
Failed: 0
------------
Total states run: 8
Total run time: 482.624 ms
Näyttäisi siltä, että portti 199 on generoitu uudeksi SSH daemonin yhteysportiksi koneelle 'orjakone'. Varmistetaan tietojen oikeellisuus. Tämän voi tehdä etänä SSH-yhteyden avulla muultakin koneelta (testataan yhteyden toimivuus orjakoneen IP:een SSH clientilla porttia 199 käyttäen), mutta tässä varmistamme SSH-yhteyden toimivuuden portissa 199 suoraan minionin näkymästä:
/etc/ssh/sshd_config -tiedoston sisältöä SSH-client testauksineen orjakoneen näkymästä ylläolevan ajon jälkeen:
Toinen esimerkki:
Lisänä - SSH-portin vaihtamisen estäminen, jos SSH-yhteyksiä on muodostettu minionille
Jos SSH-yhteyksiä on minionilla auki, voimme haluta estää portin vaihtamisen kesken kaiken. Yllä olevassa SLS-tiedostossa tämä on määritetty state:lla prevent_if_ssh_sessions_open.
Masterin output, jos minionilla on SSH-yhteyksiä auki:
orjakone:
----------
ID: check_sshd_install
Function: pkg.installed
Result: True
Comment: All specified packages are already installed
Started: 14:29:50.043605
Duration: 390.748 ms
Changes:
----------
ID: check_sshd_config
Function: file.managed
Name: /etc/ssh/sshd_config
Result: True
Comment: File /etc/ssh/sshd_config exists with proper permissions. No changes made.
Started: 14:29:50.436782
Duration: 1.099 ms
Changes:
----------
ID: check_sshd_current_port
Function: cmd.run
Name: echo "current SSH daemon port for $(hostname) (Salt ID: orjakone) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"
Result: True
Comment: Command "echo "current SSH daemon port for $(hostname) (Salt ID: orjakone) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"" run
Started: 14:29:50.438437
Duration: 3.965 ms
Changes:
----------
pid:
2987
retcode:
0
stderr:
stdout:
current SSH daemon port for minion (Salt ID: orjakone) is: Port 379
----------
ID: prevent_if_ssh_sessions_open
Function: cmd.run
Name: SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname) (Salt ID: orjakone): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi
Result: False
Comment: Command "SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname) (Salt ID: orjakone): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi" run
Started: 14:29:50.442778
Duration: 11.447 ms
Changes:
----------
pid:
2990
retcode:
1
stderr:
stdout:
-e minion (Salt ID: orjakone): The following established SSH session were found:
tcp6 0 0 ::1:379 ::1:36896 ESTABLISHED 2869/sshd: fincer [
Not changing SSH daemon port.
----------
ID: prevent_if_ssh_sessions_open
Function: cmd.run
Name: unset SSH_SESSIONS
Result: True
Comment: Command "unset SSH_SESSIONS" run
Started: 14:29:50.454451
Duration: 3.132 ms
Changes:
----------
pid:
2998
retcode:
0
stderr:
stdout:
----------
ID: new_ssh_port
Function: file.replace
Name: /etc/ssh/sshd_config
Result: False
Comment: One or more requisite failed: ssh_random.prevent_if_ssh_sessions_open
Changes:
----------
ID: sshd_restart
Function: service.running
Name: ssh.service
Result: False
Comment: One or more requisite failed: ssh_random.new_ssh_port
Changes:
----------
ID: ssh_new_port_inform
Function: cmd.run
Name: echo "new SSH daemon port for $(hostname) (Salt ID: orjakone) is 258"
Result: False
Comment: One or more requisite failed: ssh_random.sshd_restart, ssh_random.new_ssh_port
Changes:
Summary for orjakone
------------
Succeeded: 4 (changed=3)
Failed: 4
------------
Total states run: 8
Total run time: 410.391 ms
ERROR: Minions returned with non-zero exit code
Vastaus:
Valitaan henkilön Oliver Siren harjoitus 3:n Salt state, Jinja for-in loop -tehtävän vastaus.
Ladataan wget-komennolla init.sls-tiedosto masterilla paikalliseen kansioon /srv/salt/student_sample:
SLS-tiedostossa on oletettu, että tiedosto /srv/salt/jinja/fool.txt on olemassa masterilla. Koska sitä ei ole, me luomme sen alla olevassa komentorimpsussa.
sudo -- sh -c ' \
mkdir -p /srv/salt/student_sample && mkdir -p /srv/salt/jinja && \
wget https://raw.githubusercontent.com/Oliver-Siren/palvelinten-hallinta-ict4tn022-4/master/assignments/h3.md -O /srv/salt/student_sample/init.sls && \
sed -i '51,61!d' /srv/salt/student_sample/init.sls && \
echo "This is your {{ file }}" > /srv/salt/jinja/fool.txt
'
Ajetaan tila masterilta kaikille saataville orja-alkuisille minioneille:
sudo salt 'orja*' state.apply student_sample
Masterilla saatu output:
orjakone:
----------
ID: /tmp/fool/first.txt
Function: file.managed
Result: True
Comment: File /tmp/fool/first.txt updated
Started: 00:16:20.842493
Duration: 25.759 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: /tmp/fool/second.txt
Function: file.managed
Result: True
Comment: File /tmp/fool/second.txt updated
Started: 00:16:20.868344
Duration: 19.281 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: /tmp/fool/third.txt
Function: file.managed
Result: True
Comment: File /tmp/fool/third.txt updated
Started: 00:16:20.887697
Duration: 17.221 ms
Changes:
----------
diff:
New file
mode:
0644
----------
ID: /tmp/fool/fourth.txt
Function: file.managed
Result: True
Comment: File /tmp/fool/fourth.txt updated
Started: 00:16:20.904989
Duration: 19.971 ms
Changes:
----------
diff:
New file
mode:
0644
Summary for orjakone
------------
Succeeded: 4 (changed=4)
Failed: 0
------------
Total states run: 4
Total run time: 82.232 ms
Wget:llä ladatun ja sed:llä parsitun esimerkki-SLS -tiedoston sisältö:
{% for tiedosto in ['first.txt', 'second.txt', 'third.txt', 'fourth.txt'] %}
/tmp/fool/{{ tiedosto }}:
file.managed:
- source: salt://jinja/fool.txt
- makedirs: True
- template: jinja
- context:
file: {{ tiedosto }}
{% endfor %}