Força do Elastic Beanstalk https

12

Estou tendo problemas ao forçar o HTTPS com um site que estou implantando no AWS Elastic Beanstalk.

É um aplicativo front-end usando o EmberJS. Ando em círculos há muitos dias tentando descobrir como redirecionar o tráfego http para https. Estou usando o Amazon Linux AMI na minha máquina EC2.

Cheguei à conclusão (ainda não tenho certeza se isso está correto) de que não é no Elastic Beanstalk que eu forço o HTTPS. Estou permitindo HTTP e HTTPS através do meu Elastic Beanstalk Load Balancer e estou tentando redirecionar para o servidor.

É aqui que estou tendo problemas. Estou encontrando muitas respostas sobre regras de reescrita sem as mod_rewritequais são baseadas no X-Forwarded-Protocabeçalho, mas esse arquivo não existe na minha máquina EC2 de acordo com uma pesquisa de localização.

Eu também tentei criar um arquivo de configuração dentro do .ebextensionsdiretório, mas isso também não funcionou.

A principal coisa que estou tentando fazer é direcionar os usuários para https quando tentam acessar o endereço http. Quaisquer sugestões ou sugestões são muito apreciadas, obrigado!

EDIT: Estou usando o Debian jessie v1.4.1 de 64 bits executando o Python 3.4 (pré-configurado - Docker)

awwester
fonte
Parece que a Internet não pode concordar com uma solução única, completa e funcional para esse problema. Espero que você possa obter ajuda aqui no meu post . Eu tive que pular aros para chegar a isso, finalmente.
ADTC

Respostas:

7

Eu acho que você precisa especificar qual ambiente do Elastic Beanstalk você usa (consulte: Plataformas suportadas ), porque um ambiente diferente tem uma configuração diferente.

Basicamente, você precisa personalizar:

  • Balanceador de carga elástico :
    • Ouça na porta 80 e faça proxy com a porta 80 da instância do EC2.
    • Ouça na porta 443 e faça proxy com a porta da instância EC2 443.
  • Servidor da Web EC2 / Proxy :
    • Ouça na porta 80 e responda com redirecionamento para HTTPS.
    • Ouça na porta 443 e atenda à solicitação.

Para personalizá-lo, você pode usar a CLI ou .ebextensions.

Você pode verificar Habilitar HTTPS e HTTP-Redirect no AWS Elastic Beanstalk . Ele mostra como configurar o Elastic Beanstalk Single Docker Container para HTTPS e HTTP (redirecionar para HTTPS). Você pode ajustar a configuração conforme sua necessidade.

Edward Samuel
fonte
ei, ótimo artigo, estou tentando isso.
awwester
Alguma idéia de como não incluir os certificados dentro desse arquivo, prefere não mantê-lo no controle de origem? Os certificados que carregamos já estão disponíveis em algum lugar? Eu não consigo encontrá-los no sistema de arquivos
awwester
Você pode colocar seu arquivo de certificado SSL no S3. Para permitir que o Elastic Beanstalk faça o download do objeto S3 privado, você pode ler isso .
Edward Samuel
Para o certificado SSL ELB, você pode seguir a documentação da AWS: Certificados SSL para Elastic Load Balancing . Depois, você pode obter o recurso de certificado SSL em arn:aws:iam::123456789012:server-certificate/YourSSLCertificateformato.
Edward Samuel
Eu tenho o certificado SSL configurado e tenho o arn que iria no 00-load-balancer (na verdade, estou fazendo a configuração do load balancer através da interface do usuário), mas não consigo obter o local para colocar no servidor configurações ssl_certificate /opt/ssl/default-ssl.crt;Quando eu começar a informação para o cert, dá-me um "caminho", mas é apenas "/"
awwester
10

Também é possível fazer isso com mais facilidade, sem tocar no balanceador de carga, usando o X-Forwarded-Protocabeçalho definido pelo ELB. Aqui está o que eu acabei fazendo:

