Преамбула
Config Sprawl – конфигов становится все больше, каждый IaC инструмент «изобретает» свой диалект Yaml или Json. K8s, Helm, CloudFormation, Ansible, Istio, Spring Boot properties – современные проекты зачастую содержат больше конфигов чем кода и если для Java или Kotlin есть отличные IDE, линтеры и статические анализаторы кода вроде Sonarqube, то для IaC какого-то одного инструмента нет.
Существующие сканеры для IaC могут поддерживать например Ansible, Terraform и k8s, но не Nginx. Или они могут поддерживать только Nignx но не другие форматы.
Их сложно расширять и добавлять новые политики, на изучение DSL вроде rego можно потратить много времени, но если нужно будет решить какую-то не тривиальную задачу, то DSL никогда не сравнится с полноценным языком программирования, особенно если это Lisp.
Julia идеально подходит для решения такого рода задач. Давайте посмотрим как это можно реализовать.
k8s
На конфигах Kubernetes можно было бы остановится отдельно. Найти ошибку в манифестах K8s очень сложно, они могут занимать сотни килобайт на диске, а не правильная конфигурация может стоить очень дорого. Но это если пытаться контролировать качество в ручную, а для автоматизации YAML K8s подходит отлично.
В данном случае мы будем смотреть используется ли ca сертификат для controller manager на master ноде.
-
Пример неправильной конфигурации
-
Пример правильной конфигурации
Используем библиотеку YAML для работы с конфигами k8s:
function is_negative(manifest) spec = get(manifest, "spec", Dict()) containers = get(spec, "containers", []) for container in containers name = get(container, "name", "unknown") command = get(container, "command", []) args = get(container, "args", []) # Check if the command is kube-controller-manager if "kube-controller-manager" in command # Evaluate whether --root-ca-file is present in args has_root_ca_file = any(arg -> startswith(arg, "--root-ca-file"), args) # If --root-ca-file is missing, it's a negative case if !has_root_ca_file return true, name # Return true and the container name end end end return false, "" # Return false if no negative case is found end
Проверяем:
julia k8s.jl k8s/negative.yaml The manifest is positive. All required arguments are present. julia k8s.jl k8s/positive.yaml The manifest is negative. Container 'command-demo-container' is missing '--root-ca-file'.
OpenAPI
Проверяем использование OAuth2 для авторизации в OpenAPI.
-
Пример неправильной конфигурации
-
Пример правильной конфигурации
Используем библиотеку JSON для работы с конфигами OpenAPI:
# Check if the OpenAPI specification is negative function is_negative(openapi) # Extract the security section security = get(openapi, "security", []) # Extract the securitySchemes section components = get(openapi, "components", Dict()) security_schemes = get(components, "securitySchemes", Dict()) # Check if any security scheme in the security section is OAuth2 for sec in security for scheme in keys(sec) if haskey(security_schemes, scheme) scheme_type = get(get(security_schemes, scheme, Dict()), "type", "") if scheme_type == "oauth2" return true # Negative case: OAuth2 is used end end end end return false # Positive case: No OAuth2 is used end
Проверяем:
julia openapi.jl openapi/negative.json The OpenAPI specification is negative. OAuth2 is used for security. Julia-symbolics % julia openapi.jl openapi/positive.json The OpenAPI specification is positive. API keys are used for security.
Nginx
Nginx использует своей собственной формат конфигов вместо JSON и YAML, но это не является препятствием для Julia. Как и другие Lisp-подобные языки, Julia отлично подходит для работы с regex.
-
Пример неправильной конфигурации
-
Пример правильной конфигурации
При неправильное конфигурации модуля Stub Status, любой может получить доступ к чувствительной информации. Проверяем наличие auth_basic и auth_basic_user_file в конфиге:
# https://www.f5.com/company/blog/nginx/avoiding-top-10-nginx-configuration-mistakes # Check if the configuration is negative function is_negative(config) # Regex to match the /basic_status location block location_block_regex = r"location\s*=\s*/basic_status\s*\{([^}]*)\}" # Find all matches for the /basic_status location block matches = collect(eachmatch(location_block_regex, config)) for match in matches block_content = match.captures[1] # Extract the content inside the block # Check if the block contains auth_basic or auth_basic_user_file if occursin(r"auth_basic", block_content) || occursin(r"auth_basic_user_file", block_content) return true # Negative case: Authentication directives are present end end return false # Positive case: No authentication directives are present end
Проверяем:
julia nginx.jl nginx/positive.conf The configuration is positive. No authentication directives are present in the /basic_status block. julia nginx.jl nginx/negative.conf The configuration is negative. Authentication directives are present in the /basic_status block.
Таким образом можно написать свой собственный rules-based engine вроде SonarQube. Это лишь простые примеры, возможности Julia особенно если говорить об интеграции AI гораздо шире.
ссылка на оригинал статьи https://habr.com/ru/articles/891190/
Добавить комментарий