Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Catatan. terjemahan: Penulis artikel, Reuven Harrison, memiliki pengalaman lebih dari 20 tahun dalam pengembangan perangkat lunak, dan saat ini menjabat sebagai CTO dan salah satu pendiri Tufin, sebuah perusahaan yang menciptakan solusi manajemen kebijakan keamanan. Meskipun ia memandang kebijakan jaringan Kubernetes sebagai alat yang cukup ampuh untuk mensegmentasi jaringan dalam sebuah cluster, ia juga yakin bahwa kebijakan tersebut tidak mudah diterapkan dalam praktiknya. Materi ini (cukup banyak) dimaksudkan untuk meningkatkan kesadaran para spesialis mengenai masalah ini dan membantu mereka membuat konfigurasi yang diperlukan.

Saat ini, semakin banyak perusahaan yang memilih Kubernetes untuk menjalankan aplikasi mereka. Minat terhadap perangkat lunak ini begitu tinggi sehingga beberapa orang menyebut Kubernetes sebagai β€œsistem operasi baru untuk pusat data.” Secara bertahap, Kubernetes (atau k8s) mulai dianggap sebagai bagian penting dari bisnis, yang memerlukan pengorganisasian proses bisnis yang matang, termasuk keamanan jaringan.

Bagi para profesional keamanan yang bingung bekerja dengan Kubernetes, hal yang mungkin terjadi adalah kebijakan default platform ini: izinkan semuanya.

Panduan ini akan membantu Anda memahami struktur internal kebijakan jaringan; memahami perbedaannya dengan aturan firewall biasa. Panduan ini juga akan membahas beberapa kendala dan memberikan rekomendasi untuk membantu mengamankan aplikasi di Kubernetes.

Kebijakan jaringan Kubernetes

Mekanisme kebijakan jaringan Kubernetes memungkinkan Anda untuk mengelola interaksi aplikasi yang diterapkan pada platform di lapisan jaringan (lapisan ketiga dalam model OSI). Kebijakan jaringan tidak memiliki beberapa fitur lanjutan dari firewall modern, seperti penegakan OSI Layer 7 dan deteksi ancaman, namun kebijakan tersebut memberikan tingkat keamanan jaringan dasar yang merupakan titik awal yang baik.

Kebijakan jaringan mengontrol komunikasi antar pod

Beban kerja di Kubernetes didistribusikan ke seluruh pod, yang terdiri dari satu atau lebih container yang di-deploy secara bersamaan. Kubernetes memberikan setiap pod alamat IP yang dapat diakses dari pod lain. Kebijakan jaringan Kubernetes menetapkan hak akses untuk grup pod dengan cara yang sama seperti grup keamanan di cloud digunakan untuk mengontrol akses ke instance mesin virtual.

Mendefinisikan Kebijakan Jaringan

Seperti sumber daya Kubernetes lainnya, kebijakan jaringan ditentukan di YAML. Pada contoh di bawah ini, aplikasi balance akses ke postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

(Catatan. terjemahan: tangkapan layar ini, seperti semua tangkapan layar serupa berikutnya, dibuat bukan menggunakan alat Kubernetes asli, tetapi menggunakan alat Tufin Orca, yang dikembangkan oleh perusahaan penulis artikel asli dan disebutkan di akhir materi.)

Untuk menentukan kebijakan jaringan Anda sendiri, Anda memerlukan pengetahuan dasar tentang YAML. Bahasa ini didasarkan pada indentasi (ditentukan dengan spasi, bukan tab). Elemen berindentasi adalah milik elemen berindentasi terdekat di atasnya. Elemen daftar baru dimulai dengan tanda hubung, semua elemen lainnya memiliki bentuk nilai kunci.

Setelah menjelaskan kebijakan di YAML, gunakan kubectluntuk membuatnya di cluster:

kubectl create -f policy.yaml

Spesifikasi Kebijakan Jaringan

