보안/화이트햇스쿨

[DevSecOps] - Ansible 기초 실습

hyo1o 2025. 4. 13. 14:46

☑️ DevSecOps

- 특정 workspace를 standardizing 하는 것

- 기술만 보는 것이 아닌 비즈니스와 가용기술/인원/문화와 비용을 고려한 안전한 소프트웨어 배포 문화를 만드는 것

 

☑️ CIS Benchmark 

- 수백개의 점검/설정 항목 (패스워드 정책, SSH 설정 등)

- 시스템이 얼만큼 기준을 잘 따르고 있는지에 따라 점수를 확인할 수 있음

- 단점: 항목이 너무나도 많다. 

- 모든 권고 항목에는 고유한 번호가 부여됨

 

☑️Ansible 장점

- 에이전트 없는 관리 방식

  ㄴ 에이전트의 버전을 관리하거나 프로세스 관리등의 고려사항이 없음

  ㄴ SSH / WinRM을 통신하여 동작하는 방식으로 에이전트 없는 운용 가능

- 다양한 플랫폼 지원

- 멱등성(IaC)

  ㄴ여러번 실행해도 동일한 결과를 얻는다는 멱등성을 충족

  ㄴ 멱등성을 보장하지 않는 방식의 모듈을 작성할수도있음 (Shell, Command)

 

☑️Ansible 용어

1. 실행주체: Controller

2. 인벤토리: Inventory (Ansible Hosts)

 

☑️umask

- 최소한의 권한 원칙 적용

   ㄴ 새로운 파일이나 디렉터리를 생성할 때 부여되는 기본 권한을 제어

   ㄴ 적절히 제한적으로 설정시 파일/디렉토리가 생성될 시 처음부터 너무 넓은 권한을 갖는걸 방지함

- 정보 노출 및 수정방지

   ㄴ 002, 000같이 설정될 경우 다른 사용자나 시스템의 모든 사용자가 읽거나 수정 가능

 

☑️ 실습

docker pull ubuntu:24.04
docker run -d --name ubuntu-cis-test ubuntu:24.04 sleep infinity
docker exec -it [해당 container ID] /bin/bash
 apt install ansible
ansible localhost -m ping

apt install nano -y
nano inventory.yml

nano 나가기: Ctrl + O → 엔터 → Ctrl + X

 

☑️ umask 보안설정 

- 플레이북 파일 작성 (파일명: cis.yml)

nano cis.yml
- name: Apply Simple CIS Demo Tasks on Localhost
  hosts: localhost
  become: yes  # root 권한 필요

  tasks:
    - name: "Demo Task 1: Create CIS marker file"
      ansible.builtin.copy:
        content: |
          # This file indicates that CIS demo playbook was run.
          Applied on: {{ ansible_date_time.iso8601 }}
        dest: /etc/cis_demo_applied_marker.txt
        mode: '0644'

    - name: "Demo Task 2: Ensure secure umask (e.g., 027) in /etc/profile (simple demo)"
      ansible.builtin.lineinfile:
        path: /etc/profile
        regexp: '^umask'
        line: 'umask 027'
        backrefs: no
        create: yes
        backup: yes

nano 나가기: Ctrl + O → 엔터 → Ctrl + X
ansible-playbook -i inventory.yml cis.yml #실행

 

☑️ audit 패키지 설치하기

apt install auditd -y
nano manage_packages.yml
- name: Manage packages example
  hosts: webservers
  become: yes  # 패키지 관리는 보통 root 권한이 필요

  tasks:
    - name: Ensure nginx is installed
      ansible.builtin.package:
        name: nginx
        state: present

    - name: Ensure the latest version of curl is installed
      ansible.builtin.package:
        name: curl
        state: latest

    - name: Ensure apache2 is removed
      ansible.builtin.package:
        name: apache2
        state: absent

ansible-playbook -i inventory.yml manage_packages.yml #실행

 

☑️ 패스워드 최대 사용기간 설정

nano set_password_max_days.yml
- name: CIS | 5.4.1.1 Set Password Maximum Days
  hosts: all
  become: yes
  gather_facts: no

  tasks:
    - name: Ensure password maximum days is set (e.g., 90) in login.defs
      ansible.builtin.lineinfile:
        path: /etc/login.defs
        regexp: '^\\s*PASS_MAX_DAYS\\s+'
        line: 'PASS_MAX_DAYS    90'
        backrefs: no

ansible-playbook -i inventory.yml set_password_max_days.yml #실행

☑️파일 권한 강화

- 사용자 정보, 그룹 정보 사용자 패스워드 및 해시와 그룹 정보가 포함되어 중요하게 관리되어야함

- loop 사용

nano set_auth_file_perms.yml
- name: CIS | 6.1 | Ensure Secure Permissions on Authentication Files
  hosts: localhost
  become: yes
  gather_facts: no

  tasks:
    - name: Ensure secure permissions and ownership for auth files
      ansible.builtin.file:
        path: "{{ item.path }}"
        owner: "{{ item.owner }}"
        group: "{{ item.group }}"
        mode: "{{ item.mode }}"
        state: file
      loop:
        - { path: '/etc/passwd',  owner: 'root', group: 'root', mode: '0644' }
        - { path: '/etc/group',   owner: 'root', group: 'root', mode: '0644' }
        - { path: '/etc/shadow',  owner: 'root', group: 'root', mode: '0600' }
        - { path: '/etc/gshadow', owner: 'root', group: 'root', mode: '0600' }
ansible-playbook -i inventory.yml set_auth_file_perms.yml #실행