Skip to content

Commit

Permalink
added plugin config parsing
Browse files Browse the repository at this point in the history
Signed-off-by: Maia Iyer <[email protected]>
  • Loading branch information
maia-iyer committed Oct 10, 2024
1 parent da43c3f commit 1ab19c6
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 138 deletions.
25 changes: 25 additions & 0 deletions api/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ func NewAgentsDB(dbPlugin *ast.ObjectItem) (agentdb.AgentDB, error) {
}
}

// NewCRDManager returns ...
func NewCRDManager(crdPlugin &ast.ObjectItem) (string, error) {

Check failure on line 89 in api/agent/config.go

View workflow job for this annotation

GitHub Actions / tornjak-build

syntax error: unexpected & in parameter list; possibly missing comma or ) (typecheck)

Check failure on line 89 in api/agent/config.go

View workflow job for this annotation

GitHub Actions / tornjak-build

missing ',' in parameter list (typecheck)

Check failure on line 89 in api/agent/config.go

View workflow job for this annotation

GitHub Actions / tornjak-build

syntax error: unexpected & in parameter list; possibly missing comma or )) (typecheck)
_, data, _ := getPluginConfig(crdPlugin)

// check if data is defined
if data == nil {
return nil, errors.New("SPIREControllerManager plugin ('config > plugins > SPIREControllerManager > plugin_data') not populated")
}
// decode config to struct
var config pluginControllerManager
if err := hcl.DecodeObject(&config, data); err != nil {
return nil, errors.Errorf("Couldn't parse SPIREControllerManager config: %v", err)
}

fmt.Println("CRD Controller configured. WARNING: This is currently a no-op")

return "CRD config string", nil
}