Spesifikasi kebijakan jaringan Kubernetes mencakup empat elemen:

  1. podSelector: mendefinisikan pod yang terpengaruh oleh kebijakan ini (target) - wajib diisi;
  2. policyTypes: menunjukkan jenis kebijakan apa saja yang termasuk di dalamnya: ingress dan/atau egress - opsional, namun saya sarankan untuk menentukannya secara eksplisit di semua kasus;
  3. ingress: mendefinisikan diperbolehkan masuk lalu lintas ke pod target - opsional;
  4. egress: mendefinisikan diperbolehkan keluar lalu lintas dari pod target bersifat opsional.

Contoh diambil dari website Kubernetes (saya ganti role pada app), menunjukkan bagaimana keempat elemen digunakan:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: db
  policyTypes:    # <<<
  - Ingress
  - Egress
  ingress:        # <<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan
Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Harap dicatat bahwa keempat elemen tidak harus disertakan. Itu hanya wajib podSelector, parameter lain dapat digunakan sesuai keinginan.

Jika Anda menghilangkan policyTypes, kebijakan tersebut akan diartikan sebagai berikut:

  • Secara default, diasumsikan bahwa ini mendefinisikan sisi masuknya. Jika kebijakan tidak secara eksplisit menyatakan hal ini, sistem akan berasumsi bahwa semua lalu lintas dilarang.
  • Perilaku pada sisi jalan keluar akan ditentukan oleh ada tidaknya parameter jalan keluar yang bersangkutan.

Untuk menghindari kesalahan saya sarankan selalu membuatnya eksplisit policyTypes.

Menurut logika di atas, jika parameternya ingress dan / atau egress dihilangkan, kebijakan akan menolak semua lalu lintas (lihat "Peraturan Pengupasan" di bawah).

Kebijakan default adalah Izinkan

Jika tidak ada kebijakan yang ditentukan, Kubernetes mengizinkan semua lalu lintas secara default. Semua pod dapat dengan bebas bertukar informasi satu sama lain. Hal ini mungkin tampak berlawanan dengan intuisi dari sudut pandang keamanan, namun perlu diingat bahwa Kubernetes pada awalnya dirancang oleh pengembang untuk memungkinkan interoperabilitas aplikasi. Kebijakan jaringan ditambahkan kemudian.

Ruang nama

Namespace adalah mekanisme kolaborasi Kubernetes. Mereka dirancang untuk mengisolasi lingkungan logis satu sama lain, sementara komunikasi antar ruang diperbolehkan secara default.

Seperti kebanyakan komponen Kubernetes, kebijakan jaringan berada dalam namespace tertentu. Di blok metadata Anda dapat menentukan di ruang mana kebijakan tersebut berada:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

