Skip to content

Commit

Permalink
Sso manifest update (spring-cloud-services-samples#40)
Browse files Browse the repository at this point in the history
* Update manifest files for deploying an SSO enabled gateway to Kubernetes
Add patch for using VMware harbor registry to host images
* Update routes to match the config for TAS
* Add README for SSO

Co-authored-by: Yuxin Bai <ybai@pivotal.io>
  • Loading branch information
Oliver Hughes and LittleBaiBai authored Oct 23, 2020
1 parent 1d5ba72 commit 77b6ea7
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 56 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*.ipr
out/
scripts/out/
**/secrets/
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
package io.spring.cloud.samples.animalrescue.backend;

import java.util.Collection;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.pivotal.cfenv.core.CfEnv;
import io.pivotal.cfenv.core.CfService;

import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;

import io.pivotal.cfenv.core.CfEnv;
import io.pivotal.cfenv.core.CfService;

@Configuration
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
public class CloudFoundrySecurityConfiguration {
Expand Down Expand Up @@ -50,20 +43,4 @@ public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecu

return httpSecurity.build();
}

static private class UserNameJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {

private Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter
= new JwtGrantedAuthoritiesConverter();

@Override
public AbstractAuthenticationToken convert(Jwt jwt) {
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
return new JwtAuthenticationToken(jwt, authorities, getUserName(jwt));
}

private String getUserName(Jwt jwt) {
return jwt.containsClaim("user_name") ? jwt.getClaimAsString("user_name") : jwt.getSubject();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
Expand All @@ -17,7 +18,11 @@ public class KubernetesSecurityConfiguration {

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
return httpSecurity.httpBasic().disable().build();
httpSecurity.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new ReactiveJwtAuthenticationConverterAdapter(new UserNameJwtAuthenticationConverter()));

return httpSecurity.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.spring.cloud.samples.animalrescue.backend;

import java.util.Collection;

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;

class UserNameJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {

private final Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter
= new JwtGrantedAuthoritiesConverter();

@Override
public AbstractAuthenticationToken convert(Jwt jwt) {
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
return new JwtAuthenticationToken(jwt, authorities, getUserName(jwt));
}

private String getUserName(Jwt jwt) {
return jwt.containsClaim("user_name") ? jwt.getClaimAsString("user_name") : jwt.getSubject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ spec:
env:
- name: spring.profiles.active
value: k8s
- name: spring.security.oauth2.resourceserver.jwt.jwk-set-uri
valueFrom:
secretKeyRef:
name: sso-credentials
key: jwk-set-uri
resources:
requests:
memory: "256Mi"
Expand Down Expand Up @@ -46,6 +51,22 @@ spec:
service: animal-rescue-backend
routes:
- predicates:
- Path=/api/**
- Path=/api/animals
- Method=GET
filters:
- StripPrefix=1
# - RateLimit=2,10s
- ssoEnabled: true
tokenRelay: true
predicates:
- Path=/api/whoami
- Method=GET
filters:
- StripPrefix=1
- ssoEnabled: true
tokenRelay: true
predicates:
- Path=/api/animals/*/adoption-requests/**
- Method=POST,PUT,DELETE
filters:
- StripPrefix=1
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,18 @@ spec:
gateway: gateway-demo-with-dynamic-routes
service: animal-rescue-frontend
routes:
- ssoEnabled: true
predicates:
- Path=/rescue/login
- Method=GET
filters:
- StripPrefix=1
- RedirectTo=302, /rescue
order: 0
- predicates:
- Path=/rescue/**
- Method=GET
filters:
- StripPrefix=1
order: 1000

Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGateway
metadata:
name: gateway-demo-with-dynamic-routes
spec: {}
spec:
ssoEnabled: true
58 changes: 58 additions & 0 deletions k8s/base/gateway-demo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGateway
metadata:
name: gateway-demo
spec:
ssoEnabled: true
routes:
- id: animal-rescue-frontend-0
uri: http://animal-rescue-frontend.animal-rescue.svc.cluster.local
ssoEnabled: true
predicates:
- Path=/rescue/login
- Method=GET
filters:
- StripPrefix=1
- RedirectTo=302, /rescue
order: 0
- id: animal-rescue-frontend-1
uri: http://animal-rescue-frontend.animal-rescue.svc.cluster.local
predicates:
- Path=/rescue/**
- Method=GET
filters:
- StripPrefix=1
order: 1000

- id: animal-rescue-backend-0
uri: http://animal-rescue-backend.animal-rescue.svc.cluster.local
predicates:
- Path=/api/animals
- Method=GET
filters:
- StripPrefix=1
# - RateLimit=2,10s
- id: animal-rescue-backend-1
uri: http://animal-rescue-backend.animal-rescue.svc.cluster.local
ssoEnabled: true
tokenRelay: true
predicates:
- Path=/api/whoami
- Method=GET
filters:
- StripPrefix=1
- id: animal-rescue-backend-2
uri: http://animal-rescue-backend.animal-rescue.svc.cluster.local
ssoEnabled: true
tokenRelay: true
predicates:
- Path=/api/animals/*/adoption-requests/**
- Method=POST,PUT,DELETE
filters:
- StripPrefix=1
- id: animal-rescue-backend-3
uri: http://animal-rescue-backend.animal-rescue.svc.cluster.local
predicates:
- Path=/api/actuator/
filters:
- StripPrefix=1
19 changes: 19 additions & 0 deletions k8s/base/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: animal-rescue

secretGenerator:
- name: sso-credentials
envs:
- secrets/sso-credentials-for-backend.txt
type: Opaque

generatorOptions:
disableNameSuffixHash: true

resources:
- namespace.yaml
- animal-rescue-frontend.yaml
- animal-rescue-backend.yaml
- gateway-demo.yaml
- gateway-demo-with-dynamic-routes.yaml
File renamed without changes.
18 changes: 16 additions & 2 deletions k8s/deploy_to_k8s.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,29 @@
Make sure you have Spring Cloud Gateway for k8s installed.

For SSO to work, you will need to provide two secret files:

* ./k8s/base/secrets/sso-credentials-for-backend.txt
```
jwk-set-uri=https://{your_auth_domain}/token_keys
```
* ./k8s/overlays/sso-secret-for-gateway/secrets/test-sso-credentials.txt
```
auth-domain=https://{your_auth_domain}
client-id={your-client-id}
client-secret={your-client-secret}
```
This file structure may change as the product evolves. Please refer to the SCG4K8s doc for the most up-to-date template.

If you have `kustomize` installed, you can run the following command:

```bash
kustomize build ./k8s | kubectl apply -f -
```

If you don't want to use `kustomize`, you can apply each yaml file in the `k8s` folder manually into the `animal-rescue` namespace (or any namespace you like!).
If you don't want to use `kustomize`, you can apply each yaml file in the `k8s` folder manually into the `animal-rescue` namespace (or any namespace you like!). Make sure to create the SSO credentials secret in the SCG installation namespace (`spring-cloud-gateway` by default).

There are two gateway instance being created - `gateway-demo` and `gateway-demo-with-dynamic-routes`.
There are two gateway instances created - `gateway-demo` and `gateway-demo-with-dynamic-routes`.
* `gateway-demo` has all the routes pre-defined when creating the gateway.
* `gateway-demo-with-dynamic-routes` doesn't have any routes defined on creation. The route definition is defined in a `SpringCloudGatewayBinding` object that can be version-controlled with each routed application.

Expand Down
18 changes: 0 additions & 18 deletions k8s/gateway-demo.yaml

This file was deleted.

8 changes: 2 additions & 6 deletions k8s/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: animal-rescue

resources:
- namespace.yaml
- animal-rescue-frontend.yaml
- animal-rescue-backend.yaml
- gateway-demo.yaml
- gateway-demo-with-dynamic-routes.yaml
- base
- overlays/sso-secret-for-gateway
11 changes: 11 additions & 0 deletions k8s/overlays/sso-secret-for-gateway/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: spring-cloud-gateway
secretGenerator:
- name: gateway-sso-credentials
envs:
- secrets/test-sso-credentials.txt
type: Opaque

generatorOptions:
disableNameSuffixHash: true
3 changes: 2 additions & 1 deletion skaffold.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ build:
deploy:
kustomize:
paths:
- k8s
- k8s/base
- k8s/overlays/sso-secret-for-gateway

0 comments on commit 77b6ea7

Please sign in to comment.