본문 바로가기
Ansible/Study

Ansible - 보안설정/ 모니터링 자동화

by 식사법 2024. 2. 12.

보안설정/모니터링 자동화

1. 보안설정 자동화

패스워드 변경 주기 설정하기

사전 분석

  • 패스워드 변경 주기를 설정할 대상 호스트는 인벤토리를 통해 설정한다.
  • 패스워드 변경 주기를 설정할 사용자 계정 정보와 최대 변경일은 변수를 통해 별도의 파일로 정의한다.
  • 패스워드 변경 주기 설정은 ansible.builtin.user 모듈을 이용한다.

플레이북 설계

  • 사용자 계정과 최대 변경일을 변수로 설정하기 위해 vars_maxdays.yml 파일 생성
  • 메인 플레이북 set_chage_password.yml 파일에는 변경 주기를 설정할 태스트가 포함

  1. ansilble.cfg / inventory/ 변수 / 플레이북 작성
  • ansible.cfg
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • inventory
cat inventory
[tnode]
tnode1
tnode2
tnode3
  • 변수 작성
# ansible, stack의 최대 비밀번호 사용 기간은 90일
cat vars_maxdays.yml

Userinfo:
  - username: ansible
    maxdays: 90
  - username: stack
    maxdays: 90
  • 플레이북 작성
# tnode 그룹에서 실행됨
# 변수 정보는 vars_maxdays.yml 참조
# ansible.builtin 모듈을 사용하여 name, password_expire_max의 값을
# 변수를 참조하여 설정
cat set_chage_password.yml
---

- hosts: tnode
  vars_files: vars_maxdays.yml

  tasks:
    - name: Change Password Maxdays
      ansible.builtin.user:
        name: "{{ item.username }}"
        password_expire_max: "{{ item.maxdays }}"
      loop: "{{ Userinfo }}"
  1. 실행 화면 및 확인
  • 실행

  • 확인

패스워드 생성 법칙 적용하기

사전분석

  • 패스워드 생성 법칙 적용을 위해서는 pwquality.conf 라는 pam 설정 파일을 이용해야 하며, 리눅스 서버에 libpam-pwquality 패키지가 있어야 함.
  • 패스워드 변경 주기는 /etc/securiy/pwquality.conf 파일로 설정한다.
  • /etc/securiy/pwquality.conf 파일을 설정하기 전에 원본 파일을 백업받는다.
  • pwquality.conf 파일은 사용자가 커스텀으로 설정하는 파라미터들로 구성되어 있으며, Jinja2 템플릿 방식으로 구현한다.
  • 파라미터들은 별도의 변수 설정 파일에서 정의한 파라미터 값으로 사용하고, 파라미터 정의 여부를 체크하여 pwquality.conf 파일의 내용을 구성한다.

플레이북 설계

  • 변수 vars_pw_rule.yml 에 정의
    • 최소 패스워드 길이 설정 minlen
    • 최소 숫자 개수 설정 dcredit
    • 최소 대문자 개수 설정 ucredit
    • 최소 소문자 개수 설정 lcredit
    • 최소 특수문자 개수 설정 ocredit
    • root 계정에서도 해당 패스워드 룰을 설정할 수 있는 enforce_for_root
  • Jinja2 템플릿 파일 pwqulity.conf.j2 아래 내용 포함
    • minlen, dcredit, ucredit, lcredit, orcedit, enforce_for_root
    • minclass : 최소 문자클래스 개수
    • maxrepeat : 최대 연속 동일 문자 수
    • maxclassrepeat : 동일 글래스의 최대 연속 문자 수

  1. ansilble.cfg / inventory/ 변수 / 플레이북 작성
  • ansible.cfg
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • inventory
cat inventory
[tnode]
tnode1
tnode2
tnode3
  • 변수 작성
cat vars_pw_rule.yml
---

