Kubernetes - 인증

정훈·2023년 4월 30일
0

kubernetes

목록 보기
1/2

쿠버네티스 인증

  • kubernetes 인증 기본 방법
    • X.509 : PKI(Public Key Infrastructure) 기술 중 널리 알려진 표준 포맷

    • kubernetes 내부 component간 통신에 사용

      • api-server, controller-manager, etcd, scheduler, kubelet ...
    • 사용자가 api-server에 접근하기 위해 사용하는 kubeconfig의 기본 설정

      # kubeconfig
      
      apiVersion: v1
      kind: Config
      clusters:
    • cluster:
      certificate-authority-data: !@#
      server: https://172.31.33.7:6443
      name: kubernetes
      users:

    • name: kubernetes-admin
      user:
      client-certificate-data: !@#
      client-key-data: !@#
      contexts:

    • context:


PKI

네트워크를 통해 주고받는 데이터를 누군가 훔쳐볼 수 없게하는 암호화

  • RootCA
    • 최상위 인증 기관
    • RootCA의 Private Key는 절대 털리지 않는다 (a.k.a 믿고 쓰는 DigiCert)
  • PKI 인증서의 생성과 검증
    • 만들 때
      • kakao가 인증서를 만들고 싶다는 의뢰서(CSR1))를 작성
      • DigiCert의 Private Key로 지문 암호화한 서명을 생성한다
      • kakao가 DigiCert에게 인증서를 받는다
    • 확인할 때
      • DigiCert의 Public Key로 서명이 복호화 된다
        • 인증서는 신뢰할 수 있다
      • 인증서 지문과 서명을 복호화한 것이 일치한다
        • 인증서는 변조되지 않았다
  • 어떻게 암호화를해야 안전한가?
    • 양방향 암호화 (복호화하면 풀수있는 양방향)
      • 대칭키
        • AES
      • 비대칭키
        • RSA
    • 단방향 암호화 (복호화할수없는 키 )
      • Hash
        • SHA256

RSA key pair 만들어보기

openssl genrsa -out sa.key 1024 # aws ubuntu에는 openssl이 내장되어있음 

openssl rsa -in sa.key -out sa.pub -pubout # public키와 복호화가되게끔해줘

# private 키가 털리면 복호화할수없음 

지문과 서명,(디지서트에서 서명해주는부분)

curl naver.com 
curl 아이피 주소 

# 이렇게 쳤을때 값이 다르다 다른 이유 

# 사기를 방지? 서버도메인을 TLS 에 담고있다 그래서 다르다 

HTTPS란

HTTP에 인증서를 이용한 상호 신뢰 검증과 암호화 통신을 더한 것

Tls와 Https의 차이

  • SSL은 1996년 SSL 3.0 이후 업데이트되지 않았으며, 앞으로 사라지게 될 것으로 여기지고 있다. 또한 알려진 취약성이 여러가지 있으며 보안 전문가들은 SSL 사용 중단을 권장한다고 한다. 그 대안으로는 앞에서 언급한 TLS가 있다.
  • TLS는 최신 암호화 프로토콜로, SSL 암호화로 혼용해서 부르는 경우도 많다. 실제로 현재 SSL을 인증한 업체 및 제공하는 업체는 사실상 TLS 암호화를 제공하고 있는것이다.
    • TLS(전송 계층 보안)는 통신 링크 또는 전송 계층을 보호하도록 설계된 암호화 프로토콜입니다. TLS는 전송 중인 정보를 보호함으로써 안전하지 않은 인프라를 통한 통신을 보호할 수 있다.

TLS 1.3v 사용하는 이유

  • TLS 1.3에는 더 빠른 속도와 더 강력한 보안 성능을 지원하는 향상된 기능이 포함되어 있습니다. 핸드셰이크가 100ms 개선되었기 때문에 사용자는 더 빠르고 안전한 브라우징의 이점을 누릴 수 있습니다.
  • TLS 1.3을 사용하면 다른 인터넷 서비스를 업그레이드하지 않고도 더 나은 연결 성능과 더 빠른 검색 기능을 만끽할 수 있습니다. 업무상 중요한 애플리케이션과 서비스를 빠르고 효율적으로 제공할 책임이 있는 네트워크 운영 팀은 네트워크가 빠르게 실행되고 안전하게 유지되도록 보장할 수 있습니다.

Tls와 HTTPS의 동작방식

  • SSL은 개인정보 보호를 제공하기 위해, 웹에서 전송되는 데이터를 암호화 한다. 따라서, 데이터를 가로채려해도 거의 복호화가 불가능하다.
  • ㅅTLS은 클라이언트와 서버간에 핸드셰이크를 통해 인증이 이루어진다. 또한 데이터 무결성을 위해 데이터에 디지털 서명을 하여 데이터가 의도적으로 도착하기 전에 조작된 여부를 확인한다.

