# SROS2 설치 및 초기 설정

#### 개요

ROS2에서 보안을 적용하기 위해서는 DDS 계층의 보안 기능을 활용하고, 이를 편리하게 사용할 수 있도록 제공되는 툴이 바로 SROS2(Secure ROS2)이다. ROS1 시절에도 SROS라는 패키지가 있었지만, ROS2부터는 DDS의 보안 확장(Security Extension)을 활용할 수 있게 되면서 SROS2가 좀 더 체계적으로 제공된다. 이번 장에서는 ROS2 Humble 버전을 기준으로 SROS2를 설치하고, 기본적으로 설정해야 할 항목들을 엄밀히 살펴본다.

#### 준비 사항

SROS2를 이용하기 위해서는 다음과 같은 환경이 준비되어 있어야 한다.

1. **ROS2 Humble**가 설치된 Ubuntu (일반적으로 20.04 이상) 환경
2. DDS 보안 플러그인을 지원하는 RTPS 구현체 (Fast DDS, Cyclone DDS 등)
3. Python 3.8 이상 (ROS2 패키지 빌드 및 스크립트 실행을 위해 필요)

SROS2 설치 전, 현재 ROS2 버전 및 DDS 설정을 확인할 필요가 있다. 예를 들어, Cyclone DDS를 사용 중이라면 `$ apt list --installed | grep cyclonedds` 명령어를 통해 설치 여부를 확인한다.

```bash
apt list --installed | grep cyclonedds
```

만약 Fast DDS를 사용한다면 `$ apt list --installed | grep fastdds` 명령어로 확인한다.

```bash
apt list --installed | grep fastdds
```

#### SROS2 설치

ROS2 Humble 환경에서 SROS2는 일반적으로 `ros-humble-sros2` 패키지로 제공된다. 다음과 같이 설치할 수 있다.

```bash
sudo apt update
sudo apt install ros-humble-sros2
```

설치가 완료되면, `sros2`라는 명령어를 사용할 수 있어야 한다. 다음 명령어로 버전을 확인할 수 있다.

```bash
sros2 --help
```

만약 `sros2` 명령어가 동작하지 않는다면, 터미널에서 ROS2 설정이 올바르게 되어 있는지 확인한다. 예를 들어, 다음과 같이 ROS2 Humble 환경을 미리 설정해야 한다.

```bash
source /opt/ros/humble/setup.bash
```

별도의 워크스페이스를 사용 중이라면, `colcon build` 후에 `source install/setup.bash` 등의 명령어로 워크스페이스도 불러온다.

#### 보안 디렉토리 구조

ROS2에서 보안을 활성화하면, 각 노드는 보안 아티팩트(키, 인증서 등)를 저장하는 보안 디렉토리를 참조한다. SROS2를 통해 생성되는 기본 디렉토리 구조는 다음과 같다.

```
.
└── ros2_secure/
    ├── enclaves/
    │   └── ...
    ├── keys/
    │   └── ...
    └── policies/
        └── ...
```

