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;

  1. Variables de entorno
  2. Keyword de Playbooks
  3. CLI
  4. Archivo de configuración

Requisitos

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

  1. Crear llave

ssh-keygen

  1. 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;

  1. Se crea un script que cambie el archivo cuando se ejecuta
  2. 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

  1. Cloud Computing
  2. [Modelo de responsabilidad compartida](#Modelo-de-responsabilidad compartida)

Glosario

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. Grupo de administración

Grupos_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.

  1. 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).

  1. 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.

  1. 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

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

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

  1. Cuenta normal

  2. Cuenta de prueba

  3. Cuenta gratuita para estudiantes

  4. 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

Pair_regions

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;

  1. Azure US

  2. Azure China

  3. 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;

  1. Defensa física
  2. IAM
  3. Perímetro
  4. Red
  5. Computacional
  6. Aplicación
  7. 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
  • 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
  • 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
  • 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
  • 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
  1. Inicio de archivo - header
#!/bin/bash
  1. Variables
[variable_name]=[valor]

Las variables creadas luego se referencian en el código con;

$[variable_name]
  1. 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;

    1. "-lt" para si $a es menor ("less than") a $b
    2. "-le" para si $a es menor o igual a $b
    3. "-eq" para si $a es igual a $b
    4. "-ne" para si $a NO es igual a $b
    5. "-gt" para si $a es mayor a $b
    6. "-ge" para si $a es mayor o igual a $b
  • Si $a y/o $b son strings, se puede usar;

    1. "==" para si $a y $b son iguales
    2. "!=" para si $a y $b son diferentes
    3. "<" ó ">" para menor o mayor respectivamente según el orden lexicográfico (no es igual al orden numérico)
    4. "-z" para si $a ó $b es una cadena vacía
    5. "-n" para si $a ó $b NO es una cadena vacía
  • Sí $a y/o %b son archivos, se puede usar;

    1. "-e" para sí $a ó $b existe (se recomienda que sean Path absolutos)
    2. "-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.
    3. "-d" para si $a ó $b es un directorio
    4. "-r" para si $a ó $b es un archivo legible (lo saca por permiso)
    5. "-w" para si $a ó $b es un archivo escriturable (lo saca por permiso)
    6. "-x" para si $a ó $b es un archivo ejecutable (lo saca por permiso)
    7. "-s" para si $a ó $b tiene un tamaño mayor que cero
  • Por último, se pueden anidar varias condiciones

    1. "&&" para anidar dos o más condiciones, cada una debe estar en su propio set de "[ [condición] ]"
    2. "||" 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] ]"
    3. "!" 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.

  1. 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] )

  1. Leer la entrada del usuario

read [variable_a_guardar_la_entrada]

  1. Verificar existencia

Archivo

test -f [path_absoluto_archivo]

-f [variable_o_path_absoluto]

Directorio

test -d [path_absoluto_directorio]

-d [Variable_o_path_absoluto]

  1. 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;

  1. Sección ".text"

    Indica el código ejecutable del programa.

  2. Directiva ".global XXX"

    Indica que la función ó variable "XXX" está expuerta al exterior (como el "pub" de Rust).

  3. Directiva ".type XXX, YYY"

    Indica que tipo "YYY" es la función ó variable expuerta, los valores pueden ser;

    - "function"
    
  4. 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
    
  5. 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;

ARMRegistroAliasUso
ARMv8W0-W30-Propósito general (32 bits)
ARMv8X0-X30-Propósito general (64 bits)
ARMv8WZR-Zero register (32 bits)
ARMv8XZR-Zero register (64 bits)
ARMv8WSP-Current stack pointer (32 bits)
ARMv8SP-Current stack pointer (64 bits)
ARMv8PC-Program counter (64 bits)
ARMv1-8CPSRCurrent 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;

1514131211109876543210
NZCVUnderflow-Jazelle-Greater than/or Equal-EndiannessAbort disableIRQ disableFIQ disableThumbCPU 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

Deno 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

Arquitectura

Notas

  1. Los 'Service' que van anidados a un deployment usan el valor de 'spec' -> 'selector' -> 'app', que está especificado en el deployment en 'metadata' -> 'lebels' -> 'app'

Distros

  • Bottlerocket

    Distro imutable para funcionar como worker que se actualiza automáticamente.

  • K3S

    Versión más minimalista de K8S en un solo binario.

    Tiene el socket en /run/k3s/containerd/containerd.sock

    Tiene todo en el namespace de containerd; k8s.io

sudo ctr -n=k8s.io [comandos] -a /run/k3s/containerd/containerd.sock

sudo crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock

  • RKEv2 (Goberment)

    Versión de K3S para seguridad.

    No trae containerd instalado, si no que lo tiene embebido. Se recomienda instalar containerd para poder administrarlo fuera del propio rkev2.

Tools

  • Creador de Deployment / StatefulSet / DaemonSet

  • Creador de Deployment / Service / Ingress

  • CI/CD

    • Jenkins (CI/CD, opensource)
    • Terraform (CD, opensource)
    • Spinnaker (CD, opensource)
    • IO (CD, opensource)
  • Métricas;

    • Prometheus
  • Monitoreo general;

    • DataDog (pago)
    • Sematext Monitoring (pago)
    • Cast.ai (pago)
    • Jaeger (open source)
  • Monitoreo desde métricas;

    • Grafana
  • Monitoreo desde Service mesh (específico de la red en los PODS);

    • istio (open source)
  • Análisis de seguridad;

    • kube-lint (YAML, opensource)
    • kube-bench (deployment, opensource)
    • Trivy (runner, opensource)
    • Tenable/Terrascan (IAC, opensource)

Temaplates

Deployment template

El modo por defecto para desplegar una aplicación/es.

apiVersion: apps/v1  # Define la versión de la API que se usa para manejar este recurso.
kind: Deployment  # Especifica que este manifiesto es un Deployment.
metadata:
  name: my-deployment  # Nombre del Deployment.
  namespace: default  # Namespace en el cual se desplegará este Deployment (por defecto es 'default').
  labels:
    app: my-app  # Etiquetas que permiten identificar y organizar recursos.
  annotations:
    description: "Este Deployment despliega una aplicación con múltiples configuraciones."  # Anotaciones adicionales para describir el recurso.

