Skip to content

Commit

Permalink
Merge main into current
Browse files Browse the repository at this point in the history
  • Loading branch information
nialdaly committed Jan 8, 2025
2 parents 1d0f9aa + 12a0f6b commit d495ee6
Show file tree
Hide file tree
Showing 58 changed files with 2,401 additions and 1,149 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ jobs:
federation:
name: federation
runs-on: ubuntu-latest
strategy:
matrix:
# Repeat the test with in-process plugins and the test gRPC plugin.
plugin:
- ""
- "cofidectl-test-plugin"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -80,6 +86,10 @@ jobs:
push: false
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build and install test plugin
run: just install-test-plugin
if: ${{ matrix.plugin == 'cofidectl-test-plugin' }}

- name: Install ko
uses: ko-build/[email protected]
Expand All @@ -91,3 +101,6 @@ jobs:

- name: Test
run: just integration-test federation
env:
DATA_SOURCE_PLUGIN: ${{ matrix.plugin }}
PROVISION_PLUGIN: ${{ matrix.plugin }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cofide.yaml

# Plugins
cofidectl-connect
cofidectl-test-plugin

# cofide-demos repository
demos/cofide-demos/
8 changes: 5 additions & 3 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ linters-settings:
values:
const:
COMPANY: Cofide Limited
regexp:
VALID_YEAR: 202[4-9]|20[3-9][0-9]|2[1-9][0-9][0-9]
# Require Cofide copyright and SPDX license in all source files.
template: |
Copyright {{ MOD-YEAR }} {{ COMPANY }}.
SPDX-License-Identifier: Apache-2.0
template: |-
Copyright {{ VALID_YEAR }} {{ COMPANY }}.
SPDX-License-Identifier: Apache-2.0
7 changes: 7 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
build: test
go build -o cofidectl ./cmd/cofidectl/main.go

build-test-plugin:
go build -o cofidectl-test-plugin ./cmd/cofidectl-test-plugin/main.go

install-test-plugin: build-test-plugin
mkdir -p ~/.cofide/plugins
cp cofidectl-test-plugin ~/.cofide/plugins

test:
go run gotest.tools/gotestsum@latest --format github-actions ./...

Expand Down
74 changes: 74 additions & 0 deletions cmd/cofidectl-test-plugin/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2024 Cofide Limited.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"fmt"
"log"
"os"

"github.com/cofide/cofidectl/internal/pkg/config"
cmdcontext "github.com/cofide/cofidectl/pkg/cmd/context"
"github.com/cofide/cofidectl/pkg/plugin"
"github.com/cofide/cofidectl/pkg/plugin/datasource"
"github.com/cofide/cofidectl/pkg/plugin/local"
"github.com/cofide/cofidectl/pkg/plugin/provision"
"github.com/cofide/cofidectl/pkg/plugin/provision/spirehelm"
"github.com/hashicorp/go-hclog"
go_plugin "github.com/hashicorp/go-plugin"
)

const (
cofideConfigFile = "cofide.yaml"
)

func main() {
log.SetFlags(0)
if err := run(); err != nil {
// This should be the only place that calls os.Exit, to ensure proper clean up.
// This includes functions that call os.Exit, e.g. cobra.CheckErr, log.Fatal
os.Exit(1)
}
}

func run() error {
cmdCtx := cmdcontext.NewCommandContext(cofideConfigFile)
defer cmdCtx.Shutdown()
go cmdCtx.HandleSignals()

// If the CLI is invoked with arguments plugin serve, the gRPC plugins are served.
if plugin.IsPluginServeCmd(os.Args[1:]) {
return serveDataSource()
}
return fmt.Errorf("unexpected command arguments: %v", os.Args[1:])
}

func serveDataSource() error {
// go-plugin client expects logs on stdout.
log.SetOutput(os.Stdout)

logger := hclog.New(&hclog.LoggerOptions{
Output: os.Stderr,
// Log at trace level in the plugin, it will be filtered in the host.
Level: hclog.Trace,
JSONFormat: true,
})

lds, err := local.NewLocalDataSource(config.NewFileLoader(cofideConfigFile))
if err != nil {
return err
}
spireHelm := spirehelm.NewSpireHelm(nil)

go_plugin.Serve(&go_plugin.ServeConfig{
HandshakeConfig: plugin.HandshakeConfig,
Plugins: map[string]go_plugin.Plugin{
datasource.DataSourcePluginName: &datasource.DataSourcePlugin{Impl: lds},
provision.ProvisionPluginName: &provision.ProvisionPlugin{Impl: spireHelm},
},
Logger: logger,
GRPCServer: go_plugin.DefaultGRPCServer,
})
return nil
}
10 changes: 5 additions & 5 deletions cmd/cofidectl/cmd/apbinding/apbinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
ap_binding_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/ap_binding/v1alpha1"
trust_zone_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_zone/v1alpha1"
cmdcontext "github.com/cofide/cofidectl/pkg/cmd/context"
cofidectl_plugin "github.com/cofide/cofidectl/pkg/plugin"
"github.com/cofide/cofidectl/pkg/plugin/datasource"

