mirror of
https://github.com/openziti/ziti.git
synced 2026-10-23 04:06:50 +00:00
+71
-47
@@ -69,9 +69,9 @@ type Config struct {
|
||||
Enabled bool
|
||||
Api Api
|
||||
Enrollment Enrollment
|
||||
caPems [][]byte
|
||||
caPemsBuf []byte
|
||||
caPemsOnce sync.Once
|
||||
|
||||
caPems *bytes.Buffer
|
||||
caPemsOnce sync.Once
|
||||
}
|
||||
|
||||
type HttpTimeouts struct {
|
||||
@@ -81,52 +81,35 @@ type HttpTimeouts struct {
|
||||
IdleTimeoutsDuration time.Duration
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
Enabled: false,
|
||||
caPems: bytes.NewBuffer(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) SessionTimeoutDuration() time.Duration {
|
||||
return c.Api.SessionTimeout
|
||||
}
|
||||
|
||||
func toHex(data []byte) string {
|
||||
var buf bytes.Buffer
|
||||
for i, b := range data {
|
||||
if i > 0 {
|
||||
_, _ = fmt.Fprintf(&buf, ":")
|
||||
}
|
||||
_, _ = fmt.Fprintf(&buf, "%02x", b)
|
||||
}
|
||||
return strings.ToUpper(buf.String())
|
||||
}
|
||||
|
||||
func (c *Config) CaPems() []byte {
|
||||
c.caPemsOnce.Do(func() {
|
||||
buf := bytes.Buffer{}
|
||||
//dedupe chains
|
||||
pemMap := map[string][]byte{}
|
||||
for _, caChain := range c.caPems {
|
||||
rest := caChain
|
||||
for len(rest) != 0 {
|
||||
var block *pem.Block
|
||||
block, rest = pem.Decode(rest)
|
||||
|
||||
if block != nil {
|
||||
hash := sha1.Sum(block.Bytes)
|
||||
fingerprint := toHex(hash[:])
|
||||
pemMap[fingerprint] = pem.EncodeToMemory(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, pemBytes := range pemMap {
|
||||
if i != 0 {
|
||||
buf.Write([]byte("\n"))
|
||||
}
|
||||
buf.Write(pemBytes)
|
||||
i++
|
||||
}
|
||||
c.caPemsBuf = buf.Bytes()
|
||||
c.RefreshCaPems()
|
||||
})
|
||||
|
||||
return c.caPemsBuf
|
||||
return c.caPems.Bytes()
|
||||
}
|
||||
|
||||
// AddCaPems adds a byte array of certificates to the current buffered list of CAs. The certificates
|
||||
// should be in PEM format separated by new lines. RefreshCaPems should be called after all
|
||||
// calls to AddCaPems are completed.
|
||||
func (c *Config) AddCaPems(caPems []byte) {
|
||||
c.caPems.WriteString("\n")
|
||||
c.caPems.Write(caPems)
|
||||
}
|
||||
|
||||
func (c *Config) RefreshCaPems() {
|
||||
c.caPems = CalculateCaPems(c.caPems)
|
||||
}
|
||||
|
||||
func (c *Config) loadRootIdentity(fabricConfigMap map[interface{}]interface{}) error {
|
||||
@@ -168,7 +151,8 @@ func (c *Config) loadRootIdentity(fabricConfigMap map[interface{}]interface{}) e
|
||||
return fmt.Errorf("could not read file CA file from [identity.ca]")
|
||||
}
|
||||
|
||||
c.caPems = append(c.caPems, c.RootIdentityCaPem)
|
||||
_, _ = c.caPems.WriteString("\n")
|
||||
_, _ = c.caPems.Write(c.RootIdentityCaPem)
|
||||
|
||||
c.RootIdentity, err = identity.LoadIdentity(c.RootIdentityConfig)
|
||||
|
||||
@@ -258,7 +242,8 @@ func (c *Config) loadEnrollmentSection(edgeConfigMap map[interface{}]interface{}
|
||||
pfxlog.Logger().WithError(err).Panic("unable to read [edge.enrollment.cert]")
|
||||
}
|
||||
//The signer is a valid trust anchor
|
||||
c.caPems = append(c.caPems, certPem)
|
||||
_, _ = c.caPems.WriteString("\n")
|
||||
_, _ = c.caPems.Write(certPem)
|
||||
|
||||
} else {
|
||||
return fmt.Errorf("required configuration value [edge.enrollment.cert] is missing")
|
||||
@@ -277,7 +262,8 @@ func (c *Config) loadEnrollmentSection(edgeConfigMap map[interface{}]interface{}
|
||||
return fmt.Errorf("could not read file CA file from [edge.enrollment.signingCert.ca]")
|
||||
}
|
||||
|
||||
c.caPems = append(c.caPems, c.Enrollment.SigningCertCaPem)
|
||||
_, _ = c.caPems.WriteString("\n")
|
||||
_, _ = c.caPems.Write(c.Enrollment.SigningCertCaPem)
|
||||
} //not an error if the signing certificate's CA is already represented in the root [identity.ca]
|
||||
|
||||
if c.Enrollment.SigningCert, err = identity.LoadIdentity(c.Enrollment.SigningCertConfig); err != nil {
|
||||
@@ -344,9 +330,7 @@ func (c *Config) loadEnrollmentSection(edgeConfigMap map[interface{}]interface{}
|
||||
}
|
||||
|
||||
func LoadFromMap(configMap map[interface{}]interface{}) (*Config, error) {
|
||||
edgeConfig := &Config{
|
||||
Enabled: false,
|
||||
}
|
||||
edgeConfig := NewConfig()
|
||||
|
||||
var edgeConfigMap map[interface{}]interface{}
|
||||
|
||||
@@ -366,6 +350,10 @@ func LoadFromMap(configMap map[interface{}]interface{}) (*Config, error) {
|
||||
|
||||
var err error
|
||||
|
||||
if err = edgeConfig.loadRootIdentity(configMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = edgeConfig.loadApiSection(edgeConfigMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,3 +364,39 @@ func LoadFromMap(configMap map[interface{}]interface{}) (*Config, error) {
|
||||
|
||||
return edgeConfig, nil
|
||||
}
|
||||
|
||||
// CalculateCaPems takes the supplied caPems buffer as a set of PEM Certificates separated by new lines. Duplicate
|
||||
// certificates are removed and the result is returned as a bytes.Buffer of PEM Certificates separated by new lines.
|
||||
func CalculateCaPems(caPems *bytes.Buffer) *bytes.Buffer {
|
||||
caPemMap := map[string][]byte{}
|
||||
|
||||
newCaPems := bytes.Buffer{}
|
||||
blocksToProcess := caPems.Bytes()
|
||||
for len(blocksToProcess) != 0 {
|
||||
var block *pem.Block
|
||||
block, blocksToProcess = pem.Decode(blocksToProcess)
|
||||
|
||||
if block != nil {
|
||||
hash := sha1.Sum(block.Bytes)
|
||||
fingerprint := toHex(hash[:])
|
||||
newPem := pem.EncodeToMemory(block)
|
||||
caPemMap[fingerprint] = newPem
|
||||
_, _ = newCaPems.WriteString("\n")
|
||||
_, _ = newCaPems.Write(newPem)
|
||||
}
|
||||
}
|
||||
|
||||
return &newCaPems
|
||||
}
|
||||
|
||||
// toHex takes a byte array returns a hex formatted fingerprint
|
||||
func toHex(data []byte) string {
|
||||
var buf bytes.Buffer
|
||||
for i, b := range data {
|
||||
if i > 0 {
|
||||
_, _ = fmt.Fprintf(&buf, ":")
|
||||
}
|
||||
_, _ = fmt.Fprintf(&buf, "%02x", b)
|
||||
}
|
||||
return strings.ToUpper(buf.String())
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/openziti/edge/rest_client_api_server"
|
||||
"github.com/openziti/fabric/controller/xweb"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -40,21 +41,39 @@ type ClientApiFactory struct {
|
||||
}
|
||||
|
||||
func (factory ClientApiFactory) Validate(config *xweb.Config) error {
|
||||
clientApiFound := false
|
||||
for _, webListener := range config.WebListeners {
|
||||
for _, api := range webListener.APIs {
|
||||
if api.Binding() == controller.ClientApiBinding {
|
||||
|
||||
if webListener.IdentityConfig != nil && (api.Binding() == controller.ClientApiBinding || api.Binding() == controller.ManagementApiBinding){
|
||||
caBytes, err := ioutil.ReadFile(webListener.IdentityConfig.CA)
|
||||
|
||||
if err != nil {
|
||||
return errors.Errorf("could not read xweb web listener [%s]'s CA file [%s] to retrieve CA PEMs: %v", webListener.Name, webListener.IdentityConfig.CA, err)
|
||||
}
|
||||
|
||||
factory.appEnv.Config.AddCaPems(caBytes)
|
||||
}
|
||||
|
||||
if !clientApiFound && api.Binding() == controller.ClientApiBinding {
|
||||
for _, bindPoint := range webListener.BindPoints {
|
||||
if bindPoint.Address == factory.appEnv.Config.Api.Address {
|
||||
factory.appEnv.SetEnrollmentSigningCert(webListener.Identity.ServerCert())
|
||||
return nil
|
||||
clientApiFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
break //done with this webListener, look for next if we are still running
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Errorf("could not find [edge.api.address] value [%s] as a bind point any instance of API [%s]", factory.appEnv.Config.Api.Address, controller.ClientApiBinding)
|
||||
factory.appEnv.Config.RefreshCaPems()
|
||||
|
||||
if !clientApiFound {
|
||||
return errors.Errorf("could not find [edge.api.address] value [%s] as a bind point any instance of API [%s]", factory.appEnv.Config.Api.Address, controller.ClientApiBinding)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewClientApiFactory(appEnv *env.AppEnv) *ClientApiFactory {
|
||||
|
||||
Reference in New Issue
Block a user