spec:
  replicas: 3  # Número de réplicas del pod a desplegar.
  selector:  # Define cómo se seleccionarán los Pods creados por este Deployment.
    matchLabels:
      app: my-app  # Etiquetas que deben coincidir para que un pod sea considerado parte de este Deployment.
  strategy:  # Estrategia de actualización de los Pods.
    type: RollingUpdate  # Define cómo se actualizarán los pods, opciones: RollingUpdate o Recreate.
    rollingUpdate:  # Parámetros específicos para una actualización progresiva.
      maxUnavailable: 1  # Número o porcentaje máximo de pods no disponibles durante la actualización.
      maxSurge: 1  # Número o porcentaje máximo de pods adicionales que pueden crearse temporalmente durante la actualización.

  template:  # Define la plantilla para los pods que serán gestionados por este Deployment.
    metadata:
      labels:
        app: my-app  # Las etiquetas que los pods llevarán. Deben coincidir con el selector.
    spec:
      containers:
        - name: my-container  # Nombre del contenedor.
          image: nginx:1.19  # Imagen del contenedor.
          ports:
            - containerPort: 80  # Puerto expuesto dentro del contenedor.
          resources:  # Define los recursos solicitados y límites para este contenedor.
            requests:
              memory: "64Mi"  # Memoria mínima solicitada.
              cpu: "250m"  # CPU mínima solicitada.
            limits:
              memory: "128Mi"  # Memoria máxima permitida.
              cpu: "500m"  # CPU máxima permitida.
          env:  # Variables de entorno para configurar el contenedor.
            - name: ENVIRONMENT
              value: production
            - name: LOG_LEVEL
              valueFrom:
                configMapKeyRef:
                  name: app-config  # Toma el valor desde un ConfigMap.
                  key: log-level
          envFrom:  # Cargar variables de entorno desde ConfigMap o Secret.
            - configMapRef:
                name: app-config  # Nombre del ConfigMap.
            - secretRef:
                name: app-secrets  # Nombre del Secret.
          volumeMounts:  # Define los volúmenes que se montarán dentro del contenedor.
            - name: config-volume
              mountPath: /etc/config
            - name: logs
              mountPath: /var/log/nginx
          livenessProbe:  # Configuración de liveness para comprobar si el contenedor sigue funcionando.
            httpGet:
              path: /healthz
              port: 80
            initialDelaySeconds: 10  # Espera antes de la primera comprobación.
            periodSeconds: 10  # Intervalo de tiempo entre las comprobaciones.
            timeoutSeconds: 1  # Tiempo límite para cada comprobación.
            failureThreshold: 3  # Número de fallos consecutivos antes de considerarse fallido.
          readinessProbe:  # Configuración para verificar si el contenedor está listo para recibir tráfico.
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5
          startupProbe:  # Verificación de que el contenedor ha arrancado correctamente.
            httpGet:
              path: /startup
              port: 80
            initialDelaySeconds: 20
            periodSeconds: 10
          imagePullPolicy: Always  # Política de pull de la imagen: Always, IfNotPresent, Never.

      initContainers:  # Contenedores que se ejecutarán antes que los contenedores principales.
        - name: init-my-service
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing... && sleep 5']
          resources:
            requests:
              memory: "32Mi"
              cpu: "100m"

      volumes:  # Define los volúmenes que se montarán en los contenedores.
        - name: config-volume
          configMap:
            name: app-config  # Nombre del ConfigMap del que se cargará la configuración.
        - name: logs
          emptyDir: {}  # Volumen temporal que desaparece cuando el pod se reinicia o se borra.

      nodeSelector:  # Define en qué nodos pueden desplegarse los pods.
        disktype: ssd  # Ejemplo de nodo con un determinado tipo de disco.

      affinity:  # Afinidad de los pods con respecto a nodos.
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/e2e-az-name
                    operator: In
                    values:
                      - e2e-az1
                      - e2e-az2
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            labelSelector:
              matchExpressions:
                - key: security
                  operator: In
                  values:
                    - S1
            topologyKey: "kubernetes.io/hostname"

      tolerations:  # Define tolerancias para nodos con taints específicos.
        - key: "key1"
          operator: "Equal"
          value: "value1"
          effect: "NoSchedule"

      restartPolicy: Always  # Política de reinicio del contenedor: Always, OnFailure, Never.
      dnsPolicy: ClusterFirst  # Política DNS para los pods.
      serviceAccountName: my-service-account  # Cuenta de servicio que se utilizará.
      securityContext:  # Configuración de seguridad para todo el pod.
        runAsUser: 1000
        fsGroup: 2000
      schedulerName: default-scheduler  # Define el scheduler que gestionará este pod.
      hostNetwork: false  # Si se debe usar el networking del host.
      priorityClassName: high-priority  # Define la prioridad de los pods.

  minReadySeconds: 5  # Tiempo que un pod debe estar listo antes de ser considerado disponible.
  revisionHistoryLimit: 10  # Número máximo de réplicas anteriores mantenidas.
  progressDeadlineSeconds: 600  # Tiempo máximo para considerar que una actualización es exitosa.
  paused: false  # Si el deployment está pausado o no.

Daemon Set

Un DaemonSet asegura que un Pod específico esté corriendo en cada nodo (o en nodos seleccionados) del clúster.

No maneja el estado de las aplicaciones.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-daemonset  # Nombre del DaemonSet.
  namespace: default  # Namespace donde se desplegará el DaemonSet.
  labels:
    app: my-daemon-app  # Etiquetas para identificar el DaemonSet.
  annotations:
    description: "DaemonSet para ejecutar un pod en cada nodo del clúster."

spec:
  selector:
    matchLabels:
      app: my-daemon-app  # Etiquetas que deben coincidir con los pods gestionados por el DaemonSet.
  
  template:  # Define la plantilla para los Pods gestionados por este DaemonSet.
    metadata:
      labels:
        app: my-daemon-app  # Etiquetas que deben coincidir con el selector.
    spec:
      containers:
        - name: my-daemon-container  # Nombre del contenedor.
          image: busybox:1.28  # Imagen del contenedor.
          args:  # Argumentos pasados al contenedor.
            - "/bin/sh"
            - "-c"
            - "while true; do echo Hello DaemonSet; sleep 3600; done"
          resources:  # Configura los recursos solicitados y límites para este contenedor.
            requests:
              memory: "64Mi"
              cpu: "250m"
            limits:
              memory: "128Mi"
              cpu: "500m"
          volumeMounts:
            - name: logs
              mountPath: /var/log/daemonset
          ports:
            - containerPort: 80
              name: http
          livenessProbe:  # Verificación de si el contenedor está vivo.
            httpGet:
              path: /healthz
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:  # Verificación de si el contenedor está listo para recibir tráfico.
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5

      initContainers:  # Contenedores que se ejecutarán antes del contenedor principal.
        - name: init-container
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing DaemonSet... && sleep 5']

      volumes:  # Define los volúmenes que se utilizarán.
        - name: logs
          emptyDir: {}

      nodeSelector:  # Reglas para limitar los nodos donde se ejecutará el DaemonSet.
        disktype: ssd

      affinity:  # Define la afinidad de los Pods con respecto a nodos.
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/e2e-az-name
                    operator: In
                    values:
                      - e2e-az1
                      - e2e-az2

      tolerations:  # Define tolerancias a ciertos taints de los nodos.
        - key: "key1"
          operator: "Equal"
          value: "value1"
          effect: "NoSchedule"

  updateStrategy:  # Estrategia de actualización de los DaemonSets.
    type: RollingUpdate  # Opciones: RollingUpdate o OnDelete.
    rollingUpdate:
      maxUnavailable: 1  # Número o porcentaje máximo de pods no disponibles durante la actualización.
      
  revisionHistoryLimit: 10  # Número máximo de revisiones guardadas para el DaemonSet.

Stateful Set

El StatefulSet gestiona el despliegue y el escalado de un conjunto de Pods, garantizando un orden de despliegue, actualización y eliminación, manteniendo una identidad única para cada Pod.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset  # Nombre del StatefulSet.
  namespace: default  # Namespace donde se desplegará.
  labels:
    app: my-stateful-app
  annotations:
    description: "StatefulSet para manejar aplicaciones con estado que requieren una identidad única en cada pod."

spec:
  replicas: 3  # Número de réplicas gestionadas por el StatefulSet.
  serviceName: "my-service"  # Nombre del Headless Service asociado al StatefulSet.
  selector:
    matchLabels:
      app: my-stateful-app

  template:  # Plantilla para los pods gestionados por el StatefulSet.
    metadata:
      labels:
        app: my-stateful-app
    spec:
      containers:
        - name: my-stateful-container
          image: postgres:13  # Ejemplo con una base de datos Postgres.
          ports:
            - containerPort: 5432
              name: postgres
          env:
            - name: POSTGRES_USER
              value: "admin"
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secret
                  key: password
          volumeMounts:
            - name: postgres-data
              mountPath: /var/lib/postgresql/data  # Donde se almacenan los datos persistentes.

      initContainers:
        - name: init-container
          image: busybox:1.28
          command: ['sh', '-c', 'echo Initializing StatefulSet... && sleep 5']

  volumeClaimTemplates:  # Define volúmenes persistentes para cada pod.
    - metadata:
        name: postgres-data  # Nombre del volumen.
      spec:
        accessModes: ["ReadWriteOnce"]  # Modo de acceso del volumen.
        resources:
          requests:
            storage: 1Gi  # Espacio de almacenamiento solicitado.
        storageClassName: standard  # Define la StorageClass que gestionará este PVC.

  podManagementPolicy: Parallel  # Controla cómo se crean o eliminan los pods. Opciones: OrderedReady, Parallel.
  updateStrategy:
    type: RollingUpdate  # Estrategia de actualización.
    rollingUpdate:
      partition: 1  # Permite actualizar solo una parte de los pods a la vez.
  revisionHistoryLimit: 10  # Número de revisiones mantenidas.
  persistentVolumeClaimRetentionPolicy:  # Define la política de retención de los volúmenes persistentes.
    whenDeleted: Retain  # Mantener el PVC cuando se elimine el StatefulSet.
    whenScaled: Retain  # Mantener el PVC cuando se escale el StatefulSet hacia abajo.

