Skip to content
English
On this page

Ejercicio: Plataforma de Streaming Segura con AWS

Parte 1: Configuración de ECS y Base de la Aplicación

Escenario

Implementaremos una plataforma de streaming que incluirá:

  • Contenedores con ECS para la aplicación
  • Autenticación de usuarios con Cognito
  • Protección con WAF
  • Streaming con MediaStore

Parte 1: Configuración de ECS

1. Crear VPC y Subredes

bash
# Crear VPC
aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=streaming-vpc}]'

# Crear subredes
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.1.0/24 --availability-zone us-east-1a
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.2.0/24 --availability-zone us-east-1b

2. Configurar ECS Cluster

bash
# Crear cluster ECS
aws ecs create-cluster --cluster-name streaming-cluster

# Configurar rol IAM para ECS
aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

3. Definición de Tarea ECS

json
{
    "family": "streaming-app",
    "networkMode": "awsvpc",
    "requiresCompatibilities": ["FARGATE"],
    "cpu": "256",
    "memory": "512",
    "containerDefinitions": [
        {
            "name": "streaming-container",
            "image": "streaming-app:latest",
            "portMappings": [
                {
                    "containerPort": 80,
                    "protocol": "tcp"
                }
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/streaming-app",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                }
            }
        }
    ]
}

4. Crear Servicio ECS

bash
aws ecs create-service \
    --cluster streaming-cluster \
    --service-name streaming-service \
    --task-definition streaming-app:1 \
    --desired-count 2 \
    --launch-type FARGATE \
    --network-configuration "awsvpcConfiguration={subnets=[subnet-xxx,subnet-yyy],securityGroups=[sg-xxx]}"

5. Dockerfile para la Aplicación

dockerfile
FROM node:14

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 80

CMD ["npm", "start"]

6. Configurar Load Balancer

bash
# Crear target group
aws elbv2 create-target-group \
    --name streaming-tg \
    --protocol HTTP \
    --port 80 \
    --vpc-id vpc-xxx \
    --target-type ip

# Crear load balancer
aws elbv2 create-load-balancer \
    --name streaming-alb \
    --subnets subnet-xxx subnet-yyy \
    --security-groups sg-xxx

7. Scripts de Despliegue

bash
#!/bin/bash
# deploy.sh

# Construir imagen
docker build -t streaming-app .

# Etiquetar imagen
docker tag streaming-app:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/streaming-app:latest

# Push a ECR
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/streaming-app:latest

# Actualizar servicio ECS
aws ecs update-service --cluster streaming-cluster --service streaming-service --force-new-deployment

Verificación Parte 1

1. Verificar ECS

  • [ ] Cluster creado y activo
  • [ ] Tareas ejecutándose
  • [ ] Logs disponibles en CloudWatch
  • [ ] Load balancer configurado

2. Verificar Networking

  • [ ] VPC configurada
  • [ ] Subredes accesibles
  • [ ] Grupos de seguridad correctos
  • [ ] Load balancer accesible

3. Verificar Containerización

  • [ ] Imagen en ECR
  • [ ] Contenedores ejecutándose
  • [ ] Puertos expuestos correctamente
  • [ ] Salud de contenedores OK

Troubleshooting Común Parte 1

Error de Despliegue

  1. Verificar roles IAM
  2. Revisar configuración de red
  3. Verificar definición de tareas

Error de Contenedor

  1. Verificar Dockerfile
  2. Revisar logs de contenedor
  3. Verificar permisos ECR

Error de Networking

  1. Verificar subredes
  2. Revisar grupos de seguridad
  3. Verificar configuración del ALB

Parte 2: Configuración de Autenticación y Seguridad

Configuración de Amazon Cognito

1. Crear User Pool

bash
# Crear User Pool
aws cognito-idp create-user-pool \
    --pool-name streaming-users \
    --policies '{"PasswordPolicy":{"MinimumLength":8,"RequireUppercase":true,"RequireLowercase":true,"RequireNumbers":true,"RequireSymbols":true}}' \
    --auto-verified-attributes email

# Guardar el User Pool ID
USER_POOL_ID=$(aws cognito-idp list-user-pools --max-results 1 --query 'UserPools[0].Id' --output text)

2. Crear App Client