Jika namespace tidak ditentukan secara eksplisit dalam metadata, sistem akan menggunakan namespace yang ditentukan dalam kubectl (secara default namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

Saya merekomendasikan tentukan namespace secara eksplisit, kecuali Anda membuat kebijakan yang menargetkan beberapa namespace sekaligus.

Primer elemen podSelector dalam kebijakan tersebut akan memilih pod dari namespace tempat kebijakan tersebut berada (akses ke pod dari namespace lain ditolak).

Demikian pula dengan podSelectors di blok masuk dan keluar hanya dapat memilih pod dari namespacenya sendiri, kecuali tentu saja Anda menggabungkannya namespaceSelector (ini akan dibahas di bagian β€œFilter berdasarkan namespace dan pod”).

Aturan Penamaan Kebijakan

Nama kebijakan bersifat unik dalam namespace yang sama. Tidak boleh ada dua kebijakan dengan nama yang sama di ruang yang sama, namun bisa ada kebijakan dengan nama yang sama di ruang berbeda. Hal ini berguna ketika Anda ingin menerapkan kembali kebijakan yang sama di beberapa ruang.

Saya terutama menyukai salah satu metode penamaan. Ini terdiri dari menggabungkan nama namespace dengan pod target. Misalnya:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Label

Anda dapat melampirkan label khusus ke objek Kubernetes, seperti pod dan namespace. Label (label - tag) setara dengan tag di cloud. Kebijakan jaringan Kubernetes menggunakan label untuk memilih polongyang mereka terapkan:

podSelector:
  matchLabels:
    role: db

… atau ruang namayang mereka terapkan. Contoh ini memilih semua pod di namespace dengan label yang sesuai:

namespaceSelector:
  matchLabels:
    project: myproject

Satu peringatan: saat menggunakan namespaceSelector pastikan namespace yang Anda pilih berisi label yang benar. Sadarilah bahwa namespace bawaan seperti default ΠΈ kube-system, secara default tidak mengandung label.

Anda dapat menambahkan label ke spasi seperti ini:

kubectl label namespace default namespace=default

Pada saat yang sama, namespace di bagian tersebut metadata harus mengacu pada nama ruang sebenarnya, bukan label:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

Sumber dan tujuan

Kebijakan firewall terdiri dari aturan dengan sumber dan tujuan. Kebijakan jaringan Kubernetes ditentukan untuk suatu target - sekumpulan pod yang menerapkannya - dan kemudian menetapkan aturan untuk lalu lintas masuk dan/atau keluar. Dalam contoh kita, target kebijakannya adalah semua pod di namespace default dengan label dengan kunci app dan artinya db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan
Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Ayat ingress dalam kebijakan ini, membuka lalu lintas masuk ke pod target. Dengan kata lain, ingress adalah sumber dan target adalah tujuan yang sesuai. Demikian pula jalan keluar adalah tujuan dan target adalah sumbernya.

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Ini setara dengan dua aturan firewall: Ingress β†’ Target; Sasaran β†’ Jalan Keluar.

Jalan keluar dan DNS (penting!)

Dengan membatasi lalu lintas keluar, berikan perhatian khusus pada DNS - Kubernetes menggunakan layanan ini untuk memetakan layanan ke alamat IP. Misalnya, kebijakan berikut tidak akan berfungsi karena Anda belum mengizinkan aplikasi tersebut balance akses DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Anda dapat memperbaikinya dengan membuka akses ke layanan DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Elemen terakhir to kosong, dan oleh karena itu ia memilih secara tidak langsung semua pod di semua namespace, mengizinkan balance mengirim kueri DNS ke layanan Kubernetes yang sesuai (biasanya berjalan di luar angkasa kube-system).

Pendekatan ini berhasil, bagaimanapun caranya terlalu permisif dan tidak aman, karena memungkinkan kueri DNS diarahkan ke luar cluster.

Anda dapat memperbaikinya dalam tiga langkah berturut-turut.

1. Izinkan permintaan DNS saja dalam cluster dengan menambahkan namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

2. Izinkan kueri DNS hanya dalam namespace kube-system.

Untuk melakukan ini, Anda perlu menambahkan label ke namespace kube-system: kubectl label namespace kube-system namespace=kube-system - dan menuliskannya dalam kebijakan menggunakan namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

3. Orang paranoid dapat melangkah lebih jauh dan membatasi permintaan DNS ke layanan DNS tertentu kube-system. Bagian β€œFilter berdasarkan namespace DAN pod” akan memberi tahu Anda cara mencapainya.

Pilihan lainnya adalah menyelesaikan DNS di tingkat namespace. Dalam hal ini, tidak perlu dibuka untuk setiap layanan:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Kosong podSelector memilih semua pod di namespace.

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Pertandingan pertama dan urutan aturan

Dalam firewall konvensional, tindakan (Izinkan atau Tolak) pada sebuah paket ditentukan oleh aturan pertama yang dipenuhinya. Di Kubernetes, urutan kebijakan tidak menjadi masalah.

Secara default, ketika tidak ada kebijakan yang ditetapkan, komunikasi antar pod diperbolehkan dan mereka dapat dengan bebas bertukar informasi. Setelah Anda mulai merumuskan kebijakan, setiap pod yang terpengaruh oleh setidaknya salah satu dari kebijakan tersebut akan diisolasi sesuai dengan disjungsi (logis OR) dari semua kebijakan yang memilihnya. Pod yang tidak terpengaruh oleh kebijakan apa pun tetap terbuka.

Anda dapat mengubah perilaku ini menggunakan aturan pengupasan.

Aturan pengupasan (β€œTolak”)

Kebijakan firewall biasanya menolak lalu lintas apa pun yang tidak diizinkan secara eksplisit.

Tidak ada tindakan penolakan di Kubernetes, namun efek serupa dapat dicapai dengan kebijakan reguler (permisif) dengan memilih grup pod sumber yang kosong (ingress):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Kebijakan ini memilih semua pod di namespace dan membiarkan ingress tidak terdefinisi, sehingga menolak semua lalu lintas masuk.

Dengan cara serupa, Anda dapat membatasi semua lalu lintas keluar dari namespace:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Harap dicatat itu kebijakan tambahan apa pun yang mengizinkan lalu lintas ke pod di namespace akan diutamakan daripada aturan ini (mirip dengan menambahkan aturan izinkan sebelum aturan penolakan dalam konfigurasi firewall).

Izinkan semuanya (Apa pun-apa pun-izinkan)

Untuk membuat kebijakan Izinkan Semua, Anda perlu melengkapi kebijakan Tolak di atas dengan elemen kosong ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Ini memungkinkan akses dari semua pod di semua namespace (dan semua IP) ke pod mana pun di namespace default. Perilaku ini diaktifkan secara default, sehingga biasanya tidak perlu didefinisikan lebih lanjut. Namun, terkadang Anda mungkin perlu menonaktifkan sementara beberapa izin tertentu untuk mendiagnosis masalah.

Aturannya dapat dipersempit untuk mengizinkan akses saja satu set pod tertentu (app:balance) di ruang nama default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Kebijakan berikut mengizinkan semua lalu lintas masuk dan keluar, termasuk akses ke IP apa pun di luar klaster:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan
Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Menggabungkan Berbagai Kebijakan

Kebijakan digabungkan menggunakan logika OR pada tiga tingkat; Izin setiap pod diatur sesuai dengan pemisahan semua kebijakan yang memengaruhinya:

1. Di ladang from ΠΈ to Tiga jenis elemen dapat didefinisikan (semuanya digabungkan menggunakan OR):

  • namespaceSelector β€” memilih seluruh namespace;
  • podSelector β€” memilih pod;
  • ipBlock β€” memilih subnet.

Apalagi jumlah elemen (bahkan yang identik) pada subbagian from/to tidak terbatas. Semuanya akan digabungkan dengan logika OR.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

2. Di dalam bagian kebijakan ingress dapat memiliki banyak elemen from (dikombinasikan dengan logika OR). Demikian pula bagian egress mungkin mencakup banyak elemen to (juga digabungkan dengan disjungsi):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

3. Kebijakan yang berbeda juga digabungkan dengan logika OR

Namun saat menggabungkannya, ada satu batasannya ditunjukkan Chris Cooney: Kubernetes hanya dapat menggabungkan kebijakan dengan kebijakan yang berbeda policyTypes (Ingress ΠΈΠ»ΠΈ Egress). Kebijakan yang mendefinisikan ingress (atau egress) akan saling menimpa.

Hubungan antar namespace

Secara default, berbagi informasi antar namespace diperbolehkan. Hal ini dapat diubah dengan menggunakan kebijakan penolakan yang akan membatasi lalu lintas keluar dan/atau masuk ke dalam namespace (lihat "Aturan Pengupasan" di atas).

Setelah Anda memblokir akses ke namespace (lihat "Aturan Pengupasan" di atas), Anda dapat membuat pengecualian terhadap kebijakan penolakan dengan mengizinkan koneksi dari namespace tertentu menggunakan namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Hasilnya, semua pod di namespace default akan memiliki akses ke pod postgres di ruang nama database. Namun bagaimana jika Anda ingin membuka aksesnya postgres hanya pod tertentu di namespace default?

Filter berdasarkan namespace dan pod

Kubernetes versi 1.11 dan lebih tinggi memungkinkan Anda menggabungkan operator namespaceSelector ΠΈ podSelector menggunakan logika AND, tampilannya seperti ini:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Mengapa ini diartikan sebagai AND dan bukan OR yang biasa?

Harap dicatat bahwa podSelector tidak dimulai dengan tanda hubung. Di YAML, ini artinya podSelector dan berdiri di depannya namespaceSelector merujuk ke elemen daftar yang sama. Oleh karena itu, mereka digabungkan dengan logika AND.

Menambahkan tanda hubung sebelumnya podSelector akan mengakibatkan munculnya elemen daftar baru, yang akan digabungkan dengan elemen sebelumnya namespaceSelector menggunakan logika OR.

Untuk memilih pod dengan label tertentu di semua namespace, masukkan kosong namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Beberapa label bekerja sama dengan I

Aturan untuk firewall dengan banyak objek (host, jaringan, grup) digabungkan menggunakan logika OR. Aturan berikut akan berfungsi jika sumber paket cocok Host_1 OR Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

Sebaliknya, di Kubernetes berbagai label masuk podSelector или namespaceSelector digabungkan dengan logika AND. Misalnya, aturan berikut akan memilih pod yang memiliki kedua label, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

Logika yang sama berlaku untuk semua jenis operator: penyeleksi target kebijakan, penyeleksi pod, dan penyeleksi namespace.

Subnet dan alamat IP (IPBlocks)

Firewall menggunakan VLAN, alamat IP, dan subnet untuk mensegmentasi jaringan.

Di Kubernetes, alamat IP ditetapkan ke pod secara otomatis dan dapat sering berubah, sehingga label digunakan untuk memilih pod dan namespace dalam kebijakan jaringan.

Subnet (ipBlocks) digunakan saat mengelola koneksi eksternal (Utara-Selatan) masuk (ingress) atau keluar (egress). Misalnya, kebijakan ini terbuka untuk semua pod dari namespace default akses ke layanan DNS Google:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Pemilih pod kosong dalam contoh ini berarti β€œpilih semua pod di namespace.”

Kebijakan ini hanya mengizinkan akses ke 8.8.8.8; akses ke IP lain dilarang. Jadi, intinya, Anda telah memblokir akses ke layanan DNS internal Kubernetes. Jika Anda masih ingin membukanya, tunjukkan secara eksplisit.

Biasanya ipBlocks ΠΈ podSelectors bersifat eksklusif satu sama lain, karena alamat IP internal pod tidak digunakan ipBlocks. Dengan menunjukkan pod IP internal, Anda sebenarnya akan mengizinkan koneksi ke/dari pod dengan alamat ini. Dalam praktiknya, Anda tidak akan mengetahui alamat IP mana yang akan digunakan, itulah sebabnya alamat IP tersebut tidak boleh digunakan untuk memilih pod.

Sebagai contoh tandingan, kebijakan berikut mencakup semua IP dan oleh karena itu mengizinkan akses ke semua pod lainnya:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Anda hanya dapat membuka akses ke IP eksternal, tidak termasuk alamat IP internal pod. Misalnya, jika subnet pod Anda adalah 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Port dan protokol

Biasanya pod mendengarkan satu port. Ini berarti Anda tidak bisa menentukan nomor port dalam kebijakan dan membiarkan semuanya sebagai default. Namun, disarankan untuk membuat kebijakan seketat mungkin, sehingga dalam beberapa kasus Anda masih dapat menentukan port:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Perhatikan bahwa pemilih ports berlaku untuk semua elemen di blok to ΠΈΠ»ΠΈ from, yang mengandung. Untuk menentukan port berbeda untuk kumpulan elemen berbeda, pisahkan ingress ΠΈΠ»ΠΈ egress menjadi beberapa subbagian dengan to ΠΈΠ»ΠΈ from dan di setiap daftarkan port Anda:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Pengantar Kebijakan Jaringan Kubernetes untuk Profesional Keamanan

Operasi pelabuhan bawaan:

  • Jika Anda menghilangkan definisi port sepenuhnya (ports), ini berarti semua protokol dan semua port;
  • Jika Anda menghilangkan definisi protokol (protocol), ini berarti TCP;
  • Jika Anda menghilangkan definisi port (port), ini berarti semua port.

Praktik terbaik: Jangan mengandalkan nilai default, tentukan apa yang Anda perlukan secara eksplisit.

Harap dicatat bahwa Anda harus menggunakan port pod, bukan port layanan (lebih lanjut tentang ini di paragraf berikutnya).

Apakah kebijakan ditentukan untuk pod atau layanan?

Biasanya, pod-pod di Kubernetes saling mengakses melalui layanan - penyeimbang beban virtual yang mengalihkan lalu lintas ke pod-pod yang mengimplementasikan layanan tersebut. Anda mungkin berpikir bahwa kebijakan jaringan mengontrol akses ke layanan, namun kenyataannya tidak demikian. Kebijakan jaringan Kubernetes berfungsi pada port pod, bukan port layanan.

Misalnya, jika suatu layanan mendengarkan port 80, tetapi mengalihkan lalu lintas ke port 8080 pada podnya, Anda harus menentukan 8080 secara tepat dalam kebijakan jaringan.

Mekanisme seperti itu harus dianggap kurang optimal: jika struktur internal layanan (port tempat pod mendengarkan) berubah, kebijakan jaringan harus diperbarui.

Pendekatan arsitektur baru menggunakan Service Mesh (misalnya, lihat tentang Istio di bawah - kira-kira terjemahan) memungkinkan Anda untuk mengatasi masalah ini.

Apakah perlu mendaftarkan Ingress dan Egress?

Jawaban singkatnya adalah ya, agar pod A dapat berkomunikasi dengan pod B, pod A harus diizinkan untuk membuat koneksi keluar (untuk ini Anda perlu mengonfigurasi kebijakan jalan keluar), dan pod B harus dapat menerima koneksi masuk ( untuk ini, oleh karena itu, Anda memerlukan kebijakan ingress).

Namun, dalam praktiknya, Anda dapat mengandalkan kebijakan default untuk mengizinkan koneksi dalam satu atau kedua arah.

Jika beberapa pod-sumber akan dipilih oleh satu atau lebih jalan keluar-politisi, pembatasan yang dikenakan padanya akan ditentukan oleh disjungsi mereka. Dalam hal ini, Anda harus secara eksplisit mengizinkan koneksi ke pod -kepada penerima. Jika sebuah pod tidak dipilih berdasarkan kebijakan apa pun, lalu lintas keluarnya (keluar) diperbolehkan secara default.

Demikian pula nasib podnyapenerima, dipilih oleh satu atau lebih masuk-politisi, akan ditentukan oleh disjungsi mereka. Dalam hal ini, Anda harus secara eksplisit mengizinkannya untuk menerima lalu lintas dari pod sumber. Jika sebuah pod tidak dipilih berdasarkan kebijakan apa pun, semua lalu lintas masuknya akan diizinkan secara default.

Lihat Stateful atau Stateless di bawah.

Log

Kebijakan jaringan Kubernetes tidak dapat mencatat lalu lintas. Hal ini mempersulit penentuan apakah suatu kebijakan berfungsi sebagaimana mestinya dan sangat mempersulit analisis keamanan.

Kontrol lalu lintas ke layanan eksternal

Kebijakan jaringan Kubernetes tidak mengizinkan Anda menentukan nama domain yang sepenuhnya memenuhi syarat (DNS) di bagian jalan keluar. Fakta ini menyebabkan ketidaknyamanan yang signifikan ketika mencoba membatasi lalu lintas ke tujuan eksternal yang tidak memiliki alamat IP tetap (seperti aws.com).

Pemeriksaan Kebijakan

Firewall akan memperingatkan Anda atau bahkan menolak menerima kebijakan yang salah. Kubernetes juga melakukan beberapa verifikasi. Saat menetapkan kebijakan jaringan melalui kubectl, Kubernetes mungkin menyatakan bahwa kebijakan tersebut salah dan menolak untuk menerimanya. Dalam kasus lain, Kubernetes akan mengambil kebijakan tersebut dan mengisinya dengan detail yang hilang. Mereka dapat dilihat menggunakan perintah:

kubernetes get networkpolicy <policy-name> -o yaml

Perlu diingat bahwa sistem validasi Kubernetes tidak sempurna dan mungkin melewatkan beberapa jenis kesalahan.

Eksekusi

Kubernetes tidak mengimplementasikan kebijakan jaringan itu sendiri, namun hanyalah sebuah gateway API yang mendelegasikan beban kendali ke sistem dasar yang disebut Container Networking Interface (CNI). Menetapkan kebijakan pada cluster Kubernetes tanpa menetapkan CNI yang sesuai sama dengan membuat kebijakan pada server manajemen firewall tanpa kemudian menginstalnya pada firewall. Terserah pada Anda untuk memastikan bahwa Anda memiliki CNI yang layak atau, dalam kasus platform Kubernetes, dihosting di cloud (Anda dapat melihat daftar penyedia di sini β€” kira-kira. trans.), aktifkan kebijakan jaringan yang akan menetapkan CNI untuk Anda.

Perhatikan bahwa Kubernetes tidak akan memperingatkan Anda jika Anda menetapkan kebijakan jaringan tanpa bantuan CNI yang sesuai.

Berstatus atau Tanpa Kewarganegaraan?

Semua CNI Kubernetes yang saya temui bersifat stateful (misalnya, Calico menggunakan koneksi Linux). Hal ini memungkinkan pod untuk menerima respons pada koneksi TCP yang dimulainya tanpa harus membangunnya kembali. Namun, saya tidak mengetahui standar Kubernetes yang dapat menjamin status.

Manajemen Kebijakan Keamanan Tingkat Lanjut

Berikut beberapa cara untuk meningkatkan penegakan kebijakan keamanan di Kubernetes:

  1. Pola arsitektur Service Mesh menggunakan kontainer sespan untuk menyediakan telemetri terperinci dan kontrol lalu lintas di tingkat layanan. Sebagai contoh bisa kita ambil Istio.
  2. Beberapa vendor CNI telah memperluas alat mereka untuk melampaui kebijakan jaringan Kubernetes.
  3. Tufin Orca Memberikan visibilitas dan otomatisasi kebijakan jaringan Kubernetes.

Paket Tufin Orca mengelola kebijakan jaringan Kubernetes (dan merupakan sumber dari tangkapan layar di atas).

informasi tambahan

Kesimpulan

Kebijakan jaringan Kubernetes menawarkan seperangkat alat yang bagus untuk melakukan segmentasi klaster, namun kebijakan tersebut tidak intuitif dan memiliki banyak kehalusan. Karena kerumitan ini, saya yakin banyak kebijakan klaster yang ada bermasalah. Solusi yang mungkin untuk masalah ini termasuk mengotomatiskan definisi kebijakan atau menggunakan alat segmentasi lainnya.

Saya harap panduan ini membantu menjernihkan beberapa pertanyaan dan menyelesaikan masalah yang mungkin Anda temui.

PS dari penerjemah

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar