When NATS is enabled on a control plane, Eclipse ioFog uses NATS JWT authentication so that microservices and system components connect to NATS with cryptographically signed identities. The Controller (and optionally iofogctl) generates or distributes these credentials so you can deploy microservices with NATS access without manually creating or rotating JWTs.
NATS uses a three-level JWT model:
The Controller stores operator and account JWTs and generates user credentials when a microservice is deployed with natsAccess: true and a valid natsRule reference.
iofogctl nats operator describe
name: pot-operator
publickey: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLV
jwt: eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJhdWQiOiJOQVRTIiwibmFtZSI6InBvdC1vcGVyYXRvciIsInN1YiI6Ik9DUlFTUkZCWkVCSFFRTVE2TjM3S0NCU1pDUUkyV0VHN0RRWEhSWFVVVzNGU0JCTjVUUDJaRExWIiwibmF0cyI6eyJ0eXBlIjoib3BlcmF0b3IiLCJ2ZXJzaW9uIjoyfSwiaXNzIjoiT0NSUVNSRkJaRUJIUVFNUTZOMzdLQ0JTWkNRSTJXRUc3RFFYSFJYVVVXM0ZTQkJONVRQMlpETFYiLCJpYXQiOjE3NzI3MDYxOTUsImp0aSI6IlRWbjFVNGVadG00ZzAvcEU0Tlo5NFZleGlURmRwMEg2ZkhROFpqKysxUUVQWVJqaFppSUE1L1JWN25icDMyYjhSSDFFdXVMV1l4eEt2bnc4dkdpL1pBPT0ifQ.BxbgFYGCE0pGQsRu08VQI8DsrC0RIKkZm7-DfcmYRsano4PShIfYppBmtSYZxwP_GZYgZIcFUdnmMqsUWQ-2DAiofogctl nats operator describe --jwt
aud: NATS
iat: 1.772706195e+09
iss: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLV
jti: TVn1U4eZtm4g0/pE4NZ94VexiTFdp0H6fHQ8Zj++1QEPYRjhZiIA5/RV7nbp32b8RH1EuuLWYxxKvnw8vGi/ZA==
name: pot-operator
nats:
type: operator
version: 2
sub: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLVspec.natsConfig.natsAccess: true and spec.natsConfig.natsRule to the Account Rule name.natsConfig.natsAccess: true and natsConfig.natsRule to a User Rule name.Using NatsAccountRule and NatsUserRule in this way makes it easy to deploy microservices with NATS access without manual JWT handling. You do not need to run nsc or manage JWT files yourself; the Controller keeps operator and account state and issues user credentials per microservice.
echo "---
apiVersion: iofog.org/v3
kind: NatsAccountRule
metadata:
name: test-export
spec:
maxConnections: -1
maxLeafNodeConnections: -1
maxData: -1
maxExports: -1
maxImports: -1
maxMsgPayload: -1
maxSubscriptions: -1
exportsAllowWildcards: true
memStorage: -1
diskStorage: -1
streams: -1
consumer: -1
maxAckPending: -1
memMaxStreamBytes: -1
diskMaxStreamBytes: -1
exports:
- name: orders-stream
subject: foo.>
type: stream
description: Orders event stream
" > /tmp/account-export.yaml
iofogctl deploy -f /tmp/account-export.yamlecho "---
apiVersion: iofog.org/v3
kind: NatsAccountRule
metadata:
name: test-import
spec:
maxConnections: -1
maxLeafNodeConnections: -1
maxData: -1
maxExports: -1
maxImports: -1
maxMsgPayload: -1
maxSubscriptions: -1
exportsAllowWildcards: true
memStorage: -1
diskStorage: -1
streams: -1
consumer: -1
maxAckPending: -1
memMaxStreamBytes: -1
diskMaxStreamBytes: -1
imports:
- name: import-stream
subject: export.>
type: stream
account: ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXX
local_subject: import.>
" > /tmp/account-import.yaml
iofogctl deploy -f /tmp/account-import.yamlecho "---
apiVersion: iofog.org/v3
kind: Application
metadata:
name: nats-test
spec:
natsConfig:
natsAccess: true
natsRule: test-export
microservices:
- name: box-1
natsConfig:
natsAccess: true
natsRule: default-user
agent:
name: edge-1
images:
registry: 1
x86: natsio/nats-box:latest
arm: natsio/nats-box:latest
container:
hostNetworkMode: false
isPrivileged: false
extraHosts: []
commands:
- /bin/sh
- -c
- trap true INT TERM; sleep infinity & wait
---
apiVersion: iofog.org/v3
kind: Application
metadata:
name: nats-test2
spec:
natsConfig:
natsAccess: true
natsRule: test-import
microservices:
- name: box-1
natsConfig:
natsAccess: true
natsRule: default-user
agent:
name: edge-2
images:
registry: 1
x86: natsio/nats-box:latest
arm: natsio/nats-box:latest
container:
hostNetworkMode: false
isPrivileged: false
extraHosts: []
commands:
- /bin/sh
- -c
- trap true INT TERM; sleep infinity & wait
---
apiVersion: iofog.org/v3
kind: Application
metadata:
name: nats-test3
spec:
natsConfig:
natsAccess: true
natsRule: default-account
microservices: []
---
apiVersion: iofog.org/v3
kind: Microservice
metadata:
name: box-1
spec:
agent:
name: edge-2
images:
registry: 1
x86: natsio/nats-box:latest
arm: natsio/nats-box:latest
container:
extraHosts: []
ports: []
cpuSetCpus: ''
commands:
- /bin/sh
- '-c'
- trap true INT TERM; sleep infinity & wait
healthCheck: {}
natsConfig:
natsAccess: true
natsRule: default-user
config: {}
application: nats-test3
" > /tmp/apps.yaml
iofogctl deploy -f /tmp/apps.yaml
iofogctl get nats-accounts
NAMESPACE
pot-local
NAME APP ID SYSTEM PUBLIC KEY
SYS 0 true ACXO6737ASXEGXI57MJPUJOIPV7OMBIDA77ACHYM57BQ4SFPIMSWQ5E3
SYS-leaf-edge-1 0 false ACJH4C3VC6SSHO42LZ6TR54AYKTOT3YCRPHYKU7IV7ZLO3TRXG4IPCOT
nats-test2 5 false ABGYBCTHOIT6OBJ2AVGPKLW4JEL44DCJYMTOUZ7SY4TRSKWXX6UKZX7H
nats-test3 4 false ABHYIEGCJ4XT3FL34BBO4IQPYO56TB3SNNBFRHWXPR7M5HSEPUCYWBLS
nats-test 3 false ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXX iofogctl describe nats-account nats-test
id: 5
name: nats-test
publickey: ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXX
jwt: eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJhdWQiOiJOQVRTIiwibmFtZSI6Im5hdHMtdGVzdCIsInN1YiI6IkFDWkQyVUlDSExHVkM2N0w0STZOQ1czU0NaMlk0V0lHU1FGWE9VNVFWSTJHVERDU0VNR1Y1R1hYIiwibmF0cyI6eyJsaW1pdHMiOnsiY29ubiI6LTEsImxlYWYiOi0xLCJkYXRhIjotMSwiZXhwb3J0cyI6LTEsImltcG9ydHMiOi0xLCJwYXlsb2FkIjotMSwic3VicyI6LTEsIndpbGRjYXJkcyI6dHJ1ZSwiZGlzYWxsb3dfYmVhcmVyIjpudWxsLCJtZW1fc3RvcmFnZSI6LTEsImRpc2tfc3RvcmFnZSI6LTEsInN0cmVhbXMiOi0xLCJjb25zdW1lciI6LTEsIm1heF9hY2tfcGVuZGluZyI6LTEsIm1lbV9tYXhfc3RyZWFtX2J5dGVzIjotMSwiZGlza19tYXhfc3RyZWFtX2J5dGVzIjotMSwibWF4X2J5dGVzX3JlcXVpcmVkIjpudWxsfSwiZGVmYXVsdF9wZXJtaXNzaW9ucyI6eyJwdWIiOnt9LCJzdWIiOnt9fSwiZXhwb3J0cyI6W3siZGVzY3JpcHRpb24iOiJFeHBvcnQgZXZlbnQgc3RyZWFtIiwibmFtZSI6ImV4cG9ydC1zdHJlYW0iLCJzdWJqZWN0IjoiZXhwb3J0Lj4iLCJ0eXBlIjoic3RyZWFtIn1dLCJyZXZvY2F0aW9ucyI6e30sInR5cGUiOiJhY2NvdW50IiwidmVyc2lvbiI6Mn0sImlzcyI6Ik9DUlFTUkZCWkVCSFFRTVE2TjM3S0NCU1pDUUkyV0VHN0RRWEhSWFVVVzNGU0JCTjVUUDJaRExWIiwiaWF0IjoxNzcyNzA2NzIxLCJqdGkiOiIvQkF6UE0ySTdsZWZBQUhEUFJkdWNnSGt2dHUxVDJhb0lGdjc0Uzh0Ykxrc3VuZWIzSFJ0bGJGaDVEZ1IxckgxMklwRjRxMzE4NmN6eEJLTkszdVJNdz09In0.oLLdkrTmkDw8Xg_RedFegd8C9qctVB_pQg8XtI7ZdSqh_c6S3UzlZNLAF6HUOLd52_sQvSKPK2UmoujVQ9z9Aw
issystem: false
isleafsystem: false
applicationid: 3iofogctl describe nats-account nats-test3 --jwt
aud: NATS
iat: 1.772706624e+09
iss: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLV
jti: 7N89IbSaB4D4dzCvirLN3xyB1VG7dZy6FJcTeuURWqY+P9g+YnOV2hamdD4HwZ+k44qr5vU51CQxthNZf1LfVQ==
name: nats-test3
nats:
default_permissions:
pub: {}
sub: {}
description: Default application account rule
limits:
conn: -1
consumer: -1
data: -1
disallow_bearer: null
disk_max_stream_bytes: -1
disk_storage: -1
exports: -1
imports: -1
leaf: -1
max_ack_pending: -1
max_bytes_required: null
mem_max_stream_bytes: -1
mem_storage: -1
payload: -1
streams: -1
subs: -1
wildcards: true
revocations: {}
type: account
version: 2
sub: ABHYIEGCJ4XT3FL34BBO4IQPYO56TB3SNNBFRHWXPR7M5HSEPUCYWBLSiofogctl describe nats-account nats-test2 --jwt
aud: NATS
iat: 1.772706721e+09
iss: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLV
jti: KVtjkd7sQ7n7rvFZ02pNd3wZQx80hO5OlsEB9+yncaG8f+QZH2uhx7SdFfeWSo1xecR2GhMQ/k+p5bBF6qMmsw==
name: nats-test2
nats:
default_permissions:
pub: {}
sub: {}
imports:
- account: ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXX
local_subject: import.>
name: import-stream
subject: export.>
type: stream
limits:
conn: -1
consumer: -1
data: -1
disallow_bearer: null
disk_max_stream_bytes: -1
disk_storage: -1
exports: -1
imports: -1
leaf: -1
max_ack_pending: -1
max_bytes_required: null
mem_max_stream_bytes: -1
mem_storage: -1
payload: -1
streams: -1
subs: -1
wildcards: true
revocations: {}
type: account
version: 2
sub: ABGYBCTHOIT6OBJ2AVGPKLW4JEL44DCJYMTOUZ7SY4TRSKWXX6UKZX7Hiofogctl describe nats-account nats-test --jwt
aud: NATS
iat: 1.772706721e+09
iss: OCRQSRFBZEBHQQMQ6N37KCBSZCQI2WEG7DQXHRXUUW3FSBBN5TP2ZDLV
jti: /BAzPM2I7lefAAHDPRducgHkvtu1T2aoIFv74S8tbLksuneb3HRtlbFh5DgR1rH12IpF4q3186czxBKNK3uRMw==
name: nats-test
nats:
default_permissions:
pub: {}
sub: {}
exports:
- description: Export event stream
name: export-stream
subject: export.>
type: stream
limits:
conn: -1
consumer: -1
data: -1
disallow_bearer: null
disk_max_stream_bytes: -1
disk_storage: -1
exports: -1
imports: -1
leaf: -1
max_ack_pending: -1
max_bytes_required: null
mem_max_stream_bytes: -1
mem_storage: -1
payload: -1
streams: -1
subs: -1
wildcards: true
revocations: {}
type: account
version: 2
sub: ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXXiofogctl describe microservice nats-test/box-1
apiVersion: iofog.org/v3
kind: Microservice
metadata:
name: nats-test/box-1
namespace: pot-local
spec:
uuid: 2bc86457-b7a3-4886-b1bf-4a5725cf0bb0
name: box-1
agent:
name: edge-1
config: {}
images:
catalogId: 0
x86: natsio/nats-box:latest
arm: natsio/nats-box:latest
registry: remote
container:
commands:
- /bin/sh
- -c
- trap true INT TERM; sleep infinity & wait
volumes:
- hostDestination: nats-creds-nats-test-box-1
containerDestination: /etc/nats/creds
accessMode: ro
type: volumeMount
env:
- key: NATS_CREDS_PATH
value: /etc/nats/creds/nats-test/box-1.creds
extraHosts: []
ports: []
hostNetworkMode: false
isPrivileged: false
annotations: {}
memoryLimit: 0
natsConfig:
natsAccess: true
natsRule: default-user
schedule: 50
config: {}
application: nats-testiofogctl nats user creds nats-test box-1
-----BEGIN NATS USER JWT-----
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJhdWQiOiJOQVRTIiwibmFtZSI6ImJveC0xIiwic3ViIjoiVUE2U0dORlNKMjRGSTY0RU9QM0hKTkdIUjJCVVBWM0E2TVQ1VllTNktIUkJVS0FSVjI2SFRLUlQiLCJuYXRzIjp7ImRhdGEiOi0xLCJwYXlsb2FkIjotMSwic3VicyI6LTEsImFsbG93ZWRfY29ubmVjdGlvbl90eXBlcyI6WyJTVEFOREFSRCIsIldFQlNPQ0tFVCJdLCJwdWIiOnt9LCJzdWIiOnt9LCJ0eXBlIjoidXNlciIsInZlcnNpb24iOjJ9LCJpc3MiOiJBQ1pEMlVJQ0hMR1ZDNjdMNEk2TkNXM1NDWjJZNFdJR1NRRlhPVTVRVkkyR1REQ1NFTUdWNUdYWCIsImlhdCI6MTc3MjcwNjczOCwianRpIjoiTFY1UTBSV2RDaElrQ0svV0VBT1ZZK0w0dlNOdHVxSGl1c1E5SUJ4UEF4aXRUVVpUeGdobHVQSzhXWnJES0JsK0xQdEVPKzgxTGxqcnJqOW05RnRib3c9PSJ9.WpKm5Aef9UgeFgz06htWTRvyOBhBb73URT0cGrUCaz3fOcXHg2xZs__2SgdIAc0LJ_clB5yTv2RENr5H9ccWCQ
------END NATS USER JWT------
************************* IMPORTANT *************************
NKEY Seed printed below can be used sign and prove identity.
NKEYs are sensitive and should be treated as secrets.
-----BEGIN USER NKEY SEED-----
SUAATMAA7T7DRPKBR4GSBRNSHPP56NISI4BTAKD2SEPUQJF5RCKLSOIXDA
------END USER NKEY SEED------iofogctl describe nats-user nats-test box-1 --jwt
aud: NATS
iat: 1.772706738e+09
iss: ACZD2UICHLGVC67L4I6NCW3SCZ2Y4WIGSQFXOU5QVI2GTDCSEMGV5GXX
jti: LV5Q0RWdChIkCK/WEAOVY+L4vSNtuqHiusQ9IBxPAxitTUZTxghluPK8WZrDKBl+LPtEO+81Lljrrj9m9Ftbow==
name: box-1
nats:
allowed_connection_types:
- STANDARD
- WEBSOCKET
data: -1
payload: -1
pub: {}
sub: {}
subs: -1
type: user
version: 2
sub: UA6SGNFSJ24FI64EOP3HJNGHR2BUPV3A6MT5VYS6KHRBUKARV26HTKRTAs you can see from the example above, once a microservice is deployed with NATS access enabled, the Controller automatically generates creds for it. The microservice's NATS user JWT is signed by its application's NATS account private key, and the creds file is mounted into the microservice container.
ioFog handles infrastructure and security for you so you can focus on the innovation and intelligence you bring to the edge.
NATS client and leaf connections are secured with TLS. ioFog provides secure NATS clusters by default, so you do not need to configure TLS between NATS instances yourself.