This tutorial will walk you through the steps to add an authentication mechanism to a sample Spring Boot application using AppSSO service, running on Tanzu Application Platform (TAP).
Before starting the tutorial, please ensure that the following items are addressed:
v0.11.6
or above is available locally.v1.2.0
or above is available and fully reconciled in your cluster.
run
(deploy-only) deploy the existing application from existing image and existing GitOps manifest.iterate
Recommended (build,deploy) build application from scratch and deploy from generated GitOps manifest.full
(build,deploy) ^^.v1.0.0-beta.5
or above is available and reconciled successfully on your cluster.👟 Skip to step-by-step instructions if you are already familiar with the accelerator used in this tutorial.
In this tutorial, you will be working with a sample Servlet-based Spring Boot application that uses Spring Security OAuth2 Client library .
You can find the source code for the application here. To follow along, be sure to Git clone the repository onto your local environment.
The application, once launched, has two pages:
/home
), available to everyone./authenticated/home
), for signed-in users only.The security configuration for the above is located at com.vmware.tanzu.apps.sso.sampleworkload.config.WebSecurityConfig
.
For more in-depth details about how apps are configured with Spring Security OAuth2 Client library, be sure to check out the official Spring Boot and OAuth2 tutorial.
By default, there is no application properties file in our sample application and this is by design: even the simplest application can be deployed with AppSSO, you can even go to start.spring.io and download a Spring Boot app with Spring Security OAuth2 Client library, and you are good to go! There is yet another reason for the absence of any properties files: a demonstration of Spring Cloud Bindings in action, which removes the need for any OAuth related properties. Spring Cloud Bindings will be introduced later in this tutorial.
ClientRegistration
A critical piece of integration with AppSSO is to create a ClientRegistration
custom resource definition. A ClientRegistration
is a way for AppSSO to learn about the sample application. In the sample application, you can find the definition file named client.yaml
, at the root of the source directory.
The ClientRegistration
resource definition contains a few critical pieces in its specification:
authorizationGrantTypes
is set to a list of one: authorization_code
. Authorization Code grant type is required for OpenID Connect authentication which we will be using in this tutorial.redirectURIs
is set to a list of two URIs: a remote URI and a local URI (i.e. 127.0.0.1
). The remote URI will be the full URL to which AppSSO will redirect the user back upon successful authentication. The local URI is only meant for debugging purposes and can be ignored unless desired. The suffix of both URIs is important for Spring Security - it adheres to the default redirect URI template .scopes
is set to a list of one scope, the openid
scope. The openid
scope is required by OpenID Connect specification in order to issue identity tokens which designate a user as ‘signed in’.For more details about
ClientRegistration
custom resource, see ClientRegistration CRD.
The client.yaml
file is using ytt templating conventions. If you have the Tanzu Cluster Essentials installed, you should already have ytt
available on your command line. Later in the tutorial, we will generate a final output ClientRegistration
declaration that will look similar to the below:
apiVersion: sso.apps.tanzu.vmware.com/v1alpha1
kind: ClientRegistration
metadata:
name: appsso-starter-java
namespace: workloads
spec:
authServerSelector:
matchLabels:
# ask your Service Operator for labels to target an `AuthServer`
clientAuthenticationMethod: basic
authorizationGrantTypes:
- authorization_code
redirectURIs:
- http://appsso-starter-java.workloads.127.0.0.1.nip.io/login/oauth2/code/appsso-starter-java-client
- http://127.0.0.1:8080/login/oauth2/code/appsso-starter-java-client
scopes:
- name: openid
Workload
sTo deploy the sample application onto a TAP cluster, we must first craft it as a Workload
resource ( a Cartographer CRD). A Workload
resource can be thought of as a manifest for a process you want to execute on the cluster, and in this context, the type of workload is web
- a web application. TAP clusters provide the capability to apply Workload
resources out of the box within the proper profiles, as described in the prerequisites section.
To deploy a workload, it is best to work in a separate workload-specific namespace. Once created, there are required TAP configurations that need to be applied before a Workload
in a specific namespace can be deployed properly.
To tie it all together and deploy the sample application, the following are the steps involved.
Create a workload namespace called workloads
:
kubectl create namespace workloads
Within the workloads
namespace, apply TAP required developer namespaces as described.
👉 Follow along with TAP developer namespace setup example in the Appendix.
ClientRegistration
Apply the client.yaml
definition file (described above)
⚠️ Make sure to set auth_server_name
field to the name of the AuthServer custom resource.
ytt \
--file client.yaml \
--data-value namespace=workloads \
--data-value workload_name=appsso-starter-java \
--data-value domain=127.0.0.1.nip.io \
--data-value auth_server_name="" \
--data-value claim_name=appsso-starter-java | \
kubectl apply -f-
A bit more detail on the above YTT data values:
127.0.0.1.nip.io
is the easiest approach to get a working DNS route on a local cluster.This command has generated a ClientRegistration
definition and applied it to the cluster. To check the status of the client registration, run:
kubectl get clientregistration appsso-starter-java --namespace workloads
You should see the ClientRegistration
entry listed.
Using Tanzu Services plugin CLI, create a service resource claim for the workload:
⚠️ Name of the claim must be the same as the value of
claim_name
from previous step.⚠️ Resource name must be the same name as the workload name.
tanzu services claims create appsso-starter-java \
--namespace workloads \
--resource-namespace workloads \
--resource-name appsso-starter-java \
--resource-kind ClientRegistration \
--resource-api-version "sso.apps.tanzu.vmware.com/v1alpha1"
Once applied, you may check the status of the claim like so:
tanzu services claim list --namespace workloads
You should see appsso-starter-java-client
claim with Ready
status as True
.
For more information about service claims, check out the Services Toolkit docs here .
The Tanzu CLI command to create a workload for the sample application should look like the following:
⚠️ You must have access to
gitops-appsso-starter-java.git
repository in Pivotal org. If you do not have access, create your own empty repository with a single commit on it, then pointgitops_repository
parameter to it. You must usessh
protocol if you are creating a private repository.
# When using 'iterate' or 'full' TAP profile(s) - build from source and deploy from generated GitOps manifest
tanzu apps workload create appsso-starter-java \
--namespace workloads \
--type web \
--label app.kubernetes.io/part-of=appsso-starter-java \
--service-ref "appsso-starter-java=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:appsso-starter-java" \
--git-repo ssh://git@github.com/sample-accelerators/appsso-starter-java.git \
--git-branch main \
--param gitops_repository=ssh://git@github.com/pivotal/gitops-appsso-starter-java.git \
--live-update \
--yes
OR when using ‘run’ TAP profile - deploy workload via existing GitOps manifest
tanzu apps workload create appsso-starter-java \
--namespace workloads \
--type web \
--label app.kubernetes.io/part-of=appsso-starter-java \
--service-ref "appsso-starter-java=services.apps.tanzu.vmware.com/v1alpha1:ResourceClaim:appsso-starter-java" \
--param gitops_repository=ssh://git@github.com/pivotal/gitops-appsso-starter-java.git \
--live-update \
--yes
The above command creates a web Workload
named ‘appsso-starter-java’ in the workloads
namespace. The sample applications’ source code repository is defined in the git-repo
and git-branch
parameters. Workloads are usually built from scratch and later deployed – the mechanism that allows a built artifact to be deployed is managed via GitOps approach, and so we specify a GitOps specific repository for the workload specified with --param gitops_repository
parameter. From the previous step, we specify a ClientRegistration
service resource claim via the service-ref
parameter. In doing so, we enable the Workload
’s Pods to have the necessary AppSSO-generated credentials available as a Service Binding. Learn more about how this works here.
It takes some minutes for the workload to become available as a URL.
To query the latest status of the Workload, run:
tanzu apps workload get appsso-starter-java --namespace workloads
⚠️ You may see the status of the workload at first:
message: waiting to read value [.status.latestImage] from resource [image.kpack.io/appsso-starter-java] in namespace [workloads]
reason: MissingValueAtPath
status: Unknown
This is NOT an error, this is normal operation of a pending workload. Watch the status for changes.
Follow the Workload
logs:
tanzu apps workload tail appsso-starter-java --namespace workloads
Once the status of the workload reaches the Ready
state, you may navigate to the URL provided, which should look similar to:
http://appsso-starter-java.workloads.127.0.0.1.nip.io
Navigate to the URL in your favorite browser, and observe a large login button tailored for logging with AppSSO.
Once you have explored the accelerator and its operation, head on to the next section for uninstall instructions.
You may delete the running accelerator by running the following:
Delete the sample application workload
tanzu apps workload delete appsso-starter-java --namespace workloads
Delete the service resource claim for the ClientRegistration
tanzu services claim delete appsso-starter-java --namespace workloads
Disconnect the accelerator from AppSSO
kubectl delete clientregistration appsso-starter-java --namespace workloads