Compare commits

...

13 Commits

Author SHA1 Message Date
deviantony
540afcd179 Merge branch 'develop' into feat-fdo-1.1 2022-08-16 14:33:02 +00:00
deviantony
64b9207497 refactor(openamt): add review comment 2022-05-11 21:28:17 +00:00
deviantony
b3dbfd1a5e feat(openamt): add comment 2022-05-11 20:58:20 +00:00
deviantony
0f08005982 feat(openamt): fix an openamt issue with v2.1.0 2022-05-10 21:11:37 +00:00
deviantony
587ea7e8ea Merge branch 'develop' into feat-fdo-1.1 2022-05-10 20:51:42 +00:00
deviantony
fe82b23211 use v2.1.0 of oact-rpc-go 2022-05-10 03:18:37 +00:00
deviantony
6099a916b9 feat(openamt): use official intel rpc-go image 2022-05-10 02:41:11 +00:00
deviantony
3d9aae9760 feat(settings): allow empty edge URL 2022-05-10 01:49:20 +00:00
deviantony
1316168b6b Merge branch 'develop' into feat-fdo-1.1 2022-05-09 23:41:28 +00:00
deviantony
88042f9b39 feat(openamt): update saveCIRAConfig logic 2022-05-08 19:14:26 +00:00
deviantony
4515315f41 feat(openamt): update addressFormat logic 2022-05-08 18:32:40 +00:00
deviantony
00bd7c3d02 feat(fdo): update configure logic 2022-05-01 00:01:22 +00:00
deviantony
0b8adb690e feat(fdo): fdo 1.1 changes 2022-04-29 19:41:51 +00:00
6 changed files with 357 additions and 131 deletions

View File