Service template

  • Cluster IP

Descripción:

Este es el tipo de Service por defecto. Expone el servicio dentro del clúster a través de una IP interna, llamada ClusterIP. Solo los recursos dentro del clúster (como otros Pods) pueden acceder a este servicio.

Uso:

Se utiliza cuando solo necesitas exponer tu aplicación dentro del clúster, sin necesidad de que sea accesible desde fuera. Ideal para microservicios que necesitan comunicarse entre sí dentro del clúster. No es accesible desde fuera del clúster.

Ejemplo de uso: Imagina que tienes un conjunto de microservicios que se comunican entre ellos, pero no necesitas exponerlos al mundo exterior.

apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service  # Nombre del Service
  namespace: default  # Namespace donde se despliega el Service
  labels:
    app: my-app  # Etiquetas para identificar el Service
  annotations:
    description: "ClusterIP Service que expone la aplicación solo dentro del cluster."

spec:
  type: ClusterIP  # Tipo de Service: expone el servicio solo dentro del cluster.
  selector:
    app: my-app  # Selecciona los Pods que coinciden con esta etiqueta.
  ports:
    - protocol: TCP  # Protocolo, puede ser TCP o UDP
      port: 80  # Puerto que expone el Service dentro del cluster.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      name: http  # Nombre del puerto, útil para algunas herramientas.
  clusterIP: None  # Si se desea crear un Headless Service, se debe establecer `None`.
  sessionAffinity: None  # Controla la afinidad de sesiones, opciones: None o ClientIP.
  externalTrafficPolicy: Cluster  # Define cómo manejar el tráfico externo. Opciones: Cluster, Local.
  ipFamilies:
    - IPv4  # Define la familia de IPs para el servicio: IPv4, IPv6, o ambas.
  ipFamilyPolicy: SingleStack  # Define la política de familia de IP: SingleStack, PreferDualStack o RequireDualStack.
  • NodePort

Descripción:

Un NodePort expone el servicio a través de un puerto específico en cada nodo del clúster. Además de ser accesible dentro del clúster como un ClusterIP, este tipo de servicio permite que los usuarios accedan al servicio desde fuera del clúster a través del IP del nodo y un puerto específico en el rango 30000-32767.

Uso:

Se usa cuando necesitas exponer tu aplicación externamente y no tienes un balanceador de carga (por ejemplo, en entornos on-premise o de desarrollo). El servicio es accesible desde el exterior usando la IP de cualquier nodo del clúster y el puerto especificado. Es más simple que usar un LoadBalancer, pero tiene la desventaja de que debes lidiar manualmente con la exposición a través de los nodos.

Ejemplo de uso: Ideal para entornos de desarrollo o pruebas donde quieres acceder a tu servicio desde fuera del clúster sin la complejidad de configurar un balanceador de carga.

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "NodePort Service que expone el servicio en todos los nodos del cluster."

spec:
  type: NodePort  # Tipo de Service: expone el servicio en un puerto específico de todos los nodos.
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80  # Puerto que expone el Service dentro del cluster.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      nodePort: 30036  # Puerto en los nodos donde estará disponible (rango: 30000-32767).
      name: http
  sessionAffinity: ClientIP  # Mantiene la afinidad de sesión basada en la IP del cliente.
  externalTrafficPolicy: Local  # Tráfico externo se envía solo a nodos con pods activos.
  healthCheckNodePort: 32000  # Puerto adicional para verificaciones de salud de los nodos (opcional).

  • LoadBalancer

Descripción: Un LoadBalancer crea un balanceador de carga externo que distribuye el tráfico entre los pods de tu servicio. Este tipo de servicio asigna automáticamente una IP externa y maneja la creación del balanceador de carga en la nube (si estás en un proveedor de nube como AWS, GCP o Azure).

Uso:

Es ideal para exponer aplicaciones al exterior en producción en la nube. El proveedor de la nube gestionará el balanceador de carga. Permite distribuir el tráfico entre los diferentes pods que respaldan el servicio. Soporta la especificación de rangos IP para restringir el acceso externo.

Ejemplo de uso: Perfecto para exponer aplicaciones web o APIs que necesitan estar accesibles desde internet. Un proveedor de nube creará automáticamente un balanceador de carga y manejará la distribución del tráfico.

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "LoadBalancer Service que expone el servicio a través de un balanceador de carga externo."
    service.beta.kubernetes.io/aws-load-balancer-type: nlb  # Ejemplo de anotación específica de AWS para usar un Network Load Balancer.
  
spec:
  type: LoadBalancer  # Tipo de Service: expone el servicio a través de un Load Balancer externo.
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80  # Puerto que el balanceador expone públicamente.
      targetPort: 8080  # Puerto donde está escuchando la aplicación en los Pods.
      name: http
    - protocol: TCP
      port: 443  # Puerto adicional para HTTPS, por ejemplo.
      targetPort: 8443
      name: https
  loadBalancerIP: 192.168.0.100  # IP externa preasignada para el balanceador de carga (opcional, depende del proveedor).
  externalTrafficPolicy: Cluster  # Cómo manejar el tráfico externo.
  sessionAffinity: None  # Controla la afinidad de sesiones, opciones: None o ClientIP.
  loadBalancerSourceRanges:
    - 203.0.113.0/24  # Restringe el acceso al balanceador de carga a estos rangos de IP (opcional).

  • ExternalName

Descripción:

Un ExternalName no redirige el tráfico a los Pods del clúster, sino que actúa como un alias para un nombre DNS externo. Básicamente, resuelve el nombre de servicio en un nombre DNS externo (como una redirección).

Uso:

Se usa cuando necesitas acceder a un servicio externo, fuera del clúster, mediante un nombre DNS específico. No crea ningún ClusterIP, ni interactúa con los Pods. Sirve para configurar aplicaciones dentro del clúster para que accedan a servicios externos sin tener que modificar el código de la aplicación, solo cambiando el nombre de servicio.

Ejemplo de uso: Si tienes una base de datos o una API externa (por ejemplo, una API SaaS) a la que necesitas acceder desde dentro de tu clúster, puedes usar un ExternalName para simplificar la configuración.

apiVersion: v1
kind: Service
metadata:
  name: my-externalname-service
  namespace: default
  labels:
    app: my-app
  annotations:
    description: "ExternalName Service que actúa como un alias DNS para servicios externos."

spec:
  type: ExternalName  # Tipo de Service: actúa como un alias para un nombre DNS externo.
  externalName: my-external-service.example.com  # Nombre DNS al que se redirige el tráfico.
  ports:
    - protocol: TCP
      port: 80  # Puerto que usará el servicio para redirigir el tráfico (opcional).

Ingress template

Descripción:

El recurso Ingress en Kubernetes permite gestionar el acceso externo a los servicios dentro de un clúster, normalmente mediante HTTP y HTTPS. Ingress proporciona reglas para enrutar solicitudes basadas en nombres de host, rutas, o incluso basándose en headers, hacia los servicios correspondientes dentro del clúster. A diferencia de NodePort o LoadBalancer, Ingress ofrece más control sobre el enrutamiento de tráfico y permite configurar reglas para múltiples servicios en un solo punto de entrada (puerta de enlace).

Uso:

