Eu tenho um aplicativo da web MVC .net core 6 que usa a autenticação OAuth2.0 do Google e não consigo publicá-lo com o Kubernetes.
Contexto do projeto:
Localmente ele compila e roda normalmente, inclusive criando uma imagem docker e executando um container, mas para rodar o container docker localmente e ter uma porta https com um certificado válido (preciso disso para o OAuth do Google funcionar) preciso executar o seguinte procedimento .
Sequência de comandos e procedimentos para tornar o certificado local confiável (você só precisa fazer isso para executar em um contêiner docker, não é necessário executar o projeto diretamente):
crie o certificado local pfx: dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\Apresentacao.Web.pfx -p pa55w0rd!
Crie uma linha de configuração UserScretsId no .csproj do aplicativo: {SomeGuidIdHere}
Digite a senha do certificado no local user-secrets: dotnet user-secrets set "Kestrel:Certificates:Development:Password" "pa55w0rd!"
tornar o certificado 'confiável' dotnet dev-certs https --trust
Execute o contêiner docker, mas passando por alguns parâmetros necessários (execute no powershell ou bash fora da pasta do projeto):
docker run -p 8080:80 -p 8081:443 -e ASPNETCORE\_URLS="https://+;http://+" -e ASPNETCORE\_HTTPS\_PORT="8081" -e ASPNETCORE\_ENVIRONMENT=Development - v $env:APPDATA\microsoft\UserSecrets\\:/root/.microsoft/usersecrets -v $env:USERPROFILE\\.aspnet\https:/root/.aspnet/https/ admin
Se eu não realizar o procedimento acima, ou executar 'Docker run' sem passar os parâmetros necessários para utilizar a porta https e o certificado, recebo o seguinte retorno ao executar o container:
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect.
Meu problema é: Localmente encontrei a solução para lidar com o contêiner docker, a porta https e o certificado SSL para localhost, porém estou publicando esta mesma aplicação no Google Cloud usando ações do Git Hub para executar meu pipeline de implantação e na nuvem eu estou salvando a janela de encaixe de imagens em um balde e criando um serviço com kubernetes. Já temos outras aplicações rodando nesta infraestrutura de nuvem do Google com Kubernetes e não tivemos problemas em expor as URLs com o Ingress e usar o certificado fornecido pelo Google.
Fiz vários testes publicando com configurações diferentes até suspeitar que poderia ser algo na aplicação, resolvi fazer um teste publicando sem a configuração de autenticação do Google e para minha surpresa a aplicação estava com status de saúde no Kubernetes e foi disponibilizada na URL com https corretamente. Quando incluo novamente a autenticação com Google no Startup.cs do projeto, meu problema retorna no container Kuberntes e ao acessar a URL o retorno que obtenho é um 502.
Veja como estou configurando a autenticação com o Google: Em Startup.cs
Método ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
//Auth config google
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{
options.ClientId = "{my_ClientId}";
options.ClientSecret = "{my_ClientSecret}";
});
...
}
Método de configuração:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/PaginaNaoEncontrada");
app.UseHsts();
}
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 404)
{
context.Request.Path = "/Home/PaginaNaoEncontrada";
await next();
}
});
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = o => { o.Context.Response.Headers.Append("Cache-Control", $"public, max-age=10800"); }
});
app.UseUnobtrusiveAjax();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication(); //Important
}
No meu HomeController.cs (onde bate minha primeira requisição ao acessar a aplicação pela primeira vez e onde eu valido que o Usuário está autenticado) a anotação [Autorizar] acima do Controlador é estritamente necessária para que o que adicionei no Startup funcione .cs :
[Authorize]
public class HomeController : Controller
{ ...}
Minha ação para o índice inicial:
[HttpGet]
return View();
LoginGoogle chamado por Index:
public ActionResult LoginGoogle(){
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, "Google");}
Para publicar no Kubernetes tenho os seguintes arquivos (destaco três deles porque considero que neles estão as configurações mais importantes para o site):
Meu deploymet é assim:
apiVersion: apps/v1
Meu Ingress é assim:
apiVersion: networking.k8s.io/v1
E meu serviço é assim:
apiVersion: v1
Com as alterações recentes que fiz em meus arquivos .yaml para Kubernetes, comecei a receber mais logs do serviço, semelhante ao que receberia localmente se executasse o comando 'Docker run' sem parâmetros para usar o certificado local: Últimos logs do contêiner: https://drive.google.com/file/d/1VcmiBe0LBuMr5B0VC5YivrvZdygZtEf5/view?usp=drive_link
Antes dessas alterações (principalmente no arquivo de implantação) eu estava recebendo o seguinte retorno nos logs: Logs anteriores: https://drive.google.com/file/d/16NoN1fhhmoGk2bZRWTY0oxqFBY3xH4Kj/view?usp=drive_link
Abaixo dos logs ilustrados acima havia apenas um loop infinito de informações sobre ResponseCoockies e as informações sobre a porta https não eram repetidas até que uma nova implantação fosse feita.
Como o serviço responde ao acessar a URL quando publicamos COM autenticação Google configurada: https://drive.google.com/file/d/1jDCmZNFPvzRvnq2VeOr7yC79A9Cba1rf/view?usp=drive_link
Minha pergunta é se estou configurando o Kubernetes ou falta algo para que o certificado seja confiável? Por que a implantação acontece normalmente quando removo a configuração de autenticação do Google do meu aplicativo? (Eu removo a configuração de inicialização e a anotação do controlador)
É importante observar que minhas credenciais de ID do cliente OAuth estão corretas, pois pude testar adicionando a URL https localhost como autorizada, portanto, esse também não seria o problema. Adicionei a URL que estou provisionando no Kubernetes na lista de URLs autorizadas a usar o Client Id OAuth, conforme segue: https://drive.google.com/file/d/1Hzi74jJ6sZ7za5D3rFZcyDQRaIoW4jOS/view?usp=drive_link
Outra informação.
Uma captura de tela de quando publico o aplicativo sem configuração de autenticação do Google e ele permanece ATIVO e o certificado parece estar vinculado ao URL e seguro:
https://drive.google.com/file/d/1RLocACa-TaCsmZo1S74sQoKrzvFgcfyx/view?usp=drive_link
Ao implantar com Ingress.yaml, ele cria um equilíbrio de carga na infraestrutura e configura automaticamente um endpoint front-end vinculado a um IP estático:
https://drive.google.com/file/d/1f1LyIzcDqUbEUEpPTh6VQqdwyshMeUVA/view?usp=drive_link
Utilizamos o serviço AWS para adquirir e hospedar domínios e para que ao acessar a URL que configurei meu DNS fosse resolvido para o IP do meu front end, configurei um 'Nome do registro' para ser redirecionado para o IP. Isso já foi feito para outras aplicações e funcionou, funciona até quando publicamos essa aplicação sem autenticação...
Abaixo está o cadastro que fiz na zona de hospedagem AWS: https://drive.google.com/file/d/1y8BIeK7RYywP95jPzpCGYkgZ7Lv-w7KG/view?usp=drive_link
E os detalhes do certificado fornecido pelo Google e que só ficou ‘Ativo’ quando a comunicação com AWS foi estabelecida devido ao mapeamento que fiz com o IP, conforme mencionado acima. https://drive.google.com/file/d/1Y9wLH_DDX-93iMY5eNwBN0VcDFbId5I1/view?usp=drive_link
Agradeço antecipadamente por sua ajuda
Encontramos a solução para o problema descrito acima. Basicamente, o container dentro do Kubernetes precisa que, além dos endpoints de health check, a url base da aplicação também esteja ativa, ou seja, eu não poderia estar tentando adicionar a anotação [Authorize] diretamente no meu HomeController pois ela foi o primeiro a ser exibido pelo aplicativo. Eu estava definindo o End-point "padrão" da minha aplicação da seguinte forma:
No entanto, o HomeController foi completamente coberto por [Authorize] e o aplicativo foi considerado insalubre no back-end do Kubernetes. Portanto, o que resolveu o principal problema foi criar uma tela de Login (sem aplicar [Autorizar]) para chamar o login do Google e alterar o endpoint padrão para ele:
Então o backend ficou heath e a aplicação subiu, primeiro chamando a tela de Login e depois clicando em "Login com Google" chamamos o OAuth 2.0 do Google, aqui está outro problema... a aplicação estava redirecionando para OAuth usando HTTP, mas precisávamos corrija isso para que seja redirecionado para HTTPS. Tentamos todas as soluções sugeridas, mas o que funcionou no nosso caso foi:
A documentação da Microsoft que usamos como base foi: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-6.0 Porém este documento. ficou confuso para nós, tentamos todas as sugestões e nada funcionou no nosso caso... até que as configurações Limpar para KnownNetworks e KnownProxies fizeram nosso aplicativo finalmente usar nosso redirecionamento para HTTPPS.