Application State Management Service(ASMS)

Application State Management Service(ASMS) is a microservice that allows storage of application specific data for an authenticated session. Decoupling this API capability from Cloudentity session service, enables this service to be protected and scaled up in an independent manner. An enterprise grade in-memory session grid solution acts as the storage mechanism for transient data persisted by this service to provide low latency and high performance throughput for data access.

ASMS provides set of RESTful JSON APIs to manage transient application data access, bound to scope of authenticated user session. This data set will expire when authenticated session of user expires. This service can be used to store and retrieve global application context data for sharing across different applications in an enterprise at a user session level. This data set can also be used to enforce business specific authorization rules at the edge along with the user’s authenticated session attributes.

This service facilitates storage and retrieval of business attributes,that are not synced directly to the Identity data store and are not part of default authenticated IAM session. These data attributes can play a major role in defining access to specific business service(s).This service is flexible to store data specific to each business app or business domain (lob) or at global level for each user session.

ASMS Capabilities

Add application data

API’s are available to post application specific data using an authenticated session token. Post authentication or critical identity lifecycle process(es) can post global data to be transiently carried throughout the lifetime of an authenticated session. If there are lot of business applications, this can be used to share business data state across multiple applications as well.

Retrieve application data

API’s are available to retrieve data using an authenticated session token. Retrieved data can be filtered at application level or application data attribute level. Based on authorization rules, if any, enforced at Cloudentity internal API GW, there might be restrictions on which all application level data can be retrieved even for the same authenticated session. For example, there can be restriction on applications from different line of business accessing each other’s business data etc.

Update application data

API’s are available to update data using an authenticated session token. Can be used if a business application wants to modify an already persisted value

Delete application data

API’s are available to delete application data for an authenticated session token. Normally, data will be automatically destroyed when authenticated session expires or times out etc. But in case data needs to be explicitly removed for a user at an application level, these API’s will be handy.

Application Data Based Authorization

Having data available in this service facilitates Cloudentity Trust engine to authorize business data access at application level. Cloudentity ASMS authz validators will have access to underlying services and can enforce application level authorization rules and policies to restrict access to underlying application endpoints.

Technical Details

Microservice Stack

Name Value

Platform

Vertx

Language

Scala

Docker

Available

Components

ASMS interacts with external Hazelcast cluster for transient application state data. It does not have dependency on any other component. Interaction with Hazelcast cluster is over native binary protocol.App state management has an independent listener verticle implementation, that removes any application state data for expired or timed-out authenticated sessions.

asms components

Dependencies

  • Cloudentity Enterprise Session Store Cluster

  • Cloudentity API GW (Optional)

ASMS API’s are normally protected by Cloudentity internal API GW, as is the case with any internal Cloudentity microservice. This translation allows to inject an authenticated JWT with authenticated session information onto this service. If there is enough trust inside network, authenticated session JWT’s can be created by internal service and can access the API’s exposed by these services.

Configuration

This document outlines all the configurable points exposed in this microservice.

Data Storage Mechanism

This service can either be run in a standalone in-memory mode for test purpose or can be configured to connect to an external Enterprise Hazelcast cluster.

To run the service in one of the configuration modes following config needs to be tweaked, default is set to be hazelcast grid.

[source.json]
registry:components": {
    "app-state-storage-service": { "main": "com.cloudentity.services.asms.routes.storage.HazelcastApplicationStateStorage" }
    ..
    }

Value

Description

Native-memory

com.cloudentity.services.asms.routes.storage.InMemoryApplicationStateStorage

Hazelcast

com.cloudentity.services.asms.routes.storage.HazelcastApplicationStateStorage

Incoming Transaction Authorization

Endpoints in this service can be accessed by only callers that passes in a valid JWT. Current configuration expects the JWT to be symmetrically signed and uses following configuration to configure the signature for incoming JWT verificaiton

In below example, the services are exposed via Cloudentity API GW and hence accepts only requests signed and forwarded by Cloudentity API GW.

[source.json]
"jwt-service": {
    "secret": "PUT_API_GW_SECRET",
    "issuer": "api-gateway"
  }