Ingress se utiliza para exponer servicios HTTP/HTTPS a través de reglas de enrutamiento. Permite:

  1. Enrutar solicitudes basadas en el nombre de dominio (host).
  2. Dirigir diferentes rutas (URL) a diferentes servicios.
  3. Gestionar certificados SSL para el tráfico HTTPS.
  4. Utilizar un único punto de acceso para múltiples servicios.
  5. Configurar reglas avanzadas como redireccionamientos, autenticación o balanceo de carga.

Uso común de Ingress:

  1. Controlar el acceso HTTP/HTTPS de manera centralizada.
  2. Proveer un único dominio para múltiples servicios en el clúster, cada uno con diferentes rutas.
  3. Implementar balanceo de carga HTTP avanzado y TLS (SSL).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress  # Nombre del recurso Ingress.
  namespace: default  # Namespace donde se despliega el Ingress.
  labels:
    app: my-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  # Ejemplo de anotación para reescribir URL.
    kubernetes.io/ingress.class: "nginx"  # Especifica la clase de controlador Ingress.
    nginx.ingress.kubernetes.io/ssl-redirect: "true"  # Redirige automáticamente HTTP a HTTPS.
    cert-manager.io/cluster-issuer: "letsencrypt-prod"  # Para gestionar certificados SSL con cert-manager.

spec:
  rules:
    - host: example.com  # Define el nombre de dominio que será gestionado por el Ingress.
      http:
        paths:
          - path: /  # Ruta principal.
            pathType: Prefix  # Especifica que todas las rutas con este prefijo serán redirigidas.
            backend:
              service:
                name: my-service  # Nombre del servicio al que se redirige.
                port:
                  number: 80  # Puerto del servicio (puerto HTTP en este caso).

          - path: /api  # Ruta para la API.
            pathType: Prefix
            backend:
              service:
                name: api-service  # Servicio que manejará las solicitudes de la ruta "/api".
                port:
                  number: 8080

          - path: /static  # Ruta para servir contenido estático.
            pathType: Prefix
            backend:
              service:
                name: static-service  # Servicio para manejar la ruta "/static".
                port:
                  number: 8081

  tls:  # Configuración para el manejo de certificados SSL.
    - hosts:
        - example.com  # Nombre de dominio que se asegura con TLS.
      secretName: tls-secret  # Nombre del Secret que contiene el certificado TLS.

  defaultBackend:  # Define un backend por defecto si no se cumplen las reglas anteriores.
    service:
      name: default-service  # Servicio por defecto al que se enviará el tráfico si ninguna regla coincide.
      port:
        number: 80

POD identities

Utilizan el IAM de la nube en conjunto con cuentas de servicio del propio K8S para proveer un token en las variables de entorno.

Firewall

- Master

sudo firewall-cmd --permanent --add-port=6443/tcp

sudo firewall-cmd --permanent --add-port=2379-2380/tcp

sudo firewall-cmd --permanent --add-port=10250/tcp

sudo firewall-cmd --permanent --add-port=10259/tcp

sudo firewall-cmd --permanent --add-port=10257/tcp

sudo firewall-cmd --reload

- Worker

sudo firewall-cmd --permanent --add-port=10250/tcp

sudo firewall-cmd --permanent --add-port=30000-32767/tcp

sudo firewall-cmd --reload

SELinux

sudo setenforce 1

sed -i 's/SELINUX=permissive/SELINUX=enforcing/g' /etc/selinux/config

CRI-O

curl https://raw.githubusercontent.com/cri-o/packaging/main/get | sudo bash

sudo systemctl enable --now crio

sudo systemctl enable --now podman.socket

Kube repo

  • /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni

sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

kube-controller-manager

Archivo; /etc/kubernetes/manifests/kube-controller-manager.yaml

Debe llevar los siguientes flags;

  • "--allocate-node-cidrs=true"
  • "--cluster-cidr="

Ubicaciones

  • Kubeconfig

Todas las distribuciones

~/.kube/config

kubectl --kubeconfig [path_location]

$KUBECONFIG

Rancher Goverment (RKEv2)

/etc/rancher/rke2/rke2.yaml

Kubernetes bare metal

/etc/kubernetes/admin.conf

Tags - Roles

Posibles roles para los nodos;

  • worker
  • control-plane
  • etcd
  • master

Asignar un rol

kubectl label node [node_name] node-role.kubernetes.io/[role]=[tag_any_name]

Borrar un rol

kubectl label node [node_name] node-role.kubernetes.io/[role]-

Persistent Volume (PV)

Sirve para que independientemente de la instancia de POD, se pueda usar el volumes en cada despliegue, se definen mediante el StorageClass.

Si se maneja bien los espacios y los nombres, se puede usar un PV y su PVC para pods especificos.

A diferencia de los volumenes comunes, estos no varian dependiendo de la instancia, por eso son "persistent".

El PV no se usa en el master, si no que afecta a los worker.

  • Volumen persistente manual
apiVersion: v1
kind: PersistentVolume
metadata:
  name: [pv_name]
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

Luego se puede crear el PersistentVolumeClaim para que pueda usar un espacio determinado según el PV que lo satisfaga

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: [pvc_name]
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

Ejemplo de un POD con un PVC específico

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

Backups

  • ETCD

Rancher Goverment (RKEv2)

rke2 etcd-snapshot save --name pre-upgrade-snapshot

systemctl stop rke2-server && rke2 server --cluster-reset --cluster-reset-restore-path=[PATH-TO-SNAPSHOT] && systemctl start rke2-server

Comandos

sudo KUBECONFIG=[path_absoluto] kubectl ....

- Unir al cluster

Kubernetes bare metal

kubeadm join --discovery-token [master_token] --discovery-token-ca-cert-hash sha256:[HASH] --control-plane [master_IP]:6443

- Aplicar deployment

Apply sobre escribirá si ya existe el recurso

kubectl apply -f [file_or_URLfile]

  • "-l [key]=[value]" asignar tag
  • "-k [ditectory]" aplica varios deployments a la vez

Mientras que "create" no sobre escribirá

kubectl create -f [file_or_URLfile]

  • "-l [key]=[value]" asignar tag
  • "-k [ditectory]" aplica varios deployments a la vez

En ambos ("create" y "apply") los tipos que se soportan son;

  1. clusterrole
  2. clusterrolebinding
  3. configmap
  4. cronjob
  5. deployment
  6. ingress
  7. job
  8. namespace
  9. poddisruptionbudget
  10. priorityclass
  11. quota
  12. role
  13. rolebinding
  14. secret
  15. secret docker-registry
  16. secret generic
  17. secret tls
  18. service
  19. service clusterip
  20. service externalname
  21. service loadbalancer
  22. service nodeport
  23. serviceaccount
  24. token
  25. pv
  26. pvc

- Editar deployment

Se usa el editor especificado en la variable de entorno KUBE_EDITOR ó EDITOR

kubectl edit [type]/[resource_name]

  • "-o json" edita usando el modo json
  • "-o yaml" edita usando el modo yaml

- Mostrar eventos

Para todo el clúster

kubectl events --all-namespaces

Para un pod específico

kubectl events --for pod/[pod_name] --watch

- Customizar salida

... -o [yaml,json,wide,etc]

- Obtener información

kubectl get [info] -o yaml

  1. nodes
  2. deployments
  3. pods
  4. svc (services)
  5. rc (replication controller)
  6. pv (persistent volume)
  7. pvc (persistent volume claim)

kubectl cluster-info

  • "--storage-driver-password [string]" contraseña para la base de datos
  • "--storage-driver-host [ip]:[port]" ip y puerto para la base de datos
  • "--storage-driver-db [name]" nombre de la base de datos
  • "--storage-driver-table [name]" nombre de la tabla
  • "--storage-driver-user [name]" nombre de usuario
  • "-s [ip]:[port]" ip y puerto del servidor

- Obtener una descripción

kubectl describe [recurso] -o yaml