@@ -2,11 +2,13 @@ package fdo
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
@@ -38,6 +40,10 @@ type ServiceInfo struct {
func (c FDOOwnerClient) doDigestAuthReq(method, endpoint, contentType string, body io.Reader) (*http.Response, error) {
transport := digest.NewTransport(c.Username, c.Password)
// TODO: REVIEW
// Temporary work-around to support sending requests to HTTPS AIO local setups
transport.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client, err := transport.Client()
if err != nil {
return nil, err
@@ -70,7 +76,7 @@ func (c FDOOwnerClient) PostVoucher(ov []byte) (string, error) {
resp, err := c.doDigestAuthReq(
http.MethodPost,
"api/v1/owner/vouchers",
"application/cbor",
"text/plain",
bytes.NewReader(ov),
)
if err != nil {
@@ -90,25 +96,69 @@ func (c FDOOwnerClient) PostVoucher(ov []byte) (string, error) {
return string(body), nil
}
func (c FDOOwnerClient) PutDeviceSVI(info ServiceInfo) error {
values := url.Values{}
values.Set("module", info.Module)
values.Set("var", info.Var)
values.Set("filename", info.Filename)
values.Set("guid", info.GUID)
values.Set("device", info.Device)
values.Set("priority", strconv.Itoa(info.Priority))
values.Set("os", info.OS)
values.Set("version", info.Version)
values.Set("arch", info.Arch)
values.Set("crid", strconv.Itoa(info.CRID))
values.Set("hash", info.Hash)
// func (c FDOOwnerClient) PutDeviceSVI(info ServiceInfo) error {
// values := url.Values{}
// values.Set("module", info.Module)
// values.Set("var", info.Var)
// values.Set("filename", info.Filename)
// values.Set("guid", info.GUID)
// values.Set("device", info.Device)
// values.Set("priority", strconv.Itoa(info.Priority))
// values.Set("os", info.OS)
// values.Set("version", info.Version)
// values.Set("arch", info.Arch)
// values.Set("crid", strconv.Itoa(info.CRID))
// values.Set("hash", info.Hash)
// resp, err := c.doDigestAuthReq(
// http.MethodPut,
// "api/v1/device/svi?"+values.Encode(),
// "application/octet-stream",
// strings.NewReader(string(info.Bytes)),
// )
// if err != nil {
// return err
// }
// defer resp.Body.Close()
// if resp.StatusCode != http.StatusOK {
// return errors.New(http.StatusText(resp.StatusCode))
// }
// return nil
// }
// Sending SVI instruction
// curl -D - --digest -u ${api_user}: --location --request POST 'http://localhost:8080/api/v1/owner/svi' --header 'Content-Type: text/plain' --data-raw '[{"filedesc" : "setup.sh","resource" : "URL"}, {"write": "content_string"} {"exec" : ["bash","setup.sh"] }]'
// Uploading resources
// curl -D - --digest -u ${api_user}: --location --request POST 'http://localhost:8080/api/v1/owner/resource?filename=fileName' --header 'Content-Type: text/plain' --data-binary '@< path to file >'
func SVIInstructionsToString(SVIInstructions []json.RawMessage) (string, error) {
data, err := json.Marshal(SVIInstructions)
if err != nil {
return "", err
}
return string(data), nil
}
// curl -k -D - --digest -u apiUser:U8MdQyV7W9TUXtG --location --request POST 'https://localhost:8443/api/v1/owner/svi' \
// --header 'Content-Type: text/plain' \
// --data-raw '[{"filedesc" : "sample.txt","resource" : "file.txt"}]'
// curl -k -D - --digest -u apiUser:U8MdQyV7W9TUXtG --location --request POST 'https://localhost:8443/api/v1/owner/resource?filename=file.txt' --header 'Content-Type: text/plain' --data-binary '@/tmp/file.txt'
func (c FDOOwnerClient) PostResource(fileName string, resourceContent []byte) error {
params := url.Values{
"filename": []string{fileName},
}
resp, err := c.doDigestAuthReq(
http.MethodPut,
"api/v1/device/svi?"+values.Encode(),
"application/octet-stream",
strings.NewReader(string(info.Bytes)),
http.MethodPost,
"api/v1/owner/resource?"+params.Encode(),
"text/plain",
bytes.NewReader(resourceContent),
)
if err != nil {
return err
@@ -122,12 +172,28 @@ func (c FDOOwnerClient) PutDeviceSVI(info ServiceInfo) error {
return nil
}
func (c FDOOwnerClient) PutDeviceSVIRaw(info url.Values, body []byte) error {
// TODO: REVIEW
// Review comments
// POST a SVI to the Owner service
// That SVI will instruct the device to retrieve a file called resourceName from the database and write it under the fileName path (in local process CWD? e.g. in agent CWD - not sure about that)
// To FileName
// From ResourceName
func (c FDOOwnerClient) PostSVI(fileName, resourceName string) error {
op1 := json.RawMessage([]byte(fmt.Sprintf(`{"filedesc" : "%s", "resource": "%s"}`, fileName, resourceName)))
data := []json.RawMessage{op1}
payload, err := SVIInstructionsToString(data)
if err != nil {
return err
}
resp, err := c.doDigestAuthReq(
http.MethodPut,
"api/v1/device/svi?"+info.Encode(),
"application/octet-stream",
strings.NewReader(string(body)),
http.MethodPost,
"api/v1/owner/svi",
"text/plain",
bytes.NewReader([]byte(payload)),
)
if err != nil {
return err
@@ -141,6 +207,59 @@ func (c FDOOwnerClient) PutDeviceSVIRaw(info url.Values, body []byte) error {
return nil
}
// POST a SVI to the Owner service
// That SVI will instruct the device to retrieve a file called resourceName from the database and write it under the fileName path (in local process CWD? e.g. in agent CWD - not sure about that)
// It will then instruct the device to execute a command afterwards
// To FileName
// From ResourceName
// func (c FDOOwnerClient) PostSVIFileExec(fileName, resourceName string, execCommand []string) error {
// op1 := json.RawMessage([]byte(fmt.Sprintf(`{"filedesc" : "%s", "resource": "%s"}`, fileName, resourceName)))
// op2 := json.RawMessage([]byte(fmt.Sprintf(`{"exec" : ["%s"]}`, strings.Join(execCommand, "\",\""))))
// data := []json.RawMessage{op1, op2}
// payload, err := SVIInstructionsToString(data)
// if err != nil {
// return err
// }
// resp, err := c.doDigestAuthReq(
// http.MethodPost,
// "api/v1/owner/svi",
// "text/plain",
// strings.NewReader(payload),
// )
// if err != nil {
// return err
// }
// defer resp.Body.Close()
// if resp.StatusCode != http.StatusOK {
// return errors.New(http.StatusText(resp.StatusCode))
// }
// return nil
// }
// func (c FDOOwnerClient) PutDeviceSVIRaw(info url.Values, body []byte) error {
// resp, err := c.doDigestAuthReq(
// http.MethodPut,
// "api/v1/device/svi?"+info.Encode(),
// "application/octet-stream",
// strings.NewReader(string(body)),
// )
// if err != nil {
// return err
// }
// defer resp.Body.Close()
// if resp.StatusCode != http.StatusOK {
// return errors.New(http.StatusText(resp.StatusCode))
// }
// return nil
// }
func (c FDOOwnerClient) GetVouchers() ([]string, error) {
resp, err := c.doDigestAuthReq(
http.MethodGet,

View File

@@ -8,11 +8,18 @@ import (
"io"
"net"
"net/http"
"net/url"
"strings"
portainer "github.com/portainer/portainer/api"
)
const (
addrFormatFQDN = 201
addrFormatIpv4 = 3
addrFormatIpv6 = 4
)
type CIRAConfig struct {
ConfigName string `json:"configName"`
MPSServerAddress string `json:"mpsServerAddress"`
@@ -70,15 +77,15 @@ func (service *Service) saveCIRAConfig(method string, configuration portainer.Op
return nil, err
}
addressFormat, err := addressFormat(configuration.MPSServer)
addressFormat, serverAddress, err := addressFormat(configuration.MPSServer)
if err != nil {
return nil, err
}
config := CIRAConfig{
ConfigName: configName,
MPSServerAddress: configuration.MPSServer,
CommonName: configuration.MPSServer,
MPSServerAddress: serverAddress,
CommonName: serverAddress,
ServerAddressFormat: addressFormat,
MPSPort: 4433,
Username: "admin",
@@ -101,18 +108,33 @@ func (service *Service) saveCIRAConfig(method string, configuration portainer.Op
return &result, nil
}
func addressFormat(url string) (int, error) {
ip := net.ParseIP(url)
if ip == nil {
return 201, nil // FQDN
// addressFormat returns the address format and the address for the given server address.
// when using a IP:PORT format, only the IP is returned.
// see https://github.com/open-amt-cloud-toolkit/rps/blob/b63e0112f8a6323764742165a2cd5b465d9a9a24/src/routes/admin/ciraconfig/ciraValidator.ts#L20-L25
func addressFormat(u string) (int, string, error) {
ip2 := net.ParseIP(u)
if ip2 != nil {
if ip2.To4() != nil {
return addrFormatIpv4, u, nil
}
return addrFormatIpv6, u, nil
}
if strings.Contains(url, ".") {
return 3, nil // IPV4
_, err := url.Parse(u)
if err == nil {
return addrFormatFQDN, u, nil
}
if strings.Contains(url, ":") {
return 4, nil // IPV6
host, _, err := net.SplitHostPort(u)
if err == nil {
if strings.Count(u, ":") >= 2 {
return addrFormatIpv6, host, nil
}
return addrFormatIpv4, host, nil
}
return 0, fmt.Errorf("could not determine server address format for %s", url)
return 0, "", fmt.Errorf("could not determine server address format for %s", u)
}
func (service *Service) getCIRACertificate(configuration portainer.OpenAMTConfiguration) (string, error) {

View File

@@ -1,13 +1,9 @@
package fdo
import (
"encoding/hex"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/fxamacker/cbor/v2"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@@ -17,7 +13,7 @@ import (
)
const (
deploymentScriptName = "fdo.sh"
deploymentScriptName = "fdo-profile.sh"
)
type deviceConfigurePayload struct {
@@ -95,94 +91,173 @@ func (handler *Handler) fdoConfigureDevice(w http.ResponseWriter, r *http.Reques
}
// enable fdo_sys
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"0"},
"module": []string{"fdo_sys"},
"var": []string{"active"},
"bytes": []string{"F5"}, // this is "true" in CBOR
}, []byte("")); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
// TODO: REVIEW
// This might not be needed anymore
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"0"},
// "module": []string{"fdo_sys"},
// "var": []string{"active"},
// "bytes": []string{"F5"}, // this is "true" in CBOR
// }, []byte("")); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
// }
// write down the edge id
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"1"},
// "module": []string{"fdo_sys"},
// "var": []string{"filedesc"},
// "filename": []string{"DEVICE_edgeid.txt"},
// }, []byte(payload.EdgeID)); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(edgeid)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(edgeid)", Err: err}
// }
const deviceConfiguration = `
GUID=%s
DEVICE_NAME=%s
EDGE_ID=%s
EDGE_KEY=%s
`
deviceConfData := fmt.Sprintf(deviceConfiguration, guid, payload.Name, payload.EdgeID, payload.EdgeKey)
deviceConfResourceName := fmt.Sprintf("%s-agent.conf", guid)
err = fdoClient.PostResource(deviceConfResourceName, []byte(deviceConfData))
if err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: UploadResource(DEVICE.conf)")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: UploadResource(DEVICE.conf)", Err: err}
}
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"1"},
"module": []string{"fdo_sys"},
"var": []string{"filedesc"},
"filename": []string{"DEVICE_edgeid.txt"},
}, []byte(payload.EdgeID)); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(edgeid)")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(edgeid)", Err: err}
}
// TODO: REVIEW
// I believe this will need a filter on GUID
// https://github.com/secure-device-onboard/pri-fidoiot/tree/1.1.0-rel/component-samples/demo/aio#service-info-filters
// err = fdoClient.PostSVIFile("DEVICE.conf", deviceConfResourceName)
// TODO: REVIEW whether the $guid shortcut works
// If that's the case - then potentially we only need to do this once
// and just do a PostResource here (the one above)
// That would mean that we would need to relocate this action to somewhere else (a setup process after enabling the FDO integration for example)
// err = fdoClient.PostSVI("DEVICE.conf", "$(guid)-DEVICE.conf")
// if err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PostSVIFile(DEVICE.conf)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PostSVIFile(DEVICE.conf)", Err: err}
// }
// write down the edgekey
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"1"},
"module": []string{"fdo_sys"},
"var": []string{"filedesc"},
"filename": []string{"DEVICE_edgekey.txt"},
}, []byte(payload.EdgeKey)); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(edgekey)")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(edgekey)", Err: err}
}
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"1"},
// "module": []string{"fdo_sys"},
// "var": []string{"filedesc"},
// "filename": []string{"DEVICE_edgekey.txt"},
// }, []byte(payload.EdgeKey)); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(edgekey)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(edgekey)", Err: err}
// }
// err = fdoClient.PostSVIFile("DEVICE_edgekey.txt", payload.EdgeKey)
// if err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PostSVIFile(edgekey)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PostSVIFile(edgekey)", Err: err}
// }
// write down the device name
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"1"},
"module": []string{"fdo_sys"},
"var": []string{"filedesc"},
"filename": []string{"DEVICE_name.txt"},
}, []byte(payload.Name)); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(name)")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(name)", Err: err}
}
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"1"},
// "module": []string{"fdo_sys"},
// "var": []string{"filedesc"},
// "filename": []string{"DEVICE_name.txt"},
// }, []byte(payload.Name)); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw(name)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw(name)", Err: err}
// }
// err = fdoClient.PostSVIFile("DEVICE_name.txt", payload.Name)
// if err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PostSVIFile(name)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PostSVIFile(name)", Err: err}
// }
// write down the device GUID - used as the EDGE_DEVICE_GUID too
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"1"},
"module": []string{"fdo_sys"},
"var": []string{"filedesc"},
"filename": []string{"DEVICE_GUID.txt"},
}, []byte(guid)); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
}
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"1"},
"module": []string{"fdo_sys"},
"var": []string{"filedesc"},
"filename": []string{deploymentScriptName},
}, fileContent); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
}
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"1"},
// "module": []string{"fdo_sys"},
// "var": []string{"filedesc"},
// "filename": []string{"DEVICE_GUID.txt"},
// }, []byte(guid)); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
// }
b, err := cbor.Marshal([]string{"/bin/sh", deploymentScriptName})
// err = fdoClient.PostSVIFile("DEVICE_GUID.txt", guid)
// if err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PostSVIFile(guid)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PostSVIFile(guid)", Err: err}
// }
// write down the profile script
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"1"},
// "module": []string{"fdo_sys"},
// "var": []string{"filedesc"},
// "filename": []string{deploymentScriptName},
// }, fileContent); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
// }
// b, err := cbor.Marshal([]string{"/bin/sh", deploymentScriptName})
// if err != nil {
// logrus.WithError(err).Error("failed to marshal string to CBOR")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw() failed to encode", Err: err}
// }
// cborBytes := strings.ToUpper(hex.EncodeToString(b))
// logrus.WithField("cbor", cborBytes).WithField("string", deploymentScriptName).Info("converted to CBOR")
// if err = fdoClient.PutDeviceSVIRaw(url.Values{
// "guid": []string{guid},
// "priority": []string{"2"},
// "module": []string{"fdo_sys"},
// "var": []string{"exec"},
// "bytes": []string{cborBytes},
// }, []byte("")); err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
// }
// TODO: REVIEW
// The PostResource and PostSVI steps probably can be done once just after creating the profile
// PostResource should also be done after removing a profile
// DelResource should also be done after deleting a profile
err = fdoClient.PostResource(deploymentScriptName, fileContent)
if err != nil {
logrus.WithError(err).Error("failed to marshal string to CBOR")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw() failed to encode", Err: err}
logrus.WithError(err).Info("fdoConfigureDevice: UploadResource(DEVICE.conf)")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: UploadResource(DEVICE.conf)", Err: err}
}
cborBytes := strings.ToUpper(hex.EncodeToString(b))
logrus.WithField("cbor", cborBytes).WithField("string", deploymentScriptName).Info("converted to CBOR")
if err = fdoClient.PutDeviceSVIRaw(url.Values{
"guid": []string{guid},
"priority": []string{"2"},
"module": []string{"fdo_sys"},
"var": []string{"exec"},
"bytes": []string{cborBytes},
}, []byte("")); err != nil {
logrus.WithError(err).Info("fdoConfigureDevice: PutDeviceSVIRaw()")
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PutDeviceSVIRaw()", Err: err}
}
// TODO: REVIEW
// Must be named OS_Install.sh to work with the BMO AIO setup
// This might need to be configurable in the future
// err = fdoClient.PostSVI("OS_Install.sh", deploymentScriptName)
// if err != nil {
// logrus.WithError(err).Info("fdoConfigureDevice: PostSVIFileExec(profile)")
// return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "fdoConfigureDevice: PostSVIFileExec(profile)", Err: err}
// }
return response.Empty(w)
}