minlen: 8
dcredit: -1
ucredit: -1
lcredit: -1
ocredit: -1
enforce_for_root: true
  • Jinja2 템플릿 파일 pwquality.conf.j2 작성
    • {% ~ %} 사이에 제어문 구문 위치
    • {% if minlen is defined %} 구문 : minlen 이라는 변수가 정의되면 아래 문장을 삽입하라’ 는 의미
    • 아래 템플릿에는 {% if 변수 is defined %} ~ {% endif %} 구문을 사용하여 파라미터와 관련된 변수가 선언되면 해당 파라미터를 삽입
    • # Created by ansible {% if minlen is defined %} # Minimum acceptable size for the new password minlen = {{ minlen }} {% endif %} {% if dcredit is defined %} # The maximum credit for having digits in the new password dcredit = {{ dcredit }} {% endif %} {% if ucredit is defined %} # The maximum credit for having uppercase characters in the new password ucredit = {{ ucredit }} {% endif %} {% if lcredit is defined %} # The maximum credit for having lowercase characters in the new password lcredit = {{ lcredit }} {% endif %} {% if ocredit is defined %} # The maximum credit for having other characters in the new password ocredit = {{ ocredit }} {% endif %} {% if minclass is defined %} # The minimum number of required classes of characters for the new password minclass = {{ minclass }} {% endif %} {% if maxrepeat is defined %} # The maximum number of allowed consecutive same characters in the new password maxrepeat = {{ maxrepeat}} {% endif %} {% if maxclassrepeat is defined %} # The maximum number of allowed consecutive characters of the same class in the new password maxclassrepeat = {{ maxclassreapt }} {% endif %} {% if retry is defined %} # Prompt user at most N times before returning with error retry = {{ retry }} {% endif %} {% if enforce_for_root is defined %} # Enforces pwquality checks on the root user password. enforce_for_root {% endif %}
  • 플레이북 작성
# tnode 그룹에서 실행됨
# 변수 정보는 vars_pw_rule.yml 참조
# ansible.builtin 모듈을 사용하여 libpam-pwqualit 패키지 설치
# 기존에 있던 pwquality.conf 파일을 백업
# ansible을 실행하는 곳의 pwquality.conf.j2 파일을 node로 이동
cat set_password_rule.yml
---

- hosts: tnode
  vars_files: vars_pw_rule.yml

  tasks:
    - name: Install libpam-pwquality
      ansible.builtin.apt:
        name: libpam-pwquality
        state: present
      when: ansible_facts.os_family == "Ubuntu"

    - name: Backup pwquality.conf
      ansible.builtin.copy:
        src: /etc/security/pwquality.conf
        dest: /etc/security/pwquality.conf.bak
        remote_src: yes

    - name: Copy pwquality.conf.j2 at /etc/security
      ansible.builtin.template:
        src: pwquality.conf.j2
        dest: /etc/security/pwquality.conf
        mode: '0644'
  • remote_src : yes를 해주지 않는다면 로컬에서 node로 파일을 복사하려하기 때문에 꼭 기입해줘야 한다
  1. 실행 및 확인
  • 플레이북 실행

  • 테스크 실행 확인

  • 패스워드 변경 실행 ( qwer123, qwer1234 입력시 경고 메세지 출력 확인)

디렉토리 및 파일 접근 권한 변경

상황

  • 리눅스 보안 중에 꼭 확인해야 하는 항목이 바로 Sticky bit 설정 파일과 World Writable 설정 파일입니다.
  • Sticky bit 설정 파일은 리눅스에서 파일 소유자나 그룹 소유자만 해당 파일을 읽고 쓰고 삭제할 수 있도록 권한을 부여한 것을 의미합니다.
  • 파일 소유자에게 권한을 부여하면 SUID, 파일 그룹에게 권한을 부여하면 SGID, 다른 사람에게 권한을 부여하면 Sticky bit 라고 합니다.
  • Sticky bit가 적용된 파일 목록 중 보안을 위해 이를 적용하면 안 되는 파일 목록들이 있습니다.
  • Sticky bit가 적용된 파일의 권한을 수정할 때는 적용되면 안 되는 파일인지 반드시 먼저 확인합니다 → 보안 관련 가이드 문서 참고
  • World Writable 파일은 모든 사용자에게 파일을 읽고 쓸 수 있는 권한이 부여된 파일을 의미합니다.