Recursos compatibles

  1. nodes
  2. deployments
  3. pods
  4. svc (services)
  5. rc (replication controller)

- Inspeccionar pod

kubectl inspect pods/[podname]

- Ver registros (logs)

kubectl logs [pod_name]

  • "--tail=X" las últimas X líneas
  • "--since=Xh" las últimas X horas
  • "-c [container_name]" de un contenedor específico de ese POD
  • "--previous" contenedores previos fallidos
  • "--all-containers" todos los contenedores de ese pod

- Adjuntar a container

kubectl attach [pod_name]

  • "-c [container_name]" a un contenedor específico
  • "... -i -t" interactive y TTY
  • "rs/[pod_name]" primera réplica del pod

- Ejecutar en un contenedor

kubectl exec [pod_name] -c [container] -i -t -- [comand] [command_arguments]

- Auditar autenticación

kubectl auth

  • "--storage-driver-password [string]" contraseña para la base de datos
  • "--storage-driver-host [ip]:[port]" ip y puerto para la base de datos
  • "--storage-driver-db [name]" nombre de la base de datos
  • "--storage-driver-table [name]" nombre de la tabla
  • "--storage-driver-user [name]" nombre de usuario
  • "-s [ip]:[port]" ip y puerto del servidor

- Setear auto escalado horizontal

kubectl autoscale [type] [resource] --min=[X] --max=[Y] --cpu-percent=[Z]

Tipos;

  1. deployments
  2. pods
  3. svc (services)
  4. rc (replication controller)

- Setear escalado manual

kubectl scale --replicas=[X] [type]/[resource_name]

- Aprobar una solicitud de firmar un certificado (CSR: Certificate Signing Request)

kubectl certificate approve [CSR_name]

  • "-f [file_or_URLFile]" si no está el nombre, se puede usar un archivo
  • "-R" si se usó "-f" y son más de un archivo se puede especificar esto para que lea todo el directorio
  • "--force"
  • "-h"

- Marcar nodo como inusable

Esto hace que el scheduler del master no mande algo a ejecutar

kubectl cordon [node]

También se lo puede marcar como "drain" para realizar tareas de mantenimiento

kubectl dran [node]

- Copiar desde/hacia el POD

El src ó dest puede ser la máquina local, el otro tiene que ser el POD.

El pod se especifica; [namespace]/[pod_name]:[absolute_path]

kubectl cp [src] [dest]

- Debug resource

kubectl debug [type]/[resource_name] -it --image=[busybox,debian,etc]

  • "-c [containers_pod]" especificamente para los tipos; pod

- Borrar recursos

kubectl delete [type-1],[type-n] [resource_name]

- Ver diferencias entre configuraciones

La diferencia es entre el archivo de deployment original y la configuración actual del recurso

kubectl diff -f [file]

- Crear un servicio en un pod existente

kubectl expose [type] [resource_name] --port=[host_port] --target-port=[container_port] --name=[service_name]

  • "-f [archivo].yaml" también se puede usar un archivo en vez de especificar el tipo

- Actualizar labels en un recurso

kubectl label --overwrite [type] [resource_name] [label]=[value]

  • "-f [archivo].yaml" también se puede usar un archivo en vez de especificar el tipo

- Exponer puerto sin crear servicios

kubectl port-forward [type]/[resoource_name] [host_port]:[container_port] --address [ip_where_allow_incoming]

- Proxy HTTP para acceder a la API de Kubernetes

Se inicia un proxy entre el host donde ejecutamos y el clúster para poder consumir la API de Kubernetes

kubectl proxy --port=[port_to_use] --address=[ip_master_node]

La URL luego tiene esta forma;

http://localhost:8080/api/v1/proxy/namespaces/[namespace]/services/[service]

Se debe usar kubectl config para especificar usar ese proxy

kubectl config set-context [name] --proxy=http://[proxy_ip]:[port]

kubectl proxy -n default --url http://[proxy_ip]:[port]

- Remplazar/actualizar POD

kubectl replace -f [file].[yaml/json]

- Rollback

Son soportados; deployments, daemonsts, statefulsets.

kubectl rollout undo [type]/[resource_name]

kubectl rollout status [type]/[resource_name]

kubectl rollout restart [type]/[resource_name]

kubectl rollout history

kubectl rollout [pause/resume] [type]/[resource_name]

kubectl rollout undo [type]/[resource_name]

Se puede incluir el argumento "--selector=app=[name]" en vez del tipo y nombre_recurso.

- Crear POD

kubectl run [name] --image=[image] --port=[container_port] --env=[environment_variable] --labels="[var]=[value],[var2]=[value2]" --restart=[Never/Always] -t -i

- Ver consumo de recursos

kubectl top [node/pod]/[resource_name]

MySQL

Python

Es un lenguage interpretado, pensado (originalmente) para scripting.

Al igual que JavaScript y BASH, procesa todo en lote y llama a funciones especificamente si son convocadas de forma explícita.

Comentarios

Los comentarios son con "#"

Math Operators

From highest to lowest precedence:

OperatorsOperationExample
**Exponent2 ** 3 = 8
%Modulus/Remainder22 % 8 = 6
//Integer division22 // 8 = 2
/Division22 / 8 = 2.75
*Multiplication3 * 3 = 9
-Subtraction5 - 2 = 3
+Addition2 + 2 = 4
>>> 2 + 3 * 6
# 20

>>> (2 + 3) * 6
# 30

>>> 2 ** 8
#256

>>> 23 // 7
# 3

>>> 23 % 7
# 2

>>> (5 - 1) * ((7 + 1) / (3 - 1))
# 16.0

Augmented Assignment Operators

OperatorEquivalent
var += 1var = var + 1
var -= 1var = var - 1
var *= 1var = var * 1
var /= 1var = var / 1
var //= 1var = var // 1
var %= 1var = var % 1
var **= 1var = var ** 1
>>> greeting = 'Hello'
>>> greeting += ' world!'
>>> greeting
# 'Hello world!'

>>> number = 1
>>> number += 1
>>> number
# 2

>>> my_list = ['item']
>>> my_list *= 3
>>> my_list
# ['item', 'item', 'item']

Walrus Operator

The Walrus Operator allows assignment of variables within an expression while returning the value of the variable

>>> print(my_var:="Hello World!")
# 'Hello world!'

>>> my_var="Yes"
>>> print(my_var)
# 'Yes'

>>> print(my_var:="Hello")
# 'Hello'

Concatenation and Replication

String concatenation

>>> 'Alice' 'Bob'
# 'AliceBob'

String replication:

>>> 'Alice' * 5
# 'AliceAliceAliceAliceAlice'

Variables

You can name a variable anything as long as it obeys the following rules:

It can be only one word.

>>> # good
>>> var = 'Hello'
>>> my_var_2 = 'Hello'

# It can’t begin with a number.

>>> 23_var = 'hello'

# Variable name starting with an underscore (_) are considered as “unuseful”.

>>> _spam = 'Hello'

Condicionales

if

if name == 'Debora':
   print('Hi Debora!')
elif name == 'George':
   print('Hi George!')
else:
   print('Who are you?')


print('kid' if age < 18 else 'adult')

Si se necesita saber si una variable está vacia o no, no se debe usar "len([variable])" si no un simpĺe "if [variable]" y ya se evaluará por si mismo.

Funciones comunes

Imprimir en pantalla

print("[texto]", [variable], [modificador])

  • El modificador "end=[letra]" permite añadir [letra] al final de cada palabra en la iteración del cilo "while", "for", etc.
  • El modificador "sep=[letra]" permite añadir [letra] como separador de cada palabra en la iteración del cilo "while", "for", etc.

Imprimir variable sin texto previo

print(f'{[variable]}')

Tomar la entrada - input

Por defecto no llama al input directo, si no que esa variable debe ser impresa y ahí se ejecuta el input

[variable_store] = input("[texto a mostrar en el input]")

print(f'{[variable]}')

Largos - length

  • Largo de caracteres
len('hello')
# 5
  • Largo de una tupla
