Skip to content

Commit 71a03a4

Browse files
authored
Adding CRD config plugin section (#537)
* removed handlers Signed-off-by: Maia Iyer <[email protected]> * nit spacing fixes Signed-off-by: Maia Iyer <[email protected]> * Nits Signed-off-by: Maia Iyer <[email protected]> * added plugin config parsing Signed-off-by: Maia Iyer <[email protected]> * Nits Signed-off-by: Maia Iyer <[email protected]> * Initialize Package Signed-off-by: Maia Iyer <[email protected]> * add initial documentation Signed-off-by: Maia Iyer <[email protected]> * added documentation Signed-off-by: Maia Iyer <[email protected]> * nit lint Signed-off-by: Maia Iyer <[email protected]> * nit Signed-off-by: Maia Iyer <[email protected]> * Add reference link Signed-off-by: Maia Iyer <[email protected]> * nit lints Signed-off-by: Maia Iyer <[email protected]> * fix key length check Signed-off-by: Maia Iyer <[email protected]> * nit Signed-off-by: Maia Iyer <[email protected]> * nits Signed-off-by: Maia Iyer <[email protected]> --------- Signed-off-by: Maia Iyer <[email protected]>
1 parent 952e302 commit 71a03a4

File tree

7 files changed

+249
-147
lines changed

7 files changed

+249
-147
lines changed

Diff for: api/agent/config.go

+55-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/spiffe/tornjak/pkg/agent/authentication/authenticator"
1515
"github.com/spiffe/tornjak/pkg/agent/authorization"
1616
agentdb "github.com/spiffe/tornjak/pkg/agent/db"
17+
"github.com/spiffe/tornjak/pkg/agent/spirecrd"
1718
)
1819

