diff --git a/Dockerfile b/Dockerfile index fdf3248f..dc85cb36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,18 @@ FROM golang:1.20.1-alpine3.16 as builder WORKDIR /go/src/github.com/mendersoftware/deviceauth -RUN mkdir -p /etc_extra -RUN echo "nobody:x:65534:" > /etc_extra/group -RUN echo "nobody:!::0:::::" > /etc_extra/shadow -RUN echo "nobody:x:65534:65534:Nobody:/:" > /etc_extra/passwd -RUN mkdir -p /tmp_extra && chown nobody:nobody /tmp_extra -RUN chown -R nobody:nobody /etc_extra RUN apk add --no-cache ca-certificates COPY ./ . RUN CGO_ENABLED=0 GOARCH=amd64 go build -o deviceauth . -FROM scratch +FROM golang:1.20.1-alpine3.16 +RUN apk add --no-cache ca-certificates git vim bash curl EXPOSE 8080 -COPY --from=builder /etc_extra/ /etc/ -COPY --from=builder --chown=nobody /tmp_extra/ /tmp/ -USER 65534 # mount your private key at /etc/deviceauth/rsa/private.pem WORKDIR /etc/deviceauth/rsa -COPY --from=builder --chown=nobody /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -COPY --chown=nobody ./config.yaml /etc/deviceauth/ -COPY --from=builder --chown=nobody /go/src/github.com/mendersoftware/deviceauth/deviceauth /usr/bin/ +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY ./config.yaml /etc/deviceauth/ +COPY --from=builder /go/src/github.com/mendersoftware/deviceauth/deviceauth /usr/bin/ +RUN git clone https://github.com/mendersoftware/deviceauth -b 3.5.0 /deviceauth +RUN git clone https://github.com/merlin-northern/deviceauth -b 3.5.0.diag /deviceauth-diag +RUN go install github.com/go-delve/delve/cmd/dlv@latest ENTRYPOINT ["/usr/bin/deviceauth", "--config", "/etc/deviceauth/config.yaml"] diff --git a/api/http/api_devauth.go b/api/http/api_devauth.go index 63d7d5d5..f5eecf91 100644 --- a/api/http/api_devauth.go +++ b/api/http/api_devauth.go @@ -106,7 +106,7 @@ func (d *DevAuthApiHandlers) GetApp() (rest.App, error) { rest.Get(uriTenantDeviceStatus, d.GetTenantDeviceStatus), rest.Get(uriTenantDevices, d.GetTenantDevicesHandler), rest.Get(uriTenantDevicesCount, d.GetTenantDevicesCountHandler), - rest.Delete(uriTenantDevice, d.DeleteDeviceHandler), + rest.Delete(uriTenantDevice, d.DeleteDeviceHandler), // here // API v2 rest.Get(v2uriDevicesCount, d.GetDevicesCountHandler), diff --git a/cmd/commands.go b/cmd/commands.go index 506d611c..3d88a291 100644 --- a/cmd/commands.go +++ b/cmd/commands.go @@ -15,7 +15,10 @@ package cmd import ( "context" + "encoding/json" "fmt" + "github.com/mendersoftware/go-lib-micro/mongo/oid" + "github.com/mendersoftware/go-lib-micro/ratelimits" "time" "github.com/mendersoftware/go-lib-micro/config" @@ -103,6 +106,146 @@ func listTenants(db *mongo.DataStoreMongo) error { return nil } +func Diag( + tenant string, + listAll bool, + deviceId string, + insert bool, + delete string, + dryRunFlag bool, +) error { + fmt.Println("deviceauth diagnostics.") + fmt.Println("connecting to db") + db, err := mongo.NewDataStoreMongo(makeDataStoreConfig()) + if err != nil { + fmt.Printf("failed to connect to mongourl: %s\n", config.Config.GetString(dconfig.SettingDb)) + return errors.Wrap(err, "failed to connect to db") + } + fmt.Printf("connected to mongourl: %s\n", config.Config.GetString(dconfig.SettingDb)) + ctx, cancel := context.WithTimeout(context.Background(), 32*time.Second) + defer cancel() + if listAll { + var tenants []string + if len(tenant)>0 { + tenants=[]string{tenant} + } else { + tenants, err = db.ListTenantsIds(context.Background()) + if err != nil { + fmt.Printf("error looking for all tenants: %s\n", err.Error()) + } + } + fmt.Printf("looking for all devices for all %d tenants\n", len(tenants)) + + for _, t := range tenants { + ctx = context.Background() + ctx = identity.WithContext(ctx, &identity.Identity{ + Tenant: t, + }) + devices, err := db.GetDevices(ctx, 0, 8388480, model.DeviceFilter{}) + if err != nil { + fmt.Printf("error looking for devices: %s\n", err.Error()) + } + fmt.Printf("listing all %d devices for tenant %s\n", len(devices), t) + for _, d := range devices { + fmt.Printf("%s\n", d.Id) + } + } + return nil + } + if len(deviceId) < 1 { + + } else { + fmt.Printf("checking device of id: %s\n", deviceId) + ctx = identity.WithContext(ctx, &identity.Identity{ + Tenant: tenant, + }) + device, err := db.GetDeviceById(ctx, deviceId) + if err != nil { + fmt.Printf("error looking for device of id: %s; %s\n", deviceId, err.Error()) + } + if device == nil { + fmt.Printf("cant find device of id: %s\n", deviceId) + tenants, err := db.ListTenantsIds(context.Background()) + if err != nil { + fmt.Printf("error looking for all tenants: %s\n", err.Error()) + } + fmt.Printf("looking for all devices for all %d tenants\n", len(tenants)) + + for _, t := range tenants { + ctx = context.Background() + ctx = identity.WithContext(ctx, &identity.Identity{ + Tenant: t, + }) + devices, err := db.GetDevices(ctx, 0, 8388480, model.DeviceFilter{}) + if err != nil { + fmt.Printf("error looking for devices: %s\n", err.Error()) + } + fmt.Printf("listing all %d devices for tenant %s\n", len(devices), t) + for _, d := range devices { + fmt.Printf("%s\n", d.Id) + } + } + // now delete a device, insert a dummy device + } + if device != nil { + jsonDevice, _ := json.MarshalIndent(*device, "", " ") + fmt.Printf("found device: +%v\n%s\n", *device, string(jsonDevice)) + } + } + if insert { + ctx = identity.WithContext(ctx, &identity.Identity{ + Tenant: tenant, + }) + newId := oid.NewUUIDv4().String() + fmt.Printf("adding a device: %s\n", newId) + err = db.AddDevice(ctx, model.Device{ + Id: newId, + IdData: "some-id" + newId, + IdDataStruct: map[string]interface{}{"some-id-k0": "some-id-v0"}, + IdDataSha256: []byte("some-hash" + newId), + Status: "preauthorized", + Decommissioning: false, + CreatedTs: time.Now(), + UpdatedTs: time.Now(), + AuthSets: nil, + CheckInTime: nil, + ApiLimits: ratelimits.ApiLimits{}, + Revision: 0, + TenantID: tenant, + }) + if err != nil { + fmt.Printf("failed to add a device: %s\n", err.Error()) + } else { + device, err := db.GetDeviceById(ctx, newId) + if err != nil { + fmt.Printf("failed to get the just added device: %s\n", err.Error()) + } else { + if device == nil { + fmt.Printf("cant find the just added device\n") + } else { + jsonDevice, _ := json.MarshalIndent(*device, "", " ") + fmt.Printf("found just added device: +%v\n%s\n", *device, jsonDevice) + if len(delete) > 0 { + if delete != "%inserted" { + newId = delete + } + fmt.Printf("removing inserted device %s\n", newId) + err = db.DeleteDevice(ctx, newId) + fmt.Printf("removing inserted device rc:%+v\n", err) + device, err = db.GetDeviceById(ctx, newId) + fmt.Printf("getting inserted-removed device rc:%+v\n", err) + if device != nil { + jsonDevice, _ = json.MarshalIndent(*device, "", " ") + fmt.Printf("(!) found just removed device: +%v\n%s\n", *device, jsonDevice) + } + } + } + } + } + } + return nil +} + func Maintenance(decommissioningCleanupFlag bool, tenant string, dryRunFlag bool) error { db, err := mongo.NewDataStoreMongo(makeDataStoreConfig()) if err != nil { diff --git a/devauth/devauth.go b/devauth/devauth.go index 0877c4c0..3b39a1e7 100644 --- a/devauth/devauth.go +++ b/devauth/devauth.go @@ -791,7 +791,7 @@ func (d *DevAuth) DecommissionDevice(ctx context.Context, devID string) error { // set decommissioning flag on the device updev := model.DeviceUpdate{ - Decommissioning: uto.BoolPtr(true), + Decommissioning: uto.BoolPtr(true), // here } if err := d.db.UpdateDevice( ctx, devID, updev, @@ -822,7 +822,7 @@ func (d *DevAuth) DecommissionDevice(ctx context.Context, devID string) error { } // Delete a device and its tokens from deviceauth db -func (d *DevAuth) DeleteDevice(ctx context.Context, devID string) error { +func (d *DevAuth) DeleteDevice(ctx context.Context, devID string) error { // here // delete device authorization sets if err := d.db.DeleteAuthSetsForDevice(ctx, devID); err != nil && err != store.ErrAuthSetNotFound { diff --git a/main.go b/main.go index a4053890..e7078cf6 100644 --- a/main.go +++ b/main.go @@ -154,6 +154,39 @@ func doMain(args []string) { Action: cmdPropagateReporting, }, + { + Name: "diag", + Usage: "Run basic tests and exit", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "tenant", + Usage: "Tenant ID (optional).", + }, + cli.BoolFlag{ + Name: "list-all", + Usage: "list all devices in all tenants.", + }, + cli.StringFlag{ + Name: "dev-id", + Usage: "Device ID (optional).", + }, + cli.BoolFlag{ + Name: "insert", + Usage: "insert a device.", + }, + cli.StringFlag{ + Name: "delete", + Usage: "delete the given device.", + }, + cli.BoolFlag{ + Name: "dry-run", + Usage: "Do not perform any modifications and serves" + + " only as a way to inspect changes and detect if any are necessary", + }, + }, + + Action: cmdDiag, + }, { Name: "maintenance", Usage: "Run maintenance operations and exit", @@ -174,7 +207,8 @@ func doMain(args []string) { }, Action: cmdMaintenance, - }, { + }, + { Name: "check-device-limits", Usage: "Warn users if user is approaching device limit", Description: "Loops through all tenant databases and " + @@ -279,6 +313,21 @@ func cmdMaintenance(args *cli.Context) error { return nil } +func cmdDiag(args *cli.Context) error { + err := cmd.Diag( + args.String("tenant"), + args.Bool("list-all"), + args.String("dev-id"), + args.Bool("insert"), + args.String("delete"), + args.Bool("dry-run"), + ) + if err != nil { + return cli.NewExitError(err, 6) + } + return nil +} + func cmdPropagateStatusesInventory(args *cli.Context) error { db, err := mongo.NewDataStoreMongo(makeDataStoreConfig()) if err != nil {