bash
# Crear App Client
aws cognito-idp create-user-pool-client \
    --user-pool-id $USER_POOL_ID \
    --client-name streaming-app-client \
    --no-generate-secret \
    --explicit-auth-flows ALLOW_USER_PASSWORD_AUTH ALLOW_REFRESH_TOKEN_AUTH

# Guardar el Client ID
CLIENT_ID=$(aws cognito-idp list-user-pool-clients --user-pool-id $USER_POOL_ID --query 'UserPoolClients[0].ClientId' --output text)

3. Configurar Dominio

bash
# Configurar dominio de Cognito
aws cognito-idp create-user-pool-domain \
    --domain streaming-auth-domain \
    --user-pool-id $USER_POOL_ID

4. Implementar Autenticación en Frontend

javascript
// auth.js
import { CognitoUserPool, CognitoUser, AuthenticationDetails } from 'amazon-cognito-identity-js';

const poolData = {
    UserPoolId: process.env.USER_POOL_ID,
    ClientId: process.env.CLIENT_ID
};

const userPool = new CognitoUserPool(poolData);

export const signUp = async (email, password) => {
    return new Promise((resolve, reject) => {
        userPool.signUp(email, password, [], null, (err, result) => {
            if (err) {
                reject(err);
                return;
            }
            resolve(result.user);
        });
    });
};

export const signIn = async (email, password) => {
    const authenticationDetails = new AuthenticationDetails({
        Username: email,
        Password: password,
    });

    const cognitoUser = new CognitoUser({
        Username: email,
        Pool: userPool
    });

    return new Promise((resolve, reject) => {
        cognitoUser.authenticateUser(authenticationDetails, {
            onSuccess: (result) => {
                resolve(result);
            },
            onFailure: (err) => {
                reject(err);
            }
        });
    });
};

Configuración de WAF

1. Crear Web ACL

bash
# Crear Web ACL
aws wafv2 create-web-acl \
    --name streaming-protection \
    --scope REGIONAL \
    --default-action Block={} \
    --description "Protection for streaming application" \
    --rules file://waf-rules.json \
    --region us-east-1

2. Configurar Reglas WAF

json
// waf-rules.json
{
    "Rules": [
        {
            "Name": "RateLimit",
            "Priority": 1,
            "Statement": {
                "RateBasedStatement": {
                    "Limit": 2000,
                    "AggregateKeyType": "IP"
                }
            },
            "Action": {
                "Block": {}
            },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "RateLimitRule"
            }
        },
        {
            "Name": "PreventSQLInjection",
            "Priority": 2,
            "Statement": {
                "SqliMatchStatement": {
                    "FieldToMatch": {
                        "QueryString": {}
                    },
                    "TextTransformations": [
                        {
                            "Priority": 1,
                            "Type": "URL_DECODE"
                        }
                    ]
                }
            },
            "Action": {
                "Block": {}
            },
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "SQLInjectionRule"
            }
        }
    ]
}

3. Asociar WAF con ALB

bash
# Obtener ARN del ALB
ALB_ARN=$(aws elbv2 describe-load-balancers --names streaming-alb --query 'LoadBalancers[0].LoadBalancerArn' --output text)

# Asociar Web ACL con ALB
aws wafv2 associate-web-acl \
    --web-acl-arn $WAF_ACL_ARN \
    --resource-arn $ALB_ARN

4. Configurar Monitoreo WAF

bash
# Crear grupo de logs
aws logs create-log-group --log-group-name /aws/waf/streaming

# Habilitar logging
aws wafv2 put-logging-configuration \
    --logging-configuration \
    "ResourceArn=$WAF_ACL_ARN,LogDestinationConfigs=[arn:aws:logs:us-east-1:$ACCOUNT_ID:log-group:/aws/waf/streaming]"

Integración de Componentes

1. Configurar Headers de Seguridad

javascript
// security-headers.js
app.use((req, res, next) => {
    res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
    res.setHeader('X-Content-Type-Options', 'nosniff');
    res.setHeader('X-Frame-Options', 'DENY');
    res.setHeader('X-XSS-Protection', '1; mode=block');
    next();
});

2. Middleware de Autenticación

