Skip to main content

4 posts tagged with "security"

View All Tags

· 18 min read
Jinwoong Kim

해당 포스팅은 현재 재직중인 회사에 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

Tetragon

Tetragon를 사용하여 Kubernetes 클러스터의 보안 및 프로세스 모니터링을 수행하는 방법에 대해 간단히 알아보자.

Tetragon이란 무엇인가?

그림 출처: https://isovalent.com/blog/post/2022-05-16-tetragon/

tetragon

https://tetragon.io/

Tetragon은 eBPF(extended Berkeley Packet Filter)를 기반으로 하는 강력한 보안 및 모니터링 도구이다. eBPF는 커널 레벨에서 실행되는 프로그램으로, 시스템 성능에 최소한의 영향을 주면서 실시간으로 데이터를 수집하고 처리할 수 있다. Tetragon은 이를 활용하여 Kubernetes 환경에서 네트워크 트래픽, 시스템 호출, 컨테이너 활동 등을 모니터링하고 분석할 수 있다.

· 16 min read
Jinwoong Kim

컨테이너 내부에서 실행 중인 애플리케이션이나 프로세스는 시스템 호출(system call)을 수행할 수 있다. 대표적인 예로 HTTP 요청을 수행하는 curl 명령을 들 수 있다. 시스템 호출은 커널에 서비스를 요청하기 위해 사용자 공간에서 실행되는 추상화된 프로그래밍인데, 커널 강화 도구를 사용하여 허용되는 시스템 호출을 제한할 수 있으며, CKS 시험에서는 AppArmor와 seccomp라는 두 가지 도구를 명시적으로 언급하고 있다. 이 두 도구는 컨테이너화된 환경에서 보안을 강화하는 데 중요한 역할을 하며, Kubernetes와의 통합을 통해 보다 안전한 클러스터 운영을 지원한다. 이 두 도구와 쿠버네티스와 통합하는 메커니즘에 대해 설명한다.

AppArmor

AppArmor는 Linux 시스템에서 실행되는 프로그램에 대한 액세스 제어 기능을 제공한다. AppArmor는 경로 기반으로 작동하며, 프로필을 통해 특정 프로그램이나 컨테이너가 필요한 접근만 허용하도록 설정할 수 있다. Kubernetes에서는 AppArmor 프로필을 Pod 또는 컨테이너 수준에서 지정할 수 있으며, securityContext를 통해 적용한다. 이 도구는 user space에서 호출되는 애플리케이션과 기본 시스템 기능 사이에 추가적인 보안 계층을 구현한다. 네트워크 호출 또는 파일 시스템 상호 작용을 제한할 수 있다. 많은 Linux 배포판(예: Debian, Ubuntu, openSUSE)이 AppArmor를 기본으로 제공한다. AppArmor를 지원하지 않는 Amazon Linux와 같은 배포판은 AppArmor와 유사한 접근 방식을 취하는 SELinux를 대신 사용할 수 있다.

· 11 min read
Jinwoong Kim

kyverno 도구를 이용해서 쿠버네티스의 정책 엔진으로 활용하여 보안을 포함한 다양한 정책을 적용하는 방법을 알아본다.

kyverno

Kyverno는 그리스어로 "지배하다, 다스리다"의 뜻으로 쿠버네티스 네이티브로 설계된 정책 엔진(policy engine)이다. Kyverno 정책을 활용하여 쿠버네티스 리소스가 정책에 부합하는지 검사하고, 필요하면 리소스를 변경하거나 생성할 수 있다. Kyverno 구조 및 동작 방식을 간단히 정리한다.

OPA Gatekeeper는 독자적인 policy 언어인 Rego를 사용하여 policy를 정의하만 kyverno는 쿠버네티스 리소스로 관리되며 정책을 작성하는 데 새로운 언어가 필요하지 않다. OPA Gatekeeper와 유사하게 pre-defined policy library 를 제공한다.

· 9 min read

TLS 인증서