사전 분석

  • Sticky bit 파일 검색 명령어: find / -xdev -perm -04000 -o -perm -02000 -o -perm -01000
  • World Writable 파일 검색 명령어: find / -xdev -type f -perm -2
  • ansible.builtin.shell 모듈을 이용하여 Sticky bit 파일과 World Writable 파일을 찾는다.
  • 찾은 파일 목록은 ansible.builtin.file 모듈을 이용하여 파일의 접속 권한을 설정한다.
  • Sticky bit 파일은 u-s, g-s, o-s 로 설정하고, World Writable 파일은 o-w 로 설정한다.

플레이북 설계

  1. ansilble.cfg / inventory/ 변수 / 플레이북 작성
  • ansible.cfg
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • inventory
cat inventory
[tnode]
tnode1
tnode2
tnode3
  • 플레이북 작성
cat set_sticky_writable_files.yml
---

- hosts: tnode

  tasks:
  - name: Find Sticky bit files
    ansible.builtin.shell: |
      find / -xdev -perm -04000 -o -perm -02000 -o -perm 01000 \
      | grep -e 'dump$' \
             -e 'lp*-lpd$' \ 
             -e 'newgrp$' \
             -e 'restore$' \
             -e 'at$' \
             -e 'traceroute$' | xargs ls
    register: sfile_list

  - name: Find World Writable files
    ansible.builtin.shell: |
      find / -xdev -perm -2 -ls \
      | grep -v 'l..........' | awk '{print $NF}'
    register: wfile_list

  - name: Print Sticky bit files
    ansible.builtin.debug:
      msg: "{{ sfile_list.stdout_lines }}"

  - name: Print World Writable files
    ansible.builtin.debug:
      msg: "{{ wfile_list.stdout_lines }}"

  - name: Set Sticky bit files
    ansible.builtin.file:
      path: "{{ item }}"
      mode: "u-s,g-s,o-s"
    loop: "{{ sfile_list.stdout_lines }}"

  - name: Set World Writable files
    ansible.builtin.file:
      path: "{{ item }}"
      mode: "o-w"
    loop: "{{ wfile_list.stdout_lines }}"
  1. 실행 및 확인
  • 실행

  • 확인

2. 모니터링 자동화

팩트를 이용한 시스템 모니터링

사전분석

  • 팩트는 관리 노드에서 시스템과 관련된 정보(아래 예시)들을 찾아 변수로 제공 → 인프라 정보 파악 및 로그로 저장
    • 호스트 이름
    • 커널 버전
    • 네트워크 인터페이스 이름
    • 네트워크 인터페이스 IP 주소
    • 운영체제 버전
    • CPU 개수
    • 사용 가능한 메모리
    • 스토리지 장치의 크기 및 여유 공간
  • 추출한 내용은 ansible.builtin.shell 모듈을 이용하여 /var/log/daily_check 디렉터리에 저장

플레이북 설계

  1. ansible.cfg / inventory / 변수 / 플레이북 작성
  • ansible.cfg
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • inventory
cat inventory
[tnode]
tnode1
tnode2
tnode3
  • 플레이북 작성 : debug과 facts 수집 후 file 에 저장
---