javascript
// auth-middleware.js
const verifyToken = async (req, res, next) => {
    const token = req.headers.authorization;
    
    if (!token) {
        return res.status(401).json({ error: 'No token provided' });
    }

    try {
        const decoded = await validateCognitoToken(token);
        req.user = decoded;
        next();
    } catch (error) {
        return res.status(401).json({ error: 'Invalid token' });
    }
};

Verificación Parte 2

1. Verificar Cognito

  • [ ] User Pool creado
  • [ ] App Client configurado
  • [ ] Flujo de registro funcional
  • [ ] Flujo de login funcional

2. Verificar WAF

  • [ ] Web ACL creado
  • [ ] Reglas configuradas
  • [ ] Asociación con ALB
  • [ ] Logs habilitados

3. Verificar Seguridad

  • [ ] Headers de seguridad
  • [ ] Middleware de autenticación
  • [ ] Rate limiting funcional
  • [ ] Protección SQL injection activa

Troubleshooting Común Parte 2

Errores de Autenticación

  1. Verificar configuración de Cognito
  2. Revisar tokens y expiración
  3. Verificar configuración de App Client

Errores de WAF

  1. Verificar reglas y prioridades
  2. Revisar logs de WAF
  3. Verificar asociación con ALB

Errores de Integración

  1. Verificar headers de seguridad
  2. Revisar configuración CORS
  3. Verificar flujo de tokens

Parte 3: Configuración de Servicios Multimedia e Integración Final

Configuración de MediaStore

1. Crear Contenedor MediaStore

bash
# Crear contenedor
aws mediastore create-container \
    --container-name streaming-content \
    --tags Key=Environment,Value=Production

# Guardar el endpoint
ENDPOINT=$(aws mediastore describe-container \
    --container-name streaming-content \
    --query 'Container.Endpoint' \
    --output text)

2. Configurar Política de Acceso

json
// mediastore-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadAccess",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "mediastore:GetObject",
                "mediastore:DescribeObject"
            ],
            "Resource": "arn:aws:mediastore:region:account-id:container/streaming-content/*",
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "true"
                }
            }
        }
    ]
}

3. Configurar CORS

json
// cors-policy.json
{
    "CorsPolicy": [
        {
            "AllowedHeaders": ["*"],
            "AllowedMethods": ["GET", "HEAD"],
            "AllowedOrigins": ["https://*.your-domain.com"],
            "MaxAgeSeconds": 3600,
            "ExposeHeaders": ["Content-Length", "Content-Type"]
        }
    ]
}

Configuración del Servicio de Streaming

1. Integrar MediaStore con la Aplicación

javascript
// media-service.js
import AWS from 'aws-sdk';

const mediastore = new AWS.MediaStore({
    endpoint: process.env.MEDIASTORE_ENDPOINT,
    region: process.env.AWS_REGION
});

export const getStreamingUrl = async (videoId) => {
    const params = {
        Path: `videos/${videoId}/manifest.m3u8`,
        Container: 'streaming-content'
    };

    try {
        const url = await mediastore.getObject(params).promise();
        return url;
    } catch (error) {
        console.error('Error getting streaming URL:', error);
        throw error;
    }
};

2. Implementar Reproductor de Video

javascript
// video-player.js
import React from 'react';
import HLS from 'hls.js';

const VideoPlayer = ({ streamUrl }) => {
    const videoRef = React.useRef(null);

    React.useEffect(() => {
        if (HLS.isSupported() && videoRef.current && streamUrl) {
            const hls = new HLS();
            hls.loadSource(streamUrl);
            hls.attachMedia(videoRef.current);
        }
    }, [streamUrl]);

    return (
        <video
            ref={videoRef}
            controls
            style={{ width: '100%', maxWidth: '800px' }}
        />
    );
};

Monitoreo y Alertas

1. Configurar CloudWatch Dashboard

bash
# Crear dashboard
aws cloudwatch put-dashboard \
    --dashboard-name streaming-dashboard \
    --dashboard-body file://dashboard.json