제한된 예산과 시간, 인력으로 서비스를 만들다 보니 어려운 점들이 참 많다. 특히나 TLS 인증서 같은 경우 관리하는것이 은근히 귀찮다. 인증서 만료일 관리하는것 부터 어느 페이지까지를 평문으로만 두어야 하는지도... 그런데 바보같은 이슈를 저지르고 말았다. 도메인을 신청하고 fanout, Name based virtual hosting 방식중에 고민하다가 설계를 virtual host로 하였다.

그런데 문제는 어이없는곳에서 나왔다. *.xxxxx.io 라고 wildcard SSL 인증서를 신청하였는데 virtual host방식으로 2차 subdomin (예, api.stg.xxxxx.io)으로 ingress를 마구잡이로 생성하고 인증서를 적용을 했다. 하지만 인증서 오류 ㅋㅋ

인터넷 비지니스를 거의 해보지 않아서 인지, 이런 기본적인 내용도 간과하고 서비스를 구상한 내가 모든걸 책임져야하는 상황이 와버렸다.

설계를 이상하게 해서 wildcard 도메인을 몇십개를 신규로 계약해야하는 쓸데없는 비용을 들어야하는 처지가 되었다. 하지만 그냥 죽으란 법은 없는게 사람사는 세상이고 이런 고민들을 분명 다른사람들도 했을거야라고 생각하면서 떠오른게 let's encrypt 였고 찾아보니 이걸 또 kubernetes에서 발급부터 갱신까지 해주는 오픈소스를 찾아 적용까지 하고 이렇게 포스팅을 한다.

Cert-manager

인증서 없이 구성할수도 있지만 기본적으로 kubernetes 는 secret과 ingress의 간단한 설정만으로 TLS를 구성할 수 있다.

  • Cert-manager : K8s 클러스터내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈소스
  • Let’s Encrypt : 자율적으로 작동하는 개방된 CA(Certificate authority-인증기관)으로 공공성(공공의 이익)을 위해서 운영되는 오픈소스

Cert-manager는 AWS의 Certificate Manager와 유사하게 인증서를 발급하고 설정할수 있다. 3개월 유효기간을 가지는 let's encrypt를 사용하기에 인증서 만료시 문제가 될거라 생각했지만 이것도 자동으로 갱신을 해주는 관리 app.을 같이 배포하기 때문에 인증서 관리에 대한 부담을 덜수 있다.

기본적으로 Cert-manager는 let's encrypt, Vault 같은 것을들 사용하여 인증서 발급을 할 수 있다. 인증서 발급후에도 만료가 되기 전에 바로 갱신을 자동으로 한다.

구성

certmanager

사전준비사항

  • helm
  • k8s cluster (1.7+) - CRD 사용이 가능해야함

설치

$ helm install --name cert-manager --version v0.3.1 \
--namespace kube-system stable/cert-manager

$ helm status cert-manager
LAST DEPLOYED: Fri Jun 15 10:02:45 2018
NAMESPACE: kube-system
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
cert-manager-cert-manager-5f76b676b4-5tdh8 1/1 Running 0 2d

==> v1/ServiceAccount
NAME SECRETS AGE
cert-manager-cert-manager 1 28d

==> v1beta1/CustomResourceDefinition
NAME AGE
certificates.certmanager.k8s.io 28d
clusterissuers.certmanager.k8s.io 28d
issuers.certmanager.k8s.io 28d

==> v1beta1/ClusterRole
cert-manager-cert-manager 28d

==> v1beta1/ClusterRoleBinding
NAME AGE
cert-manager-cert-manager 28d

==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
cert-manager-cert-manager 1 1 1 1 28d


NOTES:
cert-manager has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://cert-manager.readthedocs.io/en/latest/reference/issuers.html

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://cert-manager.readthedocs.io/en/latest/reference/ingress-shim.html

인증서 설정 및 배포

인증서 등록 및 만료시 noti를 받기 위한 변수 설정을 한다.

$ export EMAIL=zaction@sk.com

