Skip to content
Draft
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
9 changes: 9 additions & 0 deletions internal/commands/activate/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/device-management-toolkit/rpc-go/v2/internal/device"
"github.com/device-management-toolkit/rpc-go/v2/internal/orchestrator"
"github.com/device-management-toolkit/rpc-go/v2/internal/profile"
"github.com/device-management-toolkit/rpc-go/v2/pkg/utils"
log "github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -412,6 +413,13 @@ func (cmd *ActivateCmd) addDeviceToConsole(ctx *commands.Context, consoleBaseURL

useTLS, allowSelfSigned := cmd.resolveTLSFlags(cfg)

isLMSAvailable := false
if cmd.WSMan != nil {
isLMSAvailable = cmd.WSMan.IsLMSAvailable()
} else {
isLMSAvailable = utils.DetectLMS(cmd.LocalTLSEnforced)
}

payload := device.DevicePayload{
GUID: guid,
Hostname: hostname,
Expand All @@ -422,6 +430,7 @@ func (cmd *ActivateCmd) addDeviceToConsole(ctx *commands.Context, consoleBaseURL
MEBXPassword: mebxPassword,
UseTLS: useTLS,
AllowSelfSigned: allowSelfSigned,
IsLMSAvailable: isLMSAvailable,
}

if hasCIRA {
Expand Down
30 changes: 16 additions & 14 deletions internal/commands/amtinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,14 @@ type syncPayload struct {
}

type syncDeviceInfo struct {
FWVersion string `json:"fwVersion"`
FWBuild string `json:"fwBuild"`
FWSku string `json:"fwSku"`
CurrentMode string `json:"currentMode"`
Features string `json:"features"`
IPAddress string `json:"ipAddress"`
LastUpdated time.Time `json:"lastUpdated"`
FWVersion string `json:"fwVersion"`
FWBuild string `json:"fwBuild"`
FWSku string `json:"fwSku"`
CurrentMode string `json:"currentMode"`
Features string `json:"features"`
IPAddress string `json:"ipAddress"`
LastUpdated time.Time `json:"lastUpdated"`
LMSInstalled bool `json:"lmsInstalled"`
}

// SyncDeviceInfo sends a PATCH to the provided endpoint URL with the device info payload
Expand All @@ -397,13 +398,14 @@ func (s *InfoService) SyncDeviceInfo(ctx *Context, result *InfoResult, urlArg st
payload := syncPayload{
GUID: result.UUID,
DeviceInfo: syncDeviceInfo{
FWVersion: result.AMT,
FWBuild: result.BuildNumber,
FWSku: result.SKU,
CurrentMode: result.ControlMode,
Features: result.Features,
IPAddress: bestIPAddress(result),
LastUpdated: time.Now(),
FWVersion: result.AMT,
FWBuild: result.BuildNumber,
FWSku: result.SKU,
CurrentMode: result.ControlMode,
Features: result.Features,
IPAddress: bestIPAddress(result),
LastUpdated: time.Now(),
LMSInstalled: utils.DetectLMS(s.localTLSEnforced),
},
}

Expand Down
1 change: 1 addition & 0 deletions internal/device/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type DevicePayload struct {
MPSPassword string `json:"mpspassword,omitempty"`
UseTLS bool `json:"useTLS"`
AllowSelfSigned bool `json:"allowSelfSigned"`
IsLMSAvailable bool `json:"isLMSAvailable"`
}

// AddDevice registers a device via POST to the devices API endpoint.
Expand Down
1 change: 1 addition & 0 deletions internal/interfaces/wsman.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

type WSMANer interface {
SetupWsmanClient(username, password string, useTLS, logAMTMessages bool, tlsConfig *cryptotls.Config) error
IsLMSAvailable() bool
Close() error
Unprovision(int) (setupandconfiguration.Response, error)
PartialUnprovision() (setupandconfiguration.Response, error)
Expand Down
13 changes: 13 additions & 0 deletions internal/local/amt/wsman.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type GoWSMANMessages struct {
wsmanMessages wsman.Messages
target string
localTransport *LocalTransport
lmsAvailable bool
}

func NewGoWSMANMessages(lmsAddress string) *GoWSMANMessages {
Expand Down Expand Up @@ -78,6 +79,8 @@ func (g *GoWSMANMessages) SetupWsmanClient(username, password string, useTLS, lo
LogAMTMessages: logAMTMessages,
}

g.lmsAvailable = false

probeTimeout := time.Duration(utils.LMSDialerTimeout) * time.Second

if clientParams.UseTLS {
Expand All @@ -97,6 +100,8 @@ func (g *GoWSMANMessages) SetupWsmanClient(username, password string, useTLS, lo
} else {
logrus.Debug("Successfully connected to LMS.")

g.lmsAvailable = true

Comment thread
sinchubhat marked this conversation as resolved.
if tlsConn, ok := conn.(*cryptotls.Conn); ok {
state := tlsConn.ConnectionState()
cert := state.PeerCertificates[0]
Expand All @@ -119,6 +124,9 @@ func (g *GoWSMANMessages) SetupWsmanClient(username, password string, useTLS, lo
clientParams.Transport = g.localTransport
} else {
logrus.Debug("Successfully connected to LMS.")

g.lmsAvailable = true

con.Close()
}
}
Expand All @@ -128,6 +136,11 @@ func (g *GoWSMANMessages) SetupWsmanClient(username, password string, useTLS, lo
return nil
}

// IsLMSAvailable returns whether LMS was reachable during the last SetupWsmanClient call.
func (g *GoWSMANMessages) IsLMSAvailable() bool {
return g.lmsAvailable
}

// Close closes any open local transport connections
func (g *GoWSMANMessages) Close() error {
if g.localTransport != nil {
Expand Down
43 changes: 43 additions & 0 deletions internal/local/amt/wsman_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,46 @@
**********************************************************************/

package amt

import (
"context"
"net"
"testing"

"github.com/device-management-toolkit/rpc-go/v2/pkg/utils"
"github.com/stretchr/testify/assert"
)

func TestIsLMSAvailable_DefaultFalse(t *testing.T) {
g := NewGoWSMANMessages(utils.LMSAddress)
assert.False(t, g.IsLMSAvailable(), "should be false before SetupWsmanClient is called")
}

func TestIsLMSAvailable_TrueWhenLMSListening(t *testing.T) {
// Start a temporary TCP listener simulating LMS on port 16992.
lc := &net.ListenConfig{}

ln, err := lc.Listen(context.Background(), "tcp4", "127.0.0.1:"+utils.LMSPort)
if err != nil {
t.Skipf("cannot bind to port %s (may be in use): %v", utils.LMSPort, err)
}
Comment thread
sinchubhat marked this conversation as resolved.
defer ln.Close()

go func() {
for {
conn, err := ln.Accept()
if err != nil {
return
}

conn.Close()
}
}()

g := NewGoWSMANMessages(utils.LMSAddress)

// SetupWsmanClient with dummy credentials — the TCP probe happens before auth.
err = g.SetupWsmanClient("admin", "password", false, false, nil)
assert.NoError(t, err)
assert.True(t, g.IsLMSAvailable(), "should be true when LMS port is reachable")
}
42 changes: 28 additions & 14 deletions internal/mocks/wsman_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions internal/rps/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type MessagePayload struct {
FriendlyName string `json:"friendlyName,omitempty"`
TLSEnforced bool `json:"tlsEnforced,omitempty"`
TLSTunnel bool `json:"tlsTunnel,omitempty"`
LMSInstalled bool `json:"lmsInstalled"`
}

// MethodTLSData is the method type for TLS tunnel data passthrough
Expand Down Expand Up @@ -240,6 +241,7 @@ func (p Payload) CreateMessageRequest(req Request) (Message, error) {
payload.FriendlyName = req.FriendlyName
payload.TLSEnforced = req.LocalTlsEnforced
payload.TLSTunnel = req.TLSTunnel
payload.LMSInstalled = utils.DetectLMS(req.LocalTlsEnforced)

// convert struct to json
data, err := json.Marshal(payload)
Expand Down
32 changes: 32 additions & 0 deletions pkg/utils/lms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*********************************************************************
* Copyright (c) Intel Corporation 2026
* SPDX-License-Identifier: Apache-2.0
**********************************************************************/

package utils

import (
"context"
"net"
"time"
)

// DetectLMS probes the local LMS port to determine if Intel LMS is running.
// It uses the TLS port when localTLSEnforced is true.
func DetectLMS(localTLSEnforced bool) bool {
port := LMSPort
if localTLSEnforced {
port = LMSTLSPort
}

dialer := &net.Dialer{Timeout: time.Duration(LMSDialerTimeout) * time.Second}

conn, err := dialer.DialContext(context.Background(), "tcp4", net.JoinHostPort(LMSAddress, port))
if err != nil {
return false
}

conn.Close()

return true
}
Loading