コマンド一発でEKSベストプラクティスに沿っているかチェックできる! Hardeneksを使ってみた

2023.01.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Hardeneksとは

EKSのベストプラクティスは、以下でまとめられています。ありがたい。

なのですが、自分のクラスターがこのベスプラに準拠しているのかどうか逐一チェックしていくのは中々大変です。量(項目数) が多いですし、各項目も内容が難しかったりします。

そこでこのHardeneksです。このツールはコマンド一発で対象のEKSクラスターがベストプラクティスに準拠しているのかチェックして結果を返してくれます。

注意点

EKS Best Practices Guidesに書かれている全項目をチェックするわけではありません。一部の項目だけです。

インストール

pipで簡単にインストール可能です。

% pip install hardeneks

チェック対象のEKSクラスターを作成

EKS Blueprintsのexampleからeks-cluster-with-new-vpcを使うことにします。

% direnv reload  #AWSアカウント認証
% git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git
% cd examples/eks-cluster-with-new-vpc/
% terraform init
% terraform apply

最初の行のdirenvコマンドでのAWS認証についての詳細は以下をご確認ください。

チェック

まずコンテキストを作成して先程Terraformで作ったEKSクラスターに接続できるようにします。

% aws eks --region us-west-2 update-kubeconfig --name eks-cluster-with-new-vpc

その後コマンド実行です。

% hardeneks # 実際には `hardeneks --export-txt=result.txt`としてブログにコピペした際に見やすくしました

出力結果は以下です。(長いです)

*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  HARDENEKS *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 
You are operating at ap-northeast-1
You context is arn:aws:eks:us-west-2:047429787746:cluster/eks-cluster-with-new-vpc
Your cluster name is None
You are using 
/Users/kazue.masaki/.anyenv/envs/pyenv/versions/3.11.1/lib/python3.11/site-packages/hardeneks/config.yaml as your 
config file

- - - - - - - - - - - - - - - - - - - - - -  Checking cluster wide rules - - - - - - - - - - - - - - - - - - - - - - 

╭─────────────────────────── Don't bind clusterroles to anonymous/unauthenticated groups ───────────────────────────╮
│ ┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                    │
│ ┃ Kind               ┃ Namespace ┃ Name                      ┃                                                    │
│ ┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                    │
│ │ ClusterRoleBinding │           │ system:public-info-viewer │                                                    │
│ └────────────────────┴───────────┴───────────────────────────┘                                                    │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Update the aws-node daemonset to use IRSA                                                                         │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────── ClusterRoles should not have '*' in Verbs or Resources ──────────────────────────────╮
│ ┏━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                         │
│ ┃ Kind        ┃ Namespace ┃ Name                                        ┃                                         │
│ ┡━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                         │
│ │ ClusterRole │           │ aws-node                                    │                                         │
│ │ ClusterRole │           │ cluster-admin                               │                                         │
│ │ ClusterRole │           │ cluster-admin                               │                                         │
│ │ ClusterRole │           │ cluster-admin                               │                                         │
│ │ ClusterRole │           │ eks:addon-manager                           │                                         │
│ │ ClusterRole │           │ eks:cloud-controller-manager                │                                         │
│ │ ClusterRole │           │ gatekeeper-manager-role                     │                                         │
│ │ ClusterRole │           │ gatekeeper-manager-role                     │                                         │
│ │ ClusterRole │           │ gatekeeper-manager-role                     │                                         │
│ │ ClusterRole │           │ gatekeeper-manager-role                     │                                         │
│ │ ClusterRole │           │ system:controller:generic-garbage-collector │                                         │
│ │ ClusterRole │           │ system:controller:horizontal-pod-autoscaler │                                         │
│ │ ClusterRole │           │ system:controller:horizontal-pod-autoscaler │                                         │
│ │ ClusterRole │           │ system:controller:namespace-controller      │                                         │
│ │ ClusterRole │           │ system:controller:resourcequota-controller  │                                         │
│ │ ClusterRole │           │ system:kube-controller-manager              │                                         │
│ │ ClusterRole │           │ system:kubelet-api-admin                    │                                         │
│ └─────────────┴───────────┴─────────────────────────────────────────────┘                                         │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────────────── Namespaces should have quotas assigned ──────────────────────────────────────╮
│ ┏━━━━━━━━━━━━━━┓                                                                                                  │
│ ┃ Namespace    ┃                                                                                                  │
│ ┡━━━━━━━━━━━━━━┩                                                                                                  │
│ │ default      │                                                                                                  │
│ │ cert-manager │                                                                                                  │
│ └──────────────┘                                                                                                  │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Install aws privateca issuer for your certificates.                                                               │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭─────────────────────────── Namespaces that does not have default network deny policies ───────────────────────────╮
│ ┏━━━━━━━━━━━━━━┓                                                                                                  │
│ ┃ Namespace    ┃                                                                                                  │
│ ┡━━━━━━━━━━━━━━┩                                                                                                  │
│ │ default      │                                                                                                  │
│ │ cert-manager │                                                                                                  │
│ └──────────────┘                                                                                                  │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Enable Amazon Inspector for ec2 and ecr                                                                           │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭──────────────────────────────────────── Namespaces should have psa modes. ────────────────────────────────────────╮
│ ┏━━━━━━━━━━━━━━━━━━━┓                                                                                             │
│ ┃ Namespace         ┃                                                                                             │
│ ┡━━━━━━━━━━━━━━━━━━━┩                                                                                             │
│ │ amazon-cloudwatch │                                                                                             │
│ │ kube-node-lease   │                                                                                             │
│ │ kube-public       │                                                                                             │
│ │ kube-system       │                                                                                             │
│ │ kubecost          │                                                                                             │
│ └───────────────────┘                                                                                             │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭─────────────────────────────────────────── Make image tags immutable. ────────────────────────────────────────────╮
│ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓                               │
│ ┃ Repository                                                 ┃ imageTagMutability ┃                               │
│ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩                               │
│ │ pet-site                                                   │ MUTABLE            │                               │
│ │ pet-payforadoption                                         │ MUTABLE            │                               │
│ │ pet-traffic-generator                                      │ MUTABLE            │                               │
│ │ pet-listadoptions                                          │ MUTABLE            │                               │
│ │ pet-trafficgenerator                                       │ MUTABLE            │                               │
│ │ pet-list-adoption                                          │ MUTABLE            │                               │
│ │ pet-search-java                                            │ MUTABLE            │                               │
│ │ cdk-hnb659fds-container-assets-047429787746-ap-northeast-1 │ MUTABLE            │                               │
│ │ ecrrepository-3ktca1zgrmx5                                 │ MUTABLE            │                               │
│ │ pet-pay-for-adoption                                       │ MUTABLE            │                               │
│ │ pet-search                                                 │ MUTABLE            │                               │
│ └────────────────────────────────────────────────────────────┴────────────────────┘                               │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Deploy vertical pod autoscaler if needed.                                                                         │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

 - - - - - - - - - - - - - - - - - -  Checking rules against namespace: default  - - - - - - - - - - - - - - - - - - 


 - - - - - - - - - - - - - - - - - Checking rules against namespace: cert-manager  - - - - - - - - - - - - - - - - - 

