Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mpx 24 coap #1

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,15 @@ MPROXY_HTTP_WITH_MTLS_SERVER_CA_FILE=ssl/certs/ca.crt
MPROXY_HTTP_WITH_MTLS_CLIENT_CA_FILE=ssl/certs/ca.crt
MPROXY_HTTP_WITH_MTLS_CERT_VERIFICATION_METHODS=ocsp
MPROXY_HTTP_WITH_MTLS_OCSP_RESPONDER_URL=http://localhost:8080/ocsp

MPROXY_COAP_WITHOUT_DTLS_ADDRESS=:5682
MPROXY_COAP_WITHOUT_DTLS_TARGET=localhost:5683

MPROXY_COAP_WITH_DTLS_ADDRESS=:5684
MPROXY_COAP_WITH_DTLS_TARGET=localhost:5683
MPROXY_COAP_WITH_DTLS_CERT_FILE=ssl/certs/server.crt
MPROXY_COAP_WITH_DTLS_KEY_FILE=ssl/certs/server.key
MPROXY_COAP_WITH_DTLS_SERVER_CA_FILE=ssl/certs/ca.crt
MPROXY_COAP_WITH_DTLS_CLIENT_CA_FILE=ssl/certs/ca.crt


28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ LB tasks can be offloaded to a standard ingress proxy - for example, NginX.
- Golang
- Mosquitto MQTT Server
- Mosquitto Publisher and Subscriber Client
- coap-client or Magistrala coap-cli

### Example Setup of mProxy

Expand Down Expand Up @@ -122,6 +123,8 @@ mProxy is used to proxy requests to a backend server. For the example setup, we
- mProxy server for `HTTP protocol without TLS` on port `8086` with prefix path `/messages`
- mProxy server for `HTTP protocol with TLS` on port `8087` with prefix path `/messages`
- mProxy server for `HTTP protocol with mTLS` on port `8088` with prefix path `/messages`
- mProxy server for `COAP protocol without DTLS` on port `5682`
- mProxy server for `COAP protocol with DTLS` on port `5684`

### Example testing of mProxy