Storage Map Name

Application state data is configured in hazelcast to store the data in a specific Hazelcast map. Name of the map is configurable at this service level. This storage map name is configured at this location

[source.json]
  "app-state-storage-service" : {
    "storage-map-name" : "app-state-data"
  },
Warning
Modify the map name only if required. If map name is modified here, make sure the remote cluster has proper configuration of new map name

IMPORTANT : Refer Evicting App State Entries configuration section as well.

Evicting App State Entries

This service has eviction listeners that tie lifetime of an entry to a user’s authenticated sessionToken. This allows the service to remove entries once user’s session expires or times out etc

map-to-listen → hazelcast map name for authenticated sessions map-to-update → hazelcast map name for application data storage

[source.json]
 "hz-eviction-service" : {
    "map-to-listen" : "sessions",
    "map-to-update" : "app-state-data"
  }

Service Listener Port

Service is written in vertx and is exposed at following configuration by default, unless overriden by a containerized or wrapper services, if applicable

[source.json]
{
  "apiServer": {
    "http": {
      "port": 7071
    },

Hazelcast configuration

ASMS uses Hazelcast Map for storing application state data when hazelcast is specificed as the storage mechanism. Following map entry in external hazelcast configuration, will enable explicit definition and management of the entries in map in remote cluster like ttl etc.

Hazelcast configuration file entry

These entries can be either made manually in remote cluster hazelcast server.xml or via chef cookbook role file overrides or mounted configs in terms of docker configuration etc.

Below is the final configuration that should be made available to hazelcast server cluster to manage the map configuration for app state data.

[source,xml]
  <map name="app-state-data">
        <in-memory-format>BINARY</in-memory-format>
        <backup-count>1</backup-count>
        <async-backup-count>1</async-backup-count>
        <time-to-live-seconds>0</time-to-live-seconds>
        <max-idle-seconds>28800</max-idle-seconds>
        <eviction-policy>NONE</eviction-policy>
        <max-size>0</max-size>
        <eviction-percentage>25</eviction-percentage>
        <min-eviction-check-millis>100</min-eviction-check-millis>
        <merge-policy>com.hazelcast.map.merge.PutIfAbsentMapMergePolicy</merge-policy>
        <cache-deserialized-values>INDEX-ONLY</cache-deserialized-values>
    </map>
Note
backup-count & async-backup-count should be deployment specific and will vary based on number of hazelcast server nodes and availability requirements.

Chef role file configuration

In case you are using Cloudentity chef cookbook for configuring Hazelcast cluster, below section needs to be added to default attributes

[source,json]
"hazelcast": {
    "maps": {
 "app-state-data": {
  "in-memory-format": "BINARY",
   "backup-count": 1,
   "async-backup-count": 1,
   "time-to-live-seconds": 0,
   "max-idle-seconds": 28800,
   "eviction-policy": "NONE",
   "max-size": 0,
   "eviction-percentage": 25,
   "min-eviction-check-millis": 100,
   "merge-policy": "com.hazelcast.map.merge.PutIfAbsentMapMergePolicy",
   "cache-deserialized-values": "INDEX-ONLY"
 },
 ...
 }
}

API GW configuration

ASMS can be exposed via internal Cloudentity API GW and routing rules can be enforced via the API GW. Below configurations are samples and may not be up-to-date with latest API GW configuration rules, but the configuration concepts can still be applied. API GW configuration referenced are of API GW version 1.14+

Service discovery

API GW must be configured to locate ASMS either using a fixed service discovery or using consul as service discovery mechanism

[source,json]
"fixed-sd-provider.json": {
  "fixed-sd-provider": {
    "records": [
      {
        "location": {
          "host": "localhost",
          "port": 7071,
          "ssl": false
        },
        "name": "asms"
      },
      ..
    ]
  }
}

Routing configuration

Below routing configuration exposes all available endpoint within ASMS service for consumption and access to this is protected by "ASMS_ACCESS" access policy.

[source,json]
 "rules": [
 {
      "default": {
        "dropPrefix": true,
        "pathPrefix": "/asms",
        "requestPlugins": [
          {
            "conf": {
              "entities": [],
              "methods": [
                "someJwt"
              ]
            },
            "name": "authn"
          },
          {
            "conf": {
              "policy": "ASMS_ACCESS"
            },
            "name": "authz"
          }
        ],
        "targetHost": "localhost",
        "targetPort": 7071
      },
      "endpoints": [
        {
          "endpointName": "All GET endpoints",
          "method": "GET",
          "pathPattern": ".*"
        },
        {
          "endpointName": "All POST endpoints",
          "method": "POST",
          "pathPattern": ".*"
        },
        {
          "endpointName": "All PUT endpoints",
          "method": "PUT",
          "pathPattern": ".*"
        },
        {
          "endpointName": "All DELETE endpoints",
          "method": "DELETE",
          "pathPattern": ".*"
        }
      ],
      "request": {
        "postFlow": {
          "plugins": [
            {
              "conf": {},
              "name": "outgoingDefaultJwt"
            }
          ]
        }
      }
},
..
]

There are couple of important configurations

  • authN request plugin
    This will ensure only requests that has proper bearer jwt authentication signed with proper credentials will be allowed to access this endpoint.

[source,json]
{
  "conf": {
    "entities": [],
    "methods": [
      "someJwt"
    ]
  },
  "name": "authn"
}
  • authZ request plugin
    This will ensure only calls that satisfy below access policy criteria will be propagated downstream to actual endpoint.

[source,json]
 {
  "conf": {
    "policy": "ASMS_ACCESS"
  },
  "name": "authz"
}

Configure JWT Authentication Providers

LOB specific JWT authentication providers can be configured to limit access to traffic from specific microservices that possess such JWT’s.

Define authentication provider

This will define the kind of authentication provider and configuration to underlying verticle implementation that supports the authentication provider.

[source,json]
 "registry:authn-method-providers": {
    "app2JwtAuthnProvider": {
      "main": "io.orchis.gateway.plugin.impl.authn.methods.JwtAuthnProvider",
      "verticleConfig": {
        "jwtServiceAddress": "app2-symmetric"
      }
    }
    ...
}

Define Verticle service interfaces

This will define service interface that will be used by authN providers used above. JwtAuthentication providers internally depends on SymmetricJwtService in this example. This is the defintion of the underlying JwtService interface and implementation that it will use

[source,json]
 "registry:system": {
          "cache": {
            "main": "io.orchis.tools.vertx.hazelcast.inmemory.InMemoryHazelcastVerticle"
          },
          "fixed-sd-provider": {
            "main": "io.orchis.tools.vertx.sd.provider.FixedSdProvider"
          },
          "jwt-service": {
            "main": "io.orchis.tools.vertx.jwt.impl.JwtServiceVerticle"
          },
          "app1-symmetric-jwt-service": {
            "main": "io.orchis.gateway.jwt.impl.SymmetricJwtService",
            "prefix": "app1-symmetric"
          },
          "app2-symmetric-jwt-service": {
            "main": "io.orchis.gateway.jwt.impl.SymmetricJwtService",
            "prefix": "app2-symmetric"
          }
          ...
        },

Define configuration for jwt service

This will provide the jwt configuration secrets that the provider must use to verify any incoming jwt request against.

[source,json]
"app2-symmetric-jwt-service": {
  "expiresIn": "PT60S",
  "issuer": "cloudentity-api-gateway",
  "secret": "randomappsecret"
}

Configure Advanced Http Settings

This section will allow service configuration to allow advanced feature for retry, configuring httpClient pools sizes, timeout to underlying ASMS service and retry etc for the communication between API GW and ASMS service

[source,json]
"smart-http-target-clients": {
      "asms" : {
        "circuitBreakerOptions": {
          "off": false
        },
        "failureHttpCodes": [
          500,503
        ],
        "httpClientOptions": {
          "maxPoolSize": 20
        },
        "responseTimeout": 5000,
        "retries": 3
      },
      ...
}