- Configure Private Cloud
- Security
- Authentication
Multiple private keys support for JWT token authentication
StreamNative Pulsar extends the JWT token authentication to support multiple private keys AuthenticationProvider AuthenticationProviderMultipleSignKeyToken, and implement automatic reloading of configuration files into the cache without restarting the broker.
The multiple multiple private keys will be maintained in a JSON file and issue new JWT token needs to include a kid field in the header to match the private key for signature verification.
Before you begin
Create multiple secret keys
Create the default secret key
pulsarctl token create-secret-key -a HS256 --output-file default-secret.key cat default-secret.key | base64 GRgrvdFdNijm0xPompgfJGwE77ifM+U31exWERDEiB0=Create the second secret key
pulsarctl token create-secret-key -a HS256 --output-file kid-secret.key cat kid-secret.key| base64 IeNNHJmTM6icg71/D6aFQ/buslNV+FZWT/TiJRDZpYo=Create a JSON to include the multiple secret keys, key is kid, value is the corresponding secret key encoded by base64
{ "KID1": "Cysl6yGZb6xFygc0hB5Pt+ha1ZXpt7jmFU3CR1AS2os=", "DEFAULT_KID": "nVXSRdlQm4wbgxiS4/MHjxgLqyL9iF2oEXdq9E6iIeo=" }Create the K8s Secret for the multi secret key JSON
kubectl create secret generic multi-secret-key --from-file=secret-keys.json
Create broker and proxy tokens
Use the default secret key to generate broker admin token
pulsarctl token create -a HS256 --secret-key-file default-secret.key --subject broker-admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJicm9rZXItYWRtaW4ifQ.bi1Bx9Wg-4HOA-xvAPJQQbf-J70u359TL_8_GqSdC6ECreate the K8s Secret for the tokens
kubectl create secret generic broker-admin --from-literal=broker-admin=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJicm9rZXItYWRtaW4ifQ.bi1Bx9Wg-4HOA-xvAPJQQbf-J70u359TL_8_GqSdC6Ekubectl create secret generic proxy-admin --from-literal=proxy-admin=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwcm94eS1hZG1pbiJ9.ELqIKJlb0ISShCTBmhV0MenPbBLG0xkRk1mrfbnWT8s
Configure PulsarBroker and PulsarProxy
PulsarBroker
spec:
image: streamnative/private-cloud:3.3.0.7
replicas: 1
zkServers: private-cloud-zk:2181
config:
clusterName: private-cloud
custom:
managedLedgerDefaultAckQuorum: '1'
managedLedgerDefaultEnsembleSize: '1'
managedLedgerDefaultWriteQuorum: '1'
authenticationEnabled: 'true'
authenticateOriginalAuthData: 'true'
authenticationProviders: 'io.streamnative.pulsar.broker.authentication.AuthenticationProviderMultipleSignKeyToken'
brokerClientAuthenticationPlugin: 'org.apache.pulsar.client.impl.auth.AuthenticationToken'
superUserRoles: 'admin,proxy-admin,broker-admin,admin-approle'
proxyRoles: 'proxy-admin'
authorizationEnabled: 'true'
authorizationProvider: 'org.apache.pulsar.broker.authorization.PulsarAuthorizationProvider'
pod:
resources:
requests:
cpu: 200m
memory: 512Mi
securityContext:
runAsNonRoot: true
secretRefs:
- mountPath: /mnt/secrets
secretName: multi-secret-key
- mountPath: /mnt/tokens
secretName: broker-admin
vars:
- name: brokerClientAuthenticationParameters
value: 'file:///mnt/tokens/broker-admin'
- name: tokenSecretKey
value: 'file:///mnt/secrets/secret-keys.json'
- [1]
spec.config.cusom:authenticationProvidersshould use theio.streamnative.pulsar.broker.authentication.AuthenticationProviderMultipleSignKeyToken
PulsarProxy
spec:
image: streamnative/private-cloud:3.3.0.7
replicas: 1
config:
custom:
authenticationEnabled: 'true'
authenticateOriginalAuthData: 'true'
forwardAuthorizationCredentials: 'true'
authenticationProviders: 'io.streamnative.pulsar.broker.authentication.AuthenticationProviderMultipleSignKeyToken'
brokerClientAuthenticationPlugin: 'org.apache.pulsar.client.impl.auth.AuthenticationToken'
superUserRoles: 'proxy-admin'
brokerAddress: private-cloud-broker
pod:
annotations:
prometheus.io/port: '8080'
prometheus.io/scrape: 'true'
resources:
requests:
cpu: 200m
memory: 512Mi
securityContext:
runAsNonRoot: true
secretRefs:
- mountPath: /mnt/secrets
secretName: multi-secret-key
- mountPath: /mnt/tokens
secretName: proxy-admin
vars:
- name: brokerClientAuthenticationParameters
value: 'file:///mnt/tokens/proxy-admin'
- name: tokenSecretKey
value: 'file:///mnt/secrets/secret-keys.json'
Create client tokens
Create a token by the default secret key
pulsarctl token create -a HS256 --secret-key-file default-secret.key --subject test-client eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LWNsaWVudCJ9.BC8hq47exYyCirBCP5AlIDzFQtnxhCPrv94BHeQ08toCreate a token by the kid secret key
Note
The
kid=KID1in the headers should be consistent with thesecret-keys.jsondefination.pulsarctl token create -a HS256 --secret-key-file kid-secret.key --subject test-client --headers kid=KID1 eyJhbGciOiJIUzI1NiIsImtpZCI6ImtpZDEiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiJ0ZXN0LWNsaWVudCJ9.y5qXOgb_ibTQD09nVaS6sr4bGI8caByY_FnJXuhq4_4Grant permission to the role
pulsarctl --token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJicm9rZXItYWRtaW4ifQ.bi1Bx9Wg-4HOA-xvAPJQQbf-J70u359TL_8_GqSdC6E" \ namespaces grant-permission --role test-client --actions produce --actions consume public/defaultUse the token generated by the default secret key to produce data
bin/pulsar-client --auth-params token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LWNsaWVudCJ9.BC8hq47exYyCirBCP5AlIDzFQtnxhCPrv94BHeQ08to --auth-plugin org.apache.pulsar.client.impl.auth.AuthenticationToken produce default-secret-token -m "test-with-multisecretKey" -n 15 2024-05-29T21:46:20,293+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] Connected through proxy to target broker at private-cloud-broker-0.private-cloud-broker-headless.default.svc.cluster.local:6650 2024-05-29T21:46:20,854+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [null] Creating producer on cnx [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] 2024-05-29T21:46:21,263+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [private-cloud-0-3] Created producer on cnx [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] 2024-05-29T21:46:25,671+0800 [main] INFO org.apache.pulsar.client.impl.ProducerStatsRecorderImpl - [default-secret-token] [private-cloud-0-3] --- Publish throughput: 2.66 msg/s --- 0.00 Mbit/s --- Latency: med: 267.000 ms - 95pct: 441.000 ms - 99pct: 441.000 ms - 99.9pct: 441.000 ms - max: 441.000 ms --- BatchSize: med: 1.000 - 95pct: 1.000 - 99pct: 1.000 - 99.9pct: 1.000 - max: 1.000 --- MsgSize: med: 24.000 bytes - 95pct: 24.000 bytes - 99pct: 24.000 bytes - 99.9pct: 24.000 bytes - max: 24.000 bytes --- Ack received rate: 2.66 ack/s --- Failed messages: 0 --- Pending messages: 0 2024-05-29T21:46:25,928+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [private-cloud-0-3] Closed Producer 2024-05-29T21:46:25,930+0800 [main] INFO org.apache.pulsar.client.impl.PulsarClientImpl - Client closing. URL: pulsar://172.171.186.162:6650/ 2024-05-29T21:46:25,935+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xc1116ccc, L:/198.18.0.1:62077 ! R:/172.171.186.162:6650] Disconnected 2024-05-29T21:46:25,935+0800 [pulsar-client-io-1-3] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xe6914d5b, L:/198.18.0.1:62075 ! R:/172.171.186.162:6650] Disconnected 2024-05-29T21:46:27,989+0800 [main] INFO org.apache.pulsar.client.cli.PulsarClientTool - 15 messages successfully producedUse the token generated by the KID1 secret key to produce data
bin/pulsar-client --auth-params token:eyJhbGciOiJIUzI1NiIsImtpZCI6IktJRDEiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiJ0ZXN0LWNsaWVudCJ9.YbsyE54ulm9ioMx2xZBqLgCNrYmjk2o6wxR5WOwaPSE --auth-plugin org.apache.pulsar.client.impl.auth.AuthenticationToken produce test -m "test-with-multisecretKey" -n 15 2024-05-29T21:46:20,293+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] Connected through proxy to target broker at private-cloud-broker-0.private-cloud-broker-headless.default.svc.cluster.local:6650 2024-05-29T21:46:20,854+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [null] Creating producer on cnx [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] 2024-05-29T21:46:21,263+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [private-cloud-0-3] Created producer on cnx [id: 0xc1116ccc, L:/198.18.0.1:62077 - R:/172.171.186.162:6650] 2024-05-29T21:46:25,671+0800 [main] INFO org.apache.pulsar.client.impl.ProducerStatsRecorderImpl - [default-secret-token] [private-cloud-0-3] --- Publish throughput: 2.66 msg/s --- 0.00 Mbit/s --- Latency: med: 267.000 ms - 95pct: 441.000 ms - 99pct: 441.000 ms - 99.9pct: 441.000 ms - max: 441.000 ms --- BatchSize: med: 1.000 - 95pct: 1.000 - 99pct: 1.000 - 99.9pct: 1.000 - max: 1.000 --- MsgSize: med: 24.000 bytes - 95pct: 24.000 bytes - 99pct: 24.000 bytes - 99.9pct: 24.000 bytes - max: 24.000 bytes --- Ack received rate: 2.66 ack/s --- Failed messages: 0 --- Pending messages: 0 2024-05-29T21:46:25,928+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ProducerImpl - [default-secret-token] [private-cloud-0-3] Closed Producer 2024-05-29T21:46:25,930+0800 [main] INFO org.apache.pulsar.client.impl.PulsarClientImpl - Client closing. URL: pulsar://172.171.186.162:6650/ 2024-05-29T21:46:25,935+0800 [pulsar-client-io-1-5] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xc1116ccc, L:/198.18.0.1:62077 ! R:/172.171.186.162:6650] Disconnected 2024-05-29T21:46:25,935+0800 [pulsar-client-io-1-3] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xe6914d5b, L:/198.18.0.1:62075 ! R:/172.171.186.162:6650] Disconnected 2024-05-29T21:46:27,989+0800 [main] INFO org.apache.pulsar.client.cli.PulsarClientTool - 15 messages successfully produced