Elasticsearch 클래식 플러그인 개발
원본 보기Elasticsearch 클래식 플러그인 개발
클래식 플러그인은 Elasticsearch에 사용자 정의 인증, 권한 부여, 점수 산정 등을 위한 메커니즘을 제공합니다.
클래식 플러그인은 Elasticsearch가 새로 릴리스될 때마다 새 버전을 빌드해야 합니다. 이 버전은 플러그인을 설치할 때와 로드할 때 확인됩니다. elasticsearch.version이 올바르지 않은 플러그인이 있으면 Elasticsearch는 시작되지 않습니다.
클래식 플러그인은 JAR 파일과 플러그인을 설명하는 Java 속성 파일인 plugin-descriptor.properties라는 메타데이터 파일로 구성된 ZIP 파일입니다.
플러그인 루트에 있는 JAR 파일만 플러그인의 클래스 경로에 추가된다는 점에 유의하세요. 다른 리소스가 필요하면 리소스 JAR로 패키징하세요.
Elasticsearch 저장소에는 플러그인 예제가 있습니다. 다음과 같은 예제가 포함됩니다.
- 사용자 정의 설정이 있는 플러그인
- 사용자 정의 수집 프로세서가 있는 플러그인
- 사용자 정의 REST 엔드포인트 추가
- 사용자 정의 재채점기 추가
- Java로 구현된 스크립트
이 예제는 시작하는 데 필요한 최소한의 구성 요소를 제공합니다. 플러그인 작성 방법에 관한 자세한 내용은 기존 플러그인의 소스 코드를 참고하는 것이 좋습니다.
테스트를 위해 bin/elasticsearch-plugin install file:///path/to/your/plugin을 사용하여 플러그인을 설치하세요. Java 플러그인은 plugins/ 디렉터리에 있는 경우에만 자동으로 로드됩니다.
일부 플러그인에는 추가 권한이 필요할 수 있습니다.
Elasticsearch는 권한 보안 메커니즘의 일부로 보안에 민감한 특정 작업을 수행하는 기능을 제한합니다(예: 원격 코드 실행(RCE) 취약점으로 인한 잠재적 피해를 제한하기 위해).
권한 모델은 Java 모듈을 기반으로 합니다.
Java 모듈에 부여된 권한은 해당 모듈의 코드가 그 권한과 관련된 보안에 민감한 작업을 수행할 수 있게 합니다. 예를 들어 스레드를 생성하는 기능은 manage_threads 권한이 있는 모듈로 제한됩니다. 마찬가지로 파일 시스템에서 파일을 읽는 기능은 해당 파일에 대한 files 권한이 있는 모듈로 제한됩니다.
실제로 권한은 플러그인 코드가 명확히 정의된 일련의 해당 JDK 메서드를 호출할 수 있게 합니다. 권한이 없으면 해당 JDK 메서드 호출이 거부되고 NotEntitledException이 발생합니다. 플러그인은 선택 사항인 entitlement-policy.yaml 파일을 포함하여 모듈과 필요한 권한을 정의할 수 있습니다. 플러그인이 요청한 모든 추가 권한은 큰 경고와 함께 사용자에게 표시되며, 사용자는 대화형으로 플러그인을 설치할 때 이를 확인해야 합니다. 따라서 불필요한 권한은 요청하지 않는 것이 가장 좋습니다!
Elasticsearch Gradle 빌드 시스템을 사용하는 경우 이 파일을 src/main/plugin-metadata에 배치하면 단위 테스트 중에도 적용됩니다.
권한 정책은 플러그인의 모든 JAR(자체 코드 및 서드파티 종속성)에 적용됩니다. 이에 맞게 정책 파일을 작성해야 합니다. 예를 들어 플러그인이 Example API 클라이언트를 사용하여 네트워크 작업을 수행한다면 다음과 같은 정책이 필요할 수 있습니다.
org.elasticsearch.example-plugin:
- manage_threads
com.example.api.client:
- set_https_connection_properties
- outbound_network
보안에 민감한 네트워크 작업을 수행하는 코드가 example-api-client 종속성에 있으므로 네트워크 관련 권한이 com.example.api.client 모듈에 부여된다는 점에 유의하세요.
플러그인이 모듈식이 아닌 경우 모든 권한을 포괄적인 ALL-UNNAMED 모듈 이름 아래에 지정해야 합니다.
ALL-UNNAMED:
- manage_threads
- set_https_connection_properties
- outbound_network
현재 Elasticsearch에서 구현 및 적용되며 플러그인에서 사용할 수 있는 권한은 다음과 같습니다.
코드가 Java 스레드를 생성하거나 속성을 수정하는 메서드(예: Thread#start 또는 ThreadGroup#setMaxPriority)를 호출할 수 있게 합니다.
이 권한은 필요한 경우가 드뭅니다. 플러그인은 자체 스레드를 생성하고 관리하는 대신 Elasticsearch 스레드 풀과 실행기(Plugin#getExecutorBuilders 참조)를 사용해야 합니다. 플러그인은 ES 스레드 풀에서 실행될 때 스레드 이름, 우선순위, 데몬 상태 및 컨텍스트 클래스 로더를 수정하지 않아야 합니다.
하지만 Apache HTTP 클라이언트처럼 비동기 작업을 지원하는 많은 서드파티 라이브러리는 자체 스레드를 생성하고 관리해야 합니다. 이러한 경우에는 이 권한을 요청하는 것이 적절합니다.
예:
org.example.module:
- manage_threads
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
코드가 네트워크 연결을 만드는 메서드를 호출할 수 있게 합니다. Elasticsearch는 기본적으로 어떠한 네트워크 액세스도 허용하지 않습니다. 외부 리소스에 직접 연결해야 하는 각 플러그인(예: 데이터 업로드 또는 다운로드)은 이 권한을 요청해야 합니다.
예:
org.example.module:
- outbound_network
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
코드가 설정된 HTTPS 연결의 속성을 변경하는 메서드를 호출할 수 있게 합니다. 일반적으로 이는 무해하지만(예: google API 클라이언트는 방금 생성한 HTTPS 연결을 수정하는 데 사용함), 이러한 메서드를 사용하면 코드가 임의의 연결을 변경할 수 있습니다.
예:
org.example.module:
- set_https_connection_properties
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
외부 리소스가 플러그인에 직접 연결할 수 있도록 코드가 수신 연결을 대기하는 메서드를 호출할 수 있게 합니다. 이 권한은 반드시 필요한 경우에만 사용해야 합니다(예: 의존하는 라이브러리가 인증을 위해 이 권한을 요구하는 경우). 이 권한을 부여하면 Elasticsearch 노드가 공격에 더 취약해집니다. 이 권한은 더 이상 사용되지 않으며 향후 Elasticsearch 버전에서 제거될 수 있습니다.
예:
org.example.module:
- inbound_network
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
코드가 네이티브 라이브러리를 로드하고 제한된 메서드를 호출할 수 있게 합니다. 또한 이 권한이 부여된 모듈에 대한 네이티브 액세스도 활성화합니다. 네이티브 코드는 JVM을 변경하거나 파일 또는 네트워크 제한과 같은 액세스 검사를 우회할 수 있습니다.
예:
org.example.module:
- load_native_libraries
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
코드가 파일 시스템에 액세스하여 권한의 필드에 지정된 경로를 읽거나 쓸 수 있게 합니다. Elasticsearch를 호스팅하는 OS의 파일 시스템에는 자격 증명과 같은 민감한 파일이 있을 수 있습니다. 일부 파일은 Elasticsearch에서 항상 액세스할 수 있어야 하지만 플러그인은 해당 파일에 직접 액세스할 수 없습니다. Elasticsearch는 특정 파일을 핵심 코드만 읽을 수 있도록 하고 다른 일부 파일은 전혀 읽거나 쓸 수 없도록 합니다. 플러그인에는 항상 Elasticsearch 구성 디렉터리에 대한 read 액세스 권한과 임시 디렉터리에 대한 read_write 액세스 권한이 부여됩니다. 플러그인이 추가 파일이나 디렉터리를 읽거나 쓰거나 액세스해야 한다면 이 권한을 통해 해당 항목을 지정해야 합니다.
다음 3가지 파일 권한 유형을 지정할 수 있습니다.
- 절대 경로를 지정하는
path - 상대 경로를 지정하는
relative_path.relative_to필드를 사용하여 상대 경로의 기준을 지정합니다.relative_to에는 다음 옵션을 사용할 수 있습니다. - Elasticsearch 설정을 통해 정의된 경로를 지정하는
path_setting. 경로는 절대 경로나 상대 경로일 수 있습니다. 상대 경로인 경우basedir_if_relative경로(relative_to와 동일한 값을 사용할 수 있음)를 사용하여 경로를 확인합니다.
3가지 유형에는 각각 몇 가지 추가 필드가 있습니다.
mode(필수):read또는read_write중 하나일 수 있습니다.platform(선택 사항): 이 항목이 하나의 플랫폼에만 적용됨을 나타내며,linux,macos또는windows중 하나일 수 있습니다. 다른 플랫폼에서는 해당 항목이 무시됩니다. 이 필드를 지정하지 않으면 항목이 모든 플랫폼에 적용됩니다.exclusive: 이 경로에 대한 액세스는 해당 플러그인 전용입니다. 즉, 다른 플러그인은 일반적으로 해당 경로에 대한 액세스 권한을 부여하는 권한이 있더라도 이 경로에 액세스할 수 없습니다.
예:
org.example.module:
- files:
- path: "/absolute/path"
mode: read
- relative_path: "relative/file.txt"
relative_to: data
mode: read_write
- path_setting: setting.name
basedir_if_relative: data
mode: read
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
코드가 하나 이상의 시스템 속성을 설정할 수 있게 합니다(예: System#setProperty 호출). 이 권한이 부여된 코드는 properties 필드에 나열된 속성을 변경할 수 있습니다. 일반적으로 시스템 속성을 동적으로 변경하면 나중에 해당 속성을 읽는 코드에 영향을 줄 수 있으므로 피하는 것이 가장 좋습니다. 시스템 속성은 전역적이므로 로드 순서에 따라 한 플러그인이 다른 플러그인에 영향을 줄 수 있습니다.
예:
org.example.module:
- write_system_properties:
properties:
- property.one
- property.two
- 플러그인이 모듈식이 아닌 경우 'ALL-UNNAMED'
자세한 내용은 elasticsearch 저장소의 권한 README를 확인하세요.