Kubernetes RBAC分析により簡単になりました
Kraneは、単純なKubernetes RBAC静的分析ツールです。 K8S RBAC設計の潜在的なセキュリティリスクを特定し、それらを緩和する方法について提案します。 Krane Dashboardは、現在のRBACセキュリティの姿勢を提示し、その定義をナビゲートできます。
ターゲットKubernetesクラスターにヘルムチャート経由でインストールするか、Dockerでローカルに実行することで、Kraneを始めることができます。
ヘルムCLIがマシンにインストールされていると想定されています。
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespaceポートフォワードクレーンダッシュボードの方法について、ヘルムチャートのインストール出力をフォローしてください。
ローカルマシンでDockerを実行していると想定されています。まだ行っていない場合は、Docker-Composeをインストールしてください。
クレーンはredisgraphに依存しています。 docker-compose Stackは、 Krane Serviceをローカルで構築および実行するために必要なものをすべて定義します。また、Redisgraphの依存度も処理します。
docker-compose up -d
Krane Docker Imageは、ローカルマシンにまだ存在していない場合、自動的に事前に構築されます。
docker-composeローカルで実行している場合、 KraneはRBACレポートとダッシュボードを自動的に開始しないことに注意してください。代わりに、コンテナはデフォルトで24時間スリープされます - この値はdocker-compose.override.ymlで調整できます。実行中のクレーンコンテナに執行してコマンドを実行します。また、ローカルdocker-compose既にアクセスできるKubernetesクラスターに対してレポートを実行できるようにするため、Kube Config( ~/.kube/config )をコンテナ内にマウントします。
実行中のクレーンコンテナに執行します。
docker-compose exec krane bashコンテナに入ったら、 kraneコマンドの使用を開始できます。 krane -helpをお試しください。
krane -h実行中のサービスと関連するポートを調べるには:
docker-compose ps
Kraneとその依存サービスを停止するには:
docker-compose down
$ krane --help
NAME:
krane
DESCRIPTION:
Kubernetes RBAC static analysis & visualisation tool
COMMANDS:
dashboard Start K8s RBAC dashboard server
help Display global or [command] help documentation
report Run K8s RBAC report
GLOBAL OPTIONS:
-h, --help
Display help documentation
-v, --version
Display version information
-t, --trace
Display backtrace when an error occurs
AUTHOR:
Marcin Ciszak <[email protected]> - Appvia Ltd <appvia.io>
kubectlコンテキストで実行中のクラスターに対してレポートを実行するには、 Kubectlコンテキストを提供する必要があります
krane report -k <context>
また、各クラスター名の複数のクラスターとインデックスRBACグラフに対してツールを実行する予定がある場合は-c <cluster-name>フラグを渡すこともできます。
ローカルRBAC YAML/JSONファイルに対するレポートを実行するには、ディレクトリパスを提供します
krane report -d </path/to/rbac-directory>
注: Kraneは、次のファイル(YAMLまたはJSON形式のいずれか)が指定されたディレクトリパスに存在することを期待しています。
PODセキュリティポリシーが使用されていない場合は、次のコンテンツで手動でpspファイルを作成することで、上記の期待をバイパスできます。
{
"items" : []
}注PodSecurityPolicy Kubernetes v1.21で廃止され、v1.25のKubernetesから除去されました。
Kubernetesクラスターで実行されているコンテナからレポートを実行するには
krane report --incluster
注: Kraneが使用するサービスアカウントでは、RBACリソースへのアクセスが必要です。詳細については、前提条件を参照してください。
CI/CDパイプラインのステップとしてRBAC定義を検証する
krane report --ci -d </path/to/rbac-directory>
注: Kraneは、ローカルに保存されたRBACリソースファイルについて、特定の命名条約に従うことを期待しています。上記のセクションを参照してください。 kraneコマンドを実行するには、CI executorがquay.io/appvia/krane:latest docker画像を参照することをお勧めします。
CIモードは--ciフラグによって有効になります。 Kraneは、1つ以上の危険が検出された場合、リスクルールを破る詳細とともに、非ゼロステータスコードを返します。
RBACファセットツリー、ネットワークグラフ、および最新のレポートの結果を表示するには、最初にダッシュボードサーバーを開始する必要があります。
krane dashboard
クラスターフラグ-c <cluster-name>特定のクラスター名に対してダッシュボードを実行する場合は、渡される場合があります。ダッシュボードは、ファイルシステムにキャッシュされた指定されたクラスター名に関連するデータを探します。
上記のコマンドは、デフォルトのポート8000でローカルWebサーバーを起動し、ダッシュボードリンクを表示します。
Krane Indexes RBACはRedisgraphに絡み合っています。これにより、依存関係のネットワークを効率的に、単にRedisgraphがサポートするCyPHERQLのサブセットを使用することができます。
次のノードは、関連するRBACオブジェクトのグラフに作成されています。
Psp -PODセキュリティポリシーの周りに属性を含むPSPノード。 k8s <1.25で作業する場合にのみ適用されます。Rule - ルールノードは、Kubernetesリソースに関するアクセス制御ルールを表します。Role - ロールノードは、特定の役割またはクラスターロールを表します。 kind属性は、役割のタイプを定義します。Subject - 科目はクラスター内のすべての可能なアクターを表します( kind :ユーザー、グループ、およびサービケアクロント)Namespace -KubernetesNamespaceノード。 :SECURITY - ルールノードとPSPノードの間のリンクを定義します。 k8s <1.25で作業する場合にのみ適用されます。:GRANTその役割に関連するルールとの間のリンクを定義します。:ASSIGN -assion-アクター(件名)と指定された役割/クラスターロール(ロールノード)の間のリンクを定義します。:RELATION - 2つの異なるアクター(サブジェクト)ノード間のリンクを定義します。:SCOPEロールと名前空間ノードの間のリンクを定義します。:ACCESS - サブジェクトと名前空間ノードの間のリンクを定義します。:AGGREGATEクラスターロール間のリンクを定義します(1つのクラスターロールが別の集合体を集めます) A-(aggregates)->B:COMPOSITEクラスターロール間のリンクを定義します(あるクラスターロールは別のクラスターロールで集約できます) A<-(is a composite of)-Bすべてのエッジは双方向であるため、グラフはどちらの方向にも照会できます。例外のみが:AGGREGATE同じエッジノードに関係していますが、統一性の:COMPOSITE関係。
グラフを直接照会するには、実行中のredisgraphコンテナに実行し、 redis-cliを起動して任意のクエリを実行できます。コマンドの例については、公式の指示に従ってください。
Krane Consoleからグラフをクエリすることもできます。次に、最初のエグゼクティブを実行します
# Start Krane console - this will open interactive ruby shell with Krane code preloaded
console
# Instantiate Graph client
graph = Krane :: Clients :: RedisGraph . client cluster : 'default'
# Run arbitrary CypherQL query against indexed RBAC Graph
res = graph . query ( %Q(
MATCH (r:Rule {resource: "configmaps", verb: "update"})<-[:GRANT]-(ro:Role)<-[:ASSIGN]-(s:Subject)
RETURN s.kind as subject_kind, s.name as subject_name, ro.kind as role_kind, ro.name as role_name) )
# Print the results
res . print_resultset # Results...
+----------------+--------------------------------+-----------+------------------------------------------------+
| subject_kind | subject_name | role_kind | role_name |
+----------------+--------------------------------+-----------+------------------------------------------------+
| ServiceAccount | bootstrap-signer | Role | system:controller:bootstrap-signer |
| User | system:kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| ServiceAccount | kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| User | system:kube-scheduler | Role | system::leader-locking-kube-scheduler |
| ServiceAccount | kube-scheduler | Role | system::leader-locking-kube-scheduler |
+----------------+--------------------------------+-----------+------------------------------------------------+
注:上記のクエリの例は、割り当てられた役割/ClusterRolesを備えたすべての被験者を選択し、 update configmapsへのアクセスを許可します。
RBACリスクルールは、ルールファイルで定義されています。各ルールの構造は、主に自明です。内蔵セットは、Cutomルールファイルに追加のカスタムルールを追加することにより、拡張 /オーバーライドできます。
マクロは、共通/共有属性のセットの「コンテナ」であり、1つ以上のリスクルールで参照されます。特定のリスクmacro: <macro-name>でマクロを使用することを選択した場合、名前で参照する必要があります。参照されたmacroで定義されている属性は、ルールレベルで定義されているのと同じ属性よりも優先されることに注意してください。
マクロには、次の属性のいずれかを含めることができます。
query - Redisgraphクエリ。 templateよりも優先されます。 writerを定義する必要があります。writer - ライターは、結果セットをqueryフォーマットに使用するRuby Expressionです。作家はtemplateよりも優先されます。template - 組み込みクエリ/ライターテンプレート名。 queryとwriterが指定されていない場合、選択したクエリジェネレーターはマッチングライターとともに使用されます。 ルールには、次の属性のいずれかを含めることができます。
id [必須]ルールIDは一意のルール識別子です。
group_title [必須]このリスクチェックに該当するすべてのアイテムに適用されるタイトル。
severity [必須]重大度、危険、:警告、:情報。
info [必須]チェックに関するテキスト情報と、リスクを軽減する方法に関する提案。
query [Conditonal] Redisgraphクエリ。
templateよりも優先されます。 writerを定義する必要があります。 writer [Conditonal] Writerは、クエリ結果セットをフォーマットするために使用されるRuby Expressionです。
templateよりも優先されます。定義するqueryが必要です。 template [Conditonal]組み込みクエリ/ライターテンプレート名。 queryとwriterが指定されていない場合、選択したクエリジェネレーターはマッチングライターとともに使用されます。
いくつかの内蔵テンプレートでは、正しいクエリを構築するために、個々のルールレベルでmatch_rules属性を指定する必要があります。現在それを必要としているテンプレート:
match_rulesで指定されたアクセスルールに基づいて、マルチマッチグラフクエリを構築します。生成されたグラフクエリは、次の列を返します。 match_rules [Conditonal]は、クエリを作成するためにtemplate Matchルールに依存している場合に必要です。
match_rules :
- resources : ['cronjobs']
verbs : ['update'] custom_params [オプション]ルールqueryとwriter表現で評価および置き換えるカスタムキー価値ペアのリスト。
custom_params :
- attrA : valueA
- attrB : valueB{{attrA}}および{{attrB}}それぞれvalueAとvalueBに置き換えられます。 threshold [オプション]数値。定義されている場合、これはwriter表現でテンプレートプレースホルダー{{threshold}}として利用可能になります。
macro [オプション]名前付きマクロで定義された共通パラメーターへの参照。
disabled [オプション] trueに設定すると、指定されたルールを無効にし、評価から除外します。デフォルトでは、すべてのルールが有効になっています。
- id : verbose-rule-example
group_title : Example rule
severity : :danger
info : Risk description and instructions on how to mitigate it goes here
query : |
MATCH
(s:Subject)-[:ACCESS]->(ns:Namespace)
WHERE
NOT s.name IN {{whitelist_subject_names}}
RETURN
s.kind as subject_kind,
s.name as subject_name,
COLLECT(ns.name) as namespace_names
ORDER BY
subject_kind,
subject_name,
namespace_names DESC
threshold : 2
writer : |
if result.namespace_names.count > {{threshold}}
"#{result.subject_kind} #{result.subject_name} can access namespaces: #{result.namespace_names.join(', ')}"
end
disabled : true上記の例は、RBACリスクの評価に使用されるグラフqueryと、クエリ結果セットのフォーマットに使用されるwriter表現を明示的に定義します。クエリは、すべてのSubjects (ホワイトリストを除く)とアクセスできるNamespacesを選択するだけです。結果セットには、 2以上の名前空間にアクセスできるSubjectsのみが含まれることに注意してください(そこにあるthresholdが表示されますか?)。ラストwriterの表現は、フォーマットされた結果アイテム出力としてキャプチャされます。
writer result.subject_name Queryによって返される要素を一致させるresult.subject_kindを使用して、 resultセットアイテムにアクセスできます。
注記:
{{threshold}} writerのプレースホルダーは、ルールのthresholdキーワード値に置き換えられます。{{whitelist_subject_names}}特定のルールidに対して定義されたホワイトリスト値と補間されるカスタムフィールドを表します。プレースホルダーのフィールド名がホワイトリストに定義されていない場合、デフォルトでは空の配列['']で置き換えられます。以下のホワイトリストの詳細をご覧ください。 組み込みテンプレートは、リスクルールの定義を大幅に簡素化しますが、特定の種類の情報を抽出するように設計されており、カスタムルールに適していない場合があります。複数のルールにわたって同じqueryまたはwriter表現を再利用していることに気付いた場合は、それらをmacroに抽出することを検討し、カスタムルールでそれを参照して乾燥させる必要があります。
- id : risky-any-verb-secrets
group_title : Risky Roles/ClustersRoles allowing all actions on secrets
severity : :danger
info : Roles/ClusterRoles allowing all actions on secrets. This might be dangerous. Review listed Roles!
template : risky-role
match_rules :
- resources : ['secrets']
verbs : ['*']上記の例は、組み込みのルールの1つを示しています。ルール評価がトリガーする前にqueryとwriter表現を注入することにより、処理時にルールを拡張するrisky-roleテンプレートを参照します。 match_rules 、適切なマッチクエリを構築するために使用されます。
オプションのホワイトリストには、カスタム定義属性名のセットとそれぞれの(ホワイトリスト)値が含まれています。
属性名とその値は任意です。それらはホワイトリストファイルで定義され、3つの別々のセクションに分かれています。
global - トップレベルの範囲。ここで定義されているカスタム属性は、クラスター名に関係なく、すべてのリスクルールに適用されます。common - カスタム属性は、クラスター名に関係なく、特定のリスクルールidにスコープされます。cluster (クラスター名のネストされたリスト付き) - カスタム属性は、特定のクラスター名の特定のリスクルールidに適用されます。各リスクルールは、評価時に、 queryで使用されているすべてのパラメータープレースホルダー{{your_whitelist_attribute_name}}散布しようとします。プレースホルダーパラメーター名(つまり、ダブルカーリーブラケットの間の名前)が、そのリスクルールidのホワイトリスト属性名のいずれかと一致する場合、計算値に置き換えられます。特定のプレースホルダーに値が見つからない場合、 ['']に置き換えられます。
以下のホワイトリストの例では、次のplaceholder-key => value id属性値が「SomeRisk-Rule-ID」を一致させるリスクルールの値マッピングを生成します。
{{whitelist_role_names}} => ['acp:prometheus:operator']
{{whitelist_subject_names}} => ['privileged-psp-user', 'another-user']
上記のプレースホルダーキーは、カスタムグラフクエリで使用される場合、リスクルール評価時にそれぞれの値に置き換えられます。
例:
---
rules :
global : # global scope - applies to all risk rule and cluster names
whitelist_role_names : # custom attribute name
- acp:prometheus:operator # custom attribute values
common : # common scope - applies to specific risk rule id regardless of cluster name
some-risk-rule-id : # this corresponds to risk rule id defined in config/rules.yaml
whitelist_subject_names : # custom attribute name
- privileged-psp-user # custom attribute values
cluster : # cluster scope - applies to speciifc risk rule id and cluster name
default : # example cluster name
some-risk-rule-id : # risk rule id
whitelist_subject_names : # custom attribute nane
- another-user # custom attribute values Kraneは、ローカルまたはリモートのKubernetesクラスターに簡単に展開できます。
Kubernetesの名前空間、サービスアカウントと適切なRBACがクラスターに存在する必要があります。参照のために前提条件を参照してください。
デフォルトのKrane EntryPointは、RBACレポートループとダッシュボードWebサーバーを開始する前に、Redisgraphインスタンスが利用可能になるのを待つBIN/Cluster-Runを実行します。
次の環境変数を使用して、クラスター内実行の特定の側面を制御できます。
KRANE_REPORT_INTERVAL RBAC静的分析レポートの実行の間隔を秒単位で定義します。デフォルト: 300 (秒単位、つまり5分)。KRANE_REPORT_OUTPUT RBACリスクレポート出力形式を定義します。考えられる値:json 、 :yaml 、 :none 。デフォルト:: :json 。開始する前に、次のツールが必要です。
ヘルムチャートのインストール:
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespace他の設定可能なオプションとパラメーターの詳細については、value.yamlファイルを参照してください。
kubectl create
--context < docker-desktop >
--namespace krane
-f k8s/redisgraph-service.yaml
-f k8s/redisgraph-deployment.yaml
-f k8s/krane-service.yaml
-f k8s/krane-deployment.yamlKrane Dashboardサービスはデフォルトで公開されていないことに注意してください!
kubectl port-forward svc/krane 8000
--context= < docker-desktop >
--namespace=krane
# Open Krane dashboard at http://localhost:8000K8Sディレクトリで展開の例を見つけることができます。
展開に必要に応じてマニフェストを変更して、展開ファイルのKrane Docker画像の正しいバージョンを参照するようにします。利用可能なタグについては、Krane Dockerレジストリを参照するか、 latestを使用してください。
K8Sクラスターに組み込みのCompose-on-Kubernetesコントローラーサポートが付属している場合( docker-desktopデフォルトでそれをサポートします)、単一のDockerスタックコマンドでKraneとその依存関係を展開できます。
docker stack deploy
--orchestrator kubernetes
--namespace krane
--compose-file docker-compose.yml
--compose-file docker-compose.k8s.yml krane注:上記のコマンドを実行する前に、現在のKubeコンテキストが正しく設定されていることを確認してください!
アプリケーションスタックは、Kubernetesクラスターとすべてのサービスが準備完了して露出しているように展開する必要があります。 Kraneは、レポートループおよびダッシュボードサーバーを自動的に開始することに注意してください。
docker stack services --orchestrator kubernetes --namespace krane krane上記のコマンドは、次の出力を生成します。
ID NAME MODE REPLICAS IMAGE PORTS
0de30651-dd5 krane_redisgraph replicated 1/1 redislabs/redisgraph:1.99.7 *:6379->6379/tcp
aa377a5f-62b krane_krane replicated 1/1 quay.io/appvia/krane:latest *:8000->8000/tcp
http:// localhost:8000にアクセスして、KubernetesクラスターRBACセキュリティの姿勢を確認してください。
リモートクラスターの展開には、最初にポートフォワードクレーンサービスが必要である可能性が高いことに注意してください
kubectl --context=my-remote-cluster --namespace=krane port-forward svc/krane 8000スタックを削除します
docker stack rm krane
--orchestrator kubernetes
--namespace kraneKraneは、そのスラック統合を介して、中程度と高い重症度の異常が検出されたことについて通知します。
通知を有効にするには、config/config.yamlファイルでslack webhook_url & channelを指定するか、またはSLACK_WEBHOOK_URLとSLACK_CHANNEL環境変数の両方を設定します。環境変数は、構成ファイル値よりも優先されます。
このセクションでは、現地開発を可能にする手順について説明します。
Kraneコード依存関係をインストールします
./bin/setupクレーンはredisgraphに依存しています。 docker-compose Kraneの依存関係をローカルで実行する最も迅速な方法です。
docker-compose up -d redisgraphRedisgraphサービスを検査するには:
docker-compose psサービスを停止する:
docker-compose downこの時点で、ローカルシェルでコマンドを呼び出すことにより、クレーンコードベースとテスト結果を変更できるはずです。
$ ./bin/krane --help # to get help
$ ./bin/krane report -k docker-desktop # to generate your first report for
# local docker-desktop k8s cluster
...ダッシュボードUIローカル開発モードを有効にするには
$ cd dashboard
$ npm install
$ npm startこれにより、ダッシュボードサーバーが自動的に起動し、デフォルトのブラウザを開き、ソースファイルの変更を監視します。
Kraneは、Skaffoldで開発者エクスペリエンスを改善するために事前に設定されています。ローカルまたはリモートのKubernetesクラスターでスタック全体を実行することでプロジェクトを反復し、アプリケーションを検証しました。コードホットレロードにより、ローカルの変更を実行中のコンテナに自動的に伝播して、開発ライフサイクルを高速化します。
skaffold dev --kube-context docker-desktop --namespace krane --port-forwardローカルでテストを実行します
bundle exec rspecコミュニティからの貢献を歓迎します!開始方法の詳細については、寄付ガイドをご覧ください。 Kraneを使用したり、有用であることを見つけたり、一般的にKubernetesのセキュリティに興味がある場合は、このレポを視聴してお知らせください。ありがとう!
コミュニティチャネルに関するディスカッションに参加してください。
Kraneはコミュニティプロジェクトであり、ご貢献を歓迎します。バグを報告する、改善を提案するか、新しい機能をリクエストするには、GitHubの問題を開いてください。あなたが支援する方法の詳細については、私たちの寄稿ガイドを参照してください。
プロジェクトの計画の詳細については、ロードマップをご覧ください。
著者:Marcin Ciszak [email protected]
Copyright(c)2019-2020 Appvia Ltd
このプロジェクトは、Apacheライセンスバージョン2.0の下で配布されています。