This page captures useful background from the development of the pluggable security seccom proposal. This material has been moved here for clarity.


Basic Interaction Pattern

We shall illustrate the proposed approach with simple A&AI example, securing the Sparky (A&AI UI) microservice:



1.The ONAP portal authenticates the A&AI user on launch (this may use the Auth* service as an abstraction to perform the authentication).
2.The portal invokes the Sparky microservice to launch the A&AI UI including the provided token.
3.The auth* filter intercepts the request and invokes the authorize method on the Auth* microservice.
4.The Auth* microservice invokes the AuthZ provider (the CADI library in this example) authorisations method and returns the principal’s claims (ideally in a JWT).
5.The filter compares the claims with the filter requirements for the invoked method/URI pattern.
6.If the authorisations are satisfied, Sparky processes the request.


Components

Auth* Microservice

A standardised interface for:

    • User authentication
    • Request authorisation
    • Other operations –  e.g. token revocation check.

Characteristics

Operates on Security Provider tokens and JWTs.

Abstracts ONAP components from the specifics of authorisation and authentication service:

    • Composition and Implementation
    • Configuration
    • Token representation


Specific implementations, such as the CADI based example opposite, provide an adaptation layer between the standardised interface and the required Authentication and Authorisation providers.



Auth* example implementation based on CADI/AAF


Auth* Servlet filter

    • Intercepts Service Requests
    • Logs the request and its transactionId for traceability.
    • Invokes the Auth* service to authenticate/validate token and retrieve authorisations (in JWT)
    • Compares the user authorisations with those required for the requested operation
    • Can perform local JWT authorisation comparisons 
    • Can call Auth* to check for revoked tokens.
    • Passes authorisation context to the service.

Transparently propagates valid tokens to calls made by the microservice.

Characteristics

    • Isolates application code from security concerns
    • Insensitive to the token representation
    • Largely insensitive to the method of propagating the token
    • Driven by deploy time configuration to minimise updates to the service distribution.


Auth* filter


Extensions

Multiple microservices can be invoked for a single user request. Having to invoke the Auth* microservice at every leg in the call-chain inflates the latency budget (even if the Auth* service caches results). To offset this cost we propose:



1.The Sparky Auth* filter is configured to append the returned JSON Web Token (JWT - https://tools.ietf.org/html/rfc7519) to the downstream request.
2.The Resource Microservice Auth* filter is configured to accept either a JWT or the original credential.
3.The filter interrogates the JWT locally to determine whether the request is authorised for the requested URI pattern avoiding interrogating the Auth* service:

If the necessary authorisations are present the request is admitted.

If not, a call is made to the Auth* service with the original credential JWT and the current scope as per the standard flow.

If the necessary authorisations are still absent, the request is rejected.


Impacts of Pluggable Security:

To A&AI clients:

  1. (development) Need to integrate client with Authentication Provider to retrieve credential. Note - this could be abstracted via a call to Auth* configured with a re-direct if required?
  2. (development) Client needs to provide tokenised credential in REST request to A&AI.


TO A&AI:

  1. (deployment) Need to configure authorisation requirements per URI, per service. Note that this can be as fine or coarse as the project requires.
  2. (development) All new or modified microservices need to use the secured REST client to invoke other microservices for seamless and secure propagation of JWT.

Other impacts.

It is the intention of this proposal that all ONAP components can adopt pluggable security. This provides a consistent security implementation across the entire platform In order to do so the following changes would be required:

  1. (development) All REST interfaces are secured with an Auth* filter.
  2. (development) All REST interfaces specify their authorisation requirements in an Auth* configuration file.
  3. (development) Microservices that initiate REST calls to other ONAP components should use the A&AI REST client (should move to a general ONAP package) for seamless and secure propagation of JWT
  4. (test/deploy) All users of the application should be provisioned with the appropriate Authorisations.


Auth* / CADI analysis:

It is the position of the AAF Security team, that the CADI Framework portion of AAF already provides Pluggable security, 

Note: there seems to have been a confusion of Terms between Providers and Protocols.  Here is a mini-glossary defining these terms.

Protocol - the definitions of handling security at real time.  What kind of Security information is on a transaction, how is Security information passed with that transaction, what is the appropriate response when the security information is not there.

Examples:

Basic Auth puts encoded user/password on an HTTP Header called "Authorization" prepended by "Basic ".  

OAuth2 puts a reference token as an "Authorization" Header prepended by "Bearer".

X509 Authentication is entirely different.  The client certificate used to instantiate the TLS connection is made available for inspection by Request Object function call.

Provider - an external source of real-time security information.  

Examples:

For Basic Auth, the Provider is an external entity that will validate User/Password.  

For OAuth2, the Provider is an external entity that provides Tokens and Introspection information.


Topic

Auth*

CADI

Do you support more than one Authentication Protocol?


By Protocol, we mean, for example, Basic Auth/Certificate/OAuth2, etc)?


