mirror of https://github.com/portainer/portainer
feat(api): support AGENT_SECRET environment variable (#2486)
parent
fe8dfee69a
commit
d03fd5805a
|
@ -2,6 +2,7 @@ package main // import "github.com/portainer/portainer"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ func initJWTService(authenticationEnabled bool) portainer.JWTService {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initDigitalSignatureService() portainer.DigitalSignatureService {
|
func initDigitalSignatureService() portainer.DigitalSignatureService {
|
||||||
return &crypto.ECDSAService{}
|
return crypto.NewECDSAService(os.Getenv("AGENT_SECRET"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func initCryptoService() portainer.CryptoService {
|
func initCryptoService() portainer.CryptoService {
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/portainer/portainer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -26,6 +28,15 @@ type ECDSAService struct {
|
||||||
privateKey *ecdsa.PrivateKey
|
privateKey *ecdsa.PrivateKey
|
||||||
publicKey *ecdsa.PublicKey
|
publicKey *ecdsa.PublicKey
|
||||||
encodedPubKey string
|
encodedPubKey string
|
||||||
|
secret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewECDSAService returns a pointer to a ECDSAService.
|
||||||
|
// An optional secret can be specified
|
||||||
|
func NewECDSAService(secret string) *ECDSAService {
|
||||||
|
return &ECDSAService{
|
||||||
|
secret: secret,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodedPublicKey returns the encoded version of the public that can be used
|
// EncodedPublicKey returns the encoded version of the public that can be used
|
||||||
|
@ -91,11 +102,17 @@ func (service *ECDSAService) GenerateKeyPair() ([]byte, []byte, error) {
|
||||||
return private, public, nil
|
return private, public, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign creates a signature from a message.
|
// CreateSignature creates a digital signature.
|
||||||
// It automatically hash the message using MD5 and creates a signature from
|
// It automatically hash a specific message using MD5 and creates a signature from
|
||||||
// that hash.
|
// that hash.
|
||||||
// It then encodes the generated signature in base64.
|
// It then encodes the generated signature in base64.
|
||||||
func (service *ECDSAService) Sign(message string) (string, error) {
|
func (service *ECDSAService) CreateSignature() (string, error) {
|
||||||
|
|
||||||
|
message := portainer.PortainerAgentSignatureMessage
|
||||||
|
if service.secret != "" {
|
||||||
|
message = service.secret
|
||||||
|
}
|
||||||
|
|
||||||
hash := HashFromBytes([]byte(message))
|
hash := HashFromBytes([]byte(message))
|
||||||
|
|
||||||
r := big.NewInt(0)
|
r := big.NewInt(0)
|
||||||
|
|
|
@ -67,7 +67,7 @@ func createAgentClient(endpoint *portainer.Endpoint, signatureService portainer.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := signatureService.Sign(portainer.PortainerAgentSignatureMessage)
|
signature, err := signatureService.CreateSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ func (manager *SwarmStackManager) updateDockerCLIConfiguration(dataPath string)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := manager.signatureService.Sign(portainer.PortainerAgentSignatureMessage)
|
signature, err := manager.signatureService.CreateSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,12 +111,13 @@ func (handler *Handler) proxyWebsocketRequest(w http.ResponseWriter, r *http.Req
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := handler.SignatureService.Sign(portainer.PortainerAgentSignatureMessage)
|
signature, err := handler.SignatureService.CreateSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.Director = func(incoming *http.Request, out http.Header) {
|
proxy.Director = func(incoming *http.Request, out http.Header) {
|
||||||
|
out.Set(portainer.PortainerAgentPublicKeyHeader, handler.SignatureService.EncodedPublicKey())
|
||||||
out.Set(portainer.PortainerAgentSignatureHeader, signature)
|
out.Set(portainer.PortainerAgentSignatureHeader, signature)
|
||||||
out.Set(portainer.PortainerAgentTargetHeader, params.nodeName)
|
out.Set(portainer.PortainerAgentTargetHeader, params.nodeName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (p *proxyTransport) proxyDockerRequest(request *http.Request) (*http.Respon
|
||||||
request.URL.Path = path
|
request.URL.Path = path
|
||||||
|
|
||||||
if p.enableSignature {
|
if p.enableSignature {
|
||||||
signature, err := p.SignatureService.Sign(portainer.PortainerAgentSignatureMessage)
|
signature, err := p.SignatureService.CreateSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,7 @@ type (
|
||||||
GenerateKeyPair() ([]byte, []byte, error)
|
GenerateKeyPair() ([]byte, []byte, error)
|
||||||
EncodedPublicKey() string
|
EncodedPublicKey() string
|
||||||
PEMHeaders() (string, string)
|
PEMHeaders() (string, string)
|
||||||
Sign(message string) (string, error)
|
CreateSignature() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JWTService represents a service for managing JWT tokens
|
// JWTService represents a service for managing JWT tokens
|
||||||
|
|
Loading…
Reference in New Issue