그리고 issuer manifest를 배포한다.
(letsencrypt-issuer.yaml)

# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: ''
privateKeySecretRef:
name: letsencrypt-staging
http01: {}
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ''
privateKeySecretRef:
name: letsencrypt-prod
http01: {}

두개의 endpoint를 생성한다. (Staging, Prod)

$ sed -e "s/email: ''/email: $EMAIL/g" letsencrypt-issuer.yaml | \
kubectl apply -f-
clusterissuer "letsencrypt-staging" created
clusterissuer "letsencrypt-prod" created

Web App을 HTTP Ingress 형태로 배포한다. TLS발급전에 미리 HTTP(80) Ingress를 배포해야 한다. 이후 Let's encrypt TLS배포 후 TLS spec을 추가하고 재배포를 해야한다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: auth-ingress
spec:
rules:
- host: auth.dev.action.cloudz.co.kr
http:
paths:
- backend:
serviceName: faas-auth-service
servicePort: 8081
path: /

TLS 인증서 발급

인증서를 발급할때는 위에서 만든 Ingress로 생성하고namespace별 생성이 필요하다.

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: auth-dev-tls
namespace: auth #### namespace별 생성
spec:
secretName: auth-dev-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: auth.dev.action.cloudz.co.kr
dnsNames:
- auth.dev.action.cloudz.co.kr
acme:
config:
- http01:
ingress: auth-ingress ### 기존에 만든 HTTP ingress 명
domains:
- auth.dev.action.cloudz.co.kr
$ kubectl apply -f auth-dev-tls.yaml
certificate "auth-dev-tls" created

이후 TLS 생성 상태를 확인한다. 이때 Message에서 Normal CeritifcateIssued Certificated issued successfully 문구가 확인되면 인증서 발급이 정상적으로 되었다고 볼 수 있다.
이때 발급되는 시간이 네트워크 환경에 따라 1~5분정도 소요될때로 있는것으로 보인다.

$ kubectl describe -f auth-dev-tls.yaml
...
Type Reason Message
---- ------ -------
Warning ErrorCheckCertificate Error checking existing TLS certificate: secret "auth-dev-tls" not found
Normal PrepareCertificate Preparing certificate with issuer
Normal PresentChallenge Presenting http-01 challenge for domain foo.kubernetes.tips
Normal SelfCheck Performing self-check for domain auth.dev.action.cloudz.co.kr
Normal ObtainAuthorization Obtained authorization for domain auth.dev.action.cloudz.co.kr
Normal IssueCertificate Issuing certificate...
Normal CeritifcateIssued Certificated issued successfully

secret이 생성된것을 확인할 수 있다.

$ kubectl get secret | grep tls
auth-dev-tls kubernetes.io/tls 2 3h

이후 위에서 만든 Ingress에 TLS를 적용한다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: auth-ingress
annotations:
ingress.bluemix.net/hsts: enabled=true maxAge=<31536000> includeSubdomains=true
ingress.bluemix.net/redirect-to-https: "True"
spec:
rules:
- host: auth.dev.action.cloudz.co.kr
http:
paths:
- backend:
serviceName: faas-auth-service
servicePort: 8081
path: /
tls:
- hosts:
- auth.dev.action.cloudz.co.kr
secretName: auth-dev-tls

위 설정을 적용하고 상태를 확인한다.

$ kubectl apply -f auth-tls-ingress.yaml

$ kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
auth-ingress auth.dev.action.cloudz.co.kr 10.1.1.182 80, 443 14h

cert-tls

정리

설계의 실수로 시작되었지만 정리하다보니 인증서 갱신이 자동을 된다는 점과 또한 Kubernetes환경에서 TLS관리가 간편하다는것을 알게 되었다. 인증서 비용을 아낀것도 하나의 성과이기도 하다. 인증서는 써야하겠고 정말 많은 애플리케이션들을 생성/삭제를 상시 해야하는 환경이라면 한번 적용해볼만한 가치가 있는것 같다.