"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -64,7 +64,7 @@ func (c *APBindingCommand) GetListCommand() *cobra.Command {
Long: apBindingListCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand All @@ -85,7 +85,7 @@ func (c *APBindingCommand) GetListCommand() *cobra.Command {
return cmd
}

func (c *APBindingCommand) list(source cofidectl_plugin.DataSource, opts ListOpts) ([]*ap_binding_proto.APBinding, error) {
func (c *APBindingCommand) list(source datasource.DataSource, opts ListOpts) ([]*ap_binding_proto.APBinding, error) {
var err error
var trustZones []*trust_zone_proto.TrustZone

Expand Down Expand Up @@ -149,7 +149,7 @@ func (c *APBindingCommand) GetAddCommand() *cobra.Command {
Long: apBindingAddCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand Down Expand Up @@ -191,7 +191,7 @@ func (c *APBindingCommand) GetDelCommand() *cobra.Command {
Long: apBindingDelCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/cofidectl/cmd/attestationpolicy/attestationpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (c *AttestationPolicyCommand) GetListCommand() *cobra.Command {
Long: attestationPolicyListCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand Down Expand Up @@ -162,7 +162,7 @@ func (c *AttestationPolicyCommand) GetAddK8sCommand() *cobra.Command {
Long: attestationPolicyAddK8sCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand Down
10 changes: 7 additions & 3 deletions cmd/cofidectl/cmd/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ func (d *DownCommand) DownCmd() *cobra.Command {
Long: downCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := d.cmdCtx.PluginManager.GetDataSource()
ds, err := d.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}

provision := d.cmdCtx.PluginManager.GetProvision()
statusCh, err := provision.TearDown(cmd.Context(), ds)
provision, err := d.cmdCtx.PluginManager.GetProvision(cmd.Context())
if err != nil {
return err
}

statusCh, err := provision.TearDown(cmd.Context(), ds, kubeCfgFile)
if err != nil {
return err
}
Expand Down
35 changes: 22 additions & 13 deletions cmd/cofidectl/cmd/federation/federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ import (
trust_zone_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_zone/v1alpha1"
cmdcontext "github.com/cofide/cofidectl/pkg/cmd/context"

"github.com/cofide/cofidectl/pkg/spire"
kubeutil "github.com/cofide/cofidectl/pkg/kube"
"github.com/cofide/cofidectl/pkg/provider/helm"
"github.com/cofide/cofidectl/pkg/spire"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
)

const (
FederationStatusHealthy string = "Healthy"
FederationStatusUnhealthy string = "Unhealthy"

FederationStatusReasonNoBundleFound string = "No bundle found"
FederationStatusReasonBundlesDoNotMatch string = "Bundles do not match"
)

type FederationCommand struct {
cmdCtx *cmdcontext.CommandContext
}
Expand Down Expand Up @@ -57,7 +65,7 @@ func (c *FederationCommand) GetListCommand() *cobra.Command {
Long: federationListCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand All @@ -84,7 +92,7 @@ func (c *FederationCommand) GetListCommand() *cobra.Command {
return err
}

status, err := checkFederationStatus(cmd.Context(), kubeConfig, from, to)
status, reason, err := checkFederationStatus(cmd.Context(), kubeConfig, from, to)
if err != nil {
return err
}
Expand All @@ -93,11 +101,12 @@ func (c *FederationCommand) GetListCommand() *cobra.Command {
federation.From,
federation.To,
status,
reason,
}
}

table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"From Trust Zone", "To Trust Zone", "Status"})
table.SetHeader([]string{"From Trust Zone", "To Trust Zone", "Status", "Reason"})
table.SetBorder(false)
table.AppendBulk(data)
table.Render()
Expand All @@ -115,24 +124,24 @@ type bundles struct {

// checkFederationStatus builds a comparison map between two trust domains, retrieves there server CA bundle and any federated bundles available
// locally from the SPIRE server, and then compares the bundles on each to verify SPIRE has the correct bundles on each side of the federation
func checkFederationStatus(ctx context.Context, kubeConfig string, from *trust_zone_proto.TrustZone, to *trust_zone_proto.TrustZone) (string, error) {
func checkFederationStatus(ctx context.Context, kubeConfig string, from *trust_zone_proto.TrustZone, to *trust_zone_proto.TrustZone) (string, string, error) {
compare := make(map[*trust_zone_proto.TrustZone]bundles)

for _, tz := range []*trust_zone_proto.TrustZone{from, to} {
if deployed, err := isTrustZoneDeployed(ctx, tz); err != nil {
return "", err
return "", "", err
} else if !deployed {
return "Inactive", nil
return "Inactive", "", nil
}

client, err := kubeutil.NewKubeClientFromSpecifiedContext(kubeConfig, tz.GetKubernetesContext())
if err != nil {
return "", err
return "", "", err
}

serverCABundle, federatedBundles, err := spire.GetServerCABundleAndFederatedBundles(ctx, client)
if err != nil {
return "", err
return "", "", err
}

compare[tz] = bundles{
Expand All @@ -144,15 +153,15 @@ func checkFederationStatus(ctx context.Context, kubeConfig string, from *trust_z
// Bundle does not exist at all on opposite trust domain
_, ok := compare[from].federatedBundles[to.TrustDomain]
if !ok {
return "Unhealthy", nil
return FederationStatusUnhealthy, FederationStatusReasonNoBundleFound, nil
}

// Bundle does not match entry on opposite trust domain
if compare[from].federatedBundles[to.TrustDomain] != compare[to].serverCABundle {
return "Unhealthy", nil
return FederationStatusUnhealthy, FederationStatusReasonBundlesDoNotMatch, nil
}

return "Healthy", nil
return FederationStatusHealthy, "", nil
}

// isTrustZoneDeployed returns whether a trust zone has been deployed, i.e. whether a SPIRE Helm release has been installed.
Expand Down Expand Up @@ -181,7 +190,7 @@ func (c *FederationCommand) GetAddCommand() *cobra.Command {
Long: federationAddCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ds, err := c.cmdCtx.PluginManager.GetDataSource()
ds, err := c.cmdCtx.PluginManager.GetDataSource(cmd.Context())
if err != nil {
return err
}
Expand Down
23 changes: 14 additions & 9 deletions cmd/cofidectl/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os"

pluginspb "github.com/cofide/cofide-api-sdk/gen/go/proto/plugins/v1alpha1"
"github.com/cofide/cofidectl/pkg/cmd/context"
"github.com/cofide/cofidectl/pkg/plugin"
"github.com/cofide/cofidectl/pkg/plugin/manager"
Expand All @@ -33,7 +34,9 @@ directory
`

type Opts struct {
enableConnect bool
enableConnect bool
dataSourcePlugin string
provisionPlugin string
}

func (i *InitCommand) GetRootCommand() *cobra.Command {
Expand All @@ -44,26 +47,28 @@ func (i *InitCommand) GetRootCommand() *cobra.Command {
Long: initRootCmdDesc,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
var pluginName string
if opts.enableConnect {
if ok, _ := plugin.PluginExists(connectPluginName); ok {
pluginName = connectPluginName
fmt.Println(`Please run "cofidectl connect init"`)
} else {
fmt.Println("👀 get in touch with us at [email protected] to find out more")
os.Exit(1)
}
} else {
// Default to the local file data source.
pluginName = manager.LocalPluginName
os.Exit(1)
}

_, err := i.cmdCtx.PluginManager.Init(pluginName, nil)
return err
plugins := &pluginspb.Plugins{
DataSource: &opts.dataSourcePlugin,
Provision: &opts.provisionPlugin,
}
return i.cmdCtx.PluginManager.Init(cmd.Context(), plugins, nil)
},
}

defaultPlugins := manager.GetDefaultPlugins()
f := cmd.Flags()
f.BoolVar(&opts.enableConnect, "enable-connect", false, "Enables Cofide Connect")
f.StringVar(&opts.dataSourcePlugin, "data-source-plugin", defaultPlugins.GetDataSource(), "Data source plugin")
f.StringVar(&opts.provisionPlugin, "provision-plugin", defaultPlugins.GetProvision(), "Provision plugin")

return cmd
}
Loading

0 comments on commit d495ee6

Please sign in to comment.