╭───────────────────────────────────────── Running as root is not allowed ──────────────────────────────────────────╮
│ ┏━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                 │
│ ┃ Kind ┃ Namespace    ┃ Name                                    ┃                                                 │
│ ┡━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                 │
│ │ Pod  │ cert-manager │ cert-manager-89564df59-tqrn9            │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-cainjector-86f7f4749-2gt4n │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-webhook-66c85f8577-rvdmp   │                                                 │
│ └──────┴──────────────┴─────────────────────────────────────────┘                                                 │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭─────────────────────────────────── Set requests and limits for each container. ───────────────────────────────────╮
│ ┏━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                 │
│ ┃ Kind ┃ Namespace    ┃ Name                                    ┃                                                 │
│ ┡━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                 │
│ │ Pod  │ cert-manager │ cert-manager-89564df59-tqrn9            │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-cainjector-86f7f4749-2gt4n │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-webhook-66c85f8577-rvdmp   │                                                 │
│ └──────┴──────────────┴─────────────────────────────────────────┘                                                 │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭───────────────────────────── Configure your images with a read-only root file system ─────────────────────────────╮
│ ┏━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                 │
│ ┃ Kind ┃ Namespace    ┃ Name                                    ┃                                                 │
│ ┡━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                 │
│ │ Pod  │ cert-manager │ cert-manager-89564df59-tqrn9            │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-cainjector-86f7f4749-2gt4n │                                                 │
│ │ Pod  │ cert-manager │ cert-manager-webhook-66c85f8577-rvdmp   │                                                 │
│ └──────┴──────────────┴─────────────────────────────────────────┘                                                 │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭──────────────────────────────────────── Make sure you specify an ssl cert ────────────────────────────────────────╮
│ ┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓                                                                 │
│ ┃ Kind    ┃ Namespace    ┃ Name                 ┃                                                                 │
│ ┡━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩                                                                 │
│ │ Service │ cert-manager │ cert-manager         │                                                                 │
│ │ Service │ cert-manager │ cert-manager-webhook │                                                                 │
│ └─────────┴──────────────┴──────────────────────┘                                                                 │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭──────────────────────────────── Deploy horizontal pod autoscaler for deployments ─────────────────────────────────╮
│ ┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                              │
│ ┃ Kind    ┃ Namespace    ┃ Name                    ┃                                                              │
│ ┡━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                              │
│ │ Service │ cert-manager │ cert-manager            │                                                              │
│ │ Service │ cert-manager │ cert-manager-cainjector │                                                              │
│ │ Service │ cert-manager │ cert-manager-webhook    │                                                              │
│ └─────────┴──────────────┴─────────────────────────┘                                                              │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭────────────────────────────────────── Spread replicas across AZs and Nodes ───────────────────────────────────────╮
│ ┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                              │
│ ┃ Kind    ┃ Namespace    ┃ Name                    ┃                                                              │
│ ┡━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                              │
│ │ Service │ cert-manager │ cert-manager            │                                                              │
│ │ Service │ cert-manager │ cert-manager-cainjector │                                                              │
│ │ Service │ cert-manager │ cert-manager-webhook    │                                                              │
│ └─────────┴──────────────┴─────────────────────────┘                                                              │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