1920
func stringFromToken(keyToken token.Token) (string, error) {
@@ -34,9 +35,17 @@ func stringFromToken(keyToken token.Token) (string, error) {
3435
// getPluginConfig returns first plugin configuration
3536
func getPluginConfig(plugin *ast.ObjectItem) (string, ast.Node, error) {
3637
// extract plugin name and value
37-
pluginName, err := stringFromToken(plugin.Keys[1].Token)
38-
if err != nil {
39-
return "", nil, fmt.Errorf("invalid plugin type name %q: %w", plugin.Keys[1].Token.Text, err)
38+
pluginKeys := plugin.Keys
39+
var pluginName string
40+
var err error
41+
42+
if len(pluginKeys) > 1 {
43+
pluginName, err = stringFromToken(pluginKeys[1].Token)
44+
if err != nil {
45+
return "", nil, fmt.Errorf("invalid plugin type name %q: %w", pluginKeys[1].Token.Text, err)
46+
}
47+
} else {
48+
pluginName = ""
4049
}
4150
// extract data
4251
var hclPluginConfig hclPluginConfig
@@ -85,6 +94,30 @@ func NewAgentsDB(dbPlugin *ast.ObjectItem) (agentdb.AgentDB, error) {
8594
}
8695
}
8796

97+
// NewCRDManager returns ...
98+
func NewCRDManager(crdPlugin *ast.ObjectItem) (spirecrd.CRDManager, error) {
99+
_, data, _ := getPluginConfig(crdPlugin)
100+
101+
// check if data is defined
102+
if data == nil {
103+
return "", errors.New("SPIRECRDManager plugin ('config > plugins > SPIRECRDManager > plugin_data') not populated")
104+
}
105+
// decode config to struct
106+
var config pluginControllerManager
107+
if err := hcl.DecodeObject(&config, data); err != nil {
108+
return "", errors.Errorf("Couldn't parse SPIREControllerManager config: %v", err)
109+
}
110+
111+
fmt.Println("CRD Controller configured. WARNING: This is currently a no-op")
112+
113+
crdManager, err := spirecrd.NewSPIRECRDManager(config.Classname)
114+
if err != nil {
115+
return nil, errors.Errorf("Could not initialize CRD manager: %v", err)
116+
}
117+
118+
return crdManager, nil
119+
}
120+
88121
// NewAuthenticator returns a new Authenticator
89122
func NewAuthenticator(authenticatorPlugin *ast.ObjectItem) (authenticator.Authenticator, error) {
90123
key, data, _ := getPluginConfig(authenticatorPlugin)
@@ -225,10 +258,6 @@ func (s *Server) Configure() error {
225258
// iterate over plugin list
226259

227260
for _, pluginObject := range pluginList.Items {
228-
if len(pluginObject.Keys) != 2 {
229-
return fmt.Errorf("plugin item expected to have two keys (type then name)")
230-
}
231-
232261
pluginType, err := stringFromToken(pluginObject.Keys[0].Token)
233262
if err != nil {
234263
return fmt.Errorf("invalid plugin type key %q: %w", pluginObject.Keys[0].Token.Text, err)
@@ -238,18 +267,37 @@ func (s *Server) Configure() error {
238267
switch pluginType {
239268
// configure datastore
240269
case "DataStore":
270+
if len(pluginObject.Keys) != 2 {
271+
return fmt.Errorf("plugin DataStore expected to have two keys (type then name)")
272+
}
241273
s.Db, err = NewAgentsDB(pluginObject)
242274
if err != nil {
243275
return errors.Errorf("Cannot configure datastore plugin: %v", err)
244276
}
277+
// configure controller maanger CRD management
278+
case "SPIRECRDManager":
279+
if len(pluginObject.Keys) != 1 {
280+
return fmt.Errorf("plugin SPIRECRDManager expected to have one key (type)")
281+
}
282+
283+
s.CRDManager, err = NewCRDManager(pluginObject)
284+
if err != nil {
285+
return errors.Errorf("Cannot configure CRD management plugin: %v", err)
286+
}
245287
// configure Authenticator
246288
case "Authenticator":
289+
if len(pluginObject.Keys) != 2 {
290+
return fmt.Errorf("plugin Authenticator expected to have two keys (type then name)")
291+
}
247292
s.Authenticator, err = NewAuthenticator(pluginObject)
248293
if err != nil {
249294
return errors.Errorf("Cannot configure Authenticator plugin: %v", err)
250295
}
251296
// configure Authorizer
252297
case "Authorizer":
298+
if len(pluginObject.Keys) != 2 {
299+
return fmt.Errorf("plugin Authorizer expected to have two keys (type then name)")
300+
}
253301
s.Authorizer, err = NewAuthorizer(pluginObject)
254302
if err != nil {
255303
return errors.Errorf("Cannot configure Authorizer plugin: %v", err)

Diff for: api/agent/server.go

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/spiffe/tornjak/pkg/agent/authentication/authenticator"
1919
"github.com/spiffe/tornjak/pkg/agent/authorization"
2020
agentdb "github.com/spiffe/tornjak/pkg/agent/db"
21+
"github.com/spiffe/tornjak/pkg/agent/spirecrd"
2122
)
2223

2324
type Server struct {
@@ -32,6 +33,7 @@ type Server struct {
3233

3334
// Plugins
3435
Db agentdb.AgentDB
36+
CRDManager spirecrd.CRDManager
3537
Authenticator authenticator.Authenticator
3638
Authorizer authorization.Authorizer
3739
}

Diff for: api/agent/types.go

+136-132
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,136 @@
1-
package api
2-
3-
import (
4-
"crypto/tls"
5-
"crypto/x509"
6-
"fmt"
7-
"os"
8-
9-
"github.com/hashicorp/hcl/hcl/ast"
10-
)
11-
12-
// TornjakServerInfo provides insight into the configuration of the SPIRE server
13-
// where the Tornjak Agent resides
14-
type TornjakSpireServerInfo struct {
15-
// Plugins is a map from plugin types to respective names of plugins configured
16-
Plugins map[string][]string `json:"plugins"`
17-
// TrustDomain specifies the trust domain of the SPIRE server configured with tornjak
18-
TrustDomain string `json:"trustDomain"`
19-
// Verbose config contains unstructure information on the config on the agent
20-
VerboseConfig string `json:"verboseConfig"`
21-
}
22-
23-
// pared down version of full Server Config type spire/cmd/spire-server/cli/run
24-
// we curently need only extract the trust domain
25-
type SpireServerConfig struct {
26-
TrustDomain string `hcl:"trust_domain"`
27-
}
28-
29-
type SPIREConfig struct {
30-
Server *SpireServerConfig `hcl:"server"`
31-
Plugins ast.Node `hcl:"plugins"`
32-
}
33-
34-
type TornjakConfig struct {
35-
Server *serverConfig `hcl:"server"`
36-
Plugins *ast.Node `hcl:"plugins"`
37-
}
38-
39-
/* Server configuration*/
40-
41-
type serverConfig struct {
42-
SPIRESocket string `hcl:"spire_socket_path"`
43-
HTTPConfig *HTTPConfig `hcl:"http"`
44-
HTTPSConfig *HTTPSConfig `hcl:"https"`
45-
}
46-
47-
type HTTPConfig struct {
48-
ListenPort int `hcl:"port"`
49-
}
50-
51-
type HTTPSConfig struct {
52-
ListenPort int `hcl:"port"`
53-
Cert string `hcl:"cert"`
54-
Key string `hcl:"key"`
55-
ClientCA string `hcl:"client_ca"`
56-
}
57-
58-
func (h HTTPSConfig) Parse() (*tls.Config, error) {
59-
serverCertPath := h.Cert
60-
serverKeyPath := h.Key
61-
clientCAPath := h.ClientCA
62-
63-
mtls := (clientCAPath != "")
64-
65-
if _, err := os.Stat(serverCertPath); os.IsNotExist(err) {
66-
return nil, fmt.Errorf("server cert path '%s': %w", serverCertPath, err)
67-
}
68-
if _, err := os.Stat(serverKeyPath); os.IsNotExist(err) {
69-
return nil, fmt.Errorf("server key path '%s': %w", serverKeyPath, err)
70-
}
71-
72-
// Create a CA certificate pool and add cert.pem to it
73-
serverCert, err := os.ReadFile(serverCertPath)
74-
if err != nil {
75-
return nil, fmt.Errorf("server ca pool error: %w", err)
76-
}
77-
caCertPool := x509.NewCertPool()
78-
caCertPool.AppendCertsFromPEM(serverCert)
79-
80-
if mtls {
81-
// add mTLS CA path to cert pool as well
82-
if _, err := os.Stat(clientCAPath); os.IsNotExist(err) {
83-
return nil, fmt.Errorf("server file does not exist %s", clientCAPath)
84-
}
85-
clientCA, err := os.ReadFile(clientCAPath)
86-
if err != nil {
87-
return nil, fmt.Errorf("server: could not read file %s: %w", clientCAPath, err)
88-
}
89-
caCertPool.AppendCertsFromPEM(clientCA)
90-
}
91-
92-
// Create the TLS Config with the CA pool and enable Client certificate validation
93-
tlsConfig := &tls.Config{
94-
ClientCAs: caCertPool,
95-
}
96-
97-
if mtls {
98-
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
99-
}
100-
//tlsConfig.BuildNameToCertificate()
101-
102-
return tlsConfig, nil
103-
}
104-
105-
/* Plugin types */
106-
type pluginDataStoreSQL struct {
107-
Drivername string `hcl:"drivername"`
108-
Filename string `hcl:"filename"`
109-
}
110-
111-
type pluginAuthenticatorKeycloak struct {
112-
IssuerURL string `hcl:"issuer"`
113-
Audience string `hcl:"audience"`
114-
}
115-
116-
type AuthRole struct {
117-
Name string `hcl:",key"`
118-
Desc string `hcl:"desc"`
119-
}
120-
121-
type APIv1RoleMapping struct {
122-
Name string `hcl:",key"`
123-
Method string `hcl:"-"`
124-
Path string `hcl:"-"`
125-
AllowedRoles []string `hcl:"allowed_roles"`
126-
}
127-
128-
type pluginAuthorizerRBAC struct {
129-
Name string `hcl:"name"`
130-
RoleList []*AuthRole `hcl:"role,block"`
131-
APIv1RoleMappings []*APIv1RoleMapping `hcl:"APIv1,block"`
132-
}
1+
package api
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"fmt"
7+
"os"
8+
9+
"github.com/hashicorp/hcl/hcl/ast"
10+
)
11+
12+
// TornjakServerInfo provides insight into the configuration of the SPIRE server
13+
// where the Tornjak Agent resides
14+
type TornjakSpireServerInfo struct {
15+
// Plugins is a map from plugin types to respective names of plugins configured
16+
Plugins map[string][]string `json:"plugins"`
17+
// TrustDomain specifies the trust domain of the SPIRE server configured with tornjak
18+
TrustDomain string `json:"trustDomain"`
19+
// Verbose config contains unstructure information on the config on the agent
20+
VerboseConfig string `json:"verboseConfig"`
21+
}
22+
23+
// pared down version of full Server Config type spire/cmd/spire-server/cli/run
24+
// we curently need only extract the trust domain
25+
type SpireServerConfig struct {
26+
TrustDomain string `hcl:"trust_domain"`
27+
}
28+
29+
type SPIREConfig struct {
30+
Server *SpireServerConfig `hcl:"server"`
31+
Plugins ast.Node `hcl:"plugins"`
32+
}
33+
34+
type TornjakConfig struct {
35+
Server *serverConfig `hcl:"server"`
36+
Plugins *ast.Node `hcl:"plugins"`
37+
}
38+
39+
/* Server configuration*/
40+
41+
type serverConfig struct {
42+
SPIRESocket string `hcl:"spire_socket_path"`
43+
HTTPConfig *HTTPConfig `hcl:"http"`
44+
HTTPSConfig *HTTPSConfig `hcl:"https"`
45+
}
46+
47+
type HTTPConfig struct {
48+
ListenPort int `hcl:"port"`
49+
}
50+
51+
type HTTPSConfig struct {
52+
ListenPort int `hcl:"port"`
53+
Cert string `hcl:"cert"`
54+
Key string `hcl:"key"`
55+
ClientCA string `hcl:"client_ca"`
56+
}
57+
58+
func (h HTTPSConfig) Parse() (*tls.Config, error) {
59+
serverCertPath := h.Cert
60+
serverKeyPath := h.Key
61+
clientCAPath := h.ClientCA
62+
63+
mtls := (clientCAPath != "")
64+
65+
if _, err := os.Stat(serverCertPath); os.IsNotExist(err) {
66+
return nil, fmt.Errorf("server cert path '%s': %w", serverCertPath, err)
67+
}
68+
if _, err := os.Stat(serverKeyPath); os.IsNotExist(err) {
69+
return nil, fmt.Errorf("server key path '%s': %w", serverKeyPath, err)
70+
}
71+
72+
// Create a CA certificate pool and add cert.pem to it
73+
serverCert, err := os.ReadFile(serverCertPath)
74+
if err != nil {
75+
return nil, fmt.Errorf("server ca pool error: %w", err)
76+
}
77+
caCertPool := x509.NewCertPool()
78+
caCertPool.AppendCertsFromPEM(serverCert)
79+
80+
if mtls {
81+
// add mTLS CA path to cert pool as well
82+
if _, err := os.Stat(clientCAPath); os.IsNotExist(err) {
83+
return nil, fmt.Errorf("server file does not exist %s", clientCAPath)
84+
}
85+
clientCA, err := os.ReadFile(clientCAPath)
86+
if err != nil {
87+
return nil, fmt.Errorf("server: could not read file %s: %w", clientCAPath, err)
88+
}
89+
caCertPool.AppendCertsFromPEM(clientCA)
90+
}
91+
92+
// Create the TLS Config with the CA pool and enable Client certificate validation
93+
tlsConfig := &tls.Config{
94+
ClientCAs: caCertPool,
95+
}
96+
97+
if mtls {
98+
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
99+
}
100+
//tlsConfig.BuildNameToCertificate()
101+
102+
return tlsConfig, nil
103+
}
104+
105+
/* Plugin types */
106+
type pluginDataStoreSQL struct {
107+
Drivername string `hcl:"drivername"`
108+
Filename string `hcl:"filename"`
109+
}
110+
111+
type pluginControllerManager struct {
112+
Classname string `hcl:"classname"`
113+
}
114+
115+
type pluginAuthenticatorKeycloak struct {
116+
IssuerURL string `hcl:"issuer"`
117+
Audience string `hcl:"audience"`
118+
}
119+
120+
type AuthRole struct {
121+
Name string `hcl:",key"`
122+
Desc string `hcl:"desc"`
123+
}
124+
125+
type APIv1RoleMapping struct {
126+
Name string `hcl:",key"`
127+
Method string `hcl:"-"`
128+
Path string `hcl:"-"`
129+
AllowedRoles []string `hcl:"allowed_roles"`
130+
}
131+
132+
type pluginAuthorizerRBAC struct {
133+
Name string `hcl:"name"`
134+
RoleList []*AuthRole `hcl:"role,block"`
135+
APIv1RoleMappings []*APIv1RoleMapping `hcl:"APIv1,block"`
136+
}

0 commit comments

Comments
 (0)