View File

@@ -65,7 +65,7 @@ func (handler *Handler) newFDOClient() (fdo.FDOOwnerClient, error) {
OwnerURL: settings.FDOConfiguration.OwnerURL,
Username: settings.FDOConfiguration.OwnerUsername,
Password: settings.FDOConfiguration.OwnerPassword,
Timeout: 5 * time.Second,
Timeout: 10 * time.Second,
}, nil
}

View File

@@ -56,9 +56,19 @@ func (handler *Handler) openAMTActivate(w http.ResponseWriter, r *http.Request)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve AMT information", Err: err}
}
if hostInfo.ControlModeRaw < 1 {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Failed to activate device", Err: errors.New("failed to activate device")}
}
// TODO: REVIEW
// Should check here that the activation is OK (can check for control mode / RAS remote status)
// If not, ask the user to check the logs
// We should also check for the following logs in the service container
// INFO[0050] Status: Admin control mode., MEBx Password updated
// INFO[0050] Network: Ethernet Configured.
// INFO[0050] CIRA: Configured
// without the 0050 as it might change at runtime
// if these logs are not found, assume an error and don't remove the service container as it will be useful for troubleshooting
// consider redirecting these logs to portainer
if hostInfo.UUID == "" {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve device UUID", Err: errors.New("unable to retrieve device UUID")}
}