len(['cat', 3, 'dog'])
# 3

Rust

Seguridad

Certificaciones

  • Blueteam
  1. Level 1: CompTIA Segurity +, CSA, eCDFP, BTL1
  2. Level 2: CompTIA CySA+, BTL2, eCTHP, CCD, CDSA, OSDA, GCIH, eCIR
  3. Level 3: CompTIA CASP+, GCFA
  • Redteam
  1. Level 1: PNPT, CBBH, eJPT, CRTP, CEH
  2. Level 2: OSCP, OSWP, OSWA, OSEP, CPTS
  3. Level 3: OSMR, OSED, CRTO
  4. Level 4: OSCE3, OSEE, OSWE
  • InfoSec
  1. Level 2: CRISC, CISA, CISM
  2. Level 3: CGEIT, CISSP

Cyber seguridad militar

CapaHerramienta / Procedimiento
1: Seguridad PerimetralICAM, Sensor de movimiento, App Firewall, Honeypot, analisis de malware, seguridad de mensaje, IDPS (Intrusion Detection Prevention System), seguridad perimetral, seguridad física, zona demilitarizada segura, DLP
2: Seguridad de redICAM, Enclave de firewalls, Acceso remoto empresarial, seguridad de mensaje, seguridad móvil, NAC, Network IDPS, Firewall virtual, protección VoIP (Voz en IP), filtrado por proxy web, DLP, bloqueo por DNS/IP de publicidad/trackers/etc
3: Seguridad en endpointICAM, seguridad en contenido, aplicación de seguridad en endpoint, IDPS en el sistema operativo, manejo de parches, firewall personal, cumplimiento de estándares NIST800/CIS/ENISA/PCI, DLP, EPP (Endpoint Protection Platform)
4: Seguridad en aplicaciónICAM, Monitoreo y escaneo de configuración, Control de cambios, gestión de parches, prueba de penetración, WAF (Web Application Firewall), DLP, cifrado de la comunicación entre los pares conectados
5: Seguridad en datosICAM, Protección DAR/DIM/DIU, lugar de almacenamiento de datos, cifrado en reposo, cifrado en transporte, prevención de exportación de los datos, sanitización de los datos a guardar/leer, manejo de permisos, ofuscación de datos, monitoreo de integridad

Capas adyacentes a todas las anteriores;

  • Prevención
  1. Manejo de configuraciones
  2. Pruebas de penetración
  3. Entrenamiento continuo
  4. Cumplimiento en políticas de seguridad humanas
  5. Auditorias de vulnerabilidades
  6. Modelado de amenazas
  7. Gobernanza de la seguridad IT
  8. Inteligencia de amenazas cibernéticas
  9. Marco de trabajo para el manejo de riesgos
  10. Plan de recuperación ante desastres
  11. Marco de trabajo de cero confianza (ZeroTrust)
  • Monitoreo y respuesta
  1. Operaciones enfocadas a la detección de amenazas
  2. CIRT
  3. Análisis de comportamiento
  4. Soluciones multi dominio
  5. Forencia digital
  6. Adminitración y manejo de escalamiento de privilegios
  7. Respuestas ante amenazas
  8. SIEM (Security Information and Event Management)
  9. Sistemas de reporteria y alertas
  10. ISCM

Seguridad móvil

  1. Autenticación centralizada en el dispositivo
  2. On-boarding
  3. Detección de conectividad a redes inalámbricas in/seguras
  4. Revisión de amenazas basado en OWASP Mobile TOP 10
  5. Escaneo de las aplicaciones instaladas y configuraciones
  6. Detección de root/jailbreak en el dispositivo
  7. Detección de aplicaciones inseguras o que no cumplen con los estándares de seguridad
  8. Pruebas de penetración
  9. Deshabilitación del IPC para bloquear la compartición de información sensible
  10. Aplicación forzada de configuraciones según estándares

Seguridad de la infraestructura

  1. Seguridad en las zonas DNS
  2. Seguridad en los servidores de correo y sus configuraciones DKIM, etc del DNS
  3. AppArmor y SELinux
  4. Kernel LandLock
  5. Actualizaciones de seguridad
  6. Uso de BTRFS ó XFS
  7. Verificación de servicios (en systemd) corriendo de fondo y/o habilitados en el inicio de sistema (--state=enabled)
  8. Exportación y análisis de los registros para todos los eventos en las aplicaciones y sistemas operativos
  9. Aislamientos de los usuarios e imposibilidad de ver archivos ajenos
  10. Aplicación forzada de configuraciones según estándares
  11. Uso de VPN como; wireguard, openvpn (preferiblemente wireguard por ser más simple, rápida y segura)
  12. Bloqueo de nodos conocidos para evitar conectividad hacia Tor, Freenet, I2P, entre otros

Seguridad en contenedores

  1. Imagen base del contenedor y su propietario/publisher
  2. Repositorio base de la imagen
  3. INIT 1 del contenedor
  4. Volumen de datos en el contenedor
  5. Dispositivos físicos expuestos en el contenedor
  6. Versionado del sistema base (el contenedor y su imagen) como de las aplicaciones instaladas
  7. Puertos expuestos en el contenedor y en el host
  8. Versión y que engine de contenedor se está usando (Docker, Podman, Containerd, CRI-O, etc)
  9. Modelado de amenazas
  10. Benchmarks como CIS Docker, etc
  11. Hardenización del engine de contenedor
  12. Uso de secrets y no de variables de entorno para pasar tokens
  13. Shell deshabilitada en el contenedor como interactive/TTY
  14. Contenedores sin permisos "privileged"
  15. Contenedores no integrados nativamente (cloud cli, etc) a la nube
  16. Exportación de logs fuera del contenedor

Seguridad en Kubernetes

  1. Todo lo anterior de contenedores
  2. Uso de Ingress y no de NodePorts como servicios
  3. Versión de Kubernetes en uso
  4. Archivo de administración yaml del clúster
  5. Alta disponibilidad en cantidad para los worker y master
  6. Kube-bench de Aquasecurity
  7. Auditorias de; Kubernetes CronJob,
  8. Uso de Kubernetes Secrets o servicio de la nube integrado
  9. Role Based Access Control (RBAC)
  10. Dashboard expuesto; autenticación, etc
  11. Exposición de la API de Kubernetes Master hacia fuera del clúster
  12. No disponibilidad para saltar de un contenedor a otro (osea; los namespaces del cluster)
  13. Uso de los service mesh para segurizar y monitorear la red de los contenedores con Mutual TLS habilitado (Istio por ejemplo)
  14. Uso de agentes de políticas (Open Policy Agent por ejemplo)
  15. Exportación, anaálisis y procedimientos con los registros del clúster
  16. Integraciones del contenedor con terceros
  17. Despliegues realizados con Helm
  18. Configuraciones de auto escalado horizontal para los servicios (aka; replicas)
  19. Configuraciones de auto escalado horizontal para los nodos worker
  20. Verificar las identidades en el cluster
  21. PODs sin metadatos sensibles

Seguridad en bases de datos

  1. Copias de seguridad automatizadas y cifradas de los datos
  2. Aplicación contenerizada para portabilidad
  3. Autenticación por defecto deshabilitada en el motor

Seguridad en BigData

  1. Análisis (Inteligencia) de registros multi-dominios para detección de comportamiento, correlaciones y eventos.

Seguridad en PHP

Todo es en el archivo de configuración

  1. Deshabilitar "remote connections"
allow_url_fopen = 0
allow_url_include = 0
  1. Limitar tiempo máximo para los procesos de entrada y cuanto puede correr un script (todo en segundos)
max_input_time = 30
max_execution_time = 30
  1. Limitar memoria máxima a utilizar
memory_limit = 8M
  1. Deshabilitar que la data solicitada se almacene, por parte de PHP, en una variable global
register_globals=off
  1. Deshabilitar la exposición de información
expose_php = 0
  1. Deshabilitar que pueda ser llamado directamente, solamente a traves de un web server