json
// dashboard.json
{
    "widgets": [
        {
            "type": "metric",
            "properties": {
                "metrics": [
                    ["AWS/MediaStore", "RequestCount", "ContainerName", "streaming-content"],
                    ["AWS/MediaStore", "4xxErrorCount", "ContainerName", "streaming-content"],
                    ["AWS/MediaStore", "5xxErrorCount", "ContainerName", "streaming-content"]
                ],
                "period": 300,
                "stat": "Sum",
                "region": "us-east-1",
                "title": "MediaStore Metrics"
            }
        },
        {
            "type": "metric",
            "properties": {
                "metrics": [
                    ["AWS/WAF", "BlockedRequests", "WebACL", "streaming-protection"],
                    ["AWS/WAF", "AllowedRequests", "WebACL", "streaming-protection"]
                ],
                "period": 300,
                "stat": "Sum",
                "region": "us-east-1",
                "title": "WAF Metrics"
            }
        }
    ]
}

2. Configurar Alertas

bash
# Crear alarma para errores 5xx
aws cloudwatch put-metric-alarm \
    --alarm-name streaming-5xx-errors \
    --alarm-description "Alert on high 5xx error rate" \
    --metric-name 5xxErrorCount \
    --namespace AWS/MediaStore \
    --statistic Sum \
    --period 300 \
    --threshold 10 \
    --comparison-operator GreaterThanThreshold \
    --evaluation-periods 2 \
    --alarm-actions $SNS_TOPIC_ARN

Integración Final y Pruebas

1. Script de Prueba de Integración

python
# integration_test.py
import boto3
import requests
import time

def test_streaming_platform():
    # 1. Autenticación
    response = requests.post(f"{API_URL}/auth/login", json={
        "username": "test@example.com",
        "password": "Test123!"
    })
    token = response.json()['token']
    
    # 2. Obtener URL de streaming
    response = requests.get(
        f"{API_URL}/videos/sample",
        headers={"Authorization": f"Bearer {token}"}
    )
    stream_url = response.json()['url']
    
    # 3. Verificar acceso al stream
    response = requests.get(stream_url)
    assert response.status_code == 200
    
    return "All tests passed!"

if __name__ == "__main__":
    print(test_streaming_platform())

2. Configurar CI/CD para Tests

yaml
# .github/workflows/integration-tests.yml
name: Integration Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
    - name: Install dependencies
      run: pip install -r requirements.txt
    - name: Run integration tests
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      run: python integration_test.py

Verificación Final

1. Verificar Streaming

  • [ ] Upload de contenido funcional
  • [ ] Streaming HLS funcionando
  • [ ] CORS configurado correctamente
  • [ ] Métricas visibles en CloudWatch

2. Verificar Integración

  • [ ] Autenticación integrada con streaming
  • [ ] WAF protegiendo endpoints
  • [ ] Alarmas configuradas
  • [ ] Tests de integración pasando

3. Verificar Performance

  • [ ] Latencia aceptable
  • [ ] Escalamiento funcionando
  • [ ] Sin errores de memoria
  • [ ] Logs completos y útiles

Troubleshooting Final

Errores de Streaming

  1. Verificar permisos de MediaStore
  2. Revisar configuración de CORS
  3. Verificar formato de video

Errores de Integración

  1. Verificar flujo completo de autenticación
  2. Revisar configuración de WAF
  3. Verificar logs de aplicación

Problemas de Performance

  1. Revisar métricas de ECS
  2. Verificar configuración de ALB
  3. Revisar tamaño de contenedores

Limpieza Final

  1. Eliminar contenedor MediaStore
  2. Eliminar contenido de S3
  3. Eliminar alarmas CloudWatch
  4. Eliminar dashboard
  5. Eliminar reglas WAF
  6. Limpiar User Pool de Cognito
  7. Eliminar cluster ECS

Puntos Importantes

  1. MediaStore es optimizado para streaming
  2. La seguridad es multicapa (WAF, Cognito, HTTPS)
  3. El monitoreo es crucial para la calidad del servicio
  4. Los tests automatizados son esenciales

Para el examen Cloud Practitioner, enfócate en:

  • Comprensión de servicios multimedia de AWS
  • Integración entre servicios
  • Aspectos de seguridad
  • Monitoreo y logging

Con estas tres partes, hemos cubierto:

  1. Configuración de infraestructura base con ECS
  2. Implementación de seguridad con Cognito y WAF
  3. Configuración de streaming con MediaStore
  4. Integración completa y pruebas