SSL/TLS 핸드셰이크

핸드셰이크는 클라이언트와 서버간의 메세지 교환이며,  HTTPS 웹에 처음 커넥션할 때 진행된다. 핸드셰이크의 단계는 클라이언트와 서버에서 지원하는 암호화 알고리즘, 키 교환 알고리즘에 따라 달라진다. 일반적으로는 RSA 키 교환 알고리즘이 사용된다.

RSA 키 교환 알고리즘 순서

  1. 클라이언트 -> 서버 메세지 전송 - 이때 핸드셰이크가 시작된다. 이 메세지에는 TLS 버전, 암호화 알고리즘, 무작위 바이트 문자열이 포함된다.
  2. 서버 -> 클라이언트 메세지 전송 - 클라이언트의 메세지에 응답으로 서버의 SSL인증서, 선택한 암호화 알고리즘, 서버에서 생성한 무작위 바이트 문자열을 포함한 메세지를 전송한다.
  3. 인증 - 클라이언트가 서버의 SSL인증서를 인증 발행 기관에 검증한다.
  4. 예비 마스터 암호 - 클라이언트는 무작위 바이트 문자열을 공개 키로 암호화된 premater secret 키를 서버로 전송한다.
  5. 개인 키 사용 - 서버가 premaster secret 키를 개인 키를 통해 복호화한다. (개인 키로만 복호화 가능)
  6. 세션 키 생성 - 클라이언트와 서버는 클라이언트가 생성한 무작위 키, 서버가 생성한 무작위 키, premaster secret 키를 통해 세션 키를 생성한다. 양쪽은 같은 키가 생성되어야 한다.
  7. 클라이언트 완료 전송 - 클라이언트는 세션 키로 암호화된 완료 메세지를 전송한다.
  8. 서버 완료 전송 - 서버도 세션 키로 암호화된 완료 메세지를 전송한다.
  9. 핸드셰이크 완료 - 핸드셰이크가 완료되고, 세션 키를 이용해 통신을 진행한다.

Authentication

  • api-server 서버 인증서 살펴보기1)
    • Issuer가 누구인가?
    • Digital Signature가 있는가?
    • 인증서에 또 무엇이 들어 있는가?
openssl x509 -in apiserver.crt -noout -text

CN 이 쿠버네티스다 # 각기 다 다른걸만듬 
# CN은 인증서이다 . 
Subject: # tls-handshake 방식을 따라하는것.  

X509v3 Subject Alternative Name: 
                DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:""
    Signature Algorithm: sha256WithRSAEncryption
         89:46:01:4d:f7:e1:47:1d:85:c9:e1:4d:54:9c:31:a4:04:d9:
         7a:18:eb:f1:6e:78:20:e4:39:c5:ed:24:be:2c:45:7c:ec:c2:
         8e:0f:47:1a:fe:fb:6d:eb:d7:2e:85:c9:6a:b8:7a:47:ff:7f:
         68:4d:39:df:43:07:ba:1a:37:d7:cf:40:0d:ca:8e:83:cb:df:
         43:cf:e5:76:21:c7:97:42:e1:36:b4:91:ec:f2:a7:c7:40:88:
         d1:5b:3d:d4:99:3c:b1:ca:e4:78:25:97:f3:86:c2:43:dd:5a:
         b3:23:3d:9a:09:0d:4a:5f:bb:23:3e:12:23:a4:df:ec:f3:e5:
         17:e6:fc:1e:68:51:6f:72:c3:02:e9:e4:ea:69:ee:0f:24:e5:
         42:aa:ca:11:4d:1a:42:c7:e7:b1:02:f9:93:f4:4a:a8:6c:c5:
         95:4c:be:ae:99:ca:cb:86:8c:88:7d:a7:28:b8:b5:00:f4:cd:
         cd:1b:3c:e0:f7:c3:01:c0:a9:3e:a8:be:de:80:5b:14:21:c8:
         8b:1b:bb:95:5c:59:87:07:43:d3:df:74:da:35:d5:40:bb:08:
         6b:65:86:05:d7:d6:50:7c:20:17:04:35:dd:26:ce:b3:71:a8:
         28:f5:bb:20:76:4f:aa:10:9a:f5:c0:0f:e2:30:d0:f8:05:ab:
         74:80:33:d8

# 쿠버네티스에서는 SANS가 안맞으면 실행이안된다 
  • kubernetes-admin config
clusters:
- cluster:
    certificate-authority-data 
# 필요한이유 : 쿠버네티스 CA인증서이다. 원래 기존의 RootCA이지만 쿠버네티스가 만듬
#  RootCA가 퍼블릭키 를 확인하면서 검증을하는데 쿠버네티스는 쿠버네티스가 CA를만듬 