The implementation of the Auth* filter on each MS is the same. The filter only needs to be configured to extract the credential(s) or token(s) from the request. The list of tokens and their types are sent to the Auth* service in a request header.

The communication between the application and the Auth* service is protected by TLS.

Interpretation/validation of the submitted tokens is delegated to the Auth* service and the operator's AuthN provider.

Expected Protocols, like those in the question are built in.

For each new kind of Authentication Protocol, you build an implementation of a TAF, making that available as part of the program.

This would be created, for instance, by a company having its own kind of SSO Protocol.

It should be noted that not every Protocol has an external Provider. Certificate Authentication, provided by CADI, does not require any external calls. Some have only an initialization setup, and do not make "provider" calls real time. The TAF allows all these differences to be accounted for, but plugged into CADI the same way.

How do you make make new Protocols?

New or additional configuration of the Auth* filter. No code change or rebuild of the application microservices.

New or additional adapter code in the Auth* service.

Heavy lifting is done by the underlying AuthNZ provider.

To create a whole new Protocol Adapter, you extend the TAF Interface, recognizing, for instance, the Security Information on the incoming call, and the appropriate response if it is not.
Do you support these Authentication Protocols simultaneously?

So long as the filter can extract the required credential or tokens the Auth* service can be adapted to support whatever protocol scheme is required of the operator.

This does not require rebuild or redeploy of the application services.

CADI allows for Multiple Protocols to be enabled for the configuration. An incoming transaction is checked for the first positive Authentication.

This is critical, for instance, when some apps can do x509, and others can only do Basic Auth. This is ability is also important for any migration, for instance, from User/Password to Certificate based Authentication.

Within the same Container, different Microservices can serve GUI (Browsers) or Applications with the same configuration, because CADI recognizes at real-time what these protocols are.

Could you support Multi-factor Authentication in the future?Yes, as outlined above.The current CADI behavior is to accept onevalid Authentication out of all the configured Plugins before proceeding. Multi-factor Authentication only requires a small modification to require two Authentication protocols before proceeding. This would be an extremely minimal change.

How do you swap authentication provider?

Update/replace central Auth* implementation with adapter for new provider. No impact to microservices.

Adding Configuration Properties will both enable the Protocol indicated, but also change Providers (if it makes sense for the Protocol) by directing Endpoints in configurations.

Example: You can enable the OAuth2 TAF, and point it to ISAM Endpoints, AAF Endpoints or another OAuth2 provider altogether by modifying the endpoint property.

There is no impact to micro services to change out Providers of the same Protocol.


What is the response to the Client when there is no Authentication?

The filter sends an HTTP 401 as per restpatterns.org best practice.

If a redirect is required for sign-on then it is expected that this is handled by another filter in the filter chain.

The CADI TAF accommodates different responses based on the Protocol. For instance, a BasicAuth response is "401" in the HTTP Header. However, the appropriate response to a Browser call with OAuth or Single Sign-on may be a redirect to an external login.

Further, CADI recognizes real-time whether the caller is a Machine or a Person (Browser), and sends the appropriate response.

