diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce769a..12c7207 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,76 @@ +## v0.11.0 (2024-10-15) + +## v0.10.3 (2023-09-11) + +### Fix + +- Remove debugging statement +- Fix security context container bug +- Check container.security_context.capabilities.add before checking capabilites +- Check rules that config has "cluster_wide" or "namespace_based" +- Change validation condition for check_logs_are_enabled rule +- Print namespace name for passed namespace based rules + +## v0.10.1 (2023-07-24) + +### Fix + +- Add resolution url to the json output + +## v0.10.0 (2023-07-12) + +### Feat + +- Add console size as args + +## v0.9.3 (2023-05-15) + +### Fix + +- Fix aws-node service account irsa bug + +## v0.9.2 (2023-05-03) + +### Fix + +- Ignore public info viewer +- Fix namespace psa bug + +## v0.9.0 (2023-03-31) + +### Feat + +- Add json output +- Implement namespace based rules with rule class +- Implement cluster wide security rules with Rule +- Add consolidated tables for cleaner report +- Implement rule class +- Implement security iam with rule class +- Implement reliabillity checks using rule class +- Make scalability section use the rule class +- Implement cluster autoscaling with new rules class +- **scalability**: adding generic get_kube_config and getting clusters to check +- **scalability**: adding checks for compression and skipped file +- **scalability**: adding first scalability checks + +### Fix + +- Fix namespace bug +- **scalability**: checking clusterName in cluster.name +- **scalability**: fixing up some things 2 +- **scalability**: fixing up some things +- **scalability**: only checking current cluster +- **config**: fix up config +- **config**: uncomment config + +### Refactor + +- Simplify tests +- Remove Map Class + ## v0.8.0 (2023-02-02) -### Feat (implemented by @ajpaws) +### Feat - Add check for managed node groups - Add check for CA role polp diff --git a/README.md b/README.md index 0c8898e..92cd97d 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,13 @@ hardeneks [OPTIONS] * `--namespace TEXT`: Namespace to be checked (default is all namespaces) * `--config TEXT`: Path to a hardeneks config file * `--export-txt TEXT`: Export the report in txt format +* `--export-csv TEXT`: Export the report in csv format * `--export-html TEXT`: Export the report in html format +* `--export-json TEXT`: Export the report in json format +* `--export-security-hub`: Export failed checks to AWS Security Hub * `--insecure-skip-tls-verify`: Skip TLS verification +* `--width`: Width of the output (defaults to terminal size) +* `--height`: Height of the output (defaults to terminal size) * `--help`: Show this message and exit. @@ -138,11 +143,11 @@ rules: - avoid_running_singleton_pods ``` -**RBAC**: +## RBAC In order to run hardeneks we need to have some permissions both on AWS side and k8s side. -Minimal IAM role policy: +### Minimal IAM role policy ```json { @@ -182,7 +187,7 @@ Minimal IAM role policy: } ``` -Minimal ClusterRole: +### Minimal ClusterRole ```yaml kind: ClusterRole @@ -191,7 +196,7 @@ metadata: name: hardeneks-runner rules: - apiGroups: [""] - resources: ["namespaces", "resourcequotas", "persistentvolumes", "pods", "services"] + resources: ["namespaces", "resourcequotas", "persistentvolumes", "pods", "services", "nodes"] verbs: ["list"] - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"] @@ -220,7 +225,7 @@ rules: **Installation**: ```console -git clone git@github.com:dorukozturk/hardeneks.git +git clone git@github.com:aws-samples/hardeneks.git cd hardeneks poetry install ``` diff --git a/docs/hardeneks.gif b/docs/hardeneks.gif index 9b607d8..4b50dae 100644 Binary files a/docs/hardeneks.gif and b/docs/hardeneks.gif differ diff --git a/hardeneks/__init__.py b/hardeneks/__init__.py index 275a63e..0621154 100644 --- a/hardeneks/__init__.py +++ b/hardeneks/__init__.py @@ -3,11 +3,16 @@ from pkg_resources import resource_filename import tempfile import yaml +import json +from collections import defaultdict +import csv from botocore.exceptions import EndpointConnectionError import boto3 import kubernetes from rich.console import Console +from rich.table import Table +from rich.panel import Panel import typer from .resources import ( @@ -17,6 +22,8 @@ from .harden import harden from hardeneks import helpers +import datetime +import hashlib app = typer.Typer() console = Console(record=True) @@ -66,6 +73,7 @@ def _get_cluster_name(context, region): def _get_region(): return boto3.session.Session().region_name + def _add_tls_verify(): kubeconfig = helpers.get_kube_config() tmp_config = tempfile.NamedTemporaryFile().name @@ -79,6 +87,182 @@ def _add_tls_verify(): os.remove(tmp_config) +def _export_json(rules: list, json_path=str): + def ndd(): + return defaultdict(ndd) + + json_blob = ndd() + + for rule in rules: + result = { + "status": rule.result.status, + "resources": rule.result.resources, + "resource_type": rule.result.resource_type, + "namespace": rule.result.namespace, + "resolution": rule.url, + } + json_blob[rule._type][rule.pillar][rule.section][rule.message] = result + with open(json_path, "w", encoding="utf-8") as f: + json.dump(json_blob, f, ensure_ascii=False, indent=4) + +def _export_csv(rules: list, csv_path=str): + csv_data = [] + + for rule in rules: + csv_row = { + "Type": rule._type, + "Pillar": rule.pillar, + "Section": rule.section, + "Message": rule.message, + "Status": rule.result.status, + "Resources": ', '.join(rule.result.resources) if rule.result.resources else '', + "Resource Type": rule.result.resource_type, + "Namespace": rule.result.namespace, + "Resolution": rule.url, + } + csv_data.append(csv_row) + + with open(csv_path, "w", encoding="utf-8") as f: + writer = csv.DictWriter(f, fieldnames=csv_data[0].keys()) + writer.writeheader() + writer.writerows(csv_data) + +def _export_security_hub(rules: list,region,context): + """ + Export failed checks to AWS Security Hub as custom findings + """ + try: + security_hub = boto3.client('securityhub', region_name=region) + account_id = boto3.client('sts').get_caller_identity()['Account'] + + findings = [] + current_time = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ') + + for rule in rules: + if not rule.result.status: # Only process failed checks + # Process each failed resource as a separate finding + resources = rule.result.resources if rule.result.resources else ['NoSpecificResource'] + + for resource in resources: + finding = { + 'SchemaVersion': '2018-10-08', + 'Id': f"hardeneks/{rule.pillar}/{rule.section}/{hashlib.md5(resource.encode()).hexdigest()}", + 'ProductArn': f"arn:aws:securityhub:{region}:{account_id}:product/{account_id}/default", + 'GeneratorId': f"hardeneks/{rule.pillar}/{rule.section}", + 'AwsAccountId': account_id, + 'Types': [ + 'Software and Configuration Checks/AWS Security Best Practices' + ], + 'CreatedAt': current_time, + 'UpdatedAt': current_time, + 'Severity': { + 'Label': 'HIGH' + }, + 'Title': rule.message, + 'Description': f"HardenEKS check failed: {rule.message}", + 'Resources': [{ + 'Type': f'EKS {rule.result.resource_type}', + 'Id': context, + 'Partition': 'aws', + 'Region': region + }], + 'Compliance': { + 'Status': 'FAILED' + }, + 'RecordState': 'ACTIVE', + 'Workflow': { + 'Status': 'NEW' + }, + 'ProductFields': { + 'Provider': 'HardenEKS', + 'Pillar': rule.pillar, + 'Section': rule.section + } + } + + # Add namespace information if available + if rule.result.namespace: + finding['ProductFields']['Namespace'] = rule.result.namespace + + # Add remediation URL if available + if rule.url: + finding['Remediation'] = { + 'Recommendation': { + 'Text': 'For remediation steps, see the Amazon EKS Best Practices documentation', + 'Url': rule.url + } + } + + findings.append(finding) + + # Security Hub has a batch limit of 100 findings + if len(findings) >= 100: + try: + response = security_hub.batch_import_findings(Findings=findings) + _process_security_hub_response(response) + findings = [] + except Exception as e: + console.print(f"[red]Error sending batch to Security Hub: {str(e)}[/red]") + + # Send any remaining findings + if findings: + try: + response = security_hub.batch_import_findings(Findings=findings) + _process_security_hub_response(response) + except Exception as e: + console.print(f"[red]Error sending final batch to Security Hub: {str(e)}[/red]") + + console.print("[green]Successfully exported failed checks to Security Hub[/green]") + + except Exception as e: + console.print(f"[red]Error connecting to Security Hub: {str(e)}[/red]") + +def _process_security_hub_response(response): + """ + Process the response from Security Hub batch import + """ + if response['FailedCount'] > 0: + for failure in response['FailedFindings']: + console.print( + f"[yellow]Warning: Failed to import finding: {failure['Id']}, " + f"Error: {failure['ErrorCode']} - {failure['ErrorMessage']}[/yellow]" + ) + + +def print_consolidated_results(rules: list): + + pillars = set([i.pillar for i in rules]) + + for pillar in pillars: + table = Table() + table.add_column("Section") + table.add_column("Namespace") + table.add_column("Rule") + table.add_column("Resource") + table.add_column("Resource Type") + table.add_column("Resolution") + filtered_rules = [i for i in rules if i.pillar == pillar] + for rule in filtered_rules: + color = "red" + namespace = "Cluster Wide" + if rule.result.status: + color = "green" + if rule.result.namespace: + namespace = rule.result.namespace + for resource in rule.result.resources: + table.add_row( + rule.section, + namespace, + rule.message, + resource, + rule.result.resource_type, + f"[link={rule.url}]Link[/link]", + style=color, + ) + console.print(Panel(table, title=f"[cyan][bold]{pillar} rules")) + console.print() + + @app.command() def run_hardeneks( region: str = typer.Option( @@ -102,14 +286,33 @@ def run_hardeneks( default=None, help="Export the report in txt format", ), + export_csv: str = typer.Option( + default=None, + help="Export the report in csv format", + ), export_html: str = typer.Option( default=None, help="Export the report in html format", ), + export_json: str = typer.Option( + default=None, help="Export the report in json format" + ), + export_security_hub: bool = typer.Option( + False, + "--export-security-hub", + help="Export failed checks to AWS Security Hub (Security Hub must be enabled and have securityhub:GetFindings, securityhub:BatchImportFindings IAM permission)", + ), insecure_skip_tls_verify: bool = typer.Option( False, "--insecure-skip-tls-verify", ), + width: int = typer.Option( + default=None, help="Width of the console (defaults to terminal width)" + ), + height: int = typer.Option( + default=None, + help="Height of the console (defaults to terminal height)", + ), ): """ Main entry point to hardeneks. @@ -121,8 +324,13 @@ def run_hardeneks( namespace (str): Specific namespace to be checked config (str): Path to hardeneks config file export-txt (str): Export the report in txt format + export-csv (str): Export the report in csv format export-html (str): Export the report in html format + export-json (str): Export the report in json format + export-security-hub (str): Export the report to AWS Security Hub insecure-skip-tls-verify (str): Skip tls verification + width (int): Output width + height (int): Output height Returns: None @@ -131,9 +339,14 @@ def run_hardeneks( if insecure_skip_tls_verify: _add_tls_verify() else: - # should pass in config file + # should pass in config file kubernetes.config.load_kube_config(context=context) + if width: + console.width = width + if height: + console.height = height + context = _get_current_context(context) if not cluster: @@ -159,24 +372,31 @@ def run_hardeneks( rules = config["rules"] - console.rule("[b]Checking cluster wide rules", characters="- ") - console.print() - resources = Resources(region, context, cluster, namespaces) resources.set_resources() - harden(resources, rules, "cluster_wide") - for ns in namespaces: - console.rule( - f"[b]Checking rules against namespace: {ns}", characters=" -" - ) - console.print() - resources = NamespacedResources(region, context, cluster, ns) - resources.set_resources() - harden(resources, rules, "namespace_based") - console.print() + results = [] + + if "cluster_wide" in rules: + cluster_wide_results = harden(resources, rules, "cluster_wide") + results = results + cluster_wide_results + + if "namespace_based" in rules: + for ns in namespaces: + resources = NamespacedResources(region, context, cluster, ns) + resources.set_resources() + namespace_based_results = harden(resources, rules, "namespace_based") + results = results + namespace_based_results + + print_consolidated_results(results) if export_txt: console.save_text(export_txt) + if export_csv: + _export_csv(results, export_csv) if export_html: console.save_html(export_html) + if export_json: + _export_json(results, export_json) + if export_security_hub: + _export_security_hub(results,region,context) diff --git a/hardeneks/cluster_wide/cluster_autoscaling/cluster_autoscaler.py b/hardeneks/cluster_wide/cluster_autoscaling/cluster_autoscaler.py index 5be50d6..213ea69 100644 --- a/hardeneks/cluster_wide/cluster_autoscaling/cluster_autoscaler.py +++ b/hardeneks/cluster_wide/cluster_autoscaling/cluster_autoscaler.py @@ -1,10 +1,8 @@ import boto3 from kubernetes import client -from rich.panel import Panel -from hardeneks import console +from hardeneks.rules import Rule, Result from ...resources import Resources -from ...report import print_role_action_table, print_node_table def _get_policy_documents_for_role(role_name, iam_client): @@ -39,184 +37,216 @@ def _get_policy_documents_for_role(role_name, iam_client): return actions -def check_any_cluster_autoscaler_exists(resources: Resources): +class check_any_cluster_autoscaler_exists(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = "Cluster Autoscaler or Karpenter is not deployed." + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/" - deployments = [ - i.metadata.name - for i in client.AppsV1Api().list_deployment_for_all_namespaces().items - ] + def check(self, resources: Resources): + deployments = [ + i.metadata.name + for i in client.AppsV1Api() + .list_deployment_for_all_namespaces() + .items + ] + if not ( + "cluster-autoscaler" in deployments or "karpenter" in deployments + ): + self.result = Result(status=False, resource_type="Deployment") + else: + self.result = Result(status=True, resource_type="Deployment") - if not ("cluster-autoscaler" in deployments or "karpenter" in deployments): - console.print( - Panel( - "[red]Cluster Autoscaler or Karpeneter is not deployed.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/]Click to see the guide[/link]", - ) + return self.result + + +class ensure_cluster_autoscaler_and_cluster_versions_match(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = ( + "Cross version compatibility between CA and k8s is not recommended." + ) + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#operating-the-cluster-autoscaler" + + def check(self, resources): + eks_client = boto3.client("eks", region_name=resources.region) + cluster_metadata = eks_client.describe_cluster(name=resources.cluster) + + cluster_version = cluster_metadata["cluster"]["version"] + + deployments = ( + client.AppsV1Api().list_deployment_for_all_namespaces().items ) - console.print() - return False - else: - return True - - -def ensure_cluster_autoscaler_and_cluster_versions_match(resources: Resources): - eks_client = boto3.client("eks", region_name=resources.region) - cluster_metadata = eks_client.describe_cluster(name=resources.cluster) - - cluster_version = cluster_metadata["cluster"]["version"] - - deployments = client.AppsV1Api().list_deployment_for_all_namespaces().items - - for deployment in deployments: - if deployment.metadata.name == "cluster-autoscaler": - ca_containers = deployment.spec.template.spec.containers - ca_image = ca_containers[0].image - ca_image_version = ca_image.split(":")[-1] - if cluster_version not in ca_image_version: - console.print( - Panel( - f"[red]CA({ca_image_version})-k8s({cluster_version}) Cross version compatibility is not recommended.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#operating-the-cluster-autoscaler]Click to see the guide[/link]", + + self.result = Result(status=True, resource_type="Deployment") + + for deployment in deployments: + if deployment.metadata.name == "cluster-autoscaler": + ca_containers = deployment.spec.template.spec.containers + ca_image = ca_containers[0].image + ca_image_version = ca_image.split(":")[-1] + if cluster_version not in ca_image_version: + self.result = Result( + status=False, resource_type="Deployment" ) - ) - console.print() - return False - else: - return True -def ensure_cluster_autoscaler_has_autodiscovery_mode(resources: Resources): +class ensure_cluster_autoscaler_has_autodiscovery_mode(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = "Auto discovery is not enabled for Cluster Autoscaler." + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#operating-the-cluster-autoscaler" - deployments = client.AppsV1Api().list_deployment_for_all_namespaces().items + def check(self, resources): + deployments = ( + client.AppsV1Api().list_deployment_for_all_namespaces().items + ) - for deployment in deployments: - if deployment.metadata.name == "cluster-autoscaler": - ca_containers = deployment.spec.template.spec.containers - ca_command = ca_containers[0].command - if not any( - "node-group-auto-discover" in item for item in ca_command - ): - console.print( - Panel( - "[red]Auto discovery is not enabled for Cluster Autoscaler", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#operating-the-cluster-autoscaler]Click to see the guide[/link]", + self.result = Result(status=True, resource_type="Deployment") + + for deployment in deployments: + if deployment.metadata.name == "cluster-autoscaler": + ca_containers = deployment.spec.template.spec.containers + ca_command = ca_containers[0].command + if not any( + "node-group-auto-discover" in item for item in ca_command + ): + self.result = Result( + status=False, resource_type="Deployment" ) - ) - console.print() - return False - else: - break + else: + break - return True +class use_separate_iam_role_for_cluster_autoscaler(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = "Cluster-autoscaler deployment does not use a dedicated IAM Role (IRSA)." + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#employ-least-privileged-access-to-the-iam-role" -def use_separate_iam_role_for_cluster_autoscaler(resources: Resources): - deployments = client.AppsV1Api().list_deployment_for_all_namespaces().items + def check(self, resources): + deployments = ( + client.AppsV1Api().list_deployment_for_all_namespaces().items + ) - for deployment in deployments: - if deployment.metadata.name == "cluster-autoscaler": - service_account = ( - deployment.spec.template.spec.service_account_name - ) - sa_data = client.CoreV1Api().read_namespaced_service_account( - service_account, "kube-system", pretty="true" - ) - if ( - "eks.amazonaws.com/role-arn" - not in sa_data.metadata.annotations.keys() - ): - console.print( - Panel( - "[red]Cluster-autoscaler deployment does not use a dedicated IAM Role (IRSA)", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#employ-least-privileged-access-to-the-iam-role]Click to see the guide[/link]", - ) - ) - console.print() - return False - else: - break - - return True - - -def employ_least_privileged_access_cluster_autoscaler_role( - resources: Resources, -): - deployments = client.AppsV1Api().list_deployment_for_all_namespaces().items - - iam_client = boto3.client("iam", region_name=resources.region) - - ACTIONS = { - "autoscaling:DescribeAutoScalingGroups", - "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeLaunchConfigurations", - "autoscaling:DescribeScalingActivities", - "autoscaling:DescribeTags", - "ec2:DescribeImages", - "ec2:DescribeInstanceTypes", - "ec2:DescribeLaunchTemplateVersions", - "ec2:GetInstanceTypesFromInstanceRequirements", - "eks:DescribeNodegroup", - "autoscaling:SetDesiredCapacity", - "autoscaling:TerminateInstanceInAutoScalingGroup", - } - - for deployment in deployments: - if deployment.metadata.name == "cluster-autoscaler": - service_account = ( - deployment.spec.template.spec.service_account_name - ) - sa_data = client.CoreV1Api().read_namespaced_service_account( - service_account, "kube-system", pretty="true" - ) - if ( - "eks.amazonaws.com/role-arn" - not in sa_data.metadata.annotations.keys() - ): - break - else: + self.result = Result(status=True, resource_type="Deployment") - sa_iam_role_arn = sa_data.metadata.annotations[ - "eks.amazonaws.com/role-arn" - ] - sa_iam_role = sa_iam_role_arn.split("/")[-1] - actions = _get_policy_documents_for_role( - sa_iam_role, iam_client + for deployment in deployments: + if deployment.metadata.name == "cluster-autoscaler": + service_account = ( + deployment.spec.template.spec.service_account_name ) - - if len(set(actions) - ACTIONS) > 0: - print_role_action_table( - set(actions) - ACTIONS, - "[red]Cluster autoscaler role has unnecessary actions assigned.", - "[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#employ-least-privileged-access-to-the-iam-role]Click to see the guide[/link]", + sa_data = client.CoreV1Api().read_namespaced_service_account( + service_account, "kube-system", pretty="true" + ) + if ( + "eks.amazonaws.com/role-arn" + not in sa_data.metadata.annotations.keys() + ): + self.result = Result( + status=False, resource_type="Deployment" ) - return False else: - return True + break - return False +class employ_least_privileged_access_cluster_autoscaler_role(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = "Cluster autoscaler role has unnecessary actions assigned." + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#employ-least-privileged-access-to-the-iam-role" -def use_managed_nodegroups(resources: Resources): + def check(self, resources): - offenders = [] - nodes = client.CoreV1Api().list_node().items + deployments = ( + client.AppsV1Api().list_deployment_for_all_namespaces().items + ) - for node in nodes: - labels = node.metadata.labels - if "eks.amazonaws.com/nodegroup" in labels.keys(): - pass - elif "alpha.eksctl.io/nodegroup-name" in labels.keys(): - offenders.append(node) - elif "karpenter.sh/provisioner-name" in labels.keys(): - pass - else: - offenders.append(node) + iam_client = boto3.client("iam", region_name=resources.region) + + ACTIONS = { + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeAutoScalingInstances", + "autoscaling:DescribeLaunchConfigurations", + "autoscaling:DescribeScalingActivities", + "autoscaling:DescribeTags", + "ec2:DescribeImages", + "ec2:DescribeInstanceTypes", + "ec2:DescribeLaunchTemplateVersions", + "ec2:GetInstanceTypesFromInstanceRequirements", + "eks:DescribeNodegroup", + "autoscaling:SetDesiredCapacity", + "autoscaling:TerminateInstanceInAutoScalingGroup", + } + self.result = Result(status=True, resource_type="IAM Role Action") + + for deployment in deployments: + if deployment.metadata.name == "cluster-autoscaler": + service_account = ( + deployment.spec.template.spec.service_account_name + ) + sa_data = client.CoreV1Api().read_namespaced_service_account( + service_account, "kube-system", pretty="true" + ) + if ( + "eks.amazonaws.com/role-arn" + not in sa_data.metadata.annotations.keys() + ): + break + else: - if offenders: - print_node_table( - offenders, - "[red]Following nodes are not part of a managed noge group.", - "[link=https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#configuring-your-node-groups]Click to see the guide[/link]", - ) - return offenders + sa_iam_role_arn = sa_data.metadata.annotations[ + "eks.amazonaws.com/role-arn" + ] + sa_iam_role = sa_iam_role_arn.split("/")[-1] + actions = _get_policy_documents_for_role( + sa_iam_role, iam_client + ) + + if len(set(actions) - ACTIONS) > 0: + self.result = Result( + status=False, + resource_type="IAM Role Action", + resources=(set(actions) - ACTIONS), + ) + else: + self.result = Result( + status=True, resource_type="IAM Role Action" + ) + + +class use_managed_nodegroups(Rule): + _type = "cluster_wide" + pillar = "cluster_autoscaling" + section = "cluster_autoscaler" + message = "Nodes are recommended to be part of a managed node group." + url = "https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#configuring-your-node-groups" + + def check(self, resources): + offenders = [] + nodes = client.CoreV1Api().list_node().items + + for node in nodes: + labels = node.metadata.labels + if "eks.amazonaws.com/nodegroup" in labels.keys(): + pass + elif "alpha.eksctl.io/nodegroup-name" in labels.keys(): + offenders.append(node) + elif "karpenter.sh/provisioner-name" in labels.keys(): + pass + else: + offenders.append(node) + + self.result = Result(status=True, resource_type="Node") + + if offenders: + self.result = Result( + status=False, + resource_type="Node", + resources=[i.metadata.name for i in offenders], + ) diff --git a/hardeneks/cluster_wide/reliability/applications.py b/hardeneks/cluster_wide/reliability/applications.py index 243c595..503da42 100644 --- a/hardeneks/cluster_wide/reliability/applications.py +++ b/hardeneks/cluster_wide/reliability/applications.py @@ -1,43 +1,45 @@ from kubernetes import client -from rich.panel import Panel - -from hardeneks import console -from ...resources import Resources - - -def check_metrics_server_is_running(resources: Resources): - services = [ - i.metadata.name - for i in client.CoreV1Api().list_service_for_all_namespaces().items - ] - - if "metrics-server" in services: - return True - else: - console.print( - Panel( - "[red]Deploy metrics server.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#run-kubernetes-metrics-server]Click to see the guide[/link]", - ) - ) - console.print() - return False - - -def check_vertical_pod_autoscaler_exists(resources: Resources): - deployments = [ - i.metadata.name - for i in client.AppsV1Api().list_deployment_for_all_namespaces().items - ] - - if "vpa-recommender" in deployments: - return True - else: - console.print( - Panel( - "[red]Deploy vertical pod autoscaler if needed.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#vertical-pod-autoscaler-vpa]Click to see the guide[/link]", - ) - ) - console.print() - return False + +from hardeneks.rules import Rule, Result +from hardeneks.resources import Resources + + +class check_metrics_server_is_running(Rule): + _type = "cluster_wide" + pillar = "reliability" + section = "applications" + message = "Metrics server is not deployed." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#run-kubernetes-metrics-server" + + def check(self, resources: Resources): + services = [ + i.metadata.name + for i in client.CoreV1Api().list_service_for_all_namespaces().items + ] + + if "metrics-server" in services: + self.result = Result(status=True, resource_type="Service") + else: + self.result = Result(status=False, resource_type="Service") + + +class check_vertical_pod_autoscaler_exists(Rule): + _type = "cluster_wide" + pillar = "reliability" + section = "applications" + message = "Vertical pod autoscaler is not deployed." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#run-kubernetes-metrics-server" + + def check(self, resources: Resources): + + deployments = [ + i.metadata.name + for i in client.AppsV1Api() + .list_deployment_for_all_namespaces() + .items + ] + + if "vpa-recommender" in deployments: + self.result = Result(status=True, resource_type="Deployment") + else: + self.result = Result(status=False, resource_type="Deployment") diff --git a/hardeneks/cluster_wide/scalability/control_plane.py b/hardeneks/cluster_wide/scalability/control_plane.py index b972c65..c575405 100644 --- a/hardeneks/cluster_wide/scalability/control_plane.py +++ b/hardeneks/cluster_wide/scalability/control_plane.py @@ -1,49 +1,58 @@ import re import kubernetes -from rich.panel import Panel from hardeneks import helpers -from hardeneks import console +from hardeneks.rules import Rule, Result from hardeneks import Resources -def check_EKS_version(resources: Resources): - client = kubernetes.client.VersionApi() - version = client.get_code() - minor = version.minor +class check_EKS_version(Rule): + _type = "cluster_wide" + pillar = "scalability" + section = "control_plane" + message = "EKS Version Should be greater or equal to 1.24." + url = "https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#use-eks-124-or-above" - if int(re.sub("[^0-9]", "", minor)) < 24: - console.print( - Panel( - f"[red]EKS Version Should be greater or equal too 1.24. Current Version == {version.major}.{version.minor}", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#use-eks-124-or-above]Click to see the guide[/link]", + def check(self, resources: Resources): + client = kubernetes.client.VersionApi() + version = client.get_code() + minor = version.minor + + if int(re.sub("[^0-9]", "", minor)) < 24: + self.result = Result( + status=False, + resources=f"{version.major}.{minor}", + resource_type="Cluster Version", ) - ) - console.print() - return False + else: + self.result = Result(status=True, resource_type="Cluster Version") - return True # # check_kubectl_compression # checks all clusters in config for disable-compression flag set to true # if any cluster does not have setting, it returns False -def check_kubectl_compression(resources: Resources): - kubeconfig = helpers.get_kube_config() - isSetCorrectly = False - for cluster in kubeconfig.get("clusters", []): - clusterName = cluster.get("name", "") - if (resources.cluster in clusterName): - if cluster.get("cluster", {}).get("disable-compression", False) != True: - console.print( - Panel( - f"[red]`disable-compression` in Cluster {clusterName} should equal True", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#disable-kubectl-compression]Click to see the guide[/link]", +class check_kubectl_compression(Rule): + _type = "cluster_wide" + pillar = "scalability" + section = "control_plane" + message = "`disable-compression` in kubeconfig should equal True" + url = "https://aws.github.io/aws-eks-best-practices/scalability/docs/control-plane/#disable-kubectl-compression" + + def check(self, resources: Resources): + kubeconfig = helpers.get_kube_config() + for cluster in kubeconfig.get("clusters", []): + clusterName = cluster.get("name", "") + if resources.cluster in clusterName: + if not ( + cluster.get("cluster", {}).get( + "disable-compression", False + ) + ): + self.result = Result( + status=False, resource_type="Compression Setting" + ) + else: + self.result = Result( + status=True, resource_type="Compression Setting" ) - ) - console.print() - else: - isSetCorrectly = True - break - - - return isSetCorrectly + break diff --git a/hardeneks/cluster_wide/security/detective_controls.py b/hardeneks/cluster_wide/security/detective_controls.py index 528a128..f0e902e 100644 --- a/hardeneks/cluster_wide/security/detective_controls.py +++ b/hardeneks/cluster_wide/security/detective_controls.py @@ -1,23 +1,23 @@ import boto3 -from rich.panel import Panel -from hardeneks import console from ...resources import Resources +from hardeneks.rules import Rule, Result -def check_logs_are_enabled(resources: Resources): - client = boto3.client("eks", region_name=resources.region) - cluster_metadata = client.describe_cluster(name=resources.cluster) - logs = cluster_metadata["cluster"]["logging"]["clusterLogging"][0][ - "enabled" - ] - if not logs: - console.print( - Panel( - "[red]Enable control plane logs for auditing", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/detective/#enable-audit-logs]Click to see the guide[/link]", - ) - ) - console.print() +class check_logs_are_enabled(Rule): + _type = "cluster_wide" + pillar = "security" + section = "detective_controls" + message = "Enable control plane logs for auditing." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/detective/#enable-audit-logs" - return logs + def check(self, resources: Resources): + client = boto3.client("eks", region_name=resources.region) + cluster_metadata = client.describe_cluster(name=resources.cluster) + logs = filter(lambda x: x.get('enabled') and 'audit' in x.get('types'), + cluster_metadata["cluster"]["logging"]["clusterLogging"]) + self.result = Result(status=True, resource_type="Log Configuration") + if not list(logs): + self.result = Result( + status=False, resource_type="Log Configuration" + ) diff --git a/hardeneks/cluster_wide/security/encryption_secrets.py b/hardeneks/cluster_wide/security/encryption_secrets.py index b740624..f557a68 100644 --- a/hardeneks/cluster_wide/security/encryption_secrets.py +++ b/hardeneks/cluster_wide/security/encryption_secrets.py @@ -1,62 +1,88 @@ from ...resources import Resources -from ...report import print_storage_class_table, print_persistent_volume_table - - -def use_encryption_with_ebs(resources: Resources): - offenders = [] - - for storage_class in resources.storage_classes: - if storage_class.provisioner == "ebs.csi.aws.com": - encrypted = storage_class.parameters.get("encrypted") - if not encrypted: - offenders.append(storage_class) - elif encrypted == "false": - offenders.append(storage_class) - - if offenders: - print_storage_class_table( - offenders, - "[red]EBS Storage Classes should have encryption parameter", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/data/#encryption-at-rest]Click to see the guide[/link]", - ) - return offenders - - -def use_encryption_with_efs(resources: Resources): - offenders = [] - - for persistent_volume in resources.persistent_volumes: - csi = persistent_volume.spec.csi - if csi and csi.driver == "efs.csi.aws.com": - mount_options = persistent_volume.spec.mount_options - if not mount_options: - offenders.append(persistent_volume) - else: - if "tls" not in mount_options: +from hardeneks.rules import Rule, Result + + +class use_encryption_with_ebs(Rule): + _type = "cluster_wide" + pillar = "security" + section = "encryption_secrets" + message = "EBS Storage Classes should have encryption parameter." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/data/#encryption-at-rest" + + def check(self, resources: Resources): + offenders = [] + + for storage_class in resources.storage_classes: + if storage_class.provisioner == "ebs.csi.aws.com": + encrypted = storage_class.parameters.get("encrypted") + if not encrypted: + offenders.append(storage_class) + elif encrypted == "false": + offenders.append(storage_class) + + self.result = Result(status=True, resource_type="StorageClass") + + if offenders: + self.result = Result( + status=False, + resource_type="StorageClass", + resources=[i.metadata.name for i in offenders], + ) + + +class use_encryption_with_efs(Rule): + _type = "cluster_wide" + pillar = "security" + section = "encryption_secrets" + message = "EFS Persistent volumes should have tls mount option." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/data/#encryption-at-rest" + + def check(self, resources: Resources): + + offenders = [] + + for persistent_volume in resources.persistent_volumes: + csi = persistent_volume.spec.csi + if csi and csi.driver == "efs.csi.aws.com": + mount_options = persistent_volume.spec.mount_options + if not mount_options: + offenders.append(persistent_volume) + else: + if "tls" not in mount_options: + offenders.append(persistent_volume) + + self.result = Result(status=True, resource_type="PersistentVolume") + + if offenders: + self.result = Result( + status=False, + resource_type="PersistentVolume", + resources=[i.metadata.name for i in offenders], + ) + + +class use_efs_access_points(Rule): + _type = "cluster_wide" + pillar = "security" + section = "encryption_secrets" + message = "EFS Persistent volumes should leverage access points." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/data/#use-efs-access-points-to-simplify-access-to-shared-datasets" + + def check(self, resources: Resources): + + offenders = [] + + for persistent_volume in resources.persistent_volumes: + csi = persistent_volume.spec.csi + if csi and csi.driver == "efs.csi.aws.com": + if "::" not in csi.volume_handle: offenders.append(persistent_volume) - if offenders: - print_persistent_volume_table( - offenders, - "[red]EFS Persistent volumes should have tls mount option", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/data/#encryption-at-rest]Click to see the guide[/link]", - ) - return offenders - - -def use_efs_access_points(resources: Resources): - offenders = [] - - for persistent_volume in resources.persistent_volumes: - csi = persistent_volume.spec.csi - if csi and csi.driver == "efs.csi.aws.com": - if "::" not in csi.volume_handle: - offenders.append(persistent_volume) - - if offenders: - print_persistent_volume_table( - offenders, - "[red]EFS Persistent volumes should leverage access points", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/data/#use-efs-access-points-to-simplify-access-to-shared-datasets]Click to see the guide[/link]", - ) - return offenders + self.result = Result(status=True, resource_type="PersistentVolume") + + if offenders: + self.result = Result( + status=False, + resource_type="PersistentVolume", + resources=[i.metadata.name for i in offenders], + ) diff --git a/hardeneks/cluster_wide/security/iam.py b/hardeneks/cluster_wide/security/iam.py index 385e66e..b7b3dcf 100644 --- a/hardeneks/cluster_wide/security/iam.py +++ b/hardeneks/cluster_wide/security/iam.py @@ -1,120 +1,162 @@ import boto3 from kubernetes import client -from rich.panel import Panel -from hardeneks import console +from hardeneks.rules import Rule, Result from ...resources import Resources -from ...report import print_role_table, print_instance_metadata_table -def restrict_wildcard_for_cluster_roles(resources: Resources): - offenders = [] +class restrict_wildcard_for_cluster_roles(Rule): + _type = "cluster_wide" + pillar = "security" + section = "iam" + message = "ClusterRoles should not have '*' in Verbs or Resources." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#employ-least-privileged-access-when-creating-rolebindings-and-clusterrolebindings" - for role in resources.cluster_roles: - for rule in role.rules: - if "*" in rule.verbs: - offenders.append(role) - if rule.resources and "*" in rule.resources: - offenders.append(role) + def check(self, resources: Resources): - if offenders: - print_role_table( - offenders, - "[red]ClusterRoles should not have '*' in Verbs or Resources", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#employ-least-privileged-access-when-creating-rolebindings-and-clusterrolebindings]Click to see the guide[/link]", - "ClusterRole", - ) - return offenders - - -def check_endpoint_public_access(resources: Resources): - client = boto3.client("eks", region_name=resources.region) - cluster_metadata = client.describe_cluster(name=resources.cluster) - endpoint_access = cluster_metadata["cluster"]["resourcesVpcConfig"][ - "endpointPublicAccess" - ] - if endpoint_access: - console.print( - Panel( - "[red]EKS Cluster Endpoint is not Private", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#make-the-eks-cluster-endpoint-private]Click to see the guide[/link]", - ) - ) - console.print() - return False + offenders = [] + self.result = Result(status=True, resource_type="Cluster Role") - return True + allow_list = [ + "aws-node", + "cluster-admin", + "eks:addon-manager", + "eks:cloud-controller-manager", + ] + for role in resources.cluster_roles: + role_name = role.metadata.name + if not (role_name.startswith("system") or role_name in allow_list): + for rule in role.rules: + if "*" in rule.verbs: + offenders.append(role_name) + if rule.resources and "*" in rule.resources: + offenders.append(role_name) + + if offenders: + self.result = Result( + status=False, + resources=offenders, + resource_type="Cluster Role", + ) -def check_aws_node_daemonset_service_account(resources: Resources): - daemonset = client.AppsV1Api().read_namespaced_daemon_set( - name="aws-node", namespace="kube-system" - ) - if daemonset.spec.template.spec.service_account_name == "aws-node": - console.print( - Panel( - "[red]Update the aws-node daemonset to use IRSA", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#update-the-aws-node-daemonset-to-use-irsa]Click to see the guide[/link]", - ) - ) - console.print() - return False +class check_endpoint_public_access(Rule): + _type = "cluster_wide" + pillar = "security" + section = "iam" + message = "EKS Cluster Endpoint is not Private." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#make-the-eks-cluster-endpoint-private" - return True + def check(self, resources: Resources): + client = boto3.client("eks", region_name=resources.region) + cluster_metadata = client.describe_cluster(name=resources.cluster) + endpoint_access = cluster_metadata["cluster"]["resourcesVpcConfig"][ + "endpointPublicAccess" + ] + self.result = Result(status=True, resource_type="Cluster Endpoint") + if endpoint_access: + self.result = Result( + status=False, resource_type="Cluster Endpoint" + ) -def check_access_to_instance_profile(resources: Resources): - client = boto3.client("ec2", region_name=resources.region) - offenders = [] - instance_metadata = client.describe_instances( - Filters=[ - { - "Name": "tag:aws:eks:cluster-name", - "Values": [ - resources.cluster, - ], - }, - ] - ) +class check_aws_node_daemonset_service_account(Rule): + _type = "cluster_wide" + pillar = "security" + section = "iam" + message = "Update the aws-node daemonset to use IRSA." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#update-the-aws-node-daemonset-to-use-irsa" - for instance in instance_metadata["Reservations"]: + def check(self, resources: Resources): + daemonset = client.AppsV1Api().read_namespaced_daemon_set( + name="aws-node", namespace="kube-system" + ) + self.result = Result(status=True, resource_type="Daemonset") + v1 = client.CoreV1Api() + service_account = v1.read_namespaced_service_account( + name=daemonset.spec.template.spec.service_account_name, + namespace="kube-system", + ) if ( - instance["Instances"][0]["MetadataOptions"][ - "HttpPutResponseHopLimit" - ] - == 2 + "eks.amazonaws.com/role-arn" + not in service_account.metadata.annotations ): - offenders.append(instance) + self.result = Result( + status=False, resources=["aws-node"], resource_type="Daemonset" + ) - if offenders: - print_instance_metadata_table( - offenders, - "[red]Restrict access to the instance profile assigned to nodes", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#when-your-application-needs-access-to-imds-use-imdsv2-and-increase-the-hop-limit-on-ec2-instances-to-2]Click to see the guide[/link]", - ) - return offenders - - -def disable_anonymous_access_for_cluster_roles(resources: Resources): - offenders = [] - - for cluster_role_binding in resources.cluster_role_bindings: - if cluster_role_binding.subjects: - for subject in cluster_role_binding.subjects: - if ( - subject.name == "system:unauthenticated" - or subject.name == "system:anonymous" - ): - offenders.append(cluster_role_binding) - - if offenders: - print_role_table( - offenders, - "[red]Don't bind clusterroles to anonymous/unauthenticated groups", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#review-and-revoke-unnecessary-anonymous-access]Click to see the guide[/link]", - "ClusterRoleBinding", + +class check_access_to_instance_profile(Rule): + _type = "cluster_wide" + pillar = "security" + section = "iam" + message = "Restrict access to the instance profile assigned to nodes." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#when-your-application-needs-access-to-imds-use-imdsv2-and-increase-the-hop-limit-on-ec2-instances-to-2" + + def check(self, resources: Resources): + client = boto3.client("ec2", region_name=resources.region) + offenders = [] + + instance_metadata = client.describe_instances( + Filters=[ + { + "Name": "tag:aws:eks:cluster-name", + "Values": [ + resources.cluster, + ], + }, + ] ) - return offenders + for instance in instance_metadata["Reservations"]: + if ( + instance["Instances"][0]["MetadataOptions"][ + "HttpPutResponseHopLimit" + ] + == 2 + ): + offenders.append(instance) + + self.result = Result(status=True, resource_type="Node") + + if offenders: + self.result = Result( + status=False, + resource_type="Node", + resources=[i["Instances"][0]["InstanceId"] for i in offenders], + ) + + +class disable_anonymous_access_for_cluster_roles(Rule): + _type = "cluster_wide" + pillar = "security" + section = "iam" + message = "Don't bind clusterroles to anonymous/unauthenticated groups." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#review-and-revoke-unnecessary-anonymous-access" + + def check(self, resources: Resources): + offenders = [] + + ignored = ["system:public-info-viewer"] + + for cluster_role_binding in resources.cluster_role_bindings: + if ( + cluster_role_binding.subjects + and cluster_role_binding.metadata.name not in ignored + ): + for subject in cluster_role_binding.subjects: + if ( + subject.name == "system:unauthenticated" + or subject.name == "system:anonymous" + ): + offenders.append(cluster_role_binding) + + self.result = Result(status=True, resource_type="ClusterRoleBinding") + if offenders: + self.result = Result( + status=False, + resource_type="ClusterRoleBinding", + resources=[i.metadata.name for i in offenders], + ) diff --git a/hardeneks/cluster_wide/security/image_security.py b/hardeneks/cluster_wide/security/image_security.py index ba232c0..558ba4b 100644 --- a/hardeneks/cluster_wide/security/image_security.py +++ b/hardeneks/cluster_wide/security/image_security.py @@ -1,24 +1,29 @@ import boto3 -from ...report import print_repository_table from ...resources import Resources +from hardeneks.rules import Rule, Result -def use_immutable_tags_with_ecr(resources: Resources): - offenders = [] +class use_immutable_tags_with_ecr(Rule): + _type = "cluster_wide" + pillar = "security" + section = "image_security" + message = "Make image tags immutable." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/image/#use-immutable-tags-with-ecr" - client = boto3.client("ecr", region_name=resources.region) - repositories = client.describe_repositories() - for repository in repositories["repositories"]: - if repository["imageTagMutability"] != "IMMUTABLE": - offenders.append(repository) + def check(self, resources: Resources): + offenders = [] - if offenders: - print_repository_table( - offenders, - "imageTagMutability", - "[red]Make image tags immutable.", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/image/#use-immutable-tags-with-ecr]Click to see the guide[/link]", - ) + client = boto3.client("ecr", region_name=resources.region) + repositories = client.describe_repositories() + for repository in repositories["repositories"]: + if repository["imageTagMutability"] != "IMMUTABLE": + offenders.append(repository) - return offenders + self.result = Result(status=True, resource_type="ECR Repository") + if offenders: + self.result = Result( + status=False, + resource_type="ECR Repository", + resources=[i["repositoryName"] for i in offenders], + ) diff --git a/hardeneks/cluster_wide/security/infrastructure_security.py b/hardeneks/cluster_wide/security/infrastructure_security.py index f9508cb..047319b 100644 --- a/hardeneks/cluster_wide/security/infrastructure_security.py +++ b/hardeneks/cluster_wide/security/infrastructure_security.py @@ -1,64 +1,72 @@ import boto3 -from rich.panel import Panel -from hardeneks import console from ...resources import Resources -from ...report import print_instance_public_table - - -def deploy_workers_onto_private_subnets(resources: Resources): - client = boto3.client("ec2", region_name=resources.region) - - offenders = [] - - instance_metadata = client.describe_instances( - Filters=[ - { - "Name": "tag:aws:eks:cluster-name", - "Values": [ - resources.cluster, - ], - }, - ] - ) - - for instance in instance_metadata["Reservations"]: - if instance["Instances"][0]["PublicDnsName"]: - offenders.append(instance) - - if offenders: - print_instance_public_table( - offenders, - "[red]Place worker nodes on private subnets.", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/hosts/#deploy-workers-onto-private-subnets]Click to see the guide[/link]", +from hardeneks.rules import Rule, Result + + +class deploy_workers_onto_private_subnets(Result): + _type = "cluster_wide" + pillar = "security" + section = "infrastructure_security" + message = "Place worker nodes on private subnets." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/hosts/#deploy-workers-onto-private-subnets" + + def check(self, resources: Resources): + client = boto3.client("ec2", region_name=resources.region) + + offenders = [] + + instance_metadata = client.describe_instances( + Filters=[ + { + "Name": "tag:aws:eks:cluster-name", + "Values": [ + resources.cluster, + ], + }, + ] ) - return offenders - - -def make_sure_inspector_is_enabled(resources: Resources): - client = boto3.client("inspector2", region_name=resources.region) - account_id = boto3.client( - "sts", region_name=resources.region - ).get_caller_identity()["Account"] - - response = client.batch_get_account_status( - accountIds=[ - account_id, - ] - ) - - resource_state = response["accounts"][0]["resourceState"] - ec2_status = resource_state["ec2"]["status"] - ecr_status = resource_state["ecr"]["status"] - - if ec2_status != "ENABLED" and ecr_status != "ENABLED": - console.print( - Panel( - "[red]Enable Amazon Inspector for ec2 and ecr", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/hosts/#run-amazon-inspector-to-assess-hosts-for-exposure-vulnerabilities-and-deviations-from-best-practices]Click to see the guide[/link]", + + for instance in instance_metadata["Reservations"]: + if instance["Instances"][0]["PublicDnsName"]: + offenders.append(instance["Instances"][0]["InstanceId"]) + + self.result = Result(status=True, resource_type="Node") + + if offenders: + self.result = Result( + status=False, resource_type="Node", resources=offenders ) + + +class make_sure_inspector_is_enabled(Rule): + _type = "cluster_wide" + pillar = "security" + section = "infrastructure_security" + message = "Enable Amazon Inspector for ec2 and ecr." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/hosts/#deploy-workers-onto-private-subnets" + + def check(self, resources: Resources): + client = boto3.client("inspector2", region_name=resources.region) + account_id = boto3.client( + "sts", region_name=resources.region + ).get_caller_identity()["Account"] + + response = client.batch_get_account_status( + accountIds=[ + account_id, + ] ) - console.print() - return False - return True + resource_state = response["accounts"][0]["resourceState"] + ec2_status = resource_state["ec2"]["status"] + ecr_status = resource_state["ecr"]["status"] + + self.result = Result( + status=True, resource_type="Inspector Configuration" + ) + + if ec2_status != "ENABLED" and ecr_status != "ENABLED": + self.result = Result( + status=False, resource_type="Inspector Configuration" + ) diff --git a/hardeneks/cluster_wide/security/multi_tenancy.py b/hardeneks/cluster_wide/security/multi_tenancy.py index d04c1eb..4eddb62 100644 --- a/hardeneks/cluster_wide/security/multi_tenancy.py +++ b/hardeneks/cluster_wide/security/multi_tenancy.py @@ -1,22 +1,22 @@ from ...resources import Resources +from hardeneks.rules import Rule, Result -from ...report import ( - print_namespace_table, -) +class ensure_namespace_quotas_exist(Rule): + _type = "cluster_wide" + pillar = "security" + section = "multi_tenancy" + message = "Namespaces should have quotas assigned." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/multitenancy/#namespaces" -def ensure_namespace_quotas_exist(resources: Resources): + def check(self, resources: Resources): + offenders = resources.namespaces - offenders = resources.namespaces + for quota in resources.resource_quotas: + offenders.remove(quota.metadata.namespace) - for quota in resources.resource_quotas: - offenders.remove(quota.metadata.namespace) - - if offenders: - print_namespace_table( - offenders, - "[red]Namespaces should have quotas assigned", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/multitenancy/#namespaces]Click to see the guide[/link]", - ) - - return offenders + self.result = Result(status=True, resource_type="Namespace") + if offenders: + self.result = Result( + status=False, resources=offenders, resource_type="Namespace" + ) diff --git a/hardeneks/cluster_wide/security/network_security.py b/hardeneks/cluster_wide/security/network_security.py index 1d6d3d9..02f7561 100644 --- a/hardeneks/cluster_wide/security/network_security.py +++ b/hardeneks/cluster_wide/security/network_security.py @@ -1,61 +1,71 @@ import boto3 from kubernetes import client -from rich.panel import Panel -from hardeneks import console from ...resources import Resources -from ...report import print_namespace_table +from hardeneks.rules import Rule, Result -def check_vpc_flow_logs(resources: Resources): - client = boto3.client("eks", region_name=resources.region) - cluster_metadata = client.describe_cluster(name=resources.cluster) +class check_vpc_flow_logs(Rule): + _type = "cluster_wide" + pillar = "security" + section = "network_security" + message = "Enable flow logs for your VPC." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/network/#log-network-traffic-metadata" - vpc_id = cluster_metadata["cluster"]["resourcesVpcConfig"]["vpcId"] - client = boto3.client("ec2", region_name=resources.region) + def check(self, resources: Resources): + client = boto3.client("eks", region_name=resources.region) + cluster_metadata = client.describe_cluster(name=resources.cluster) - flow_logs = client.describe_flow_logs( - Filters=[{"Name": "resource-id", "Values": [vpc_id]}] - )["FlowLogs"] + vpc_id = cluster_metadata["cluster"]["resourcesVpcConfig"]["vpcId"] + client = boto3.client("ec2", region_name=resources.region) - if not flow_logs: - console.print( - Panel( - "[red]Enable flow logs for your VPC.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/network/#log-network-traffic-metadata]Click to see the guide[/link]", + flow_logs = client.describe_flow_logs( + Filters=[{"Name": "resource-id", "Values": [vpc_id]}] + )["FlowLogs"] + + self.result = Result(status=True, resource_type="VPC Configuration") + if not flow_logs: + self.result = Result( + status=False, resource_type="VPC Configuration" ) - ) - console.print() - return False -def check_awspca_exists(resources: Resources): - services = client.CoreV1Api().list_service_for_all_namespaces().items - for service in services: - if service.metadata.name.startswith("aws-privateca-issuer"): - return True +class check_awspca_exists(Rule): + _type = "cluster_wide" + pillar = "security" + section = "network_security" + message = "Install aws privateca issuer for your certificates." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/network/#acm-private-ca-with-cert-manager" + + def check(self, resources: Resources): + services = client.CoreV1Api().list_service_for_all_namespaces().items + for service in services: + if service.metadata.name.startswith("aws-privateca-issuer"): + self.result = Result(status=True, resource_type="Service") - console.print( - Panel( - "[red]Install aws privateca issuer for your certificates.", - subtitle="[link=https://aws.github.io/aws-eks-best-practices/security/docs/network/#acm-private-ca-with-cert-manager]Click to see the guide[/link]", + self.result = Result( + status=False, + resource_type="Service", + resources=["aws-privateca-issuer"], ) - ) - console.print() - return False -def check_default_deny_policy_exists(resources: Resources): - offenders = resources.namespaces +class check_default_deny_policy_exists(Rule): + _type = "cluster_wide" + pillar = "security" + section = "network_security" + message = "Namespaces that does not have default network deny policies." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/network/#create-a-default-deny-policy" - for policy in resources.network_policies: - offenders.remove(policy.metadata.namespace) + def check(self, resources: Resources): + offenders = resources.namespaces - if offenders: - print_namespace_table( - offenders, - "[red]Namespaces that does not have default network deny policies", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/network/#create-a-default-deny-policy]Click to see the guide[/link]", - ) + for policy in resources.network_policies: + offenders.remove(policy.metadata.namespace) + + self.result = Result(status=True, resource_type="Namespace") - return offenders + if offenders: + self.result = Result( + status=False, resource_type="Service", resources=offenders + ) diff --git a/hardeneks/cluster_wide/security/pod_security.py b/hardeneks/cluster_wide/security/pod_security.py index 1f8c478..0c1f0f3 100644 --- a/hardeneks/cluster_wide/security/pod_security.py +++ b/hardeneks/cluster_wide/security/pod_security.py @@ -1,28 +1,34 @@ import kubernetes from ...resources import Resources +from hardeneks.rules import Rule, Result -from ...report import ( - print_namespace_table, -) +class ensure_namespace_psa_exist(Rule): + _type = "cluster_wide" + pillar = "security" + section = "pod_security" + message = "Namespaces should have psa modes." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#pod-security-standards-pss-and-pod-security-admission-psa" -def ensure_namespace_psa_exist(resources: Resources): - offenders = [] - namespaces = kubernetes.client.CoreV1Api().list_namespace().items - for namespace in namespaces: - if namespace.metadata.name not in resources.namespaces: - labels = namespace.metadata.labels.keys() - if "pod-security.kubernetes.io/enforce" not in labels: - offenders.append(namespace.metadata.name) - elif "pod-security.kubernetes.io/warn" not in labels: - offenders.append(namespace.metadata.name) + def check(self, resources: Resources): + offenders = [] - if offenders: - print_namespace_table( - offenders, - "[red]Namespaces should have psa modes.", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#pod-security-standards-pss-and-pod-security-admission-psa]Click to see the guide[/link]", - ) + namespaces = kubernetes.client.CoreV1Api().list_namespace().items + psa_labels = [ + "pod-security.kubernetes.io/enforce", + "pod-security.kubernetes.io/warn", + "pod-security.kubernetes.io/audit", + ] - return offenders + for namespace in namespaces: + if namespace.metadata.name in resources.namespaces: + labels = namespace.metadata.labels.keys() + if not any(i in labels for i in psa_labels): + offenders.append(namespace.metadata.name) + + self.result = Result(status=True, resource_type="Namespace") + if offenders: + self.result = Result( + status=False, resource_type="Namespace", resources=offenders + ) diff --git a/hardeneks/harden.py b/hardeneks/harden.py index 8fb4af3..68f9c90 100644 --- a/hardeneks/harden.py +++ b/hardeneks/harden.py @@ -3,15 +3,20 @@ def harden(resources, config, _type): config = config[_type] + results = [] for pillar in config.keys(): for section in config[pillar]: for rule in config[pillar][section]: module = import_module(f"hardeneks.{_type}.{pillar}.{section}") try: - func = getattr(module, rule) + cls = getattr(module, rule) except AttributeError as exc: print(f"[bold][red]{exc}") try: - func(resources) + rule = cls() + rule.check(resources) + results.append(rule) except Exception as exc: print(f"[bold][red]{exc}") + + return results diff --git a/hardeneks/namespace_based/reliability/applications.py b/hardeneks/namespace_based/reliability/applications.py index a6aeeb5..672070e 100644 --- a/hardeneks/namespace_based/reliability/applications.py +++ b/hardeneks/namespace_based/reliability/applications.py @@ -1,117 +1,188 @@ from ...resources import NamespacedResources +from hardeneks.rules import Rule, Result -from ...report import ( - print_pod_table, - print_service_table, - print_deployment_table, -) +class avoid_running_singleton_pods(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Avoid running pods without deployments." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#avoid-running-singleton-pods" + def check(self, namespaced_resources: NamespacedResources): + offenders = [] + for pod in namespaced_resources.pods: + owner = pod.metadata.owner_references + if not owner: + offenders.append(pod) -def avoid_running_singleton_pods(namespaced_resources: NamespacedResources): - offenders = [] - for pod in namespaced_resources.pods: - owner = pod.metadata.owner_references - if not owner: - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Avoid running pods without deployments.", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#avoid-running-singleton-pods]Click to see the guide[/link]", + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace ) - return offenders - + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) -def run_multiple_replicas(namespaced_resources: NamespacedResources): - offenders = [] - for deployment in namespaced_resources.deployments: - if deployment.spec.replicas < 2: - offenders.append(deployment) - - if offenders: - print_deployment_table( - offenders, - "[red]Avoid running single replica deployments", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#run-multiple-replicas]Click to see the guide[/link]", - ) - return offenders +class run_multiple_replicas(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Avoid running single replica deployments." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#run-multiple-replicas" + def check(self, namespaced_resources: NamespacedResources): -def schedule_replicas_across_nodes(namespaced_resources: NamespacedResources): - offenders = [] + offenders = [] - for deployment in namespaced_resources.deployments: - spread = deployment.spec.template.spec.topology_spread_constraints - if not spread: - offenders.append(deployment) - else: - topology_keys = set([i.topology_key for i in spread]) - if not set(["topology.kubernetes.io/zone"]).issubset( - topology_keys - ): + for deployment in namespaced_resources.deployments: + if deployment.spec.replicas < 2: offenders.append(deployment) - if offenders: - print_service_table( - offenders, - "[red]Spread replicas across AZs and Nodes", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#schedule-replicas-across-nodes]Click to see the guide[/link]", + self.result = Result( + status=True, + resource_type="Deployment", + namespace=namespaced_resources.namespace ) - return offenders + if offenders: + self.result = Result( + status=False, + resource_type="Deployment", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) -def check_horizontal_pod_autoscaling_exists( - namespaced_resources: NamespacedResources, -): - offenders = [] +class schedule_replicas_across_nodes(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Spread replicas across AZs and Nodes." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#schedule-replicas-across-nodes" - hpas = [i.spec.scale_target_ref.name for i in namespaced_resources.hpas] + def check(self, namespaced_resources: NamespacedResources): - for deployment in namespaced_resources.deployments: - if deployment.metadata.name not in hpas: - offenders.append(deployment) + offenders = [] - if offenders: - print_service_table( - offenders, - "[red]Deploy horizontal pod autoscaler for deployments", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#horizontal-pod-autoscaler-hpa]Click to see the guide[/link]", + for deployment in namespaced_resources.deployments: + spread = deployment.spec.template.spec.topology_spread_constraints + if not spread: + offenders.append(deployment) + else: + topology_keys = set([i.topology_key for i in spread]) + if not set(["topology.kubernetes.io/zone"]).issubset( + topology_keys + ): + offenders.append(deployment) + + self.result = Result( + status=True, + resource_type="Deployment", + namespace=namespaced_resources.namespace ) - return offenders + if offenders: + self.result = Result( + status=False, + resource_type="Deployment", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) -def check_readiness_probes(namespaced_resources: NamespacedResources): - offenders = [] +class check_horizontal_pod_autoscaling_exists(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Deploy horizontal pod autoscaler for deployments." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#horizontal-pod-autoscaler-hpa" - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if not container.readiness_probe: - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Define readiness probes for pods.", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#use-readiness-probe-to-detect-partial-unavailability]Click to see the guide[/link]", - ) - return offenders + def check(self, namespaced_resources: NamespacedResources): + offenders = [] -def check_liveness_probes(namespaced_resources: NamespacedResources): - offenders = [] + hpas = [ + i.spec.scale_target_ref.name for i in namespaced_resources.hpas + ] - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if not container.liveness_probe: - offenders.append(pod) + for deployment in namespaced_resources.deployments: + if deployment.metadata.name not in hpas: + offenders.append(deployment) - if offenders: - print_pod_table( - offenders, - "[red]Define liveness probes for pods.", - "[link=https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#use-liveness-probe-to-remove-unhealthy-pods]Click to see the guide[/link]", + self.result = Result( + status=True, + resource_type="Deployment", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Deployment", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class check_readiness_probes(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Define readiness probes for pods." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#use-readiness-probe-to-detect-partial-unavailability" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if not container.readiness_probe: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, ) - return offenders + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class check_liveness_probes(Rule): + _type = "namespace_based" + pillar = "reliability" + section = "applications" + message = "Define liveness probes for pods." + url = "https://aws.github.io/aws-eks-best-practices/reliability/docs/application/#use-liveness-probe-to-remove-unhealthy-pods" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if not container.liveness_probe: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) diff --git a/hardeneks/namespace_based/security/encryption_secrets.py b/hardeneks/namespace_based/security/encryption_secrets.py index 9ca1743..296c7b4 100644 --- a/hardeneks/namespace_based/security/encryption_secrets.py +++ b/hardeneks/namespace_based/security/encryption_secrets.py @@ -1,28 +1,37 @@ from ...resources import NamespacedResources -from ...report import ( - print_pod_table, -) +from hardeneks.rules import Rule, Result -def disallow_secrets_from_env_vars(resources: NamespacedResources): - offenders = [] +class disallow_secrets_from_env_vars(Rule): + _type = "namespace_based" + pillar = "security" + section = "encryption_secrets" + message = "Disallow secrets from env vars." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/data/#use-volume-mounts-instead-of-environment-variables" - for pod in resources.pods: - for container in pod.spec.containers: - if container.env: - for env in container.env: - if env.value_from and env.value_from.secret_key_ref: - offenders.append(pod) - if container.env_from: - for env_from in container.env_from: - if env_from.secret_ref: - offenders.append(pod) + def check(self, namespaced_resources: NamespacedResources): + offenders = [] - if offenders: - print_pod_table( - offenders, - "[red]Disallow secrets from env vars", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/data/#use-volume-mounts-instead-of-environment-variables]Click to see the guide[/link]", - ) + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if container.env: + for env in container.env: + if env.value_from and env.value_from.secret_key_ref: + offenders.append(pod) + if container.env_from: + for env_from in container.env_from: + if env_from.secret_ref: + offenders.append(pod) - return offenders + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) diff --git a/hardeneks/namespace_based/security/iam.py b/hardeneks/namespace_based/security/iam.py index 93ef75b..9b459b0 100644 --- a/hardeneks/namespace_based/security/iam.py +++ b/hardeneks/namespace_based/security/iam.py @@ -1,180 +1,264 @@ from collections import Counter from ...resources import NamespacedResources -from ...report import ( - print_role_table, - print_pod_table, - print_workload_table, -) - - -def restrict_wildcard_for_roles(resources: NamespacedResources): - offenders = [] - - for role in resources.roles: - for rule in role.rules: - if "*" in rule.verbs: - offenders.append(role) - if "*" in rule.resources: - offenders.append(role) - - if offenders: - print_role_table( - offenders, - "[red]Roles should not have '*' in Verbs or Resources", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#employ-least-privileged-access-when-creating-rolebindings-and-clusterrolebindings]Click to see the guide[/link]", - "Role", +from hardeneks.rules import Rule, Result + + +class restrict_wildcard_for_roles(Rule): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Roles should not have '*' in Verbs or Resources." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#employ-least-privileged-access-when-creating-rolebindings-and-clusterrolebindings" + + def check(self, namespaced_resources: NamespacedResources): + offenders = [] + + for role in namespaced_resources.roles: + for rule in role.rules: + if "*" in rule.verbs: + offenders.append(role) + if "*" in rule.resources: + offenders.append(role) + + self.result = Result( + status=True, + resource_type="Role", + namespace=namespaced_resources.namespace, ) - return offenders - - -def disable_service_account_token_mounts(resources: NamespacedResources): - offenders = [] - - for pod in resources.pods: - if pod.spec.automount_service_account_token: - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Auto-mounting of Service Account tokens is not allowed", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#disable-auto-mounting-of-service-account-tokens]Click to see the guide[/link]", + if offenders: + self.result = Result( + status=False, + resource_type="Role", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class disable_service_account_token_mounts(Rule): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Auto-mounting of Service Account tokens is not allowed." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#disable-auto-mounting-of-service-account-tokens" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + if pod.spec.automount_service_account_token: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class disable_run_as_root_user(Rule): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Running as root is not allowed." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#run-the-application-as-a-non-root-user" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + security_context = pod.spec.security_context + containers = pod.spec.containers + + if ( + not security_context.run_as_group + and not security_context.run_as_user + ): + for con in containers: + security_context = con.security_context + try: + run_as_group = security_context.run_as_group + run_as_user = security_context.run_as_user + except AttributeError: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, ) - return offenders - - -def disable_run_as_root_user(resources: NamespacedResources): - offenders = [] - - for pod in resources.pods: - security_context = pod.spec.security_context - if ( - not security_context.run_as_group - and not security_context.run_as_user - ): - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Running as root is not allowed", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#run-the-application-as-a-non-root-user]Click to see the guide[/link]", + + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class disable_anonymous_access_for_roles(Rule): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Don't bind roles to anonymous or unauthenticated groups." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#review-and-revoke-unnecessary-anonymous-access" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for role_binding in namespaced_resources.role_bindings: + if role_binding.subjects: + for subject in role_binding.subjects: + if ( + subject.name == "system:unauthenticated" + or subject.name == "system:anonymous" + ): + offenders.append(role_binding) + + self.result = Result( + status=True, + resource_type="RoleBinding", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="RoleBinding", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class use_dedicated_service_accounts_for_each_deployment(Rule): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Don't share service accounts between Deployments." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + count = Counter( + [ + i.spec.template.spec.service_account_name + for i in namespaced_resources.deployments + ] ) - - return offenders - - -def disable_anonymous_access_for_roles(resources: NamespacedResources): - offenders = [] - - for role_binding in resources.role_bindings: - if role_binding.subjects: - for subject in role_binding.subjects: - if ( - subject.name == "system:unauthenticated" - or subject.name == "system:anonymous" - ): - offenders.append(role_binding) - - if offenders: - print_role_table( - offenders, - "[red]Don't bind roles to anonymous or unauthenticated groups", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#review-and-revoke-unnecessary-anonymous-access]Click to see the guide[/link]", - "RoleBinding", + repeated_service_accounts = { + x: count for x, count in count.items() if count > 1 + } + + for k, v in repeated_service_accounts.items(): + for deployment in namespaced_resources.deployments: + if k == deployment.spec.template.spec.service_account_name: + offenders.append(deployment) + + self.result = Result( + status=True, + resource_type="Deployment", + namespace=namespaced_resources.namespace, ) - return offenders + if offenders: + self.result = Result( + status=False, + resource_type="Deployment", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) -def use_dedicated_service_accounts_for_each_deployment( - resources: NamespacedResources, +class use_dedicated_service_accounts_for_each_stateful_set( + Rule, ): - offenders = [] - - count = Counter( - [ - i.spec.template.spec.service_account_name - for i in resources.deployments - ] - ) - repeated_service_accounts = { - x: count for x, count in count.items() if count > 1 - } - - for k, v in repeated_service_accounts.items(): - for deployment in resources.deployments: - if k == deployment.spec.template.spec.service_account_name: - offenders.append(deployment) - - if offenders: - print_workload_table( - offenders, - "[red]Don't share service accounts between Deployments", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application]Click to see the guide[/link]", - "Deployment", - ) + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Don't share service accounts between StatefulSets." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application" - return offenders + def check(self, namespaced_resources: NamespacedResources): + offenders = [] -def use_dedicated_service_accounts_for_each_stateful_set( - resources: NamespacedResources, -): - offenders = [] - - count = Counter( - [ - i.spec.template.spec.service_account_name - for i in resources.stateful_sets - ] - ) - repeated_service_accounts = { - x: count for x, count in count.items() if count > 1 - } - - for k, v in repeated_service_accounts.items(): - for deployment in resources.stateful_sets: - if k == deployment.spec.template.spec.service_account_name: - offenders.append(deployment) - - if offenders: - print_workload_table( - offenders, - "[red]Don't share service accounts between StatefulSets", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application]Click to see the guide[/link]", - "StatefulSet", + count = Counter( + [ + i.spec.template.spec.service_account_name + for i in namespaced_resources.stateful_sets + ] ) + repeated_service_accounts = { + x: count for x, count in count.items() if count > 1 + } + + for k, v in repeated_service_accounts.items(): + for deployment in namespaced_resources.stateful_sets: + if k == deployment.spec.template.spec.service_account_name: + offenders.append(deployment) + + self.result = Result( + status=True, + resource_type="StatefulSet", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="StatefulSet", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class use_dedicated_service_accounts_for_each_daemon_set( + Rule, +): + _type = "namespace_based" + pillar = "security" + section = "iam" + message = "Don't share service accounts between DaemonSets." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application" - return offenders + def check(self, namespaced_resources: NamespacedResources): + offenders = [] -def use_dedicated_service_accounts_for_each_daemon_set( - resources: NamespacedResources, -): - offenders = [] - - count = Counter( - [ - i.spec.template.spec.service_account_name - for i in resources.daemon_sets - ] - ) - repeated_service_accounts = { - x: count for x, count in count.items() if count > 1 - } - - for k, v in repeated_service_accounts.items(): - for deployment in resources.daemon_sets: - if k == deployment.spec.template.spec.service_account_name: - offenders.append(deployment) - - if offenders: - print_workload_table( - offenders, - "[red]Don't share service accounts between DaemonSets", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/iam/#use-dedicated-service-accounts-for-each-application]Click to see the guide[/link]", - "DaemonSet", + count = Counter( + [ + i.spec.template.spec.service_account_name + for i in namespaced_resources.daemon_sets + ] ) - - return offenders + repeated_service_accounts = { + x: count for x, count in count.items() if count > 1 + } + + for k, v in repeated_service_accounts.items(): + for deployment in namespaced_resources.daemon_sets: + if k == deployment.spec.template.spec.service_account_name: + offenders.append(deployment) + + self.result = Result( + status=True, + resource_type="DaemonSet", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="DaemonSet", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) diff --git a/hardeneks/namespace_based/security/network_security.py b/hardeneks/namespace_based/security/network_security.py index c22ff1b..fba609d 100644 --- a/hardeneks/namespace_based/security/network_security.py +++ b/hardeneks/namespace_based/security/network_security.py @@ -1,30 +1,38 @@ -from ...report import ( - print_service_table, -) +from hardeneks.rules import Rule, Result from hardeneks.resources import NamespacedResources -def use_encryption_with_aws_load_balancers( - namespaced_resources: NamespacedResources, -): - offenders = [] - for service in namespaced_resources.services: - annotations = service.metadata.annotations - if annotations: - ssl_cert = ( - "service.beta.kubernetes.io/aws-load-balancer-ssl-cert" - in annotations +class use_encryption_with_aws_load_balancers(Rule): + _type = "namespace_based" + pillar = "security" + section = "network_security" + message = "Make sure you specify an ssl cert." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/network/#use-encryption-with-aws-load-balancers" + + def check(self, namespaced_resources: NamespacedResources): + offenders = [] + for service in namespaced_resources.services: + annotations = service.metadata.annotations + if service.spec.type == 'LoadBalancer' and annotations: + ssl_cert = ( + "service.beta.kubernetes.io/aws-load-balancer-ssl-cert" + in annotations + ) + ssl_cert_port = annotations.get( + "service.beta.kubernetes.io/aws-load-balancer-ssl-ports" + ) + if not (ssl_cert and ssl_cert_port == "443"): + offenders.append(service) + + self.result = Result( + status=True, + resource_type="Service", + namespace=namespaced_resources.namespace, ) - ssl_cert_port = annotations.get( - "service.beta.kubernetes.io/aws-load-balancer-ssl-ports" + if offenders: + self.result = Result( + status=False, + resource_type="Service", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, ) - if not (ssl_cert and ssl_cert_port == "443"): - offenders.append(service) - - if offenders: - print_service_table( - offenders, - "[red]Make sure you specify an ssl cert", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/network/#use-encryption-with-aws-load-balancers]Click to see the guide[/link]", - ) - return offenders diff --git a/hardeneks/namespace_based/security/pod_security.py b/hardeneks/namespace_based/security/pod_security.py index 207da02..2165cbe 100644 --- a/hardeneks/namespace_based/security/pod_security.py +++ b/hardeneks/namespace_based/security/pod_security.py @@ -1,112 +1,165 @@ -from ...report import ( - print_pod_table, -) +from hardeneks.rules import Rule, Result from ...resources import NamespacedResources -def disallow_container_socket_mount(namespaced_resources: NamespacedResources): - offenders = [] - - sockets = [ - "/var/run/docker.sock", - "/var/run/containerd.sock", - "/var/run/crio.sock", - ] - - for pod in namespaced_resources.pods: - for volume in pod.spec.volumes: - if volume.host_path and volume.host_path.path in sockets: - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Container socket mounts are not allowed", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#never-run-docker-in-docker-or-mount-the-socket-in-the-container]Click to see the guide[/link]", - ) - - return offenders - - -def disallow_host_path_or_make_it_read_only( - namespaced_resources: NamespacedResources, -): - offenders = [] - - for pod in namespaced_resources.pods: - for volume in pod.spec.volumes: - if volume.host_path: - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Restrict the use of hostpath.", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#restrict-the-use-of-hostpath-or-if-hostpath-is-necessary-restrict-which-prefixes-can-be-used-and-configure-the-volume-as-read-only]Click to see the guide[/link]", - ) - - return offenders - - -def set_requests_limits_for_containers( - namespaced_resources: NamespacedResources, -): - offenders = [] - - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if not ( - container.resources.limits and container.resources.requests - ): - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Set requests and limits for each container.", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#set-requests-and-limits-for-each-container-to-avoid-resource-contention-and-dos-attacks]Click to see the guide[/link]", - ) - - return offenders - - -def disallow_privilege_escalation(namespaced_resources: NamespacedResources): - offenders = [] - - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if ( - container.security_context - and container.security_context.allow_privilege_escalation - ): - offenders.append(pod) - - if offenders: - print_pod_table( - offenders, - "[red]Set allowPrivilegeEscalation in the pod spec to false", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#do-not-allow-privileged-escalation]Click to see the guide[/link]", - ) - - return offenders - - -def check_read_only_root_file_system( - namespaced_resources: NamespacedResources, -): - offenders = [] - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if ( - container.security_context - and not container.security_context.read_only_root_filesystem - ): - offenders.append(pod) - if offenders: - print_pod_table( - offenders, - "[red]Configure your images with a read-only root file system", - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/pods/#configure-your-images-with-read-only-root-file-system]Click to see the guide[/link]", - ) - - return offenders +class disallow_container_socket_mount(Rule): + _type = "namespace_based" + pillar = "security" + section = "pod_security" + message = "Container socket mounts are not allowed." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#never-run-docker-in-docker-or-mount-the-socket-in-the-container" + + def check(self, namespaced_resources: NamespacedResources): + offenders = [] + + sockets = [ + "/var/run/docker.sock", + "/var/run/containerd.sock", + "/var/run/crio.sock", + ] + + for pod in namespaced_resources.pods: + for volume in pod.spec.volumes: + if volume.host_path and volume.host_path.path in sockets: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class disallow_host_path_or_make_it_read_only(Rule): + _type = "namespace_based" + pillar = "security" + section = "pod_security" + message = "Restrict the use of hostpath." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#restrict-the-use-of-hostpath-or-if-hostpath-is-necessary-restrict-which-prefixes-can-be-used-and-configure-the-volume-as-read-only" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + for volume in pod.spec.volumes: + if volume.host_path: + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class set_requests_limits_for_containers(Rule): + _type = "namespace_based" + pillar = "security" + section = "pod_security" + message = "Set requests and limits for each container." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#set-requests-and-limits-for-each-container-to-avoid-resource-contention-and-dos-attacks" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if not ( + container.resources.limits and container.resources.requests + ): + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class disallow_privilege_escalation(Rule): + _type = "namespace_based" + pillar = "security" + section = "pod_security" + message = "Set allowPrivilegeEscalation in the pod spec to false." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#do-not-allow-privileged-escalation" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if ( + container.security_context + and container.security_context.allow_privilege_escalation + ): + offenders.append(pod) + + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) + + +class check_read_only_root_file_system(Rule): + _type = "namespace_based" + pillar = "security" + section = "pod_security" + message = "Configure your images with a read-only root file system." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/pods/#configure-your-images-with-read-only-root-file-system" + + def check(self, namespaced_resources: NamespacedResources): + + offenders = [] + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if container.security_context is None: + offenders.append(pod) + if ( + container.security_context + and not container.security_context.read_only_root_filesystem + ): + offenders.append(pod) + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) diff --git a/hardeneks/namespace_based/security/runtime_security.py b/hardeneks/namespace_based/security/runtime_security.py index be9fd71..db60dbf 100644 --- a/hardeneks/namespace_based/security/runtime_security.py +++ b/hardeneks/namespace_based/security/runtime_security.py @@ -1,45 +1,54 @@ -from hardeneks import console from ...resources import NamespacedResources -from ...report import print_pod_table +from hardeneks.rules import Rule, Result -def disallow_linux_capabilities(namespaced_resources: NamespacedResources): - offenders = [] +class disallow_linux_capabilities(Rule): + _type = "namespace_based" + pillar = "security" + section = "runtime_security" + message = "Capabilities beyond the allowed list are disallowed." + url = "https://aws.github.io/aws-eks-best-practices/security/docs/runtime/#consider-adddropping-linux-capabilities-before-writing-seccomp-policies" - allowed_list = [ - "AUDIT_WRITE", - "CHOWN", - "DAC_OVERRIDE", - "FOWNER", - "FSETID", - "KILL", - "MKNOD", - "NET_BIND_SERVICE", - "SETFCAP", - "SETGID", - "SETPCAP", - "SETUID", - "SYS_CHROOT", - ] - for pod in namespaced_resources.pods: - for container in pod.spec.containers: - if ( - container.security_context - and container.security_context.capabilities - ): - capabilities = set(container.security_context.capabilities.add) - if not capabilities.issubset(set(allowed_list)): - offenders.append(pod) + def check(self, namespaced_resources: NamespacedResources): + offenders = [] - if offenders: - console.print() - console.print(allowed_list) - print_pod_table( - offenders, - """ - [red]Capabilities beyond the allowed list are disallowed. - """, - "[link=https://aws.github.io/aws-eks-best-practices/security/docs/runtime/#consider-adddropping-linux-capabilities-before-writing-seccomp-policies]Click to see the guide[/link]", - ) + allowed_list = [ + "AUDIT_WRITE", + "CHOWN", + "DAC_OVERRIDE", + "FOWNER", + "FSETID", + "KILL", + "MKNOD", + "NET_BIND_SERVICE", + "SETFCAP", + "SETGID", + "SETPCAP", + "SETUID", + "SYS_CHROOT", + ] + for pod in namespaced_resources.pods: + for container in pod.spec.containers: + if ( + container.security_context + and container.security_context.capabilities + and container.security_context.capabilities.add + ): + capabilities = set( + container.security_context.capabilities.add + ) + if not capabilities.issubset(set(allowed_list)): + offenders.append(pod) - return offenders + self.result = Result( + status=True, + resource_type="Pod", + namespace=namespaced_resources.namespace, + ) + if offenders: + self.result = Result( + status=False, + resource_type="Pod", + resources=[i.metadata.name for i in offenders], + namespace=namespaced_resources.namespace, + ) diff --git a/hardeneks/report.py b/hardeneks/report.py deleted file mode 100644 index 4ac483a..0000000 --- a/hardeneks/report.py +++ /dev/null @@ -1,192 +0,0 @@ -from rich.table import Table -from rich.panel import Panel - -from hardeneks import console - - -def print_role_table(roles, message, docs, type): - table = Table() - - table.add_column("Kind", style="cyan") - table.add_column("Namespace", style="magenta") - table.add_column("Name", style="green") - - for role in roles: - table.add_row(type, role.metadata.namespace, role.metadata.name) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_instance_metadata_table(instances, message, docs): - table = Table() - - table.add_column("InstanceId", style="cyan") - table.add_column("HttpPutResponseHopLimit", style="magenta") - - for instance in instances: - table.add_row( - instance["Instances"][0]["InstanceId"], - str( - instance["Instances"][0]["MetadataOptions"][ - "HttpPutResponseHopLimit" - ] - ), - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_instance_public_table(instances, message, docs): - table = Table() - - table.add_column("InstanceId", style="cyan") - table.add_column("PublicDnsName", style="magenta") - - for instance in instances: - table.add_row( - instance["Instances"][0]["InstanceId"], - str(instance["Instances"][0]["PublicDnsName"]), - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_node_table(nodes, message, docs): - table = Table() - - table.add_column("NodeName", style="cyan") - - for node in nodes: - table.add_row(node.metadata.name) - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_repository_table(repositories, attribute, message, docs): - table = Table() - table.add_column("Repository", style="cyan") - table.add_column(attribute, style="magenta") - for repository in repositories: - table.add_row( - repository["repositoryName"], - repository[attribute], - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_pod_table(pods, message, docs): - table = Table() - - table.add_column("Kind", style="cyan") - table.add_column("Namespace", style="magenta") - table.add_column("Name", style="green") - - for pod in pods: - table.add_row("Pod", pod.metadata.namespace, pod.metadata.name) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_workload_table(workloads, message, docs, kind): - table = Table() - - table.add_column("Kind", style="cyan") - table.add_column("Namespace", style="magenta") - table.add_column("Name", style="green") - - for workload in workloads: - table.add_row( - kind, workload.metadata.namespace, workload.metadata.name - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_namespace_table(namespaces, message, docs): - table = Table() - - table.add_column("Namespace", style="cyan") - - for namespace in namespaces: - table.add_row( - namespace, - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_service_table(services, message, docs): - table = Table() - - table.add_column("Kind", style="cyan") - table.add_column("Namespace", style="magenta") - table.add_column("Name", style="green") - - for workload in services: - table.add_row( - "Service", workload.metadata.namespace, workload.metadata.name - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_deployment_table(deployments, message, docs): - table = Table() - - table.add_column("Kind", style="cyan") - table.add_column("Namespace", style="magenta") - table.add_column("Name", style="green") - - for workload in deployments: - table.add_row( - "Deployment", workload.metadata.namespace, workload.metadata.name - ) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_storage_class_table(storage_classes, message, docs): - table = Table() - - table.add_column("StorageClass", style="cyan") - table.add_column("Encyrpted", style="magenta") - - for storage_class in storage_classes: - table.add_row(storage_class.metadata.name, "false") - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_persistent_volume_table(persistent_volumes, message, docs): - table = Table() - - table.add_column("PersistentVolume", style="cyan") - table.add_column("Encrypted", style="magenta") - - for persistent_volume in persistent_volumes: - table.add_row(persistent_volume.metadata.name, "false") - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() - - -def print_role_action_table(actions, message, docs): - table = Table() - table.add_column("Action", style="cyan") - - for action in actions: - table.add_row(action) - - console.print(Panel(table, title=message, subtitle=docs)) - console.print() diff --git a/hardeneks/resources.py b/hardeneks/resources.py index 08a64f4..3097aab 100644 --- a/hardeneks/resources.py +++ b/hardeneks/resources.py @@ -1,5 +1,6 @@ from kubernetes import client + class Resources: def __init__(self, region, context, cluster, namespaces): self.region = region @@ -67,4 +68,4 @@ def set_resources(self): client.AutoscalingV1Api() .list_namespaced_horizontal_pod_autoscaler(self.namespace) .items - ) \ No newline at end of file + ) diff --git a/hardeneks/rules.py b/hardeneks/rules.py new file mode 100644 index 0000000..796fd1e --- /dev/null +++ b/hardeneks/rules.py @@ -0,0 +1,49 @@ +from abc import ABC, abstractmethod + +from hardeneks import console + + +class Result(object): + def __init__( + self, status=True, resources=[""], resource_type=None, namespace=None + ): + self.status = status + self.resources = resources + self.resource_type = resource_type + self.namespace = namespace + + +class Rule(ABC): + + message = None + url = None + _type = None + pillar = None + section = None + console = console + + def __init__(self, result=Result()): + self.result = result + + if not (hasattr(self, "message") and self.message): + raise NotImplementedError( + "Class needs to have class variable message" + ) + if not (hasattr(self, "url") and self.url): + raise NotImplementedError("Class needs to have class variable url") + if not (hasattr(self, "_type") and self._type): + raise NotImplementedError( + "Class needs to have class variable _type" + ) + if not (hasattr(self, "pillar") and self.pillar): + raise NotImplementedError( + "Class needs to have class variable pillar" + ) + if not (hasattr(self, "section") and self.section): + raise NotImplementedError( + "Class needs to have class variable section" + ) + + @abstractmethod + def check(self): + pass diff --git a/poetry.lock b/poetry.lock index 467b0ab..55880e9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,131 +1,323 @@ -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "boto3" -version = "1.26.41" +version = "1.35.40" description = "The AWS SDK for Python" -category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" +files = [ + {file = "boto3-1.35.40-py3-none-any.whl", hash = "sha256:9352f6d61f15c789231a5d608613f03425059072ed862c32e1ed102b17206abf"}, + {file = "boto3-1.35.40.tar.gz", hash = "sha256:33c6a7aeab316f7e0b3ad8552afe95a4a10bfd58519d00741c4d4f3047da8382"}, +] [package.dependencies] -botocore = ">=1.29.41,<1.30.0" +botocore = ">=1.35.40,<1.36.0" jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.6.0,<0.7.0" +s3transfer = ">=0.10.0,<0.11.0" [package.extras] crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.29.41" +version = "1.35.40" description = "Low-level, data-driven core of boto 3." -category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" +files = [ + {file = "botocore-1.35.40-py3-none-any.whl", hash = "sha256:072cc47f29cb1de4fa77ce6632e4f0480af29b70816973ff415fbaa3f50bd1db"}, + {file = "botocore-1.35.40.tar.gz", hash = "sha256:547e0a983856c7d7aeaa30fca2a283873c57c07366cd806d2d639856341b3c31"}, +] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" +urllib3 = [ + {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, + {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, +] [package.extras] -crt = ["awscrt (==0.15.3)"] +crt = ["awscrt (==0.22.0)"] [[package]] name = "cachetools" -version = "5.2.0" +version = "5.5.0" description = "Extensible memoizing collections and decorators" -category = "main" optional = false -python-versions = "~=3.7" +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, +] [[package]] name = "certifi" -version = "2022.12.7" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] [[package]] name = "cfgv" -version = "3.3.1" +version = "3.4.0" description = "Validate configuration and produce human readable error messages." -category = "main" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] [[package]] name = "chardet" -version = "5.1.0" +version = "5.2.0" description = "Universal encoding detector for Python 3" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode-backport = ["unicodedata2"] +python-versions = ">=3.7.0" +files = [ + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "commonmark" version = "0.9.1" description = "Python parser for the CommonMark Markdown spec" -category = "main" optional = false python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] [package.extras] test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "7.0.1" +version = "7.6.1" description = "Code coverage measurement for Python" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, +] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} @@ -135,114 +327,128 @@ toml = ["tomli"] [[package]] name = "distlib" -version = "0.3.6" +version = "0.3.9" description = "Distribution utilities" -category = "main" optional = false python-versions = "*" +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] [[package]] name = "exceptiongroup" -version = "1.1.0" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] [package.extras] test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.9.0" +version = "3.16.1" description = "A platform independent file lock." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, +] [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "google-auth" -version = "2.15.0" +version = "2.35.0" description = "Google Authentication Library" -category = "main" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +python-versions = ">=3.7" +files = [ + {file = "google_auth-2.35.0-py2.py3-none-any.whl", hash = "sha256:25df55f327ef021de8be50bad0dfd4a916ad0de96da86cd05661c9297723ad3f"}, + {file = "google_auth-2.35.0.tar.gz", hash = "sha256:f4c64ed4e01e8e8b646ef34c018f8bf3338df0c8e37d8b3bba40e7f574a3278a"}, +] [package.dependencies] cachetools = ">=2.0.0,<6.0" pyasn1-modules = ">=0.2.1" -rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} -six = ">=1.9.0" +rsa = ">=3.1.4,<5" [package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "requests (>=2.20.0,<3.0.0dev)"] -enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography", "pyopenssl"] pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] [[package]] name = "identify" -version = "2.5.11" +version = "2.6.1" description = "File identification library for Python" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, + {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, +] [package.extras] license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false -python-versions = ">=3.5" - -[[package]] -name = "importlib-metadata" -version = "6.0.0" -description = "Read metadata from Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = "*" +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] [[package]] name = "kubernetes" version = "25.3.0" description = "Kubernetes python client" -category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "kubernetes-25.3.0-py2.py3-none-any.whl", hash = "sha256:eb42333dad0bb5caf4e66460c6a4a1a36f0f057a040f35018f6c05a699baed86"}, + {file = "kubernetes-25.3.0.tar.gz", hash = "sha256:213befbb4e5aed95f94950c7eed0c2322fc5a2f8f40932e58d28fdd42d90836c"}, +] [package.dependencies] certifi = ">=14.05.14" @@ -254,29 +460,32 @@ requests-oauthlib = "*" setuptools = ">=21.0.0" six = ">=1.9.0" urllib3 = ">=1.24.2" -websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.0 || >=0.43.0" +websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" [package.extras] adal = ["adal (>=1.0.2)"] [[package]] name = "nodeenv" -version = "1.7.0" +version = "1.9.1" description = "Node.js virtual environment builder" -category = "main" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" - -[package.dependencies] -setuptools = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] [[package]] name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] [package.extras] rsa = ["cryptography (>=3.0.0)"] @@ -285,37 +494,41 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "packaging" -version = "22.0" +version = "24.1" description = "Core utilities for Python packages" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, +] [[package]] name = "platformdirs" -version = "2.6.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, +] [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" -category = "main" optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] [package.extras] dev = ["pre-commit", "tox"] @@ -325,92 +538,110 @@ testing = ["pytest", "pytest-benchmark"] name = "pre-commit" version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" [[package]] name = "pyasn1" -version = "0.4.8" -description = "ASN.1 types and codecs" -category = "main" +version = "0.6.1" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = false -python-versions = "*" +python-versions = ">=3.8" +files = [ + {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, + {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, +] [[package]] name = "pyasn1-modules" -version = "0.2.8" -description = "A collection of ASN.1-based protocols modules." -category = "main" +version = "0.4.1" +description = "A collection of ASN.1-based protocols modules" optional = false -python-versions = "*" +python-versions = ">=3.8" +files = [ + {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, + {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, +] [package.dependencies] -pyasn1 = ">=0.4.6,<0.5.0" +pyasn1 = ">=0.4.6,<0.7.0" [[package]] name = "pygments" -version = "2.14.0" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyproject-api" -version = "1.2.1" +version = "1.8.0" description = "API to interact with the python pyproject.toml based projects" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, + {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, +] [package.dependencies] -packaging = ">=21.3" +packaging = ">=24.1" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2022.9.29)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -testing = ["covdefaults (>=2.2.2)", "importlib-metadata (>=5.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "virtualenv (>=20.17)", "wheel (>=0.38.4)"] +docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] [[package]] name = "pytest" -version = "7.2.0" +version = "7.4.4" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.0.0" +version = "4.1.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] [package.dependencies] coverage = {version = ">=5.2.1", extras = ["toml"]} @@ -421,47 +652,110 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-datadir" -version = "1.4.1" +version = "1.5.0" description = "pytest plugin for test data directories and files" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +files = [ + {file = "pytest-datadir-1.5.0.tar.gz", hash = "sha256:1617ed92f9afda0c877e4eac91904b5f779d24ba8f5e438752e3ae39d8d2ee3f"}, + {file = "pytest_datadir-1.5.0-py3-none-any.whl", hash = "sha256:34adf361bcc7b37961bbc1dfa8d25a4829e778bab461703c38a5c50ca9c36dc8"}, +] [package.dependencies] pytest = ">=5.0" [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] [package.dependencies] six = ">=1.5" [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] [[package]] name = "requests" -version = "2.28.1" +version = "2.32.3" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -469,11 +763,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-oauthlib" -version = "1.3.1" +version = "2.0.0" description = "OAuthlib authentication support for Requests." -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.4" +files = [ + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, +] [package.dependencies] oauthlib = ">=3.0.0" @@ -486,9 +783,12 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "rich" version = "12.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "main" optional = false python-versions = ">=3.6.3,<4.0.0" +files = [ + {file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"}, + {file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"}, +] [package.dependencies] commonmark = ">=0.9.0,<0.10.0" @@ -502,97 +802,124 @@ jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" -category = "main" optional = false python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] [package.dependencies] pyasn1 = ">=0.1.3" [[package]] name = "s3transfer" -version = "0.6.0" +version = "0.10.3" description = "An Amazon S3 Transfer Manager" -category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" +files = [ + {file = "s3transfer-0.10.3-py3-none-any.whl", hash = "sha256:263ed587a5803c6c708d3ce44dc4dfedaab4c1a32e8329bab818933d79ddcf5d"}, + {file = "s3transfer-0.10.3.tar.gz", hash = "sha256:4f50ed74ab84d474ce614475e0b8d5047ff080810aac5d01ea25231cfc944b0c"}, +] [package.dependencies] -botocore = ">=1.12.36,<2.0a.0" +botocore = ">=1.33.2,<2.0a.0" [package.extras] -crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] +crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] [[package]] name = "setuptools" -version = "65.6.3" +version = "75.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, + {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, +] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "shellingham" -version = "1.5.0" +version = "1.5.4" description = "Tool to Detect Surrounding Shell" -category = "main" optional = false -python-versions = ">=3.4" +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "tomli" -version = "2.0.1" +version = "2.0.2" description = "A lil' TOML parser" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, + {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, +] [[package]] name = "tox" -version = "4.1.2" +version = "4.21.2" description = "tox is a generic virtualenv management and test command line tool" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "tox-4.21.2-py3-none-any.whl", hash = "sha256:13d996adcd792e7c82994b0e116d85efd84f0c6d185254d83d156f73f86b2038"}, + {file = "tox-4.21.2.tar.gz", hash = "sha256:49381ff102296753e378fa5ff30e42a35e695f149b4dbf8a2c49d15fdb5797b2"}, +] [package.dependencies] -cachetools = ">=5.2" -chardet = ">=5.1" +cachetools = ">=5.5" +chardet = ">=5.2" colorama = ">=0.4.6" -filelock = ">=3.9" -importlib-metadata = {version = ">=5.2", markers = "python_version < \"3.8\""} -packaging = ">=22" -platformdirs = ">=2.6.2" -pluggy = ">=1" -pyproject-api = ">=1.2.1" +filelock = ">=3.16.1" +packaging = ">=24.1" +platformdirs = ">=4.3.6" +pluggy = ">=1.5" +pyproject-api = ">=1.8" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} -virtualenv = ">=20.17.1" +typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} +virtualenv = ">=20.26.6" [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=6)", "sphinx-argparse-cli (>=1.10)", "sphinx-autodoc-typehints (>=1.19.5)", "sphinx-copybutton (>=0.5.1)", "sphinx-inline-tabs (>=2022.1.2b11)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] -testing = ["build[virtualenv] (>=0.9)", "covdefaults (>=2.2.2)", "devpi-process (>=0.3)", "diff-cover (>=7.3)", "distlib (>=0.3.6)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.12)", "psutil (>=5.9.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-xdist (>=3.1)", "re-assert (>=1.1)", "time-machine (>=2.8.2)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-argparse-cli (>=1.18.2)", "sphinx-autodoc-typehints (>=2.4.4)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=24.8)"] +testing = ["build[virtualenv] (>=1.2.2)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1.0.2)", "diff-cover (>=9.2)", "distlib (>=0.3.8)", "flaky (>=3.8.1)", "hatch-vcs (>=0.4)", "hatchling (>=1.25)", "psutil (>=6)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-xdist (>=3.6.1)", "re-assert (>=1.1)", "setuptools (>=75.1)", "time-machine (>=2.15)", "wheel (>=0.44)"] [[package]] name = "tox-gh-actions" -version = "3.0.0" +version = "3.2.0" description = "Seamless integration of tox into GitHub Actions" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "tox-gh-actions-3.2.0.tar.gz", hash = "sha256:ac6fa3b8da51bc90dd77985fd55f09e746c6558c55910c0a93d643045a2b0ccc"}, + {file = "tox_gh_actions-3.2.0-py2.py3-none-any.whl", hash = "sha256:821b66a4751a788fa3e9617bd796d696507b08c6e1d929ee4faefba06b73b694"}, +] [package.dependencies] tox = ">=4,<5" @@ -604,9 +931,12 @@ testing = ["black", "devpi-process", "flake8 (>=6,<7)", "mypy", "pytest (>=7,<8) name = "typer" version = "0.6.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "typer-0.6.1-py3-none-any.whl", hash = "sha256:54b19e5df18654070a82f8c2aa1da456a4ac16a2a83e6dcd9f170e291c56338e"}, + {file = "typer-0.6.1.tar.gz", hash = "sha256:2d5720a5e63f73eaf31edaa15f6ab87f35f0690f8ca233017d7d23d743a91d73"}, +] [package.dependencies] click = ">=7.1.1,<9.0.0" @@ -622,374 +952,85 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6. [[package]] name = "typing-extensions" -version = "4.4.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] [[package]] name = "urllib3" -version = "1.26.13" +version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, + {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, +] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "urllib3" +version = "2.2.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "virtualenv" -version = "20.17.1" +version = "20.26.6" description = "Virtual Python Environment builder" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"}, + {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"}, +] [package.dependencies] -distlib = ">=0.3.6,<1" -filelock = ">=3.4.1,<4" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.8\""} -platformdirs = ">=2.4,<3" +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" [package.extras] -docs = ["proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-argparse (>=0.3.2)", "sphinx-rtd-theme (>=1)", "towncrier (>=22.8)"] -testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] [[package]] name = "websocket-client" -version = "1.4.2" +version = "1.8.0" description = "WebSocket client for Python with low level API options" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] [package.extras] -docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] -[[package]] -name = "zipp" -version = "3.11.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - [metadata] -lock-version = "1.1" -python-versions = "^3.7" -content-hash = "30efa68d51f3d8b3958d49d1d246e26bdda2af2bbdf426c841ea1885e29fb612" - -[metadata.files] -attrs = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] -boto3 = [ - {file = "boto3-1.26.41-py3-none-any.whl", hash = "sha256:05a5ce3af2d7419e39d93498c7f56fd5c2cc17870c92c4abc75659553b0b16de"}, - {file = "boto3-1.26.41.tar.gz", hash = "sha256:8cbea352f28ec6b241f348356bcb8f331fc433bec3ad76ebf6194227f1a7f613"}, -] -botocore = [ - {file = "botocore-1.29.41-py3-none-any.whl", hash = "sha256:b670b7f8958a2908167081efb6ea39794bf61d618be729984629a63d85cf8bfe"}, - {file = "botocore-1.29.41.tar.gz", hash = "sha256:78761227d986d393956b6d08fdadcfe142748828e0e9db33f2f4c42a482dcd35"}, -] -cachetools = [ - {file = "cachetools-5.2.0-py3-none-any.whl", hash = "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db"}, - {file = "cachetools-5.2.0.tar.gz", hash = "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757"}, -] -certifi = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] -cfgv = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, -] -chardet = [ - {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, - {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, -] -click = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -commonmark = [ - {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, - {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, -] -coverage = [ - {file = "coverage-7.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b3695c4f4750bca943b3e1f74ad4be8d29e4aeab927d50772c41359107bd5d5c"}, - {file = "coverage-7.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa6a5a224b7f4cfb226f4fc55a57e8537fcc096f42219128c2c74c0e7d0953e1"}, - {file = "coverage-7.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74f70cd92669394eaf8d7756d1b195c8032cf7bbbdfce3bc489d4e15b3b8cf73"}, - {file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b66bb21a23680dee0be66557dc6b02a3152ddb55edf9f6723fa4a93368f7158d"}, - {file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87717959d4d0ee9db08a0f1d80d21eb585aafe30f9b0a54ecf779a69cb015f6"}, - {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:854f22fa361d1ff914c7efa347398374cc7d567bdafa48ac3aa22334650dfba2"}, - {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e414dc32ee5c3f36544ea466b6f52f28a7af788653744b8570d0bf12ff34bc0"}, - {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6c5ad996c6fa4d8ed669cfa1e8551348729d008a2caf81489ab9ea67cfbc7498"}, - {file = "coverage-7.0.1-cp310-cp310-win32.whl", hash = "sha256:691571f31ace1837838b7e421d3a09a8c00b4aac32efacb4fc9bd0a5c647d25a"}, - {file = "coverage-7.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:89caf4425fe88889e2973a8e9a3f6f5f9bbe5dd411d7d521e86428c08a873a4a"}, - {file = "coverage-7.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:63d56165a7c76265468d7e0c5548215a5ba515fc2cba5232d17df97bffa10f6c"}, - {file = "coverage-7.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f943a3b2bc520102dd3e0bb465e1286e12c9a54f58accd71b9e65324d9c7c01"}, - {file = "coverage-7.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:830525361249dc4cd013652b0efad645a385707a5ae49350c894b67d23fbb07c"}, - {file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd1b9c5adc066db699ccf7fa839189a649afcdd9e02cb5dc9d24e67e7922737d"}, - {file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00c14720b8b3b6c23b487e70bd406abafc976ddc50490f645166f111c419c39"}, - {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d55d840e1b8c0002fce66443e124e8581f30f9ead2e54fbf6709fb593181f2c"}, - {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66b18c3cf8bbab0cce0d7b9e4262dc830e93588986865a8c78ab2ae324b3ed56"}, - {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12a5aa77783d49e05439fbe6e6b427484f8a0f9f456b46a51d8aac022cfd024d"}, - {file = "coverage-7.0.1-cp311-cp311-win32.whl", hash = "sha256:b77015d1cb8fe941be1222a5a8b4e3fbca88180cfa7e2d4a4e58aeabadef0ab7"}, - {file = "coverage-7.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb992c47cb1e5bd6a01e97182400bcc2ba2077080a17fcd7be23aaa6e572e390"}, - {file = "coverage-7.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e78e9dcbf4f3853d3ae18a8f9272111242531535ec9e1009fa8ec4a2b74557dc"}, - {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60bef2e2416f15fdc05772bf87db06c6a6f9870d1db08fdd019fbec98ae24a9"}, - {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9823e4789ab70f3ec88724bba1a203f2856331986cd893dedbe3e23a6cfc1e4e"}, - {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9158f8fb06747ac17bd237930c4372336edc85b6e13bdc778e60f9d685c3ca37"}, - {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:486ee81fa694b4b796fc5617e376326a088f7b9729c74d9defa211813f3861e4"}, - {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1285648428a6101b5f41a18991c84f1c3959cee359e51b8375c5882fc364a13f"}, - {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2c44fcfb3781b41409d0f060a4ed748537557de9362a8a9282182fafb7a76ab4"}, - {file = "coverage-7.0.1-cp37-cp37m-win32.whl", hash = "sha256:d6814854c02cbcd9c873c0f3286a02e3ac1250625cca822ca6bc1018c5b19f1c"}, - {file = "coverage-7.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f66460f17c9319ea4f91c165d46840314f0a7c004720b20be58594d162a441d8"}, - {file = "coverage-7.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b373c9345c584bb4b5f5b8840df7f4ab48c4cbb7934b58d52c57020d911b856"}, - {file = "coverage-7.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d3022c3007d3267a880b5adcf18c2a9bf1fc64469b394a804886b401959b8742"}, - {file = "coverage-7.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92651580bd46519067e36493acb394ea0607b55b45bd81dd4e26379ed1871f55"}, - {file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cfc595d2af13856505631be072835c59f1acf30028d1c860b435c5fc9c15b69"}, - {file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b4b3a4d9915b2be879aff6299c0a6129f3d08a775d5a061f503cf79571f73e4"}, - {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b6f22bb64cc39bcb883e5910f99a27b200fdc14cdd79df8696fa96b0005c9444"}, - {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72d1507f152abacea81f65fee38e4ef3ac3c02ff8bc16f21d935fd3a8a4ad910"}, - {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a79137fc99815fff6a852c233628e735ec15903cfd16da0f229d9c4d45926ab"}, - {file = "coverage-7.0.1-cp38-cp38-win32.whl", hash = "sha256:b3763e7fcade2ff6c8e62340af9277f54336920489ceb6a8cd6cc96da52fcc62"}, - {file = "coverage-7.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:09f6b5a8415b6b3e136d5fec62b552972187265cb705097bf030eb9d4ffb9b60"}, - {file = "coverage-7.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:978258fec36c154b5e250d356c59af7d4c3ba02bef4b99cda90b6029441d797d"}, - {file = "coverage-7.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ec666533f0f70a0993f88b8273057b96c07b9d26457b41863ccd021a043b9a"}, - {file = "coverage-7.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfded268092a84605f1cc19e5c737f9ce630a8900a3589e9289622db161967e9"}, - {file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bcfb1d8ac94af886b54e18a88b393f6a73d5959bb31e46644a02453c36e475"}, - {file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b4a923cc7566bbc7ae2dfd0ba5a039b61d19c740f1373791f2ebd11caea59"}, - {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aec2d1515d9d39ff270059fd3afbb3b44e6ec5758af73caf18991807138c7118"}, - {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c20cfebcc149a4c212f6491a5f9ff56f41829cd4f607b5be71bb2d530ef243b1"}, - {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fd556ff16a57a070ce4f31c635953cc44e25244f91a0378c6e9bdfd40fdb249f"}, - {file = "coverage-7.0.1-cp39-cp39-win32.whl", hash = "sha256:b9ea158775c7c2d3e54530a92da79496fb3fb577c876eec761c23e028f1e216c"}, - {file = "coverage-7.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:d1991f1dd95eba69d2cd7708ff6c2bbd2426160ffc73c2b81f617a053ebcb1a8"}, - {file = "coverage-7.0.1-pp37.pp38.pp39-none-any.whl", hash = "sha256:3dd4ee135e08037f458425b8842d24a95a0961831a33f89685ff86b77d378f89"}, - {file = "coverage-7.0.1.tar.gz", hash = "sha256:a4a574a19eeb67575a5328a5760bbbb737faa685616586a9f9da4281f940109c"}, -] -distlib = [ - {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, - {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, -] -exceptiongroup = [ - {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, - {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, -] -filelock = [ - {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"}, - {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"}, -] -google-auth = [ - {file = "google-auth-2.15.0.tar.gz", hash = "sha256:72f12a6cfc968d754d7bdab369c5c5c16032106e52d32c6dfd8484e4c01a6d1f"}, - {file = "google_auth-2.15.0-py2.py3-none-any.whl", hash = "sha256:6897b93556d8d807ad70701bb89f000183aea366ca7ed94680828b37437a4994"}, -] -identify = [ - {file = "identify-2.5.11-py2.py3-none-any.whl", hash = "sha256:e7db36b772b188099616aaf2accbee122949d1c6a1bac4f38196720d6f9f06db"}, - {file = "identify-2.5.11.tar.gz", hash = "sha256:14b7076b29c99b1b0b8b08e96d448c7b877a9b07683cd8cfda2ea06af85ffa1c"}, -] -idna = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] -importlib-metadata = [ - {file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, - {file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -jmespath = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] -kubernetes = [ - {file = "kubernetes-25.3.0-py2.py3-none-any.whl", hash = "sha256:eb42333dad0bb5caf4e66460c6a4a1a36f0f057a040f35018f6c05a699baed86"}, - {file = "kubernetes-25.3.0.tar.gz", hash = "sha256:213befbb4e5aed95f94950c7eed0c2322fc5a2f8f40932e58d28fdd42d90836c"}, -] -nodeenv = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, -] -oauthlib = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, -] -packaging = [ - {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, - {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, -] -platformdirs = [ - {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, - {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pre-commit = [ - {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, - {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, -] -pyasn1 = [ - {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, - {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, -] -pyasn1-modules = [ - {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, - {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, -] -pygments = [ - {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, - {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, -] -pyproject-api = [ - {file = "pyproject_api-1.2.1-py3-none-any.whl", hash = "sha256:155d5623453173b7b4e9379a3146ccef2d52335234eb2d03d6ba730e7dad179c"}, - {file = "pyproject_api-1.2.1.tar.gz", hash = "sha256:093c047d192ceadcab7afd6b501276bf2ce44adf41cb9c313234518cddd20818"}, -] -pytest = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, -] -pytest-cov = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, -] -pytest-datadir = [ - {file = "pytest-datadir-1.4.1.tar.gz", hash = "sha256:9f7a3c4def6ac4cac3cc8181139ab53bd2667231052bd40cb07081748d4420f0"}, - {file = "pytest_datadir-1.4.1-py3-none-any.whl", hash = "sha256:095f441782b1b907587eca7227fdbae94be43f1c96b4b2cbcc6801a4645be1af"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] -requests-oauthlib = [ - {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, - {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, -] -rich = [ - {file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"}, - {file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"}, -] -rsa = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] -s3transfer = [ - {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, - {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, -] -setuptools = [ - {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, - {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, -] -shellingham = [ - {file = "shellingham-1.5.0-py2.py3-none-any.whl", hash = "sha256:a8f02ba61b69baaa13facdba62908ca8690a94b8119b69f5ec5873ea85f7391b"}, - {file = "shellingham-1.5.0.tar.gz", hash = "sha256:72fb7f5c63103ca2cb91b23dee0c71fe8ad6fbfd46418ef17dbe40db51592dad"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -tox = [ - {file = "tox-4.1.2-py3-none-any.whl", hash = "sha256:aa1c07530f07265d025d534715f5e8d522606db71568cf6acbf7eadc30a8d0ed"}, - {file = "tox-4.1.2.tar.gz", hash = "sha256:3910e7ddf260de9004738a416f2efdbca21ad7f35d279f8a323117256696535f"}, -] -tox-gh-actions = [ - {file = "tox-gh-actions-3.0.0.tar.gz", hash = "sha256:1a20286a1102c720a5979f56a060f6d618306dbb660a6724a31d89f397421e5c"}, - {file = "tox_gh_actions-3.0.0-py2.py3-none-any.whl", hash = "sha256:059ebfdba76864819f3a4629c3404be094dae9dc8e7922c7c7a9999b9551f82a"}, -] -typer = [ - {file = "typer-0.6.1-py3-none-any.whl", hash = "sha256:54b19e5df18654070a82f8c2aa1da456a4ac16a2a83e6dcd9f170e291c56338e"}, - {file = "typer-0.6.1.tar.gz", hash = "sha256:2d5720a5e63f73eaf31edaa15f6ab87f35f0690f8ca233017d7d23d743a91d73"}, -] -typing-extensions = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, -] -urllib3 = [ - {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, - {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, -] -virtualenv = [ - {file = "virtualenv-20.17.1-py3-none-any.whl", hash = "sha256:ce3b1684d6e1a20a3e5ed36795a97dfc6af29bc3970ca8dab93e11ac6094b3c4"}, - {file = "virtualenv-20.17.1.tar.gz", hash = "sha256:f8b927684efc6f1cc206c9db297a570ab9ad0e51c16fa9e45487d36d1905c058"}, -] -websocket-client = [ - {file = "websocket-client-1.4.2.tar.gz", hash = "sha256:d6e8f90ca8e2dd4e8027c4561adeb9456b54044312dba655e7cae652ceb9ae59"}, - {file = "websocket_client-1.4.2-py3-none-any.whl", hash = "sha256:d6b06432f184438d99ac1f456eaf22fe1ade524c3dd16e661142dc54e9cba574"}, -] -zipp = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, -] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "0c7d1658f1f52fa9e0c884fe5f69be3a02fb87a89c561fa441492773012b153f" diff --git a/pyproject.toml b/pyproject.toml index 351996e..2c78608 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [tool.poetry] name = "hardeneks" -version = "0.8.0" +version = "0.10.4" description = "" authors = ["Doruk Ozturk "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.7" +python = "^3.8" typer = {extras = ["all"], version = "^0.6.1"} kubernetes = "^25.3.0" boto3 = "^1.26.2" @@ -41,7 +41,7 @@ exclude = ''' [tool.commitizen] name = "cz_conventional_commits" -version = "0.8.0" +version = "0.11.0" version_files = [ "pyproject.toml:[tool.commitizen]\nversion", "pyproject.toml:[tool.poetry]\nname = \"commitizen\"\nversion", diff --git a/tests/data/check_aws_node_daemonset_service_account/service_accounts_api_response.json b/tests/data/check_aws_node_daemonset_service_account/service_accounts_api_response.json new file mode 100644 index 0000000..18f8c32 --- /dev/null +++ b/tests/data/check_aws_node_daemonset_service_account/service_accounts_api_response.json @@ -0,0 +1,20 @@ +{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/instance\":\"aws-vpc-cni\",\"app.kubernetes.io/name\":\"aws-node\",\"app.kubernetes.io/version\":\"v1.11.4\",\"k8s-app\":\"aws-node\"},\"name\":\"aws-node\",\"namespace\":\"kube-system\"}}\n" + }, + "creationTimestamp": "2023-04-14T12:17:01Z", + "labels": { + "app.kubernetes.io/instance": "aws-vpc-cni", + "app.kubernetes.io/name": "aws-node", + "app.kubernetes.io/version": "v1.11.4", + "k8s-app": "aws-node" + }, + "name": "aws-node", + "namespace": "kube-system", + "resourceVersion": "3691", + "uid": "122cc1c7-ba3b-4133-9b7a-b847398cf11b" + } +} diff --git a/tests/data/disable_run_as_root_user_container/bad.yaml b/tests/data/disable_run_as_root_user_container/bad.yaml new file mode 100644 index 0000000..b30da75 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/bad.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + namespace: test-namespace + name: bad +spec: + containers: + - name: sec-ctx-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + - name: sec-ctx-demo-2 + image: busybox + command: [ "sh", "-c", "sleep 1h" ] \ No newline at end of file diff --git a/tests/data/disable_run_as_root_user_container/cluster/cluster_role_bindings_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/cluster_role_bindings_api_response.json new file mode 100644 index 0000000..3df131e --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/cluster_role_bindings_api_response.json @@ -0,0 +1,1903 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/instance\":\"aws-vpc-cni\",\"app.kubernetes.io/name\":\"aws-node\",\"app.kubernetes.io/version\":\"v1.12.6\",\"k8s-app\":\"aws-node\"},\"name\":\"aws-node\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"aws-node\"},\"subjects\":[{\"kind\":\"ServiceAccount\",\"name\":\"aws-node\",\"namespace\":\"kube-system\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "app.kubernetes.io/instance": "aws-vpc-cni", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "aws-node", + "app.kubernetes.io/version": "v1.14.1", + "helm.sh/chart": "aws-vpc-cni-1.14.1", + "k8s-app": "aws-node" + }, + "name": "aws-node", + "resourceVersion": "1527", + "uid": "c67e4d8c-ba47-4ff8-b8a3-82668e457b73" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "aws-node" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "aws-node", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "cluster-admin", + "resourceVersion": "132", + "uid": "ade24be7-3f07-4a8e-a0bd-cce12158ee75" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "cluster-admin" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:masters" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:addon-cluster-admin\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"cluster-admin\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:addon-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:addon-cluster-admin", + "resourceVersion": "289", + "uid": "c01c3d8e-95d6-4254-8d6f-00cc2151c117" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "cluster-admin" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:addon-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:addon-manager\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:addon-manager\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:addon-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:addon-manager", + "resourceVersion": "288", + "uid": "99583044-c4b4-4118-ad06-c139ff30f268" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:addon-manager" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:addon-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:az-poller\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:az-poller\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:az-poller\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:az-poller", + "resourceVersion": "211", + "uid": "fa641bb8-a8e1-480d-a07b-b8fe41c23513" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:az-poller" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:az-poller" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:certificate-controller\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"system:controller:certificate-controller\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:certificate-controller\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:certificate-controller", + "resourceVersion": "216", + "uid": "d595dd4e-cb58-4ae1-a4f2-f679c90954e6" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:certificate-controller" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:certificate-controller" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:certificate-controller-approver\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:certificate-controller-approver\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:certificate-controller\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:certificate-controller-approver", + "resourceVersion": "218", + "uid": "f2cb295d-2129-4c7a-a42a-d73675519896" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:certificate-controller-approver" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:certificate-controller" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:certificate-controller-signer\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:certificate-controller-signer\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:certificate-controller\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:certificate-controller-signer", + "resourceVersion": "219", + "uid": "8eb09f13-efe5-4b8e-bc1e-9a1f6770dfd0" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:certificate-controller-signer" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:certificate-controller" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloud-controller-manager\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:cloud-controller-manager\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:cloud-controller-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cloud-controller-manager", + "resourceVersion": "200", + "uid": "ee7f371e-221c-4b66-85d5-4152b8ee604d" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:cloud-controller-manager" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:cloud-controller-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloud-provider-extraction-migration\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:cloud-provider-extraction-migration\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"system:kube-controller-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:14Z", + "name": "eks:cloud-provider-extraction-migration", + "resourceVersion": "238", + "uid": "44532715-3c3b-4d88-8af0-e8bd6babcede" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:cloud-provider-extraction-migration" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "system:kube-controller-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloudwatch-agent-role-binding\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:cloudwatch-agent-role\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:cloudwatch-agent\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cloudwatch-agent-role-binding", + "resourceVersion": "203", + "uid": "66f7e24a-c0e9-4ffd-bce3-50cba1fc91ef" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:cloudwatch-agent-role" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:cloudwatch-agent" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cluster-event-watcher\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:cluster-event-watcher\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:cluster-event-watcher\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cluster-event-watcher", + "resourceVersion": "223", + "uid": "24270f17-48cd-46d1-97c7-370fd4a36e4a" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:cluster-event-watcher" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:cluster-event-watcher" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:fargate-manager\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:fargate-manager\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:fargate-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:fargate-manager", + "resourceVersion": "308", + "uid": "7808186a-8888-4354-b708-140f1b4fae0e" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:fargate-manager" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:fargate-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:fargate-scheduler\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:fargate-scheduler\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:fargate-scheduler\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:fargate-scheduler", + "resourceVersion": "225", + "uid": "61afe555-fef8-47e0-8993-064896056430" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:fargate-scheduler" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:fargate-scheduler" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:k8s-metrics\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:k8s-metrics\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:k8s-metrics\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:k8s-metrics", + "resourceVersion": "229", + "uid": "8abcbd11-bada-4d9b-afa9-1ea74d1def40" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:k8s-metrics" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:k8s-metrics" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"kube-proxy\",\"k8s-app\":\"kube-proxy\"},\"name\":\"eks:kube-proxy\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"system:node-proxier\"},\"subjects\":[{\"kind\":\"ServiceAccount\",\"name\":\"kube-proxy\",\"namespace\":\"kube-system\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "eks:kube-proxy", + "resourceVersion": "315", + "uid": "0119e2d5-8ff9-4410-be3a-e4b6d2919d55" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:node-proxier" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "kube-proxy", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:kube-proxy-fargate\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"system:node-proxier\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Group\",\"name\":\"system:node-proxier\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:kube-proxy-fargate", + "resourceVersion": "307", + "uid": "6a97caef-2c6e-4601-806c-987d4e353bb6" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:node-proxier" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:node-proxier" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"kube-proxy\",\"k8s-app\":\"kube-proxy\"},\"name\":\"eks:kube-proxy-windows\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"system:node-proxier\"},\"subjects\":[{\"kind\":\"Group\",\"name\":\"eks:kube-proxy-windows\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "eks:kube-proxy-windows", + "resourceVersion": "304", + "uid": "95f6184f-4c15-403f-87ad-14aca75814c5" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:node-proxier" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "eks:kube-proxy-windows" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/component\":\"rbac\",\"app.kubernetes.io/created-by\":\"amazon-network-policy-controller-k8s\",\"app.kubernetes.io/instance\":\"manager-rolebinding\",\"app.kubernetes.io/name\":\"amazon-network-policy-controller-k8s\",\"app.kubernetes.io/part-of\":\"amazon-network-policy-controller-k8s\"},\"name\":\"eks:network-policy-controller\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:network-policy-controller\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:network-policy-controller\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:25Z", + "labels": { + "app.kubernetes.io/component": "rbac", + "app.kubernetes.io/created-by": "amazon-network-policy-controller-k8s", + "app.kubernetes.io/instance": "manager-rolebinding", + "app.kubernetes.io/name": "amazon-network-policy-controller-k8s", + "app.kubernetes.io/part-of": "amazon-network-policy-controller-k8s" + }, + "name": "eks:network-policy-controller", + "resourceVersion": "393", + "uid": "a84d5ecb-4781-4d41-8586-7f88da2147f1" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:network-policy-controller" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:network-policy-controller" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"node\"},\"name\":\"eks:node-bootstrapper\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:node-bootstrapper\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Group\",\"name\":\"system:bootstrappers\"},{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Group\",\"name\":\"system:nodes\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "node" + }, + "name": "eks:node-bootstrapper", + "resourceVersion": "317", + "uid": "473ef22e-f1b6-4f51-a98c-ecac79da4981" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:node-bootstrapper" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:bootstrappers" + }, + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:nodes" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:node-manager\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:node-manager\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:node-manager\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:node-manager", + "resourceVersion": "285", + "uid": "9f508a66-6092-4e0c-bcd7-f8a3e9eb68c8" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:node-manager" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:node-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:nodewatcher\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:nodewatcher\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:nodewatcher\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:nodewatcher", + "resourceVersion": "231", + "uid": "26c4902d-d4e1-40fb-ae00-1be4eb5085f0" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:nodewatcher" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:nodewatcher" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:pod-identity-mutating-webhook\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:pod-identity-mutating-webhook\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:pod-identity-mutating-webhook\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:pod-identity-mutating-webhook", + "resourceVersion": "233", + "uid": "6122cd4d-ccd0-4874-9e6f-2b2a995d4466" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:pod-identity-mutating-webhook" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:pod-identity-mutating-webhook" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:service-operations\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:service-operations\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Group\",\"name\":\"eks:service-operations\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:service-operations", + "resourceVersion": "235", + "uid": "9b27d071-cd09-48e8-a0e2-37312c5355d2" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:service-operations" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "eks:service-operations" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"eks:tagging-controller\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"eks:tagging-controller\"},\"subjects\":[{\"kind\":\"ServiceAccount\",\"name\":\"tagging-controller\",\"namespace\":\"kube-system\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:14Z", + "name": "eks:tagging-controller", + "resourceVersion": "241", + "uid": "908061f7-09b5-44bf-942e-bf91acf0f5e7" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "eks:tagging-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "tagging-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:basic-user", + "resourceVersion": "135", + "uid": "367166fd-fa1e-4759-b439-7715b3ec3efa" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:basic-user" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:authenticated" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:attachdetach-controller", + "resourceVersion": "144", + "uid": "fa5a6f04-9e0d-443b-bdc0-334a478494af" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:attachdetach-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "attachdetach-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:certificate-controller", + "resourceVersion": "170", + "uid": "ea2e0008-1efe-4920-a316-0d22902daf76" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:certificate-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "certificate-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:clusterrole-aggregation-controller", + "resourceVersion": "145", + "uid": "f100e439-4c2f-4c5a-a6f9-dd27b3c917ec" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:clusterrole-aggregation-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "clusterrole-aggregation-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:cronjob-controller", + "resourceVersion": "146", + "uid": "b8c23011-7ba1-4061-8841-327fc82066e2" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:cronjob-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "cronjob-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:daemon-set-controller", + "resourceVersion": "147", + "uid": "a0d300a6-2d4f-4707-8828-040d856e4d04" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:daemon-set-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "daemon-set-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:deployment-controller", + "resourceVersion": "148", + "uid": "7ded11f3-9dbd-4f8e-8e2d-dde8e6c51c4e" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:deployment-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "deployment-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:disruption-controller", + "resourceVersion": "149", + "uid": "6db672e1-0bb5-45d8-9b51-64055de7ff42" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:disruption-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "disruption-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpoint-controller", + "resourceVersion": "150", + "uid": "7114484d-850c-414b-ac31-c74c19aac3b0" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:endpoint-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "endpoint-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpointslice-controller", + "resourceVersion": "151", + "uid": "eb0ad073-bf79-49ed-af2e-63317c0c34fc" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:endpointslice-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "endpointslice-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpointslicemirroring-controller", + "resourceVersion": "152", + "uid": "7dd99b41-918b-46f3-9fe3-34e4a5feca24" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:endpointslicemirroring-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "endpointslicemirroring-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ephemeral-volume-controller", + "resourceVersion": "154", + "uid": "c99db44a-9dfe-477e-9ef4-307bb23778d6" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:ephemeral-volume-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "ephemeral-volume-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:expand-controller", + "resourceVersion": "153", + "uid": "73ca9414-f97e-4969-9a18-1ce533a26fe9" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:expand-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "expand-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:generic-garbage-collector", + "resourceVersion": "155", + "uid": "90a9af91-4f46-499c-9cd2-09fd4df66329" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:generic-garbage-collector" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "generic-garbage-collector", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:horizontal-pod-autoscaler", + "resourceVersion": "156", + "uid": "26440b32-a0a1-45ab-b4e1-2ccd51835d3a" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:horizontal-pod-autoscaler" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "horizontal-pod-autoscaler", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:job-controller", + "resourceVersion": "157", + "uid": "bc2df578-f891-47e7-9f50-61dd82e4f203" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:job-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "job-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:namespace-controller", + "resourceVersion": "158", + "uid": "06ef1db8-6e65-47fc-ac14-c553b962e34c" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:namespace-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "namespace-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:node-controller", + "resourceVersion": "159", + "uid": "cfebad81-421b-439d-b2a3-6842862cd905" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:node-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "node-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:persistent-volume-binder", + "resourceVersion": "160", + "uid": "994fb5eb-3f5a-4066-9bb7-095ce312caaa" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:persistent-volume-binder" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "persistent-volume-binder", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pod-garbage-collector", + "resourceVersion": "161", + "uid": "d2cc1d71-b015-4207-bd39-500c2b6a34f4" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:pod-garbage-collector" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "pod-garbage-collector", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pv-protection-controller", + "resourceVersion": "172", + "uid": "e15d96e5-b2a8-4de3-9687-332347c132b4" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:pv-protection-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "pv-protection-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pvc-protection-controller", + "resourceVersion": "171", + "uid": "a3665f9b-c2bc-48e0-83d5-b8a6ffa8c229" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:pvc-protection-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "pvc-protection-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:replicaset-controller", + "resourceVersion": "162", + "uid": "f0654c9f-cc3c-4ee9-ae9a-9d71fc464b4f" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:replicaset-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "replicaset-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:replication-controller", + "resourceVersion": "163", + "uid": "7ea6dfa5-7d2b-43ae-b74a-f28b3adc9dc1" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:replication-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "replication-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:resourcequota-controller", + "resourceVersion": "164", + "uid": "16d76295-00c3-4b98-be87-2bf2d6bd98d0" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:resourcequota-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "resourcequota-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:root-ca-cert-publisher", + "resourceVersion": "174", + "uid": "6f6996cf-a44b-4a09-aa9d-a5ad11617080" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:root-ca-cert-publisher" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "root-ca-cert-publisher", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:route-controller", + "resourceVersion": "165", + "uid": "533d00cd-5e90-4138-8169-e0a21abb5797" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:route-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "route-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:service-account-controller", + "resourceVersion": "166", + "uid": "bdbbd6e1-6081-4ad5-8968-c716c9721169" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:service-account-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "service-account-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:service-controller", + "resourceVersion": "167", + "uid": "4c54806b-739c-4fb3-b16e-f6a48d644952" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:service-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "service-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:statefulset-controller", + "resourceVersion": "168", + "uid": "5e4f0e4b-ee65-48f1-8992-baf1ba663797" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:statefulset-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "statefulset-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ttl-after-finished-controller", + "resourceVersion": "173", + "uid": "68fe60de-ffa4-4952-b112-aec41fd5ff3f" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:ttl-after-finished-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "ttl-after-finished-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ttl-controller", + "resourceVersion": "169", + "uid": "1da2bceb-8ac9-4a58-9dcc-4694a19990d7" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:controller:ttl-controller" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "ttl-controller", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{\"rbac.authorization.kubernetes.io/autoupdate\":\"true\"},\"labels\":{\"eks.amazonaws.com/component\":\"coredns\",\"k8s-app\":\"kube-dns\",\"kubernetes.io/bootstrapping\":\"rbac-defaults\"},\"name\":\"system:coredns\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"system:coredns\"},\"subjects\":[{\"kind\":\"ServiceAccount\",\"name\":\"coredns\",\"namespace\":\"kube-system\"}]}\n", + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns", + "resourceVersion": "295", + "uid": "f2825cdb-d205-497d-acec-2b9ed6aeff5e" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:coredns" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "coredns", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:discovery", + "resourceVersion": "134", + "uid": "5f860329-ada7-4d00-a2d1-e56dba04cc0f" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:discovery" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:authenticated" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-controller-manager", + "resourceVersion": "138", + "uid": "e09689bd-970e-4922-a697-1c08641153a6" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:kube-controller-manager" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "system:kube-controller-manager" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-dns", + "resourceVersion": "139", + "uid": "cfc5fa6a-4926-4666-b26c-b9da61dc2796" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:kube-dns" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "kube-dns", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-scheduler", + "resourceVersion": "140", + "uid": "ac7a4462-2ec9-47f3-9c94-f1bc1dbd7bc6" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:kube-scheduler" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "system:kube-scheduler" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:monitoring", + "resourceVersion": "133", + "uid": "563ae462-a3d9-46c1-a5cc-3115e3d2b7e5" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:monitoring" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:monitoring" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node", + "resourceVersion": "142", + "uid": "41d72f64-7581-4712-89ee-d56c2362f500" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:node" + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node-proxier", + "resourceVersion": "137", + "uid": "b7f184f2-8d04-4b8e-8ce6-35ab777bf49a" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:node-proxier" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "system:kube-proxy" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:public-info-viewer", + "resourceVersion": "136", + "uid": "04049dc3-5b67-4aa7-b369-67a5a3ba684e" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:public-info-viewer" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:authenticated" + }, + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:unauthenticated" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:service-account-issuer-discovery", + "resourceVersion": "143", + "uid": "e08c329e-e10a-486e-b2fd-93dabc0c1f8b" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:service-account-issuer-discovery" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:serviceaccounts" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:volume-scheduler", + "resourceVersion": "141", + "uid": "64ef65bc-1d8c-4a46-9ff0-db27848295b8" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:volume-scheduler" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "system:kube-scheduler" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRoleBinding\",\"metadata\":{\"annotations\":{},\"name\":\"vpc-resource-controller-rolebinding\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"ClusterRole\",\"name\":\"vpc-resource-controller-role\"},\"subjects\":[{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"User\",\"name\":\"eks:vpc-resource-controller\"},{\"kind\":\"ServiceAccount\",\"name\":\"eks-vpc-resource-controller\",\"namespace\":\"kube-system\"}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:24Z", + "name": "vpc-resource-controller-rolebinding", + "resourceVersion": "379", + "uid": "9f2eb6e6-bca2-4f58-880a-0a6680cf5a24" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "vpc-resource-controller-role" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "User", + "name": "eks:vpc-resource-controller" + }, + { + "kind": "ServiceAccount", + "name": "eks-vpc-resource-controller", + "namespace": "kube-system" + } + ] + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/cluster_roles_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/cluster_roles_api_response.json new file mode 100644 index 0000000..9f46869 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/cluster_roles_api_response.json @@ -0,0 +1,7693 @@ +{ + "apiVersion": "v1", + "items": [ + { + "aggregationRule": { + "clusterRoleSelectors": [ + { + "matchLabels": { + "rbac.authorization.k8s.io/aggregate-to-admin": "true" + } + } + ] + }, + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "admin", + "resourceVersion": "342", + "uid": "857fb82b-a29a-41e5-b16b-394bbd2d5ee3" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy", + "secrets", + "services/proxy" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "impersonate" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "events", + "persistentvolumeclaims", + "replicationcontrollers", + "replicationcontrollers/scale", + "secrets", + "serviceaccounts", + "services", + "services/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "replicasets", + "replicasets/scale", + "statefulsets", + "statefulsets/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "jobs" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "ingresses", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicationcontrollers/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "networkpolicies" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "endpoints", + "persistentvolumeclaims", + "persistentvolumeclaims/status", + "pods", + "replicationcontrollers", + "replicationcontrollers/scale", + "serviceaccounts", + "services", + "services/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "bindings", + "events", + "limitranges", + "namespaces/status", + "pods/log", + "pods/status", + "replicationcontrollers/status", + "resourcequotas", + "resourcequotas/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions", + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "replicasets", + "replicasets/scale", + "replicasets/status", + "statefulsets", + "statefulsets/scale", + "statefulsets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers", + "horizontalpodautoscalers/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "cronjobs/status", + "jobs", + "jobs/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "ingresses", + "ingresses/status", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicasets/status", + "replicationcontrollers/scale" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets", + "poddisruptionbudgets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "ingresses/status", + "networkpolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "localsubjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resources": [ + "rolebindings", + "roles" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/instance\":\"aws-vpc-cni\",\"app.kubernetes.io/name\":\"aws-node\",\"app.kubernetes.io/version\":\"v1.12.6\",\"k8s-app\":\"aws-node\"},\"name\":\"aws-node\"},\"rules\":[{\"apiGroups\":[\"crd.k8s.amazonaws.com\"],\"resources\":[\"eniconfigs\"],\"verbs\":[\"list\",\"watch\",\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"namespaces\"],\"verbs\":[\"list\",\"watch\",\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"list\",\"watch\",\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"list\",\"watch\",\"get\",\"update\"]},{\"apiGroups\":[\"extensions\"],\"resources\":[\"*\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"\",\"events.k8s.io\"],\"resources\":[\"events\"],\"verbs\":[\"create\",\"patch\",\"list\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "app.kubernetes.io/instance": "aws-vpc-cni", + "app.kubernetes.io/managed-by": "Helm", + "app.kubernetes.io/name": "aws-node", + "app.kubernetes.io/version": "v1.14.1", + "helm.sh/chart": "aws-vpc-cni-1.14.1", + "k8s-app": "aws-node" + }, + "name": "aws-node", + "resourceVersion": "1523", + "uid": "a6b45658-fac6-452a-b5f0-e8a7d55d416e" + }, + "rules": [ + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "eniconfigs" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "list", + "watch", + "get", + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "list" + ] + }, + { + "apiGroups": [ + "networking.k8s.aws" + ], + "resources": [ + "policyendpoints" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.aws" + ], + "resources": [ + "policyendpoints/status" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "cluster-admin", + "resourceVersion": "70", + "uid": "3848ba9d-babf-40f9-8b20-4a9b9970627c" + }, + "rules": [ + { + "apiGroups": [ + "*" + ], + "resources": [ + "*" + ], + "verbs": [ + "*" + ] + }, + { + "nonResourceURLs": [ + "*" + ], + "verbs": [ + "*" + ] + } + ] + }, + { + "aggregationRule": { + "clusterRoleSelectors": [ + { + "matchLabels": { + "rbac.authorization.k8s.io/aggregate-to-edit": "true" + } + } + ] + }, + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults", + "rbac.authorization.k8s.io/aggregate-to-admin": "true" + }, + "name": "edit", + "resourceVersion": "340", + "uid": "684d79c4-adb6-4761-99fb-afca46bfd3ba" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy", + "secrets", + "services/proxy" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "impersonate" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "events", + "persistentvolumeclaims", + "replicationcontrollers", + "replicationcontrollers/scale", + "secrets", + "serviceaccounts", + "services", + "services/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "replicasets", + "replicasets/scale", + "statefulsets", + "statefulsets/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "jobs" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "ingresses", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicationcontrollers/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "networkpolicies" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "endpoints", + "persistentvolumeclaims", + "persistentvolumeclaims/status", + "pods", + "replicationcontrollers", + "replicationcontrollers/scale", + "serviceaccounts", + "services", + "services/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "bindings", + "events", + "limitranges", + "namespaces/status", + "pods/log", + "pods/status", + "replicationcontrollers/status", + "resourcequotas", + "resourcequotas/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions", + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "replicasets", + "replicasets/scale", + "replicasets/status", + "statefulsets", + "statefulsets/scale", + "statefulsets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers", + "horizontalpodautoscalers/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "cronjobs/status", + "jobs", + "jobs/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "ingresses", + "ingresses/status", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicasets/status", + "replicationcontrollers/scale" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets", + "poddisruptionbudgets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "ingresses/status", + "networkpolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:addon-manager\"},\"rules\":[{\"apiGroups\":[\"crd.k8s.amazonaws.com\"],\"resources\":[\"eniconfigs\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"namespaces\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"list\",\"update\",\"watch\"]},{\"apiGroups\":[\"extensions\"],\"resources\":[\"*\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"rbac.authorization.k8s.io\"],\"resourceNames\":[\"aws-node\",\"system:coredns\",\"eks:kube-proxy\",\"ebs-csi-provisioner-binding\",\"ebs-csi-node-binding\",\"ebs-csi-attacher-binding\",\"ebs-csi-snapshotter-binding\",\"ebs-csi-resizer-binding\",\"ebs-csi-node-getter-binding\"],\"resources\":[\"clusterrolebindings\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"rbac.authorization.k8s.io\"],\"resourceNames\":[\"aws-node\",\"system:coredns\",\"ebs-external-attacher-role\",\"ebs-csi-node-role\",\"ebs-external-provisioner-role\",\"ebs-external-snapshotter-role\",\"ebs-external-resizer-role\"],\"resources\":[\"clusterroles\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"apiextensions.k8s.io\"],\"resourceNames\":[\"eniconfigs.crd.k8s.amazonaws.com\"],\"resources\":[\"customresourcedefinitions\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"endpoints\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"events\"],\"verbs\":[\"list\",\"watch\",\"create\",\"patch\",\"update\"]},{\"apiGroups\":[\"\"],\"resources\":[\"services\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"list\"]},{\"apiGroups\":[\"discovery.k8s.io\"],\"resources\":[\"endpointslices\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"events.k8s.io\"],\"resources\":[\"events\"],\"verbs\":[\"list\",\"watch\",\"create\",\"patch\",\"update\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"replicasets\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resourceNames\":[\"ebs.csi.aws.com\"],\"resources\":[\"csidrivers\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"persistentvolumes\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"watch\",\"update\",\"patch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"persistentvolumeclaims\"],\"verbs\":[\"get\",\"list\",\"watch\",\"update\"]},{\"apiGroups\":[\"\"],\"resources\":[\"persistentvolumeclaims/status\"],\"verbs\":[\"update\",\"patch\"]},{\"apiGroups\":[\"csi.storage.k8s.io\"],\"resources\":[\"csinodeinfos\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"storageclasses\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"volumeattachments\"],\"verbs\":[\"get\",\"list\",\"watch\",\"update\",\"patch\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"volumeattachments/status\"],\"verbs\":[\"patch\"]},{\"apiGroups\":[\"snapshot.storage.k8s.io\"],\"resources\":[\"volumesnapshots\"],\"verbs\":[\"get\",\"list\"]},{\"apiGroups\":[\"snapshot.storage.k8s.io\"],\"resources\":[\"volumesnapshotcontents\"],\"verbs\":[\"create\",\"get\",\"list\",\"watch\",\"update\",\"delete\",\"patch\"]},{\"apiGroups\":[\"snapshot.storage.k8s.io\"],\"resources\":[\"volumesnapshotclasses\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"snapshot.storage.k8s.io\"],\"resources\":[\"volumesnapshotcontents/status\"],\"verbs\":[\"update\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"csinodes\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resources\":[\"leases\"],\"verbs\":[\"get\",\"watch\",\"list\",\"delete\",\"update\",\"create\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"volumeattachments\"],\"verbs\":[\"get\",\"list\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:addon-manager", + "resourceVersion": "290", + "uid": "e6ed7122-962f-411a-9931-f2d202fe75d5" + }, + "rules": [ + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "eniconfigs" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "*" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resourceNames": [ + "aws-node", + "system:coredns", + "eks:kube-proxy", + "ebs-csi-provisioner-binding", + "ebs-csi-node-binding", + "ebs-csi-attacher-binding", + "ebs-csi-snapshotter-binding", + "ebs-csi-resizer-binding", + "ebs-csi-node-getter-binding" + ], + "resources": [ + "clusterrolebindings" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resourceNames": [ + "aws-node", + "system:coredns", + "ebs-external-attacher-role", + "ebs-csi-node-role", + "ebs-external-provisioner-role", + "ebs-external-snapshotter-role", + "ebs-external-resizer-role" + ], + "resources": [ + "clusterroles" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "apiextensions.k8s.io" + ], + "resourceNames": [ + "eniconfigs.crd.k8s.amazonaws.com" + ], + "resources": [ + "customresourcedefinitions" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "list", + "watch", + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "list", + "watch", + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resourceNames": [ + "ebs.csi.aws.com" + ], + "resources": [ + "csidrivers" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "watch", + "update", + "patch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "watch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims/status" + ], + "verbs": [ + "update", + "patch" + ] + }, + { + "apiGroups": [ + "csi.storage.k8s.io" + ], + "resources": [ + "csinodeinfos" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "storageclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "volumeattachments" + ], + "verbs": [ + "get", + "list", + "watch", + "update", + "patch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "volumeattachments/status" + ], + "verbs": [ + "patch" + ] + }, + { + "apiGroups": [ + "snapshot.storage.k8s.io" + ], + "resources": [ + "volumesnapshots" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "snapshot.storage.k8s.io" + ], + "resources": [ + "volumesnapshotcontents" + ], + "verbs": [ + "create", + "get", + "list", + "watch", + "update", + "delete", + "patch" + ] + }, + { + "apiGroups": [ + "snapshot.storage.k8s.io" + ], + "resources": [ + "volumesnapshotclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "snapshot.storage.k8s.io" + ], + "resources": [ + "volumesnapshotcontents/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csinodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "get", + "watch", + "list", + "delete", + "update", + "create" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "volumeattachments" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:az-poller\"},\"rules\":[{\"apiGroups\":[\"\"],\"resourceNames\":[\"kubernetes\"],\"resources\":[\"endpoints\"],\"verbs\":[\"get\",\"update\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:az-poller", + "resourceVersion": "204", + "uid": "bd76a012-27d9-4655-9460-009d5af3fffd" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resourceNames": [ + "kubernetes" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "get", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:certificate-controller-approver\"},\"rules\":[{\"apiGroups\":[\"certificates.k8s.io\"],\"resourceNames\":[\"kubernetes.io/kubelet-serving\"],\"resources\":[\"signers\"],\"verbs\":[\"approve\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:certificate-controller-approver", + "resourceVersion": "213", + "uid": "28798979-057e-47ab-b6db-f55a7042300b" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kubelet-serving" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:certificate-controller-signer\"},\"rules\":[{\"apiGroups\":[\"certificates.k8s.io\"],\"resourceNames\":[\"beta.eks.amazonaws.com/app-serving\"],\"resources\":[\"signers\"],\"verbs\":[\"sign\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:certificate-controller-signer", + "resourceVersion": "214", + "uid": "24a662c5-895a-42bf-9002-d44ccc3d28cc" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "beta.eks.amazonaws.com/app-serving" + ], + "resources": [ + "signers" + ], + "verbs": [ + "sign" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloud-controller-manager\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"events\"],\"verbs\":[\"create\",\"patch\",\"update\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes/status\"],\"verbs\":[\"patch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"services\"],\"verbs\":[\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"services/status\"],\"verbs\":[\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"serviceaccounts\"],\"verbs\":[\"create\",\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"persistentvolumes\"],\"verbs\":[\"get\",\"list\",\"update\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"endpoints\"],\"verbs\":[\"create\",\"get\",\"list\",\"watch\",\"update\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resources\":[\"leases\"],\"verbs\":[\"create\",\"get\",\"list\",\"watch\",\"update\"]},{\"apiGroups\":[\"\"],\"resources\":[\"serviceaccounts/token\"],\"verbs\":[\"create\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cloud-controller-manager", + "resourceVersion": "199", + "uid": "f32d7b0d-f23f-455c-8ab9-9cff8bc3856c" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "*" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services/status" + ], + "verbs": [ + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "create", + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "create", + "get", + "list", + "watch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "get", + "list", + "watch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloud-provider-extraction-migration\"},\"rules\":[{\"apiGroups\":[\"coordination.k8s.io\"],\"resources\":[\"leases\"],\"verbs\":[\"create\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resourceNames\":[\"cloud-provider-extraction-migration\"],\"resources\":[\"leases\"],\"verbs\":[\"create\",\"list\",\"get\",\"update\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:14Z", + "name": "eks:cloud-provider-extraction-migration", + "resourceVersion": "239", + "uid": "81dedbc0-8364-4ca2-8444-7c7d95e73b7e" + }, + "rules": [ + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resourceNames": [ + "cloud-provider-extraction-migration" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "list", + "get", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cloudwatch-agent-role\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"nodes\",\"endpoints\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"replicasets\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"batch\"],\"resources\":[\"jobs\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes/proxy\"],\"verbs\":[\"get\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes/stats\",\"events\"],\"verbs\":[\"create\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cloudwatch-agent-role", + "resourceVersion": "202", + "uid": "5c0b1d83-b606-4bb9-90e0-c2cf52e4b6b1" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "nodes", + "endpoints" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/proxy" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/stats", + "events" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:cluster-event-watcher\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"nodes\"],\"verbs\":[\"get\",\"list\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:cluster-event-watcher", + "resourceVersion": "222", + "uid": "7ba83267-5e93-41cd-8637-c46939485b1a" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:fargate-manager\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"get\",\"list\",\"watch\",\"delete\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods/eviction\"],\"verbs\":[\"create\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:fargate-manager", + "resourceVersion": "309", + "uid": "158ff52a-0d89-411e-862a-303668a542ae" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch", + "delete" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:fargate-scheduler\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"persistentvolumes\",\"persistentvolumeclaims\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods/status\"],\"verbs\":[\"get\",\"list\",\"watch\",\"update\"]},{\"apiGroups\":[\"\"],\"resources\":[\"configmaps\"],\"verbs\":[\"get\",\"list\",\"watch\",\"create\"]},{\"apiGroups\":[\"\"],\"resourceNames\":[\"fargate-scheduler\"],\"resources\":[\"configmaps\"],\"verbs\":[\"update\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resourceNames\":[\"fargate-scheduler\"],\"resources\":[\"leases\"],\"verbs\":[\"get\",\"update\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resources\":[\"leases\"],\"verbs\":[\"create\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods/binding\"],\"verbs\":[\"create\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"list\",\"watch\",\"delete\"]},{\"apiGroups\":[\"events.k8s.io\",\"\"],\"resources\":[\"events\"],\"verbs\":[\"create\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:fargate-scheduler", + "resourceVersion": "224", + "uid": "e9b4cc96-aa91-4a3e-915e-f3542dbdb33c" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "persistentvolumes", + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "get", + "list", + "watch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps" + ], + "verbs": [ + "get", + "list", + "watch", + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resourceNames": [ + "fargate-scheduler" + ], + "resources": [ + "configmaps" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resourceNames": [ + "fargate-scheduler" + ], + "resources": [ + "leases" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/binding" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch", + "delete" + ] + }, + { + "apiGroups": [ + "events.k8s.io", + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:k8s-metrics\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"endpoints\",\"pods\",\"nodes\"],\"verbs\":[\"list\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"list\"]},{\"nonResourceURLs\":[\"/metrics\",\"/metrics/slis\",\"/debug/api_priority_and_fairness/*\"],\"verbs\":[\"get\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:k8s-metrics", + "resourceVersion": "228", + "uid": "53f87237-0026-4bd8-9f32-c54abf761867" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "pods", + "nodes" + ], + "verbs": [ + "list" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "deployments" + ], + "verbs": [ + "list" + ] + }, + { + "nonResourceURLs": [ + "/metrics", + "/metrics/slis", + "/debug/api_priority_and_fairness/*" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":null,\"labels\":{\"app.kubernetes.io/name\":\"amazon-network-policy-controller-k8s\"},\"name\":\"eks:network-policy-controller\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"namespaces\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"services\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"networking.k8s.aws\"],\"resources\":[\"policyendpoints\"],\"verbs\":[\"create\",\"delete\",\"get\",\"list\",\"patch\",\"update\",\"watch\"]},{\"apiGroups\":[\"networking.k8s.aws\"],\"resources\":[\"policyendpoints/finalizers\"],\"verbs\":[\"update\"]},{\"apiGroups\":[\"networking.k8s.aws\"],\"resources\":[\"policyendpoints/status\"],\"verbs\":[\"get\",\"patch\",\"update\"]},{\"apiGroups\":[\"networking.k8s.io\"],\"resources\":[\"networkpolicies\"],\"verbs\":[\"get\",\"list\",\"patch\",\"update\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:24Z", + "labels": { + "app.kubernetes.io/name": "amazon-network-policy-controller-k8s" + }, + "name": "eks:network-policy-controller", + "resourceVersion": "391", + "uid": "45b35f15-a4d4-4fd4-bc43-c72ec87478b5" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.aws" + ], + "resources": [ + "policyendpoints" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.aws" + ], + "resources": [ + "policyendpoints/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "networking.k8s.aws" + ], + "resources": [ + "policyendpoints/status" + ], + "verbs": [ + "get", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "networkpolicies" + ], + "verbs": [ + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"node\"},\"name\":\"eks:node-bootstrapper\"},\"rules\":[{\"apiGroups\":[\"certificates.k8s.io\"],\"resources\":[\"certificatesigningrequests/selfnodeserver\"],\"verbs\":[\"create\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "node" + }, + "name": "eks:node-bootstrapper", + "resourceVersion": "318", + "uid": "f1e5c2e8-51b8-4206-b1ba-727d5839fa6e" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests/selfnodeserver" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:node-manager\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"get\",\"list\",\"watch\",\"delete\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"list\",\"watch\",\"patch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods/eviction\"],\"verbs\":[\"create\"]},{\"apiGroups\":[\"apps\"],\"resourceNames\":[\"aws-node\"],\"resources\":[\"daemonsets\"],\"verbs\":[\"get\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "eks:node-manager", + "resourceVersion": "287", + "uid": "8179631b-59c1-4b62-a757-de25dba1d057" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch", + "delete" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch", + "patch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resourceNames": [ + "aws-node" + ], + "resources": [ + "daemonsets" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:nodewatcher\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"watch\",\"list\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:nodewatcher", + "resourceVersion": "230", + "uid": "d8de070f-d298-4be3-87b2-e208140b24f6" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "watch", + "list" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:pod-identity-mutating-webhook\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"serviceaccounts\"],\"verbs\":[\"get\",\"watch\",\"list\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:pod-identity-mutating-webhook", + "resourceVersion": "232", + "uid": "5730ace0-07a1-4c0d-83ba-603565787d1e" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "get", + "watch", + "list" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:service-operations\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"endpoints\",\"persistentvolumeclaims\",\"persistentvolumeclaims/status\",\"pods\",\"replicationcontrollers\",\"replicationcontrollers/scale\",\"serviceaccounts\",\"services\",\"services/status\",\"bindings\",\"events\",\"limitranges\",\"namespaces/status\",\"pods/status\",\"replicationcontrollers/status\",\"resourcequotas\",\"resourcequotas/status\",\"namespaces\",\"nodes\",\"nodes/status\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"discovery.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"autoscaling\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"batch\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"extensions\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"policy\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"networking.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"coordination.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"rbac.authorization.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"storage.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"certificates.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"admissionregistration.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"apiextensions.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"apiregistration.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"policy\"],\"resources\":[\"podsecuritypolicies\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"node.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"flowcontrol.apiserver.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"scheduling.k8s.io\"],\"resources\":[\"*\"],\"verbs\":[\"get\",\"list\"]},{\"apiGroups\":[\"crd.k8s.amazonaws.com\"],\"resources\":[\"eniconfigs\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"vpcresources.k8s.aws\"],\"resources\":[\"securitygrouppolicies\"],\"verbs\":[\"get\",\"list\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:13Z", + "name": "eks:service-operations", + "resourceVersion": "234", + "uid": "194b653f-fbbe-4331-92a9-d96104136d43" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "persistentvolumeclaims", + "persistentvolumeclaims/status", + "pods", + "replicationcontrollers", + "replicationcontrollers/scale", + "serviceaccounts", + "services", + "services/status", + "bindings", + "events", + "limitranges", + "namespaces/status", + "pods/status", + "replicationcontrollers/status", + "resourcequotas", + "resourcequotas/status", + "namespaces", + "nodes", + "nodes/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "admissionregistration.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apiextensions.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apiregistration.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "podsecuritypolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "node.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "flowcontrol.apiserver.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "scheduling.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "eniconfigs" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "vpcresources.k8s.aws" + ], + "resources": [ + "securitygrouppolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"eks:tagging-controller\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"patch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:14Z", + "name": "eks:tagging-controller", + "resourceVersion": "240", + "uid": "e33db17c-5648-41d2-988e-80a3fd82dab9" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "patch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults", + "rbac.authorization.k8s.io/aggregate-to-admin": "true" + }, + "name": "system:aggregate-to-admin", + "resourceVersion": "78", + "uid": "02f31a7a-463c-4a1e-8d78-06c79d07a773" + }, + "rules": [ + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "localsubjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resources": [ + "rolebindings", + "roles" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults", + "rbac.authorization.k8s.io/aggregate-to-edit": "true" + }, + "name": "system:aggregate-to-edit", + "resourceVersion": "79", + "uid": "493e7b95-2ddb-4c0e-b860-af23c407c755" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy", + "secrets", + "services/proxy" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "impersonate" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "pods/attach", + "pods/exec", + "pods/portforward", + "pods/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "events", + "persistentvolumeclaims", + "replicationcontrollers", + "replicationcontrollers/scale", + "secrets", + "serviceaccounts", + "services", + "services/proxy" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "replicasets", + "replicasets/scale", + "statefulsets", + "statefulsets/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "jobs" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "deployments", + "deployments/rollback", + "deployments/scale", + "ingresses", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicationcontrollers/scale" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "networkpolicies" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults", + "rbac.authorization.k8s.io/aggregate-to-view": "true" + }, + "name": "system:aggregate-to-view", + "resourceVersion": "80", + "uid": "91ec70b3-062e-495e-a15a-5ac1f90f6148" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "endpoints", + "persistentvolumeclaims", + "persistentvolumeclaims/status", + "pods", + "replicationcontrollers", + "replicationcontrollers/scale", + "serviceaccounts", + "services", + "services/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "bindings", + "events", + "limitranges", + "namespaces/status", + "pods/log", + "pods/status", + "replicationcontrollers/status", + "resourcequotas", + "resourcequotas/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions", + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "replicasets", + "replicasets/scale", + "replicasets/status", + "statefulsets", + "statefulsets/scale", + "statefulsets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers", + "horizontalpodautoscalers/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "cronjobs/status", + "jobs", + "jobs/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "ingresses", + "ingresses/status", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicasets/status", + "replicationcontrollers/scale" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets", + "poddisruptionbudgets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "ingresses/status", + "networkpolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:auth-delegator", + "resourceVersion": "86", + "uid": "4bb9f33c-71a5-4cbc-ae43-3dd9133ed7c9" + }, + "rules": [ + { + "apiGroups": [ + "authentication.k8s.io" + ], + "resources": [ + "tokenreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "subjectaccessreviews" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:basic-user", + "resourceVersion": "73", + "uid": "cbd3a8a5-ddbc-4921-857f-12dba43652cc" + }, + "rules": [ + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "selfsubjectaccessreviews", + "selfsubjectrulesreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "authentication.k8s.io" + ], + "resources": [ + "selfsubjectreviews" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:certificatesigningrequests:nodeclient", + "resourceVersion": "91", + "uid": "ba993b8d-8524-4797-ae32-6d8c5f122280" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests/nodeclient" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient", + "resourceVersion": "92", + "uid": "7344a284-5b22-48d8-9e01-aebeaff49f8a" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests/selfnodeclient" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:kube-apiserver-client-approver", + "resourceVersion": "96", + "uid": "c7e624f6-4f79-41b3-bdc4-4580d11341f1" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kube-apiserver-client" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:kube-apiserver-client-kubelet-approver", + "resourceVersion": "97", + "uid": "9b275d63-d75d-4659-bc47-6b12a9413b36" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kube-apiserver-client-kubelet" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:kubelet-serving-approver", + "resourceVersion": "95", + "uid": "c8b309a5-de1e-47c7-800b-7e04bee63026" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kubelet-serving" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:certificates.k8s.io:legacy-unknown-approver", + "resourceVersion": "94", + "uid": "097068cf-2c05-4690-a453-4f2410f2d441" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/legacy-unknown" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:attachdetach-controller", + "resourceVersion": "101", + "uid": "00d19f56-da20-49c8-89d6-faa21692f693" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims", + "persistentvolumes" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "volumeattachments" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csidrivers" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csinodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:certificate-controller", + "resourceVersion": "127", + "uid": "1694dd17-ffde-4f23-90bf-3f81a3380439" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests" + ], + "verbs": [ + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests/approval", + "certificatesigningrequests/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kube-apiserver-client-kubelet" + ], + "resources": [ + "signers" + ], + "verbs": [ + "approve" + ] + }, + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resourceNames": [ + "kubernetes.io/kube-apiserver-client", + "kubernetes.io/kube-apiserver-client-kubelet", + "kubernetes.io/kubelet-serving", + "kubernetes.io/legacy-unknown" + ], + "resources": [ + "signers" + ], + "verbs": [ + "sign" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "subjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:clusterrole-aggregation-controller", + "resourceVersion": "102", + "uid": "199aed18-5618-4522-9d2a-ecc3a8ccbd01" + }, + "rules": [ + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "resources": [ + "clusterroles" + ], + "verbs": [ + "escalate", + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:cronjob-controller", + "resourceVersion": "103", + "uid": "4eefb726-ffa0-42f1-ac44-29af7e2c1f3f" + }, + "rules": [ + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "delete", + "list" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:daemon-set-controller", + "resourceVersion": "104", + "uid": "5cc1e30a-1e48-483c-849e-9c9449e6e26a" + }, + "rules": [ + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "daemonsets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "daemonsets/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "daemonsets/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "list", + "patch", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/binding" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:deployment-controller", + "resourceVersion": "105", + "uid": "9d3b5bef-8e20-4d7a-92d6-3d5479b0e7fb" + }, + "rules": [ + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "deployments" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "deployments/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "deployments/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:disruption-controller", + "resourceVersion": "106", + "uid": "771bc463-1858-4446-9dac-1dccca688d18" + }, + "rules": [ + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "deployments" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "replicationcontrollers" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "statefulsets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "*" + ], + "resources": [ + "*/scale" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "patch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpoint-controller", + "resourceVersion": "107", + "uid": "ff7110a9-b27c-4602-9687-fdb44d51e578" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints/restricted" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpointslice-controller", + "resourceVersion": "108", + "uid": "59ed7e78-7f1c-41f2-9eee-83c978147475" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes", + "pods", + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:endpointslicemirroring-controller", + "resourceVersion": "109", + "uid": "3ada9f76-a818-48a3-9127-0a1cff8e49a0" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ephemeral-volume-controller", + "resourceVersion": "111", + "uid": "93adbdf5-13b4-497d-ad6a-5dc84eb9001a" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "create", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:expand-controller", + "resourceVersion": "110", + "uid": "a4e261ef-a665-4b62-8ef8-433565369fd9" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "storageclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:generic-garbage-collector", + "resourceVersion": "112", + "uid": "f74ece1d-d2dc-49a3-b1ac-7403c47b344b" + }, + "rules": [ + { + "apiGroups": [ + "*" + ], + "resources": [ + "*" + ], + "verbs": [ + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:horizontal-pod-autoscaler", + "resourceVersion": "113", + "uid": "8da2e041-ceac-4373-a5e0-9d18a79ced28" + }, + "rules": [ + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "*" + ], + "resources": [ + "*/scale" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "list" + ] + }, + { + "apiGroups": [ + "metrics.k8s.io" + ], + "resources": [ + "pods" + ], + "verbs": [ + "list" + ] + }, + { + "apiGroups": [ + "custom.metrics.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "external.metrics.k8s.io" + ], + "resources": [ + "*" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:job-controller", + "resourceVersion": "114", + "uid": "a37a91ba-5e91-4cdb-a44d-e0ef630ac024" + }, + "rules": [ + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs" + ], + "verbs": [ + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "list", + "patch", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:namespace-controller", + "resourceVersion": "115", + "uid": "a54d8f01-21dd-46e7-8f6d-3dfa12e30936" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces/finalize", + "namespaces/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "*" + ], + "resources": [ + "*" + ], + "verbs": [ + "delete", + "deletecollection", + "get", + "list" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:node-controller", + "resourceVersion": "116", + "uid": "f0a1f87c-9616-440d-96a8-e3655c99f8e3" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "delete", + "get", + "list", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "delete", + "list" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "clustercidrs" + ], + "verbs": [ + "create", + "get", + "list", + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:persistent-volume-binder", + "resourceVersion": "117", + "uid": "16bda771-dbcb-4dd7-9d2c-95469dc99ecf" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "storageclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "create", + "delete", + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "create", + "delete", + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pod-garbage-collector", + "resourceVersion": "118", + "uid": "dca0a84d-ca66-4f25-b11a-6a0cbf89f1a9" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "delete", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "patch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pv-protection-controller", + "resourceVersion": "129", + "uid": "eedf57d6-ad2d-4bed-8871-daebfa01d019" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:pvc-protection-controller", + "resourceVersion": "128", + "uid": "42f5f121-5367-4519-86f5-0efe92f76c14" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:replicaset-controller", + "resourceVersion": "119", + "uid": "0ee6116f-9893-4e94-89d7-75df3bc38f73" + }, + "rules": [ + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "list", + "patch", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:replication-controller", + "resourceVersion": "120", + "uid": "74c3363c-4daf-4c1c-9687-7940ebcda548" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "replicationcontrollers" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "replicationcontrollers/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "replicationcontrollers/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "list", + "patch", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:resourcequota-controller", + "resourceVersion": "121", + "uid": "8d3c5423-b068-4557-9c7c-f85b1e5a1ebd" + }, + "rules": [ + { + "apiGroups": [ + "*" + ], + "resources": [ + "*" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "resourcequotas/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:root-ca-cert-publisher", + "resourceVersion": "131", + "uid": "f2b7b83e-29f7-4b69-92fb-f53ee8a7c52f" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps" + ], + "verbs": [ + "create", + "update" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:route-controller", + "resourceVersion": "122", + "uid": "eff39fd4-c1cd-498c-b042-67003e518788" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:service-account-controller", + "resourceVersion": "123", + "uid": "66598dc0-22b1-4cca-86dc-579a330e7f45" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:service-controller", + "resourceVersion": "124", + "uid": "d1c83faf-6878-4551-96dd-7af437083926" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:statefulset-controller", + "resourceVersion": "125", + "uid": "0afcffac-8b70-42b1-b129-a3a25c308f3c" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "statefulsets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "statefulsets/status" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "statefulsets/finalizers" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete", + "get", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "create", + "get" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "delete", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ttl-after-finished-controller", + "resourceVersion": "130", + "uid": "6e54d65f-eb03-4a40-b240-0a3130e9f880" + }, + "rules": [ + { + "apiGroups": [ + "batch" + ], + "resources": [ + "jobs" + ], + "verbs": [ + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:07Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:controller:ttl-controller", + "resourceVersion": "126", + "uid": "cb169228-6256-4fd3-a102-5bd97e2dd8af" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"coredns\",\"k8s-app\":\"kube-dns\",\"kubernetes.io/bootstrapping\":\"rbac-defaults\"},\"name\":\"system:coredns\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"endpoints\",\"services\",\"pods\",\"namespaces\"],\"verbs\":[\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\"]},{\"apiGroups\":[\"discovery.k8s.io\"],\"resources\":[\"endpointslices\"],\"verbs\":[\"list\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns", + "resourceVersion": "293", + "uid": "83f14377-1f8a-4b3c-914a-c80371437698" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services", + "pods", + "namespaces" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:discovery", + "resourceVersion": "71", + "uid": "215419e4-906d-4b6d-9c50-1f1963943d9a" + }, + "rules": [ + { + "nonResourceURLs": [ + "/api", + "/api/*", + "/apis", + "/apis/*", + "/healthz", + "/livez", + "/openapi", + "/openapi/*", + "/readyz", + "/version", + "/version/" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:heapster", + "resourceVersion": "81", + "uid": "aad5e422-85d5-431b-a413-461ec6c8ef9f" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "events", + "namespaces", + "nodes", + "pods" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "deployments" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-aggregator", + "resourceVersion": "87", + "uid": "faba62ef-3b53-4f0c-83f4-c2f06d3b1a58" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-controller-manager", + "resourceVersion": "88", + "uid": "6e3308e3-7daa-4230-b7b3-31d0bbd62784" + }, + "rules": [ + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resourceNames": [ + "kube-controller-manager" + ], + "resources": [ + "leases" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resourceNames": [ + "kube-controller-manager" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets", + "serviceaccounts" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets" + ], + "verbs": [ + "delete" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "namespaces", + "secrets", + "serviceaccounts" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "secrets", + "serviceaccounts" + ], + "verbs": [ + "update" + ] + }, + { + "apiGroups": [ + "authentication.k8s.io" + ], + "resources": [ + "tokenreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "subjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "*" + ], + "resources": [ + "*" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-dns", + "resourceVersion": "89", + "uid": "43afcc0d-16d4-48f0-a2e4-264dd30e8048" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kube-scheduler", + "resourceVersion": "100", + "uid": "a751cdb8-8474-418d-b4fa-ef768b320089" + }, + "rules": [ + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resourceNames": [ + "kube-scheduler" + ], + "resources": [ + "leases" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resourceNames": [ + "kube-scheduler" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "get", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "bindings", + "pods/binding" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "replicationcontrollers", + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps", + "extensions" + ], + "resources": [ + "replicasets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "statefulsets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims", + "persistentvolumes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "authentication.k8s.io" + ], + "resources": [ + "tokenreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "subjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csinodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csidrivers" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csistoragecapacities" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:kubelet-api-admin", + "resourceVersion": "84", + "uid": "2c037087-3c75-4cf6-acf6-eec75e85be2e" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "proxy" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/log", + "nodes/metrics", + "nodes/proxy", + "nodes/stats" + ], + "verbs": [ + "*" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:monitoring", + "resourceVersion": "72", + "uid": "f4d0ebbb-d267-402f-a885-bb523d75a55f" + }, + "rules": [ + { + "nonResourceURLs": [ + "/healthz", + "/healthz/*", + "/livez", + "/livez/*", + "/metrics", + "/metrics/slis", + "/readyz", + "/readyz/*" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node", + "resourceVersion": "82", + "uid": "ee57d291-e363-485c-98cc-f3186fb1baf2" + }, + "rules": [ + { + "apiGroups": [ + "authentication.k8s.io" + ], + "resources": [ + "tokenreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "authorization.k8s.io" + ], + "resources": [ + "localsubjectaccessreviews", + "subjectaccessreviews" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "services" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "create", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "create", + "delete" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/status" + ], + "verbs": [ + "patch", + "update" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods/eviction" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "secrets" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims", + "persistentvolumes" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests" + ], + "verbs": [ + "create", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "coordination.k8s.io" + ], + "resources": [ + "leases" + ], + "verbs": [ + "create", + "delete", + "get", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "volumeattachments" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts/token" + ], + "verbs": [ + "create" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims/status" + ], + "verbs": [ + "get", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csidrivers" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "csinodes" + ], + "verbs": [ + "create", + "delete", + "get", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "node.k8s.io" + ], + "resources": [ + "runtimeclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node-bootstrapper", + "resourceVersion": "85", + "uid": "ef598d1c-c853-4cf9-a72a-c1d55e5a8ed9" + }, + "rules": [ + { + "apiGroups": [ + "certificates.k8s.io" + ], + "resources": [ + "certificatesigningrequests" + ], + "verbs": [ + "create", + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node-problem-detector", + "resourceVersion": "83", + "uid": "bddd3cba-3b4f-4fef-a669-27da33c3650c" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "patch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:node-proxier", + "resourceVersion": "99", + "uid": "1511cd85-4df4-4990-bfae-915c910e6695" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:persistent-volume-provisioner", + "resourceVersion": "90", + "uid": "e7a7708b-b161-4d18-9648-3b0b620479cb" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "create", + "delete", + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "storageclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "watch" + ] + }, + { + "apiGroups": [ + "", + "events.k8s.io" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "patch", + "update" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:public-info-viewer", + "resourceVersion": "74", + "uid": "5cef30b2-3904-42e0-9fac-db2e19875169" + }, + "rules": [ + { + "nonResourceURLs": [ + "/healthz", + "/livez", + "/readyz", + "/version", + "/version/" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:service-account-issuer-discovery", + "resourceVersion": "98", + "uid": "31d92ec6-cb64-4b54-bab4-0c6d7ed732f9" + }, + "rules": [ + { + "nonResourceURLs": [ + "/.well-known/openid-configuration", + "/openid/v1/jwks" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:volume-scheduler", + "resourceVersion": "93", + "uid": "516adaa1-fdb2-40bb-b74f-e99428a04c90" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumes" + ], + "verbs": [ + "get", + "list", + "patch", + "update", + "watch" + ] + }, + { + "apiGroups": [ + "storage.k8s.io" + ], + "resources": [ + "storageclasses" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "persistentvolumeclaims" + ], + "verbs": [ + "get", + "list", + "patch", + "update", + "watch" + ] + } + ] + }, + { + "aggregationRule": { + "clusterRoleSelectors": [ + { + "matchLabels": { + "rbac.authorization.k8s.io/aggregate-to-view": "true" + } + } + ] + }, + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "creationTimestamp": "2023-09-11T19:26:06Z", + "labels": { + "kubernetes.io/bootstrapping": "rbac-defaults", + "rbac.authorization.k8s.io/aggregate-to-edit": "true" + }, + "name": "view", + "resourceVersion": "338", + "uid": "a4f1126c-5f52-45d7-887a-6ddd589c321d" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "configmaps", + "endpoints", + "persistentvolumeclaims", + "persistentvolumeclaims/status", + "pods", + "replicationcontrollers", + "replicationcontrollers/scale", + "serviceaccounts", + "services", + "services/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "bindings", + "events", + "limitranges", + "namespaces/status", + "pods/log", + "pods/status", + "replicationcontrollers/status", + "resourcequotas", + "resourcequotas/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "namespaces" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "discovery.k8s.io" + ], + "resources": [ + "endpointslices" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "apps" + ], + "resources": [ + "controllerrevisions", + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "replicasets", + "replicasets/scale", + "replicasets/status", + "statefulsets", + "statefulsets/scale", + "statefulsets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "autoscaling" + ], + "resources": [ + "horizontalpodautoscalers", + "horizontalpodautoscalers/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "batch" + ], + "resources": [ + "cronjobs", + "cronjobs/status", + "jobs", + "jobs/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets", + "daemonsets/status", + "deployments", + "deployments/scale", + "deployments/status", + "ingresses", + "ingresses/status", + "networkpolicies", + "replicasets", + "replicasets/scale", + "replicasets/status", + "replicationcontrollers/scale" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "policy" + ], + "resources": [ + "poddisruptionbudgets", + "poddisruptionbudgets/status" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "networking.k8s.io" + ], + "resources": [ + "ingresses", + "ingresses/status", + "networkpolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"vpc-resource-controller-role\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"events\"],\"verbs\":[\"create\",\"update\",\"patch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"nodes/status\"],\"verbs\":[\"get\",\"patch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"get\",\"list\",\"patch\",\"watch\"]},{\"apiGroups\":[\"\"],\"resources\":[\"serviceaccounts\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"crd.k8s.amazonaws.com\"],\"resources\":[\"eniconfigs\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"vpcresources.k8s.aws\"],\"resources\":[\"securitygrouppolicies\"],\"verbs\":[\"get\",\"list\",\"watch\"]},{\"apiGroups\":[\"vpcresources.k8s.aws\"],\"resources\":[\"cninodes\"],\"verbs\":[\"create\",\"get\",\"list\",\"watch\"]}]}\n" + }, + "creationTimestamp": "2023-09-11T19:26:24Z", + "name": "vpc-resource-controller-role", + "resourceVersion": "378", + "uid": "fca235df-b4e7-430e-8d13-9da233296648" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "events" + ], + "verbs": [ + "create", + "update", + "patch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes/status" + ], + "verbs": [ + "get", + "patch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods" + ], + "verbs": [ + "get", + "list", + "patch", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "serviceaccounts" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "eniconfigs" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "vpcresources.k8s.aws" + ], + "resources": [ + "securitygrouppolicies" + ], + "verbs": [ + "get", + "list", + "watch" + ] + }, + { + "apiGroups": [ + "vpcresources.k8s.aws" + ], + "resources": [ + "cninodes" + ], + "verbs": [ + "create", + "get", + "list", + "watch" + ] + } + ] + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/daemon_sets_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/daemon_sets_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/daemon_sets_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/deployments_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/deployments_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/deployments_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/horizontal_pod_autoscaler_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/horizontal_pod_autoscaler_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/horizontal_pod_autoscaler_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/namespaces_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/namespaces_api_response.json new file mode 100644 index 0000000..544c358 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/namespaces_api_response.json @@ -0,0 +1,135 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T19:31:08Z", + "labels": { + "kubernetes.io/metadata.name": "amazon-guardduty" + }, + "name": "amazon-guardduty", + "resourceVersion": "990", + "uid": "25bba3c3-4eb8-41e7-88cf-08237a3f03a0" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T19:26:05Z", + "labels": { + "kubernetes.io/metadata.name": "default" + }, + "name": "default", + "resourceVersion": "35", + "uid": "98c1c5cf-4dcd-4338-8667-3458d9021c0b" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T19:26:05Z", + "labels": { + "kubernetes.io/metadata.name": "kube-node-lease" + }, + "name": "kube-node-lease", + "resourceVersion": "30", + "uid": "5cbce384-3e78-421e-9700-2462c269c5ce" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T19:26:05Z", + "labels": { + "kubernetes.io/metadata.name": "kube-public" + }, + "name": "kube-public", + "resourceVersion": "17", + "uid": "f474518e-f7c9-4e55-aab1-952af6012044" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T19:26:05Z", + "labels": { + "kubernetes.io/metadata.name": "kube-system" + }, + "name": "kube-system", + "resourceVersion": "9", + "uid": "4fa13f72-b949-40c6-8605-c263a762819b" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "creationTimestamp": "2023-09-11T20:06:51Z", + "labels": { + "kubernetes.io/metadata.name": "test-namespace" + }, + "name": "test-namespace", + "resourceVersion": "7493", + "uid": "60a8dd29-0ad8-4b3f-90f4-1b366e30c88b" + }, + "spec": { + "finalizers": [ + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/network_policies_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/network_policies_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/network_policies_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/persistent_volumes_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/persistent_volumes_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/persistent_volumes_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/pods_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/pods_api_response.json new file mode 100644 index 0000000..6fa9f0d --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/pods_api_response.json @@ -0,0 +1,364 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"bad\",\"namespace\":\"test-namespace\"},\"spec\":{\"containers\":[{\"command\":[\"sh\",\"-c\",\"sleep 1h\"],\"image\":\"busybox\",\"name\":\"sec-ctx-demo\",\"securityContext\":{\"runAsGroup\":3000,\"runAsUser\":1000}},{\"command\":[\"sh\",\"-c\",\"sleep 1h\"],\"image\":\"busybox\",\"name\":\"sec-ctx-demo-2\"}]}}\n" + }, + "creationTimestamp": "2023-09-11T20:06:52Z", + "name": "bad", + "namespace": "test-namespace", + "resourceVersion": "7506", + "uid": "ba3c509c-e32f-4bcb-9eb2-78e75313306c" + }, + "spec": { + "containers": [ + { + "command": [ + "sh", + "-c", + "sleep 1h" + ], + "image": "busybox", + "imagePullPolicy": "Always", + "name": "sec-ctx-demo", + "resources": {}, + "securityContext": { + "runAsGroup": 3000, + "runAsUser": 1000 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-plcl6", + "readOnly": true + } + ] + }, + { + "command": [ + "sh", + "-c", + "sleep 1h" + ], + "image": "busybox", + "imagePullPolicy": "Always", + "name": "sec-ctx-demo-2", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-plcl6", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "i-0bd5715b2476849a1.ec2.internal", + "preemptionPolicy": "PreemptLowerPriority", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "kube-api-access-plcl6", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ], + "name": "kube-root-ca.crt" + } + }, + { + "downwardAPI": { + "items": [ + { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + }, + "path": "namespace" + } + ] + } + } + ] + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "message": "containers with unready status: [sec-ctx-demo sec-ctx-demo-2]", + "reason": "ContainersNotReady", + "status": "False", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "message": "containers with unready status: [sec-ctx-demo sec-ctx-demo-2]", + "reason": "ContainersNotReady", + "status": "False", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "image": "busybox", + "imageID": "", + "lastState": {}, + "name": "sec-ctx-demo", + "ready": false, + "restartCount": 0, + "started": false, + "state": { + "waiting": { + "reason": "ContainerCreating" + } + } + }, + { + "image": "busybox", + "imageID": "", + "lastState": {}, + "name": "sec-ctx-demo-2", + "ready": false, + "restartCount": 0, + "started": false, + "state": { + "waiting": { + "reason": "ContainerCreating" + } + } + } + ], + "hostIP": "192.168.104.131", + "phase": "Pending", + "qosClass": "BestEffort", + "startTime": "2023-09-11T20:06:52Z" + } + }, + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"good\",\"namespace\":\"test-namespace\"},\"spec\":{\"containers\":[{\"command\":[\"sh\",\"-c\",\"sleep 1h\"],\"image\":\"busybox\",\"name\":\"sec-ctx-demo\",\"securityContext\":{\"runAsGroup\":3000,\"runAsUser\":1000}}]}}\n" + }, + "creationTimestamp": "2023-09-11T20:06:52Z", + "name": "good", + "namespace": "test-namespace", + "resourceVersion": "7522", + "uid": "441fb67e-9266-46aa-b972-6d314a6651a0" + }, + "spec": { + "containers": [ + { + "command": [ + "sh", + "-c", + "sleep 1h" + ], + "image": "busybox", + "imagePullPolicy": "Always", + "name": "sec-ctx-demo", + "resources": {}, + "securityContext": { + "runAsGroup": 3000, + "runAsUser": 1000 + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-q75j4", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "i-0bd5715b2476849a1.ec2.internal", + "preemptionPolicy": "PreemptLowerPriority", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "default", + "serviceAccountName": "default", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "kube-api-access-q75j4", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ], + "name": "kube-root-ca.crt" + } + }, + { + "downwardAPI": { + "items": [ + { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + }, + "path": "namespace" + } + ] + } + } + ] + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:54Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:54Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2023-09-11T20:06:52Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "containerd://cbb05e3350f3c447b6d8bef21ffcd27be93affdd83a1aea6e09741ddf9eefa27", + "image": "docker.io/library/busybox:latest", + "imageID": "docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79", + "lastState": {}, + "name": "sec-ctx-demo", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2023-09-11T20:06:53Z" + } + } + } + ], + "hostIP": "192.168.104.131", + "phase": "Running", + "podIP": "192.168.102.161", + "podIPs": [ + { + "ip": "192.168.102.161" + } + ], + "qosClass": "BestEffort", + "startTime": "2023-09-11T20:06:52Z" + } + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/resource_quotas_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/resource_quotas_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/resource_quotas_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/role_bindings_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/role_bindings_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/role_bindings_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/roles_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/roles_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/roles_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/services_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/services_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/services_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/stateful_sets_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/stateful_sets_api_response.json new file mode 100644 index 0000000..6da8d27 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/stateful_sets_api_response.json @@ -0,0 +1,8 @@ +{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/cluster/storage_classes_api_response.json b/tests/data/disable_run_as_root_user_container/cluster/storage_classes_api_response.json new file mode 100644 index 0000000..66be917 --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/cluster/storage_classes_api_response.json @@ -0,0 +1,30 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "storage.k8s.io/v1", + "kind": "StorageClass", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"storage.k8s.io/v1\",\"kind\":\"StorageClass\",\"metadata\":{\"annotations\":{\"storageclass.kubernetes.io/is-default-class\":\"true\"},\"name\":\"gp2\"},\"parameters\":{\"fsType\":\"ext4\",\"type\":\"gp2\"},\"provisioner\":\"kubernetes.io/aws-ebs\",\"volumeBindingMode\":\"WaitForFirstConsumer\"}\n", + "storageclass.kubernetes.io/is-default-class": "true" + }, + "creationTimestamp": "2023-09-11T19:26:20Z", + "name": "gp2", + "resourceVersion": "301", + "uid": "949fdd2a-508e-407f-a36e-ade29b1ad0ea" + }, + "parameters": { + "fsType": "ext4", + "type": "gp2" + }, + "provisioner": "kubernetes.io/aws-ebs", + "reclaimPolicy": "Delete", + "volumeBindingMode": "WaitForFirstConsumer" + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} diff --git a/tests/data/disable_run_as_root_user_container/good.yaml b/tests/data/disable_run_as_root_user_container/good.yaml new file mode 100644 index 0000000..38cbcba --- /dev/null +++ b/tests/data/disable_run_as_root_user_container/good.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + namespace: test-namespace + name: good +spec: + containers: + - name: sec-ctx-demo + image: busybox + command: [ "sh", "-c", "sleep 1h" ] + securityContext: + runAsUser: 1000 + runAsGroup: 3000 \ No newline at end of file diff --git a/tests/test_cluster_autoscaling_cluster_autoscaler.py b/tests/test_cluster_autoscaling_cluster_autoscaler.py index 3e04d5f..1894f2b 100644 --- a/tests/test_cluster_autoscaling_cluster_autoscaler.py +++ b/tests/test_cluster_autoscaling_cluster_autoscaler.py @@ -44,7 +44,10 @@ def test_check_any_cluster_autoscaler_exists(mocked_client): ) resources = Resources("some_region", "some_context", "some_cluster", []) - assert not check_any_cluster_autoscaler_exists(resources) + rule = check_any_cluster_autoscaler_exists() + rule.check(resources) + + assert not rule.result.status @patch("boto3.client") @@ -71,8 +74,10 @@ def test_ensure_cluster_autoscaler_and_cluster_versions_match( "cluster": {"version": "1.23"} } resources = Resources("some_region", "some_context", "some_cluster", []) + rule = ensure_cluster_autoscaler_and_cluster_versions_match() + rule.check(resources) - assert not ensure_cluster_autoscaler_and_cluster_versions_match(resources) + assert not rule.result.status @patch("kubernetes.client.AppsV1Api.list_deployment_for_all_namespaces") @@ -92,8 +97,9 @@ def test_ensure_cluster_autoscaler_has_autodiscovery_mode(mocked_client): "V1DeploymentList", ) resources = Resources("some_region", "some_context", "some_cluster", []) - - assert not ensure_cluster_autoscaler_has_autodiscovery_mode(resources) + rule = ensure_cluster_autoscaler_has_autodiscovery_mode() + rule.check(resources) + assert not rule.result.status @patch("kubernetes.client.AppsV1Api.list_deployment_for_all_namespaces") @@ -129,8 +135,9 @@ def test_use_separate_iam_role_for_cluster_autoscaler( sa_client.return_value = sa_return_value resources = Resources("some_region", "some_context", "some_cluster", []) - - assert not use_separate_iam_role_for_cluster_autoscaler(resources) + rule = use_separate_iam_role_for_cluster_autoscaler() + rule.check(resources) + assert not rule.result.status @patch("boto3.client") @@ -207,9 +214,10 @@ def test_employ_least_privileged_access_cluster_autoscaler_role( resources = Resources("some_region", "some_context", "some_cluster", []) - assert not employ_least_privileged_access_cluster_autoscaler_role( - resources - ) + rule = employ_least_privileged_access_cluster_autoscaler_role() + rule.check(resources) + + assert not rule.result.status @patch("kubernetes.client.CoreV1Api.list_node") @@ -230,9 +238,10 @@ def test_use_managed_nodegroups(mocked_client): ) resources = Resources("some_region", "some_context", "some_cluster", []) - not_managed = [i.metadata.name for i in use_managed_nodegroups(resources)] + rule = use_managed_nodegroups() + rule.check(resources) - assert not_managed == [ + assert rule.result.resources == [ "ip-192-168-59-44.ec2.internal", "ip-192-168-6-151.ec2.internal", ] diff --git a/tests/test_reliability_applications.py b/tests/test_reliability_applications.py index a081c15..fe6294f 100644 --- a/tests/test_reliability_applications.py +++ b/tests/test_reliability_applications.py @@ -27,10 +27,11 @@ indirect=["namespaced_resources"], ) def test_avoid_running_singleton_pods(namespaced_resources): - offenders = avoid_running_singleton_pods(namespaced_resources) + rule = avoid_running_singleton_pods() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -39,10 +40,12 @@ def test_avoid_running_singleton_pods(namespaced_resources): indirect=["namespaced_resources"], ) def test_run_multiple_replicas(namespaced_resources): - offenders = run_multiple_replicas(namespaced_resources) + rule = run_multiple_replicas() - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule.check(namespaced_resources) + + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -51,10 +54,11 @@ def test_run_multiple_replicas(namespaced_resources): indirect=["namespaced_resources"], ) def test_schedule_replicas_across_nodes(namespaced_resources): - offenders = schedule_replicas_across_nodes(namespaced_resources) + rule = schedule_replicas_across_nodes() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @patch("kubernetes.client.CoreV1Api.list_service_for_all_namespaces") @@ -75,8 +79,10 @@ def test_check_metrics_server_is_running(mocked_client): namespaced_resources = Resources( "some_region", "some_context", "some_cluster", [] ) + rule = check_metrics_server_is_running() + rule.check(namespaced_resources) - assert not check_metrics_server_is_running(namespaced_resources) + assert not rule.result.status @patch("kubernetes.client.AppsV1Api.list_deployment_for_all_namespaces") @@ -99,8 +105,10 @@ def test_check_vertical_pod_autoscaler_exists(mocked_client): namespaced_resources = Resources( "some_region", "some_context", "some_cluster", [] ) + rule = check_vertical_pod_autoscaler_exists() + rule.check(namespaced_resources) - assert not check_vertical_pod_autoscaler_exists(namespaced_resources) + assert not rule.result.status @pytest.mark.parametrize( @@ -109,10 +117,12 @@ def test_check_vertical_pod_autoscaler_exists(mocked_client): indirect=["namespaced_resources"], ) def test_check_horizontal_pod_autoscaling_exists(namespaced_resources): - offenders = check_horizontal_pod_autoscaling_exists(namespaced_resources) + rule = check_horizontal_pod_autoscaling_exists() + + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -121,10 +131,12 @@ def test_check_horizontal_pod_autoscaling_exists(namespaced_resources): indirect=["namespaced_resources"], ) def test_check_liveness_probes(namespaced_resources): - offenders = check_liveness_probes(namespaced_resources) + rule = check_liveness_probes() - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule.check(namespaced_resources) + + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -133,7 +145,9 @@ def test_check_liveness_probes(namespaced_resources): indirect=["namespaced_resources"], ) def test_check_readiness_probes(namespaced_resources): - offenders = check_readiness_probes(namespaced_resources) + rule = check_readiness_probes() + + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources diff --git a/tests/test_scalability_control_plane.py b/tests/test_scalability_control_plane.py index 9b11a2e..bd1a4af 100644 --- a/tests/test_scalability_control_plane.py +++ b/tests/test_scalability_control_plane.py @@ -4,7 +4,7 @@ from hardeneks.cluster_wide.scalability.control_plane import ( check_EKS_version, - check_kubectl_compression + check_kubectl_compression, ) @@ -19,27 +19,85 @@ def test_check_EKS_version(mocked_client): namespaced_resources = Resources( "some_region", "some_context", "some_cluster", [] ) + rule = check_EKS_version() mocked_client.return_value = Version("23+") - assert not check_EKS_version(namespaced_resources) + rule.check(namespaced_resources) + assert not rule.result.status mocked_client.return_value = Version("24+") - assert check_EKS_version(namespaced_resources) + rule.check(namespaced_resources) + assert rule.result.status mocked_client.return_value = Version("24") - assert check_EKS_version(namespaced_resources) + rule.check(namespaced_resources) + assert rule.result.status + @patch(helpers.__name__ + ".get_kube_config") def test_check_kubectl_compression(mocked_helpers): namespaced_resources = Resources( "some_region", "some_context", "foobarcluster", [] ) - mocked_helpers.return_value = {'clusters': [{'cluster': {'server': 'testtest', 'disable-compression': True}, 'name': 'foobarcluster'}]} - assert check_kubectl_compression(namespaced_resources) - mocked_helpers.return_value = {'clusters': [{'cluster': {'server': 'testtest', 'disable-compression': True}, 'name': 'foobarcluster'}, {'cluster': {'server': 'testtest', 'disable-compression': False}, 'name': 'foobarcluster2'}]} - assert check_kubectl_compression(namespaced_resources) - mocked_helpers.return_value = {'clusters': [{'cluster': {'server': 'testtest', 'disable-compression': False}, 'name': 'foobarcluster'}, {'cluster': {'server': 'testtest', 'disable-compression': False}, 'name': 'foobarcluster4'}]} - assert not check_kubectl_compression(namespaced_resources) - mocked_helpers.return_value = {'clusters': [{'cluster': {'test': 'user'}, 'name': 'foobarcluster7'}]} - assert not check_kubectl_compression(namespaced_resources) - mocked_helpers.return_value = {'clusters': [{}]} - assert not check_kubectl_compression(namespaced_resources) + rule = check_kubectl_compression() + + mocked_helpers.return_value = { + "clusters": [ + { + "cluster": {"server": "testtest", "disable-compression": True}, + "name": "foobarcluster", + } + ] + } + rule.check(namespaced_resources) + assert rule.result.status + + mocked_helpers.return_value = { + "clusters": [ + { + "cluster": {"server": "testtest", "disable-compression": True}, + "name": "foobarcluster", + }, + { + "cluster": { + "server": "testtest", + "disable-compression": False, + }, + "name": "foobarcluster2", + }, + ] + } + rule.check(namespaced_resources) + assert rule.result.status + + mocked_helpers.return_value = { + "clusters": [ + { + "cluster": { + "server": "testtest", + "disable-compression": False, + }, + "name": "foobarcluster", + }, + { + "cluster": { + "server": "testtest", + "disable-compression": False, + }, + "name": "foobarcluster4", + }, + ] + } + rule.check(namespaced_resources) + assert not rule.result.status + + mocked_helpers.return_value = { + "clusters": [{"cluster": {"test": "user"}, "name": "foobarcluster7"}] + } + rule.check(namespaced_resources) + assert not rule.result.status + + mocked_helpers.return_value = {"clusters": [{}]} + rule.check(namespaced_resources) + assert not rule.result.status + mocked_helpers.return_value = {} - assert not check_kubectl_compression(namespaced_resources) \ No newline at end of file + rule.check(namespaced_resources) + assert not rule.result.status diff --git a/tests/test_security_detective_controls.py b/tests/test_security_detective_controls.py index e955e8c..0bb97de 100644 --- a/tests/test_security_detective_controls.py +++ b/tests/test_security_detective_controls.py @@ -30,5 +30,7 @@ def test_check_logs_are_enabled(mocked_client): mocked_client.return_value.describe_cluster.return_value = read_json( test_data ) + rule = check_logs_are_enabled() + rule.check(namespaced_resources) - assert not check_logs_are_enabled(namespaced_resources) + assert not rule.result.status diff --git a/tests/test_security_encryption_secrets.py b/tests/test_security_encryption_secrets.py index 63ec54d..4093433 100644 --- a/tests/test_security_encryption_secrets.py +++ b/tests/test_security_encryption_secrets.py @@ -16,10 +16,11 @@ indirect=["resources"], ) def test_use_encryption_with_ebs(resources): - offenders = use_encryption_with_ebs(resources) + rule = use_encryption_with_ebs() + rule.check(resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -28,10 +29,11 @@ def test_use_encryption_with_ebs(resources): indirect=["resources"], ) def test_use_encryption_with_efs(resources): - offenders = use_encryption_with_efs(resources) + rule = use_encryption_with_efs() + rule.check(resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -40,10 +42,11 @@ def test_use_encryption_with_efs(resources): indirect=["resources"], ) def test_use_efs_access_points(resources): - offenders = use_efs_access_points(resources) + rule = use_efs_access_points() + rule.check(resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -52,7 +55,9 @@ def test_use_efs_access_points(resources): indirect=["namespaced_resources"], ) def test_disallow_secrets_from_env_vars(namespaced_resources): - offenders = disallow_secrets_from_env_vars(namespaced_resources) + rule = disallow_secrets_from_env_vars() - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule.check(namespaced_resources) + + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources diff --git a/tests/test_security_iam.py b/tests/test_security_iam.py index 7c1add9..7d3e458 100644 --- a/tests/test_security_iam.py +++ b/tests/test_security_iam.py @@ -38,10 +38,11 @@ def read_json(file_path): indirect=["namespaced_resources"], ) def test_restrict_wildcard_for_roles(namespaced_resources): - offenders = restrict_wildcard_for_roles(namespaced_resources) + rule = restrict_wildcard_for_roles() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -50,10 +51,11 @@ def test_restrict_wildcard_for_roles(namespaced_resources): indirect=["namespaced_resources"], ) def test_restrict_wildcard_for_cluster_roles(namespaced_resources): - offenders = restrict_wildcard_for_cluster_roles(namespaced_resources) + rule = restrict_wildcard_for_cluster_roles() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @patch("boto3.client") @@ -73,7 +75,9 @@ def test_check_endpoint_public_access(mocked_client): mocked_client.return_value.describe_cluster.return_value = read_json( test_data ) - assert not check_endpoint_public_access(namespaced_resources) + rule = check_endpoint_public_access() + rule.check(namespaced_resources) + assert not rule.result.status @patch("boto3.client") @@ -93,29 +97,46 @@ def test_check_access_to_instance_profile(mocked_client): mocked_client.return_value.describe_instances.return_value = read_json( test_data ) - offenders = check_access_to_instance_profile(namespaced_resources) - assert len(offenders) == 2 + rule = check_access_to_instance_profile() + rule.check(namespaced_resources) + resources = rule.result.resources + assert len(resources) == 2 @patch("kubernetes.client.AppsV1Api.read_namespaced_daemon_set") -def test_check_aws_node_daemonset_service_account(mocked_client): - test_data = ( +@patch("kubernetes.client.CoreV1Api.read_namespaced_service_account") +def test_check_aws_node_daemonset_service_account( + mocked_core_api, mocked_apps_api +): + daemon_set_data = ( Path.cwd() / "tests" / "data" / "check_aws_node_daemonset_service_account" / "daemon_sets_api_response.json" ) - mocked_client.return_value = get_response( + service_account_data = ( + Path.cwd() + / "tests" + / "data" + / "check_aws_node_daemonset_service_account" + / "service_accounts_api_response.json" + ) + mocked_apps_api.return_value = get_response( kubernetes.client.AppsV1Api, - test_data, + daemon_set_data, "V1DaemonSet", ) - + mocked_core_api.return_value = get_response( + kubernetes.client.CoreV1Api, service_account_data, "V1ServiceAccount" + ) namespaced_resources = NamespacedResources( "some_region", "some_context", "some_cluster", "some_ns" ) - assert not check_aws_node_daemonset_service_account(namespaced_resources) + rule = check_aws_node_daemonset_service_account() + rule.check(namespaced_resources) + + assert not rule.result.status @pytest.mark.parametrize( @@ -124,10 +145,11 @@ def test_check_aws_node_daemonset_service_account(mocked_client): indirect=["namespaced_resources"], ) def test_disable_service_account_token_mounts(namespaced_resources): - offenders = disable_service_account_token_mounts(namespaced_resources) + rule = disable_service_account_token_mounts() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -136,24 +158,39 @@ def test_disable_service_account_token_mounts(namespaced_resources): indirect=["namespaced_resources"], ) def test_disable_run_as_root_user(namespaced_resources): - offenders = disable_run_as_root_user(namespaced_resources) + rule = disable_run_as_root_user() - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule.check(namespaced_resources) + + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources +@pytest.mark.parametrize( + "namespaced_resources", + [("disable_run_as_root_user_container")], + indirect=["namespaced_resources"], +) +def test_disable_run_as_root_user_container(namespaced_resources): + rule = disable_run_as_root_user() + + rule.check(namespaced_resources) + + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources + + @pytest.mark.parametrize( "namespaced_resources", [("disable_anonymous_access_for_cluster_roles")], indirect=["namespaced_resources"], ) def test_disable_anonymous_access_for_cluster_roles(namespaced_resources): - offenders = disable_anonymous_access_for_cluster_roles( - namespaced_resources - ) - - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule = disable_anonymous_access_for_cluster_roles() + rule.check(namespaced_resources) + assert "system:public-info-viewer" not in rule.result.resources + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -162,10 +199,12 @@ def test_disable_anonymous_access_for_cluster_roles(namespaced_resources): indirect=["namespaced_resources"], ) def test_disable_anonymous_access_for_roles(namespaced_resources): - offenders = disable_anonymous_access_for_roles(namespaced_resources) + rule = disable_anonymous_access_for_roles() + + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -176,12 +215,11 @@ def test_disable_anonymous_access_for_roles(namespaced_resources): def test_use_dedicated_service_accounts_for_each_daemon_set( namespaced_resources, ): - offenders = use_dedicated_service_accounts_for_each_daemon_set( - namespaced_resources - ) + rule = use_dedicated_service_accounts_for_each_daemon_set() + rule.check(namespaced_resources) - assert "shared-sa-1" in [i.metadata.name for i in offenders] - assert "shared-sa-2" in [i.metadata.name for i in offenders] + assert "shared-sa-1" in rule.result.resources + assert "shared-sa-2" in rule.result.resources @pytest.mark.parametrize( @@ -192,12 +230,11 @@ def test_use_dedicated_service_accounts_for_each_daemon_set( def test_use_dedicated_service_accounts_for_each_deployment( namespaced_resources, ): - offenders = use_dedicated_service_accounts_for_each_deployment( - namespaced_resources - ) + rule = use_dedicated_service_accounts_for_each_deployment() + rule.check(namespaced_resources) - assert "shared-sa-1" in [i.metadata.name for i in offenders] - assert "shared-sa-2" in [i.metadata.name for i in offenders] + assert "shared-sa-1" in rule.result.resources + assert "shared-sa-2" in rule.result.resources @pytest.mark.parametrize( @@ -208,9 +245,7 @@ def test_use_dedicated_service_accounts_for_each_deployment( def test_use_dedicated_service_accounts_for_each_stateful_set( namespaced_resources, ): - offenders = use_dedicated_service_accounts_for_each_stateful_set( - namespaced_resources - ) - - assert "shared-sa-1" in [i.metadata.name for i in offenders] - assert "shared-sa-2" in [i.metadata.name for i in offenders] + rule = use_dedicated_service_accounts_for_each_stateful_set() + rule.check(namespaced_resources) + assert "shared-sa-1" in rule.result.resources + assert "shared-sa-2" in rule.result.resources diff --git a/tests/test_security_image_security.py b/tests/test_security_image_security.py index 8bc14ee..890c0f1 100644 --- a/tests/test_security_image_security.py +++ b/tests/test_security_image_security.py @@ -31,13 +31,15 @@ def test_use_immutable_tags_with_ecr(mocked_client): mocked_client.return_value.describe_repositories.return_value = read_json( test_data ) - offenders = use_immutable_tags_with_ecr(namespaced_resources) - offender_names = [i["repositoryName"] for i in offenders] + + rule = use_immutable_tags_with_ecr() + rule.check(namespaced_resources) + assert ( "rolling-deployment-service-ecrrepo714fb1b2-xbs3hua1h3ud" - in offender_names + in rule.result.resources ) assert ( "rolling-deployment-service-ecrrepo714fb1b2-nyrkgiafcyyx" - not in offender_names + not in rule.result.resources ) diff --git a/tests/test_security_infrastructure_security.py b/tests/test_security_infrastructure_security.py index 47ee618..3256848 100644 --- a/tests/test_security_infrastructure_security.py +++ b/tests/test_security_infrastructure_security.py @@ -36,13 +36,13 @@ def test_deploy_workers_onto_private_subnets(mocked_client): mocked_client.return_value.describe_instances.return_value = read_json( test_data ) - offenders = deploy_workers_onto_private_subnets(namespaced_resources) - instance_ids = [i["Instances"][0]["InstanceId"] for i in offenders] + rule = deploy_workers_onto_private_subnets() + rule.check(namespaced_resources) - assert "i-063ca77fc509e2bf6" not in instance_ids - assert "i-083cc9da5e18e2702" not in instance_ids - assert "i-01c10da9688b958a0" in instance_ids - assert "i-0f282d6ee7edb633f" in instance_ids + assert "i-063ca77fc509e2bf6" not in rule.result.resources + assert "i-083cc9da5e18e2702" not in rule.result.resources + assert "i-01c10da9688b958a0" in rule.result.resources + assert "i-0f282d6ee7edb633f" in rule.result.resources @patch("boto3.client") @@ -63,5 +63,6 @@ def test_make_sure_inspector_is_enabled(mocked_client): read_json(test_data) ) mocked_client.return_value.get_caller_identity = mocked_caller_identity - - assert not make_sure_inspector_is_enabled(namespaced_resources) + rule = make_sure_inspector_is_enabled() + rule.check(namespaced_resources) + assert not rule.result.status diff --git a/tests/test_security_multi_tenancy.py b/tests/test_security_multi_tenancy.py index dc61bb1..7d15d7f 100644 --- a/tests/test_security_multi_tenancy.py +++ b/tests/test_security_multi_tenancy.py @@ -11,7 +11,8 @@ indirect=["resources"], ) def test_ensure_namespace_quotas_exist(resources): - offenders = ensure_namespace_quotas_exist(resources) + rule = ensure_namespace_quotas_exist() + rule.check(resources) - assert "good" not in offenders - assert "bad" in offenders + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources diff --git a/tests/test_security_network_security.py b/tests/test_security_network_security.py index 326322a..623016a 100644 --- a/tests/test_security_network_security.py +++ b/tests/test_security_network_security.py @@ -29,10 +29,11 @@ def read_json(file_path): indirect=["namespaced_resources"], ) def test_use_encryption_with_aws_load_balancers(namespaced_resources): - offenders = use_encryption_with_aws_load_balancers(namespaced_resources) + rule = use_encryption_with_aws_load_balancers() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @patch("boto3.client") @@ -53,8 +54,10 @@ def test_check_vpc_flow_logs(mocked_client): mocked_client.return_value.describe_flow_logs.return_value = { "FlowLogs": [] } + rule = check_vpc_flow_logs() + rule.check(resources) - assert not check_vpc_flow_logs(resources) + assert not rule.result.status @pytest.mark.parametrize( @@ -63,8 +66,9 @@ def test_check_vpc_flow_logs(mocked_client): indirect=["resources"], ) def test_check_default_deny_policy_exists(resources): - offenders = check_default_deny_policy_exists(resources) - assert ["good", "bad", "default"] == offenders + rule = check_default_deny_policy_exists() + rule.check(resources) + assert ["good", "bad", "default"] == rule.result.resources @patch("kubernetes.client.CoreV1Api.list_service_for_all_namespaces") @@ -86,5 +90,7 @@ def test_check_awspca_exists(mocked_client): namespaced_resources = Resources( "some_region", "some_context", "some_cluster", [] ) + rule = check_awspca_exists() + rule.check(namespaced_resources) - assert not check_awspca_exists(namespaced_resources) + assert not rule.result.status diff --git a/tests/test_security_pod_security.py b/tests/test_security_pod_security.py index d3f19e2..20f01d8 100644 --- a/tests/test_security_pod_security.py +++ b/tests/test_security_pod_security.py @@ -25,9 +25,9 @@ indirect=["namespaced_resources"], ) def test_disallow_container_socket_mount(namespaced_resources): - offenders = disallow_container_socket_mount(namespaced_resources) - - assert "bad" in [i.metadata.name for i in offenders] + rule = disallow_container_socket_mount() + rule.check(namespaced_resources) + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -36,9 +36,10 @@ def test_disallow_container_socket_mount(namespaced_resources): indirect=["namespaced_resources"], ) def test_disallow_host_path_or_make_it_read_only(namespaced_resources): - offenders = disallow_host_path_or_make_it_read_only(namespaced_resources) - - assert "bad" in [i.metadata.name for i in offenders] + rule = disallow_host_path_or_make_it_read_only() + rule.check(namespaced_resources) + rule.check(namespaced_resources) + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -47,10 +48,10 @@ def test_disallow_host_path_or_make_it_read_only(namespaced_resources): indirect=["namespaced_resources"], ) def test_set_requests_limits_for_containers(namespaced_resources): - offenders = set_requests_limits_for_containers(namespaced_resources) - - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule = set_requests_limits_for_containers() + rule.check(namespaced_resources) + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -59,10 +60,11 @@ def test_set_requests_limits_for_containers(namespaced_resources): indirect=["namespaced_resources"], ) def test_disallow_privilege_escalation(namespaced_resources): - offenders = disallow_privilege_escalation(namespaced_resources) + rule = disallow_privilege_escalation() + rule.check(namespaced_resources) - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @pytest.mark.parametrize( @@ -71,10 +73,10 @@ def test_disallow_privilege_escalation(namespaced_resources): indirect=["namespaced_resources"], ) def test_check_read_only_root_file_system(namespaced_resources): - offenders = check_read_only_root_file_system(namespaced_resources) - - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule = check_read_only_root_file_system() + rule.check(namespaced_resources) + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources @patch("kubernetes.client.CoreV1Api.list_namespace") @@ -97,8 +99,9 @@ def test_ensure_namespace_psa_exist(mocked_client): "some_region", "some_context", "some_cluster", - ["kube-node-lease", "kube-public", "kube-system", "kube-apiserver"], + ["bad", "default", "good", "test-namespace"], ) - offenders = ensure_namespace_psa_exist(resources) + rule = ensure_namespace_psa_exist() + rule.check(resources) - assert offenders == ["bad", "default", "test-namespace"] + assert rule.result.resources == ["bad", "default", "test-namespace"] diff --git a/tests/test_security_runtime_security.py b/tests/test_security_runtime_security.py index 10181fb..1615d86 100644 --- a/tests/test_security_runtime_security.py +++ b/tests/test_security_runtime_security.py @@ -11,7 +11,7 @@ indirect=["namespaced_resources"], ) def test_disallow_linux_capabilities(namespaced_resources): - offenders = disallow_linux_capabilities(namespaced_resources) - - assert "good" not in [i.metadata.name for i in offenders] - assert "bad" in [i.metadata.name for i in offenders] + rule = disallow_linux_capabilities() + rule.check(namespaced_resources) + assert "good" not in rule.result.resources + assert "bad" in rule.result.resources