Skip to content

Commit 1ff378d

Browse files
committed
wip(api,agent,ssh): devices
1 parent 1346770 commit 1ff378d

File tree

20 files changed

+228
-766
lines changed

20 files changed

+228
-766
lines changed

api/routes/sshkeys.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func (h *Handler) EvaluateKey(c gateway.Context) error {
160160
return c.JSON(http.StatusForbidden, err)
161161
}
162162

163-
pubKey, err := h.service.GetPublicKey(c.Ctx(), c.Param(ParamPublicKeyFingerprint), device.TenantID)
163+
pubKey, err := h.service.GetPublicKey(c.Ctx(), c.Param(ParamPublicKeyFingerprint), device.NamespaceID)
164164
if err != nil {
165165
return c.JSON(http.StatusForbidden, err)
166166
}

api/services/auth.go

Lines changed: 47 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -68,119 +68,75 @@ type AuthService interface {
6868
}
6969

7070
func (s *service) AuthDevice(ctx context.Context, req requests.DeviceAuth, remoteAddr string) (*models.DeviceAuthResponse, error) {
71-
var identity *models.DeviceIdentity
72-
if req.Identity != nil {
73-
identity = &models.DeviceIdentity{
74-
MAC: req.Identity.MAC,
75-
}
71+
if _, err := s.store.NamespaceGet(ctx, store.NamespaceIdentID, req.TenantID); err != nil {
72+
return nil, NewErrNamespaceNotFound(req.TenantID, err)
7673
}
7774

78-
var hostname string
79-
if req.Hostname != "" {
80-
hostname = req.Hostname
81-
}
75+
if req.Hostname == "" {
76+
if req.Identity == nil || req.Identity.MAC == "" {
77+
return nil, NewErrAuthDeviceNoIdentityAndHostname()
78+
}
8279

83-
if hostname == "" && (identity == nil || identity.MAC == "") {
84-
return nil, NewErrAuthDeviceNoIdentityAndHostname()
80+
req.Hostname = req.Identity.MAC
8581
}
8682

8783
auth := models.DeviceAuth{
88-
Hostname: hostname,
89-
Identity: identity,
84+
Hostname: req.Hostname,
85+
Identity: &models.DeviceIdentity{MAC: req.Identity.MAC},
9086
PublicKey: req.PublicKey,
9187
TenantID: req.TenantID,
9288
}
9389

94-
uid := sha256.Sum256(structhash.Dump(auth, 1))
95-
key := hex.EncodeToString(uid[:])
96-
97-
claims := authorizer.DeviceClaims{
98-
UID: key,
99-
TenantID: req.TenantID,
100-
}
101-
102-
token, err := jwttoken.EncodeDeviceClaims(claims, s.privKey)
90+
uidSHA := sha256.Sum256(structhash.Dump(auth, 1))
91+
device, err := s.store.DeviceGet(ctx, models.UID(hex.EncodeToString(uidSHA[:])))
10392
if err != nil {
104-
return nil, NewErrTokenSigned(err)
105-
}
106-
107-
type Device struct {
108-
Name string
109-
Namespace string
110-
}
111-
112-
var value *Device
113-
114-
if err := s.cache.Get(ctx, strings.Join([]string{"auth_device", key}, "/"), &value); err == nil && value != nil {
115-
return &models.DeviceAuthResponse{
116-
UID: key,
117-
Token: token,
118-
Name: value.Name,
119-
Namespace: value.Namespace,
120-
}, nil
121-
}
122-
var info *models.DeviceInfo
123-
if req.Info != nil {
124-
info = &models.DeviceInfo{
125-
ID: req.Info.ID,
126-
PrettyName: req.Info.PrettyName,
127-
Version: req.Info.Version,
128-
Arch: req.Info.Arch,
129-
Platform: req.Info.Platform,
93+
if err != store.ErrNoDocuments {
94+
return nil, err
13095
}
131-
}
13296

133-
position, err := s.locator.GetPosition(net.ParseIP(remoteAddr))
134-
if err != nil {
135-
return nil, err
136-
}
137-
138-
device := models.Device{
139-
UID: key,
140-
Identity: identity,
141-
Info: info,
142-
PublicKey: req.PublicKey,
143-
TenantID: req.TenantID,
144-
LastSeen: clock.Now(),
145-
RemoteAddr: remoteAddr,
146-
Position: &models.DevicePosition{
147-
Longitude: position.Longitude,
148-
Latitude: position.Latitude,
149-
},
150-
}
151-
152-
// The order here is critical as we don't want to register devices if the tenant id is invalid
153-
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentID, device.TenantID)
154-
if err != nil {
155-
return nil, NewErrNamespaceNotFound(device.TenantID, err)
156-
}
97+
position, err := s.locator.GetPosition(net.ParseIP(remoteAddr))
98+
if err != nil {
99+
return nil, err
100+
}
157101

158-
hostname = strings.ToLower(hostname)
102+
device = &models.Device{
103+
ID: hex.EncodeToString(uidSHA[:]),
104+
NamespaceID: req.TenantID,
105+
SeenAt: clock.Now(),
106+
DisconnectedAt: time.Time{},
107+
Status: models.DeviceStatusPending,
108+
Name: req.Hostname,
109+
MAC: req.Identity.MAC,
110+
PublicKey: req.PublicKey,
111+
Position: &models.DevicePosition{
112+
Longitude: position.Longitude,
113+
Latitude: position.Latitude,
114+
},
115+
Info: nil,
116+
}
159117

160-
if err := s.store.DeviceCreate(ctx, device, hostname); err != nil {
161-
return nil, NewErrDeviceCreate(device, err)
162-
}
118+
if req.Info != nil {
119+
device.Info = &models.DeviceInfo{
120+
ID: req.Info.ID,
121+
PrettyName: req.Info.PrettyName,
122+
Version: req.Info.Version,
123+
Arch: req.Info.Arch,
124+
Platform: req.Info.Platform,
125+
}
126+
}
163127

164-
for _, uid := range req.Sessions {
165-
if err := s.store.SessionSetLastSeen(ctx, models.UID(uid)); err != nil {
166-
continue
128+
if _, err := s.store.DeviceCreate(ctx, device); err != nil {
129+
return nil, NewErrDeviceCreate(*device, err)
167130
}
168131
}
169132

170-
dev, err := s.store.DeviceGetByUID(ctx, models.UID(device.UID), device.TenantID)
133+
claims := authorizer.DeviceClaims{UID: device.ID, TenantID: device.NamespaceID}
134+
token, err := jwttoken.EncodeDeviceClaims(claims, s.privKey)
171135
if err != nil {
172-
return nil, NewErrDeviceNotFound(models.UID(device.UID), err)
173-
}
174-
if err := s.cache.Set(ctx, strings.Join([]string{"auth_device", key}, "/"), &Device{Name: dev.Name, Namespace: namespace.Name}, time.Second*30); err != nil {
175-
return nil, err
136+
return nil, NewErrTokenSigned(err)
176137
}
177138

178-
return &models.DeviceAuthResponse{
179-
UID: key,
180-
Token: token,
181-
Name: dev.Name,
182-
Namespace: namespace.Name,
183-
}, nil
139+
return &models.DeviceAuthResponse{UID: device.ID, Token: token, Name: device.Name, Namespace: "dev"}, nil
184140
}
185141

186142
func (s *service) AuthLocalUser(ctx context.Context, req *requests.AuthLocalUser, sourceIP string) (*models.UserAuthResponse, int64, string, error) {

0 commit comments

Comments
 (0)