* **enclaves/**: ROS2 보안 도메인을 구분하는 디렉토리 구조로, 실제 키와 인증서가 저장되는 폴더 구조가 여기에 생성된다.
* **keys/**: 각 엔클레이브(Enclave)에 대한 비공개 키(Private Key)와 공개 키(Public Key)를 포함한다.
* **policies/**: XML 형식 등의 보안 정책(Access Control Policy)이 저장된다.

이때 각 노드가 액세스할 수 있는 토픽, 서비스를 정의한 정책 파일이 필요하며, 이 파일은 ROS2 보안에서 매우 중요한 역할을 한다.

#### 작업공간에서 SROS2 소스 빌드 (선택)

표준 패키지로 설치한 `ros-humble-sros2` 외에, 최신 소스 코드를 직접 빌드하여 사용하고 싶다면, 다음 단계를 수행한다.

워크스페이스 내 `src` 폴더에서 SROS2를 내려받는다.

```bash
cd ~/ros2_ws/src
git clone https://github.com/ros2/sros2.git -b humble
```

의존성을 설치하고, 빌드한다.

```bash
cd ~/ros2_ws
rosdep update
rosdep install --from-paths src --ignore-src -y
colcon build --packages-select sros2
source install/setup.bash
```

`sros2` 명령어가 동작하는지 확인한다.

```bash
sros2 --help
```

빌드가 잘 되었다면, 위 명령어에 대한 사용법이 출력될 것이다.

#### 보안 정책 파일 개념

SROS2를 활용하기 위해서는 **보안 정책(Security Policy)** 개념을 이해해야 한다. 보안 정책은 크게 두 가지 요소로 구성된다.

1. **Authentication**: 노드를 인증하기 위한 인증서, 키 등의 자격 증명.
2. **Access Control**: 토픽, 서비스, 액션에 대한 접근 권한을 정의하는 XML 정책 파일.

ROS2 DDS 보안 모델에서 액세스 컨트롤은 DDS 보안 정책을 XML 형식으로 작성하여 적용한다. 실제로는 다음과 같은 XML 구조로 작성하게 된다.

```xml
<policy>
  <permissions>
    <grant name="example_grant">
      <subject_name>some_node_identity</subject_name>
      <validity>
        <not_before>2024-01-01T00:00:00</not_before>
        <not_after>2025-01-01T00:00:00</not_after>
      </validity>
      <permissions>
        <allow_rule>
          <domains>
            <id>0</id>
          </domains>
          <publish>
            <topic>chatter</topic>
          </publish>
          <subscribe>
            <topic>chatter</topic>
          </subscribe>
        </allow_rule>
      </permissions>
    </grant>
  </permissions>
</policy>
```

이 파일에서 특정 노드(Identity)가 어떤 토픽에 대해 퍼블리시/서브스크라이브 권한을 가지는지 선언한다. 이는 보안을 적용하는 핵심 중 하나다.

#### 인증서와 키 생성

SROS2 환경에서 보안을 활성화하려면, 각 노드는 적절한 인증서(Certificate)와 키(Key)를 통해 자신을 증명하고, 보안 정책에 따라 DDS 통신을 수행하게 된다. 보안 정책 파일(Access Control Policy)과 더불어, 노드의 암호화 통신을 위한 **공개 키**와 **비공개 키**, 그리고 노드 신뢰를 위한 **인증서**가 필요하다. 이를 자동화하는 스크립트가 `sros2` 명령어에 포함되어 있으며, 가장 기본적으로는 CA(Certificate Authority)를 먼저 생성하고, 각 노드별로 인증서를 발급받는 순서로 진행한다.

**1. CA 생성**

보안 통신 구조에서 CA는 인증서를 발급해 주는 **루트 인증기관(Root CA)** 역할을 한다. `sros2` 툴은 CA 생성에 필요한 파일을 자동으로 생성해 준다. 아래 예시는 기본적으로 `$HOME/.ros/sros2/` 폴더에 CA 관련 파일들을 생성한다.

```bash
sros2 generate_ca
```

위 명령을 실행하면 다음과 유사한 파일 구조가 생성된다.

```
~/.ros/sros2/ca/
├── ca.cert.pem
└── ca.key.pem
```

* **ca.cert.pem**: CA의 인증서
* **ca.key.pem**: CA의 비공개 키

CA 생성 시, CA 명이나 유효기간 등을 추가 옵션으로 지정할 수 있다. 예를 들어 다음과 같은 옵션들을 확인해 볼 수 있다.

```bash
sros2 generate_ca --help
```

**2. 노드별 인증서 생성**

노드별 엔클레이브(Enclave)를 생성하면서, 인증서와 키를 발급받는다. 일반적으로 CA 디렉토리와 별개의 출력 폴더를 지정하여, 노드별 인증서를 체계적으로 관리한다. 예시로, `enclave_example`이라는 이름으로 엔클레이브를 생성해보자.

```bash
sros2 generate_artifacts -k enclave_example \
                         -n /my_robot/controller
```

이 명령어를 실행하면, 다음과 같은 디렉토리 구조가 생긴다. (기본적으로 `~/.ros/sros2/enclave_example/` 경로에 생성)

```
~/.ros/sros2/enclave_example/
├── cert.pem
├── key.pem
├── identity_ca.cert.pem
└── identity_ca.key.pem
```

* **cert.pem**: `enclave_example` 엔클레이브의 인증서
* **key.pem**: `enclave_example` 엔클레이브의 개인 키
* **identity\_ca.cert.pem**: 노드용 CA 인증서
* **identity\_ca.key.pem**: 노드용 CA 개인 키

실제 생성된 인증서(`cert.pem`)와 키(`key.pem`)는 노드에서 보안 통신에 사용되며, CA 인증서로부터 서명(Signature)을 받은 상태이므로, 인증 신뢰 체인(Trust Chain)이 형성된다.

**3. 보안 정책 파일 생성**

노드별 권한 설정을 위해 XML 형식의 보안 정책(Access Control Policy) 파일을 작성해야 한다. `sros2` 툴은 템플릿을 생성하는 기능을 제공한다. 예를 들어, 아래와 같이 `sros2 create_policy` 명령어로 정책 템플릿을 생성할 수 있다.

```bash
sros2 create_policy -p my_policy.xml \
                    -n /my_robot/controller
```

이렇게 하면, `my_policy.xml` 파일이 생성되며, 기본적인 구조만 포함한다. 생성된 XML 내부에서 **토픽, 서비스, 액션, 파라미터** 등에 대한 접근 권한을 직접 명시해야 한다. 예시 구조는 다음과 같다.

```xml
<policy xmlns="https://github.com/ros2/sros2">
  <permissions>
    <grant name="/my_robot/controller">
      <subject_name>/my_robot/controller</subject_name>
      <validity>
        <not_before>2024-01-01T00:00:00</not_before>
        <not_after>2026-01-01T00:00:00</not_after>
      </validity>
      <permissions>
        <allow_rule>
          <domains>
            <id>0</id>
          </domains>
          <publish>
            <topic>control_cmd</topic>
          </publish>
          <subscribe>
            <topic>sensor_data</topic>
          </subscribe>
        </allow_rule>
      </permissions>
    </grant>
  </permissions>
</policy>
```

이 정책 파일을 토대로, 실제 노드가 퍼블리시/서브스크라이브 할 수 있는 대상 리소스를 제어할 수 있다. 정책 파일이 완성된 후에는, 해당 정책과 연결된 엔클레이브가 올바르게 접근 권한을 가져야 한다.

**4. 보안 아티팩트 적용**

엔클레이브별로 발급된 인증서와 키, 그리고 정책 파일을 함께 묶어 DDS 보안을 활성화하기 위해 다음 과정을 수행한다.

1. **CA 인증서**: 전체 노드가 신뢰할 수 있는 상위 인증서.
2. **엔클레이브 인증서**: 노드별로 부여된 개별 인증서.
3. **엔클레이브 비공개 키**: 노드별로 엄격히 보관되는 비밀 키.
4. **액세스 컨트롤 정책 파일**: XML 형식의 정책 선언.

이 모든 아티팩트를 **보안 디렉토리**(Security Artifacts Directory)에 적절히 배치해야 한다. 일반적으로 다음과 같은 계층 구조를 사용한다.

```
~/.ros/sros2/
├── ca/
│   ├── ca.cert.pem
│   └── ca.key.pem
├── enclave_example/
│   ├── cert.pem
│   ├── key.pem
│   └── permissions.xml
└── another_enclave/
    ├── cert.pem
    ├── key.pem
    └── permissions.xml
```

위 구조에서 `permissions.xml` 파일이 정책 파일이며, 실제 이름은 `policy.xml`, `permissions.xml`, `allow.xml` 등으로 다양하게 지정할 수 있다. 중요한 것은 DDS 보안에서 참조하는 표준 이름과 위치에 맞춰 배치하거나, XML 태그 내에서 적절히 참조할 수 있도록 구성해야 한다.

#### 보안 모드 활성화

ROS2에서 보안을 활성화하기 위해서는 ROS2 런타임이 DDS 보안 확장을 사용할 수 있도록 설정해야 한다. 이때 중요한 환경 변수(ROS\_SECURITY\_\*)를 지정하면, 노드 실행 시 보안 관련 파일(인증서, 정책 파일 등)을 자동으로 참조하게 된다.

일반적으로 다음 변수를 설정하여 노드를 실행한다.

```bash
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
export ROS_SECURITY_KEYSTORE=~/.ros/sros2/enclave_example
```

* **ROS\_SECURITY\_ENABLE**: `true`로 설정하면 보안을 활성화한다.
* **ROS\_SECURITY\_STRATEGY**: `Enforce`로 설정하면, 보안 아티팩트가 없거나 유효하지 않은 노드는 통신을 차단한다. `Permissive`로 설정하면, 보안 아티팩트가 없는 노드도 통신할 수 있지만 보안은 적용되지 않는다.
* **ROS\_SECURITY\_KEYSTORE**: 노드가 사용할 CA, 인증서, 키, 정책 등이 위치한 보안 디렉토리 경로를 지정한다.

위와 같은 환경 변수들을 설정한 뒤, `ros2 run` 명령어 등을 통해 노드를 실행하면 DDS 보안이 활성화된 상태에서 통신을 수행한다.

예:

```bash
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
export ROS_SECURITY_KEYSTORE=~/.ros/sros2/enclave_example

ros2 run my_package my_node_exe
```

만약 엔클레이브(Enclave)를 여러 개 사용해야 한다면, **각 노드별로 고유 엔클레이브 폴더**를 생성해 사용하거나, 노드 실행 시점에 `--enclave` 옵션을 활용할 수도 있다.

#### 여러 엔클레이브(Enclaves) 사용

ROS2에서 보안 설정을 세분화하기 위해, 노드마다 독립적인 엔클레이브를 부여할 수 있다. 엔클레이브 경로가 다르면 인증서와 키, 정책 파일 역시 독립적으로 운영 가능하다.

* **예시 시나리오**: 물리 로봇 제어 노드와 센서 데이터 노드를 분리하여, 서로 다른 보안 정책을 적용하고 싶을 때

1. `~/sros2/robot_control` 폴더: 로봇 제어 노드에 대한 인증서, 정책
2. `~/sros2/robot_sensing` 폴더: 센서 노드에 대한 인증서, 정책

엔클레이브 구분을 위해서는 다음과 같이 노드를 실행할 때, `--enclave` 옵션 또는 환경 변수를 활용한다.

```bash
# (예시) 제어 노드
ros2 run my_package control_node_exe --enclave /robot_control_enclave

# (예시) 센서 노드
ros2 run my_package sensor_node_exe --enclave /robot_sensing_enclave
```

이때, `ROS_SECURITY_KEYSTORE`를 각각의 엔클레이브 폴더로 지정해 두거나, SROS2가 만들어 놓은 표준 디렉토리 구조에 맞춰 노드를 실행해야 한다. 더 세부적으로는 ROS2의 `rmw_fastrtps` 또는 `rmw_cyclonedds` 보안 구현체가 관련 폴더를 어떻게 참조하는지 확인해야 한다.

#### 실행 및 검증

1. **보안 디렉토리 확인**: `~/.ros/sros2/<엔클레이브>` 경로에 `cert.pem`, `key.pem`, `permissions.xml` 등 보안 아티팩트가 있는지 확인한다.
2. **환경 변수 설정**: `ROS_SECURITY_ENABLE`, `ROS_SECURITY_STRATEGY`, `ROS_SECURITY_KEYSTORE` 등이 올바르게 설정되어 있는지 확인한다.
3. **노드 실행**: `ros2 run ...` 명령어를 사용하여 노드를 실행한다.
4. **통신 확인**: `ros2 topic echo`, `ros2 topic list` 등 명령어로 통신이 정상적으로 이루어지는지 확인한다. 보안이 적용된 상태라면, 노드들이 서로 신뢰할 수 없을 때 통신이 차단된다.

만약 설정이 올바르지 않다면, DDS 통신이 이루어지지 않거나 노드가 제대로 동작하지 않을 수 있다. 이 경우, 다음과 같은 절차로 문제를 진단한다.

* 환경 변수 체크: `printenv | grep ROS_SECURITY`
* CA 인증서와 노드 인증서, 키의 유효성 검사
* `permissions.xml` 정책에서 해당 노드와 토픽이 허용되어 있는지 확인
* DDS 보안 로깅 옵션 또는 `RMW_SECURITY_LOG_LEVEL` 설정을 통해 디버깅 메시지를 확인

#### 참고: 보안 설정 자동화

개발 환경에서 매번 환경 변수를 수동으로 설정하기 번거롭다면, `setup.bash` 스크립트에 미리 지정해 두거나, 별도의 `.sh` 파일을 만들어 로드하는 방식을 활용할 수 있다. 예를 들어, 다음과 같이 `secure_setup.sh`를 만들어 두고 필요할 때마다 `source` 명령어로 불러오면 편리하다.

```bash
# secure_setup.sh

#!/bin/bash
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
export ROS_SECURITY_KEYSTORE=~/.ros/sros2/enclave_example
source secure_setup.sh
ros2 run my_package my_node_exe
```

이렇게 하면 간단한 명령어로 보안 모드를 활성화하고, 노드를 실행할 수 있다.

#### 추가적인 보안 설정

ROS2 보안은 DDS 계층의 다양한 설정 옵션을 통해 세밀하게 구성될 수 있다. 여기서는 SROS2를 기반으로, 몇 가지 추가적인 보안 항목들을 간략히 살펴본다.

#### 보안 로깅(Log)

DDS 보안에서는 인증 실패나 정책 위반이 발생했을 때 로깅 정보를 남길 수 있도록 다양한 옵션을 제공한다. 예컨대, `rmw_fastrtps_cpp`나 `rmw_fastrtps_dynamic_cpp`를 사용 중이라면, 환경 변수를 통해 디버깅 메시지를 확인할 수 있다.

```bash
export RMW_SECURITY_LOG_LEVEL=debug
```

이 변수를 `debug` 수준으로 설정하면, 노드가 DDS 보안 인증을 시도할 때의 과정을 좀 더 상세히 확인할 수 있다. 이를 통해 인증서가 유효한지, 정책이 올바르게 적용되는지 등을 진단할 수 있다.

#### 요청/응답(Service) 보안

ROS2는 토픽만이 아니라 서비스도 DDS를 통해 통신한다. 서비스 호출(Request)과 응답(Response)은 기본적으로 **DDS RPC(Remote Procedure Call)** 개념 위에서 동작하며, 보안이 활성화되면 이들 역시 마찬가지로 인증과 권한 확인 과정을 거친다.

보안 정책 파일(XML)에서 토픽이 아닌 서비스 이름에 대해 접근 제어를 지정할 수 있다. 예시를 들면, 특정 노드가 `/my_robot/move` 서비스만을 호출할 수 있도록 정책을 작성한다.

```xml
<policy xmlns="https://github.com/ros2/sros2">
  <permissions>
    <grant name="/controller_node">
      <subject_name>/controller_node</subject_name>
      <permissions>
        <allow_rule>
          <domains>
            <id>0</id>
          </domains>
          <call_service>
            <service>/my_robot/move</service>
          </call_service>
        </allow_rule>
      </permissions>
    </grant>
  </permissions>
</policy>
```

이렇게 하면, 보안이 적용된 상태에서 `/controller_node`가 `/my_robot/move` 서비스만 콜할 수 있고, 다른 서비스에 대한 호출은 허용되지 않는다.

#### 액션(Action) 보안

액션(Action)도 내부적으로 피드백(Feedback), 목표(Goal), 결과(Result), 취소(Cancel) 등의 트픽/서비스를 사용해 구현된다. 따라서, 액션 보안을 구성하기 위해서는 액션이 내부적으로 사용하는 토픽과 서비스를 모두 정책에서 허용해 주어야 한다.

ROS2 Humble 이후에는 `ros2 action` CLI를 통해 생성되는 액션 인터페이스 파일을 참고하여, 해당 액션 이름에 매핑되는 주제명/서비스명을 파악할 수 있다. 이를 기반으로 XML 정책에 해당 항목을 추가하면 액션 레벨에서도 보안을 유지할 수 있다.

#### 윈도우 및 Docker 환경

ROS2 보안은 플랫폼에 관계없이 동작하지만, CA 생성 및 인증서 관련 툴 체인이 Linux 기반 명령어에 최적화되어 있으므로, Windows나 Docker 컨테이너 환경에서 사용할 때는 몇 가지 주의 사항이 있다.

* **Windows 환경**: OpenSSL 등 관련 라이브러리를 별도로 설치해야 하며, `sros2 generate_ca` 명령어 등이 의존하는 툴이 있는지 확인해야 한다.
* **Docker**: Docker 컨테이너 내부에서 보안을 설정할 경우, 볼륨 마운트(volume mount)를 통해 호스트의 CA 인증서와 키를 컨테이너에 전달하거나, 컨테이너 내부에서 `sros2` 명령어를 실행해 CA를 생성한다.

특히 Docker 내에서 여러 컨테이너 간 통신에 보안을 적용할 경우, 각 컨테이너가 동일한 CA를 신뢰하는지, 노드 이름(enclave 이름)을 어떻게 구분할지 등에 대해 미리 설계해야 한다.

#### 에피머럴(일시적) 키/인증서

일부 환경에서는 보안성을 강화하기 위해, 노드가 실행될 때마다 일시적인(에피머럴, ephemeral) 키/인증서를 생성해 사용하고, 노드 종료 시 폐기하기도 한다. 이런 시나리오를 위해서는 다음과 같은 순서를 자동화 스크립트로 구성한다.

1. 노드 실행 전, 임시 CA 및 노드용 인증서를 생성한다.
2. 정책 파일을 기반으로 SROS2 아티팩트를 완성한다.
3. 노드 종료 시, 해당 인증서와 키를 삭제한다.

이렇게 하면 키 유출 위험을 줄일 수 있으나, 생성/삭제 과정이 매번 필요하므로 구현이 복잡할 수 있다.

#### 보안 업데이트/회수(Revocation)

보안 설정을 변경하거나, 특정 인증서를 폐기(회수)해야 하는 경우도 발생한다. DDS 보안 계층에서는 다음과 같은 방식으로 처리할 수 있다.

1. **CRL(Certificate Revocation List)**: 폐기된 인증서 목록을 DDS가 참조할 수 있도록 관리한다.
2. **정책 파일 갱신**: 허용/거부 노드 목록이 바뀌었을 때, 새로운 정책 파일(permissions.xml 등)을 반영한다.
3. **새 인증서 재발급**: 유효 기간 만료나 키 교체 등이 필요할 때, 새로 발급받은 인증서와 키를 사용한다.

대규모 시스템에서는 자동화된 인증서 발급 및 폐기 메커니즘이 중요한 이슈가 된다.
