Skip to content

Load mei kernel module and start lms from PMA #172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 82 commits into from
Jul 30, 2025
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
2d1b94d
Implement GRPC Connection
Rashika-Rajaraman Jul 17, 2025
4a7c255
Add API implementation
Rashika-Rajaraman Jul 18, 2025
30746f4
Fix review comments
Rashika-Rajaraman Jul 18, 2025
0b2cb72
Fix review comments
Rashika-Rajaraman Jul 18, 2025
c1c300d
Add ticker for periodic activation check
Rashika-Rajaraman Jul 18, 2025
b03045a
Fix review comments
Rashika-Rajaraman Jul 21, 2025
b8de271
Rebase main
Rashika-Rajaraman Jul 21, 2025
02bf4fc
Send activation results back to dm-manager
Rashika-Rajaraman Jul 21, 2025
d6359cb
Add license check
Rashika-Rajaraman Jul 21, 2025
7ab4d1d
Load mei_me kernel module
punam20 Jul 21, 2025
a206fd1
Enable LMS service
punam20 Jul 21, 2025
8d2a9ad
Merge branch 'main' into grpc-implementation
Rashika-Rajaraman Jul 22, 2025
f96818e
Fix review comments
Rashika-Rajaraman Jul 22, 2025
d289ff6
Fix review comments
Rashika-Rajaraman Jul 22, 2025
06116e6
Load mei module and start LMS service
punam20 Jul 22, 2025
5e356c6
Fix lint error
punam20 Jul 22, 2025
d5ecd8c
Updated code based on review comments
punam20 Jul 22, 2025
2833ef1
Fis review comments
punam20 Jul 22, 2025
1f62f62
unmask lms service
punam20 Jul 22, 2025
22268ca
Fix minor issues
Rashika-Rajaraman Jul 23, 2025
c09b02e
Add test files
Rashika-Rajaraman Jul 23, 2025
1cd7c98
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 23, 2025
1fd0ee7
Fix lint issues
Rashika-Rajaraman Jul 23, 2025
adef6c9
Rename cert files
Rashika-Rajaraman Jul 23, 2025
fc2dcb9
Fix vulnerability issue
Rashika-Rajaraman Jul 23, 2025
01ba5f8
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 23, 2025
afeb2d3
Fix vulnerability issue
Rashika-Rajaraman Jul 23, 2025
9f76f4c
Add .gitleaksignore for test certificates
Rashika-Rajaraman Jul 23, 2025
4b2517c
Fix review comment
Rashika-Rajaraman Jul 23, 2025
38bdddd
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 23, 2025
1778bb5
Merge branch 'main' into grpc-implementation
punam20 Jul 23, 2025
07e06b8
Fix commands
Rashika-Rajaraman Jul 23, 2025
cbcf693
Fix commands
Rashika-Rajaraman Jul 23, 2025
ac2e720
Merge branch 'main' into grpc-implementation
punam20 Jul 23, 2025
55b4ee2
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 23, 2025
a3fb878
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 23, 2025
2bbf051
Add license header
Rashika-Rajaraman Jul 24, 2025
3eb5754
Add more logs
Rashika-Rajaraman Jul 24, 2025
7913a74
fix sudoer and DM manager connection issue
vthiruveedula Jul 24, 2025
d31fa28
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 24, 2025
e560ec3
Fix bug
Rashika-Rajaraman Jul 24, 2025
821d057
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 24, 2025
207814d
Fix access token issue
punam20 Jul 24, 2025
8ec0377
Enable lms only once
punam20 Jul 25, 2025
602b6a9
Change AMT status report to be called once
Rashika-Rajaraman Jul 25, 2025
dcc9b55
Handle grpc status code
Rashika-Rajaraman Jul 25, 2025
e32dbd4
Merge branch 'main' into grpc-implementation
Rashika-Rajaraman Jul 25, 2025
ec21da7
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 25, 2025
3103b94
Fix AMT Status
Rashika-Rajaraman Jul 25, 2025
2c5bd08
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 25, 2025
d4762fd
Adding rpsAddress changes
punam20 Jul 25, 2025
1a92656
fix for review comments
punam20 Jul 25, 2025
bb00344
Fix review comments
Rashika-Rajaraman Jul 28, 2025
90f06cd
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 28, 2025
21eff5a
Update PMA version
Rashika-Rajaraman Jul 28, 2025
f0225ef
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 28, 2025
bfd2078
Fix lint issues
Rashika-Rajaraman Jul 28, 2025
27424fa
Fix .gitleaksignore file
Rashika-Rajaraman Jul 28, 2025
619c004
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 28, 2025
31a3a1d
Add .semgrepignore file
Rashika-Rajaraman Jul 29, 2025
4edd809
Add specific rule
Rashika-Rajaraman Jul 29, 2025
cb56054
Change the .semgrepignore format
Rashika-Rajaraman Jul 29, 2025
0fe4f9a
Try various semgrepignore formats
Rashika-Rajaraman Jul 29, 2025
9ab6e5a
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 29, 2025
ed53be9
Add rule in .semgrepignore file
Rashika-Rajaraman Jul 29, 2025
fe85f67
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 29, 2025
e5eb023
Merge branch 'main' into grpc-implementation
Rashika-Rajaraman Jul 29, 2025
96fb585
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 29, 2025
1f3085c
Merge branch 'main' into grpc-implementation
Rashika-Rajaraman Jul 29, 2025
b9c8beb
Add debug logs
Rashika-Rajaraman Jul 29, 2025
6a170d2
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 29, 2025
acd2c0b
Add FIXME comment
Rashika-Rajaraman Jul 29, 2025
cb43a23
Merge branch 'main' into grpc-implementation
Rashika-Rajaraman Jul 30, 2025
ab23369
Remove .semgrepignore file
Rashika-Rajaraman Jul 30, 2025
e59412a
Merge branch 'grpc-implementation' into mei_lms_changes
punam20 Jul 30, 2025
0291ae7
Merge branch 'main' into mei_lms_changes
punam20 Jul 30, 2025
792f3b9
fix indentation
punam20 Jul 30, 2025
840f558
Update version and cleanup code
Rashika-Rajaraman Jul 30, 2025
b347f8c
Changing rpc path to /usr/bin/rpc
punam20 Jul 30, 2025
6028107
Bump NA version
punam20 Jul 30, 2025
a394701
Update en manifest file with NA and PMA version
punam20 Jul 30, 2025
4290c4d
Bump EN manifest tag
punam20 Jul 30, 2025
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
2 changes: 1 addition & 1 deletion ena-manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ packages:
version: 1.7.2
ociArtifact: edge-orch/en/deb/node-agent
- name: platform-manageability-agent
version: 0.1.2
version: 0.1.3
ociArtifact: edge-orch/en/deb/platform-manageability-agent
- name: platform-observability-agent
version: 1.8.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ include <tunables/global>
owner /etc/intel_edge_node/tokens/node-agent/access_token rw,
owner /etc/intel_edge_node/tokens/platform-observability-agent/access_token rw,
owner /etc/intel_edge_node/tokens/platform-telemetry-agent/access_token rw,
owner /etc/intel_edge_node/tokens/platform-manageability-agent/access_token rw,
owner /etc/intel_edge_node/tokens/platform-update-agent/access_token rw,
owner /etc/intel_edge_node/tokens/prometheus/access_token rw,
owner /etc/intel_edge_node/tokens/release-service/access_token rw,
Expand Down
2 changes: 1 addition & 1 deletion node-agent/configs/node-agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ auth:
rsTokenURL: token-provider.edgeorch.intel.com
accessTokenPath: /etc/intel_edge_node/tokens
clientCredsPath: /etc/intel_edge_node/client-credentials
tokenClients: [ node-agent, hd-agent, cluster-agent, platform-update-agent, platform-observability-agent, platform-telemetry-agent, prometheus, connect-agent, attestation-manager ]
tokenClients: [ node-agent, hd-agent, cluster-agent, platform-update-agent, platform-observability-agent, platform-telemetry-agent, prometheus, connect-agent, attestation-manager, platform-manageability-agent ]
1 change: 1 addition & 0 deletions node-agent/debian/dirs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ etc/intel_edge_node/tokens/node-agent
etc/intel_edge_node/tokens/platform-observability-agent
etc/intel_edge_node/tokens/platform-telemetry-agent
etc/intel_edge_node/tokens/platform-update-agent
etc/intel_edge_node/tokens/platform-manageability-agent
etc/intel_edge_node/tokens/prometheus
etc/intel_edge_node/tokens/release-service
run/node-agent
2 changes: 1 addition & 1 deletion platform-manageability-agent/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.2
0.1.3
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"os"
"os/signal"
"strings"
"sync"
"sync/atomic"
"syscall"
Expand Down Expand Up @@ -39,7 +40,12 @@ const (
AMTStatusEnabled int32 = 1
)

