Ansible
Ansible es una plataforma de software libre para configurar y administrar ordenadores. Combina instalación multi-nodo, ejecuciones de tareas ad hoc y administración de configuraciones. Adicionalmente, Ansible es categorizado como una herramienta de orquestación.
Los archivos de órdenes se llaman "playbook" y tienen extensión "yaml".
El orden de prioridad de las configuraciones es de mayor a menor;
- Variables de entorno
- Keyword de Playbooks
- CLI
- Archivo de configuración
Requisitos
-
En el control node y managed node debe estar instalado Python.
-
En el managed node debe estar habilitado ssh y la autenticación por llave
Si la llave está cifrada se debe usar;
ssh-agent bash && ssh-add [path]/[priv_key]
-
En el control node; python-pipx (en algunas distros es; python3-pipx ó py3-pipx)
-
La máquina target debe tener sudo como passwordless
Se puede hacer que ansible solicite la contraseña para escalar con el argumento de "--ask-become-pass" al ejecutar el playbook.
Instalación
- Full
pipx install --include-deps ansible
- Minimal
pipx install ansible-core
- Versión específica
pipx install ansible-core==[version]
- Upgrade
pipx upgrade --include-injected ansible
- Dependencia de autocompletado
pipx inject --include-apps ansible argcomplete
bash -c "activate-global-python-argcomplete --user"
Configuración
Documentacion y variables de entorno
- Archivo de configuración
./ansible.cfg
/etc/ansible/ansible.cfg
~/.ansible.cfg
ó variable de entorno
ANSIBLE_CONFIG
- Home de Ansible
~/.ansible
- Generar archivo template de configuración
ansible-config init --disabled -t all > ansible.cfg
- Por defecto no loguea, si se quiere se debe habilitar en el cfg
log_path = [absolute_path]/[file]
loguea en el controller
- Conf para syslog, se debe habilitar en el cfg
syslog_facility = [ip]:[port]
- Verbose en el log, se debe habilitar en el cfg
log_verbosity = [0-3]
Conectividad a los target
Ansible necesita conectarse por ssh con llave, no admite contraseña
- Crear llave
ssh-keygen
- Copiar llave pública
ssh-copy-id -i [path_absoluto]/[llave].pub
Archivos playbook y hosts
- Verificar sintaxis del playbook
ansible-playbook [archivo].yml --syntax-check --check
- Correr playbook
ansible-playbook [archivo].yml -u [usuario_ssh] -t [playbook_tag_to_run] -l [specific_server_or_not_in_run] -k --verbose
"-k" indica que pregunte la clave de la llave ssh
"-t" y "-l" son opcionales
- Dry-run playbook
ansible-playbook [archivo].yml --check
- Archivo "hosts" que contiene el inventario de máquinas aplicar el playbook
ansible-playbook [archivo].yml -i [inventario_1] -i [inventario_n] -i [directorio_con_los_inventarios]
/etc/ansible/hosts
Ejemplo;
[[group_name]]
[name] [variable_n_to_use_in_playbook]=[value] ansible_host=[IP] ansible_port=[SSH_PORT] ansible_ssh_private_key_file=[aboslute_path_ssh_key]
[[group_name_2]]
[IP] [variable_n_to_use_in_playbook]=[value] ansible_port=[SSH_PORT] ansible_ssh_private_key_file=[aboslute_path_ssh_key]
[[group_name:childen]]
[parent_group-1]
[parent_group-N]
Así mismo, si los servers cambian con el tiempo hay dos opciones;
- Se crea un script que cambie el archivo cuando se ejecuta
- Se utiliza un plugin de inventario específicamente según si es AWS, Azure, GCP, OpenStack, etc.
- Archivo que tiene las variables de entorno a utilizar en el playbook
vars.yml
- Archivo playbook de ejemplo
Cada task es un plugin, por lo que ansible tiene para casi cualquier programa.
Los plugins se ven con
ansible-doc -l
Un plugin específico se obtiene su man con
ansible-doc [plugin]
La variable hosts es muy personalizable; url
---
- name: [string_name]
hosts: [group_name_or_all_or_IPs/CNAMES/GROUPS_separeted_with_:]
remote_user: [ssh_remote_user]
become: [true_to_execute_as_root]
vars:
[variable_X]: [value]
tasks:
- name: [task_name]
[plugin]:
[plugin_configuration]
[plugin_variable]: "{{ [variable_X] }}"
- name: Start service
ansible.builtin.service:
name: [servie_name]
state: started
- name: Copy file
ansible.builtin.copy:
src: [path]/[file]
dest: [path]/[file]
onwer: [owner]
group: [group]
mode: '[unix_numeric_mode]'
- name: Changeing file
ansible.builtin.file:
dest: [path]/[file]
mode: '[unix_numeric_mode]'
register: [return_variable]
failed_when:
- [return_variable].rc =! 0
- "[Error message]"
...
- name: Tasks block
block:
- name: Install trough legacy yum
ansible.builtin.yum:
name:
- httpd
- memcached
state: present
...
when: ansible_facts['distribution'] == 'CentOS'
rescue:
- name: Rescue tasks if above fail
when: ansible_failed_task.name == "[task_failed]"
ansible.builtin.debug:
msg: 'Message to show in verbose mode'
always:
- name: Tasks to run even if block fails
...
Se pueden incluir tantos "- name" con tasks y hosts como se quiera
Comandos de una linea
ansible [group_name] -m [plugin] -a "[plugin_arguments]"
Templates
Ansible usa el motor Jinja2 para procesar las variables que se encuentren en "vars" del playbook y luego proceder.
Ubicación;
./templates/[name].j2
Luego se llama por módulo. Lo que se ejecute se guardará en el dest del nodo slave.
ansible.builtin.template:
src: templates/[name].j2
dest: /tmp/hostname
Así mismo, dentro del playbook lo que está dentro de; "{{ xxx }}" forma parte de Jinja2 pero sin ir a su archivo específico.
Condicionales
Son todos los "when" debajo de cada task.
Están los "ansible_facts" que lo que hacen es chequear cosas comunes a todos los Linux, de ahí que existen;
- ansible_facts['os_family'] == "Debian"
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
- ansible_facts['lsb']['major_release'] | int >= 6
- ansible_facts['cpu_temperature']
entre otros.
- ansible_selinux.status == "enabled"
Se pueden combinar mediante paréntesis para crear condicionales juntos ('and') o excluyentes ('or')
También se pueden usar los register para evaluar una tarea y como salió;
- [register_name].rc != 0
- [register_name].stdout == ""
Retorno ('register') de una task
- name: Test play
hosts: all
tasks:
- name: Register a variable
ansible.builtin.shell: cat /etc/motd
register: [name_to_save_return_status]
AZ-900
- Cloud Computing
- [Modelo de responsabilidad compartida](#Modelo-de-responsabilidad compartida)
Glosario
- Escalado horizontal
Es el escalado de recursos de un mismo tipo en base a este último, no en base a las capacidades de cada uno. Por ejemmplo; el aumentar el número de VMs según la carga de trabajo.
- Escalado vertical
Es el escalado de las características de un recurso específico. Por ejemplo; el aumento de espacio de almacenamiento en un disco.
- Capital Expenditure (CapEx)
Gastos en temas de infraestructuras físicas. Por la devaluación natural de la nube, el costo neto se reduce con el paso del tiempo hasta que es amortizado.
- Operational Expenditure (OpEx)
Gastos en temas de infraestructuras bajo uso de la nube. Se paga lo que se usa. Generalmente todos los proveedores de la nube proveen descuentos en CapEx por pagos adelantados.
Permite una mejor predicción de costos y el desgrane de costos por recurso individual.
- Grupo de administración
Contiene suscripciones que contienen grupos de recursos y que contienen recursos.
Un directorio de Azure (osea una cuenta) puede tener hasta 10k de estos con hasta 6 niveles de profundidad cada uno.
- Suscripción
Grupos de recurso agrupados por un nombre que identifica una forma de pago específico para tales. También ayuda a delimitar que personas tienen acceso a que suscripciones (y por ende a sus grupos de recursos).
- Grupos de recursos
Recursos agrupados en grupos específicos para su mejor organización. No necesariamente tienen que pertenecer a la misma región o zona.
Cada grupo no es anidable a otro. Si es eliminado, se borra todo lo que contiene.
- Recurso
Instancia de un servicio. Cada recurso existe en un solo grupo de recursos, se pueden mover entre grupos.
Cloud Computing
Is the delivery of computing services over the internet, enabling faster innovation, flexible resources and economies of scale.
Modelo de responsabilidad compartida
Tipos de nubes
Nube privada
Características;
-
Las organizaciones pueden crear ambientes cloud en sus centros de datos.
-
La organización es responsable por las operaciones de los servicios que provee.
-
No provee acceso a los usuarios fuera de la organización.
Nube pública
Es un proveedor de la nube de terceros.
Características;
-
Es perteneciente al proveedor de la nube y de sus servicios.
-
Provee recursos y servicios a múltiples organizaciones y usuarios.
-
Es accedida mediante redes públicas segurizadas (como HTTPS).
Nube híbrida
Es un intermedio entre ambas anteriores. Al ser híbrida, le permite a una empresa el poder personalizar que se necesita de ambos mundos.
Comparación de los modelos de la nube
- Nube pública
Las aplicaciones pueden ser provistas y desprovistas rápidamente (dependiendo de la automatización, pueden ser hasta segundos) con una alta escalabilidad, predicibilidad y manejo.
Las organizaciones solamente pagan por lo que usan.
- Nube privada
El hardware debe ser comprado, aunque quede desproporcionado para los requerimientos.
Las organizaciones tienen control total sobrel a seguridad y los recursos.
Las organizaciones son responsables por TODO.
- Nube híbrida
Provee la mayor flexibilidad.
Las organizaciones determinen donde correr sus aplicaciones.
Las organizaciones controlan la seguridad, el cumplimiento legal y los requerimientos.
Tipos de nubes
- Infrastructure as a Service (IaaS)
Servidores virtuales, almacenamientos, redes y sistemas operativos.
- Platform as a Service (PaaS)
Provee ambientes para construir, desarrollar, probar y desplegar software, sin importar la infraestructura que va debajo.
Sistemas operativos y ambientes de desarrollo.
- Software as a Service (SaaS)
Software basado en apps por internet.
Tipos de cuentas
-
Cuenta normal
-
Cuenta de prueba
-
Cuenta gratuita para estudiantes
-
Sandbox para Microsoft Learn
Regiones
Región; un centro de datos para desplegar los servicios.
Azure ofrece más de 60 regiones.
Se debe elegir la región más cerca a donde se van a proveer los servicios, así mismo el uso de requerimientos legales (como el GPDR) obliga al uso de determinadas regiones para el cliente.
Zona de disponibilidad
Existen 3 por región. Son centros de datos en la misma región que provee protección física ante caidas, ya que están separados físicamente pero conectados por red.
Se suelen usar también para crear redundancia y alta disponibilidad en aplicaciones y datos críticos dentro de la misma región.
Pares de región
Regiones separados por, al menos, 300 millas. Proveen réplicas automáticas para algunos servicios ante la caida de una región, sincronizándose periódicamente.
Como todo servicio pago, hay que solicitarlo.
Regiones soberanas y gubernamentales
Regiones para gobiernos federales que están separadas del Azure normal (aisladas físicamente y solamente accesibles por personal autorizado).
Existen;
-
Azure US
-
Azure China
-
Azure Germany (recientemente deprecada).
Recursos y servicios
Compute Services
Todo lo que sea on-demand de recursos de discos, procesadores, memoria, red y sistemas operativos. Incluye cosas como; AKS (Azure Kubernetes Services), Azure container (PaaS), Azure Functions (simplemente es código que se ejecuta en un contenedor propio de Linux/Windows), "VM Availability sets" (conjuntos de disponibilidad para auto reinicio) y el auto escalado de máquinas virtuales.
-
Azure Bastion; Setup de configuraciones para que otras apps puedan usar RDP y SSH desde el portal.azure.com
-
Azure Virtual Desktop; servicio que utiliza Bastion para conectarse de forma remota por RDP o SSH.
Networking Services
Todo lo que sea networking; Azure Virtual Network, Virtual Private Network Gateway (VPN - Es usado como gateway entre Azure y otra red a nivell VPN), Azure Express Route (Es una VPN provista por un partner de Microsoft a nivel del ISP que no solamente enruta a Azure si no también a Office365 y otros servicios), Azure DNS,
Storage
Todo lo que sea almacenamiento; Storage Accounts (tienen nombres globales únicos, proveen acceso por internet, tienen servicios como contenedores/tablas/etc y opciones de redundancia - Locally Redundant Storage LRS, Zone redundant storage ZRS, Geo redundant Storage GRS, Geo-Zone Redundant Storage GZRS con triple réplica - ), Disk Storage (los volúmenes), Azure Files (disponibles por SMB), Azure Data Box (almacena hasta 80 teras de datos, puede funcionar como disaster recovery backups, usa TLS, puede migrar data FUERA de Azure por temas de compliance y migrar datos HACIA Azure), AzCpy CLI, Azure Storage Explrer, Azure File Sync,
Manejo de costos
El costo depende del tipo de recurso, su consumo, zona geográfica, del costo por recurso del Azure Marketplace, del tráfico saliente-entrante, del tipo de suscripción, y el mantenimiento.
- Billing Service - Azure cost Management
Para el control de gastos. Tiene segmentación por recurso y en totalidad por suscripción.
IAM, Gobierno, Gobernanza y compliance
- Azure Policy
Políticas tanto de acceso como de uso para poder cumplir con los requerimientos.
- Azure Migrate
Una plataforma unificada de amplio espectro en herramientas para la migración de datos.
- Azure Active Directory (AAD)
Provee; Authenticación, SSO, App Management, Business to Business (B2B - Identidades externas como apps empresariales y organizaciones externas para que inicien sesión), Business to Customer (B2C - Como B2B pero para usuarios finales), Device Management, Azure MFA, Conditional Access
- Azure Role-Based Access control (Azure RBAC)
Se apoya en AAD para garantizar privilegios en cada suscripción y sus respectivos servicios/recursos. No se aplica este nivel a las aplicaciones, ya que cada aplicación tiene su propio RBAC.
- Zero Trust
No se confia en absolutamente algo, se desconfia de todo y se chequea todo. En Azure el método de cero confianza se debe chequear con políticas condicionales.
- Defensa en profundidad
Un sistema de cada con múltiples niveles de protección a fin de que un ataque a una capa no comprometa a todo el sistema.
De arriba a abajo;
- Defensa física
- IAM
- Perímetro
- Red
- Computacional
- Aplicación
- Datos
- Lock Resources
Bloquear ciertos recursos aún cuando los permisos de X usuario le permitan realizar tales acciones.
Despliegue de recursos
- Azure Resource Manager (ARC)
Permite lo mismo que Azure pero integrando multinube, on-premise y edge mediante templates (en formato JSON).
- Cloud Shell y PowerShell
Soporte tanto en BASH como PowerShell
-
Azure REST Clients
-
Azure Blueprints
Planos de configuraciones (roles, políticas, templates de recursos, grupos de recursos) versionados.
Monitoreo
- Microsoft Defender for cloud
Detecta y bloquea malware, analiza los recursos buscando CVE's/malas configuraciones y recomendaciones.
- TAGS
"Key=value" sirven para organizar recursos y que puedan ser mejor reconocidos
- Azure Advisor
Monitorea los recurso y provee recomendaciones basadas en las mejores prácticas de seguridad, performance, costo y operacional.
- Azure Monitor
Chequea el estado de los recursos operacionales.
- Azure Health Service Check
Chequea el estado operacional de los servicios de Azure.
List users
az user list
Create user
az ad user create --display-name
--password
--user-principal-name
[--force-change-password-next-login {false, true}]
[--immutable-id]
[--mail-nickname]
Delete user
az ad user delete --id [user]
Get user member groups
az ad user get-member-groups --id [user]
See user details
az ad user show --id [user]
MFA State Users
- https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-userstates
Usuarios sin MFA
securityresources
| where type == "microsoft.security/assessments"
| extend source = trim(' ', tolower(tostring(properties.resourceDetails.Source)))
| extend resourceId = trim(' ', tolower(tostring(case(
source =~ "azure", properties.resourceDetails.Id,
source =~ "aws" and isnotempty(tostring(properties.resourceDetails.ConnectorId)), properties.resourceDetails.Id,
source =~ "gcp" and isnotempty(tostring(properties.resourceDetails.ConnectorId)), properties.resourceDetails.Id,
source =~ 'aws', properties.resourceDetails.AzureResourceId,
source =~ 'gcp', properties.resourceDetails.AzureResourceId,
extract('^(.+)/providers/Microsoft.Security/assessments/.+$',1,id)
))))
| extend status = trim(" ", tostring(properties.status.code))
| extend cause = trim(" ", tostring(properties.status.cause))
| extend assessmentKey = tostring(name)
| where assessmentKey == "57e98606-6b1e-6193-0e3d-fe621387c16b"
Windows vulnerabilties
Querys de logs
Ensure 'Do not show feedback notifications is set to enabled'
- Critical
- Registry, Policy Option
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "596d3922-71a7-49ce-b34b-1f5e63ff03da")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Enable insecure guest logons' is set to 'Disabled'
- Critical
- Registry, Policy Option
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "09ed81b2-8dba-4009-84f9-dcfd6009ed0d")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Enable 'Scan removable drives' by setting DisableRemovableDriveScanning (REG_DWORD) to 0
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "081da702-ce92-480f-aa68-af49bf5b94db")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Bypass traverse checking
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "a30f6d7d-f3dc-442c-8a1f-921123c6250c")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Configure 'Access this computer from the network'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "3f2d92c2-5850-4f2d-b245-f5089aa975dd")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Microsoft network server: Digitally sign communications (if client agrees)' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "b625a003-d015-436e-89fb-fb2dfe71ae0f")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Disallow WinRM from storing RunAs credentials' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "5fc2dc21-a630-45ee-a62d-5e3d87a45a84")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Interactive logon: Do not display last user name' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "9e11215f-9b0b-4ca6-ad5b-d1a0c989af36")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Audit Process Creation' is set to 'Success'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "6b3dc518-61f4-4a47-920c-0411674596a0")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Domain: Firewall state' is set to 'On (recommended)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "4a459b04-79c8-4fb3-9ea0-cf4b77ee58d7")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Network access: Do not allow anonymous enumeration of SAM accounts and shares' is set to 'Enabled' (MS only)
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "87822480-3af9-4cf1-b0d2-93ceb957b129")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'System: Specify the maximum log file size (KB)' is set to 'Enabled: 32,768 or greater'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "3e20b64c-0356-4e95-ba4e-2ebd51e10bb9")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Domain: Outbound connections' is set to 'Allow (default)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "68757cac-7589-4ed9-a162-27e5926f2deb")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Network security: LAN Manager authentication level' is set to 'Send NTLMv2 response only. Refuse LM & NTLM'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "315cc7e3-7252-47ce-af2f-9abf243fac16")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Do not allow passwords to be saved' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "0979b47f-fbbf-46ad-8def-768256fa012a")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Public: Settings: Apply local connection security rules' is set to 'Yes'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "10a43735-527c-46f0-a95c-954a8f9594dc")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Microsoft network client: Digitally sign communications (always)' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "41a8be7d-69bd-48f4-ae77-9568cf7b15d1")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'User Account Control: Admin Approval Mode for the Built-in Administrator account' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "967531f7-69cd-4a38-a517-3ebf4e5284cd")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Minimum password length' is set to '14 or more character(s)'
- Critical
- REgistry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "bc9d4fef-9e33-48fc-bcbd-b53e60caf4a2")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'User Account Control: Behavior of the elevation prompt for standard users' is set to 'Automatically deny elevation requests'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "ea132d56-9c29-4d2a-bc92-fc81f616e540")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'User Account Control: Switch to the secure desktop when prompting for elevation' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "21a9a771-ef63-419c-bee4-8619f19a77ff")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Deny log on through Remote Desktop Services' is configured
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "60e0c2c9-0b14-44fe-83d6-2b7095e06674")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Turn off Autoplay' is set to 'Enabled: All drives'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "d0f025af-b24b-49ab-9b75-60f485ed5407")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Deny log on as a batch job' is configured
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "49258884-b2f0-4a4e-b66a-6954bb8473bf")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Include command line in process creation events' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "1648f727-644b-4454-a472-b1a803342e8a")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode' is set to 'Prompt for consent on the secure desktop'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "fc8a4401-ff7a-4a6d-add4-758acce6b76c")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Password must meet complexity requirements' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "299d1595-5ab2-4ef5-b287-6477c0df5178")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Deny log on locally' is configured
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "b7432fc2-51ba-4ddf-83dd-ca7f92e670c1")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Enforce password history' is set to '24 or more password(s)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "dad8097d-db46-4df3-9839-a8504e60c878")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Configure Solicited Remote Assistance' is set to 'Disabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "b17eabc0-5d73-4861-acc8-d5b97bc53f12")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Enable RPC Endpoint Mapper Client Authentication' is set to 'Enabled' (MS only)
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "7983c8b6-ceca-4475-b58c-5b1d7745cde3")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Public: Outbound connections' is set to 'Allow (default)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "753e721c-be46-47f4-9571-8509ca5c1e61")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Setup: Specify the maximum log file size (KB)' is set to 'Enabled: 32,768 or greater'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "5bfb71c2-897f-4ccb-b7d5-7181b1f2527a")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Network security: Minimum session security for NTLM SSP based (including secure RPC) clients' is set to 'Require NTLMv2 session security, Require 128-bit encryption'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "2a074d39-eee4-4bfe-b1e7-4132c033a762")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Require secure RPC communication' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "01d9a108-3379-4c5a-8236-1a724bcccff1")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Audit Removable Storage' is set to 'Success and Failure'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "b88b1d85-5f3c-4235-91ab-6d8b5e767311")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Disallow Autoplay for non-volume devices' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "420cf8af-038e-4d06-89a4-aa8bfaec0191")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Configure 'Allow log on locally'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "051545a4-179e-4c04-9e9b-8f33821ef36f")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Security: Specify the maximum log file size (KB)' is set to 'Enabled: 196,608 or greater'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "c139db2e-8dea-418e-bf7c-372ec0278e31")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Network security: Minimum session security for NTLM SSP based (including secure RPC) servers' is set to 'Require NTLMv2 session security, Require 128-bit encryption'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "6ed9ad58-c9de-4a8b-9512-8fe5421ac8a7")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Public: Firewall state' is set to 'On (recommended)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "5e33a15a-7db0-4a1d-b771-db3764f3a625")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Microsoft network server: Digitally sign communications (always)' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "032b5976-1c4b-4c68-bc5d-0c65e35306b2")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Always prompt for password upon connection' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "d9794f70-e03c-40e5-a812-d2878c0eb6d5")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Application: Specify the maximum log file size (KB)' is set to 'Enabled: 32,768 or greater'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "e7e377d1-d6e0-4acc-a073-75b3243a646e")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Configure 'Deny access to this computer from the network'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "fbe348fd-0402-4e31-8482-66ae9ae82ea2")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Domain: Settings: Apply local connection security rules' is set to 'Yes (default)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "88338d83-a4e2-421b-b3f3-db6bd2c694a0")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Set the default behavior for AutoRun' is set to 'Enabled: Do not execute any autorun commands'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "7869ddef-04ab-4cc5-90f2-5e6fd1540cba")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Private: Firewall state' is set to 'On (recommended)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "c8e1851a-fb32-4197-a1c0-d9da262d37f1")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Disallow Digest authentication' is set to 'Enabled'
- Critical
- REgistry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "34edb7eb-697c-4be9-8830-5aa5b031372e")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Windows Firewall: Private: Outbound connections' is set to 'Allow (default)'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "c98cfb4e-113f-4a25-a080-ab1f7d0f8f38")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Ensure 'Network security: Allow Local System to use computer identity for NTLM' is set to 'Enabled'
- Critical
- Registry, Policy Options
SecurityBaseline
| where AnalyzeResult == "Failed" and (BaselineRuleId =~ "e7d5034f-5652-4180-90c8-c49130acb3c6")
| where tolower(SubscriptionId) in ("SUBSCRIPTION", "SUBSCRIPTION") or isempty(SubscriptionId)
| summarize AggregatedValue = dcount(SourceComputerId) by SourceComputerId, Computer
| limit 1000000000
Bash
Bash = Bourne Again Shell
- Proyecto; GNU
- URL; https://www.gnu.org/software/bash/
Los comentarios en Bash se ponen con los numerables; # así se puede comentar cosas sin que den error en el script (por que no se procesan básicamente)
Scripting
No te hagas la cabeza, el scripting de una shell es usar el 95% del tiempo los condicionales y el otro 5% es usar variables en comandos que uno necesita.
- Extensión de archivo; sh
- Inicio de archivo - header
#!/bin/bash
- Variables
[variable_name]=[valor]
Las variables creadas luego se referencian en el código con;
$[variable_name]
- If / elif / else
El único mandatorio es "if", "elif" es para hacer una segunda verificación.
if [ [condición] ]; then
[acción_si_condición_verdadera]
elif [ [condición_2] ]; then
[acción_si_condición_verdadera]
else
[acción_si_ninguno_verdadero]
fi
La condición tiene formas según lo que se quiera comparar;
-
Si $a y/o $b son numerales, se puede usar;
- "-lt" para si $a es menor ("less than") a $b
- "-le" para si $a es menor o igual a $b
- "-eq" para si $a es igual a $b
- "-ne" para si $a NO es igual a $b
- "-gt" para si $a es mayor a $b
- "-ge" para si $a es mayor o igual a $b
-
Si $a y/o $b son strings, se puede usar;
- "==" para si $a y $b son iguales
- "!=" para si $a y $b son diferentes
- "<" ó ">" para menor o mayor respectivamente según el orden lexicográfico (no es igual al orden numérico)
- "-z" para si $a ó $b es una cadena vacía
- "-n" para si $a ó $b NO es una cadena vacía
-
Sí $a y/o %b son archivos, se puede usar;
- "-e" para sí $a ó $b existe (se recomienda que sean Path absolutos)
- "-f" para si $a ó $b es un archivo regular (osea; no es un directorio, dispositivo, etc). Sirve también para saber si el archivo existe.
- "-d" para si $a ó $b es un directorio
- "-r" para si $a ó $b es un archivo legible (lo saca por permiso)
- "-w" para si $a ó $b es un archivo escriturable (lo saca por permiso)
- "-x" para si $a ó $b es un archivo ejecutable (lo saca por permiso)
- "-s" para si $a ó $b tiene un tamaño mayor que cero
-
Por último, se pueden anidar varias condiciones
- "&&" para anidar dos o más condiciones, cada una debe estar en su propio set de "[ [condición] ]"
- "||" para hacer un "ó" exclusivo de dos o más condiciones, apenas se encuentre con la primera que sea verdadera la condición procede y deja de verificar las siguientes, cada una debe estar en su propio set de "[ [condición] ]"
- "!" para hacer una negación de la condición de verificación, a diferencia de los dos anteriores este debe ir dentro del set.
-
Consideraciones
Si por esas casualidades llegamos a tener en la condición una cadena (string) no guardada en una variable previamente, entonces debemos poner en el set un "[ ]" doble, quedando; "[[ [condición] ]]" ya que si no dará error.
- Retornos de comandos
Como bash almacena en una variable el retorno del comando, lo podemos usar para trabajarlo.
- Guardar la salida (stdout) de un comando en una variable
[variable]=$( [comando_a_guardar_su_stdout] )
- Leer la entrada del usuario
read [variable_a_guardar_la_entrada]
- Verificar existencia
Archivo
test -f [path_absoluto_archivo]
-f [variable_o_path_absoluto]
Directorio
test -d [path_absoluto_directorio]
-d [Variable_o_path_absoluto]
- Ciclo "for"
El ciclo "for" de bash es igual que en Python, Rust y otros; lo que hace es iterar sobre los valores y en cada iteración ejecuta el código con ese valor correspondiente.
Asi mismo separa los valores por "nuevalínea" de esa manera si la salida de un comando tiene 3 párrafos (aunque sean de pocas palabras), entonces la salida tiene 3 valores (cada párrafo) y en cada iteración trabajará sobre cada uno de ellos.
variable_1=$(ls /)
for [variable_de_iteración] in $variable_1; do
[comandos_de_trabajo_en_cada_iteración]
done
También bash posee la capacidad de trabajar indicando archivos de un directorio. Al igual que en todos los Unix, tenemos la capacidad de utilizar el * (llamado wildcard) para indicar todo lo que coincida con algo, en el caso de abajo todo lo que tenga extensión ".md"
for [variable_de_iteración] in /home/usuario_linux/Documentos/*.md; do
[comandos_de_trabajo_en_cada_iteración]
done
Ejemplo
#!/bin/bash
echo "Ingrese el documento a verificar"
read $doc
if [ ! -f $doc ]; then
echo "El archivo no existe"
exit
fi
# Extraemos el peso separando por espacios hasta el campo 6 y luego extrae la letra, para dejar el número solamente
len=$(ls -lh | grep document.pdf | cut -d' ' -f6 | tr -dc '0-9')
if [ -r $doc ]; then
echo "El documento es legible"
else
echo "El documento no es legible"
fi
###############
if [ $len -ne 0 ]; then
echo "El archivo no tiene peso vacio"
else
echo "El archivo tiene peso vacio, saliendo erroneamente"
return 1
fi
## Lee recursivamente /usr
variable_iterativa=$(ls -R /usr/*)
## Itera en cada nueva linea almacenando en valor en la variable "i" y luego ejecuta
for i in $variable_iterativa; do
if [ -f $i ]; then
echo $i es un archivo
elif [ -d $i ]; then
echo $i es un directorio
fi
done
DataDog
-
Alternativa paga a Prometheus y Grafana
-
Parece que tiene mala documentación
-
SaaS, hecho en Go
-
Monitorización, alertas y métricas (con logs) de servidores, BBDD, tools, networking y servicios
-
Cumple las mismas funciones que Jira y Confluence
-
AWS, Azure, GCP, Openshift y OpenStack
-
Ayuda a ver toda la infra completa en un solo lugar
-
Utiliza operadores como agentes para analizar y monitorizar
-
Cada usuario puede tener su propio dashboard personalizado
-
Soporta una amplia gama de productos a integrar por defecto mediante los agentes
-
Soporta análisis de código (con Code Analysis) en GitHub o editor de texto
-
CoScreen
-
Quality Gates; QA para código de software soporta: Tests, Pipelines, Static Analysis y Software Composition Analysis
-
User simil test; Synthetic Monitoring
-
El agente completo es datadog-agent y dogstatsd es un módulo especializado para métricas
Otros módulos son el datadog-trace-agent (para la performance y trousbleshoot de las apps) y el datadog-process-agent para los procesos y contenedores
Usa los puertos 5000-5002 y 8125
-
Service y binario del agent; datadog-agent
-
Configuración del angent; /etc/datadog-agent/datadog.yaml
-
Configuración para integraciones del agent; /etc/datadog-agent/conf.d/
-
Log del agent; /var/log/datalog
Compilación
as [archivo].s -o [salida_object].o
ld [object].o -o [salida_binaria]
Inspección
La inspección tiene por objeto ver todo en ensamblador (-d):
aarch64-linux-gnu-objdump -d
Misc
- Los comentarios van con //, como en C puro.
- Mientras que "[r2, #4]" indica 4 movimientos en el registro r2, un "#4" solo indica el número entero 4.
Estructura
Los archivos en ensamblador van con la extensión ".s" y llevan la siguiente estructura;
-
Sección ".text"
Indica el código ejecutable del programa.
-
Directiva ".global XXX"
Indica que la función ó variable "XXX" está expuerta al exterior (como el "pub" de Rust).
-
Directiva ".type XXX, YYY"
Indica que tipo "YYY" es la función ó variable expuerta, los valores pueden ser;
- "function"
-
Directiva ".p2align Z"
Indica que el código debe ir alineado en la memoria usando "Z" bytes.
"Z" debe ser número entero que coincida con la arquitectura de bits del procesador;
- 4 - 8 - 16 - 32 - 64 - 128
-
Función/label "XXX:"
Indica el comienzo de la función "XXX".
Se recomienda que todo el código de la función tenga 3 espacios como sangría.
Siempre debe retornar ("ret") y asegurarse de devolver a su estado original los registros usados. El registro x0 es el encargado de funcionar como retorno.
En caso de no tener "ret" una función, hará que se ejecute la siguiente y así hasta que se encuentre uno. Esto es lo que se llama; "funciones anidadas".
Por ejemplo, funciones separadas que no se ejecutarán hasta ser llamadas específicamente;
funcion_1:
mov x3,x0
ret
funcion_2:
cmp x3,#1
b.eq funcion1
ret
Por ejemplo, funciones anidadas que al ser ejecutada una continuará
ejecutando las siguientes;
funcion_1:
mov x3,x0
ret
funcion_2:
cmp x3,#1
b.eq funcion1
ret
Registros y variables
Los registros son las variables del propio chip, ARM tiene los siguientes;
ARM | Registro | Alias | Uso |
---|---|---|---|
ARMv8 | W0-W30 | - | Propósito general (32 bits) |
ARMv8 | X0-X30 | - | Propósito general (64 bits) |
ARMv8 | WZR | - | Zero register (32 bits) |
ARMv8 | XZR | - | Zero register (64 bits) |
ARMv8 | WSP | - | Current stack pointer (32 bits) |
ARMv8 | SP | - | Current stack pointer (64 bits) |
ARMv8 | PC | - | Program counter (64 bits) |
ARMv1-8 | CPSR | – | Current Program Status Register |
- Wn está englobado dentro del Xn; W0 está como 32 bits dentro del X0 de 64 bits.
- El WZR ó XZR .
- Antes de usar un registro se debe cargar el valor en él (ldr ó str).
- El estándar de llamado procedural de ARM64 estipula que los datos a devolver deben estar sí o sí en el registro x0
Los registros pueden almacenar los datos en little endian (derecha a izquierda) ó big endian (izquierda a derecha).
Los registros tienen su propio espacio de memoria interno, ya que los mismos están circunscritos en el propio procesador por lo que no necesitan en si de la RAM. Por lo que "str" saca de la memoria ese dato y se lo asigna al registro destino, mientras que "ldr" hace lo mismo pero sin eliminarlo de la memoria RAM haciendo solamente una copia al registro.
En caso de necesitar más, se puede usar segmentos de la RAM para almacenar.
El registro CPSR es muy importante; ya que en si mismo coniene todos los flags así como los estados del procesador;
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
N | Z | C | V | Underflow | - | Jazelle | - | Greater than/or Equal | - | Endianness | Abort disable | IRQ disable | FIQ disable | Thumb | CPU Mode |
-
Negative (N)
Se habilita si el resultados de la operación es un número negativo.
-
Zero (Z)
Se habilita si el resultado de la operación es un cero.
-
Carry (C)
Se habilita si el número requiere un bit adicional para ser representado completamente. Véase, cuando el número repesentado requiere más de 64 bits para ser representado.
No diferencia números positivos de negativos.
-
Overflow-Underflow / Saturation (V)
Se habilita si el resultado de la operación atimética no puede ser representado con el rango de memoria usado.
El rango va desde -2^63 a 2^63 (considerando que un bit, el primero, se usa para representar positivo o negativo), cualquier número fuera de ese rango es overflow ó underflow.
-
Jazelle
Se utilizaba en versiones viejas de la arquitectura; ARMv5 y v6.
Permitía que código bytecode de Java se ejecutara sin necesidad de una JVM (Java Virtual Machine) de por medio. Desde ARMv7 quedó obsoleo y remplazado por ThumbEE, que a su vez fue eliminado en ARMv8.
-
Endianness
Si está marcado en cero (0) se está usando little-endian. Si está marcado en uno (1) se está usando big-endian.
-
Thumb
Si está marcado, significa que se está usando el modo Thumb y no el ARM.
El modo Thumb es un modo de 16bits del procesador, y a diferencia del modo ARM (que es 32 o 64 bits) no tiene soporte per se para condiciones de ejecución. Salvo Thumbv2 que sí tiene algunas condiciones.
-
Mode-bis (M)
Indica el modo de ejecución actual del procesador. Puede tomar los siguientes valores:
- 0b0000: Modo Usuario (User)
- 0b0001: Modo FIQ (Fast Interrupt Request)
- 0b0010: Modo IRQ (Interrupt Request)
- 0b0011: Modo Supervisor
- 0b0100: Modo Abort
- 0b0101: Modo Undefined
- 0b0110: Modo System
- 0b0111: Modo Monitor
-
Abort-disable (A)
Deshabilita las excepciones de tipo Abort. Se utiliza para impedir que determinadas operaciones generen excepciones Abort, lo que puede ser útil para proteger la integridad del sistema o para realizar operaciones críticas sin interrupciones.
-
IRQ-disable (I)
Deshabilita las interrupciones IRQ (Interrupt Request). Se utiliza para impedir que el procesador sea interrumpido por eventos externos, lo que puede ser necesario para realizar operaciones sensibles al tiempo o para proteger regiones críticas de código.
-
FIQ-disable (F)
Deshabilita las interrupciones FIQ (Fast Interrupt Request). Las interrupciones FIQ tienen mayor prioridad que las IRQ y se suelen utilizar para eventos críticos que requieren atención inmediata. Deshabilitarlas puede ser necesario para garantizar la ejecución ininterrumpida de tareas sensibles.
Memoria
La primera posición de memoria es la dirección; 0x00000000
Cada registro o variable puede almacenar en la memoria de a estos rangos;
-
byte; 8 bits
Las instrucciones que llevan una "b" al final indica que el tipo de dato con el que operan es un "byte".
Si es "sb" indica que un "signed byte"; puede contener positivos y negativos. Si no está aclarado que un "signed byte" solamente puede contener como valores; cero y positivos.
-
half word; 16 bits (2 bytes)
Las instrucciones que llevan un "h" ó "sh" al final indican que el tipo de dato con el que operan es un "half word".
-
word; 32 bits (4 bytes)
Las instrucciones que operan con words no llevan un indicativo.
-
dword; 64 bits (8 bytes)
El primer bit se le llama LSB (Low Significant Bit) y el último MSB (Most Significant Bit), se lee de derecha a izquierda.
En ARM las operaciones de memoria se consideran las posiciones:
ldr r0, [r2, #4]
El "#4" es una forma de indicar que la instrucción debe desplazarse 4 posiciones de memoria en el registro "r2". Cada posición son 8 bits.
-
ARMv7
Como la memoria está alineada a 32 bits, cada posición de memoria está separada por 32 bits.
Ergo; #4 = 4*8 = 32, lo que al moverse 32 bits hace que pase a la siguiente posición de los valores en el registro "r2" (un vector es).
Por lo tanto, el desplazamiento de 4 posiciones corresponde a la segunda posición de memoria.
-
ARMv8
Como la memoria está alineada a 64 bits, cada posición de memoria está separada por 64 bits.
Ergo; #4 = 4*8 = 32, lo que al moverse 32 bits hace que siga estando en la misma posicon de los valores en el registro "r2" (un vector es).
Por lo tanto, el desplazamiento de 4 posiciones corresponde a la misma posición de memoria (la primera) en ARM64.
Almacenaje
Hay dos formas en que se guarda la información en la RAM; little endian ó big endian.
ARM tiene la capacidad de usar uno u otro, como se vió en el bit del registro CPSR.
La diferencia viene en que; en Big Endian el byte más significativo es el primero en almacenarse, mientras que en Little Endian es el byte menos significativo.
Dicho en criollo; en big endian se lee y almacenan los bytes leyendo de izquierda a derecha, mientras que en little endian se lee y almacenan leyendo de derecha a izquierda.
Organización
La memoria RAM puede organizarse de dos formas diferentes;
-
Heap
El heap es una estrucura que hace un seguimiento de la memoria que usa un programa y es capaz de aumentar o disminuir la memoria asignada al mismo para evitar un sobre uso o una limitación de memoria al programa.
-
Stack
El stack hace uso del LIFO (Last-In, First-Out; Último en entrar, primero en salir.) para almacenar datos.
En ARM el registro R13, o también SP (Stack Pointer) contiene la posición del tope del stack.
El stack se usa mucho cuando se necesita guardar datos para luego restaurarlos; ocurre principalmente cuando una función "A" utiliza unos determinados registros "X" e "Y" y luego llama a otra función "B" que utiliza los mismos registros, para permitir que al finalizar "B", "A" pueda seguir utilizando sus registros los mismos se ponen (push) en el stack y luego se sacan (pop) para ser restaurados.
En ARM el registro R15, o también PC (Program Counter) indica la dirección en RAM (el offset) de la siguiente instrucción a ser ejecutada. La modificación del PC y su uso se conoce como "branching" y/o "jumping". El valor que va a tomar el registro R15 depende de las condiciones que se seteen (de ahí vienen el if-else) como; si el resultado de la operación fue cero (Zero; Z), negativo (N, en donde el bit más significativo está activo; 1), si hay un carry (C) habilitado (que es cuando sobran números por aumento de valor superior al máximo) o si hay un overflow dada en alguna operación aritmética (V). Tales condiciones (llamadas; "flags") se almacenan en el registro CPSR (Curent Program Status Register).
Operaciones
- Copia de un registro/valor/offset origen a un registro destino
mov [registro_destino],[registro_valor_o_offset_origen]
- Suma
add [destino],[valor_1],[valor_2]
- Resta (no actualiza NZCV)
sub [destino],[operando_registro_1],[operando_registro_2]
- Resta (actualiza NZCV)
subs [destino],[operando_registro_1],[operando_registro_2]
- Multiplicación
mul [destino],[operando_registro_1],[operando_registro_2]
- División 32 bits, sin contar signo
udiv [cociente],[dividendo],[divisor]
Si el divisor es cero, el cociente también lo será.
- División 64 bits, contando signo
sdiv [cociente],[dividendo],[divisor]
Si el divisor es cero, el cociente también lo será.
Se puede generar un overflow si se hace una división de un entero mínimo por "-1", en tal caso se sobre escribirá el resultado a cero.
- Retorno a la función que lo llamó (interna ó externa)
ret
- Cargar el valor de "YYY" en el registro "XX" sacandolo de la RAM
ldr XX, YYY
Si es dirección de memoria se usa [YYY]
- Comparar dos valores (lo hace ejecutando la diferencia)
cmp [valor_variable_1],[valor_variable_2]
Si son iguales habilita (poner en 1) el flag Z, si no son iguales lo deja deshabilitado.
Si el segundo operando es mayor que el primero, entonces se habilita el flag N (negativo). Debido a que la diferencia da un número negativo.
Dicho lo anterior, si el primer operando es más grande entonces N queda en deshabilitado y N también.
- Saltar a la funcióń/offset "X" si el flag Z (zero) no está habilitado
b.ne X
El acrónico "bne" significa "branch if not equal".
- Saltar a la funcióń/offset "X" si dos registros/valores no son iguales
b.ne [registro_valor_1],[registro_valor_2], X
- Saltar a la función/offset "X" si el flag N (negative) está habilitado
b.lt X
b.le = "Branch i Less Than"
Ejemplos
Factorial de un número
my_function:
mov x3, x0
loop:
subs x3, x3, #1
cmp x3, #0
b.eq finish
mul x0, x0, x3
b loop
finish:
ret
Energía quinética de un objeto (KE =1/2 * m * v^2)
my_function:
mul x2, x1, x1
mul x3, x2, x0
mov x4, #2
udiv x5, x3, x4
mov x0, x5
ret
Cálculo factorial
my_function:
mov x3, x0
loop:
subs x3, x3, #1
cmp x3, #0
b.eq finish
mul x0, x0, x3
b loop
finish:
ret
Helm
- Añadir repositorio
helm repo add [repo_name] [repo_url]
- Instalar un deployment
helm install [nombre_local] [repo_name]/[chart] --version [version] --namespace [namespace_to_install]
Para indicar un archivos de valores "-f [archivo].yml"
- Ver valores para instalar en el deployment
helm show values [repo_name]/[chart]
JavaScript
Es un estándar (ECMAScript), por lo que cada engine puede expandirlo.
-
TypeScript
Creado por Microsoft añade que se tengan que especificar el tipo de dato.
TypeScript usa la extensión ".ts"
Al estar pensado para scripting, sigue el mismo esquema que BASH; solo ejecuta funciones si son llamadas directamente, el resto lo procesa todo en tiempo de ejecución.
Deno
Instalar Deno Engine
curl -fsSL https://deno.land/install.sh | sh
Ejecutar un archivo
deno run [archivo].ts
- "--allow-net" para permitir que el archivo use red
- "--config" para especificar otro archivo de configuración deno.json ó deno.jsonc
Vendor - Dependencias en local
deno cache [archivo].ts
Archivos de proyecto
-
deno.json ó deno.jsonc
Contiene las dependencias y configuración del proyecto para el compilador, formateador y enlazador.
Si contiene "tasks" permite acortar comandos largos en una simple tarea. Las tareas se corren con; "deno task [name]"
Si contiene "fmt" permite personalizar como va a formatear si se corre un "deno fmt".
Si contiene el tuple "exclude" se puede indicar que directorios no se quiere incluir por parte de la ejecución de Deno.
{
"compilerOptions": {
"allowJs": true,
"lib": ["deno.window"],
"strict": true
},
"lint": {
"include": ["src/"],
"exclude": ["src/testdata/", "src/fixtures/**/*.ts"],
"rules": {
"tags": ["recommended"],
"include": ["ban-untagged-todo"],
"exclude": ["no-unused-vars"]
}
},
"fmt": {
"useTabs": true,
"lineWidth": 80,
"indentWidth": 4,
"semiColons": false,
"singleQuote": true,
"proseWrap": "preserve",
"include": ["src/"],
"exclude": ["src/testdata/", "src/fixtures/**/*.ts"]
},
"lock": false,
"nodeModulesDir": true,
"unstable": ["webgpu"],
"npmRegistry": "https://mycompany.net/artifactory/api/npm/virtual-npm",
"test": {
"include": ["src/"],
"exclude": ["src/testdata/", "src/fixtures/**/*.ts"]
},
"tasks": {
"start": "deno run --allow-read main.ts"
},
"imports": {
"oak": "jsr:@oak/oak"
},
"exclude": [
"dist/"
]
}
TypeScript - JavaScript
Comentarios
// Esto es un comentario
Importar
Deno soporta tanto NPM como JSR.
Consideración; la función debe estar dentro de "{}" cuando el módulo no tiene un "export default function ....."
Las funciones que no necesitar las "{}" en el import son las que tienen en su módulo un el default.
- De otros archivos
import [Struct],[function_N] from "./[archivo].ts";
- De la stdlib
import [Function] from "[package_registry]:@std/[module]"
Importar desde JSR
import [Function] as mod from "jsr:@[user_or_organization]/[module]"
Importar desde NPM
import [Function] from "npm:[module]@[version]"
Variables y constantes
-
Variable
Alcance local en una función
var [var_name]: [var_type_if_is_Typescript] = [value]
-
Constante
Alcance global cuando son variables declaradas fuera de una función pero con alcance de bloque. Funciones incluidas.
Solo pueden ser declaradas una vez dentro de su alcance.
{
const [var_name]: [var_type_if_is_Typescript] = [value]
}
Las constantes no pueden actualizarse a futuro (por que hace un shadowing en realidad, que es una redeclaración a bajo nivel).
-
let
Al igual que en Rust, sirven para declarar variables. Y al igual que en "const" tiene alcance de bloque pero pueden actualizarse a posteriori.
{
let [var_name]: [var_type_if_is_Typescript] = [value]
}
Structuras
interface [struct_name] {
[var_name1]: [type];
[var_name2]: [type];
}
const [instance_name]: [struct_name] = {
[var_name1]: [value],
[var_name2]: [value],
}
Tipos
let var1 = 5;
let var2 = 12.1;
let var3 = 'string1';
let var4 = "string2";
let var5 = true;
let var6 = false;
let var7 = 'c';
Se puede formatear un retorno de string sin guardar previamente en una variable;
return 'Hello, ${[var_or_struct]}';
Funciones
function [func_name]([var_name]: [type]): [return_type]{
[operations];
return [return_value];
}
Si a la función se le añade "export function ...." entonces se vuelve pública y puede ser llamada desde otros archivos.
Equivalente al "pub" en Rust.
Si a la función le añadis "async" la volves eso; asíncrona, luego la variable que va a contener el retorno debe tener un "await" antes de su llamado.
Condicionales
- Para booleanos es un triple = para verificar valores
- Para el resto de tipos de datos son dobles = solamente
If - else if - else
if (var1 > var2) {
console.log("el valor de var2 es mayor que var1." + '\n' + "Var2;" + var2 + '\n' + "Var1;" + var1);
} else if (var1 > var2) {
console.log("el valor de var2 es menor que var1." + '\n' + "Var2;" + var2 + '\n' + "Var1;" + var1);
} else if (var1 == 0 || var2 >=12) {
console.log("var1 es cero ó var2 es mayor o igual a 12" + '\n' + "Var2;" + var2 + '\n' + "Var1;" + var1);
} else if ( var1 != var2 ) {
console.log("var1 no es igual a var2");
} else {
console.log("sin valores de coincidencia");
}
Switch
switch (var1) {
case 0:
case 1:
console.log("el valor de var1 es 0 ó 1");
break;
case 5:
console.log("el valor de var1 es 5");
break;
default:
console.log("sin valores de coincidencia");
break;
}
While
while (var5 === true) {
console.log("var 5 es verdadero");
}
/// Loop infinito
while (true){
console.log("loop infinito");
}
/// Loop combinado
let temporal1 = 0;
while (var5 === true && temporal1 <= 5){
console.log("loop finito");
temporal1 += 1;
}
For
Es igual que en C: inicio; condicion; modificacion final Al igual que con los if/else, pueden combinarse unos dentro de otros
for (let i = 0; i <= 15; i++){
console.log("i = " + i + ".");
}
/// Breaks combinados
/// Cuando en un bucle se usa el break se asegura que el resto no se procesa y que se
/// termina el ciclo
for (let j = 0; j <= 15; j++){
// Acá el if hace que no se impriman los mayores a 10
if ( j > 10) {
break;
}
console.log("j = " + j + ".");
}
/// El continue en cambio, hace que el ciclo se termine y se inicie el nuevo
for (let e = 0; e <= 15; e++){
// Acá el if hace que solamente se impriman los mayores a 10
if ( e < 10) {
continue;
}
console.log("e = " + e + ".");
}
Arrays
El estándar de javascript lo toma como una sucesion finita de chars con eso se puede hacer uso de cada uno de sus componentes/chars.
Se cuenta desde cero, por que va por posiciones
let string1 = "Cadena de texto 1";
/// imprimirá "C"
console.log("caracter cero; " + string1[0]);
/// también se puede contar desde atrás
/// imprimirá "!"
/// el método "length" devuelve el largo de la cadena
console.log("ultimo caracter; " + string1[ string1.length -1 ]);
/// Si se utiliza un array que está en una posición inválida se obtiene un error de tipo
/// "undefined"
console.log("caracter fuera de rango; " + string1[99999]);
/// Así mismo los valores pueden ser asignados a otras variables
/// La primera toma el primer caracter
/// La segunda toma el rango desde cero hasta la posicion numero 5
let varbuffer = string1[0];
let varbuffer2 = string1[0,5];
console.log("Buffer1 es;" + varbuffer + '\n' + "Buffer2 es;" + varbuffer2);
Tests - Pruebas
Esto lo ofrece el motor Deno
import { assertEquals } from "jsr:@std/assert";
import Person, { sayHello } from "./person.ts";
Deno.test("sayHello function", () => {
const grace: Person = {
lastName: "Hopper",
firstName: "Grace",
};
assertEquals("Hello, Grace!", sayHello(grace));
});
Luego se ejecuta ese testeo con;
deno test [archivo].ts
Funciones comunes
- Imprimir en pantalla
console.log([function_or_variable])
// show variable type
console.log("constante1 es del tipo; " + typeof constante1);
- Llamado asíncrono
await [function][func_parameters];
Al ser guardado en una variable, si se imprime en pantalla también necesita un "await").
- Request web (asíncrono)
fetch("[URL]");
- Tipo de dato
typeof [var]
- Obtener el largo de una cadena
[string_variable].length
- Ejecutar proceso hijo
new Deno.command("[path]/[binario]", [args], [opciones])
Algunas de las opciones son; - stdin: "piped", - stdout: "piped",
Jenkins
Kubernetes