Security in the Arrowhead Framework
Security in the Arrowhead Framework is established using a combination of TLS and JWT-based token authorization.
Security Modes
An ArrowheadClient
can be run in two different security modes, Security.INSECURE
mode and Security.SECURE
mode.
An ArrowheadClient
must be run in the same security mode as the local cloud it is in, as the SECURE
mode enables TLS.
INSECURE
mode should only be run during testing and prototyping, and SECURE
mode must be used in actual production local clouds.
Access Policies
ArrowheadClient
objects support the CERTIFICATE
, UNRESTRICTED
,
and TOKEN
access policies for services.
Here we only explain what the policies are used for and how to enable and use them.
For an explanation on how they work, go read about the Authorization System.
Unrestricted Access Policy
To make services use the UNRESTRICTED
access policy, you simply don’t provide a cert- or keyfile
to the ArrowheadClient providing those services.
By not providing both a cert- and keyfile, the client will run in INSECURE
mode.
INSECURE
mode ensures that all provided services will use the UNRESTRICTED
access policy
and that the client can only consume services with UNRESTRICTED
access.
The UNRESTRICTED
access policy should only be used during testing and prototyping and never in production.
Even if a local cloud is using UNRESTRICTED
access, you need to set both orchestration and authorization
rules. The Orchestrator will ignore an orchestration rule if the equivalent authorization rule is not set.
Example:
from arrowhead_client.client import SyncClient
example_client = SyncClient.create(
system_name='Insecure',
address='127.0.0.1',
port=1338
)
print(example_client.secure)
# False
Certificate Access Policy
The CERTIFICATE
access policy is one of two policies that can be used when the client is running in SECURE
mode,
which is enabled by providing both the certfile and keyfile.
Then, given a client that runs in SECURE
mode, we can specify that a provided service should use the CERTIFICATE
access policy when creating it using the arrowhead_client.client.ArrowheadClient.provided_service()
method or
arrowhead_client.client.provided_service()
decorator.
Running a client in SECURE
mode will enable the consumption of services using both the CERTIFICATE
and TOKEN
access policies.
Example:
from arrowhead_client.client import SyncClient
example_client = SyncClient(
system_name='Secure',
address='127.0.0.1',
port=1337,
keyfile='path/to/secure.key',
certfile='path/to/secure.crt',
)
@example_client.provided_service.create(
service_definition='secure_echo',
service_uri='secure/echo',
protocol='HTTP',
method='GET',
payload_format='JSON',
access_policy='CERTIFICATE',
)
def secure_echo(request):
return 'ECHO'
Token Access Policy
The TOKEN
access policy works out-of-the-box with the arrowhead_client.client.SyncClient
, but
not with the arrowhead_client.client.AsyncClient
.
With the AsyncClient
, you will need to use a reverse proxy that provides the consumer certificate as an HTTP header,
but that functionality is not yet implemented.
The reason for this is that the ASGI standard which the Provider is built upon does not forward the certificate to the application.
Once that is implemented in the standard and Uvicorn updates to support it, the TOKEN
access policy will work
with the AsyncClient
without hassle.
While the CERTIFICATE
does enable the use of TLS, any system with a valid certificate could consume the service.
The TOKEN
access policy allows the provider to authenticate the consumer and make sure the consumer was given
permission to consume the service by the Authorization system.
You use the TOKEN
access policies the same way you use the CERTIFICATE
access policy, except that you specify
the TOKEN
access policy:
from arrowhead_client.client import SyncClient
example_client = SyncClient.create(
system_name='Secure',
address='127.0.0.1',
port=1337,
keyfile='path/to/secure.key',
certfile='path/to/secure.crt',
)
@example_client.provided_service(
service_definition='token_data',
service_uri='secure/token',
protocol='HTTP',
method='GET',
payload_format='JSON',
access_policy='TOKEN',
)
def secure_echo(request):
return {"access policy": "TOKEN"}
Summary
What access policies can be used with what security mode is summarized in this table
Client security mode |
TLS enabled |
Allowed access policy |
||
|
|
|
||
|
No |
Yes |
No |
No |
|
Yes |
No |
Yes |
Yes |