client-certificate-data: # 인증서 ... ..  무수히많은데이터 base64로 인코딩 된 데이터 
client-key-data: # private key에 해당하는 부분 무수히많은데이터 base64로 인코딩 된 데이터 
# 무수히많은 데이터 .. 
  • Tls HandShake
  • kubeconfig 파일이 도와주는역할을한다
    • 해당 os 가 들고있는게 아니여서

일반 사용자 생성하기 Authentication

  • 일반 사용자 생성하기
  • CN={{ ID }} O=" " 인 client cert를 생성한다
  • client cert/key를 이용해 kubeconfig를 만든다
  • 만들어진 kubeconfig로 kube-apiserver에 접근한다

# ca.crt 와 ca.key가 있어야 인증서를 만들수있다 . 
cd /home/ubuntu/kjh/pki

# Generate private key for user
openssl genrsa -out kjh.key 2048
 
# Generate CSR for user. Note the OU.
openssl req -new -key kjh.key -subj "/CN=kjh/O= " -out kjh.csr
 
# Sign certificate for user using CA servers private key
openssl x509 -req -in kjh.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kjh.crt -days 365
# 확인
openssl x509 -in kjh.crt -noout -text



{
  kubectl config set-cluster k8s-tls-example \
    --certificate-authority=ca.crt \ # 인증서를 인증하고싶으면 ca.crt를 이용해서 복호화해 
    --embed-certs=true \ # 인증서가 복사되도 인증되게할꺼냐 
    --server=https://host:6443 \ # 접근할려는 엔드포인트는 이거다 
    --kubeconfig=kjh.kubeconfig # 이러한 정보를 kubeconfig라는 파일에 해라 
 
  kubectl config set-credentials kjh \
    --client-certificate=kjh.crt \
    --client-key=kjh.key \
    --embed-certs=true \
    --kubeconfig=kjh.kubeconfig
 
  kubectl config set-context tls-context \ # 어떤 유저를 넣을건데 ?
    --cluster=k8s-tls-example \
    --user=kjh \
    --kubeconfig=kjh.kubeconfig
 
  kubectl config use-context tls-context --kubeconfig=kjh.kubeconfig # 이tls는 kjh.kubeconfig파일을 사용해라 
}
# base64 로 열어서 디버깅을해서 이 인증서가 맞는지 여부 판단하기 (잘됟던 쿠버네티스가 안된다하면)

root@~: kubectl get nodes --kubeconfig kjh.kubeconfig

Error from server (Forbidden): nodes is forbidden: 
User "kjh" cannot list resource "nodes" in API group "" at the cluster scope
# 인증이 되었는데, 인가가 아직 안되었어 (권한이없다 ? ) 이유 : 어떠한 role도 부여한적이없기때문에 

k8s Authorization (인가) - 에러를 고치기위한 인가 과정

  • kubernetes-admin kubeconfig는 무엇이든 다 할 수 있다
    • 근데 내가 만든건 아무것도 못한다.. 왜??
  • admin.crt 인증서 Common Name
    • CN=admin O=system:master
  • k8s에 User 저장소는 없지만 User/Group에게 Role을 부여할 수는 있다
    • Role(네임스페이스와 관계하의 할거면), ClusterRole(네임스페이스와 관계없이 모두 할거면)
      • 어떤 네임스페이스 에 속한 디플로이먼트를 지우지못하게할려면 Role로 해야한다 .
      • 무엇을 할 수 있는가?
    • RoleBinding, ClusterRoleBinding
      • 누가 무엇을 할 수 있는가?
kubectl get clusterrole # clusterrole 종류 

kubectl get clusterrole cluster-admin -o yaml # 어드민에대한 정보를 yaml로보고싶어 

kubectl get clusterrolebinding cluster-admin -o yaml

# cluster role 에대해서 부여를 하는곳 마스터그룹에 속한 사용자들한테 
oleRef:
  apiGroup: rbac.authorization.k8s.io 
  kind: ClusterRole # 모든 api 모든 리소스 모든 verb 
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:masters

Authorizatin


# 클러스터 롤이 생김 
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kjh-test
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs: # update fetch delete는 못한다 
  - get
  - list
- nonResourceURLs:
  - '*'
  verbs:
  - get
  - list
EOF

cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kjh-test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kjh-test
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kjh
EOF

# 하고나서 아까 안되던 에러부분이 다시 잘됨 

kubectl get nodes --kubeconfig kjh.kubeconfig # 정상작동 

