Workshop Microservices Microservices com Spring Cloud e Netflix OSS
Objetivos • Ao final desta unidade você compreenderá como: • Compreender as funcionalidades das plataformas Spring Cloud e Netflix OSS • Implementar um serviço de configuração centralizada utilizando Spring Cloud Config • Realizar o registro e descoberta dos serviços utilizando Netflix Eureka • Suportar tolerância à falhas e balanceamento de carga na chamada entre serviços com Netflix Ribbon • Tornar os serviços mais resilientes com a implementação de circuit breakers com Netflix Hystrix • Orquestrar a implementação de segurança entre serviços com Spring Cloud Security • Implementar um serviço de proxy e/ou roteamento utilizando Netflix Zuul
Agenda • Spring Cloud e Netflix OSS • Spring Cloud Config • Netflix Eureka • Netflix Ribbon e Feign • Netflix Hystrix • Spring Cloud Security • Netflix Zuul
Arquitetura Microservices
Microservices • Quais os principais desafios? • Gerenciamento de configuração • Registro e descoberta dos serviços • Roteamento • Balanceamento de carga • Tolerância à falhas
• Eureka • Hystrix • Ribbon • Zuul • + muitos outros… • API • Routing / Health check • Microservices • Logging • Data Management
Spring Cloud • Conjunto de bibliotecas / componentes • Não é apenas uma ferramenta • Integrado ao Spring Boot • Suporta diferentes arquiteturas e tecnologias em Cloud • AWS, Netflix, Heroku, Cloud Foundry, etc • Facilita a implementação de padrões necessários aos sistemas distribuídos “Toolset designed for building distributed systems”
Spring Cloud • Principais Componentes
Spring Cloud
Spring Cloud Component Camden.SR7 Dalston.RELEASE spring-cloud-aws 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-bus 1.2.2.RELEASE 1.3.0.RELEASE spring-cloud-cli 1.2.4.RELEASE 1.3.1.RELEASE spring-cloud-commons 1.1.9.RELEASE 1.3.0.RELEASE spring-cloud-contract 1.0.5.RELEASE 1.1.0.RELEASE spring-cloud-config 1.2.3.RELEASE 1.3.0.RELEASE spring-cloud-netflix 1.2.7.RELEASE 1.3.0.RELEASE spring-cloud-security 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-cloudfoundry 1.0.1.RELEASE 1.1.0.RELEASE spring-cloud-consul 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-sleuth 1.1.3.RELEASE 1.2.0.RELEASE spring-cloud-stream Brooklyn.SR3 Chelsea.SR1 spring-cloud-zookeeper 1.0.4.RELEASE 1.1.0.RELEASE spring-boot 1.4.5.RELEASE 1.5.2.RELEASE spring-cloud-task 1.0.3.RELEASE 1.1.3.RELEASE
Spring Cloud • Para adicionar no projeto basta incluir parent POM <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Spring Cloud + Netflix OSS "Casamento perfeito para criação de microservices auto-curáveis" Gerenciamento de configuração Spring Cloud Config + Bus Descoberta de serviços Netflix Eureka Balanceamento de carga Netflix Ribbon Tolerância à falhas Netflix Hystrix + Turbine Roteamento Netflix Zuul Segurança Spring Cloud Security
Spring Cloud + Netflix OSS
Gerenciamento de Configuração
Spring Cloud Config “Gerenciamento de configuração para micro-serviços“ • Centraliza a configuração da aplicação • Permite atualizações dinâmicas • Suporta versionamento • Suporte à rollback • Suporta configuração via repositórios • Git, SVN, filesystem • Permite atualização via barramento • Spring Cloud Bus
Spring Cloud Config • Serviço de configuração centralizado
Spring Cloud Config (server) • Basta adicionar a dependência Maven • Utilizar a anotação @EnableConfigServer <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> @EnableConfigServer @SpringBootApplication public class ConfigServer { public static void main(String[] args) { SpringApplication.run(ConfigServer.class, args); } }
Spring Cloud Config (server) • É necessário também configurar o repositório com as configurações externas server: port: 8888 spring: cloud: config: server: git: uri: file://config-repo $ cd $HOME $ mkdir config-repo $ cd config-repo $ git init . $ echo foo > application.properties $ git add -A . $ git commit -m “Initial commit"
Spring Cloud Config (server) @SpringBootApplication @EnableConfigServer public class ConfigServer {...} spring.cloud.config.git.uri: https://github.com/... ConfigServer.java application.yml
Spring Cloud Config (server) • É possível customizar configurações para utilização do repositório Git spring: cloud: config: server: git: uri: https://github.com/spring-cloud-samples/config-repo username: trolley password: strongpassword default-label: master force-pull: true basedir: file://server/local/path timeout: 60 clone-on-start: true search-paths: foo,bar*
Spring Cloud Config (server) • Suporta também utilização de diferentes repositórios Git de acordo com um padrão / perfil definido (12-factor) spring: cloud: config: server: git: uri: https://github.com/spring-cloud-samples/config-repo repos: development: pattern: - */development - */staging uri: https://github.com/development/config-repo staging: pattern: - */qa - */production uri: https://github.com/staging/config-repo
Spring Cloud Config (server) • Exemplo com configuração para SVN repo • Exemplo com configuração para Filesystem spring: profiles: active: subversion cloud: config: server: svn: uri: https://svn/config-repo default-label: trunk spring: profiles: active: native cloud: config: server: native: searchLocations: file://local/config-repo
Spring Cloud Config (server) • Suporta a manipulação de diferentes Spring Profiles • Basta acessar as configurações via HTTP REST no seguinte formato • /{application}/{profile}[/{label}] • /{application}-{profile}.yml • /{label}/{application}-{profile}.yml • /{application}-{profile}.properties • /{label}/{application}-{profile}.properties • YML • Você configura dentro do próprio arquivo • Separando por --- • Properties • application.properties • application-dev.properties • application-prod.properties logging: level: debug --- spring: profiles: dev, prod logging: level: info application.yml
Spring Cloud Config (client)
Spring Cloud Config (client) • Basta adicionar a dependência Maven • Configurar o arquivo bootstrap.yml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> spring: application: name: microservice1 cloud: config: uri: http://localhost:8888
Spring Cloud Config (client) @RefreshScope @Component public class AppComponent { @Value("${thread-pool}") private int threadPool; @Value("${email}") private String email; @Autowired Environment env } • É possível buscar as propriedades definidas pelo Config Server utilizando @Value e Spring Environment • Existe a possibilidade de atualizar as propriedades sem derrubar a aplicação, utilizando a anotação @RefreshScope • POST http://localhost:8080/refresh
Laboratório 1 (cloud-lab01) • Centralizando a configuração com Spring Cloud Config
Spring Cloud Config + Bus
• Exemplo da arquitetura de replicação de configuração utilizada Spring Cloud Config + Bus
• Lightweight AMQP Messaging Broker • Arquitetura flexível e fornece extensões para outros protocolos • HTTP, STOMP, MQTT • Ótima integração com Spring • Spring Boot, Cloud Bus, Cloud Stream, Messaging • Instalação • Windows • https://www.rabbitmq.com/install-windows.html • Mac OS X • brew install rabbitmq • Linux • apt-get install rabbitmq-server • yum install rabbitmq-server • Web Console • http://localhost:15672 • user: guest / password: guest RabbitMQ
Spring Cloud Config + Bus (server) • É necessário adicionar as seguintes dependências • É suportado também a utilização de Kafka ou Redis como implementação do barramento <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-monitor</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency> spring: cloud: bus: enabled: true rabbitmq: host: localhost port: 5672 • Deve ser ativado o suporte ao barramento via properties
Spring Cloud Config + Bus (client) • É necessário adicionar as seguintes dependências • Incorporar a seguinte configuração no bootstrap.yml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> spring: application: name: microservice1 cloud: config: uri: http://localhost:8888 rabbitmq: host: localhost port: 5672
Spring Cloud Config + Bus • Configuração do Webhook no repositório Git
Laboratório 2 (cloud-lab02) • Replicando a configuração centralizada com Spring Cloud Config Bus
Registro e Descoberta de Serviços
Registro e Descoberta de Serviços
Registro e Descoberta de Serviços
Registro e Descoberta de Serviços Service Register Health Check
Netflix Eureka "Transparência de localização aos micro-serviços“ • Registro de serviços REST based • Suporte à replicação • Cache aplicado no stub cliente • Resiliente • Rápido… mas não consistente • Fornece o alicerce para outros serviços • Mantém registro de clientes com metadados
Netflix Eureka (server) • Basta adicionar a dependência Maven • Utilizar a anotação @EnableEurekaServer <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> @SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }
Netflix Eureka (server) • Exemplo de configuração básica application.yml • Para acessar o Eureka Dashboard Web • http://localhost:8761 server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Netflix Eureka (server)
Netflix Eureka @SpringBootApplication @EnableEurekaServer public class EurekaServer {...} EurekaServer.java
Netflix Eureka (client) • Basta adicionar a dependência Maven • Utilizar a anotação @EnableDiscoveryClient <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> @EnableDiscoveryClient @SpringBootApplication public class EurekaClient { public static void main(String[] args) { SpringApplication.run(EurekaClient.class, args); } }
Netflix Eureka (client) • Exemplo de configuração básica application.yml • Cliente será registrado no Eureka Server spring: application: name: spring-cloud-eureka-client eureka: client: serviceUrl: defaultZone: ${EUREKA_URI:http://localhost:8761/eureka} instance: preferIpAddress: true
Netflix Eureka (client) • Exemplo utilizando DiscoveryClient @RestController public class ProductController { @Autowired DiscoveryClient discoveryClient; @GetMapping("/get/customers") public void getCustomers() throws Exception { List<ServiceInstance> instances = discoveryClient.getInstances("customer-service"); ServiceInstance firstOne = instances.get(0); String uri = "http://" + firstOne.getHost() + ":" + firstOne.getPort(); HttpGet getRequest = new HttpGet(uri + "/customers"); DefaultHttpClient httpClient = new DefaultHttpClient(); HttpResponse response = httpClient.execute(getRequest); // ... } }
Netflix Eureka (client) • Exemplo utilizando RestTemplate @RestController public class ProductController { @Autowired RestTemplate restTemplate; @GetMapping("/get/customers") public void getCustomers() throws Exception { // use the "smart" Eureka-aware RestTemplate ResponseEntity<List<CustomerDTO>> exchange = this.restTemplate.exchange( "http://customer-service/customers", HttpMethod.GET, null, new ParameterizedTypeReference<List<CustomerDTO>>() {}, (Object) null); // ... } }
Laboratório 3 (cloud-lab03) • Registrando e descobrindo serviços com Netflix Eureka
Netflix Eureka
Netflix Eureka
Netflix Eureka • Para configurar o mecanismo de suporte à replicação --- spring: profiles: peer1 eureka: instance: hostname: peer1 client: serviceUrl: defaultZone: http://peer2:[port]/eureka/ --- spring: profiles: peer2 eureka: instance: hostname: peer2 client: serviceUrl: defaultZone: http://peer1:[port]/eureka/ ## Hosts / IPs peer1 127.0.0.1 peer2 127.0.0.1 /etc/hosts application.yml
Netflix Eureka
Laboratório 4 (cloud-lab04) • Ativando o suporte à replicação com Netflix Eureka
Balanceamento de Carga
Balanceamento de Carga
Netflix Ribbon "Balanceamento de carga para microservices" • Balanceamento decentralizado no cliente • Resiliente • Suporte à tolerância a falhas • Trabalha com múltiplos protocolos • HTTP, TCP, UDP • Modelo assíncrono e reativo • Suporte à caching e batching • Múltiplos algoritmos de balanceamento
Netflix Ribbon
Netflix Ribbon • Basta adicionar a dependência Maven • Pode ser utilizado de duas maneiras • Diretamente (sem Eureka) • Por meio do objeto LoadBalancerClient • Utilizando configurações na aplicação • Properties, Ribbon Client Configuration • Por meio de anotações • @RibbonClient, @LoadBalanced • Integrado (com Eureka) • Pode ser customizado via propriedades <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
Netflix Ribbon • Exemplo de configuração do Ribbon client public class GroupRibbonConfiguration { @Autowired IClientConfig ribbonClientConfig; @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } @Bean public IRule ribbonRule(IClientConfig config) { return new AvailabilityFilteringRule(); } } group-service: ribbon: eureka: enabled: false listOfServers: localhost:9092,localhost:9999 ServerListRefreshInterval: 15000
Netflix Ribbon • Configurações possíveis para Ribbon Configuration • IClientConfig • Define a configuração para o cliente do load balancer • ServerList<Server> • Define como recuperar a lista de servidores para escolha • ServerListFilter<Server> • Define uma lista de filtro para a lista de servidores para escolha • ILoanBalancer • Representa o software de load balancer • IRule • Descreve a estratégia de load balancing • IPing • Define qual a periodicidade dos pings realizados
Netflix Ribbon • Configurações possíveis para IRule • AvailabilityFilteringRule • ClientConfigEnabledRoundRobinRule • RandomRule • ResponseTimeWeightedRule • RetryRule • RoundRobinRule • WeightedResponseTimeRule • ZoneAvoidanceRule
Netflix Ribbon • Configurações possíveis para ILoadBalancer • BaseLoadBalancer • DynamicServerListLoadBalancer • NoOpLoadBalancer • ZoneAwareLoadBalancer • Configurações possíveis para IPing • DummyPing • NoOpPing • PingConstant
Netflix Ribbon • Uso direto via LoadBalancerClient @RestController @RibbonClient(name = "group-service", configuration = GroupRibbonConfiguration.class) public class UserController { @Autowired LoadBalancerClient loadBalancer; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { ServiceInstance instance = loadBalancer.choose("group-service"); URI storesUri = URI.create(String.format(“http://%s:%s", instance.getHost(), instance.getPort())); // ... do something with the URI } }
Netflix Ribbon • Uso direto via @LoadBalanced @RestController @RibbonClient(name = "group-service", configuration = GroupRibbonConfiguration.class) public class UserController { @LoadBalanced @Bean RestTemplate restTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { return this.restTemplate.getForObject( "http://group-service/user/" + id, Group.class); } }
Netflix Ribbon @EnableDiscoveryClient @SpringBootApplication public class RibbonEurekaClient { public static void main(String[] args) { SpringApplication.run(RibbonEurekaClient.class, args); } } spring: application: name: ribbon-client eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka instance: preferIpAddress: true • Exemplo de uso com Eureka
Netflix Ribbon • Exemplo de uso com Eureka • group-service é um serviço registrado no Eureka @RestController public class UserController { @LoadBalanced @Bean RestTemplate restTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { return this.restTemplate.getForObject( "http://group-service/user/" + id, Group.class); } }
Laboratório 5 (cloud-lab05) • Implementando balanceamento de carga e tolerância à falhas com Netflix Ribbon
Netflix Feign • Facilita criação de clientes REST • Ótima integração com Spring Cloud • Suporta implementação de circuit breakers • Simples, produtivo e customizável • Pode ser utilizado em conjunto com • Ribbon - balanceamento de carga • Eureka - descoberta dos serviços “Declarative REST interfaces"
Netflix Feign • Basta adicionar a dependência Maven • Utilizar a anotação @EnableFeignClients <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> @EnableFeignClients @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Netflix Feign • Exemplo de uso com Eureka (service-id) • Utilização com URL externas @FeignClient("stores-service") public interface StoreClient { @RequestMapping(method = RequestMethod.GET, value = "/stores") List<Store> getStores(); @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json") Store update(@PathVariable("storeId") Long storeId, Store store); } @FeignClient(name = "stores-service", url = "http://example.com") public interface StoreClient {}
Netflix Feign • Exemplo de customização de configurações @Configuration public class CustomFeignConfiguration { static final int FIVE_SECONDS = 5000; @Bean public Logger.Level feignLogger() { return Logger.Level.FULL; } @Bean public Request.Options options() { return new Request.Options(FIVE_SECONDS, FIVE_SECONDS); } } @FeignClient(value = "stores-service", configuration = CustomFeignConfiguration.class) public interface StoreClient {...}
Netflix Feign • Configurações opcionais • Decoder: decodificação do response payload • Encoder: codificação do request payload • Logger: definição da engine de logging • Contract: configuração para utilizando Spring Cloud Contract • Feign.Builder: customização do Builder Feign • Logger.Level: definição do nível de logging • Retryer: estratégia para implementação de retry • ErrorDecoder: decodificação para erros no response • Request.Options: opções para customização das requisições
Netflix Feign • Oferece suporte à compressão do request e response • Funcionamento similar as configurações fornecidas pelo Web server • Ótimo para melhoria de performance em requisições e respostas com muitos dados envolvidos feign.compression.request.enabled=true feign.compression.response.enabled=true feign.compression.request.mime-types=application/xml,application/json feign.compression.request.min-request-size=2048
Netflix Feign • Oferece customização para mecanismo logging • Pode ser definido logging por Feign client definido • Ou pode ser alterado o nível de log padrão Logger.Level • NONE: Nenhuma impressão de log • BASIC: Apenas dos métodos de request, URL, e status de respostas • HEADERS: Informação básica sobre headers do request / response • FULL: Headers, body, e metadados das requisições e respostas logging.level.project.user.UserClient: DEBUG @Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
Netflix Feign • Oferece também uma Feign Client Builder API public interface BookClient { @RequestLine("GET /{isbn}") BookResource findByIsbn(@Param("isbn") String isbn); @RequestLine("GET") List<BookResource> findAll(); @RequestLine("POST") @Headers("Content-Type: application/json") void create(Book book); } BookClient bookClient = Feign.builder() .client(new OkHttpClient()) .encoder(new GsonEncoder()) .decoder(new GsonDecoder()) .logger(new Slf4jLogger(BookClient.class)) .logLevel(Logger.Level.FULL) .target(BookClient.class, "http://localhost:8081/api/books");
Netflix Feign • É possível customizar diferentes Enconder e Decoder • GSON • Jackson • Sax • JAXB Feign.builder() .encoder(new GsonEncoder()) .decoder(new GsonDecoder()); Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()); Feign.builder() .decoder(SAXDecoder.builder() .registerContentHandler(UserIdHandler.class) .build()); Feign.builder() .encoder(new JAXBEncoder()) .decoder(new JAXBDecoder());
Netflix Feign • Outras configurações também são suportadas • JAX-RS • OkHttp • SLF4J Feign.builder().contract(new JAXRSContract()); Feign.builder().client(new OkHttpClient()); Feign.builder().logger(new Slf4jLogger()); interface GitHub { @GET @Path("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @PathParam("owner") String owner, @PathParam(“repo") String repo); }
Netflix Feign • Para trabalhar com Spring MultipartFile <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form-spring</artifactId> <version>2.1.0</version> </dependency> @Configuration class MultipartSupportConfig { @Bean @Primary @Scope("prototype") Encoder feignFormEncoder() { return new SpringFormEncoder(); } } @FeignClient(name = "file-upload-service", configuration = MultipartSupportConfig.class) interface ServiceClient { @RequestMapping(method = RequestMethod.POST, value = "/upload") ResponseEntity upload(@RequestPart(value="content") MultipartFile file) }
Netflix Feign • Sugestão de design para implementação nas aplicações public interface UserService { @RequestMapping(method = RequestMethod.GET, value ="/users/{id}") User getUser(@PathVariable("id") long id); } @RestController public class UserRestController implements UserService { User getUser(@PathVariable("id") long id) { // Implement the REST endpoint } } @FeignClient("users") public interface UserClient extends UserService { // Empty }
Laboratório 6 (cloud-lab06) • Implementando clientes REST com Netflix Feign
Tolerância à Falhas
Tolerância à Falhas
Tolerância à Falhas
Netflix Hystrix “Tolerância à falhas para micro-serviços“ • Implementa padrão circuit breakers • Fornece monitoramento aos serviços • Hystrix dashboard • Suporta comandos assíncronos • Utiliza diferentes thread pools • Pode implementar timeouts
Netflix Hystrix • Circuit Breaker Pattern • Máquina de estados • Closed, Open, Half-Open • Falha não é propagada para chamada do cliente
Netflix Hystrix • Basta adicionar a dependência Maven • Utilizar a anotação @EnableCircuitBreaker <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> @EnableCircuitBreaker @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
• Exemplo de implementação @HystrixCommand Netflix Hystrix public class StoreIntegration { @HystrixCommand(fallbackMethod = "defaultStores") public Object getStores(Map<String, Object> parameters) { //do stuff that might fail } public Object defaultStores(Map<String, Object> parameters) { return /* something useful */; } }
Netflix Hystrix
Netflix Hystrix • Suporte integrado ao Feign via Hystrix Fallback @FeignClient(name = "service-to-call", fallback = FeignClientFallback.class) public interface FeignClient { @RequestMapping(value = "/rest/do", method = RequestMethod.GET) ResponseEntity<String> doSomething(); } @Component public class FeignClientFallback implements FeignClient { @Override public ResponseEntity<String> doSomething() { return ResponseEntity.ok("fallback"); } }
Netflix Hystrix • Configurações possíveis para Hystrix Command • Execution • execution.isolation.strategy • execution.isolation.thread.timeoutInMilliseconds • execution.timeout.enabled • execution.isolation.thread.interruptOnTimeout • execution.isolation.thread.interruptOnCancel • execution.isolation.semaphore.maxConcurrentRequests • Fallback • fallback.isolation.semaphore.maxConcurrentRequests • fallback.enabled https://github.com/Netflix/Hystrix/wiki/Configuration
Netflix Hystrix • Configurações possíveis para Hystrix Command • Circuit Breaker • circuitBreaker.enabled • circuitBreaker.requestVolumeThreshold • circuitBreaker.sleepWindowInMilliseconds • circuitBreaker.errorThresholdPercentage • circuitBreaker.forceOpen • circuitBreaker.forceClosed • Request Context • requestCache.enabled • requestLog.enabled https://github.com/Netflix/Hystrix/wiki/Configuration
Netflix Hystrix • Configurações possíveis para Hystrix Command • Metrics • metrics.rollingStats.timeInMilliseconds • metrics.rollingStats.numBuckets • metrics.rollingPercentile.enabled • metrics.rollingPercentile.timeInMilliseconds • metrics.rollingPercentile.numBuckets • metrics.rollingPercentile.bucketSize • metrics.healthSnapshot.intervalInMilliseconds https://github.com/Netflix/Hystrix/wiki/Configuration
Netflix Hystrix • Outras possíveis configurações • Collapser Properties • maxRequestsInBatch • timerDelayInMilliseconds • requestCache.enabled • Thread Pool • coreSize • maximumSize • maxQueueSize • queueSizeRejectionThreshold • keepAliveTimeMinutes • allowMaximumSizeToDivergeFromCoreSize https://github.com/Netflix/Hystrix/wiki/Configuration
Netflix Hystrix • Propriedades podem ser configuradas via anotação • @HystrixCommand e @HystrixProperty @HystrixCommand(fallbackMethod = "defaultStores", commandProperties = { @HystrixProperty(name="execution.isolation.strategy", value="THREAD"), @HystrixProperty(name="requestCache.enabled", value="false") },threadPoolProperties = { @HystrixProperty(name="coreSize", value="5"), @HystrixProperty(name="maximumSize", value="5") }) public Object getStores(Map<String, Object> parameters) { //do stuff that might fail }
Netflix Hystrix • Propriedades podem ser configuradas via YML hystrix: command: FeignClient#doSomething(): execution: isolation: strategy: SEMAPHORE semaphore: maxConcurrentRequests: 5 fallback: isolation: semaphore: maxConcurrentRequests: 5 circuitBreaker: requestVolumeThreshold: 5 application.yml
Netflix Hystrix • Estratégia de execução THREAD vs. SEMAPHORE
Laboratório 7 (cloud-lab07) • Implementando circuit breakers com Netflix Hystrix
Hystrix Dashboard
Hystrix Dashboard • Basta adicionar a dependência Maven • Utilizar a anotação @EnableHystrixDashboard <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> @EnableHystrixDashboard @SpringBootApplication public class HytrixDashboard { public static void main(String[] args) { SpringApplication.run(HytrixDashboard.class, args); } }
Hystrix Dashboard • Para visualizar o dashboard basta acessar o endereço • http://localhost:[port]/hystrix
Hystrix Dashboard • Visualização do painel de circuitos para um serviço
Hystrix Dashboard
Netflix Turbine • Agregador dos eventos Hystrix
Netflix Turbine • Basta adicionar a dependência Maven • Utilizar a anotação @EnableTurbine • Pode ser utilizando em conjunto Hystrix Dashboard <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId> </dependency> @EnableTurbine @SpringBootApplication public class TurbineApplication { public static void main(String[] args) { SpringApplication.run(TurbineApplication.class, args); } }
Netflix Turbine • É necessário configurar um cluster para visualização dos eventos gerados pelos serviços • Utiliza o registro Eureka para localização dos serviços • Basta adicionar uma configuração nas propriedades • Pode ser definido diferentes configurações de clusters (views) • http://turbine.sever/turbine.stream?cluster=<CLUSTERNAME> turbine: appConfig: service-a, service-b clusterNameExpression: "'default'" turbine: aggregator: clusterConfig: STORE appConfig: customers,stores,ui,admin
Netflix Turbine • Para acessar o endereço do Turbine no Hystrix Dashboard • http://turbine.server:[port]/turbine.stream
• Agregador dos eventos Hystrix assíncrono Netflix Turbine Stream
• Utiliza um sistema de mensagens assíncrono para publicar e processar os eventos Hystrix • Pode ser utilizado com diferentes middleware • RabbitMQ, ActiveMQ, Apache Kafta, etc • Cada serviço publica seus eventos na fila processada pelo Turbine Netflix Turbine Stream
Netflix Turbine Stream (server) • Basta adicionar a dependência Maven • É necessário também adicionar a dependência de um Stream (Rabbit, Kafta, etc) • spring-cloud-starter-stream-rabbit • Utilizar a anotação @EnableTurbineStream <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine-stream</artifactId> </dependency> @EnableTurbineStream @SpringBootApplication public class TurbineStreamApplication {}
Netflix Turbine Stream (client) • Necessário adicionar a dependência Hystrix stream • Também necessário adicionar a dependência de um Stream (Rabbit, Kafta, etc) • spring-cloud-starter-stream-rabbit • Caso necessário configurar as propriedades de configuração no Stream adicionado <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-hystrix-stream</artifactId> </dependency>
Laboratório 8 (cloud-lab08) • Monitorando os circuitos com Hystrix Dashboard e Turbine
Segurança Closed ClosedOpen Autenticação Autorização
Principais requisitos de segurança? • Como identificar as permissões que serão manipuladas? • Como a informação será codificada e decodificada? • Quais dados serão necessários para restrição de acesso? • Quem será responsável por armazenar e fornecer os dados de segurança? • Como identificar se a requisição não foi modificada? “Stop bad guys from accessing your resources"
Segurança com REST • Algumas estratégias para proteger os serviços • Basic Auth (HTTP Basic) • Network Security • Certificate Based • Arquitetura RESTful não define procedimentos de segurança • HTTP methods: GET, POST, PUT, DELETE • API’s REST são tão vulneráveis quanto aplicações web tradicionais • SQL Injection, replay attacks, cross-site scripting, etc
HTTP Basic Auth • Qual o problema com isto? • Nada, mas… • Em qual lugar você busca as credenciais? • Ok para sistemas onde todos os participantes podem compartilhar dados confidenciais de um modo seguro • Apenas suporta informações de "usuário / senha” • Apenas trabalha com autenticação • Sem distinção entre usuários e máquinas $ curl “https://$username:$password@myhost/resource"
Network Security • Qual o problema com isto? • Nada, mas… • Chato para "debugar" e um pouco difícil de manter • Configuração fica fora do escopo de desenvolvedores • Não existe o conceito de identidade e autenticação "Security architecture based on top of web server"
Certificate Based • Qual o problema com isto? • Nada, mas… • Não existe o conceito de identidade, apenas caso o browser tenha os certificados instalados • Obriga keystores e certificados nas aplicações e nos serviços • Não existe uma distinção muito clara quanto a usuários e máquinas $ curl -k -cert file.pem:password https://myhost:443/resource
OAuth 2.0 • Protocolo baseado em uma especificação de padrão aberto definido pelo IETF • Habilita as aplicações acessarem e compartilharem serviços sem necessidade de compartilhar credenciais • Evita problemas com "passwords" • Essencial para mecanismo via delegação de acesso • Aplicações terceiras • Para serviços específicos • Por um tempo limitado • Pode trabalhar com revogação seletiva
Quem utiliza OAuth
OAuth Timeline • OAuth 1.0 • Especificação core publicada em dezembro/2007 • OAuth 1.0a • Especificação revisada publicada em junho/2009 • Relacionado a correções de vulnerabilidades de segurança • OAuth 2.0 • Especificação publicada em outubro/2012 • Ser mais seguro, simples e padronizado • RFCs adicionais ainda continuam sendo trabalhadas
OAuth 2.0 Tokens • Tipos • Bearer • Large random token • Necessita de SSL para proteção em transito • Servidor necessita gerar e armazenar este hash • Mac • Utilizado para evitar repetição • Não requer a utilização de SSL • Apenas suportado no OAuth 1.0 • Access Token • Short-lived token • Refresh Token • Long-lived token { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":“bearer", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", }
OAuth 2.0 Flow
OAuth 2.0 Flow
Papéis Envolvidos • Resource Server • Proteção dos serviços • Authorization Server • Emissão de tokens de acesso para os clientes • Client Application • Solicita os serviços protegidos em nome do proprietário • Resource Owner • Concede o acesso a um serviço protegido
OAuth 2.0 Grant Types • Authorization Code (web apps) • Confidencialidade aos clientes • Utiliza um código de autorização emitido pelo servidor • Implicit (browser-based and mobile apps) • Script heavy web apps • Usuário final pode ver o access token gerado • Resource Owner Password Credentials (user / password) • Utilizado em casos aonde o usuário confia no cliente • Expõe as credenciais do usuário para o cliente • Client Credentials (application) • Clientes recebem um token (secret) para acesso • Ideal para acesso entre aplicações
OAuth 2.0 Grant Types • Authorization Code http://server/oauth/authorize?response_type=code&client_id=client &scope=read+write+trust &redirect_uri=http://localhost/app http://server/oauth/token?grant_type=authorization_code&code=SkiGJ8 &client_id=client &client_secret=secret &redirect_uri=http://localhost/app {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
OAuth 2.0 Grant Types • Implicit http://server/oauth/authorize?response_type=token&client_id=client &scope=read+write+trust &redirect_uri=http://localhost/app http://localhost/app/#?access_token=292e1ec1-fda9-4968- b1c3-7cc0dd99483f
OAuth 2.0 Grant Types • Resource Owner Password Credentials http://server/oauth/token?grant_type=password&client_id=client &client_secret=secret &username=admin &password=admin {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
OAuth 2.0 Grant Types • Client Credentials http://server/oauth/token?grant_type=client_credentials &client_id=client&client_secret=secret {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
OAuth 2.0 Prós & Contras • Prós • Ótima integração para acesso de aplicações à serviços oferecidos por web sites • Acesso permitido para um escopo limitado ou por tempo (duração) • Sem necessidade de compartilhamento de passwords com aplicações terceiras • Contras • Implementação pode ser um pouco complexa • Problemas de interoperabilidade • Algumas más implementações podem expor falhas de segurança
Spring Security OAuth • Oferece implementação para OAuth (1a) e OAuth2 • Implementa os 4 tipos de authorization grants • Suporta todos os requisitos definidos pelo OAuth2 • Authorization Server • Resources Server • Client • Ótima integração com Spring MVC e JAX-RS • Configuração utilizando anotações • Integração com todo o eco-sistema Spring
Spring Authorization Server • @EnableAuthorizationServer • Anotação utilizada para configurar OAuth2 authorization server • Existe também disponível em XML <authorization-server/> • ClientDetailsServiceConfigurer • Define os detalhes do cliente do serviço • Implementação in-memory ou via JDBC • AuthorizationServerTokenServices • Operações para gerenciar OAuth2 tokens • Tokens in-memory, JDBC ou JSON Web Token (JWT) • AuthorizationServerEndpointConfigurer • Fornece os grant types suportado pelo servidor • Todos os grant types são suportados exceto via password
Spring Resource Server • Pode ser a mesma instância do Authorization Server • Ou então instalado como uma aplicação separada • Fornece um filtro de autenticação para aplicações web • @EnableResourceServer • Anotação utilizada para configurar OAuth2 resource server • Existe também disponível em XML <resource-server/> • Suporta controle de acesso via expressions • #oauth2.hasScope • #oauth2.clientHasRole • #oauth2.clientHasAnyRole • #oauth2.denyClient
Spring OAuth2 Client • Cria um filtro para armazenar o contexto do request • Gerencia o redirecionamento de/para o servidor de autenticação OAuth2 • @EnableOAuth2Client • Anotação utilizada para configurar o OAuth2 client • Existe também disponível em XML <client/> • OAuth2RestTemplate • Wrapper client object para acessar os serviços
Authorization Server @Configuration @EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess(“permitAll()”) .checkTokenAccess("isAuthenticated()"); } @Override public void configure( ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("SampleClientId") .secret("secret") .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) ; } }
Resource Server @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/users/ping").permitAll() .antMatchers("/users/current").authenticated() .anyRequest().authenticated(); } }
Laboratório 9 (cloud-lab09) • Implementando e manipulando segurança com o protocolo OAuth2
JSON Web Token “Padrão aberto que define uma forma compacta e auto-contida para transmitir de forma segura, informações entre duas partes“
JSON Web Token • Basta adicionar a dependência Maven • Definir um JwtTokenStore • Configurar um JwtAccessTokenConverter • Utilizando chaves simétricas, ou assimétricas • Configurar o modelo geração e validação de JWT tokens nos serviços de autorização e recursos OAuth2 <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency>
JSON Web Token • Configuração utilizando modelo simétrico de chaves @Configuration public class JwtConfig { @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey("123"); return converter; } }
JSON Web Token • Modelo assimétrico de chaves (chave privada) @Configuration public class JwtConfig { //... @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(“mykeys.jks"), "mypass".toCharArray()); converter.setKeyPair( keyStoreKeyFactory.getKeyPair("security-server")); return converter; } }
JSON Web Token • Modelo assimétrico de chaves (chave pública) @Configuration public class JwtConfig { //... public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); Resource resource = new ClassPathResource("public.txt"); String publicKey = null; try { publicKey = IOUtils.toString(resource.getInputStream()); } catch (final IOException e) { throw new RuntimeException(e); } converter.setVerifierKey(publicKey); return converter; } }
JSON Web Token • Para realizar a geração do par de chaves (privada e pública) pode ser utilizado keytool • Para exportar a chave pública, pode ser utilizado openssl keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore mytest.jks -storepass mypass keytool -list -rfc --keystore mytest.jks | openssl x509 -inform pem -pubkey -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgIK2Wt4x2EtDl41C7vfp OsMquZMyOyteO2RsVeMLF/hXIeYvicKr0SQzVkodHEBCMiGXQDz5prijTq3RHPy2 /5WJBCYq7yHgTLvspMy6sivXN7NdYE7I5pXo/KHk4nz+Fa6P3L8+L90E/3qwf6j3 DKWnAgJFRY8AbSYXt1d5ELiIG1/gEqzC0fZmNhhfrBtxwWXrlpUDT0Kfvf0QVmPR xxCLXT+tEe1seWGEqeOLL5vXRLqmzZcBe1RZ9kQQm43+a9Qn5icSRnDfTAesQ3Cr lAWJKl2kcWU1HwJqw+dZRSZ1X4kEXNMyzPdPBbGmU6MHdhpywI7SKZT7mX4BDnUK eQIDAQAB -----END PUBLIC KEY-----
JWT Response • Exemplo de resposta utilizando JWT { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTMyODMxNzksInVzZXJfbmFtZSI6 InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIiwiTUFOQUdFUiJdLCJqdGkiOiJkMGY5OTY2OC01Nz dkLTRkZTEtODkwYi1hNDY1MTBkZjg2YjAiLCJjbGllbnRfaWQiOiJjbGllbnQiLCJzY29wZSI6WyJv cGVuaWQiXX0.iH1pnwJZPZi05hdpY9MDGIvtx34Dj8lxc5fdU5c5NCCtUblT_L9kdZO6NaOIIZffbG zSHoyVUEZkSwkGXm6lT1jRTcOHq2khAZlwmO3hN3c1xb8bumAgmpF8fJSIKTVIkFJpbVO4uDfHSSbB m6QsTbqHkNgNwWSWbNG1n6ZlsHCcZCh37cmgbh- B4tPD9QEfH3CSI6Z7AgUbS9UCIytjm02sgxgAr3liOcykRrdcOvxgIBx_yGDvornQ5JOBVdW-TS0- uJmHe6sHCFYeBNchJhRi7xqZCMYFD6IcP4dftPupzg3IMl5oWberxhZTCCLoi18JtQyZgIgqmSlOAI q8wg", "token_type": "bearer", "expires_in": 43199, "scope": "openid", "jti": "d0f99668-577d-4de1-890b-a46510df86b0" }
JWT Response • É possível informações extras no JWT gerado implementando customizações via TokenEnhancer public class CustomTokenEnhancer implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put("organization", authentication.getName() + randomAlphabetic(4)); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation( additionalInfo); return accessToken; } }
JWT Response • Exemplo de payload com informações extras adicionadas via TokenEnhancer { "user_name": "john", "scope": [ "foo", "read", "write" ], "organization": "johnIiCh", "exp": 1458126622, "authorities": [ "ROLE_USER" ], "jti": "e0ad1ef3-a8a5-4eef-998d-00b26bc2c53f", "client_id": "fooClientIdPassword" }
Laboratório 10 (cloud-lab10) • Trabalhando com JSON Web Tokens
Spring Cloud Security “Segurança aplicada para microservices" • Integração com Spring Security + OAuth2 • Proteção dos serviços com tokens (JWT) • SSO com OAuth2 e OpenID Connect • Transmissão tokens entre SSO e apps • OAuth2 + JWT + SSO ;)
Spring Cloud Security Discovery Client Relying Party Resource Server Get an access token & an ID Token (JWT) Use an access token Authorization Server Iden.ty	Provider	or IDP	or OpenID	Provider	or OP Authorization Endpoint Token Endpoint Important Stuff Userinfo Endpoint Registration Endpoint JWKS Endpoint JWKS Endpoint Validate (JWT) ID Token /.well-known /webfinger /openid-configura.on Check Session IFrame End Session Endpoint
Spring Cloud Security • Basta adicionar a seguinte dependência Maven • Integração dos projetos Spring Security OAuth2 + JWT • spring-security-oauth2 e spring-security-jwt • Customizações de segurança as projetos Spring Cloud • OAuth2FeignRequestInterceptor • OAuth2LoadBalancerClientAutoConfiguration • AccessTokenContextRelay <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency>
Spring Cloud Security • Propriedades customizadas para integração com serviço de recursos OAuth2 # SECURITY OAUTH2 RESOURCES (ResourceServerProperties) security.oauth2.resource.filter-order= # The order of the filter chain used to authenticate tokens. security.oauth2.resource.id= # Identifier of the resource. security.oauth2.resource.jwt.key-uri= # The URI of the JWT token. Can be set if the value is not available and the key is public. security.oauth2.resource.jwt.key-value= # The verification key of the JWT token. Can either be a symmetric secret or PEM-encoded RSA public key. security.oauth2.resource.prefer-token-info=true # Use the token info, can be set to false to use the user info. security.oauth2.resource.service-id=resource # security.oauth2.resource.token-info-uri= # URI of the token decoding endpoint. security.oauth2.resource.token-type= # The token type to send when using the userInfoUri. security.oauth2.resource.user-info-uri= # URI of the user endpoint.
Spring Cloud Security • Propriedades customizadas para um cliente OAuth2 • PPro • Propriedades customizadas para trabalhar com SSO # SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) security.oauth2.client.client-id= # OAuth2 client id. security.oauth2.client.client-secret= # OAuth2 client secret. A random secret is generated by default # SECURITY OAUTH2 SSO (OAuth2SsoProperties) security.oauth2.sso.filter-order= # Filter order to apply if not providing an explicit WebSecurityConfigurerAdapter security.oauth2.sso.login-path=/login # Path to the login page, i.e. the one that triggers the redirect to the OAuth2 Authorization Server
Spring Cloud Security • Exemplo de proteção de um serviço com OAuth2 • Utilizando o servidor de autorização para validar os tokens @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { //... } security: sessions: stateless basic: enabled: false user: password: none oauth2: resource: preferTokenInfo: false userInfoUri: http://localhost:9999/users/current
Spring Cloud Security • Validando o token diretamente no cliente security: sessions: stateless basic: enabled: false user: password: none oauth2: resource: jwt: keyValue: | -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo1jWPfjvJxaXCHzvClU7 uJg+6AlZ8ht1Rbr+7Wo5o+YBWgCc6lZmSv/mwxvfL/wqagQ/W756a8vUJ7qFz/k9 eBSJQSRuzJ6pT4OMMR9gbmYroh3RM/Xd5RelJgT3+OrvjAZr1pFYdAwp0q1T9XPa 6PnCXq8KhIqNPxMjcaBrOycWEgWE4g4VnnrKDLtMmEZZIc0EMv8j7womsyNkbTyl nPsbFttNwtFoTVJeqvD01Fd6ISaoOVQAUfAcxvp77B/A1g0No3GHBupEtW3Hgp2/ 80Zl0+Gwjl6Wag5Mu9H7MIUPo+4xFGAJ0uwseHiErZqdWlHIo179IacB87+9Vt0g pwIDAQAB -----END PUBLIC KEY-----
• Suporte à definição de regras de segurança via anotações • Habilita o suporte as anotações • @PreAuthorize, @PostAuthorize, @Secured • Suportando as expressões de segurança do Spring Security • E também adicionando suporte as expressões OAuth2 Spring Cloud Security @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration { @Override protected MethodSecurityExpressionHandler createExpressionHandler() { return new OAuth2MethodSecurityExpressionHandler(); } }
• OAuth2SecurityExpressionMethods • Expressões para restrição de segurança via OAuth2 • #oauth2.clientHasAnyRole('ADMIN', 'MANAGER') • #oauth2.clientHasRole('MANAGER') • #oauth2.denyOAuthClient() • #oauth2.hasAnyScope('read', 'write') • #oauth2.hasAnyScopeMatching('^abc .*', '[^a-z]{3}') • #oauth2.hasScope('read') • #oauth2.hasScopeMatching('^abc .*') • #oauth2.isClient() • #oauth2.isOAuth() • #oauth2.isUser() Spring Cloud Security
• Integração com Feign via OAuth2FeignRequestInterceptor Spring Cloud Security @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Bean public OAuth2FeignRequestInterceptor feignRequestInterceptor( OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource) { return new OAuth2FeignRequestInterceptor( oAuth2ClientContext, resource); } }
Laboratório 11 (cloud-lab11) • Protegendo os microservices com Spring Cloud Security
Spring Cloud Security • É necessário proteger os demais serviços da aplicação
Spring Cloud Security • Para proteger o Config Server • É necessário habilitar restrição de acesso no Config Server • Informar login e senha para conexão pelos clientes security: user: name: configUser password: configPassword role: SYSTEM spring: cloud: config: uri: http://localhost:8888 username: configUser password: configPassword application.yml bootstrap.yml
Spring Cloud Security • Para proteger o Eureka Server • É necessário habilitar segurança global no serviço Eureka @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("eurekaUser").password("eurekaPassword"); } @Override public void configure(HttpSecurity http) throws Exception { http.httpBasic().and().csrf().disable() .authorizeRequests().anyRequest().authenticated(); } } eureka: client: serviceUrl: defaultZone: http://eurekaUser:eurekaPassword@localhost:8761/eureka application.yml
Spring Cloud Security • Para proteger o Hystrix Dashboard • Necessário habilitar restrição de acesso nas propriedades • Informar login e senha para acesso ao Hystrix Dashboard • http://hystrixUser:hystrixPassword@localhost:7979/hystrix • http://hystrixUser:hystrixPassword@localhost:7979/turbine.stream security: basic: enabled: true user: name: hystrixUser password: hystrixPassword role: SYSTEM application.yml
Laboratório 12 (cloud-lab12) • Aplicando segurança nos serviços da plataforma Spring Cloud
Roteamento
Roteamento
API Gateway • Design pattern aplicado à microservices • Requisições podem ser apenas repassadas, ou modificadas “Single entry point for the service clients”
Netflix Zuul “Roteamento centralizado para microservices" • Fornece único ponto de entrada para os serviços • Roteamento e balanceamento na JVM • Cria uma rota para cada serviço no Eureka • Define filtros para pontos de entrada • Similar outros roteamentos • httpd, nginx, CF go router
Netflix Zuul
Netflix Zuul
Netflix Zuul • Basta adicionar a dependência Maven • Utilizar a anotação @EnableZuulProxy <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> @EnableZuulProxy @SpringBootApplication public class ZuulServer { public static void main(String[] args) { SpringApplication.run(ZuulServer.class, args); } }
Netflix Zuul • @EnableZuulServer vs @EnableZuulProxy • @EnableZuulServer • Simples definição de um roteamento Zuul • Deve ser utilizado para customização de código de roteamento sem comportamento de proxy • “Blank” Zuul server • @EnableZuulProxy • Modelo de uso mais comum • Extensão do @EnableZuulServer • Incorpora o suporte a proxy suportando a definição de routes na configuração • Também suporta customização de código de roteamento por meio de filtros
Netflix Zuul • Exemplo de configuração de rotas via URL zuul: routes: first: path: /first/** url: http://first.example.com second: path: /second/** url: forward:/second third: path: /third/** url: forward:/3rd legacy: path: /** url: http://legacy.example.com
Netflix Zuul • Integração do Zuul com Eureka e Ribbon
Netflix Zuul • Exemplo de utilização Zuul com Ribbon (serviceId) zuul: routes: aluno-service: path: /aluno/** serviceId: aluno-service disciplina-service: path: /disciplina/** serviceId: disciplina-service ribbon: eureka: enabled: false aluno-service: ribbon: listOfServers: localhost:8080,localhost:18080 disciplina-service: ribbon: listOfServers: localhost:8081,localhost:18081
Netflix Zuul • Exemplo de utilização Zuul com Eureka (serviceId) zuul: routes: aluno-service: path: /aluno/** serviceId: aluno-service disciplina-service: path: /disciplina/** serviceId: disciplina-service eureka: client: serviceUrl: defaultZone: http://eurekaUser:eurekaPassword@localhost:8761/eureka instance: preferIpAddress: true ribbon: eureka: enabled: true
Netflix Zuul • Por padrão Zuul ignora alguns HTTP headers • Pode-se customizar os sensitiveHeaders para definir quais headers devem ser ignorados por rota definida • Adicionalmente pode ser configurado • zuul.ignoreHeaders • Para ignorar headers globais (todos as rotas) • zuul.ignoreSecurityHeaders • True/false para ignorar os headers de segurança • https://docs.spring.io/spring-security/site/docs/current/reference/html/ headers.html#default-security-headers sensitiveHeaders: Cookie,Set-Cookie,Authorization zuul: routes: users: path: /myusers/** sensitiveHeaders: IgnoredHeader1, X-Auth-Token url: https://downstream
Netflix Zuul • Demais configurações suportadas • zuul.max.host.connections • zuul.max.host.maxTotalConnections • zuul.max.host.maxPerRouteConnections • zuul.ribbonIsolationStrategy • zuul.prefix • zuul.stripPrefix • zuul.retryable • zuul.addProxyHeaders • zuul.addHostHeader • zuul.ignoredPatterns • zuul.ignoredServices • zuul.forceOriginalQueryStringEncoding
Laboratório 13 (cloud-lab13) • Roteando os serviços com Netflix Zuul
Zuul Filter • Lifecycle
Zuul Filter • Basta implementar a interface IZuulFilter ou extender a classe ZuulFilter • Tipos de filtros • PRE • Executado antes de rotear à origem • ROUTING • Manipula a logica de roteamento do request à origem • POST • Executado após o request ter sido roteado à origem • ERROR • Executado quando algum erro acontece durante o roteamento
Zuul Filter public class SimpleFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { return null; } }
Zuul Fallback
Zuul Fallback class MyFallbackProvider implements ZuulFallbackProvider { @Override public String getRoute() { return "customers"; // use "*" to all routes } @Override public ClientHttpResponse fallbackResponse() { //... } } • Basta implementar um ZuulFallbackProvider • getRoute() define em qual rota será aplicado
Zuul CORS • CORS Overview
Zuul CORS @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:8080"); config.addAllowedOrigin("http://www.example.com"); config.addAllowedHeader("*"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } • Pode ser ativado definindo um CorsFilter
Laboratório 14 (cloud-lab14) • Implementando recursos avançados no Netflix Zuul
Conclusões • Microservices são sistemas distribuídos • Sistemas distribuídos são essencialmente complexos • Netflix OSS define ótimas ferramentas para implementação de uma arquitetura de microservices • Spring Cloud • Ótima abstração para Netflix OSS • Fácil utilização por meio de anotações • Integrado com ecossistema Spring Boot • Enjoy it :)
Revisão Nessa unidade você teve a oportunidade de compreender como: • Compreender as funcionalidades das plataformas Spring Cloud e Netflix OSS • Implementar um serviço de configuração centralizada utilizando Spring Cloud Config • Realizar o registro e descoberta dos serviços utilizando Netflix Eureka • Suportar tolerância à falhas e balanceamento de carga na chamada entre serviços com Netflix Ribbon • Tornar os serviços mais resilientes com a implementação de circuit breakers com Netflix Hystrix • Orquestrar a implementação de segurança entre serviços com Spring Cloud Security • Implementar um serviço de proxy e/ou roteamento utilizando Netflix Zuul
Referências • http://projects.spring.io/spring-cloud/ • https://netflix.github.io/ • http://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.1.RELEASE/ • http://cloud.spring.io/spring-cloud-static/spring-cloud-config/1.3.1.RELEASE/ • https://github.com/Netflix/ribbon • https://github.com/Netflix/eureka • https://github.com/Netflix/Hystrix • https://ahus1.github.io/hystrix-examples/manual.html • http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html • http://www.baeldung.com/spring-security-oauth-jwt • http://www.baeldung.com/sso-spring-security-oauth2 • http://blog.monkey.codes/how-to-use-jwt-and-oauth-with-spring-boot/ • http://stytex.de/blog/2016/02/01/spring-cloud-security-with-oauth2/ • https://jmnarloch.wordpress.com/2015/10/14/spring-cloud-feign-oauth2-authentication/ • http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html • http://www.baeldung.com/spring-cloud-securing-services • https://github.com/Netflix/zuul • https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee • http://callistaenterprise.se/blogg/teknik/2015/05/20/blog-series-building-microservices/

Workshop Microservices - Microservices com Spring Cloud e Netflix OSS

  • 1.
    Workshop Microservices Microservices comSpring Cloud e Netflix OSS
  • 2.
    Objetivos • Ao finaldesta unidade você compreenderá como: • Compreender as funcionalidades das plataformas Spring Cloud e Netflix OSS • Implementar um serviço de configuração centralizada utilizando Spring Cloud Config • Realizar o registro e descoberta dos serviços utilizando Netflix Eureka • Suportar tolerância à falhas e balanceamento de carga na chamada entre serviços com Netflix Ribbon • Tornar os serviços mais resilientes com a implementação de circuit breakers com Netflix Hystrix • Orquestrar a implementação de segurança entre serviços com Spring Cloud Security • Implementar um serviço de proxy e/ou roteamento utilizando Netflix Zuul
  • 3.
    Agenda • Spring Cloude Netflix OSS • Spring Cloud Config • Netflix Eureka • Netflix Ribbon e Feign • Netflix Hystrix • Spring Cloud Security • Netflix Zuul
  • 4.
  • 5.
    Microservices • Quais osprincipais desafios? • Gerenciamento de configuração • Registro e descoberta dos serviços • Roteamento • Balanceamento de carga • Tolerância à falhas
  • 9.
    • Eureka • Hystrix •Ribbon • Zuul • + muitos outros… • API • Routing / Health check • Microservices • Logging • Data Management
  • 10.
    Spring Cloud • Conjuntode bibliotecas / componentes • Não é apenas uma ferramenta • Integrado ao Spring Boot • Suporta diferentes arquiteturas e tecnologias em Cloud • AWS, Netflix, Heroku, Cloud Foundry, etc • Facilita a implementação de padrões necessários aos sistemas distribuídos “Toolset designed for building distributed systems”
  • 11.
  • 12.
  • 13.
    Spring Cloud Component Camden.SR7Dalston.RELEASE spring-cloud-aws 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-bus 1.2.2.RELEASE 1.3.0.RELEASE spring-cloud-cli 1.2.4.RELEASE 1.3.1.RELEASE spring-cloud-commons 1.1.9.RELEASE 1.3.0.RELEASE spring-cloud-contract 1.0.5.RELEASE 1.1.0.RELEASE spring-cloud-config 1.2.3.RELEASE 1.3.0.RELEASE spring-cloud-netflix 1.2.7.RELEASE 1.3.0.RELEASE spring-cloud-security 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-cloudfoundry 1.0.1.RELEASE 1.1.0.RELEASE spring-cloud-consul 1.1.4.RELEASE 1.2.0.RELEASE spring-cloud-sleuth 1.1.3.RELEASE 1.2.0.RELEASE spring-cloud-stream Brooklyn.SR3 Chelsea.SR1 spring-cloud-zookeeper 1.0.4.RELEASE 1.1.0.RELEASE spring-boot 1.4.5.RELEASE 1.5.2.RELEASE spring-cloud-task 1.0.3.RELEASE 1.1.3.RELEASE
  • 14.
    Spring Cloud • Paraadicionar no projeto basta incluir parent POM <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
  • 15.
    Spring Cloud +Netflix OSS "Casamento perfeito para criação de microservices auto-curáveis" Gerenciamento de configuração Spring Cloud Config + Bus Descoberta de serviços Netflix Eureka Balanceamento de carga Netflix Ribbon Tolerância à falhas Netflix Hystrix + Turbine Roteamento Netflix Zuul Segurança Spring Cloud Security
  • 16.
    Spring Cloud +Netflix OSS
  • 17.
  • 18.
    Spring Cloud Config “Gerenciamentode configuração para micro-serviços“ • Centraliza a configuração da aplicação • Permite atualizações dinâmicas • Suporta versionamento • Suporte à rollback • Suporta configuração via repositórios • Git, SVN, filesystem • Permite atualização via barramento • Spring Cloud Bus
  • 19.
    Spring Cloud Config •Serviço de configuração centralizado
  • 20.
    Spring Cloud Config(server) • Basta adicionar a dependência Maven • Utilizar a anotação @EnableConfigServer <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> @EnableConfigServer @SpringBootApplication public class ConfigServer { public static void main(String[] args) { SpringApplication.run(ConfigServer.class, args); } }
  • 21.
    Spring Cloud Config(server) • É necessário também configurar o repositório com as configurações externas server: port: 8888 spring: cloud: config: server: git: uri: file://config-repo $ cd $HOME $ mkdir config-repo $ cd config-repo $ git init . $ echo foo > application.properties $ git add -A . $ git commit -m “Initial commit"
  • 22.
    Spring Cloud Config(server) @SpringBootApplication @EnableConfigServer public class ConfigServer {...} spring.cloud.config.git.uri: https://github.com/... ConfigServer.java application.yml
  • 23.
    Spring Cloud Config(server) • É possível customizar configurações para utilização do repositório Git spring: cloud: config: server: git: uri: https://github.com/spring-cloud-samples/config-repo username: trolley password: strongpassword default-label: master force-pull: true basedir: file://server/local/path timeout: 60 clone-on-start: true search-paths: foo,bar*
  • 24.
    Spring Cloud Config(server) • Suporta também utilização de diferentes repositórios Git de acordo com um padrão / perfil definido (12-factor) spring: cloud: config: server: git: uri: https://github.com/spring-cloud-samples/config-repo repos: development: pattern: - */development - */staging uri: https://github.com/development/config-repo staging: pattern: - */qa - */production uri: https://github.com/staging/config-repo
  • 25.
    Spring Cloud Config(server) • Exemplo com configuração para SVN repo • Exemplo com configuração para Filesystem spring: profiles: active: subversion cloud: config: server: svn: uri: https://svn/config-repo default-label: trunk spring: profiles: active: native cloud: config: server: native: searchLocations: file://local/config-repo
  • 26.
    Spring Cloud Config(server) • Suporta a manipulação de diferentes Spring Profiles • Basta acessar as configurações via HTTP REST no seguinte formato • /{application}/{profile}[/{label}] • /{application}-{profile}.yml • /{label}/{application}-{profile}.yml • /{application}-{profile}.properties • /{label}/{application}-{profile}.properties • YML • Você configura dentro do próprio arquivo • Separando por --- • Properties • application.properties • application-dev.properties • application-prod.properties logging: level: debug --- spring: profiles: dev, prod logging: level: info application.yml
  • 27.
  • 28.
    Spring Cloud Config(client) • Basta adicionar a dependência Maven • Configurar o arquivo bootstrap.yml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> spring: application: name: microservice1 cloud: config: uri: http://localhost:8888
  • 29.
    Spring Cloud Config(client) @RefreshScope @Component public class AppComponent { @Value("${thread-pool}") private int threadPool; @Value("${email}") private String email; @Autowired Environment env } • É possível buscar as propriedades definidas pelo Config Server utilizando @Value e Spring Environment • Existe a possibilidade de atualizar as propriedades sem derrubar a aplicação, utilizando a anotação @RefreshScope • POST http://localhost:8080/refresh
  • 30.
    Laboratório 1 (cloud-lab01) •Centralizando a configuração com Spring Cloud Config
  • 31.
  • 32.
    • Exemplo daarquitetura de replicação de configuração utilizada Spring Cloud Config + Bus
  • 33.
    • Lightweight AMQPMessaging Broker • Arquitetura flexível e fornece extensões para outros protocolos • HTTP, STOMP, MQTT • Ótima integração com Spring • Spring Boot, Cloud Bus, Cloud Stream, Messaging • Instalação • Windows • https://www.rabbitmq.com/install-windows.html • Mac OS X • brew install rabbitmq • Linux • apt-get install rabbitmq-server • yum install rabbitmq-server • Web Console • http://localhost:15672 • user: guest / password: guest RabbitMQ
  • 34.
    Spring Cloud Config+ Bus (server) • É necessário adicionar as seguintes dependências • É suportado também a utilização de Kafka ou Redis como implementação do barramento <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-monitor</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency> spring: cloud: bus: enabled: true rabbitmq: host: localhost port: 5672 • Deve ser ativado o suporte ao barramento via properties
  • 35.
    Spring Cloud Config+ Bus (client) • É necessário adicionar as seguintes dependências • Incorporar a seguinte configuração no bootstrap.yml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> spring: application: name: microservice1 cloud: config: uri: http://localhost:8888 rabbitmq: host: localhost port: 5672
  • 36.
    Spring Cloud Config+ Bus • Configuração do Webhook no repositório Git
  • 37.
    Laboratório 2 (cloud-lab02) •Replicando a configuração centralizada com Spring Cloud Config Bus
  • 38.
  • 39.
  • 40.
  • 41.
    Registro e Descobertade Serviços Service Register Health Check
  • 42.
    Netflix Eureka "Transparência delocalização aos micro-serviços“ • Registro de serviços REST based • Suporte à replicação • Cache aplicado no stub cliente • Resiliente • Rápido… mas não consistente • Fornece o alicerce para outros serviços • Mantém registro de clientes com metadados
  • 43.
    Netflix Eureka (server) •Basta adicionar a dependência Maven • Utilizar a anotação @EnableEurekaServer <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> @SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }
  • 44.
    Netflix Eureka (server) •Exemplo de configuração básica application.yml • Para acessar o Eureka Dashboard Web • http://localhost:8761 server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  • 45.
  • 46.
  • 47.
    Netflix Eureka (client) •Basta adicionar a dependência Maven • Utilizar a anotação @EnableDiscoveryClient <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> @EnableDiscoveryClient @SpringBootApplication public class EurekaClient { public static void main(String[] args) { SpringApplication.run(EurekaClient.class, args); } }
  • 48.
    Netflix Eureka (client) •Exemplo de configuração básica application.yml • Cliente será registrado no Eureka Server spring: application: name: spring-cloud-eureka-client eureka: client: serviceUrl: defaultZone: ${EUREKA_URI:http://localhost:8761/eureka} instance: preferIpAddress: true
  • 49.
    Netflix Eureka (client) •Exemplo utilizando DiscoveryClient @RestController public class ProductController { @Autowired DiscoveryClient discoveryClient; @GetMapping("/get/customers") public void getCustomers() throws Exception { List<ServiceInstance> instances = discoveryClient.getInstances("customer-service"); ServiceInstance firstOne = instances.get(0); String uri = "http://" + firstOne.getHost() + ":" + firstOne.getPort(); HttpGet getRequest = new HttpGet(uri + "/customers"); DefaultHttpClient httpClient = new DefaultHttpClient(); HttpResponse response = httpClient.execute(getRequest); // ... } }
  • 50.
    Netflix Eureka (client) •Exemplo utilizando RestTemplate @RestController public class ProductController { @Autowired RestTemplate restTemplate; @GetMapping("/get/customers") public void getCustomers() throws Exception { // use the "smart" Eureka-aware RestTemplate ResponseEntity<List<CustomerDTO>> exchange = this.restTemplate.exchange( "http://customer-service/customers", HttpMethod.GET, null, new ParameterizedTypeReference<List<CustomerDTO>>() {}, (Object) null); // ... } }
  • 51.
    Laboratório 3 (cloud-lab03) •Registrando e descobrindo serviços com Netflix Eureka
  • 52.
  • 53.
  • 54.
    Netflix Eureka • Paraconfigurar o mecanismo de suporte à replicação --- spring: profiles: peer1 eureka: instance: hostname: peer1 client: serviceUrl: defaultZone: http://peer2:[port]/eureka/ --- spring: profiles: peer2 eureka: instance: hostname: peer2 client: serviceUrl: defaultZone: http://peer1:[port]/eureka/ ## Hosts / IPs peer1 127.0.0.1 peer2 127.0.0.1 /etc/hosts application.yml
  • 55.
  • 56.
    Laboratório 4 (cloud-lab04) •Ativando o suporte à replicação com Netflix Eureka
  • 57.
  • 58.
  • 59.
    Netflix Ribbon "Balanceamento decarga para microservices" • Balanceamento decentralizado no cliente • Resiliente • Suporte à tolerância a falhas • Trabalha com múltiplos protocolos • HTTP, TCP, UDP • Modelo assíncrono e reativo • Suporte à caching e batching • Múltiplos algoritmos de balanceamento
  • 60.
  • 61.
    Netflix Ribbon • Bastaadicionar a dependência Maven • Pode ser utilizado de duas maneiras • Diretamente (sem Eureka) • Por meio do objeto LoadBalancerClient • Utilizando configurações na aplicação • Properties, Ribbon Client Configuration • Por meio de anotações • @RibbonClient, @LoadBalanced • Integrado (com Eureka) • Pode ser customizado via propriedades <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
  • 62.
    Netflix Ribbon • Exemplode configuração do Ribbon client public class GroupRibbonConfiguration { @Autowired IClientConfig ribbonClientConfig; @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } @Bean public IRule ribbonRule(IClientConfig config) { return new AvailabilityFilteringRule(); } } group-service: ribbon: eureka: enabled: false listOfServers: localhost:9092,localhost:9999 ServerListRefreshInterval: 15000
  • 63.
    Netflix Ribbon • Configuraçõespossíveis para Ribbon Configuration • IClientConfig • Define a configuração para o cliente do load balancer • ServerList<Server> • Define como recuperar a lista de servidores para escolha • ServerListFilter<Server> • Define uma lista de filtro para a lista de servidores para escolha • ILoanBalancer • Representa o software de load balancer • IRule • Descreve a estratégia de load balancing • IPing • Define qual a periodicidade dos pings realizados
  • 64.
    Netflix Ribbon • Configuraçõespossíveis para IRule • AvailabilityFilteringRule • ClientConfigEnabledRoundRobinRule • RandomRule • ResponseTimeWeightedRule • RetryRule • RoundRobinRule • WeightedResponseTimeRule • ZoneAvoidanceRule
  • 65.
    Netflix Ribbon • Configuraçõespossíveis para ILoadBalancer • BaseLoadBalancer • DynamicServerListLoadBalancer • NoOpLoadBalancer • ZoneAwareLoadBalancer • Configurações possíveis para IPing • DummyPing • NoOpPing • PingConstant
  • 66.
    Netflix Ribbon • Usodireto via LoadBalancerClient @RestController @RibbonClient(name = "group-service", configuration = GroupRibbonConfiguration.class) public class UserController { @Autowired LoadBalancerClient loadBalancer; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { ServiceInstance instance = loadBalancer.choose("group-service"); URI storesUri = URI.create(String.format(“http://%s:%s", instance.getHost(), instance.getPort())); // ... do something with the URI } }
  • 67.
    Netflix Ribbon • Usodireto via @LoadBalanced @RestController @RibbonClient(name = "group-service", configuration = GroupRibbonConfiguration.class) public class UserController { @LoadBalanced @Bean RestTemplate restTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { return this.restTemplate.getForObject( "http://group-service/user/" + id, Group.class); } }
  • 68.
    Netflix Ribbon @EnableDiscoveryClient @SpringBootApplication public classRibbonEurekaClient { public static void main(String[] args) { SpringApplication.run(RibbonEurekaClient.class, args); } } spring: application: name: ribbon-client eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka instance: preferIpAddress: true • Exemplo de uso com Eureka
  • 69.
    Netflix Ribbon • Exemplode uso com Eureka • group-service é um serviço registrado no Eureka @RestController public class UserController { @LoadBalanced @Bean RestTemplate restTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/users/{id}/group") public Group userGroup(@PathVariable Long id) { return this.restTemplate.getForObject( "http://group-service/user/" + id, Group.class); } }
  • 70.
    Laboratório 5 (cloud-lab05) •Implementando balanceamento de carga e tolerância à falhas com Netflix Ribbon
  • 71.
    Netflix Feign • Facilitacriação de clientes REST • Ótima integração com Spring Cloud • Suporta implementação de circuit breakers • Simples, produtivo e customizável • Pode ser utilizado em conjunto com • Ribbon - balanceamento de carga • Eureka - descoberta dos serviços “Declarative REST interfaces"
  • 72.
    Netflix Feign • Bastaadicionar a dependência Maven • Utilizar a anotação @EnableFeignClients <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> @EnableFeignClients @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
  • 73.
    Netflix Feign • Exemplode uso com Eureka (service-id) • Utilização com URL externas @FeignClient("stores-service") public interface StoreClient { @RequestMapping(method = RequestMethod.GET, value = "/stores") List<Store> getStores(); @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json") Store update(@PathVariable("storeId") Long storeId, Store store); } @FeignClient(name = "stores-service", url = "http://example.com") public interface StoreClient {}
  • 74.
    Netflix Feign • Exemplode customização de configurações @Configuration public class CustomFeignConfiguration { static final int FIVE_SECONDS = 5000; @Bean public Logger.Level feignLogger() { return Logger.Level.FULL; } @Bean public Request.Options options() { return new Request.Options(FIVE_SECONDS, FIVE_SECONDS); } } @FeignClient(value = "stores-service", configuration = CustomFeignConfiguration.class) public interface StoreClient {...}
  • 75.
    Netflix Feign • Configuraçõesopcionais • Decoder: decodificação do response payload • Encoder: codificação do request payload • Logger: definição da engine de logging • Contract: configuração para utilizando Spring Cloud Contract • Feign.Builder: customização do Builder Feign • Logger.Level: definição do nível de logging • Retryer: estratégia para implementação de retry • ErrorDecoder: decodificação para erros no response • Request.Options: opções para customização das requisições
  • 76.
    Netflix Feign • Oferecesuporte à compressão do request e response • Funcionamento similar as configurações fornecidas pelo Web server • Ótimo para melhoria de performance em requisições e respostas com muitos dados envolvidos feign.compression.request.enabled=true feign.compression.response.enabled=true feign.compression.request.mime-types=application/xml,application/json feign.compression.request.min-request-size=2048
  • 77.
    Netflix Feign • Oferececustomização para mecanismo logging • Pode ser definido logging por Feign client definido • Ou pode ser alterado o nível de log padrão Logger.Level • NONE: Nenhuma impressão de log • BASIC: Apenas dos métodos de request, URL, e status de respostas • HEADERS: Informação básica sobre headers do request / response • FULL: Headers, body, e metadados das requisições e respostas logging.level.project.user.UserClient: DEBUG @Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
  • 78.
    Netflix Feign • Oferecetambém uma Feign Client Builder API public interface BookClient { @RequestLine("GET /{isbn}") BookResource findByIsbn(@Param("isbn") String isbn); @RequestLine("GET") List<BookResource> findAll(); @RequestLine("POST") @Headers("Content-Type: application/json") void create(Book book); } BookClient bookClient = Feign.builder() .client(new OkHttpClient()) .encoder(new GsonEncoder()) .decoder(new GsonDecoder()) .logger(new Slf4jLogger(BookClient.class)) .logLevel(Logger.Level.FULL) .target(BookClient.class, "http://localhost:8081/api/books");
  • 79.
    Netflix Feign • Épossível customizar diferentes Enconder e Decoder • GSON • Jackson • Sax • JAXB Feign.builder() .encoder(new GsonEncoder()) .decoder(new GsonDecoder()); Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()); Feign.builder() .decoder(SAXDecoder.builder() .registerContentHandler(UserIdHandler.class) .build()); Feign.builder() .encoder(new JAXBEncoder()) .decoder(new JAXBDecoder());
  • 80.
    Netflix Feign • Outrasconfigurações também são suportadas • JAX-RS • OkHttp • SLF4J Feign.builder().contract(new JAXRSContract()); Feign.builder().client(new OkHttpClient()); Feign.builder().logger(new Slf4jLogger()); interface GitHub { @GET @Path("/repos/{owner}/{repo}/contributors") List<Contributor> contributors( @PathParam("owner") String owner, @PathParam(“repo") String repo); }
  • 81.
    Netflix Feign • Paratrabalhar com Spring MultipartFile <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>io.github.openfeign.form</groupId> <artifactId>feign-form-spring</artifactId> <version>2.1.0</version> </dependency> @Configuration class MultipartSupportConfig { @Bean @Primary @Scope("prototype") Encoder feignFormEncoder() { return new SpringFormEncoder(); } } @FeignClient(name = "file-upload-service", configuration = MultipartSupportConfig.class) interface ServiceClient { @RequestMapping(method = RequestMethod.POST, value = "/upload") ResponseEntity upload(@RequestPart(value="content") MultipartFile file) }
  • 82.
    Netflix Feign • Sugestãode design para implementação nas aplicações public interface UserService { @RequestMapping(method = RequestMethod.GET, value ="/users/{id}") User getUser(@PathVariable("id") long id); } @RestController public class UserRestController implements UserService { User getUser(@PathVariable("id") long id) { // Implement the REST endpoint } } @FeignClient("users") public interface UserClient extends UserService { // Empty }
  • 83.
    Laboratório 6 (cloud-lab06) •Implementando clientes REST com Netflix Feign
  • 84.
  • 85.
  • 86.
  • 87.
    Netflix Hystrix “Tolerância àfalhas para micro-serviços“ • Implementa padrão circuit breakers • Fornece monitoramento aos serviços • Hystrix dashboard • Suporta comandos assíncronos • Utiliza diferentes thread pools • Pode implementar timeouts
  • 88.
    Netflix Hystrix • CircuitBreaker Pattern • Máquina de estados • Closed, Open, Half-Open • Falha não é propagada para chamada do cliente
  • 89.
    Netflix Hystrix • Bastaadicionar a dependência Maven • Utilizar a anotação @EnableCircuitBreaker <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> @EnableCircuitBreaker @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
  • 90.
    • Exemplo deimplementação @HystrixCommand Netflix Hystrix public class StoreIntegration { @HystrixCommand(fallbackMethod = "defaultStores") public Object getStores(Map<String, Object> parameters) { //do stuff that might fail } public Object defaultStores(Map<String, Object> parameters) { return /* something useful */; } }
  • 91.
  • 92.
    Netflix Hystrix • Suporteintegrado ao Feign via Hystrix Fallback @FeignClient(name = "service-to-call", fallback = FeignClientFallback.class) public interface FeignClient { @RequestMapping(value = "/rest/do", method = RequestMethod.GET) ResponseEntity<String> doSomething(); } @Component public class FeignClientFallback implements FeignClient { @Override public ResponseEntity<String> doSomething() { return ResponseEntity.ok("fallback"); } }
  • 93.
    Netflix Hystrix • Configuraçõespossíveis para Hystrix Command • Execution • execution.isolation.strategy • execution.isolation.thread.timeoutInMilliseconds • execution.timeout.enabled • execution.isolation.thread.interruptOnTimeout • execution.isolation.thread.interruptOnCancel • execution.isolation.semaphore.maxConcurrentRequests • Fallback • fallback.isolation.semaphore.maxConcurrentRequests • fallback.enabled https://github.com/Netflix/Hystrix/wiki/Configuration
  • 94.
    Netflix Hystrix • Configuraçõespossíveis para Hystrix Command • Circuit Breaker • circuitBreaker.enabled • circuitBreaker.requestVolumeThreshold • circuitBreaker.sleepWindowInMilliseconds • circuitBreaker.errorThresholdPercentage • circuitBreaker.forceOpen • circuitBreaker.forceClosed • Request Context • requestCache.enabled • requestLog.enabled https://github.com/Netflix/Hystrix/wiki/Configuration
  • 95.
    Netflix Hystrix • Configuraçõespossíveis para Hystrix Command • Metrics • metrics.rollingStats.timeInMilliseconds • metrics.rollingStats.numBuckets • metrics.rollingPercentile.enabled • metrics.rollingPercentile.timeInMilliseconds • metrics.rollingPercentile.numBuckets • metrics.rollingPercentile.bucketSize • metrics.healthSnapshot.intervalInMilliseconds https://github.com/Netflix/Hystrix/wiki/Configuration
  • 96.
    Netflix Hystrix • Outraspossíveis configurações • Collapser Properties • maxRequestsInBatch • timerDelayInMilliseconds • requestCache.enabled • Thread Pool • coreSize • maximumSize • maxQueueSize • queueSizeRejectionThreshold • keepAliveTimeMinutes • allowMaximumSizeToDivergeFromCoreSize https://github.com/Netflix/Hystrix/wiki/Configuration
  • 97.
    Netflix Hystrix • Propriedadespodem ser configuradas via anotação • @HystrixCommand e @HystrixProperty @HystrixCommand(fallbackMethod = "defaultStores", commandProperties = { @HystrixProperty(name="execution.isolation.strategy", value="THREAD"), @HystrixProperty(name="requestCache.enabled", value="false") },threadPoolProperties = { @HystrixProperty(name="coreSize", value="5"), @HystrixProperty(name="maximumSize", value="5") }) public Object getStores(Map<String, Object> parameters) { //do stuff that might fail }
  • 98.
    Netflix Hystrix • Propriedadespodem ser configuradas via YML hystrix: command: FeignClient#doSomething(): execution: isolation: strategy: SEMAPHORE semaphore: maxConcurrentRequests: 5 fallback: isolation: semaphore: maxConcurrentRequests: 5 circuitBreaker: requestVolumeThreshold: 5 application.yml
  • 99.
    Netflix Hystrix • Estratégiade execução THREAD vs. SEMAPHORE
  • 100.
    Laboratório 7 (cloud-lab07) •Implementando circuit breakers com Netflix Hystrix
  • 101.
  • 102.
    Hystrix Dashboard • Bastaadicionar a dependência Maven • Utilizar a anotação @EnableHystrixDashboard <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency> @EnableHystrixDashboard @SpringBootApplication public class HytrixDashboard { public static void main(String[] args) { SpringApplication.run(HytrixDashboard.class, args); } }
  • 103.
    Hystrix Dashboard • Paravisualizar o dashboard basta acessar o endereço • http://localhost:[port]/hystrix
  • 104.
    Hystrix Dashboard • Visualizaçãodo painel de circuitos para um serviço
  • 105.
  • 106.
    Netflix Turbine • Agregadordos eventos Hystrix
  • 107.
    Netflix Turbine • Bastaadicionar a dependência Maven • Utilizar a anotação @EnableTurbine • Pode ser utilizando em conjunto Hystrix Dashboard <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId> </dependency> @EnableTurbine @SpringBootApplication public class TurbineApplication { public static void main(String[] args) { SpringApplication.run(TurbineApplication.class, args); } }
  • 108.
    Netflix Turbine • Énecessário configurar um cluster para visualização dos eventos gerados pelos serviços • Utiliza o registro Eureka para localização dos serviços • Basta adicionar uma configuração nas propriedades • Pode ser definido diferentes configurações de clusters (views) • http://turbine.sever/turbine.stream?cluster=<CLUSTERNAME> turbine: appConfig: service-a, service-b clusterNameExpression: "'default'" turbine: aggregator: clusterConfig: STORE appConfig: customers,stores,ui,admin
  • 109.
    Netflix Turbine • Paraacessar o endereço do Turbine no Hystrix Dashboard • http://turbine.server:[port]/turbine.stream
  • 110.
    • Agregador doseventos Hystrix assíncrono Netflix Turbine Stream
  • 111.
    • Utiliza umsistema de mensagens assíncrono para publicar e processar os eventos Hystrix • Pode ser utilizado com diferentes middleware • RabbitMQ, ActiveMQ, Apache Kafta, etc • Cada serviço publica seus eventos na fila processada pelo Turbine Netflix Turbine Stream
  • 112.
    Netflix Turbine Stream(server) • Basta adicionar a dependência Maven • É necessário também adicionar a dependência de um Stream (Rabbit, Kafta, etc) • spring-cloud-starter-stream-rabbit • Utilizar a anotação @EnableTurbineStream <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine-stream</artifactId> </dependency> @EnableTurbineStream @SpringBootApplication public class TurbineStreamApplication {}
  • 113.
    Netflix Turbine Stream(client) • Necessário adicionar a dependência Hystrix stream • Também necessário adicionar a dependência de um Stream (Rabbit, Kafta, etc) • spring-cloud-starter-stream-rabbit • Caso necessário configurar as propriedades de configuração no Stream adicionado <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-hystrix-stream</artifactId> </dependency>
  • 114.
    Laboratório 8 (cloud-lab08) •Monitorando os circuitos com Hystrix Dashboard e Turbine
  • 115.
  • 116.
    Principais requisitos desegurança? • Como identificar as permissões que serão manipuladas? • Como a informação será codificada e decodificada? • Quais dados serão necessários para restrição de acesso? • Quem será responsável por armazenar e fornecer os dados de segurança? • Como identificar se a requisição não foi modificada? “Stop bad guys from accessing your resources"
  • 117.
    Segurança com REST •Algumas estratégias para proteger os serviços • Basic Auth (HTTP Basic) • Network Security • Certificate Based • Arquitetura RESTful não define procedimentos de segurança • HTTP methods: GET, POST, PUT, DELETE • API’s REST são tão vulneráveis quanto aplicações web tradicionais • SQL Injection, replay attacks, cross-site scripting, etc
  • 118.
    HTTP Basic Auth •Qual o problema com isto? • Nada, mas… • Em qual lugar você busca as credenciais? • Ok para sistemas onde todos os participantes podem compartilhar dados confidenciais de um modo seguro • Apenas suporta informações de "usuário / senha” • Apenas trabalha com autenticação • Sem distinção entre usuários e máquinas $ curl “https://$username:$password@myhost/resource"
  • 119.
    Network Security • Qualo problema com isto? • Nada, mas… • Chato para "debugar" e um pouco difícil de manter • Configuração fica fora do escopo de desenvolvedores • Não existe o conceito de identidade e autenticação "Security architecture based on top of web server"
  • 120.
    Certificate Based • Qualo problema com isto? • Nada, mas… • Não existe o conceito de identidade, apenas caso o browser tenha os certificados instalados • Obriga keystores e certificados nas aplicações e nos serviços • Não existe uma distinção muito clara quanto a usuários e máquinas $ curl -k -cert file.pem:password https://myhost:443/resource
  • 121.
    OAuth 2.0 • Protocolobaseado em uma especificação de padrão aberto definido pelo IETF • Habilita as aplicações acessarem e compartilharem serviços sem necessidade de compartilhar credenciais • Evita problemas com "passwords" • Essencial para mecanismo via delegação de acesso • Aplicações terceiras • Para serviços específicos • Por um tempo limitado • Pode trabalhar com revogação seletiva
  • 122.
  • 123.
    OAuth Timeline • OAuth1.0 • Especificação core publicada em dezembro/2007 • OAuth 1.0a • Especificação revisada publicada em junho/2009 • Relacionado a correções de vulnerabilidades de segurança • OAuth 2.0 • Especificação publicada em outubro/2012 • Ser mais seguro, simples e padronizado • RFCs adicionais ainda continuam sendo trabalhadas
  • 124.
    OAuth 2.0 Tokens •Tipos • Bearer • Large random token • Necessita de SSL para proteção em transito • Servidor necessita gerar e armazenar este hash • Mac • Utilizado para evitar repetição • Não requer a utilização de SSL • Apenas suportado no OAuth 1.0 • Access Token • Short-lived token • Refresh Token • Long-lived token { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":“bearer", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", }
  • 125.
  • 126.
  • 127.
    Papéis Envolvidos • ResourceServer • Proteção dos serviços • Authorization Server • Emissão de tokens de acesso para os clientes • Client Application • Solicita os serviços protegidos em nome do proprietário • Resource Owner • Concede o acesso a um serviço protegido
  • 128.
    OAuth 2.0 GrantTypes • Authorization Code (web apps) • Confidencialidade aos clientes • Utiliza um código de autorização emitido pelo servidor • Implicit (browser-based and mobile apps) • Script heavy web apps • Usuário final pode ver o access token gerado • Resource Owner Password Credentials (user / password) • Utilizado em casos aonde o usuário confia no cliente • Expõe as credenciais do usuário para o cliente • Client Credentials (application) • Clientes recebem um token (secret) para acesso • Ideal para acesso entre aplicações
  • 129.
    OAuth 2.0 GrantTypes • Authorization Code http://server/oauth/authorize?response_type=code&client_id=client &scope=read+write+trust &redirect_uri=http://localhost/app http://server/oauth/token?grant_type=authorization_code&code=SkiGJ8 &client_id=client &client_secret=secret &redirect_uri=http://localhost/app {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
  • 130.
    OAuth 2.0 GrantTypes • Implicit http://server/oauth/authorize?response_type=token&client_id=client &scope=read+write+trust &redirect_uri=http://localhost/app http://localhost/app/#?access_token=292e1ec1-fda9-4968- b1c3-7cc0dd99483f
  • 131.
    OAuth 2.0 GrantTypes • Resource Owner Password Credentials http://server/oauth/token?grant_type=password&client_id=client &client_secret=secret &username=admin &password=admin {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
  • 132.
    OAuth 2.0 GrantTypes • Client Credentials http://server/oauth/token?grant_type=client_credentials &client_id=client&client_secret=secret {"access_token":"292e1ec1-fda9-4968-b1c3-7cc0dd99483f", "token_type":"bearer", "expires_in":299997, "scope":"trust write read"}
  • 133.
    OAuth 2.0 Prós& Contras • Prós • Ótima integração para acesso de aplicações à serviços oferecidos por web sites • Acesso permitido para um escopo limitado ou por tempo (duração) • Sem necessidade de compartilhamento de passwords com aplicações terceiras • Contras • Implementação pode ser um pouco complexa • Problemas de interoperabilidade • Algumas más implementações podem expor falhas de segurança
  • 134.
    Spring Security OAuth •Oferece implementação para OAuth (1a) e OAuth2 • Implementa os 4 tipos de authorization grants • Suporta todos os requisitos definidos pelo OAuth2 • Authorization Server • Resources Server • Client • Ótima integração com Spring MVC e JAX-RS • Configuração utilizando anotações • Integração com todo o eco-sistema Spring
  • 135.
    Spring Authorization Server •@EnableAuthorizationServer • Anotação utilizada para configurar OAuth2 authorization server • Existe também disponível em XML <authorization-server/> • ClientDetailsServiceConfigurer • Define os detalhes do cliente do serviço • Implementação in-memory ou via JDBC • AuthorizationServerTokenServices • Operações para gerenciar OAuth2 tokens • Tokens in-memory, JDBC ou JSON Web Token (JWT) • AuthorizationServerEndpointConfigurer • Fornece os grant types suportado pelo servidor • Todos os grant types são suportados exceto via password
  • 136.
    Spring Resource Server •Pode ser a mesma instância do Authorization Server • Ou então instalado como uma aplicação separada • Fornece um filtro de autenticação para aplicações web • @EnableResourceServer • Anotação utilizada para configurar OAuth2 resource server • Existe também disponível em XML <resource-server/> • Suporta controle de acesso via expressions • #oauth2.hasScope • #oauth2.clientHasRole • #oauth2.clientHasAnyRole • #oauth2.denyClient
  • 137.
    Spring OAuth2 Client •Cria um filtro para armazenar o contexto do request • Gerencia o redirecionamento de/para o servidor de autenticação OAuth2 • @EnableOAuth2Client • Anotação utilizada para configurar o OAuth2 client • Existe também disponível em XML <client/> • OAuth2RestTemplate • Wrapper client object para acessar os serviços
  • 138.
    Authorization Server @Configuration @EnableAuthorizationServer public classAuthServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess(“permitAll()”) .checkTokenAccess("isAuthenticated()"); } @Override public void configure( ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("SampleClientId") .secret("secret") .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) ; } }
  • 139.
    Resource Server @Configuration @EnableResourceServer public classResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/users/ping").permitAll() .antMatchers("/users/current").authenticated() .anyRequest().authenticated(); } }
  • 140.
    Laboratório 9 (cloud-lab09) •Implementando e manipulando segurança com o protocolo OAuth2
  • 141.
    JSON Web Token “Padrãoaberto que define uma forma compacta e auto-contida para transmitir de forma segura, informações entre duas partes“
  • 142.
    JSON Web Token •Basta adicionar a dependência Maven • Definir um JwtTokenStore • Configurar um JwtAccessTokenConverter • Utilizando chaves simétricas, ou assimétricas • Configurar o modelo geração e validação de JWT tokens nos serviços de autorização e recursos OAuth2 <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency>
  • 143.
    JSON Web Token •Configuração utilizando modelo simétrico de chaves @Configuration public class JwtConfig { @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey("123"); return converter; } }
  • 144.
    JSON Web Token •Modelo assimétrico de chaves (chave privada) @Configuration public class JwtConfig { //... @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(“mykeys.jks"), "mypass".toCharArray()); converter.setKeyPair( keyStoreKeyFactory.getKeyPair("security-server")); return converter; } }
  • 145.
    JSON Web Token •Modelo assimétrico de chaves (chave pública) @Configuration public class JwtConfig { //... public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); Resource resource = new ClassPathResource("public.txt"); String publicKey = null; try { publicKey = IOUtils.toString(resource.getInputStream()); } catch (final IOException e) { throw new RuntimeException(e); } converter.setVerifierKey(publicKey); return converter; } }
  • 146.
    JSON Web Token •Para realizar a geração do par de chaves (privada e pública) pode ser utilizado keytool • Para exportar a chave pública, pode ser utilizado openssl keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore mytest.jks -storepass mypass keytool -list -rfc --keystore mytest.jks | openssl x509 -inform pem -pubkey -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgIK2Wt4x2EtDl41C7vfp OsMquZMyOyteO2RsVeMLF/hXIeYvicKr0SQzVkodHEBCMiGXQDz5prijTq3RHPy2 /5WJBCYq7yHgTLvspMy6sivXN7NdYE7I5pXo/KHk4nz+Fa6P3L8+L90E/3qwf6j3 DKWnAgJFRY8AbSYXt1d5ELiIG1/gEqzC0fZmNhhfrBtxwWXrlpUDT0Kfvf0QVmPR xxCLXT+tEe1seWGEqeOLL5vXRLqmzZcBe1RZ9kQQm43+a9Qn5icSRnDfTAesQ3Cr lAWJKl2kcWU1HwJqw+dZRSZ1X4kEXNMyzPdPBbGmU6MHdhpywI7SKZT7mX4BDnUK eQIDAQAB -----END PUBLIC KEY-----
  • 147.
    JWT Response • Exemplode resposta utilizando JWT { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTMyODMxNzksInVzZXJfbmFtZSI6 InVzZXIiLCJhdXRob3JpdGllcyI6WyJVU0VSIiwiTUFOQUdFUiJdLCJqdGkiOiJkMGY5OTY2OC01Nz dkLTRkZTEtODkwYi1hNDY1MTBkZjg2YjAiLCJjbGllbnRfaWQiOiJjbGllbnQiLCJzY29wZSI6WyJv cGVuaWQiXX0.iH1pnwJZPZi05hdpY9MDGIvtx34Dj8lxc5fdU5c5NCCtUblT_L9kdZO6NaOIIZffbG zSHoyVUEZkSwkGXm6lT1jRTcOHq2khAZlwmO3hN3c1xb8bumAgmpF8fJSIKTVIkFJpbVO4uDfHSSbB m6QsTbqHkNgNwWSWbNG1n6ZlsHCcZCh37cmgbh- B4tPD9QEfH3CSI6Z7AgUbS9UCIytjm02sgxgAr3liOcykRrdcOvxgIBx_yGDvornQ5JOBVdW-TS0- uJmHe6sHCFYeBNchJhRi7xqZCMYFD6IcP4dftPupzg3IMl5oWberxhZTCCLoi18JtQyZgIgqmSlOAI q8wg", "token_type": "bearer", "expires_in": 43199, "scope": "openid", "jti": "d0f99668-577d-4de1-890b-a46510df86b0" }
  • 148.
    JWT Response • Épossível informações extras no JWT gerado implementando customizações via TokenEnhancer public class CustomTokenEnhancer implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put("organization", authentication.getName() + randomAlphabetic(4)); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation( additionalInfo); return accessToken; } }
  • 149.
    JWT Response • Exemplode payload com informações extras adicionadas via TokenEnhancer { "user_name": "john", "scope": [ "foo", "read", "write" ], "organization": "johnIiCh", "exp": 1458126622, "authorities": [ "ROLE_USER" ], "jti": "e0ad1ef3-a8a5-4eef-998d-00b26bc2c53f", "client_id": "fooClientIdPassword" }
  • 150.
    Laboratório 10 (cloud-lab10) •Trabalhando com JSON Web Tokens
  • 151.
    Spring Cloud Security “Segurançaaplicada para microservices" • Integração com Spring Security + OAuth2 • Proteção dos serviços com tokens (JWT) • SSO com OAuth2 e OpenID Connect • Transmissão tokens entre SSO e apps • OAuth2 + JWT + SSO ;)
  • 152.
    Spring Cloud Security Discovery Client RelyingParty Resource Server Get an access token & an ID Token (JWT) Use an access token Authorization Server Iden.ty Provider or IDP or OpenID Provider or OP Authorization Endpoint Token Endpoint Important Stuff Userinfo Endpoint Registration Endpoint JWKS Endpoint JWKS Endpoint Validate (JWT) ID Token /.well-known /webfinger /openid-configura.on Check Session IFrame End Session Endpoint
  • 153.
    Spring Cloud Security •Basta adicionar a seguinte dependência Maven • Integração dos projetos Spring Security OAuth2 + JWT • spring-security-oauth2 e spring-security-jwt • Customizações de segurança as projetos Spring Cloud • OAuth2FeignRequestInterceptor • OAuth2LoadBalancerClientAutoConfiguration • AccessTokenContextRelay <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency>
  • 154.
    Spring Cloud Security •Propriedades customizadas para integração com serviço de recursos OAuth2 # SECURITY OAUTH2 RESOURCES (ResourceServerProperties) security.oauth2.resource.filter-order= # The order of the filter chain used to authenticate tokens. security.oauth2.resource.id= # Identifier of the resource. security.oauth2.resource.jwt.key-uri= # The URI of the JWT token. Can be set if the value is not available and the key is public. security.oauth2.resource.jwt.key-value= # The verification key of the JWT token. Can either be a symmetric secret or PEM-encoded RSA public key. security.oauth2.resource.prefer-token-info=true # Use the token info, can be set to false to use the user info. security.oauth2.resource.service-id=resource # security.oauth2.resource.token-info-uri= # URI of the token decoding endpoint. security.oauth2.resource.token-type= # The token type to send when using the userInfoUri. security.oauth2.resource.user-info-uri= # URI of the user endpoint.
  • 155.
    Spring Cloud Security •Propriedades customizadas para um cliente OAuth2 • PPro • Propriedades customizadas para trabalhar com SSO # SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) security.oauth2.client.client-id= # OAuth2 client id. security.oauth2.client.client-secret= # OAuth2 client secret. A random secret is generated by default # SECURITY OAUTH2 SSO (OAuth2SsoProperties) security.oauth2.sso.filter-order= # Filter order to apply if not providing an explicit WebSecurityConfigurerAdapter security.oauth2.sso.login-path=/login # Path to the login page, i.e. the one that triggers the redirect to the OAuth2 Authorization Server
  • 156.
    Spring Cloud Security •Exemplo de proteção de um serviço com OAuth2 • Utilizando o servidor de autorização para validar os tokens @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { //... } security: sessions: stateless basic: enabled: false user: password: none oauth2: resource: preferTokenInfo: false userInfoUri: http://localhost:9999/users/current
  • 157.
    Spring Cloud Security •Validando o token diretamente no cliente security: sessions: stateless basic: enabled: false user: password: none oauth2: resource: jwt: keyValue: | -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo1jWPfjvJxaXCHzvClU7 uJg+6AlZ8ht1Rbr+7Wo5o+YBWgCc6lZmSv/mwxvfL/wqagQ/W756a8vUJ7qFz/k9 eBSJQSRuzJ6pT4OMMR9gbmYroh3RM/Xd5RelJgT3+OrvjAZr1pFYdAwp0q1T9XPa 6PnCXq8KhIqNPxMjcaBrOycWEgWE4g4VnnrKDLtMmEZZIc0EMv8j7womsyNkbTyl nPsbFttNwtFoTVJeqvD01Fd6ISaoOVQAUfAcxvp77B/A1g0No3GHBupEtW3Hgp2/ 80Zl0+Gwjl6Wag5Mu9H7MIUPo+4xFGAJ0uwseHiErZqdWlHIo179IacB87+9Vt0g pwIDAQAB -----END PUBLIC KEY-----
  • 158.
    • Suporte àdefinição de regras de segurança via anotações • Habilita o suporte as anotações • @PreAuthorize, @PostAuthorize, @Secured • Suportando as expressões de segurança do Spring Security • E também adicionando suporte as expressões OAuth2 Spring Cloud Security @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityMethodConfig extends GlobalMethodSecurityConfiguration { @Override protected MethodSecurityExpressionHandler createExpressionHandler() { return new OAuth2MethodSecurityExpressionHandler(); } }
  • 159.
    • OAuth2SecurityExpressionMethods • Expressõespara restrição de segurança via OAuth2 • #oauth2.clientHasAnyRole('ADMIN', 'MANAGER') • #oauth2.clientHasRole('MANAGER') • #oauth2.denyOAuthClient() • #oauth2.hasAnyScope('read', 'write') • #oauth2.hasAnyScopeMatching('^abc .*', '[^a-z]{3}') • #oauth2.hasScope('read') • #oauth2.hasScopeMatching('^abc .*') • #oauth2.isClient() • #oauth2.isOAuth() • #oauth2.isUser() Spring Cloud Security
  • 160.
    • Integração comFeign via OAuth2FeignRequestInterceptor Spring Cloud Security @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Bean public OAuth2FeignRequestInterceptor feignRequestInterceptor( OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource) { return new OAuth2FeignRequestInterceptor( oAuth2ClientContext, resource); } }
  • 161.
    Laboratório 11 (cloud-lab11) •Protegendo os microservices com Spring Cloud Security
  • 162.
    Spring Cloud Security •É necessário proteger os demais serviços da aplicação
  • 163.
    Spring Cloud Security •Para proteger o Config Server • É necessário habilitar restrição de acesso no Config Server • Informar login e senha para conexão pelos clientes security: user: name: configUser password: configPassword role: SYSTEM spring: cloud: config: uri: http://localhost:8888 username: configUser password: configPassword application.yml bootstrap.yml
  • 164.
    Spring Cloud Security •Para proteger o Eureka Server • É necessário habilitar segurança global no serviço Eureka @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("eurekaUser").password("eurekaPassword"); } @Override public void configure(HttpSecurity http) throws Exception { http.httpBasic().and().csrf().disable() .authorizeRequests().anyRequest().authenticated(); } } eureka: client: serviceUrl: defaultZone: http://eurekaUser:eurekaPassword@localhost:8761/eureka application.yml
  • 165.
    Spring Cloud Security •Para proteger o Hystrix Dashboard • Necessário habilitar restrição de acesso nas propriedades • Informar login e senha para acesso ao Hystrix Dashboard • http://hystrixUser:hystrixPassword@localhost:7979/hystrix • http://hystrixUser:hystrixPassword@localhost:7979/turbine.stream security: basic: enabled: true user: name: hystrixUser password: hystrixPassword role: SYSTEM application.yml
  • 166.
    Laboratório 12 (cloud-lab12) •Aplicando segurança nos serviços da plataforma Spring Cloud
  • 167.
  • 168.
  • 169.
    API Gateway • Designpattern aplicado à microservices • Requisições podem ser apenas repassadas, ou modificadas “Single entry point for the service clients”
  • 170.
    Netflix Zuul “Roteamento centralizadopara microservices" • Fornece único ponto de entrada para os serviços • Roteamento e balanceamento na JVM • Cria uma rota para cada serviço no Eureka • Define filtros para pontos de entrada • Similar outros roteamentos • httpd, nginx, CF go router
  • 171.
  • 172.
  • 173.
    Netflix Zuul • Bastaadicionar a dependência Maven • Utilizar a anotação @EnableZuulProxy <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> @EnableZuulProxy @SpringBootApplication public class ZuulServer { public static void main(String[] args) { SpringApplication.run(ZuulServer.class, args); } }
  • 174.
    Netflix Zuul • @EnableZuulServervs @EnableZuulProxy • @EnableZuulServer • Simples definição de um roteamento Zuul • Deve ser utilizado para customização de código de roteamento sem comportamento de proxy • “Blank” Zuul server • @EnableZuulProxy • Modelo de uso mais comum • Extensão do @EnableZuulServer • Incorpora o suporte a proxy suportando a definição de routes na configuração • Também suporta customização de código de roteamento por meio de filtros
  • 175.
    Netflix Zuul • Exemplode configuração de rotas via URL zuul: routes: first: path: /first/** url: http://first.example.com second: path: /second/** url: forward:/second third: path: /third/** url: forward:/3rd legacy: path: /** url: http://legacy.example.com
  • 176.
    Netflix Zuul • Integraçãodo Zuul com Eureka e Ribbon
  • 177.
    Netflix Zuul • Exemplode utilização Zuul com Ribbon (serviceId) zuul: routes: aluno-service: path: /aluno/** serviceId: aluno-service disciplina-service: path: /disciplina/** serviceId: disciplina-service ribbon: eureka: enabled: false aluno-service: ribbon: listOfServers: localhost:8080,localhost:18080 disciplina-service: ribbon: listOfServers: localhost:8081,localhost:18081
  • 178.
    Netflix Zuul • Exemplode utilização Zuul com Eureka (serviceId) zuul: routes: aluno-service: path: /aluno/** serviceId: aluno-service disciplina-service: path: /disciplina/** serviceId: disciplina-service eureka: client: serviceUrl: defaultZone: http://eurekaUser:eurekaPassword@localhost:8761/eureka instance: preferIpAddress: true ribbon: eureka: enabled: true
  • 179.
    Netflix Zuul • Porpadrão Zuul ignora alguns HTTP headers • Pode-se customizar os sensitiveHeaders para definir quais headers devem ser ignorados por rota definida • Adicionalmente pode ser configurado • zuul.ignoreHeaders • Para ignorar headers globais (todos as rotas) • zuul.ignoreSecurityHeaders • True/false para ignorar os headers de segurança • https://docs.spring.io/spring-security/site/docs/current/reference/html/ headers.html#default-security-headers sensitiveHeaders: Cookie,Set-Cookie,Authorization zuul: routes: users: path: /myusers/** sensitiveHeaders: IgnoredHeader1, X-Auth-Token url: https://downstream
  • 180.
    Netflix Zuul • Demaisconfigurações suportadas • zuul.max.host.connections • zuul.max.host.maxTotalConnections • zuul.max.host.maxPerRouteConnections • zuul.ribbonIsolationStrategy • zuul.prefix • zuul.stripPrefix • zuul.retryable • zuul.addProxyHeaders • zuul.addHostHeader • zuul.ignoredPatterns • zuul.ignoredServices • zuul.forceOriginalQueryStringEncoding
  • 181.
    Laboratório 13 (cloud-lab13) •Roteando os serviços com Netflix Zuul
  • 182.
  • 183.
    Zuul Filter • Bastaimplementar a interface IZuulFilter ou extender a classe ZuulFilter • Tipos de filtros • PRE • Executado antes de rotear à origem • ROUTING • Manipula a logica de roteamento do request à origem • POST • Executado após o request ter sido roteado à origem • ERROR • Executado quando algum erro acontece durante o roteamento
  • 184.
    Zuul Filter public classSimpleFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { return null; } }
  • 185.
  • 186.
    Zuul Fallback class MyFallbackProviderimplements ZuulFallbackProvider { @Override public String getRoute() { return "customers"; // use "*" to all routes } @Override public ClientHttpResponse fallbackResponse() { //... } } • Basta implementar um ZuulFallbackProvider • getRoute() define em qual rota será aplicado
  • 187.
  • 188.
    Zuul CORS @Bean public CorsFiltercorsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:8080"); config.addAllowedOrigin("http://www.example.com"); config.addAllowedHeader("*"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } • Pode ser ativado definindo um CorsFilter
  • 189.
    Laboratório 14 (cloud-lab14) •Implementando recursos avançados no Netflix Zuul
  • 190.
    Conclusões • Microservices sãosistemas distribuídos • Sistemas distribuídos são essencialmente complexos • Netflix OSS define ótimas ferramentas para implementação de uma arquitetura de microservices • Spring Cloud • Ótima abstração para Netflix OSS • Fácil utilização por meio de anotações • Integrado com ecossistema Spring Boot • Enjoy it :)
  • 191.
    Revisão Nessa unidade vocêteve a oportunidade de compreender como: • Compreender as funcionalidades das plataformas Spring Cloud e Netflix OSS • Implementar um serviço de configuração centralizada utilizando Spring Cloud Config • Realizar o registro e descoberta dos serviços utilizando Netflix Eureka • Suportar tolerância à falhas e balanceamento de carga na chamada entre serviços com Netflix Ribbon • Tornar os serviços mais resilientes com a implementação de circuit breakers com Netflix Hystrix • Orquestrar a implementação de segurança entre serviços com Spring Cloud Security • Implementar um serviço de proxy e/ou roteamento utilizando Netflix Zuul
  • 192.
    Referências • http://projects.spring.io/spring-cloud/ • https://netflix.github.io/ •http://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.1.RELEASE/ • http://cloud.spring.io/spring-cloud-static/spring-cloud-config/1.3.1.RELEASE/ • https://github.com/Netflix/ribbon • https://github.com/Netflix/eureka • https://github.com/Netflix/Hystrix • https://ahus1.github.io/hystrix-examples/manual.html • http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html • http://www.baeldung.com/spring-security-oauth-jwt • http://www.baeldung.com/sso-spring-security-oauth2 • http://blog.monkey.codes/how-to-use-jwt-and-oauth-with-spring-boot/ • http://stytex.de/blog/2016/02/01/spring-cloud-security-with-oauth2/ • https://jmnarloch.wordpress.com/2015/10/14/spring-cloud-feign-oauth2-authentication/ • http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html • http://www.baeldung.com/spring-cloud-securing-services • https://github.com/Netflix/zuul • https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee • http://callistaenterprise.se/blogg/teknik/2015/05/20/blog-series-building-microservices/