Do you support more than one Authorization Protocol?All authorisation protocols are currently converted to JWT in the AUTH* service.Yes, Configured Authorization Protocols are in existence in CADI today. AAF supports and integrates into OAuth Authorization as well as AAF's Fine-Grained Authorization at the same time.
Do you support more than one Authorization Protocol at the same time?The availability of authorisation protocols is constrained by the operator's Authorisation provider(s).Yes. CADI is able to work with OAuth2 Authorization information when it is available. If both OAuth2 and AAF information is requested, CADI extracts the AAF Fine Grained permissions from the Introspection without network call. If there is no tokenization, CADI queries and caches a call to AAF Fine Grained Permissions.
How do you swap authorisation provider?Update/replace central Auth* implementation with adapter for new provider. No impact to microservices.Swapping providers of each Authorization Protocol is a matter of configuring the Endpoint. There is no impact to Microservices, for instance, in trading out one OAuth2 provider endpoint for another OAuth2 endpoint.
Do you support JWT Tokens for carrying Authorization?Yes

CADI was asked first to support OAuth2 Tokens. This was done by creating , which is provided in Beijing Release.

If a JWT Token method is proposed, then the details of the JWT Protocol need to be laid out. However, a new CADI LUR would extract the AAF permissions from the JWT token, like it does OAuth2 Tokens today, and make those available to the App.

Further, if this LUR is created, CADI would then accept 3 different LURs at runtime, choosing which one is appropriate on behalf of the App.

Can Security be externalized as a K8 MicroService?Yes - this is central to the proposal.

There already exists today a K8 Microservice which encapsulates CADI behavior locally, and provides this to other Microservices within the Container when required for various reasons like language, or convenience.

Given this Microservice is already being used by a major contributor to ONAP, it would not likely take much to have this moved to ONAP.

It should be noted that a Separate Microservice, either the above, or the Auth* proposal requires additional overhead because

  • Security calls, when required, are passed to another entity to make on its behalf, not made locally. This reduces speed and resiliency
  • A Separate MicroService solution would have to Translate any Authentications or Authorizations into a common format.

How does an app include the solution in K8?

The Auth* service has it's own Docker container that can be orchestrated by K8 identically to any other ONAP microservice.

At the moment, Apps are pulling in CADI Code via Maven, and configuring, as you would any Java library.

However, the current proposal is to create a Docker Image with all the CADI elements (including Configurations) built in, making it easier for Microservices to include.

The point being is that CADI is flexible to work in many scenarios, so there are options not explored to make CADI even easier in a Container world.

Is your solution available outside of K8?

Yes. The underlying technology consists of:

1) A standard request filter

2) A microservice that can be deployed in a variety of application containers.

CADI (for Java) works as standalone process, within AppServers, as Adapters in Tools such as Cassandra, Shiro, etc. Essentially, anything that can be utilize Java can use CADI.

As other Languages are built around CADI, those are available in all kinds of deployment scenarios as well.

K8 Microservices, of course, only run in K8. If the choice is made in the future to choose another Container system, CADI still works, only jettisoning the K8 specific portion.

What is the impact of new security capabilities on microservices? E.g. Add SAML support for interfacesUpdate Auth* credential config with location of new credential type. Deploy updated credential config. No rebuild/redeploy of MS.

SAML would be a new Protocol (see above). The decision to pull the protocol into the service itself, or into a separate Microservice is a policy one.

If you want to use the new Protocol Directly, then you include on the next build. Otherwise, you could implement only in the external Microservice, as

What is the impact on microservice of patching security?Rebuild MS image with updated filter/REST client jar.

Security patching comes in many flavors.

1) Java (or other) Patching - rebuild MS Image

2) CADI Jar patching - rebuild users of Jars

a) if this the separate Microservice referenced above, then rebuild that image.

b) If Apps include CADI Directly, then rebuild, using extensive ONAP CI/CD system, and allow it to build the image. Update images.

Per micro-service, what configuration is required?TLS cert management (to talk to Auth* service) Vanity URI for Auth* service Filter configuration – declaration of authorisations required per supported URI pattern.

