Skip to content

Commit

Permalink
cli: Clear root keys and session of exported devices
Browse files Browse the repository at this point in the history
  • Loading branch information
Aggelos Kolaitis committed Jan 12, 2021
1 parent 4ef7c37 commit f9d9ac0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 12 deletions.
36 changes: 24 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,22 @@ Private The Things Network Stack V2 deployments are also supported, and require
$ export TTNV2_DISCOVERY_SERVER_ADDRESS="discovery.thethings.network:1900"
```

### Notes

- The export process will halt if any error occurs.
- Execute commands with the `--dry-run` flag to verify whether the outcome will be as expected.
- Payload formatters are not exported. See [Payload Formatters](https://thethingsstack.io/integrations/payload-formatters/).
- Device sessions (**AppSKey**, **NwkSKey**, **DevAddr**, **FCntUp** and **FCntDown**) are exported by default. You can disable this by using the `--ttnv2.with-session=false` flag. It is recommended that you do not export session keys for devices that can instead re-join on The Things Stack.
- **IMPORTANT**: The migration from The Things Network Stack V2 to The Things Stack is one-way. Note that it is crucial that devices are handled by one Network Server at a time. The commands below will clear both the root keys (**AppKey**, if any) and the session (**AppSKey**, **NwkSKey** and **DevAddr**) from The Things Network Stack V2 after exporting the devices. Make sure you understand the ramifications of this. **Note that having the session keys present on both Network Servers is not supported, and you will most likely encounter uplink/downlink traffic issues and/or a corrupted device MAC state**.

### Export Devices

To export a single device using its Device ID (e.g. `mydevice`):

```bash
# dry run first, verify that no errors occur
$ ttn-lw-migrate device --source ttnv2 "mydevice" --dry-run --verbose > devices.json
# export device
$ ttn-lw-migrate device --source ttnv2 "mydevice" > devices.json
```

Expand All @@ -75,22 +86,23 @@ device5
And then export with:

```bash
$ ttn-lw-migrate device --source ttnv2 < device_ids.txt > devices.json
# dry run first, verify that no errors occur
$ ttn-lw-migrate devices --source ttnv2 "mydevice" --dry-run --verbose < device_ids.txt > devices.json
# export devices
$ ttn-lw-migrate devices --source ttnv2 < device_ids.txt > devices.json
```

### Export Applications

Similarly, to export all devices of application `my-app-id`:

```bash
# dry run first, verify that no errors occur
$ ttn-lw-migrate application --source ttnv2 "my-app-id" --dry-run --verbose > devices.json
# export devices
$ ttn-lw-migrate application --source ttnv2 "my-app-id" > devices.json
```

### Notes

- Payload formatters are not exported. See [Payload Formatters](https://thethingsstack.io/integrations/payload-formatters/).
- Active device sessions are exported by default. You can disable this by using the `--ttnv2.with-session=false` flag. It is recommended that you do not export session keys for devices that can instead re-join on The Things Stack.

## ChirpStack

### Configuration
Expand All @@ -108,6 +120,12 @@ See [Frequency Plans](https://thethingsstack.io/reference/frequency-plans/) for

> *NOTE*: `JoinEUI` and `FrequencyPlanID` are required because ChirpStack does not store these fields.
### Notes

- ABP devices without an active session are successfully exported from ChirpStack, but cannot be imported into The Things Stack.
- MaxEIRP may not be always set properly.
- ChirpStack payload formatters also accept a `variables` parameter. This will always be `null` on The Things Stack.

### Export Devices

To export a single device using its DevEUI (e.g. `0102030405060708`):
Expand Down Expand Up @@ -155,12 +173,6 @@ And export with:
$ ttn-lw-migrate application --source chirpstack < application_names.txt > devices.json
```

### Notes

- ABP devices without an active session are successfully exported from ChirpStack, but cannot be imported into The Things Stack.
- MaxEIRP may not be always set properly.
- ChirpStack payload formatters also accept a `variables` parameter. This will always be `null` on The Things Stack.

## Development Environment

Requires Go version 1.15 or higher. [Download Go](https://golang.org/dl/).
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ func Execute() int {

func init() {
rootCmd.PersistentFlags().Bool("verbose", false, "Verbose output")
rootCmd.PersistentFlags().Bool("dry-run", false, "Do everything except resetting root and session keys of exported devices")
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/Azure/go-autorest/autorest/adal v0.9.2 // indirect
github.com/TheThingsNetwork/go-app-sdk v0.0.0-20191121100818-5bae20ae2b27
github.com/TheThingsNetwork/go-utils v0.0.0-20190516083235-bdd4967fab4e
github.com/TheThingsNetwork/ttn/core/types v0.0.0-20190516112328-fcd38e2b9dc6
github.com/TheThingsNetwork/ttn/utils/errors v0.0.0-20190516081709-034d40b328bd
github.com/aws/aws-sdk-go v1.34.9 // indirect
github.com/brocaar/chirpstack-api/go/v3 v3.7.5
Expand Down
3 changes: 3 additions & 0 deletions pkg/source/ttnv2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type config struct {
frequencyPlanID string

withSession bool
dryRun bool
}

func flagSet() *pflag.FlagSet {
Expand Down Expand Up @@ -131,5 +132,7 @@ func getConfig(ctx context.Context, flags *pflag.FlagSet) (config, error) {
frequencyPlanID: frequencyPlanID,

withSession: boolFlag("ttnv2.with-session"),

dryRun: boolFlag("dry-run"),
}, nil
}
18 changes: 18 additions & 0 deletions pkg/source/ttnv2/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import (
"time"

ttnsdk "github.com/TheThingsNetwork/go-app-sdk"
ttntypes "github.com/TheThingsNetwork/ttn/core/types"
"github.com/TheThingsNetwork/ttn/utils/errors"
pbtypes "github.com/gogo/protobuf/types"
"github.com/spf13/pflag"
"go.thethings.network/lorawan-stack-migrate/pkg/source"
"go.thethings.network/lorawan-stack/v3/pkg/log"
"go.thethings.network/lorawan-stack/v3/pkg/ttnpb"
"go.thethings.network/lorawan-stack/v3/pkg/types"
)
Expand Down Expand Up @@ -151,6 +153,22 @@ func (s *Source) ExportDevice(devID string) (*ttnpb.EndDevice, error) {
}
}

log.FromContext(s.ctx).WithFields(log.Fields(
"device_id", dev.DevID,
"dev_eui", dev.DevEUI,
)).Info("Clearing device keys")
if !s.config.dryRun {
dev.AppKey = &ttntypes.AppKey{}
if s.config.withSession {
dev.AppSKey = &ttntypes.AppSKey{}
dev.NwkSKey = &ttntypes.NwkSKey{}
dev.DevAddr = &ttntypes.DevAddr{}
}
if err := s.mgr.Set(dev); err != nil {
return nil, err
}
}

return v3dev, nil
}

Expand Down

0 comments on commit f9d9ac0

Please sign in to comment.