The ORY Hydra SAP BTP, Kyma runtime component is approaching its end of life. In this blog post, I would like to show you the migration procedure to
SAP Cloud Identity Services.
Starting point
To keep things simple, this blog post uses Istio HttpBin as a workload. It is secured with APIRule of type
oauth2_introspection
and ORY Hydra
OAuth2Client
with the scope
test
. To deploy the workload to the dedicated
$NAMESPACE,
follow the steps described in
Create a workload tutorial. Create an ORY Hydra client with the scope
test
using the following command:
cat <<EOF | kubectl apply -f -
apiVersion: hydra.ory.sh/v1alpha1
kind: OAuth2Client
metadata:
name: test_app
namespace: $NAMESPACE
spec:
grantTypes:
- "client_credentials"
scope: "test"
secretName: test_app
EOF
|
Create the following APIRule to secure the workload:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
gateway: kyma-system/kyma-gateway
host: httpbin.$KYMA_DOMAIN
service:
name: httpbin
port: 8000
rules:
- path: /headers
methods: ["GET"]
accessStrategies:
- handler: oauth2_introspection
config:
required_scope: ["test"]
EOF
|
The workload is accessible with the opaque access token obtained while invoking the token endpoint:
curl -ik -X POST "https://oauth2.$KYMA_DOMAIN/oauth2/token" -H "Authorization: Basic $ENCODED_CREDENTIALS" -F "grant_type=client_credentials" -F "scope=test"
|
Configure the SAP Cloud Identity Services application
As a first step, create an application in an OIDC-compliant provider. For this purpose, I use an application created in
SAP Cloud Identity Services.
Next, configure the application protocol to use
OpenID Connect with the scope
test
set in the application's default attributes section. Then, follow the steps outlined in the
Configure Secrets tutorial to configure the secret.
Invoke the
/.well-known/openid-configuration
endpoint to obtain the service tenant configuration. In this tutorial, I use additional secret credentials to access the
introspection
endpoint.
Finally, export the required data as environment variables for later usage:
export IAS_ENC_CREDS={APPLICATION_ENCODED_CREDENTIALS}
export IAS_TOKEN_URL={TOKEN_URL}
export IAS_INTRO_URL={INTROSPECTION_URL}
export IAS_INTRO_ENC_CREDS={INTROSPECTION_ENCODED_CEDENTIALS}
|
I encourage you to read the
SAP Cloud Identity Services documentation thoroughly. Don't hesitate to ask any
questions you may have.
Migration
Modify the existing APIRule and set an additional
oauth2_introspection
access strategy. This operation allows for changing the client configuration while migrating from ORY Hydra to SAP Cloud Identity Services without causing any downtime to the exposed workload .
In addition to the default configuration, URL and its authorization.
Now, you have two
oauth2_introspection
access strategies assigned to a single path. Because of that, you must specify another source for the token. In the following example, the source is configured as
ias_token
. as described in the
authenticator's documentation.
This is a sample code of a modified APIRule:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
gateway: kyma-system/kyma-gateway
host: httpbin.$KYMA_DOMAIN
service:
name: httpbin
port: 8000
rules:
- path: /headers
methods: ["GET"]
accessStrategies:
- handler: oauth2_introspection
config:
required_scope: ["test"]
- handler: oauth2_introspection
config:
required_scope: ["test"]
introspection_url: "https://$IAS_INTRO_URL"
introspection_request_headers:
Authorization: "Basic $IAS_INTRO_ENC_CREDS"
token_from:
header: "ias_token"
EOF
|
Now, you can use both the existing ORY Hydra credentials and the newly created SAP Cloud Identity Services application credentials to invoke the /headers endpoint.
Issue an opaque token from SAP Cloud Identity Services:
curl -ik -X POST "https://$IAS_TOKEN_URL" -H "Authorization: Basic $IAS_ENC_CREDS" -F "grant_type=client_credentials" -F "token_format=opaque"
|
By default, the SAP Cloud Identity Services token endpoint returns JWT. If you want to obtain an opaque token, you need to request it explicitly.
It's recommended to switch from OAuth2 introspection to using short-lived JWTs. To learn more, read about issuing JWT security best practices and about upcoming changes in the API Gateway architecture. This will help you make an informed decision.
To configure the JWT access strategy, export the JWKS_URI obtained from well-known OIDC configuration:
export IAS_JWKS_URLI={JWKS_URI}
|
Apply the modified APIRule to extend the access strategy to JWT:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
gateway: kyma-system/kyma-gateway
host: httpbin.$KYMA_DOMAIN
service:
name: httpbin
port: 8000
rules:
- path: /headers
methods: ["GET"]
accessStrategies:
- handler: oauth2_introspection
config:
required_scope: ["test"]
- handler: jwt
config:
jwks_urls:
- $IAS_JWKS_URLI
token_from:
header: "ias_token"
EOF
|
With this configuration, you can access the workload with Hydra by using opaque tokens and with SAP Cloud Identity Services by using JWT. To obtain a JWT, run the following command:
curl -ik -X POST "https://$IAS_TOKEN_URL" -H "Authorization: Basic $IAS_ENC_CREDS" -F "grant_type=client_credentials"
|
Regardless of whether you obtained an opaque token or JWT, you must pass it in the ias_token
header to access /headers
endpoint:
curl -ik -X GET "https://httpbin.$KYMA_DOMAIN/headers" -H "ias_token: $IAS_TOKEN"
|
Clean up
After migrating all clients that use ORY Hydra credentials to access workload to SAP Cloud Identity Services or any other OIDC-compliant provider application, it is necessary to clean up APIRule. If your clients use the Oauth2 introspection flow, your APIRule should be similar to the following sample
cat <<EOF | kubectl apply -f -
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
gateway: kyma-system/kyma-gateway
host: httpbin.$KYMA_DOMAIN
service:
name: httpbin
port: 8000
rules:
- path: /headers
methods: ["GET"]
accessStrategies:
- handler: oauth2_introspection
config:
required_scope: ["test"]
introspection_url: "https://$IAS_INTRO_URL"
introspection_request_headers:
Authorization: "Basic $IAS_INTRO_ENC_CREDS"
token_from:
header: "ias_token"
EOF
|
Vice versa, if you decide to switch to JWT access tokens, your APIRule should be similar to the following sample:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: httpbin
namespace: $NAMESPACE
spec:
gateway: kyma-system/kyma-gateway
host: httpbin.$KYMA_DOMAIN
service:
name: httpbin
port: 8000
rules:
- path: /headers
methods: ["GET"]
accessStrategies:
- handler: jwt
config:
jwks_urls:
- $IAS_JWKS_URLI
token_from:
header: "ias_token"
EOF
|
As the final step, remove the ORY Hydra oauth2client:
kubectl delete oauth2clients.hydra.ory.sh -n $NAMESPACE $CLIENT_NAME
|
Once the client is deleted, it cannot be restored! To delete the client safely, you must be sure that any other resource does not use it.
Summary
I have written this blog post to show you how to safely migrate from ORY Hydra clients to other providers, focusing on SAP Cloud Identity Services. The Kyma team is well aware that this might be a time-consuming task, so we strongly recommend that you start the migration process as soon as possible.
If you need further information or assistance, please post a new
question.