Expand Down Expand Up @@ -191,6 +194,23 @@ Bash scripts available in `examples/client/http` directory help to test the mPro
examples/client/http/with_mtls.sh
```

### Test mProxy server for CoAP protocols

Bash scripts available in `example/client/coap` directory help to test the mProxy servers running for CoAP protocols. You will require to have either the [coap-client](https://libcoap.net/doc/reference/4.3.1/man_coap-client.html) or the [Magistrala coap-cli](https://github.com/absmach/coap-cli).
The script can be used alongside the simple go-coap server provided at `example/server/coap`.

- Script to test mProxy server running at 5682 for CoAP without DTLS

```bash
examples/client/coap/without_dtls.sh
```

- Script to test mProxy server running at 5684 for CoAP with DTLS

```bash
examples/client/coap/with_dtls.sh
```

## Configuration

The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.
Expand Down Expand Up @@ -246,6 +266,14 @@ The service is configured using the environment variables presented in the follo
| MPROXY_HTTP_WITH_MTLS_CLIENT_CA_FILE | HTTP with mTLS client CA file path | ssl/certs/ca.crt |
| MPROXY_HTTP_WITH_MTLS_CERT_VERIFICATION_METHODS | HTTP with mTLS certificate verification methods, if no value or unset then mProxy server will not do client validation | ocsp |
| MPROXY_HTTP_WITH_MTLS_OCSP_RESPONDER_URL | HTTP with mTLS OCSP responder URL, it is used if OCSP responder URL is not available in client certificate AIA | <http://localhost:8080/ocsp> |
| MPROXY_COAP_WITHOUT_DTLS_ADDRESS | CoAP without DTLS inbound (IN) connection listening address | localhost:5682 |
| MPROXY_COAP_WITH_DTLS_TARGET | CoAP without DTLS outbound (OUT) connection | localhost:5683 |
| MPROXY_COAP_WITH_DTLS_ADDRESS | CoAP with DTLS inbound (IN) connection listening address | localhost:5684 |
| MPROXY_COAP_WITH_DTLS_TARGET | CoAP with DTLS outbound (OUT) connection | localhost:5683 |
| MPROXY_COAP_WITH_DTLS_CERT_FILE | CoAP with DTLS certificate file | ssl/certs/server.crt |
| MPROXY_COAP_WITH_DTLS_KEY_FILE | CoAP with DTLS key file | ssl/certs/server.key |
| MPROXY_COAP_WITH_DTLS_SERVER_CA_FILE | CoAP with DTLS server CA file | ssl/certs/ca.crt |
| MPROXY_COAP_WITH_DTLS_CLIENT_CA_FILE | CoAP with DTLS client CA file | ssl/certs/ca.crt |

## mProxy Configuration Environment Variables

Expand Down
40 changes: 34 additions & 6 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/absmach/mproxy"
"github.com/absmach/mproxy/examples/simple"
"github.com/absmach/mproxy/pkg/coap"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The newly imported coap package (github.com/absmach/mproxy/pkg/coap) is not utilized anywhere in the codebase. Please ensure that this import is either used appropriately in the code or removed if it is not needed.

  • Unused import found in cmd/main.go at line 16.
Analysis chain

Ensure the new import github.com/absmach/mproxy/pkg/coap is utilized properly in the code.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the usage of the newly imported `coap` package.

# Test: Search for the usage of the `coap` package. Expect: At least one usage in the file.
ast-grep --lang go --pattern $'import "github.com/absmach/mproxy/pkg/coap" { $$$ }'

Length of output: 558



Script:

#!/bin/bash
# Description: Verify the usage of the newly imported `coap` package.

# Test: Search for the usage of the `coap` package. Expect: At least one usage in the codebase.
ast-grep --lang go --pattern $'coap.$_' --json

Length of output: 50

"github.com/absmach/mproxy/pkg/http"
"github.com/absmach/mproxy/pkg/mqtt"
"github.com/absmach/mproxy/pkg/mqtt/websocket"
Expand All @@ -34,6 +35,9 @@ const (
httpWithoutTLS = "MPROXY_HTTP_WITHOUT_TLS_"
httpWithTLS = "MPROXY_HTTP_WITH_TLS_"
httpWithmTLS = "MPROXY_HTTP_WITH_MTLS_"

coapWithoutDTLS = "MPROXY_COAP_WITHOUT_DTLS_"
coapWithDTLS = "MPROXY_COAP_WITH_DTLS_"
)

func main() {
Expand Down Expand Up @@ -62,7 +66,7 @@ func main() {
}

// mProxy server for MQTT without TLS
mqttProxy := mqtt.New(mqttConfig, handler, interceptor, logger)
mqttProxy := mqtt.NewProxy(mqttConfig, handler, interceptor, logger)
g.Go(func() error {
return mqttProxy.Listen(ctx)
})
Expand All @@ -74,7 +78,7 @@ func main() {
}

// mProxy server for MQTT with TLS
mqttTLSProxy := mqtt.New(mqttTLSConfig, handler, interceptor, logger)
mqttTLSProxy := mqtt.NewProxy(mqttTLSConfig, handler, interceptor, logger)
g.Go(func() error {
return mqttTLSProxy.Listen(ctx)
})
Expand All @@ -86,7 +90,7 @@ func main() {
}

// mProxy server for MQTT with mTLS
mqttMTlsProxy := mqtt.New(mqttMTLSConfig, handler, interceptor, logger)
mqttMTlsProxy := mqtt.NewProxy(mqttMTLSConfig, handler, interceptor, logger)
g.Go(func() error {
return mqttMTlsProxy.Listen(ctx)
})
Expand All @@ -98,7 +102,7 @@ func main() {
}

// mProxy server for MQTT over Websocket without TLS
wsProxy := websocket.New(wsConfig, handler, interceptor, logger)
wsProxy := websocket.NewProxy(wsConfig, handler, interceptor, logger)
g.Go(func() error {
return wsProxy.Listen(ctx)
})
Expand All @@ -110,7 +114,7 @@ func main() {
}

// mProxy server for MQTT over Websocket with TLS
wsTLSProxy := websocket.New(wsTLSConfig, handler, interceptor, logger)
wsTLSProxy := websocket.NewProxy(wsTLSConfig, handler, interceptor, logger)
g.Go(func() error {
return wsTLSProxy.Listen(ctx)
})
Expand All @@ -122,7 +126,7 @@ func main() {
}

// mProxy server for MQTT over Websocket with mTLS
wsMTLSProxy := websocket.New(wsMTLSConfig, handler, interceptor, logger)
wsMTLSProxy := websocket.NewProxy(wsMTLSConfig, handler, interceptor, logger)
g.Go(func() error {
return wsMTLSProxy.Listen(ctx)
})
Expand Down Expand Up @@ -172,6 +176,30 @@ func main() {
return httpMTLSProxy.Listen(ctx)
})

// mProxy server Configuration for CoAP without DTLS
coapConfig, err := mproxy.NewConfig(env.Options{Prefix: coapWithoutDTLS})
if err != nil {
panic(err)
}

// mProxy server for CoAP without DTLS
coapProxy := coap.NewProxy(coapConfig, handler, logger)
g.Go(func() error {
return coapProxy.Listen(ctx)
})

// mProxy server Configuration for CoAP with DTLS
coapDTLSConfig, err := mproxy.NewConfig(env.Options{Prefix: coapWithDTLS})
if err != nil {
panic(err)
}

// mProxy server for CoAP with DTLS
coapDTLSProxy := coap.NewProxy(coapDTLSConfig, handler, logger)
g.Go(func() error {
return coapDTLSProxy.Listen(ctx)
})

g.Go(func() error {
return StopSignalHandler(ctx, cancel, logger)
})
Expand Down
9 changes: 7 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (

mptls "github.com/absmach/mproxy/pkg/tls"
"github.com/caarlos0/env/v11"
"github.com/pion/dtls/v2"
)

type Config struct {
Address string `env:"ADDRESS" envDefault:""`
PathPrefix string `env:"PATH_PREFIX" envDefault:"/"`
Target string `env:"TARGET" envDefault:""`
TLSConfig *tls.Config
DTLSConfig *dtls.Config
}

func NewConfig(opts env.Options) (Config, error) {
Expand All @@ -27,8 +29,11 @@ func NewConfig(opts env.Options) (Config, error) {
if err != nil {
return Config{}, err
}

c.TLSConfig, err = mptls.Load(&cfg)
c.TLSConfig, err = mptls.LoadTLSConfig(&cfg, &tls.Config{})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set the minimum TLS version to TLS 1.3 to enhance security.

- c.TLSConfig, err = mptls.LoadTLSConfig(&cfg, &tls.Config{})
+ c.TLSConfig, err = mptls.LoadTLSConfig(&cfg, &tls.Config{MinVersion: tls.VersionTLS13})

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
c.TLSConfig, err = mptls.LoadTLSConfig(&cfg, &tls.Config{})
c.TLSConfig, err = mptls.LoadTLSConfig(&cfg, &tls.Config{MinVersion: tls.VersionTLS13})

if err != nil {
return Config{}, err
}
c.DTLSConfig, err = mptls.LoadTLSConfig(&cfg, &dtls.Config{})
if err != nil {
return Config{}, err
}
Expand Down
25 changes: 25 additions & 0 deletions examples/client/coap/with_dtls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
protocol=coaps
host=localhost
port=5684
path="test"
content=0x32
message="{\"message\": \"Hello mProxy\"}"
auth="TOKEN"
cafile=ssl/certs/ca.crt
certfile=ssl/certs/client.crt
keyfile=ssl/certs/client.key
Comment on lines +1 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure secure handling of sensitive data.

The auth variable contains a token that should be securely managed. Consider using environment variables or a secure vault for sensitive data.


echo "Posting message to ${protocol}://${host}:${port}/${path} with dtls ..."
coap-client -m post coap://${host}:${port}/${path} -e "${message}" -O 12,${content} -O 15,auth=${auth} \
-c $certfile -k $keyfile -C $cafile

echo "Getting message from ${protocol}://${host}:${port}/${path} with dtls ..."
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c $certfile -k $keyfile -C $cafile
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the command is split correctly over multiple lines.

There should be a space before the backslash to ensure the command is split correctly.

- coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c $certfile -k $keyfile -C $cafile
+ coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c $certfile -k $keyfile -C $cafile \
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c $certfile -k $keyfile -C $cafile
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c $certfile -k $keyfile -C $cafile \


echo "Posting message to ${protocol}://${host}:${port}/${path} with dtls and invalid client certificate..."
coap-client -m post coap://${host}:${port}/${path} -e "${message}" -O 12,${content} -O 15,auth=${auth} \
-c ssl/certs/client_unknown.crt -k ssl/certs/client_unknown.key -C $cafile

echo "Getting message from ${protocol}://${host}:${port}/${path} with dtls and invalid client certificate..."
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth} -c ssl/certs/client_unknown.crt -k ssl/certs/client_unknown.key -C $cafile
22 changes: 22 additions & 0 deletions examples/client/coap/without_dtls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
protocol=coap
host=localhost
port=5682
path="test"
content=0x32
message="{\"message\": \"Hello mProxy\"}"
auth="TOKEN"

#Examples using lib-coap coap-client
echo "Posting message to ${protocol}://${host}:${port}/${path} without tls ..."
coap-client -m post coap://${host}:${port}/${path} -e "${message}" -O 12,${content} -O 15,auth=${auth}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Ensure proper error handling for the coap-client command in the examples/client/coap/without_dtls.sh script. The current implementation does not handle errors, which could lead to unhandled failures.

  • File: examples/client/coap/without_dtls.sh
  • Lines: 12

Consider adding error handling like this:

coap-client -m post coap://${host}:${port}/${path} -e "${message}" -O 12,${content} -O 15,auth=${auth} || { echo "Failed to post message"; exit 1; }
Analysis chain

Ensure proper error handling for the coap-client command.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check if error handling is implemented for coap-client commands.

# Test: Search for error handling patterns in coap-client usage.
rg --type sh $'coap-client.*|| echo'

Length of output: 18925


echo "Getting message from ${protocol}://${host}:${port}/${path} without tls ..."
coap-client -m get coap://${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth}

#Examples using Magisrala coap-cli
echo "Posting message to ${protocol}://${host}:${port}/${path} without tls ..."
coap-cli post ${host}:${port}/${path} -d "${message}" -O 12,${content} -O 15,auth=${auth}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The script examples/client/coap/without_dtls.sh lacks error handling for coap-cli commands. Consider adding error handling to ensure robustness.

  • File: examples/client/coap/without_dtls.sh
  • Lines: 19, 23
Analysis chain

Consider adding error handling for coap-cli commands to ensure robustness.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify error handling for coap-cli commands.

# Test: Search for error handling patterns in coap-cli usage.
rg --type sh $'coap-cli.*|| echo'

Length of output: 18922


echo "Getting message from ${protocol}://${host}:${port}/${path} without tls ..."
coap-cli get ${host}:${port}/${path} -O 6,0x00 -O 15,auth=${auth}
37 changes: 37 additions & 0 deletions examples/server/coap/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package main

import (
"fmt"
"log"
"strings"

coap "github.com/plgd-dev/go-coap/v3"
"github.com/plgd-dev/go-coap/v3/message"
"github.com/plgd-dev/go-coap/v3/message/codes"
"github.com/plgd-dev/go-coap/v3/mux"
)

const defaultPort = "5683"

func handleRequest(w mux.ResponseWriter, r *mux.Message) {
resp := w.Conn().AcquireMessage(r.Context())
defer w.Conn().ReleaseMessage(resp)
resp.SetCode(codes.Content)
resp.SetToken(r.Token())
resp.SetContentFormat(message.TextPlain)
resp.SetBody(strings.NewReader(fmt.Sprintf("%v OK", r.Code())))
err := w.Conn().WriteMessage(resp)
if err != nil {
log.Printf("Cannot send response: %v", err)
}
}

func main() {
r := mux.NewRouter()
r.DefaultHandle(mux.HandlerFunc(handleRequest))
log.Println("starting coap server, listening on port " + defaultPort)
log.Fatal(coap.ListenAndServe("udp", ":"+defaultPort, r))
}
15 changes: 14 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,25 @@ toolchain go1.21.4

require (
github.com/caarlos0/env/v11 v11.0.0
github.com/dustin/go-coap v0.0.0-20190908170653-752e0f79981e
github.com/eclipse/paho.mqtt.golang v1.4.3
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.1
github.com/joho/godotenv v1.5.1
github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8
github.com/plgd-dev/go-coap/v3 v3.3.3
golang.org/x/crypto v0.22.0
golang.org/x/sync v0.7.0
)

require golang.org/x/net v0.24.0 // indirect
require (
github.com/dsnet/golib/memfile v1.0.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/transport/v3 v3.0.1 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.19.0 // indirect
)
Loading
Loading