cgi.force_redirect = 1
  1. Limitar el tamaño máximo de entrada
post_max_size = 500K
max_input_vars = 100
  1. No mostrar mensajes de error
display_errors = 0
display_startup_errors = 0
  1. Habilitar logueo
log_errors = 1
error_log = [path_absoluto]/error_log
  1. Incluir, leer y ejecutar archivos solamente de este lugar
open_basedir = "[path_absoluto]:[path_absoluto2]"
  1. Deshabilitar la carga de archivos desde el usuario al PHP
file_uploads = 0
  1. Carpeta temporal donde se suben los archivos
upload_tmp_dir = [path_absoluto]
  1. Limitar tamaño máximo de subida
file_uploads = 1
upload_max_filesize = 2M
  1. Usar una nueva ID de sesión sin reutilizar anteriores
session.use_strict_mode = 1
  1. La cookie solo es accesible desde HTTP, no desde JS
session.cookie_httponly = 1
  1. Guarda el ID de la sesion en la cookie, mas no en el parámetro de URL
session.use_cookies = 1
session.use_only_cookies = 1
session.use_trans_sid = 0
  1. Actualizar en la cookie el ID de sesión cada vez que cambia
session.name = custom_session_id
  1. La cookie solamente puede usarse desde HTTPS
session.cookie_secure = 1
  1. Permitir solamente un dominio determinado como fuente de los datos para acceder a la sesión
session.referer_check = shyanjmc.com
  1. Directorio a donde guardar los archivos de sesión por usuario
session.save_path = "[path_absoluto]"
  1. Hash criptográfico a utilizar (PHP 5.3+)
session.hash_function = sha512
  1. Deshabilitar las variables de sesión globales
session.bug_compat_42 = 0
session.bug_compat_warn = 0
  1. Deshabilitar funciones inseguras del propio PHP
disable_functions = ini_set,php_uname,getmyuid,getmypid,passthru,leak,listen,diskfreespace,tmpfile,link,ignore_user_abord,shell_exec,dl,set_time_limit,exec,system,highlight_file,source,show_source,fpaththru,virtual,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,phpinfo,popen,curl_exec,curl_multi_exec,parse_ini_file,allow_url_fopen,allow_url_include,pcntl_exec,chgrp,chmod,chown,lchgrp,lchown,putenv
  1. Directorio no default para almacenar cache SOAP
soap.wsdl_cache_dir = [path_absoluto]

Seguridad en API (Application Programming Interface)

  • Autorización a nivel de objeto - OWASP - A1
  1. Verificar que se implementen las verificaciones de autorización con las políticas de usuario y la jerarquía
  2. Verificar que la implementación de la API no dependa de las identificaciones enviadas desde el cliente, en su lugar, la API debe verificar las identificaciones de los objetos almacenados en la sesión.
  3. Verificar que la configuración del servidor esté reforzada según la recomendación del servidor de aplicaciones y el marco en uso.
  4. Verificar que la implementación de la API verifique la autorización cada vez que haya una solicitud de acceso a la base de datos por parte del cliente.
  5. Verificar que la API no esté usando identificaciones aleatorias que se puedan adivinar (UUID)
  • Autenticación interrumpida - OWASP - A2
  1. Verificar todas las formas posibles de autenticar todas las API
  2. Verificar que las API de restablecimiento de contraseña y los enlaces de un solo uso también permitan que los usuarios se autentiquen y que deban estar estrictamente protegidos.
  3. Verificar que la API implemente estándares de autenticación, generación de tokens, almacenamiento de contraseñas y autenticación multifactor.
  4. Verificar que la API use un token de acceso de corta duración.
  5. Verificar que la API utilice una limitación de velocidad más estricta para la autenticación, implementar políticas de bloqueo y verificaciones de contraseñas débiles.
  • Excesiva exposición de datos - OWASP - A3
  1. Verificar que la API no dependa del cliente para filtrar los datos.
  2. Verificar las respuestas de la API y adaptar la respuesta a lo que los consumidores de la API realmente necesitan.
  3. Verificar que la especificación de la API defina los esquemas de todas las solicitudes y respuestas.
  4. Verificar que las respuestas de la API de error estén claramente definidas.
  5. Verificar que toda la información confidencial o PII se utilice con una justificación clara.
  6. Verificar que las API apliquen verificaciones de respuesta para evitar fugas accidentales de datos y excepciones.
  • Falta de recursos y limitación de velocidad - OWASP - A4
  1. Verificar que la limitación de velocidad esté configurada teniendo en cuenta el método, el cliente y las direcciones de la API.2. Verificar que el límite de carga útil esté configurado.
  2. Verificar la relación de compresión al implementar la limitación de velocidad.
  3. Verificar la limitación de velocidad en el contexto de los recursos informáticos/de contenedor
  • Autorización de nivel funcional interrumpida - OWASP - A5
  1. Verificar que, de forma predeterminada, se denieguen todos los accesos
  2. Verificar que, la API no dependa de la aplicación para imponer el acceso de administrador
  3. Verificar que todas las funciones innecesarias estén deshabilitadas.
  4. Verificar la limitación de velocidad en el contenido de los recursos informáticos/de contenedor
  5. Asegurarse de que los roles se otorguen solo en función de un rol específico.
  6. Verificar que la autorización se implemente correctamente en la API.
  • Asignación masiva - OWASP - A6
  1. Verificar que la API no vincule automáticamente los datos entrantes y los objetos internos.
  2. Verificar que la API no defina explícitamente todos los parámetros y la carga útil que espera.
  3. Verificar que, para los esquemas de objetos, utilice readOnly establecido en verdadero para todas las propiedades que se pueden recuperar a través de las API pero que nunca se deben modificar.
  4. Verifique que las API definan con precisión en el momento del diseño los esquemas, tipos y patrones que aceptará en las solicitudes y los aplique en el tiempo de ejecución.
  • Configuración incorrecta de seguridad - OWASP - A7
  1. Verifique que la implementación de las API sea repetible y que las actividades de fortalecimiento y parcheo estén incorporadas en el proceso de desarrollo
  2. Verifique que el ecosistema de API tenga un proceso automatizado para localizar fallas de configuración.
  3. Verifique que la plataforma haya deshabilitado funciones innecesarias en cualquier API.
  4. Verifique que la plataforma restrinja el acceso administrativo.
  5. Asegúrese de definir y aplicar todas las salidas, incluidos los errores.
  6. Verifique que la autorización se implemente correctamente en la API.
  • Inyección OWASP - A8
  1. Verifique que las API no confíen en sus consumidores de API, incluso si son internos.
  2. Verifique que las API definan estrictamente todos los datos de entrada: esquemas, tipos, patrones de cadena, y los apliquen en el tiempo de ejecución.
  3. Verifique que las API validen, filtren y desinfecten todos los datos entrantes.
  4. Verificar que las API estén definidas, limitar y hacer cumplir las salidas de API para evitar fugas de datos.
  • Gestión inadecuada de activos - OWASP - A9
  1. Verificar la capacidad de la plataforma documentar/inventar todos los hosts de API.
  2. Verificar que la plataforma limite el acceso a todo lo que no deba ser público.
  3. Verificar que la plataforma limite el acceso a los datos de producción. Acceso agregado a datos de producción y no producción.
  4. Verificar que la arquitectura implemente controles externos adicionales como un firewall de API.
  5. Verificar que se considere un proceso para retirar correctamente las versiones antiguas o reportar correcciones de seguridad
  6. Verificar que la arquitectura implemente autenticación estricta, redirecciones, COR, etc.
  • Registro y monitoreo insuficientes OWASP - A10
  1. Verificar que la API registre intentos fallidos, acceso denegado, falla de validación de entrada y cualquier falla en las verificaciones de políticas de seguridad.
  2. Verificar que la plataforma se asegure de que los registros estén formateados para que puedan ser consumidos por otras herramientas.
  3. Verificar que la plataforma proteja los registros como altamente confidenciales.
  4. Verificar que la plataforma incluya suficientes detalles para identificar a los atacantes.
  5. Verificar que la plataforma se integre con SIEM y otros paneles de control, herramientas de alerta de monitoreo.