Configuration depends on the Protocol, but each Protocol is loaded by property in a property file chain depending on what is desired.

* TLS 2-way Authentication requires access to Keystore, and an alias

* Basic Auth requires endpoint to BasicAuth provider

* OAuth requires Endpoints to Token Server, Introspect Servers

Being Pluggable, if you don't want any particular Protocol or its endpoint, you simply don't configure it.

How are calls to the authentication/authorisation services minimised?Auth* doesn’t cache, but it does propagate JWT that can be locally interrogated for claims.

CADI optimizes the calls based on Protocol.

Examples of optimization:

2-way x509 Certificate Authentication

CADI developed a way to get Identity from the Certificate with no external calls whatsoever, using the certificate already prepared by TLS. There are NO external calls, and process time is in the hundredths of millisecond range.

OAuth2

CADI creates memory cache backed by encrypted persisted reference to the Introspection date, which is a one time call until expires. This is utilized over the life of Token. Further, CADI manages the Refresh of the Token, if required, without App needing to interact.

Regular AAF Call

With Beijing, regular AAF calls utilize the OAuth2 Persisted Memory solution, rather than previous Caching method in Amsterdam.

Basic Auth

Since Basic Auth requires external endpoint, these are cached.

Proposed JWT Protocol

If a new JWT Protocol is proposed and implemented by ONAP, the JWT Token would be on each transaction, and would not require caching

How is blacklisting handled?The first microservice that encounters a transaction authenticates the supplied token with Auth* (and thus the authentication provider). If the principal or the token are invalid, the request is rejected otherwise a JWT is returned. Subsequent requests in the transaction use the JWT (that has a configurable TTL).

Blacklisting involves one or both of Authentication and Authorization. For success, any given client must be Authenticated and Authorized, and since this varies by Protocol/Implementor, how this is done is based on CADI's pluggable TAF and LUR adapters.

2-way x509 Certificate

Certificate Authority choice - probably RCL

OAuth2

OAuth2 requires refreshing of Tokens after expiration. If user is blacklisted before Refreshing, standard errors apply

Regular AAF Call

Removal of User from Roles he is part of

Basic Auth

When Cache Expires, it is rechecked. If Password no longer valid, Client cannot proceed.


How are non JVM languages supported?Requires an equivalent implementation of Auth* filter and REST client in target language for full support.

The CADI methodology and interfaces can be applied to other languages. Currently, there is already a JavaScript version built, which we are looking to bring into ONAP. There are requests for other direct Language builds, which can be built according to specs by interested parties.

However, if other languages are not initially supported, then the recommended additional Microservice, recommended above, can be utilized in a manner similar to "Auth*" proposal.

Comments on the other solution/"final words"

The Auth* proposal requires first defining, then creating a new PROTOCOL (see definition at top of page), based on JWT. All ONAP microservices would then be required to adopt this new Protocol with a CADI like (but not CADI) Library for their own language.

CADI does not oppose a new PROTOCOL based on JWT, but asserts that as a pluggable library, this PROTOCOL can already be accommodated by normal CADI methodology.

Imposition of only one specific PROTOCOL between Microservices is a Policy decision, by Security Committee, easily implemented by CADI as it exists today.

In one such policy, if the ONAP decision makers decide to accept only x509 Certificates, then ONAP Microservices can be configured with only CADI x509 Certificates. Or, if they decide that Microservices should have both x509 and BasicAuth, CADI can be configured for both, and applied everywhere.

In such a way, the community asked for OAuth2 to be built for Beijing. AAF/CADI provided this. If the Committee turns its decision, and decides it doesn't like OAuth Tokens, but prefers to go with a new JWT token methodology, then this can be built, and configured as normal. It does not change CADI or how it works. There is no problem is the Committee changes its mind back, OR if individual companies decide they want to do OAuth while others choose JWT.

This is also true of Company specific Protocols, like specialized SSO Strategies.

With CADI, the idea of pluggable Security Protocols, both Authentication and Authorization already exists. Both the Protocols and the Providers are already pluggable.

