Skip to content

Commit 933dd8c

Browse files
feature: implement onboard device to hub (#101)
* implement onboard and change pb.RemoteConfiguration to similar as in hub --------- Co-authored-by: Patrik Matiaško <patrik.matiasko@gmail.com>
1 parent 8316271 commit 933dd8c

86 files changed

Lines changed: 5086 additions & 1851 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
"TEST_ROOT_CA_KEY": "${workspaceFolder}/.tmp/certs/rootcakey.pem",
1818
"TEST_ROOT_CA_CERT": "${workspaceFolder}/.tmp/certs/rootcacrt.pem",
1919
"TEST_CLOUD_SID": "adebc667-1f2b-41e3-bf5c-6d6eabc68cc6",
20+
"TEST_COAP_GW_CERT_FILE": "${workspaceFolder}/.tmp/certs/coap.crt",
21+
"TEST_COAP_GW_KEY_FILE": "${workspaceFolder}/.tmp/certs/coap.key",
2022
// "GOMAXPROCS": 1,
2123
// "GOFLAGS":"-mod=vendor",
2224
// "GRPC_VERBOSITY":"DEBUG",

Makefile

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,45 @@ certificates:
3131
docker pull $(CERT_TOOL_IMAGE)
3232
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(CERT_PATH):/out $(CERT_TOOL_IMAGE) --outCert=/out/rootcacrt.pem --outKey=/out/rootcakey.pem --cert.subject.cn="ca" --cmd.generateRootCA
3333
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(CERT_PATH):/out $(CERT_TOOL_IMAGE) --signerCert=/out/rootcacrt.pem --signerKey=/out/rootcakey.pem --outCert=/out/httpcrt.pem --outKey=/out/httpkey.pem --cert.san.domain=localhost --cert.san.ip=127.0.0.1 --cert.subject.cn="http-server" --cmd.generateCertificate
34+
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(CERT_PATH):/out $(CERT_TOOL_IMAGE) --signerCert=/out/rootcacrt.pem --signerKey=/out/rootcakey.pem --outCert=/out/coap.crt --outKey=/out/coap.key --cmd.generateIdentityCertificate=$(CLOUD_SID) --cert.san.domain=localhost
35+
cat $(WORKING_DIRECTORY)/.tmp/certs/httpcrt.pem > $(WORKING_DIRECTORY)/.tmp/certs/mongo.key
36+
cat $(WORKING_DIRECTORY)/.tmp/certs/httpkey.pem >> $(WORKING_DIRECTORY)/.tmp/certs/mongo.key
3437
mkdir -p $(MFG_CERT_PATH)
3538
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(MFG_CERT_PATH):/out $(CERT_TOOL_IMAGE) --outCert=/out/cloudca.pem --outKey=/out/cloudcakey.pem --cert.subject.cn=MfgRootCA --cmd.generateRootCA
3639
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(MFG_CERT_PATH):/out $(CERT_TOOL_IMAGE) --signerCert=/out/cloudca.pem --signerKey=/out/cloudcakey.pem --outCert=/out/mfgcrt.pem --outKey=/out/mfgkey.pem --cert.subject.cn="mfg-device-cert" --cmd.generateCertificate
3740
docker run --rm --user $(USER_ID):$(GROUP_ID) -v $(MFG_CERT_PATH):/out $(CERT_TOOL_IMAGE) --signerCert=/out/cloudca.pem --signerKey=/out/cloudcakey.pem --outCert=/out/mfgclientapplicationcrt.pem --outKey=/out/mfgclientapplicationkey.pem --cert.subject.cn="mfg-client-application-cert" --cmd.generateCertificate
3841
.PHONY: certificates
3942

43+
nats:
44+
mkdir -p $(WORKING_DIRECTORY)/.tmp/jetstream/cloud
45+
docker run \
46+
-d \
47+
--network=host \
48+
--name=nats \
49+
-v $(WORKING_DIRECTORY)/.tmp/certs:/certs \
50+
-v $(WORKING_DIRECTORY)/.tmp/jetstream/cloud:/data \
51+
--user $(USER_ID):$(GROUP_ID) \
52+
nats --jetstream --store_dir /data --tls --tlsverify --tlscert=/certs/httpcrt.pem --tlskey=/certs/httpkey.pem --tlscacert=/certs/rootcacrt.pem
53+
.PHONY: nats
54+
55+
mongo: certificates
56+
mkdir -p $(WORKING_DIRECTORY)/.tmp/mongo
57+
docker run \
58+
-d \
59+
--network=host \
60+
--name=mongo \
61+
-v $(WORKING_DIRECTORY)/.tmp/mongo:/data/db \
62+
-v $(WORKING_DIRECTORY)/.tmp/certs:/certs --user $(USER_ID):$(GROUP_ID) \
63+
mongo --tlsMode requireTLS --tlsCAFile /certs/rootcacrt.pem --tlsCertificateKeyFile /certs/mongo.key
64+
.PHONY: mongo
65+
4066
privateKeys:
4167
mkdir -p $(OAUTH_SERVER_PATH)
4268
openssl genrsa -out $(OAUTH_SERVER_ID_TOKEN_PRIVATE_KEY) 4096
4369
openssl ecparam -name prime256v1 -genkey -noout -out $(OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY)
4470
.PHONY: privateKeys
4571

46-
env: clean certificates privateKeys
72+
env: clean certificates privateKeys nats mongo
4773
mkdir -p $(DEVSIM_PATH)
4874
docker pull $(DEVSIM_IMAGE)
4975
docker run -d \
@@ -56,8 +82,10 @@ env: clean certificates privateKeys
5682
.PHONY: env
5783

5884
clean:
85+
docker rm -f mongo || true
86+
docker rm -f nats || true
5987
docker rm -f devsim || true
60-
rm -rf $(TMP_PATH) || true
88+
sudo rm -rf $(TMP_PATH) || true
6189
.PHONY: clean
6290

6391

@@ -92,6 +120,8 @@ test: env
92120
export TEST_OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY=$(OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY); \
93121
export TEST_ROOT_CA_KEY=$(WORKING_DIRECTORY)/.tmp/certs/rootcakey.pem; \
94122
export TEST_ROOT_CA_CERT=$(WORKING_DIRECTORY)/.tmp/certs/rootcacrt.pem; \
123+
export TEST_COAP_GW_CERT_FILE=$(WORKING_DIRECTORY)/.tmp/certs/coap.crt; \
124+
export TEST_COAP_GW_KEY_FILE=$(WORKING_DIRECTORY)/.tmp/certs/coap.key; \
95125
export TEST_CLOUD_SID=$(CLOUD_SID); \
96126
if [ -n "$${JSON_REPORT}" ]; then \
97127
go test -v --race -p 1 -covermode=atomic -coverpkg=./... -coverprofile=$${COVERAGE_FILE} -json ./... > "$${JSON_REPORT_FILE}" ; \
@@ -121,10 +151,13 @@ proto/generate:
121151
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/disown_device.proto
122152
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/clear_cache.proto
123153
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/get_configuration.proto
154+
protoc-go-inject-tag -input=$(WORKING_DIRECTORY)/pb/get_configuration.pb.go
124155
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/get_identity_certificate.proto
125156
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/get_json_web_keys.proto
126157
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/initialize.proto
127158
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/reset.proto
159+
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/onboard_device.proto
160+
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) --go_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/offboard_device.proto
128161

