Palvelinten hallinta - Harjoitus 3
==============

*Disclaimer:*
--------------

Tämä harjoitus on tehty osana Haaga-Helian Tietojenkäsittelyn koulutusohjelman kurssia [Palvelinten hallinta (ICT4TN022, kevät 2018)](http://www.haaga-helia.fi/fi/opinto-opas/opintojaksokuvaukset/ICT4TN022). Kurssin pitäjänä toimii [Tero Karvinen](http://terokarvinen.com/), joka on määritellyt tämän harjoituksen tehtävänkuvaukset. Tehtävien vastaukset ovat Pekka Heleniuksen (allekirjoittanut) tuottamia.

*SISÄLLYSLUETTELO*
--------------

- [b) Tiedosto muotista: tee yksinkertainen SLS-tilatiedosto, joka laittaa muuttujan tiedostoon. Käytä jinjan kontekstimuuttujaa (template: jinja, context: ...)](https://github.com/Fincer/central-management-of-multiple-servers/blob/master/h3.md#b-tiedosto-muotista-tee-yksinkertainen-sls-tilatiedosto-joka-laittaa-muuttujan-tiedostoon-k%C3%A4yt%C3%A4-jinjan-kontekstimuuttujaa-template-jinja-context-)

- [c) SLS tilaa Jinjalla: tee yksinkertainen SLS-tilatiedosto, joka käyttää for-in -silmukaa. Voit esimerkiksi tehdä kolme tiedostoa silmukalla. (Tässä tehtävässä siis käytetään jinjaa vain SLS-tiedoston sisällä, älä sotke samaan esimerkkiin tekstitiedostojen sisällön muuttamista.)](https://github.com/Fincer/central-management-of-multiple-servers/blob/master/h3.md#c-sls-tilaa-jinjalla-tee-yksinkertainen-sls-tilatiedosto-joka-k%C3%A4ytt%C3%A4%C3%A4-for-in--silmukaa-voit-esimerkiksi-tehd%C3%A4-kolme-tiedostoa-silmukalla-t%C3%A4ss%C3%A4-teht%C3%A4v%C3%A4ss%C3%A4-siis-k%C3%A4ytet%C3%A4%C3%A4n-jinjaa-vain-sls-tiedoston-sis%C3%A4ll%C3%A4-%C3%A4l%C3%A4-sotke-samaan-esimerkkiin-tekstitiedostojen-sis%C3%A4ll%C3%B6n-muuttamista)

- [d) SSH-demonin portti: tee tila, joka asentaa SSH-demonin valittuun porttiin. Käytä portin valintaan Jinjaa, siten että sshd_config:issa “Port:”-kohdan arvo tulee Jinjan muuttujasta.](https://github.com/Fincer/central-management-of-multiple-servers/blob/master/h3.md#d-ssh-demonin-portti-tee-tila-joka-asentaa-ssh-demonin-valittuun-porttiin-k%C3%A4yt%C3%A4-portin-valintaan-jinjaa-siten-ett%C3%A4-sshd_configissa-port-kohdan-arvo-tulee-jinjan-muuttujasta)

- [e) Kokeile jonkun toisen opiskelijan tekemää Salt-tilaa. Kokeiltava tila voi olla mistä vain harjoituksesta. Opiskelijoiden raportteja ja koodeja löydät tämän sivun perästä kommenteista.](https://github.com/Fincer/central-management-of-multiple-servers/blob/master/h3.md#e-kokeile-jonkun-toisen-opiskelijan-tekem%C3%A4%C3%A4-salt-tilaa-kokeiltava-tila-voi-olla-mist%C3%A4-vain-harjoituksesta-opiskelijoiden-raportteja-ja-koodeja-l%C3%B6yd%C3%A4t-t%C3%A4m%C3%A4n-sivun-per%C3%A4st%C3%A4-kommenteista)

**b)** Tiedosto muotista: tee yksinkertainen SLS-tilatiedosto, joka laittaa muuttujan tiedostoon. Käytä jinjan kontekstimuuttujaa (template: jinja, context: ...).
--------------

**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
```

**c)** SLS tilaa Jinjalla: tee yksinkertainen SLS-tilatiedosto, joka käyttää for-in -silmukaa. Voit esimerkiksi tehdä kolme tiedostoa silmukalla. (Tässä tehtävässä siis käytetään jinjaa vain SLS-tiedoston sisällä, älä sotke samaan esimerkkiin tekstitiedostojen sisällön muuttamista.)
--------------

**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

```

**d)** SSH-demonin portti: tee tila, joka asentaa SSH-demonin valittuun porttiin. Käytä portin valintaan Jinjaa, siten että sshd_config:issa “Port:”-kohdan arvo tulee Jinjan muuttujasta.
--------------

**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:

![randomport-from-master](https://raw.githubusercontent.com/Fincer/central-management-of-multiple-servers/master/images/ssh_randomport_for_minion_2.png)

Toinen esimerkki:

![randomport-from-master](https://raw.githubusercontent.com/Fincer/central-management-of-multiple-servers/master/images/ssh_randomport_for_minion.png)

**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
```

![prevent-ssh-portchange_](https://raw.githubusercontent.com/Fincer/central-management-of-multiple-servers/master/images/salt_ssh-prevent-portchange.png)

**e)** Kokeile jonkun toisen opiskelijan tekemää Salt-tilaa. Kokeiltava tila voi olla mistä vain harjoituksesta. Opiskelijoiden raportteja ja koodeja löydät tämän sivun perästä kommenteista.
--------------

**Vastaus:**

Valitaan henkilön Oliver Siren harjoitus 3:n [Salt state, Jinja for-in loop](https://github.com/Oliver-Siren/palvelinten-hallinta-ict4tn022-4/blob/master/assignments/h3.md#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 %}
```