╭──────────────────────────────────── Avoid running single replica deployments ─────────────────────────────────────╮
│ ┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┓                                                           │
│ ┃ Kind       ┃ Namespace    ┃ Name                    ┃                                                           │
│ ┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━┩                                                           │
│ │ Deployment │ cert-manager │ cert-manager            │                                                           │
│ │ Deployment │ cert-manager │ cert-manager-cainjector │                                                           │
│ │ Deployment │ cert-manager │ cert-manager-webhook    │                                                           │
│ └────────────┴──────────────┴─────────────────────────┘                                                           │
╰───────────────────────────────────────────── Click to see the guide ──────────────────────────────────────────────╯

コンソールで見ると以下のように色もついていてもう少し見やすいです。

また、Click to see the guideと書かれている箇所をクリックすると前述のEKS Best Practices Guidesの該当項目ページへ遷移します。

configファイル

デフォルトではhardeneksでチェックできる全項目がチェックされます。configファイルを作ってhardeneks実行時に指定することで特定の項目のみをチェックすることができます。

% hardeneks --config=config.yaml

というか、configファイルを指定しない場合はsite-packagesに予め作成されているconfigファイルを使って実行されて、そのconfigファイルの中身が全項目チェックということのようです。そのファイルの中身は以下でした。

---
ignore-namespaces:
  - kube-node-lease
  - kube-public
  - kube-system
  - kube-apiserver
  - karpenter
  - kubecost
  - external-dns
  - argocd
  - aws-for-fluent-bit
  - amazon-cloudwatch
  - vpa
rules: 
  cluster_wide:
    security:
      iam:
        - disable_anonymous_access_for_cluster_roles
        - check_endpoint_public_access
        - check_aws_node_daemonset_service_account
        - check_access_to_instance_profile
        - restrict_wildcard_for_cluster_roles
      multi_tenancy:
        - ensure_namespace_quotas_exist
      detective_controls:
        - check_logs_are_enabled
      network_security:
        - check_vpc_flow_logs
        - check_awspca_exists
        - check_default_deny_policy_exists
      encryption_secrets:
        - use_encryption_with_ebs
        - use_encryption_with_efs
        - use_efs_access_points
      infrastructure_security:
        - deploy_workers_onto_private_subnets
        - make_sure_inspector_is_enabled
      pod_security:
        - ensure_namespace_psa_exist
      image_security:
        - use_immutable_tags_with_ecr
    reliability:
      applications:
        - check_metrics_server_is_running
        - check_vertical_pod_autoscaler_exists
  namespace_based:
    security: 
      iam:
        - disable_anonymous_access_for_roles
        - restrict_wildcard_for_roles
        - disable_service_account_token_mounts
        - disable_run_as_root_user
        - use_dedicated_service_accounts_for_each_deployment
        - use_dedicated_service_accounts_for_each_stateful_set
        - use_dedicated_service_accounts_for_each_daemon_set
      pod_security:
        - disallow_container_socket_mount
        - disallow_host_path_or_make_it_read_only
        - set_requests_limits_for_containers
        - disallow_privilege_escalation
        - check_read_only_root_file_system
      network_security:
        - use_encryption_with_aws_load_balancers
      encryption_secrets:
        - disallow_secrets_from_env_vars    
      runtime_security:
        - disallow_linux_capabilities
    reliability:
      applications:
        - check_horizontal_pod_autoscaling_exists
        - schedule_replicas_across_nodes
        - run_multiple_replicas
        - avoid_running_singleton_pods
    #   data_plane:
    # networking:
    #   vpc_subnets:
    #   vpc_cni:
    #   prefix_mode:
    #   ipv6:
    #   security_groups:
    #   custom_networking:
    #   load_balancing:

感想

前述の通りこのhardeneksで全ての項目を網羅できているわけでは無いので、このコマンドが通ればALL OK!というわけにはいきませんが、だとしてもベストプラクティスに準拠していく取っ掛かりとしてはとても良いツールだと思います。EKSを使う場合はぜひ一度使って見てください。