SSL/TLS

SSL 3.0 es vulnerable a;

  • POODLE (Padding Oracle On Downgraded Legacy Encryption) - CVE-2014-3566.
  • BEAST (Browser Exploit Against SSL/TLS) si está el cipher; cipher block-chaining (CBC) - CVE-2011-3389.
  • Raccoon si se tiene habilitado el cipher Diffie-Hellman (DH), DHE o con OpenSSL en versiones anteriores a 1.0.2w - CVE-2020-1968
  • CRIME (Compression Ratio Info-leak Made Easy) si está habilitada la compresión. - CVE-2012-4929
  • SHAttered si tiene habilitado SHA-1 - CVE-2005-4900

TLSv1.0 es vulnerable a;

  • BEAST (Browser Exploit Against SSL/TLS) si está el cipher; cipher block-chaining (CBC) - CVE-2011-3389.
  • POODLE (Padding Oracle On Downgraded Legacy Encryption) si está el cipher; cipher block-chaining (CBC) ó RC4.
  • CRIME (Compression Ratio Info-leak Made Easy) si está habilitada la compresión. - CVE-2012-4929
  • Raccoon si se tiene habilitado el cipher Diffie-Hellman (DH), DHE o con OpenSSL en versiones anteriores a 1.0.2w - CVE-2020-1968
  • SHAttered si tiene habilitado SHA-1 - CVE-2005-4900

TLSv1.1 es vulnerable a;

  • CRIME (Compression Ratio Info-leak Made Easy) si está habilitada la compresión. - CVE-2012-4929
  • Raccoon si se tiene habilitado el cipher Diffie-Hellman (DH), DHE o con OpenSSL en versiones anteriores a 1.0.2w - CVE-2020-1968
  • SHAttered si tiene habilitado SHA-1 - CVE-2005-4900

TLSv1.2 es vulnerable a;

  • CRIME (Compression Ratio Info-leak Made Easy) si está habilitada la compresión. - CVE-2012-4929
  • SLOTH (Security Losses from Obsolete and Truncated Transcript Hashes) si se encuentran habilitados los protocolos y ciphers; SHA1+MD5, MD5 y/o SHA1 - CVE-2015-7575
  • Raccoon si se tiene habilitado el cipher Diffie-Hellman (DH), DHE o con OpenSSL en versiones anteriores a 1.0.2w - CVE-2020-1968
  • SHAttered si tiene habilitado SHA-1 - CVE-2005-4900

Todos son vulnerables a;

  • BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext ) si está habilitada la compresión HTTP. - CVE-2013-3587
  • HeartBleed si el servidor remoto está usando OpenSSL en versiones anteriores a 1.0.1g
  • Diversos tipos de ataques si tienen los ciphers; RC4, DSA, MD5, WEAK ELLIPTIC CURVES, RSA KEY EXCHANGE, DHE (RSa+DHE = Tripple Handshake), STATIC DIFFIE-HELLMAN (DH, ECDH)
  • Sweet32 si está habilitado el cipher; cipher block-chaining (CBC) - CVE-2016-2183
CiphersNivel de entropía - bitsSoportado en TLSv1.1Soportado en TLSv1.2Soportado en TLSv1.3Recomendado; Si/No
TLS_ECDHE_RSA_WITH_NULL_SHA0-Si-No
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA168-Si-No
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA168-Si-No
SSL_RSA_WITH_3DES_EDE_CBC_SHA168SiSi-No
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA128-Si-No
TLS_ECDHE_RSA_WITH_RC4_128_SHA128-Si-No
SSL_RSA_WITH_RC4_128_SHA128SiSi-No
SSL_RSA_WITH_RC4_128_MD5128Si--No
SSL_RSA_WITH_DES_CBC_SHA56Si--No
SSL_RSA_EXPORT_WITH_RC4_40_MD540---No
SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD540---No
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA56---No
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA56---No
SSL_RSA_WITH_NULL_SHA0SiSi-No
SSL_RSA_WITH_NULL_MD50Si--No
TLS_RSA_WITH_NULL_SHA2560SiSi-No
SSL_NULL_WITH_NULL_NULL0SiSi-No
SSL_DES_192_EDE3_CBC_WITH_MD5168---No
SSL_RC4_128_WITH_MD5128---No
SSL_RC2_CBC_128_CBC_WITH_MD5128---No
SSL_DES_64_CBC_WITH_MD556---No
SSL_RC2_CBC_128_CBC_EXPORT40_WITH_MD540---No
SSL_RC4_128_EXPORT40_WITH_MD540---No
SSL_RSA_FIPS_WITH_DES_CBC_SHA56---No
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA168---No
TLS_AES_128_GCM_SHA256128--SiSi
TLS_AES_256_GCM_SHA384256--SiSi
TLS_CHACHA20_POLY1305_SHA256256--SiSi
TLS_AES_128_CCM_SHA256128--SiSi
TLS_AES_128_CCM_8_SHA256128--SiSi
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384256-Si-Si
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256128-Si-Si
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384256-Si-Si
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256128-Si-Si
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA256-Si-Si
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA128-Si-Si
TLS_RSA_WITH_AES_256_GCM_SHA384256-Si-Si
TLS_RSA_WITH_AES_128_GCM_SHA256128-Si-Si
TLS_RSA_WITH_AES_256_CBC_SHA256256-Si-Si
TLS_RSA_WITH_AES_128_CBC_SHA256128-Si-Si
TLS_RSA_WITH_AES_256_CBC_SHA256SiSi-Si
TLS_RSA_WITH_AES_128_CBC_SHA128SiSi-No
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA128-Si-Si
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA256-Si-Si
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256128-Si-Si
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384256-Si-Si
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384256-Si-Si
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256128-Si-Si

Terraform

Es una herramienta de IaC (Infraestructure as Code).

Tiene conectividad dependiendo de los módulos que tenga instalados.

Estructura

  • Archivo principal;

./main.tf

  • Carpeta con los módulos;

./terraform/modules

./modules

  • Archivos con las variables

./variables.tf

  • Proveedores, backend remoto y versión de terraform a usar;

./terraform.tf

Comandos

  • Iniciar workspace

terraform init

El argumento "-upgrade" permite actualizar las versiones de los módulos.

  • Validar configuración

terraform validate

  • Mostrar cambios antes de hacerlos

terraform plan -out "[terraform_plan_file]"

  • Mostrar cambios para destruir

terraform plan -destroy -out "[terraform_plan_destroy_file]"

  • Aplicar cambios

aplicar usando el main.tf

terraform apply

aplicar usando el plan

terraform apply "[terraform_plan_file]"

  • Mostrar plan

terraform show "[terraform_plan_file]"

  • Destruir todos los recursos manejados por este workspace

terraform destroy

Archivos

  • variables.tf
variable "secret_key" {
  type        = string
  sensitive   = true
  description = "Secret key for hello module"
}

variable "region" {
  type = string
  sensitive = false
  description = "Region to rise resources"
}
  • terraform.tfvars
region = "us-east-1"
secret_key = "007_linuxrules"
  • main.tf
provider "aws" {
  region = var.region
}

provider "random" {}

provider "time" {}

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

resource "random_pet" "instance" {
  length = 2
}

resource "aws_instance" "main" {
  count = 3

  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  tags = {
    Name  = "${random_pet.instance.id}-${count.index}"
    Owner = "${var.project_name}-tutorial"
  }
}

resource "aws_s3_bucket" "example" {
  tags = {
    Name  = "Example Bucket"
    Owner = "${var.project_name}-tutorial"
  }
}
  • terraform.tf
terraform {
  required_version = "~> 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.7.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "3.5.1"
    }
  }
## ...
}