129162
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) -I=$(GOOGLEAPIS_PATH) -I=$(GRPCGATEWAY_MODULE_PATH) --go-grpc_out=$(GOPATH)/src $(WORKING_DIRECTORY)/pb/service.proto
130163
protoc -I=. -I=$(GOPATH)/src -I=$(PLGDHUB_MODULE_PATH) -I=$(GOOGLEAPIS_PATH) -I=$(GRPCGATEWAY_MODULE_PATH) --openapiv2_out=$(GOPATH)/src \

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ HTTP API of the client application service as defined [swagger](./pb/service.swa
6666
| `apis.http.ui.enabled` | bool | `Set to true if you would like to run the web UI.` | `false` |
6767
| `apis.http.ui.directory` | string | `A path to the directory with web UI files. When it is not present, it creates <client_application_binary>/www with default ui.` | `""` |
6868
| `apis.http.tls.enabled` | bool | `Enable HTTPS.` | `false` |
69-
| `apis.http.tls.caPool` | string | `File path to the root certificate in PEM format which might contain multiple certificates in a single file.` | `""` |
69+
| `apis.http.tls.caPool` | []string | `File path to the root certificate in PEM format which might contain multiple certificates in a single file.` | `""` |
7070
| `apis.http.tls.keyFile` | string | `File path to private key in PEM format.` | `""` |
7171
| `apis.http.tls.certFile` | string | `File path to certificate in PEM format.` | `""` |
7272
| `apis.http.tls.clientCertificateRequired` | bool | `If true, require client certificate.` | `true` |
@@ -86,7 +86,7 @@ gRPC API of the client application service as defined [service](./pb/service.pro
8686
| `apis.grpc.keepAlive.maxConnectionAgeGrace` | string | `An additive period after MaxConnectionAge after which the connection will be forcibly closed. 0s means infinity.` | `0s` |
8787
| `apis.grpc.keepAlive.time` | string | `After a duration of this time if the server doesn't see any activity it pings the client to see if the transport is still alive.` | `2h` |
8888
| `apis.grpc.keepAlive.timeout` | string | `After having pinged for keepalive check, the client waits for a duration of Timeout and if no activity is seen even after that the connection is closed.` | `20s` |
89-
| `apis.grpc.tls.caPool` | string | `File path to the root certificate in PEM format which might contain multiple certificates in a single file.` | `""` |
89+
| `apis.grpc.tls.caPool` | []string | `File path to the root certificate in PEM format which might contain multiple certificates in a single file.` | `""` |
9090
| `apis.grpc.tls.enabled` | bool | `Enable TLS for grpc.` | `false` |
9191
| `apis.grpc.tls.keyFile` | string | `File path to private key in PEM format.` | `""` |
9292
| `apis.grpc.tls.certFile` | string | `File path to certificate in PEM format.` | `""` |
@@ -121,12 +121,19 @@ Supported modes:
121121
| Property | Type | Description | Default |
122122
| ---------- | -------- | -------------- | ------- |
123123
| `remoteProvisioning.mode` | string | `Provides remote provisioning mode. In "userAgent" mode all signing certificates goes through the user agent (browser,cli). "" means none. The supported values are: "", "userAgent"` | `""` |
124-
| `remoteProvisioning.userAgent.certificateAuthorityAddress` | string | `Certificate authority server address in format {DNS}:{PORT}` | `""` |
124+
| `remoteProvisioning.certificateAuthority` | string | `Certificate authority server address in format {SCHEME}://{DNS}:{PORT}` | `""` |
125125
| `remoteProvisioning.userAgent.csrChallengeStateExpiration` | string | `Defines how long is valid csr challenge.` | `"1m"` |
126-
| `remoteProvisioning.authorization.authority` | string | `Authority is the address of the token-issuing authentication server.` | `""` |
127-
| `remoteProvisioning.authorization.clientId` | string | `Client ID to exchange an authorization code for an access token.` | `""` |
128-
| `remoteProvisioning.authorization.audience` | string | `Identifier of the API configured in your OAuth provider.` | `""` |
129-
| `remoteProvisioning.authorization.scopes` | []string | `List of required scopes.` | `[]` |
130-
| `remoteProvisioning.authorization.ownerClaim` | string | `Claim used to identify owner of the device.` | `"sub"` |
126+
| `remoteProvisioning.authority` | string | `Authority is the address of the token-issuing authentication server.` | `""` |
127+
| `remoteProvisioning.webOAuthClient.clientID` | string | `Client ID to exchange an authorization code for an access token.` | `""` |
128+
| `remoteProvisioning.webOAuthClient.audience` | string | `Identifier of the API configured in your OAuth provider.` | `""` |
129+
| `remoteProvisioning.webOAuthClient.scopes` | []string | `List of required scopes.` | `[]` |
130+
| `remoteProvisioning.ownerClaim` | string | `Claim used to identify owner of the device.` | `"sub"` |
131+
| `remoteProvisioning.hubID` | string | `Plgd hub id.` | `""` |
132+
| `remoteProvisioning.coapGateway` | string | `CoAP gateway for onboard device.` | `""` |
133+
| `remoteProvisioning.caPool` | []string | `File paths to root CAs which was used to sign coap-gw certificate.` | `""` |
134+
| `remoteProvisioning.deviceOAuthClient.clientID` | string | `Client ID to exchange an authorization code for an access token.` | `""` |
135+
| `remoteProvisioning.deviceOAuthClient.audience` | string | `Identifier of the API configured in your OAuth provider.` | `""` |
136+
| `remoteProvisioning.deviceOAuthClient.scopes` | []string | `List of required scopes.` | `[]` |
137+
| `remoteProvisioning.deviceOAuthClient.providerName` | string | `Name of provider, which needs to be set to cloud resource during cloud provisioning.` | `""` |
131138

132139
> Note that the string type related to time (i.e. timeout, idleConnTimeout, expirationTime) is decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m". Valid time units are "ns", "us", "ms", "s", "m", "h".

cmd/defaultConfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/plgd-dev/client-application/service/config"
2525
)
2626

27+
// resolveDefaultConfig creates default config file if it doesn't exist and sets --config argument.
2728
func resolveDefaultConfig(configPath string) error {
2829
configPathWasSet := true
2930
if configPath == "" {

cmd/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func main() {
5151
log.Errorf("cannot create default config: %v", err)
5252
return
5353
}
54+
// parse line arguments again because resolveDefaultConfig can set config path
55+
_, _ = flags.NewParser(&opts, flags.Default|flags.IgnoreUnknown).Parse()
5456
cfg, err := config.New(opts.ConfigPath)
5557
if err != nil {
5658
log.Errorf("cannot load config: %v", err)

go.mod

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,36 @@ go 1.18
44

55
require (
66
cloud.google.com/go v0.105.0
7+
github.com/favadi/protoc-go-inject-tag v1.4.0
78
github.com/fullstorydev/grpchan v1.1.1
8-
github.com/golang-jwt/jwt/v4 v4.4.2
9+
github.com/golang-jwt/jwt/v4 v4.4.3
910
github.com/google/uuid v1.3.0
1011
github.com/goreleaser/goreleaser v1.9.2
1112
github.com/gorilla/handlers v1.5.1
1213
github.com/gorilla/mux v1.8.0
13-
github.com/grpc-ecosystem/grpc-gateway/v2 v2.13.0
14+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0
1415
github.com/jellydator/ttlcache/v3 v3.0.0
1516
github.com/jessevdk/go-flags v1.5.0
1617
github.com/lestrrat-go/jwx v1.2.25
1718
github.com/pion/dtls/v2 v2.1.6-0.20221001075407-984d41b9981a
18-
github.com/plgd-dev/device/v2 v2.0.1
19-
github.com/plgd-dev/go-coap/v3 v3.0.1-0.20221107080825-5cfe76a3720f
20-
github.com/plgd-dev/hub/v2 v2.6.2-0.20221114160043-0fae0566c217
19+
github.com/plgd-dev/device/v2 v2.0.2-0.20221202214050-f9f57f7c9a61
20+
github.com/plgd-dev/go-coap/v3 v3.0.2-0.20221201101543-2e2c858a13f2
21+
github.com/plgd-dev/hub/v2 v2.7.4-0.20221213114839-98df2c84d8eb
2122
github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90
2223
github.com/stretchr/testify v1.8.1
2324
go.opentelemetry.io/otel/trace v1.11.1
2425
go.uber.org/atomic v1.10.0
25-
go.uber.org/zap v1.23.0
26-
google.golang.org/api v0.102.0
27-
google.golang.org/grpc v1.50.1
26+
go.uber.org/zap v1.24.0
27+
google.golang.org/api v0.103.0
28+
google.golang.org/grpc v1.51.0
2829
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0
2930
google.golang.org/protobuf v1.28.1
3031
gopkg.in/yaml.v3 v3.0.1
3132
)
3233

3334
require (
34-
cloud.google.com/go/compute v1.12.1 // indirect
35-
cloud.google.com/go/compute/metadata v0.2.1 // indirect
35+
cloud.google.com/go/compute v1.13.0 // indirect
36+
cloud.google.com/go/compute/metadata v0.2.2 // indirect
3637
cloud.google.com/go/iam v0.7.0 // indirect
3738
cloud.google.com/go/kms v1.6.0 // indirect
3839
cloud.google.com/go/storage v1.27.0 // indirect
@@ -81,7 +82,7 @@ require (
8182
github.com/caarlos0/go-reddit/v3 v3.0.1 // indirect
8283
github.com/caarlos0/go-shellwords v1.0.12 // indirect
8384
github.com/cavaliergopher/cpio v1.0.1 // indirect
84-
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
85+
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
8586
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
8687
github.com/davecgh/go-spew v1.1.1 // indirect
8788
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
@@ -102,7 +103,7 @@ require (
102103
github.com/go-logr/stdr v1.2.2 // indirect
103104
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
104105
github.com/gobwas/glob v0.2.3 // indirect
105-
github.com/goccy/go-json v0.9.11 // indirect
106+
github.com/goccy/go-json v0.10.0 // indirect
106107
github.com/golang/glog v1.0.0 // indirect
107108
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
108109
github.com/golang/protobuf v1.5.2 // indirect
@@ -120,7 +121,7 @@ require (
120121
github.com/gorilla/websocket v1.5.0 // indirect
121122
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
122123
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2 // indirect
123-
github.com/hashicorp/errwrap v1.0.0 // indirect
124+
github.com/hashicorp/errwrap v1.1.0 // indirect
124125
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
125126
github.com/hashicorp/go-multierror v1.1.1 // indirect
126127
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
@@ -159,12 +160,12 @@ require (
159160
github.com/muesli/mango-pflag v0.1.0 // indirect
160161
github.com/muesli/roff v0.1.0 // indirect
161162
github.com/nats-io/jwt/v2 v2.2.0 // indirect
162-
github.com/nats-io/nats.go v1.19.1 // indirect
163+
github.com/nats-io/nats.go v1.20.0 // indirect
163164
github.com/nats-io/nkeys v0.3.0 // indirect
164165
github.com/nats-io/nuid v1.0.1 // indirect
165166
github.com/panjf2000/ants/v2 v2.6.0 // indirect
166167
github.com/pion/logging v0.2.2 // indirect
167-
github.com/pion/transport v0.13.1 // indirect
168+
github.com/pion/transport v0.14.1 // indirect
168169
github.com/pion/udp v0.1.2-0.20221011090648-2589407f52c9 // indirect
169170
github.com/pkg/errors v0.9.1 // indirect
170171
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -198,17 +199,17 @@ require (
198199
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
199200
go.uber.org/multierr v1.8.0 // indirect
200201
gocloud.dev v0.24.0 // indirect
201-
golang.org/x/crypto v0.1.0 // indirect
202-
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect
203-
golang.org/x/net v0.1.0 // indirect
204-
golang.org/x/oauth2 v0.1.0 // indirect
202+
golang.org/x/crypto v0.3.0 // indirect
203+
golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb // indirect
204+
golang.org/x/net v0.2.0 // indirect
205+
golang.org/x/oauth2 v0.2.0 // indirect
205206
golang.org/x/sync v0.1.0 // indirect
206-
golang.org/x/sys v0.2.0 // indirect
207-
golang.org/x/text v0.4.0 // indirect
207+
golang.org/x/sys v0.3.0 // indirect
208+
golang.org/x/text v0.5.0 // indirect
208209
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
209210
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
210211
google.golang.org/appengine v1.6.7 // indirect
211-
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
212+
google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect
212213
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
213214
gopkg.in/mail.v2 v2.3.1 // indirect
214215
gopkg.in/warnings.v0 v0.1.2 // indirect

0 commit comments

Comments
 (0)