- hosts: tnode
  vars:
    log_directory: /var/log/daily_check

  tasks:
    - name: Print system info
      ansible.builtin.debug:
        msg:
        - "################ Start #####################"
        - "Date: {{ ansible_facts.date_time.date }} {{ ansible_facts.date_time.time }}" 
        - "HostName: {{ ansible_facts.hostname }}"
        - "OS: {{ ansible_facts.distribution }}"
        - "OS Version: {{ ansible_facts.distribution_version }}"
        - "OS Kernel: {{ ansible_facts.kernel }}"
        - "CPU Cores: {{ ansible_facts.processor_vcpus }}"
        - "Memory: {{ ansible_facts.memory_mb.real }}"
        - "Interfaces: {{ ansible_facts.interfaces }}"
        - "IPv4: {{ ansible_facts.all_ipv4_addresses }}"
        - "Devices: {{ ansible_facts.mounts }}"
        - "################# End #######################" 
      register: result

    - name: Create log directory
      ansible.builtin.file:
        path: "{{ log_directory }}"
        state: directory

    - name: Print logs to log file
      ansible.builtin.shell: |
        echo "{{ item }}" >> "{{ log_directory }}"/system_info.logs
      loop: "{{ result.msg }}"
  1. 실행 및 확인
  • 실행

  • 확인

CPU, 메모리, 디스크 사용률 모니터링

사전분석

  • 팩트에서 제공되지 않은 정보를 모니터링해야되는 상황
  • 자세한 CPU, 메모리, 디스크 사용률 모니터링을 위해 dstat, iostat, vmstat 명령어 사용 → 툴 설치 필요
  • 각각의 명령어 실행은 ansible.builtin.shell 이용하여 실행하고, loop 키워드를 이용하여 모니터링 명령어별로 여러 옵션을 추가하여 명령 실행
  • 실행된 명령어 결과는 로그 디렉터리에 저장

플레이북 설계

  1. ansible.cfg / inventory / 변수 / 플레이북 작성
  • ansible.cfg
cat ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ubuntu
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
  • inventory
cat inventory
[tnode]
tnode1
tnode2
tnode3
  1. 변수 작성
cat vars_packages.yml
---

log_directory: /home/ansible/logs
packages:
  - dstat
  - sysstat
  1. 플레이북 작성 : debug와 facts 수집 후 file 에 저장
# node의 os는 ubuntu 이므로 apt를 활용하여 dstat, sysstat 설치
# log저장을 위한 디렉토리 생성
# dstat 2 10 , dstat -cmdlt -D vda 2 10 명령어를 각각 실행하여 dstat.log에 저장
# iostat 등의 명령어를 각각 실행하여 iostat.log에 저장
# vmstat 등의 명령어를 각각 실행하여 vmstat.log에 저장
cat monitoring_system.yml
---

- hosts: tnode
  vars_files: vars_packages.yml

  tasks:
    - name: Install packages on RedHat
      ansible.builtin.dnf:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"
      when: ansible_facts.os_family == "RedHat"

    - name: Install packages on Ubuntu
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
      loop: "{{ packages }}"
      when: ansible_facts.os_family == "Debian"
    - name : creat directory
      ansible.builtin.file:
        path: "{{ log_directory }}"
        state: directory

    - name: Monitoring dstat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/dstat.log
      loop:
        - dstat 2 10
        - dstat -cmdlt -D vda 2 10

    - name: Monitoring iostat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/iostat.log
      loop:
        - iostat
        - echo "==============="
        - iostat -t -c -dp vda
        - echo "==============="

    - name: Monitoring vmstat
      ansible.builtin.shell: |
        {{ item }} >> {{ log_directory }}/vmstat.log
      loop:
        - vmstat
        - echo "==============="
        - vmstat -dt
        - echo "==============="
        - vmstat -D
        - echo "==============="

    - name: Monitoring df
      ansible.builtin.shell: |
        df -h >> {{ log_directory }}/df.log
  1. 실행 및 확인
  • 실행

  • 확인 - 각로그 존재 확인

'Ansible > Study' 카테고리의 다른 글

시스템 구축 및 환경 설정 자동화  (0) 2024.02.04
Ansible - 반복문, 조건문, 핸들러 ,롤 구조  (0) 2024.01.20
Ansible 기초 정리  (0) 2024.01.09