var isAMTEnabled int32
var (
log = logger.Logger

isAMTEnabled int32
isModuleAndServiceInitialized int32
)

func isAMTCurrentlyEnabled() bool {
return atomic.LoadInt32(&isAMTEnabled) == AMTStatusEnabled
Expand All @@ -51,7 +57,6 @@ func main() {
os.Exit(0)
}

var log = logger.Logger
log.Infof("Starting Platform Manageability Agent")

// Initialize configuration
Expand Down Expand Up @@ -117,13 +122,13 @@ func main() {

log.Info("Platform Manageability Agent started successfully")

tlsConfig, err := auth.GetAuthConfig(auth.GetAuthContext(ctx, confs.AccessTokenPath), nil)
tlsConfig, err := auth.GetAuthConfig(ctx, nil)
if err != nil {
log.Fatalf("TLS configuration creation failed! Error: %v", err)
}

log.Infof("Connecting to Device Management Manager at %s", confs.Manageability.ServiceURL)
dmMgrClient := comms.ConnectToDMManager(auth.GetAuthContext(ctx, confs.AccessTokenPath), confs.Manageability.ServiceURL, tlsConfig)
dmMgrClient := comms.ConnectToDMManager(ctx, confs.Manageability.ServiceURL, tlsConfig)

hostID, err := utils.GetSystemUUID()
if err != nil {
Expand All @@ -137,16 +142,30 @@ func main() {

op := func() error {
log.Infof("Reporting AMT status for host %s", hostID)
status, err := dmMgrClient.ReportAMTStatus(ctx, hostID)
status, err := dmMgrClient.ReportAMTStatus(auth.GetAuthContext(ctx, confs.AccessTokenPath), hostID)
if err != nil {
log.Errorf("Failed to report AMT status for host %s: %v", hostID, err)
return fmt.Errorf("failed to report AMT status: %w", err)
}

switch status {
case pb.AMTStatus_DISABLED:
atomic.StoreInt32(&isAMTEnabled, AMTStatusDisabled)
case pb.AMTStatus_ENABLED:
atomic.StoreInt32(&isAMTEnabled, AMTStatusEnabled)
if atomic.CompareAndSwapInt32(&isModuleAndServiceInitialized, 0, 1) {
if err := loadModule(); err != nil {
log.Errorf("Error while loading module: %v", err)
} else {
log.Info("Module mei_me loaded successfully")
}
for _, action := range []string{"unmask", "enable", "start"} {
log.Infof("%sing %s...\n", action, "lms.service")
if err := enableService(action); err != nil {
log.Errorf("Error while enabling service: %v", err)
}
}
}
default:
log.Warnf("Unknown AMT status: %v, treating as disabled", status)
atomic.StoreInt32(&isAMTEnabled, AMTStatusDisabled)
Expand Down Expand Up @@ -185,7 +204,7 @@ func main() {
// FIXME: https://github.com/open-edge-platform/edge-node-agents/pull/170#discussion_r2236433075
// The suggestion is to combine the activation check and retrieval of activation details into a single call
// to reduce the number of RPC calls.
err = dmMgrClient.RetrieveActivationDetails(ctx, hostID, confs)
err = dmMgrClient.RetrieveActivationDetails(auth.GetAuthContext(ctx, confs.AccessTokenPath), hostID, confs)
if err != nil {
if errors.Is(err, comms.ErrActivationSkipped) {
log.Logger.Debugf("AMT activation skipped for host %s - reason: %v", hostID, err)
Expand Down Expand Up @@ -269,6 +288,45 @@ func main() {
log.Infof("Platform Manageability Agent finished")
}

func enableService(action string) error {
allowedActions := map[string]bool{"unmask": true, "enable": true, "start": true}

if !allowedActions[action] {
return fmt.Errorf("invalid service details")
}

// Check if the service is already running
output, err := utils.ExecuteCommand("systemctl", []string{"is-active", "lms.service"})
if err == nil && strings.TrimSpace(string(output)) == "active" {
log.Infof("Service %s is already running, skipping %s operation", "lms.service", action)
return nil
}

output, err = utils.ExecuteCommand("sudo", []string{"systemctl", action, "lms.service"})
if err != nil {
return fmt.Errorf("failed to %s %s: %v", action, "lms.service", err)
}
log.Infof("Service %s %s successfully: %s", "lms.service", action, string(output))
return nil
}

func loadModule() error {
// Check if the module is already loaded using lsmod | grep
output, err := utils.ExecuteCommand("sh", []string{"-c", "lsmod | grep mei_me"})
if err == nil && len(strings.TrimSpace(string(output))) > 0 {
log.Info("Module mei_me is already loaded, skipping load operation")
return nil
}

// Load the module if not already loaded
output, err = utils.ExecuteCommand("sudo", []string{"modprobe", "mei_me"})
if err != nil {
return fmt.Errorf("failed to load module %s: %v", "mei_me", err)
}
log.Infof("Module %s loaded successfully: %s", "mei_me", string(output))
return nil
}

func initStatusClientAndTicker(ctx context.Context, cancel context.CancelFunc, log *logrus.Entry, statusServer string) (*status.StatusClient, time.Duration) {
statusClient, err := status.InitClient(statusServer)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ logLevel: info
GUID: 'aaaaaaaa-0000-1111-2222-bbbbbbbbcccc'
manageability:
enabled: true
serviceURL: infra.test.edgeorch.intel.com:443
serviceURL: 'infra.test.edgeorch.intel.com:443'
heartbeatInterval: 10s
rpsAddress: 'rps.test.edgeorch.intel.com'
statusEndpoint: 'unix:///run/node-agent/node-agent.sock'
metricsEndpoint: 'unix:///run/platform-observability-agent/platform-observability-agent.sock'
metricsInterval: 10s
accessTokenPath: /etc/intel_edge_node/tokens
accessTokenPath: /etc/intel_edge_node/tokens/platform-manageability-agent/access_token
2 changes: 1 addition & 1 deletion platform-manageability-agent/configs/sudoers.d/pm-agent
Original file line number Diff line number Diff line change
@@ -1 +1 @@
platform-manageability-agent ALL=(root) NOPASSWD:/usr/bin/sh,/usr/bin/rpc,/usr/sbin/dmidecode
pm-agent ALL=(root) NOPASSWD:/usr/bin/rpc,/usr/sbin/dmidecode,/usr/bin/systemctl,/usr/sbin/modprobe
1 change: 1 addition & 0 deletions platform-manageability-agent/debian/install
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
configs/platform-manageability-agent.yaml etc/edge-node/node/confs
configs/sudoers.d/pm-agent etc/sudoers.d
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ RestartSec=60
Restart=on-failure
User=pm-agent
Group=bm-agents
User=platform-manageability-agent
CPUQuota=20%
MemoryMax=128M

Expand Down
12 changes: 11 additions & 1 deletion platform-manageability-agent/debian/postinst
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ set -e

. /usr/share/debconf/confmodule

db_get platform-manageability-agent/manageability.serviceURL
if [ ! -z "$RET" ]; then
sed -i "s/^ serviceURL: '.*'/ serviceURL: '$RET'/" /etc/edge-node/node/confs/platform-manageability-agent.yaml
fi

db_get platform-manageability-agent/rpsAddress
if [ ! -z "$RET" ]; then
sed -i "s/^rpsAddress: '.*'/rpsAddress: '$RET'/" /etc/edge-node/node/confs/platform-manageability-agent.yaml
fi

# Create system group if it doesn't exist
groupadd -f bm-agents --system

# Create system user if it doesn't exist
id -u platform-manageability-agent >/dev/null 2>&1 || useradd platform-manageability-agent --system -g bm-agents -s /sbin/nologin
id -u pm-agent >/dev/null 2>&1 || useradd pm-agent --system -g bm-agents -s /sbin/nologin

# Directory and permission setup is handled by node-agent

Expand Down
9 changes: 9 additions & 0 deletions platform-manageability-agent/debian/templates
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Template: platform-manageability-agent/manageability.serviceURL
Type: string
Default: localhost:443
Description: Onboarding service URL:

Template: platform-manageability-agent/rpsAddress
Type: string
Default: localhost
Description: RPS address:
14 changes: 12 additions & 2 deletions platform-manageability-agent/internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,24 @@ type CommandExecutor interface {

type RealCommandExecutor struct{}

func ExecuteCommand(command string, args []string) ([]byte, error) {
cmd := exec.Command(command, args...)
output, err := cmd.Output()
if err != nil {
log.Logger.Errorf("Failed to execute command %s with args %v: %v", command, args, err)
return nil, fmt.Errorf("failed to execute command %s with args %v: %w", command, args, err)
}
return output, nil
}

// ExecuteAMTInfo executes the AMT info command with retries.
func (r *RealCommandExecutor) ExecuteAMTInfo() ([]byte, error) {
maxRetries := 3
retryInterval := 5 * time.Second

var err error
for i := 1; i <= maxRetries; i++ {
cmd := exec.Command("sudo", "/etc/intel_edge_node/rpc", "amtinfo")
cmd := exec.Command("sudo", "/usr/bin/rpc", "amtinfo")
output, err := cmd.Output()
if err == nil {
return output, nil
Expand All @@ -43,7 +53,7 @@ func (r *RealCommandExecutor) ExecuteAMTInfo() ([]byte, error) {

// ExecuteAMTActivate executes the AMT activate command.
func (r *RealCommandExecutor) ExecuteAMTActivate(rpsAddress, profileName, password string) ([]byte, error) {
cmd := exec.Command("sudo", "/etc/intel_edge_node/rpc", "activate", "-u", rpsAddress, "-profile", profileName, "-password", password, "-n")
cmd := exec.Command("sudo", "/usr/bin/rpc", "activate", "-u", rpsAddress, "-profile", profileName, "-password", password, "-n")
return cmd.CombinedOutput()
}

Expand Down
Loading