kubectl label nodes kjh-kubeadm-master-1 {{ id }}=mine --overwrite --kubeconfig {{ id }}.kubeconfig
# kjh 라벨을 붙일려고 이렇게 작성을 했는데 이렇게 작성할경우 또 forbidden 으로 뜬다 
# 이유 verb에서 get , list 만 넣었기때문에 
  • label 명령어 에대한 기능이 정상 작동을 하기 위한과정
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kjh-test
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs: 
  - get
  - patch
  - list
- nonResourceURLs:
  - '*'
  verbs:
  - get
  - list
EOF

# 이후 

kubeconfig kjh.kubeconfig --overwrite

# 정상작동 

kubectl get nodes --show-labels

쿠버네티스 서비스 계정

  • X.509 방식의 사용자 추가 단점
    • 매번 ca.crt와 ca.key로 인증서를 만들어야 한다
    • 인증서 만료 기한이 있다 (100년 주면 해결되긴 하지만 영구는 아니다)
  • Kubernetes Service Account
    • Service Account를 생성하면 Secret이 생성되고, 이 Secret에는 JWT Token이 저장됨
    • JWT Token의 서명에는 sa.key가 사용되고, 인증에는 sa.pub이 사용된다
      • 서명은 controller-manager가 수행1)
    • kubeconfig에 JWT Token을 담아 apiserver에 요청을 하면 sa.pub으로 검증하여 인증 통과
    • sa.key / sa.pub pair가 변경되지 않는한 Service Account Token은 영구적이다
      • sa.key / sa.pub pair를 TLS 인증서로 설정할 수도 있다
      • sa.key.sa.pub.pair 를 통해인증을해줘야 서명이완료댐
  • 인증서가 만료되어도 JWT Token을 생성하지 못하거나
  • 이미 생성된 JWT Token이 인증 실패 하지는 않는다
    • jwt 는 x.509 의 경량화 버전이라고 생각하자

JSON Web Token

  • • JSON 문서에 서명을 추가하고 URL-safe 문자열로 표현한 것
  • private key 로 서명되어 배포된 토큰은 public key로 검증이 가능

쿠버네티스 서비스 계정 토큰설정

  • ca 인증서가 있는곳에서하자
# 이거를 갖고있는사람은  
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kjh-test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kjh-test
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kjh
- kind: ServiceAccount
  name: kjh-test
  namespace: default
EOF
{
  kubectl config set-cluster k8s-tls-example \
    --certificate-authority=ca.crt \
    --embed-certs=true \
    --server=https://hody:6443 \
    --kubeconfig=kjh-token.kubeconfig
 
  kubectl config set-credentials kjh-token \
    --token={{ decodedToken }}2) \ # secret 웹토큰을 집어넣으면됨  (2)
    --kubeconfig=kjh-token.kubeconfig
    
  kubectl config set-context token-context \
    --cluster=k8s-tls-example \
    --user=kjh-token \
    --kubeconfig={{ id }}-token.kubeconfig
 
  kubectl config use-context token-context --kubeconfig={{ id }}-token.kubeconfig
}

#(2)
echo $(kubectl get secret $(kubectl get secret | grep kjh-test | awk '{print $1}' ) -o json|jq -r .data.token) | base64 --decode && echo

 ------------- 

kubectl get sa  kjh-test -o yaml

보여진 yaml 에서 secret 값 복사 

kubectl get secret kjh-test-token-wlhd5 -o yaml # secret에대한 상세정보 토큰 등등 

echo 토큰 | base64 -d  => jwt 토큰 

{
  kubectl config set-cluster k8s-tls-example \
    --certificate-authority=ca.crt \
    --embed-certs=true \
    --server=https://host:6443 \
    --kubeconfig=kjh-token.kubeconfig
 
  kubectl config set-credentials kjh-token \
    --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlpSLU13cGVFbTIyWDZXak9UNF94M3FKZTAzQTBIbVlsQm83UFYzU3Z5TVkifQ \
    --kubeconfig=kjh-token.kubeconfig
    
  kubectl config set-context token-context \
    --cluster=k8s-tls-example \
    --user=kjh-token \
    --kubeconfig=kjh-token.kubeconfig
 
  kubectl config use-context token-context --kubeconfig=kjh-token.kubeconfig
}

eyJhbGciOiJSUzI1NiIsImtpZCI6IlpSLU13cGVFbTIyWDZXak9UNF94M3FKZTAzQ...

echo $(kubectl get secret $(kubectl get secret | grep kjh-test | awk '{print $1}' ) -o json|jq -r .data.token) | base64 --decode && echo
  • 그 후 json webtoken 을 사용하는 부분을 불러와보자
kubectl get nodes --kubeconfig={{ id }}-token.kubeconfig

kubectl get nodes --kubeconfig=kjh-token.kubeconfig

# 잘되는지 하번보자 

0개의 댓글

관련 채용 정보