The Auth* idea of creating a separate MicroService to accommodate non-Java languages is laudable, but a solution actually already exists and works with AAF already. It may be better to obtain this working model rather than build new.


Open Issues

      1. What considerations are needed when propagating a (JWT) token between microservices? i.e. how do we stop token's being hijacked/re-purposed?
        1. <Andy> - my initial view was that:
        2. Microservices are code-scanned/reviewed to ensure that their code is trustworthy.
        3. Interactions between microservices are via TLS/2-way cert that is establishing non-repudiation between parties - we can trust that a client (application) is who they say they are, and the comms between them is secured.
        4. If (I) and (ii) are both true, then where does the risk of hi-jack originate?

There is a practical/technical question regarding how the token is made available without being invasive to the microservices developer.

The current proposal is to transparently inject the JWT/credentials (referred to as tokens in this subject) into the relevant headers for propagation:

        • Mediate all REST requests via org.onap.aai.restclient.client (may need package name generalisation)
        • The Filter injects the tokens thread local into the rest client, setting the relevant headers and request context with the token information.
        • The microservice application code invokes the rest client to call out to onward microservices.

Positives

        • Aside from the requirement to use the REST Client for communication, the approach is transparent to the application developer.
        • Single piece of code to secure.
        • Common place to log outgoing requests with transactionId and target for traceability.

Issues

        1. Needs an implementation per language/technology - e.g. would need a Python equivalent
        2. Creates a coupling with the Auth * filter

All guidance on the subject appreciated.

2. Revocation of tokens:

        1. Requests to the Auth* service are checked for token revocation.
        2. JWTs should be short lived and can be configured with short TTLs.

Progress on converged pluggable security 25th April 2018

Requirements:


1)      Microservice flows:

      1. user originated
      2. system originated

2)      Some microservices need user-level authorisation to ensure the is no privilege elevation (e.g. accessing remote sources of truth)

3)      In some scenarios (and for some authorisation providers) having fewer users (i.e. one per system/component) to authorise reduces the security administration burden.

Conclusion is to prioritise hardening of service->service authentication/authorisation, but a path to support user level authorisation has to be agreed.

4)      We need the ability to plug-in alternative authentication and authorisation providers without impacting built microservices (otherwise there is a per release, per deployment, per microservice build/test cost).  The Auth* pattern of splitting the functionality into a small footprint on the application microservice with more of the capability (such as the integration to different providers) isolated in a separate microservice is (I think) generally accepted, but the specifics of the split are being discussed, particularly wrt how much re-use of CADI features we can exploit. Parts of the split discussed to date are:


    1. Application microservice filter

                     i.      Extract of one or more credentials/tokens

                     ii.      Call out to microservice to authenticate/authorise tokens/retrieve authorisations

                     iii.      Cache results to minimise future callouts

                     iv.      Compare authorisations with the configured application microservice authorisation requirements2

                     v.      Admits/rejects the request

                     vi.      Securely inject the necessary tokens for onward propagation in subsequent communications

    1. Security microservice:

     i.      Receives secure requests for authorisations including one or more credentials/tokens1

     ii.      Validates the authenticity of the tokens via integration with the necessary authentication provider(s)

     iii.      Retrieves the authorisations for the relevant identity via integration with the necessary authorisation provider.

     iv.      Transforms the authorisations (if required) into a common, agreed representation (candidates under discussion are JWT and OAUTH2 token):

      1. Tamper resistant
      2. Time-limited (TTL)
      3. Recognised standard

     v.      Returns the authorisations if successful, otherwise an indicator that the request could not be satisfactorily resolved.

5)      We need a mechanism to trace the flow of a request through the microservices for analysis and debug purposes:

      1. One approach is to use an additive component identity chain (this is the CADI approach)
      2. Another is to use the ONAP global transaction ID and the common logging framework to trace the flow.
      3. Other methods are also available.

 Notes

1 the request format should be common irrespective of the tokens to be passed.

Authorisation comparison should not make assumptions about the representation of the authorisation beyond it being a set of string-matches.