// NewAuthenticator returns a new Authenticator
func NewAuthenticator(authenticatorPlugin *ast.ObjectItem) (authenticator.Authenticator, error) {
key, data, _ := getPluginConfig(authenticatorPlugin)
Expand Down Expand Up @@ -247,6 +266,12 @@ func (s *Server) Configure() error {
if err != nil {
return errors.Errorf("Cannot configure datastore plugin: %v", err)
}
// configure controller maanger CRD management
case "SPIREControllerManager":
s.CRDManger, err = NewCRDManager(pluginObject)
if err != nil {
return errors.Errorf("Cannot configure CRD management plugin: %v")
}
// configure Authenticator
case "Authenticator":
s.Authenticator, err = NewAuthenticator(pluginObject)
Expand Down
1 change: 1 addition & 0 deletions api/agent/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Server struct {

// Plugins
Db agentdb.AgentDB
CRDManager string // TODO create plugin for this
Authenticator authenticator.Authenticator
Authorizer authorization.Authorizer
}
Expand Down
280 changes: 142 additions & 138 deletions api/agent/types.go
Original file line number Diff line number Diff line change
@@ -1,138 +1,142 @@
package api

import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"

"github.com/hashicorp/hcl/hcl/ast"
)

// TornjakServerInfo provides insight into the configuration of the SPIRE server
// where the Tornjak Agent resides
type TornjakSpireServerInfo struct {
// Plugins is a map from plugin types to respective names of plugins configured
Plugins map[string][]string `json:"plugins"`
// TrustDomain specifies the trust domain of the SPIRE server configured with tornjak
TrustDomain string `json:"trustDomain"`
// Verbose config contains unstructure information on the config on the agent
VerboseConfig string `json:"verboseConfig"`
}

// pared down version of full Server Config type spire/cmd/spire-server/cli/run
// we curently need only extract the trust domain
type SpireServerConfig struct {
TrustDomain string `hcl:"trust_domain"`
}

type SPIREConfig struct {
Server *SpireServerConfig `hcl:"server"`
Plugins ast.Node `hcl:"plugins"`
}

type TornjakConfig struct {
Server *serverConfig `hcl:"server"`
Plugins *ast.Node `hcl:"plugins"`
}

/* Server configuration*/

type serverConfig struct {
SPIRESocket string `hcl:"spire_socket_path"`
HTTPConfig *HTTPConfig `hcl:"http"`
HTTPSConfig *HTTPSConfig `hcl:"https"`
}

type HTTPConfig struct {
ListenPort int `hcl:"port"`
}

type HTTPSConfig struct {
ListenPort int `hcl:"port"`
Cert string `hcl:"cert"`
Key string `hcl:"key"`
ClientCA string `hcl:"client_ca"`
}

func (h HTTPSConfig) Parse() (*tls.Config, error) {
serverCertPath := h.Cert
serverKeyPath := h.Key
clientCAPath := h.ClientCA

mtls := (clientCAPath != "")

if _, err := os.Stat(serverCertPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server cert path '%s': %w", serverCertPath, err)
}
if _, err := os.Stat(serverKeyPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server key path '%s': %w", serverKeyPath, err)
}

// Create a CA certificate pool and add cert.pem to it
serverCert, err := os.ReadFile(serverCertPath)
if err != nil {
return nil, fmt.Errorf("server ca pool error: %w", err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(serverCert)

if mtls {
// add mTLS CA path to cert pool as well
if _, err := os.Stat(clientCAPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server file does not exist %s", clientCAPath)
}
clientCA, err := os.ReadFile(clientCAPath)
if err != nil {
return nil, fmt.Errorf("server: could not read file %s: %w", clientCAPath, err)
}
caCertPool.AppendCertsFromPEM(clientCA)
}

// Create the TLS Config with the CA pool and enable Client certificate validation
tlsConfig := &tls.Config{
ClientCAs: caCertPool,
}

if mtls {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
//tlsConfig.BuildNameToCertificate()

return tlsConfig, nil
}

/* Plugin types */
type pluginDataStoreSQL struct {
Drivername string `hcl:"drivername"`
Filename string `hcl:"filename"`
}

type pluginAuthenticatorKeycloak struct {
IssuerURL string `hcl:"issuer"`
Audience string `hcl:"audience"`
}

type AuthRole struct {
Name string `hcl:",key"`
Desc string `hcl:"desc"`
}

type APIRoleMapping struct {
Name string `hcl:",key"`
AllowedRoles []string `hcl:"allowed_roles"`
}

type APIv1RoleMapping struct {
Name string `hcl:",key"`
Method string `hcl:"-"`
Path string `hcl:"-"`
AllowedRoles []string `hcl:"allowed_roles"`
}

type pluginAuthorizerRBAC struct {
Name string `hcl:"name"`
RoleList []*AuthRole `hcl:"role,block"`
APIRoleMappings []*APIRoleMapping `hcl:"API,block"`
APIv1RoleMappings []*APIv1RoleMapping `hcl:"APIv1,block"`
}
package api

import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"

"github.com/hashicorp/hcl/hcl/ast"
)

// TornjakServerInfo provides insight into the configuration of the SPIRE server
// where the Tornjak Agent resides
type TornjakSpireServerInfo struct {
// Plugins is a map from plugin types to respective names of plugins configured
Plugins map[string][]string `json:"plugins"`
// TrustDomain specifies the trust domain of the SPIRE server configured with tornjak
TrustDomain string `json:"trustDomain"`
// Verbose config contains unstructure information on the config on the agent
VerboseConfig string `json:"verboseConfig"`
}

// pared down version of full Server Config type spire/cmd/spire-server/cli/run
// we curently need only extract the trust domain
type SpireServerConfig struct {
TrustDomain string `hcl:"trust_domain"`
}

type SPIREConfig struct {
Server *SpireServerConfig `hcl:"server"`
Plugins ast.Node `hcl:"plugins"`
}

type TornjakConfig struct {
Server *serverConfig `hcl:"server"`
Plugins *ast.Node `hcl:"plugins"`
}

/* Server configuration*/

type serverConfig struct {
SPIRESocket string `hcl:"spire_socket_path"`
HTTPConfig *HTTPConfig `hcl:"http"`
HTTPSConfig *HTTPSConfig `hcl:"https"`
}

type HTTPConfig struct {
ListenPort int `hcl:"port"`
}

type HTTPSConfig struct {
ListenPort int `hcl:"port"`
Cert string `hcl:"cert"`
Key string `hcl:"key"`
ClientCA string `hcl:"client_ca"`
}

func (h HTTPSConfig) Parse() (*tls.Config, error) {
serverCertPath := h.Cert
serverKeyPath := h.Key
clientCAPath := h.ClientCA

mtls := (clientCAPath != "")

if _, err := os.Stat(serverCertPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server cert path '%s': %w", serverCertPath, err)
}
if _, err := os.Stat(serverKeyPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server key path '%s': %w", serverKeyPath, err)
}

// Create a CA certificate pool and add cert.pem to it
serverCert, err := os.ReadFile(serverCertPath)
if err != nil {
return nil, fmt.Errorf("server ca pool error: %w", err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(serverCert)

if mtls {
// add mTLS CA path to cert pool as well
if _, err := os.Stat(clientCAPath); os.IsNotExist(err) {
return nil, fmt.Errorf("server file does not exist %s", clientCAPath)
}
clientCA, err := os.ReadFile(clientCAPath)
if err != nil {
return nil, fmt.Errorf("server: could not read file %s: %w", clientCAPath, err)
}
caCertPool.AppendCertsFromPEM(clientCA)
}

// Create the TLS Config with the CA pool and enable Client certificate validation
tlsConfig := &tls.Config{
ClientCAs: caCertPool,
}

if mtls {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
//tlsConfig.BuildNameToCertificate()

return tlsConfig, nil
}

/* Plugin types */
type pluginDataStoreSQL struct {
Drivername string `hcl:"drivername"`
Filename string `hcl:"filename"`
}

type pluginControllerManager struct {
Classname string `hcl:"classname"`
}

type pluginAuthenticatorKeycloak struct {
IssuerURL string `hcl:"issuer"`
Audience string `hcl:"audience"`
}

type AuthRole struct {
Name string `hcl:",key"`
Desc string `hcl:"desc"`
}

type APIRoleMapping struct {
Name string `hcl:",key"`
AllowedRoles []string `hcl:"allowed_roles"`
}

type APIv1RoleMapping struct {
Name string `hcl:",key"`
Method string `hcl:"-"`
Path string `hcl:"-"`
AllowedRoles []string `hcl:"allowed_roles"`
}

type pluginAuthorizerRBAC struct {
Name string `hcl:"name"`
RoleList []*AuthRole `hcl:"role,block"`
APIRoleMappings []*APIRoleMapping `hcl:"API,block"`
APIv1RoleMappings []*APIv1RoleMapping `hcl:"APIv1,block"`
}

0 comments on commit 1ab19c6

Please sign in to comment.