files:
  "/etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf":
    mode: "00644"
    owner: root
    group: root
    content: |
      map $http_upgrade $connection_upgrade {
        default        "upgrade";
        ""            "";
      }

      server {
        listen 80;

        gzip on;
        gzip_comp_level 4;
        gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        access_log    /var/log/nginx/access.log;

        location / {
          proxy_pass            http://docker;
          proxy_http_version    1.1;

          proxy_set_header      Connection      $connection_upgrade;
          proxy_set_header      Upgrade         $http_upgrade;
          proxy_set_header      Host            $host;
          proxy_set_header      X-Real-IP       $remote_addr;
          proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        if ($http_x_forwarded_proto = 'http') {
          return 301 https://$host$request_uri;
        }
      }
FX
fonte
De longe a solução mais fácil. Não posso agradecer o suficiente!
Chris Martin
Sim, este é o caminho certo na maioria dos cenários.
jlegler
3

O Elastic Beanstalk não suporta várias portas de um contêiner de Docker único, portanto, você precisa lidar com isso no nível do proxy, conforme sugerido. No entanto, sua instância do EC2 não precisa saber sobre seu certificado, porque você pode encerrar a conexão SSL no balanceador de carga.

No seu .ebextensionsdiretório, crie uma configuração para o proxy nginx que contenha duas configurações do servidor; um que proxies http://docker(a configuração padrão, porta 80) e outro que redireciona para https (eu escolhi a porta 8080).

.ebextensions/01-nginx-proxy.config:

files:
  "/etc/nginx/sites-available/000-default.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      map $http_upgrade $connection_upgrade {
          default        "upgrade";
          ""            "";
      }

      server {
          listen 80;

          gzip on;
          gzip_comp_level 4;
          gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

          access_log    /var/log/nginx/access.log;

          location / {
              proxy_pass            http://docker;
              proxy_http_version    1.1;

              proxy_set_header    Connection            $connection_upgrade;
              proxy_set_header    Upgrade                $http_upgrade;
              proxy_set_header    Host                $host;
              proxy_set_header    X-Real-IP            $remote_addr;
              proxy_set_header    X-Forwarded-For        $proxy_add_x_forwarded_for;
          }
      }

      server {
          listen 8080;

          location / {
              return 301 https://$host$request_uri;
          }
      }

commands:
   00_enable_site:
    command: 'rm -f /etc/nginx/sites-enabled/* && ln -s /etc/nginx/sites-available/000-default.conf /etc/nginx/sites-enabled/000-default.conf'

Crie uma segunda configuração para o balanceador de carga EB e grupos de segurança que os define da seguinte maneira:

  • Instância EC2 :
    • Permitir tráfego nas portas 80/8080 do balanceador de carga
    • Permitir tráfego na porta 22 de qualquer lugar (para acesso ssh, opcional)
  • Balanceador de carga :
    • Encaminhar a porta 443 HTTPS para a porta 80 HTTP
    • Encaminhar HTTP da porta 80 para a porta 8080 HTTP

.ebextensions/02-load-balancer.config:

"Resources" : {
  "AWSEBSecurityGroup": {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
      "GroupDescription" : "Instance security group (22/80/8080 in)",
      "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "8080",
          "ToPort" : "8080",
          "SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "22",
          "ToPort" : "22",
          "CidrIp" : "0.0.0.0/0"
        } ]
    }
  },
  "AWSEBLoadBalancerSecurityGroup": {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
      "GroupDescription" : "Load balancer security group (80/443 in, 80/8080 out)",
      "VpcId" : "<vpc_id>",
      "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "CidrIp" : "0.0.0.0/0"
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "443",
          "ToPort" : "443",
          "CidrIp" : "0.0.0.0/0"
        } ],
      "SecurityGroupEgress": [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "CidrIp" : "0.0.0.0/0"
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "8080",
          "ToPort" : "8080",
          "CidrIp" : "0.0.0.0/0"
        } ]
    }
  },
  "AWSEBLoadBalancer" : {
    "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
    "Properties" : {
      "Listeners" : [ {
          "LoadBalancerPort" : "80",
          "InstancePort" : "8080",
          "Protocol" : "HTTP"
        }, {
          "LoadBalancerPort" : "443",
          "InstancePort" : "80",
          "Protocol" : "HTTPS",
          "SSLCertificateId" : "arn:aws:iam::<certificate_id>:<certificate_path>"
        } ]
    }
  }
}

(Nota: não esqueça de substituir SSLCertificateId e VpcId pelos seus valores).

Qualquer tráfego na porta 80 do balanceador de carga (HTTP) atingirá a porta 8080 na instância do EC2, que redireciona para HTTPS. O tráfego na porta 443 no balanceador de carga (HTTPS) acabará sendo atendido pela porta 80 na instância do EC2, que é o proxy do docker.

Michael de Hoog
fonte
0

Estou usando o Terraform para ativar o redirecionamento HTTP para HTTPS no ElasticBeanstalk,

Acabei de adicionar uma regra de ouvinte adicional

data "aws_alb_listener" "http" { //Get ARN of Listener on Port-80
  load_balancer_arn = aws_elastic_beanstalk_environment.myapp.load_balancers[0]
  port              = 80
}


resource "aws_alb_listener_rule" "redirect_http_to_https" {
  listener_arn = data.aws_alb_listener.http.arn
  action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
  condition {
    host_header {
      values = ["*.*"]
    }
  }
}
Denis Astahov
fonte