View File

@@ -4,12 +4,13 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/portainer/portainer/api/hostmanagement/openamt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/portainer/portainer/api/hostmanagement/openamt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
@@ -25,19 +26,18 @@ import (
)
type HostInfo struct {
EndpointID portainer.EndpointID `json:"EndpointID"`
RawOutput string `json:"RawOutput"`
AMT string `json:"AMT"`
UUID string `json:"UUID"`
DNSSuffix string `json:"DNS Suffix"`
BuildNumber string `json:"Build Number"`
ControlMode string `json:"Control Mode"`
ControlModeRaw int `json:"Control Mode (Raw)"`
EndpointID portainer.EndpointID `json:"EndpointID"`
RawOutput string `json:"RawOutput"`
AMT string `json:"AMT"`
UUID string `json:"UUID"`
DNSSuffix string `json:"DNS Suffix"`
BuildNumber string `json:"Build Number"`
ControlMode string `json:"Control Mode"`
}
const (
// TODO: this should get extracted to some configurable - don't assume Docker Hub is everyone's global namespace, or that they're allowed to pull images from the internet
rpcGoImageName = "ptrrd/openamt:rpc-go-json"
rpcGoImageName = "intel/oact-rpc-go:v2.1.0"
rpcGoContainerName = "openamt-rpc-go"
dockerClientTimeout = 5 * time.Minute
)