mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
fix folder structure from gitbook import
This commit is contained in:
6
developing-with-nats/security/README.md
Normal file
6
developing-with-nats/security/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Securing Connections
|
||||
|
||||
NATS provides several forms of security, authentication, authorization and isolation. You can turn on authentication which limits access to the NATS system. Accounts allow for isolation of a subject space and groups of applications. Authorization can be used to limit individual users access to specific subjects for publish and subscribe operations. TLS can be used to encrypt all traffic between clients and the NATS system. Finally, TLS can be used to verify client identities using client certificates. By combining all of these methods you can protect access to the system and to all message flows.
|
||||
|
||||
The client doesn't have control over access controls, but clients do provide the configurations required to authenticate with the system, bind to an account, and to require TLS.
|
||||
|
||||
92
developing-with-nats/security/creds.md
Normal file
92
developing-with-nats/security/creds.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Authenticating with a Credentials File
|
||||
|
||||
The 2.0 version of NATS server introduced the idea of JWT-based authentication. Clients interact with this new scheme using a user JWT and the private key from an NKey pair. To help make connecting with a JWT easier, the client libraries support the concept of a credentials file. This file contains both the private key and the JWT and can be generated with the `nsc` tool. The contents will look like the following and should be protected because it contains a private key. This creds file is unused and only for example purposes.
|
||||
|
||||
```text
|
||||
-----BEGIN NATS USER JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJUVlNNTEtTWkJBN01VWDNYQUxNUVQzTjRISUw1UkZGQU9YNUtaUFhEU0oyWlAzNkVMNVJBIiwiaWF0IjoxNTU4MDQ1NTYyLCJpc3MiOiJBQlZTQk0zVTQ1REdZRVVFQ0tYUVM3QkVOSFdHN0tGUVVEUlRFSEFKQVNPUlBWV0JaNEhPSUtDSCIsIm5hbWUiOiJvbWVnYSIsInN1YiI6IlVEWEIyVk1MWFBBU0FKN1pEVEtZTlE3UU9DRldTR0I0Rk9NWVFRMjVIUVdTQUY3WlFKRUJTUVNXIiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.6TQ2ilCDb6m2ZDiJuj_D_OePGXFyN3Ap2DEm3ipcU5AhrWrNvneJryWrpgi_yuVWKo1UoD5s8bxlmwypWVGFAA
|
||||
------END NATS USER JWT------
|
||||
|
||||
************************* IMPORTANT *************************
|
||||
NKEY Seed printed below can be used to sign and prove identity.
|
||||
NKEYs are sensitive and should be treated as secrets.
|
||||
|
||||
-----BEGIN USER NKEY SEED-----
|
||||
SUAOY5JZ2WJKVR4UO2KJ2P3SW6FZFNWEOIMAXF4WZEUNVQXXUOKGM55CYE
|
||||
------END USER NKEY SEED------
|
||||
|
||||
*************************************************************
|
||||
```
|
||||
|
||||
Given a creds file, a client can authenticate as a specific user belonging to a specific account:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("127.0.0.1", nats.UserCredentials("path_to_creds_file"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
authHandler(Nats.credentials("path_to_creds_file")).
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
// credentials file contains the JWT and the secret signing key
|
||||
let credsFile = path.join(confDir, 'credsfile.creds');
|
||||
|
||||
let nc = NATS.connect({
|
||||
url: server.nats,
|
||||
userCreds: credsFile
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
async def error_cb(e):
|
||||
print("Error:", e)
|
||||
|
||||
await nc.connect("nats://localhost:4222",
|
||||
user_credentials="path_to_creds_file",
|
||||
error_cb=error_cb,
|
||||
)
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// credentials file contains the JWT and the secret signing key
|
||||
let credsFile = path.join(confDir, 'credsfile.creds');
|
||||
|
||||
let nc = await connect({
|
||||
url: server.nats,
|
||||
userCreds: credsFile
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
109
developing-with-nats/security/nkey.md
Normal file
109
developing-with-nats/security/nkey.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Authenticating with an NKey
|
||||
|
||||
The 2.0 version of NATS server introduces a new challenge response authentication option. This challenge response is based on a wrapper we call NKeys which uses [Ed25519](https://ed25519.cr.yp.to/) signing. The server can use these keys in several ways for authentication. The simplest is for the server to be configured with a list of known public keys and for the clients to respond to the challenge by signing it with its private key. This challenge-response ensures security by ensuring that the client has the private key, but also protects the private key from the server which never has to actually see it.
|
||||
|
||||
Handling challenge response may require more than just a setting in the connection options, depending on the client library.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
opt, err := nats.NkeyOptionFromSeed("seed.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
nc, err := nats.Connect("127.0.0.1", opt)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
NKey theNKey = NKey.createUser(null); // really should load from somewhere
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
authHandler(new AuthHandler(){
|
||||
public char[] getID() {
|
||||
try {
|
||||
return theNKey.getPublicKey();
|
||||
} catch (GeneralSecurityException|IOException|NullPointerException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] sign(byte[] nonce) {
|
||||
try {
|
||||
return theNKey.sign(nonce);
|
||||
} catch (GeneralSecurityException|IOException|NullPointerException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public char[] getJWT() {
|
||||
return null;
|
||||
}
|
||||
}).
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
// seed should be stored in a file and treated like a secret
|
||||
const seed = 'SUAEL6GG2L2HIF7DUGZJGMRUFKXELGGYFMHF76UO2AYBG3K4YLWR3FKC2Q';
|
||||
|
||||
let nc = NATS.connect({
|
||||
url: server.nats,
|
||||
nkey: 'UD6OU4D3CIOGIDZVL4ANXU3NWXOW5DCDE2YPZDBHPBXCVKHSODUA4FKI',
|
||||
sigCB: function (nonce) {
|
||||
const sk = nkeys.fromSeed(Buffer.from(seed));
|
||||
return sk.sign(nonce);
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
async def error_cb(e):
|
||||
print("Error:", e)
|
||||
|
||||
await nc.connect("nats://localhost:4222",
|
||||
nkeys_seed="./path/to/nkeys/user.nk",
|
||||
error_cb=error_cb,
|
||||
)
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// seed should be stored in a file and treated like a secret
|
||||
const seed = 'SUAEL6GG2L2HIF7DUGZJGMRUFKXELGGYFMHF76UO2AYBG3K4YLWR3FKC2Q';
|
||||
|
||||
let nc = await connect({
|
||||
url: server.nats,
|
||||
nkey: 'UD6OU4D3CIOGIDZVL4ANXU3NWXOW5DCDE2YPZDBHPBXCVKHSODUA4FKI',
|
||||
nonceSigner: function (nonce) {
|
||||
const sk = fromSeed(Buffer.from(seed));
|
||||
return sk.sign(Buffer.from(nonce));
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
384
developing-with-nats/security/tls.md
Normal file
384
developing-with-nats/security/tls.md
Normal file
@@ -0,0 +1,384 @@
|
||||
# Encrypting Connections with TLS
|
||||
|
||||
While authentication limits which clients can connect, TLS can be used to check the server’s identity and optionally the client’s identity and will encrypt all traffic between the two. The most secure version of TLS with NATS is to use verified client certificates. In this mode, the client can check that it trusts the certificate sent by NATS system but the individual server will also check that it trusts the certificate sent by the client. From an application's perspective connecting to a server that does not verify client certificates may appear identical. Under the covers, disabling TLS verification removes the server side check on the client’s certificate. When started in TLS mode, a `nats-server` will require all clients to connect with TLS. Moreover, if configured to connect with TLS, client libraries will fail to connect to a server without TLS.
|
||||
|
||||
The [Java examples repository](https://github.com/nats-io/java-nats-examples/tree/master/src/main/resources) contains certificates for starting the server in TLS mode.
|
||||
|
||||
```bash
|
||||
> nats-server -c /src/main/resources/tls.conf
|
||||
or
|
||||
> nats-server -c /src/main/resources/tls_verify.conf
|
||||
```
|
||||
|
||||
## Connecting with TLS
|
||||
|
||||
Connecting to a server with TLS is straightforward. Most clients will automatically use TLS when connected to a NATS system using TLS. Setting up a NATS system to use TLS is primarily an exercise in setting up the certificate and trust managers. Clients may also need additional information, for example:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("localhost",
|
||||
nats.ClientCert("resources/certs/cert.pem", "resources/certs/key.pem"),
|
||||
nats.RootCAs("resources/certs/ca.pem"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class SSLUtils {
|
||||
public static String KEYSTORE_PATH = "src/main/resources/keystore.jks";
|
||||
public static String TRUSTSTORE_PATH = "src/main/resources/cacerts";
|
||||
public static String STORE_PASSWORD = "password";
|
||||
public static String KEY_PASSWORD = "password";
|
||||
public static String ALGORITHM = "SunX509";
|
||||
|
||||
public static KeyStore loadKeystore(String path) throws Exception {
|
||||
KeyStore store = KeyStore.getInstance("JKS");
|
||||
BufferedInputStream in = new BufferedInputStream(new FileInputStream(path));
|
||||
|
||||
try {
|
||||
store.load(in, STORE_PASSWORD.toCharArray());
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
public static KeyManager[] createTestKeyManagers() throws Exception {
|
||||
KeyStore store = loadKeystore(KEYSTORE_PATH);
|
||||
KeyManagerFactory factory = KeyManagerFactory.getInstance(ALGORITHM);
|
||||
factory.init(store, KEY_PASSWORD.toCharArray());
|
||||
return factory.getKeyManagers();
|
||||
}
|
||||
|
||||
public static TrustManager[] createTestTrustManagers() throws Exception {
|
||||
KeyStore store = loadKeystore(TRUSTSTORE_PATH);
|
||||
TrustManagerFactory factory = TrustManagerFactory.getInstance(ALGORITHM);
|
||||
factory.init(store);
|
||||
return factory.getTrustManagers();
|
||||
}
|
||||
|
||||
public static SSLContext createSSLContext() throws Exception {
|
||||
SSLContext ctx = SSLContext.getInstance(Options.DEFAULT_SSL_PROTOCOL);
|
||||
ctx.init(createTestKeyManagers(), createTestTrustManagers(), new SecureRandom());
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConnectTLS {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
SSLContext ctx = SSLUtils.createSSLContext();
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
sslContext(ctx). // Set the SSL context
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let caCert = fs.readFileSync(caCertPath);
|
||||
let clientCert = fs.readFileSync(clientCertPath);
|
||||
let clientKey = fs.readFileSync(clientKeyPath);
|
||||
let nc = NATS.connect({
|
||||
url: url,
|
||||
tls: {
|
||||
ca: [caCert],
|
||||
key: [clientKey],
|
||||
cert: [clientCert]
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
|
||||
ssl_ctx.load_verify_locations('ca.pem')
|
||||
ssl_ctx.load_cert_chain(certfile='client-cert.pem',
|
||||
keyfile='client-key.pem')
|
||||
await nc.connect(io_loop=loop, tls=ssl_ctx)
|
||||
|
||||
await nc.connect(servers=["nats://demo.nats.io:4222"], tls=ssl_ctx)
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
EM.run do
|
||||
|
||||
options = {
|
||||
:servers => [
|
||||
'nats://localhost:4222',
|
||||
],
|
||||
:tls => {
|
||||
:private_key_file => './spec/configs/certs/key.pem',
|
||||
:cert_chain_file => './spec/configs/certs/server.pem'
|
||||
}
|
||||
}
|
||||
|
||||
NATS.connect(options) do |nc|
|
||||
puts "#{Time.now.to_f} - Connected to NATS at #{nc.connected_server}"
|
||||
|
||||
nc.subscribe("hello") do |msg|
|
||||
puts "#{Time.now.to_f} - Received: #{msg}"
|
||||
end
|
||||
|
||||
nc.flush do
|
||||
nc.publish("hello", "world")
|
||||
end
|
||||
|
||||
EM.add_periodic_timer(0.1) do
|
||||
next unless nc.connected?
|
||||
nc.publish("hello", "hello")
|
||||
end
|
||||
|
||||
# Set default callbacks
|
||||
nc.on_error do |e|
|
||||
puts "#{Time.now.to_f } - Error: #{e}"
|
||||
end
|
||||
|
||||
nc.on_disconnect do |reason|
|
||||
puts "#{Time.now.to_f} - Disconnected: #{reason}"
|
||||
end
|
||||
|
||||
nc.on_reconnect do |nc|
|
||||
puts "#{Time.now.to_f} - Reconnected to NATS server at #{nc.connected_server}"
|
||||
end
|
||||
|
||||
nc.on_close do
|
||||
puts "#{Time.now.to_f} - Connection to NATS closed"
|
||||
EM.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let caCert = readFileSync(caCertPath);
|
||||
let clientCert = readFileSync(clientCertPath);
|
||||
let clientKey = readFileSync(clientKeyPath);
|
||||
let nc = await connect({
|
||||
url: url,
|
||||
tls: {
|
||||
ca: [caCert],
|
||||
key: [clientKey],
|
||||
cert: [clientCert]
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Connecting with the TLS Protocol
|
||||
|
||||
Some clients may support the `tls` protocol as well as a manual setting to turn on TLS. However, in that case there is likely some form of default or environmental settings to allow the TLS libraries to find certificate and trust stores.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("tls://localhost", nats.RootCAs("resources/certs/ca.pem")) // May need this if server is using self-signed certificate
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
class SSLUtils {
|
||||
public static String KEYSTORE_PATH = "src/main/resources/keystore.jks";
|
||||
public static String TRUSTSTORE_PATH = "src/main/resources/cacerts";
|
||||
public static String STORE_PASSWORD = "password";
|
||||
public static String KEY_PASSWORD = "password";
|
||||
public static String ALGORITHM = "SunX509";
|
||||
|
||||
public static KeyStore loadKeystore(String path) throws Exception {
|
||||
KeyStore store = KeyStore.getInstance("JKS");
|
||||
BufferedInputStream in = new BufferedInputStream(new FileInputStream(path));
|
||||
|
||||
try {
|
||||
store.load(in, STORE_PASSWORD.toCharArray());
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
public static KeyManager[] createTestKeyManagers() throws Exception {
|
||||
KeyStore store = loadKeystore(KEYSTORE_PATH);
|
||||
KeyManagerFactory factory = KeyManagerFactory.getInstance(ALGORITHM);
|
||||
factory.init(store, KEY_PASSWORD.toCharArray());
|
||||
return factory.getKeyManagers();
|
||||
}
|
||||
|
||||
public static TrustManager[] createTestTrustManagers() throws Exception {
|
||||
KeyStore store = loadKeystore(TRUSTSTORE_PATH);
|
||||
TrustManagerFactory factory = TrustManagerFactory.getInstance(ALGORITHM);
|
||||
factory.init(store);
|
||||
return factory.getTrustManagers();
|
||||
}
|
||||
|
||||
public static SSLContext createSSLContext() throws Exception {
|
||||
SSLContext ctx = SSLContext.getInstance(Options.DEFAULT_SSL_PROTOCOL);
|
||||
ctx.init(createTestKeyManagers(), createTestTrustManagers(), new SecureRandom());
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConnectTLS {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
SSLContext ctx = SSLUtils.createSSLContext();
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
sslContext(ctx). // Set the SSL context
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let caCert = fs.readFileSync(caCertPath);
|
||||
let clientCert = fs.readFileSync(clientCertPath);
|
||||
let clientKey = fs.readFileSync(clientKeyPath);
|
||||
let nc = NATS.connect({
|
||||
url: url,
|
||||
tls: {
|
||||
ca: [caCert],
|
||||
key: [clientKey],
|
||||
cert: [clientCert]
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
|
||||
ssl_ctx.load_verify_locations('ca.pem')
|
||||
ssl_ctx.load_cert_chain(certfile='client-cert.pem',
|
||||
keyfile='client-key.pem')
|
||||
await nc.connect(io_loop=loop, tls=ssl_ctx)
|
||||
|
||||
await nc.connect(servers=["nats://demo.nats.io:4222"], tls=ssl_ctx)
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
EM.run do
|
||||
|
||||
options = {
|
||||
:servers => [
|
||||
'nats://localhost:4222',
|
||||
],
|
||||
:tls => {
|
||||
:private_key_file => './spec/configs/certs/key.pem',
|
||||
:cert_chain_file => './spec/configs/certs/server.pem'
|
||||
}
|
||||
}
|
||||
|
||||
NATS.connect(options) do |nc|
|
||||
puts "#{Time.now.to_f} - Connected to NATS at #{nc.connected_server}"
|
||||
|
||||
nc.subscribe("hello") do |msg|
|
||||
puts "#{Time.now.to_f} - Received: #{msg}"
|
||||
end
|
||||
|
||||
nc.flush do
|
||||
nc.publish("hello", "world")
|
||||
end
|
||||
|
||||
EM.add_periodic_timer(0.1) do
|
||||
next unless nc.connected?
|
||||
nc.publish("hello", "hello")
|
||||
end
|
||||
|
||||
# Set default callbacks
|
||||
nc.on_error do |e|
|
||||
puts "#{Time.now.to_f } - Error: #{e}"
|
||||
end
|
||||
|
||||
nc.on_disconnect do |reason|
|
||||
puts "#{Time.now.to_f} - Disconnected: #{reason}"
|
||||
end
|
||||
|
||||
nc.on_reconnect do |nc|
|
||||
puts "#{Time.now.to_f} - Reconnected to NATS server at #{nc.connected_server}"
|
||||
end
|
||||
|
||||
nc.on_close do
|
||||
puts "#{Time.now.to_f} - Connection to NATS closed"
|
||||
EM.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let caCert = readFileSync(caCertPath);
|
||||
let clientCert = readFileSync(clientCertPath);
|
||||
let clientKey = readFileSync(clientKeyPath);
|
||||
let nc = await connect({
|
||||
url: url,
|
||||
tls: {
|
||||
ca: [caCert],
|
||||
key: [clientKey],
|
||||
cert: [clientCert]
|
||||
}
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
138
developing-with-nats/security/token.md
Normal file
138
developing-with-nats/security/token.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Authenticating with a Token
|
||||
|
||||
Tokens are basically random strings, much like a password, and can provide a simple authentication mechanism in some situations. However, tokens are only as safe as they are secret so other authentication schemes can provide more security in large installations.
|
||||
|
||||
For this example, start the server using:
|
||||
|
||||
```bash
|
||||
> nats-server --auth mytoken
|
||||
```
|
||||
|
||||
The code uses localhost:4222 so that you can start the server on your machine to try them out.
|
||||
|
||||
## Connecting with a Token
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Set a token
|
||||
nc, err := nats.Connect("127.0.0.1", nats.Name("API Token Example"), nats.Token("mytoken"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
token("mytoken"). // Set a token
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect({url: `nats://127.0.0.1:${port}`, token: "mytoken!"});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(servers=["nats://mytoken@demo.nats.io:4222"])
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
NATS.start(token: "deadbeef") do |nc|
|
||||
puts "Connected using token"
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let nc = await connect({url: server.nats, token: "mytoken"});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Connecting with a Token in the URL
|
||||
|
||||
Some client libraries will allow you to pass the token as part of the server URL using the form:
|
||||
|
||||
> nats://_token_@server:port
|
||||
|
||||
Again, once you construct this URL you can connect as if this was a normal URL.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Token in URL
|
||||
nc, err := nats.Connect("mytoken@localhost")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Connection nc = Nats.connect("nats://mytoken@localhost:4222");//Token in URL
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let url = `nats://mytoken!@127.0.0.1:${port}`;
|
||||
let nc = NATS.connect({url: url});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(servers=["nats://mytoken@demo.nats.io:4222"])
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
NATS.start("deadbeef@127.0.0.1:4222") do |nc|
|
||||
puts "Connected using token!"
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let url = `nats://:mytoken!@127.0.0.1:${port}`;
|
||||
let nc = await connect({url: url});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
176
developing-with-nats/security/userpass.md
Normal file
176
developing-with-nats/security/userpass.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Authenticating with a User and Password
|
||||
|
||||
For this example, start the server using:
|
||||
|
||||
```bash
|
||||
> nats-server --user myname --pass password
|
||||
```
|
||||
|
||||
You can encrypt passwords to pass to `nats-server` using a simple tool provided by the server:
|
||||
|
||||
```bash
|
||||
> go run mkpasswd.go -p
|
||||
> password: password
|
||||
> bcrypt hash: $2a$11$1oJy/wZYNTxr9jNwMNwS3eUGhBpHT3On8CL9o7ey89mpgo88VG6ba
|
||||
```
|
||||
|
||||
and use the hashed password in the server config. The client still uses the plain text version.
|
||||
|
||||
The code uses localhost:4222 so that you can start the server on your machine to try them out.
|
||||
|
||||
## Connecting with a User/Password
|
||||
|
||||
When logging in with a password `nats-server` will take either a plain text password or an encrypted password.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Set a user and plain text password
|
||||
nc, err := nats.Connect("127.0.0.1", nats.UserInfo("myname", "password"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:4222").
|
||||
userInfo("myname","password"). // Set a user and plain text password
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect({url: server.nats, user: "myname", pass: "password"});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(servers=["nats://myname:password@demo.nats.io:4222"])
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start(servers:["nats://myname:password@127.0.0.1:4222"], name: "my-connection") do |nc|
|
||||
nc.on_error do |e|
|
||||
puts "Error: #{e}"
|
||||
end
|
||||
|
||||
nc.on_reconnect do
|
||||
puts "Got reconnected to #{nc.connected_server}"
|
||||
end
|
||||
|
||||
nc.on_disconnect do |reason|
|
||||
puts "Got disconnected! #{reason}"
|
||||
end
|
||||
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let nc = await connect({url: server.nats, user: "myname", pass: "password"});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
## Connecting with a User/Password in the URL
|
||||
|
||||
Most clients make it easy to pass the user name and password by accepting them in the URL for the server. This standard format is:
|
||||
|
||||
> nats://_user_:_password_@server:port
|
||||
|
||||
Using this format, you can connect to a server using authentication as easily as you connected with a URL:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
// Set a user and plain text password
|
||||
nc, err := nats.Connect("myname:password@127.0.0.1")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Connection nc = Nats.connect("nats://myname:password@localhost:4222");
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let url = `nats://myname:password@127.0.0.1:${port}`;
|
||||
let nc = NATS.connect(url);
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
|
||||
await nc.connect(servers=["nats://myname:password@demo.nats.io:4222"])
|
||||
|
||||
# Do something with the connection.
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start(servers:["nats://myname:password@127.0.0.1:4222"], name: "my-connection") do |nc|
|
||||
nc.on_error do |e|
|
||||
puts "Error: #{e}"
|
||||
end
|
||||
|
||||
nc.on_reconnect do
|
||||
puts "Got reconnected to #{nc.connected_server}"
|
||||
end
|
||||
|
||||
nc.on_disconnect do |reason|
|
||||
puts "Got disconnected! #{reason}"
|
||||
end
|
||||
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let url = `nats://myname:password@127.0.0.1:${port}`;
|
||||
let nc = await connect({url: url});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
Reference in New Issue
Block a user