feat(openamt): initial setup and create default CIRA config
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/portainer/portainer/api/cli"
|
||||
"github.com/portainer/portainer/api/crypto"
|
||||
"github.com/portainer/portainer/api/docker"
|
||||
"github.com/portainer/portainer/api/intel/openamt"
|
||||
|
||||
"github.com/portainer/libhelm"
|
||||
"github.com/portainer/portainer/api/exec"
|
||||
@@ -468,6 +469,8 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
|
||||
|
||||
gitService := initGitService()
|
||||
|
||||
openAMTService := openamt.NewService()
|
||||
|
||||
cryptoService := initCryptoService()
|
||||
|
||||
digitalSignatureService := initDigitalSignatureService()
|
||||
@@ -623,6 +626,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
|
||||
LDAPService: ldapService,
|
||||
OAuthService: oauthService,
|
||||
GitService: gitService,
|
||||
OpenAMTService: openAMTService,
|
||||
ProxyManager: proxyManager,
|
||||
KubernetesTokenCacheManager: kubernetesTokenCacheManager,
|
||||
KubeConfigService: kubeConfigService,
|
||||
|
||||
@@ -4,13 +4,16 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// Handler is the HTTP handler used to handle OpenAMT operations.
|
||||
type Handler struct {
|
||||
*mux.Router
|
||||
OpenAMTService portainer.OpenAMTService
|
||||
}
|
||||
|
||||
// NewHandler returns a new Handler
|
||||
|
||||
@@ -10,18 +10,19 @@ import (
|
||||
)
|
||||
|
||||
type openAMTSubmitPayload struct {
|
||||
EnableOpenAMT *bool
|
||||
CertFileText *string
|
||||
CertPassword *string
|
||||
DomainName *string
|
||||
UseWirelessConfig *bool
|
||||
EnableOpenAMT *bool
|
||||
CertFileText *string
|
||||
CertPassword *string
|
||||
DomainName *string
|
||||
UseWirelessConfig *bool
|
||||
WifiAuthenticationMethod *string
|
||||
WifiEncryptionMethod *string
|
||||
WifiSSID *string
|
||||
WifiPskPass *string
|
||||
WifiEncryptionMethod *string
|
||||
WifiSSID *string
|
||||
WifiPskPass *string
|
||||
}
|
||||
|
||||
func (payload *openAMTSubmitPayload) Validate(r *http.Request) error {
|
||||
return nil //TODO remove
|
||||
if *payload.EnableOpenAMT {
|
||||
if payload.DomainName == nil || *payload.DomainName == "" {
|
||||
return errors.New("domain name must be provided")
|
||||
@@ -73,6 +74,11 @@ func (handler *Handler) openAMTSubmit(w http.ResponseWriter, r *http.Request) *h
|
||||
}
|
||||
|
||||
if *payload.EnableOpenAMT {
|
||||
err := handler.OpenAMTService.ConfigureDefault()
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "error configuring OpenAMT server", err}
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{http.StatusNotImplemented, "not implemented", errors.New("not implemented")}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ type Server struct {
|
||||
FileService portainer.FileService
|
||||
DataStore portainer.DataStore
|
||||
GitService portainer.GitService
|
||||
OpenAMTService portainer.OpenAMTService
|
||||
JWTService portainer.JWTService
|
||||
LDAPService portainer.LDAPService
|
||||
OAuthService portainer.OAuthService
|
||||
@@ -205,6 +206,7 @@ func (server *Server) Start() error {
|
||||
sslHandler.SSLService = server.SSLService
|
||||
|
||||
var openAMTHandler = openamthandler.NewHandler(requestBouncer)
|
||||
openAMTHandler.OpenAMTService = server.OpenAMTService
|
||||
|
||||
var stackHandler = stacks.NewHandler(requestBouncer)
|
||||
stackHandler.DataStore = server.DataStore
|
||||
|
||||
57
api/intel/openamt/authorization.go
Normal file
57
api/intel/openamt/authorization.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package openamt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type authenticationResponse struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func (service *Service) executeOpenAMTAuthenticationRequest() (*authenticationResponse, error) {
|
||||
loginURL := fmt.Sprintf("%v/mps/login/api/v1/authorize", MPS_SERVER_ADDRESS)
|
||||
|
||||
// TODO where to retrieve this from? autogenerated?
|
||||
payload := map[string]string{
|
||||
"username": "admin",
|
||||
"password": "chelo.Port2021",
|
||||
}
|
||||
jsonValue, _ := json.Marshal(payload)
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, loginURL, bytes.NewBuffer(jsonValue))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
response, err := service.httpsClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
responseBody, readErr := ioutil.ReadAll(response.Body)
|
||||
if readErr != nil {
|
||||
return nil, readErr
|
||||
}
|
||||
|
||||
var errorResponse errorResponse
|
||||
err = json.Unmarshal(responseBody, &errorResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(errorResponse.Errors) > 0 {
|
||||
return nil, errors.New(errorResponse.Errors[0].ErrorMsg)
|
||||
}
|
||||
if errorResponse.ErrorMsg != "" {
|
||||
return nil, errors.New(errorResponse.ErrorMsg)
|
||||
}
|
||||
|
||||
var token authenticationResponse
|
||||
err = json.Unmarshal(responseBody, &token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &token, nil
|
||||
}
|
||||
106
api/intel/openamt/ciraConfig.go
Normal file
106
api/intel/openamt/ciraConfig.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package openamt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CIRAConfig struct {
|
||||
ConfigName string `json:"configName"`
|
||||
MPSServerAddress string `json:"mpsServerAddress"`
|
||||
ServerAddressFormat int `json:"serverAddressFormat"`
|
||||
CommonName string `json:"commonName"`
|
||||
MPSPort int `json:"mpsPort"`
|
||||
Username string `json:"username"`
|
||||
MPSRootCertificate string `json:"mpsRootCertificate"`
|
||||
RegeneratePassword bool `json:"regeneratePassword"`
|
||||
AuthMethod int `json:"authMethod"`
|
||||
}
|
||||
|
||||
func (service *Service) createCIRAConfig(token string) (*CIRAConfig, error) {
|
||||
loginURL := fmt.Sprintf("%v/rps/api/v1/admin/ciraconfigs", MPS_SERVER_ADDRESS)
|
||||
|
||||
certificate, err := service.getCIRACertificate(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload := CIRAConfig{
|
||||
ConfigName: "ciraConfigDefault",
|
||||
MPSServerAddress: "192.168.0.100",
|
||||
ServerAddressFormat: 3,
|
||||
CommonName: "192.168.0.100",
|
||||
MPSPort: 4433,
|
||||
Username: "admin",
|
||||
MPSRootCertificate: certificate,
|
||||
RegeneratePassword: false,
|
||||
AuthMethod: 2,
|
||||
}
|
||||
jsonValue, _ := json.Marshal(payload)
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, loginURL, bytes.NewBuffer(jsonValue))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
|
||||
|
||||
response, err := service.httpsClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
responseBody, readErr := ioutil.ReadAll(response.Body)
|
||||
if readErr != nil {
|
||||
return nil, readErr
|
||||
}
|
||||
|
||||
var errorResponse errorResponse
|
||||
err = json.Unmarshal(responseBody, &errorResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(errorResponse.Errors) > 0 {
|
||||
return nil, errors.New(errorResponse.Errors[0].ErrorMsg)
|
||||
}
|
||||
if errorResponse.ErrorMsg != "" {
|
||||
return nil, errors.New(errorResponse.ErrorMsg)
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusCreated {
|
||||
return nil, errors.New(fmt.Sprintf("unexpected status code %v", response.Status))
|
||||
}
|
||||
|
||||
var result CIRAConfig
|
||||
err = json.Unmarshal(responseBody, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (service *Service) getCIRACertificate(token string) (string, error) {
|
||||
loginURL := fmt.Sprintf("%v/mps/api/v1/ciracert", MPS_SERVER_ADDRESS)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, loginURL, nil)
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
|
||||
|
||||
response, err := service.httpsClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return "", errors.New(fmt.Sprintf("unexpected status code %v", response.Status))
|
||||
}
|
||||
|
||||
certificate, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
block, _ := pem.Decode(certificate)
|
||||
return base64.StdEncoding.EncodeToString(block.Bytes), nil
|
||||
}
|
||||
51
api/intel/openamt/openamt.go
Normal file
51
api/intel/openamt/openamt.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package openamt
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
MPS_SERVER_ADDRESS = "https://localhost"
|
||||
)
|
||||
|
||||
// Service represents a service for managing an OpenAMT server.
|
||||
type Service struct {
|
||||
httpsClient *http.Client
|
||||
}
|
||||
|
||||
// NewService initializes a new service.
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
httpsClient:
|
||||
&http.Client{
|
||||
Timeout: time.Second * time.Duration(5),
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type errorResponse struct {
|
||||
ErrorMsg string `json:"message"`
|
||||
Errors []struct {
|
||||
ErrorMsg string `json:"msg"`
|
||||
} `json:"errors"`
|
||||
}
|
||||
|
||||
func(service *Service) ConfigureDefault() error {
|
||||
token, err := service.executeOpenAMTAuthenticationRequest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = service.createCIRAConfig(token.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1257,6 +1257,11 @@ type (
|
||||
LatestCommitID(repositoryURL, referenceName, username, password string) (string, error)
|
||||
}
|
||||
|
||||
// OpenAMTService represents a service for managing OpenAMT
|
||||
OpenAMTService interface {
|
||||
ConfigureDefault() error
|
||||
}
|
||||
|
||||
// HelmUserRepositoryService represents a service to manage HelmUserRepositories
|
||||
HelmUserRepositoryService interface {
|
||||
HelmUserRepositoryByUserID(userID UserID) ([]HelmUserRepository, error)
|
||||
|
||||
Reference in New Issue
Block a user