AB#2061 Self Documenting Config File (#143)

Move firewall up into root config, remove VPC config & autogenerate comments in config file.
This commit is contained in:
Fabian Kammel 2022-05-16 18:54:25 +02:00 committed by GitHub
parent cdfd962fcc
commit b905c28515
20 changed files with 538 additions and 348 deletions

View File

@ -11,7 +11,7 @@ import (
type gcpclient interface {
GetState() (state.ConstellationState, error)
SetState(state.ConstellationState) error
CreateVPCs(ctx context.Context, input gcpcl.VPCsInput) error
CreateVPCs(ctx context.Context) error
CreateFirewall(ctx context.Context, input gcpcl.FirewallInput) error
CreateInstances(ctx context.Context, input gcpcl.CreateInstancesInput) error
CreateServiceAccount(ctx context.Context, input gcpcl.ServiceAccountInput) (string, error)

View File

@ -261,7 +261,7 @@ func (c *fakeGcpClient) SetState(stat state.ConstellationState) error {
return nil
}
func (c *fakeGcpClient) CreateVPCs(ctx context.Context, input gcpcl.VPCsInput) error {
func (c *fakeGcpClient) CreateVPCs(ctx context.Context) error {
c.network = "network"
c.subnetwork = "subnetwork"
return nil
@ -377,7 +377,7 @@ func (c *stubGcpClient) SetState(state.ConstellationState) error {
return c.setStateErr
}
func (c *stubGcpClient) CreateVPCs(ctx context.Context, input gcpcl.VPCsInput) error {
func (c *stubGcpClient) CreateVPCs(ctx context.Context) error {
return c.createVPCsErr
}

View File

@ -6,6 +6,7 @@ import (
"io"
azurecl "github.com/edgelesssys/constellation/cli/azure/client"
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
"github.com/edgelesssys/constellation/cli/cloudprovider"
"github.com/edgelesssys/constellation/cli/gcp"
"github.com/edgelesssys/constellation/cli/gcp/client"
@ -41,9 +42,9 @@ func (c *Creator) Create(ctx context.Context, provider cloudprovider.Provider, c
case cloudprovider.GCP:
cl, err := c.newGCPClient(
ctx,
*config.Provider.GCP.Project,
*config.Provider.GCP.Zone,
*config.Provider.GCP.Region,
config.Provider.GCP.Project,
config.Provider.GCP.Zone,
config.Provider.GCP.Region,
name,
)
if err != nil {
@ -53,10 +54,10 @@ func (c *Creator) Create(ctx context.Context, provider cloudprovider.Provider, c
return c.createGCP(ctx, cl, config, insType, coordCount, nodeCount)
case cloudprovider.Azure:
cl, err := c.newAzureClient(
*config.Provider.Azure.SubscriptionID,
*config.Provider.Azure.TenantID,
config.Provider.Azure.SubscriptionID,
config.Provider.Azure.TenantID,
name,
*config.Provider.Azure.Location,
config.Provider.Azure.Location,
)
if err != nil {
return state.ConstellationState{}, err
@ -71,19 +72,22 @@ func (c *Creator) createGCP(ctx context.Context, cl gcpclient, config *config.Co
) (stat state.ConstellationState, retErr error) {
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerGCP{client: cl})
if err := cl.CreateVPCs(ctx, *config.Provider.GCP.VPCsInput); err != nil {
if err := cl.CreateVPCs(ctx); err != nil {
return state.ConstellationState{}, err
}
if err := cl.CreateFirewall(ctx, *config.Provider.GCP.FirewallInput); err != nil {
if err := cl.CreateFirewall(ctx, gcpcl.FirewallInput{
Ingress: cloudtypes.Firewall(config.IngressFirewall),
Egress: cloudtypes.Firewall(config.EgressFirewall),
}); err != nil {
return state.ConstellationState{}, err
}
createInput := client.CreateInstancesInput{
CountCoordinators: coordCount,
CountNodes: nodeCount,
ImageId: *config.Provider.GCP.Image,
ImageId: config.Provider.GCP.Image,
InstanceType: insType,
StateDiskSizeGB: *config.StateDiskSizeGB,
StateDiskSizeGB: config.StateDiskSizeGB,
KubeEnv: gcp.KubeEnv,
}
if err := cl.CreateInstances(ctx, createInput); err != nil {
@ -103,16 +107,20 @@ func (c *Creator) createAzure(ctx context.Context, cl azureclient, config *confi
if err := cl.CreateVirtualNetwork(ctx); err != nil {
return state.ConstellationState{}, err
}
if err := cl.CreateSecurityGroup(ctx, *config.Provider.Azure.NetworkSecurityGroupInput); err != nil {
if err := cl.CreateSecurityGroup(ctx, azurecl.NetworkSecurityGroupInput{
Ingress: cloudtypes.Firewall(config.IngressFirewall),
Egress: cloudtypes.Firewall(config.EgressFirewall),
}); err != nil {
return state.ConstellationState{}, err
}
createInput := azurecl.CreateInstancesInput{
CountCoordinators: coordCount,
CountNodes: nodeCount,
InstanceType: insType,
StateDiskSizeGB: *config.StateDiskSizeGB,
Image: *config.Provider.Azure.Image,
UserAssingedIdentity: *config.Provider.Azure.UserAssignedIdentity,
StateDiskSizeGB: config.StateDiskSizeGB,
Image: config.Provider.Azure.Image,
UserAssingedIdentity: config.Provider.Azure.UserAssignedIdentity,
}
if err := cl.CreateInstances(ctx, createInput); err != nil {
return state.ConstellationState{}, err

View File

@ -73,7 +73,7 @@ func (c *ServiceAccountCreator) createServiceAccountGCP(ctx context.Context, cl
}
input := gcpcl.ServiceAccountInput{
Roles: *config.Provider.GCP.ServiceAccountRoles,
Roles: config.Provider.GCP.ServiceAccountRoles,
}
serviceAccount, err := cl.CreateServiceAccount(ctx, input)
if err != nil {

View File

@ -68,19 +68,19 @@ func (v *Validators) updatePCR(pcrIndex uint32, encoded string) error {
func (v *Validators) setPCRs(config *config.Config) error {
switch v.provider {
case cloudprovider.GCP:
gcpPCRs := *config.Provider.GCP.Measurements
gcpPCRs := config.Provider.GCP.Measurements
if err := v.checkPCRs(gcpPCRs); err != nil {
return err
}
v.pcrs = gcpPCRs
case cloudprovider.Azure:
azurePCRs := *config.Provider.Azure.Measurements
azurePCRs := config.Provider.Azure.Measurements
if err := v.checkPCRs(azurePCRs); err != nil {
return err
}
v.pcrs = azurePCRs
case cloudprovider.QEMU:
qemuPCRs := *config.Provider.QEMU.Measurements
qemuPCRs := config.Provider.QEMU.Measurements
if err := v.checkPCRs(qemuPCRs); err != nil {
return err
}

View File

@ -66,18 +66,18 @@ func TestNewValidators(t *testing.T) {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
conf := &config.Config{Provider: &config.ProviderConfig{}}
conf := &config.Config{Provider: config.ProviderConfig{}}
if tc.provider == cloudprovider.GCP {
measurements := config.Measurements(tc.pcrs)
conf.Provider.GCP = &config.GCPConfig{Measurements: &measurements}
conf.Provider.GCP = &config.GCPConfig{Measurements: measurements}
}
if tc.provider == cloudprovider.Azure {
measurements := config.Measurements(tc.pcrs)
conf.Provider.Azure = &config.AzureConfig{Measurements: &measurements}
conf.Provider.Azure = &config.AzureConfig{Measurements: measurements}
}
if tc.provider == cloudprovider.QEMU {
measurements := config.Measurements(tc.pcrs)
conf.Provider.QEMU = &config.QEMUConfig{Measurements: &measurements}
conf.Provider.QEMU = &config.QEMUConfig{Measurements: measurements}
}
validators, err := NewValidators(tc.provider, conf)

View File

@ -6,20 +6,14 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/edgelesssys/constellation/internal/config"
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
"google.golang.org/protobuf/proto"
)
type FirewallRule struct {
Name string
Description string
Protocol string
IPRange string
FromPort int
ToPort int
}
type FirewallRule = config.FirewallRule
type Firewall []FirewallRule
type Firewall config.Firewall
func (f Firewall) GCP() ([]*computepb.Firewall, error) {
var fw []*computepb.Firewall

View File

@ -6,7 +6,7 @@ import (
"github.com/edgelesssys/constellation/internal/file"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
"github.com/talos-systems/talos/pkg/machinery/config/encoder"
)
func newConfigGenerateCmd() *cobra.Command {
@ -38,7 +38,12 @@ func configGenerate(cmd *cobra.Command, fileHandler file.Handler) error {
}
if flags.file == "-" {
return yaml.NewEncoder(cmd.OutOrStdout()).Encode(config.Default())
content, err := encoder.NewEncoder(config.Default()).Encode()
if err != nil {
return err
}
_, err = cmd.OutOrStdout().Write(content)
return err
}
return fileHandler.WriteYAML(flags.file, config.Default(), 0o644)

View File

@ -13,12 +13,6 @@ import (
"gopkg.in/yaml.v3"
)
func defaultConfigAsYAML(t *testing.T) string {
var readBuffer bytes.Buffer
require.NoError(t, yaml.NewEncoder(&readBuffer).Encode(config.Default()))
return readBuffer.String()
}
func TestConfigGenerateDefault(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
@ -28,9 +22,10 @@ func TestConfigGenerateDefault(t *testing.T) {
require.NoError(configGenerate(cmd, fileHandler))
readYAML, err := fileHandler.Read(constants.ConfigFilename)
var readConfig config.Config
err := fileHandler.ReadYAML(constants.ConfigFilename, &readConfig)
assert.NoError(err)
assert.Equal(defaultConfigAsYAML(t), string(readYAML))
assert.Equal(*config.Default(), readConfig)
}
func TestConfigGenerateDefaultExists(t *testing.T) {
@ -66,5 +61,8 @@ func TestConfigGenerateStdOut(t *testing.T) {
require.NoError(configGenerate(cmd, fileHandler))
assert.Equal(defaultConfigAsYAML(t), outBuffer.String())
var readConfig config.Config
require.NoError(yaml.NewDecoder(&outBuffer).Decode(&readConfig))
assert.Equal(*config.Default(), readConfig)
}

View File

@ -460,7 +460,7 @@ func getGCPInstances(stat state.ConstellationState, config *config.Config) (coor
// TODO: make min / max configurable and abstract autoscaling for different cloud providers
nodes = ScalingGroup{
Instances: nodeInstances,
GroupID: gcp.AutoscalingNodeGroup(stat.GCPProject, stat.GCPZone, stat.GCPNodeInstanceGroup, *config.AutoscalingNodeGroupsMin, *config.AutoscalingNodeGroupsMax),
GroupID: gcp.AutoscalingNodeGroup(stat.GCPProject, stat.GCPZone, stat.GCPNodeInstanceGroup, config.AutoscalingNodeGroupsMin, config.AutoscalingNodeGroupsMax),
}
return
@ -493,7 +493,7 @@ func getAzureInstances(stat state.ConstellationState, config *config.Config) (co
// TODO: make min / max configurable and abstract autoscaling for different cloud providers
nodes = ScalingGroup{
Instances: nodeInstances,
GroupID: azure.AutoscalingNodeGroup(stat.AzureNodesScaleSet, *config.AutoscalingNodeGroupsMin, *config.AutoscalingNodeGroupsMax),
GroupID: azure.AutoscalingNodeGroup(stat.AzureNodesScaleSet, config.AutoscalingNodeGroupsMin, config.AutoscalingNodeGroupsMax),
}
return
}

View File

@ -78,14 +78,8 @@ type FirewallInput struct {
Egress cloudtypes.Firewall
}
// VPCsInput defines the VPC configuration.
type VPCsInput struct {
SubnetCIDR string
SubnetExtCIDR string
}
// CreateVPCs creates all necessary VPC networks.
func (c *Client) CreateVPCs(ctx context.Context, input VPCsInput) error {
func (c *Client) CreateVPCs(ctx context.Context) error {
c.network = c.name + "-" + c.uid
op, err := c.createVPC(ctx, c.network)
@ -96,7 +90,7 @@ func (c *Client) CreateVPCs(ctx context.Context, input VPCsInput) error {
return err
}
if err := c.createSubnets(ctx, input.SubnetCIDR); err != nil {
if err := c.createSubnets(ctx); err != nil {
return err
}
@ -152,11 +146,11 @@ func (c *Client) terminateVPC(ctx context.Context, network string) (Operation, e
return c.networksAPI.Delete(ctx, req)
}
func (c *Client) createSubnets(ctx context.Context, subnetCIDR string) error {
func (c *Client) createSubnets(ctx context.Context) error {
c.subnetwork = "node-net-" + c.uid
c.secondarySubnetworkRange = "net-ext" + c.uid
op, err := c.createSubnet(ctx, c.subnetwork, subnetCIDR, c.network, c.secondarySubnetworkRange)
op, err := c.createSubnet(ctx, c.subnetwork, c.network, c.secondarySubnetworkRange)
if err != nil {
return err
}
@ -164,12 +158,12 @@ func (c *Client) createSubnets(ctx context.Context, subnetCIDR string) error {
return c.waitForOperations(ctx, []Operation{op})
}
func (c *Client) createSubnet(ctx context.Context, name, cidr, network, secondaryRangeName string) (Operation, error) {
func (c *Client) createSubnet(ctx context.Context, name, network, secondaryRangeName string) (Operation, error) {
req := &computepb.InsertSubnetworkRequest{
Project: c.project,
Region: c.region,
SubnetworkResource: &computepb.Subnetwork{
IpCidrRange: proto.String(cidr),
IpCidrRange: proto.String("192.168.178.0/24"),
Name: proto.String(name),
Network: proto.String("projects/" + c.project + "/global/networks/" + network),
SecondaryIpRanges: []*computepb.SubnetworkSecondaryRange{

View File

@ -13,11 +13,6 @@ import (
func TestCreateVPCs(t *testing.T) {
someErr := errors.New("failed")
testInput := VPCsInput{
SubnetCIDR: "192.0.2.0/24",
SubnetExtCIDR: "198.51.100.0/24",
}
testCases := map[string]struct {
operationGlobalAPI operationGlobalAPI
operationRegionAPI operationRegionAPI
@ -80,9 +75,9 @@ func TestCreateVPCs(t *testing.T) {
}
if tc.wantErr {
assert.Error(client.CreateVPCs(ctx, testInput))
assert.Error(client.CreateVPCs(ctx))
} else {
assert.NoError(client.CreateVPCs(ctx, testInput))
assert.NoError(client.CreateVPCs(ctx))
assert.NotNil(client.network)
}
})

View File

@ -85,7 +85,7 @@ func getGCPInstances(stat state.ConstellationState, config *configc.Config) (coo
// TODO: make min / max configurable and abstract autoscaling for different cloud providers
nodes = cmdc.ScalingGroup{
Instances: nodeInstances,
GroupID: gcp.AutoscalingNodeGroup(stat.GCPProject, stat.GCPZone, stat.GCPNodeInstanceGroup, *config.AutoscalingNodeGroupsMin, *config.AutoscalingNodeGroupsMax),
GroupID: gcp.AutoscalingNodeGroup(stat.GCPProject, stat.GCPZone, stat.GCPNodeInstanceGroup, config.AutoscalingNodeGroupsMin, config.AutoscalingNodeGroupsMax),
}
return

3
go.mod
View File

@ -77,6 +77,7 @@ require (
github.com/spf13/afero v1.8.2
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.1
github.com/talos-systems/talos/pkg/machinery v1.0.4
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
github.com/willdonnelly/passwd v0.0.0-20141013001024-7935dab3074c
go.etcd.io/etcd/client/v3 v3.5.2
@ -90,7 +91,7 @@ require (
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99
k8s.io/api v0.24.0
k8s.io/apimachinery v0.24.0
k8s.io/cli-runtime v0.24.0

5
go.sum
View File

@ -1402,6 +1402,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/talos-systems/talos/pkg/machinery v1.0.4 h1:zUZgIRSxAXOI6LygMDUqgS0rtFTf4DpDCL35UpW/6s4=
github.com/talos-systems/talos/pkg/machinery v1.0.4/go.mod h1:cJ/031WJGDnGQLW+zp+0lwkEn47orpJdfsJDf0BQVGM=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
@ -2280,8 +2282,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99 h1:dbuHpmKjkDzSOMKAWl10QNlgaZUd3V1q99xc81tt2Kc=
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

View File

@ -1,3 +1,6 @@
//go:generate docgen ./config.go ./config_doc.go Configuration
// This binary can be build from siderolabs/talos projects. Located at:
// https://github.com/siderolabs/talos/tree/master/hack/docgen
package config
import (
@ -5,267 +8,207 @@ import (
"fmt"
"io/fs"
azureClient "github.com/edgelesssys/constellation/cli/azure/client"
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
"github.com/edgelesssys/constellation/cli/ec2"
awsClient "github.com/edgelesssys/constellation/cli/ec2/client"
gcpClient "github.com/edgelesssys/constellation/cli/gcp/client"
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
"github.com/edgelesssys/constellation/internal/constants"
"github.com/edgelesssys/constellation/internal/deploy/ssh"
"github.com/edgelesssys/constellation/internal/file"
"google.golang.org/protobuf/proto"
)
var (
// gcpPCRs is a map of the expected PCR values for a GCP Constellation node.
// TODO: Get a full list once we have stable releases.
gcpPCRs = Measurements{
0: {0x0F, 0x35, 0xC2, 0x14, 0x60, 0x8D, 0x93, 0xC7, 0xA6, 0xE6, 0x8A, 0xE7, 0x35, 0x9B, 0x4A, 0x8B, 0xE5, 0xA0, 0xE9, 0x9E, 0xEA, 0x91, 0x07, 0xEC, 0xE4, 0x27, 0xC4, 0xDE, 0xA4, 0xE4, 0x39, 0xCF},
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
// azurePCRs is a map of the expected PCR values for an Azure Constellation node.
// TODO: Get a full list once we have a working setup with stable releases.
azurePCRs = Measurements{
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
qemuPCRs = Measurements{
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
)
// Config defines a configuration used by the CLI.
// All fields in this struct and its child structs have pointer types
// to ensure the default values of the actual type is not confused with an omitted value.
// Config defines configuration used by CLI.
type Config struct {
AutoscalingNodeGroupsMin *int `yaml:"autoscalingNodeGroupsMin,omitempty"`
AutoscalingNodeGroupsMax *int `yaml:"autoscalingNodeGroupsMax,omitempty"`
StateDiskSizeGB *int `yaml:"StateDisksizeGB,omitempty"`
Provider *ProviderConfig `yaml:"provider,omitempty"`
SSHUsers []*ssh.UserKey `yaml:"sshUsers,omitempty"`
// description: |
// Minimum number of nodes in autoscaling group.
// worker nodes.
AutoscalingNodeGroupsMin int `yaml:"autoscalingNodeGroupsMin"`
// description: |
// Maximum number of nodes in autoscaling group.
// worker nodes.
AutoscalingNodeGroupsMax int `yaml:"autoscalingNodeGroupsMax"`
// description: |
// Size (in GB) of data disk used for nodes.
StateDiskSizeGB int `yaml:"stateDisksizeGB"`
// description: |
// Ingress firewall rules for node network.
IngressFirewall Firewall `yaml:"ingressFirewall,omitempty"`
// description: |
// Egress firewall rules for node network.
EgressFirewall Firewall `yaml:"egressFirewall,omitempty"`
// description: |
// Supported cloud providers & their specific configurations.
Provider ProviderConfig `yaml:"provider"`
// description: |
// Create SSH users on Constellation nodes.
SSHUsers []*ssh.UserKey `yaml:"sshUsers,omitempty"`
}
type FirewallRule struct {
// description: |
// Name of rule.
Name string `yaml:"name"`
// description: |
// Description for rule.
Description string `yaml:"description"`
// description: |
// Protocol, such as 'udp' or 'tcp'.
Protocol string `yaml:"protocol"`
// description: |
// CIDR range for which this rule is applied.
IPRange string `yaml:"iprange"`
// description: |
// Port of start port of a range.
FromPort int `yaml:"fromport"`
// description: |
// End port of a range, or 0 if a single port is given by FromPort.
ToPort int `yaml:"toport"`
}
type Firewall []FirewallRule
// ProviderConfig are cloud-provider specific configuration values used by the CLI.
// Fields should remain pointer-types so custom specific configs can nil them
// if not required.
type ProviderConfig struct {
// description: |
// Configuration for Azure as provider.
Azure *AzureConfig `yaml:"azureConfig,omitempty"`
// description: |
// Configuration for Google Cloud as provider.
GCP *GCPConfig `yaml:"gcpConfig,omitempty"`
// description: |
// Configuration for QEMU as provider.
QEMU *QEMUConfig `yaml:"qemuConfig,omitempty"`
}
// AzureConfig are Azure specific configuration values used by the CLI.
type AzureConfig struct {
// description: |
// Subscription ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription
SubscriptionID string `yaml:"subscription"`
// description: |
// Tenant ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant
TenantID string `yaml:"tenant"`
// description: |
// Azure datacenter region to be used. See: https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#azure-regions-with-availability-zones
Location string `yaml:"location"`
// description: |
// Machine image used to create Constellation nodes.
Image string `yaml:"image"`
// description: |
// Expected confidential VM measurements.
Measurements Measurements `yaml:"measurements"`
// description: |
// Authorize spawned VMs to access Azure API. See: https://constellation-docs.edgeless.systems/6c320851-bdd2-41d5-bf10-e27427398692/#/getting-started/install?id=azure
UserAssignedIdentity string `yaml:"userassignedIdentity"`
}
// GCPConfig are GCP specific configuration values used by the CLI.
type GCPConfig struct {
// description: |
// GCP project. See: https://support.google.com/googleapi/answer/7014113?hl=en
Project string `yaml:"project"`
// description: |
// GCP datacenter region. See: https://cloud.google.com/compute/docs/regions-zones#available
Region string `yaml:"region"`
// description: |
// GCP datacenter zone. See: https://cloud.google.com/compute/docs/regions-zones#available
Zone string `yaml:"zone"`
// description: |
// Machine image used to create Constellation nodes.
Image string `yaml:"image"`
// description: |
// Roles added to service account.
ServiceAccountRoles []string `yaml:"serviceAccountRoles"`
// description: |
// Measurement used to enable measured boot.
Measurements Measurements `yaml:"measurements"`
}
type QEMUConfig struct {
// description: |
// Measurement used to enable measured boot.
Measurements Measurements `yaml:"measurements"`
}
// Default returns a struct with the default config.
func Default() *Config {
return &Config{
AutoscalingNodeGroupsMin: intPtr(1),
AutoscalingNodeGroupsMax: intPtr(10),
StateDiskSizeGB: intPtr(30),
Provider: &ProviderConfig{
EC2: &EC2Config{
Image: proto.String("ami-07d3864beb84157d3"),
Tags: &[]ec2.Tag{
{
Key: "responsible",
Value: "cli",
},
{
Key: "Name",
Value: "Constellation",
},
},
SecurityGroupInput: &awsClient.SecurityGroupInput{
Inbound: cloudtypes.Firewall{
{
Description: "Coordinator default port",
Protocol: "TCP",
IPRange: "0.0.0.0/0",
FromPort: constants.CoordinatorPort,
},
{
Description: "Enclave SSH",
Protocol: "TCP",
IPRange: "0.0.0.0/0",
FromPort: constants.EnclaveSSHPort,
},
{
Description: "WireGuard default port",
Protocol: "UDP",
IPRange: "0.0.0.0/0",
FromPort: constants.WireguardPort,
},
{
Description: "SSH",
Protocol: "TCP",
IPRange: "0.0.0.0/0",
FromPort: constants.SSHPort,
},
{
Description: "NVMe over TCP",
Protocol: "TCP",
IPRange: "0.0.0.0/0",
FromPort: constants.NVMEOverTCPPort,
},
{
Description: "NodePort",
Protocol: "TCP",
IPRange: "0.0.0.0/0",
FromPort: constants.NodePortFrom,
ToPort: constants.NodePortTo,
},
},
},
AutoscalingNodeGroupsMin: 1,
AutoscalingNodeGroupsMax: 10,
StateDiskSizeGB: 30,
IngressFirewall: Firewall{
{
Name: "coordinator",
Description: "Coordinator default port",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.CoordinatorPort,
},
{
Name: "wireguard",
Description: "WireGuard default port",
Protocol: "udp",
IPRange: "0.0.0.0/0",
FromPort: constants.WireguardPort,
},
{
Name: "ssh",
Description: "SSH",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.SSHPort,
},
{
Name: "nodeport",
Description: "NodePort",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.NodePortFrom,
ToPort: constants.NodePortTo,
},
},
Provider: ProviderConfig{
Azure: &AzureConfig{
SubscriptionID: proto.String("0d202bbb-4fa7-4af8-8125-58c269a05435"),
TenantID: proto.String("adb650a8-5da3-4b15-b4b0-3daf65ff7626"),
Location: proto.String("North Europe"),
Image: proto.String("/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/CONSTELLATION-IMAGES/providers/Microsoft.Compute/galleries/Constellation/images/constellation-coreos/versions/0.0.1651150807"),
NetworkSecurityGroupInput: &azureClient.NetworkSecurityGroupInput{
Ingress: cloudtypes.Firewall{
{
Name: "coordinator",
Description: "Coordinator default port",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.CoordinatorPort,
},
{
Name: "wireguard",
Description: "WireGuard default port",
Protocol: "udp",
IPRange: "0.0.0.0/0",
FromPort: constants.WireguardPort,
},
{
Name: "ssh",
Description: "SSH",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.SSHPort,
},
{
Name: "nodeport",
Description: "NodePort",
Protocol: "tcp",
IPRange: "0.0.0.0/0",
FromPort: constants.NodePortFrom,
ToPort: constants.NodePortTo,
},
},
},
Measurements: &azurePCRs,
UserAssignedIdentity: proto.String("/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-dev-identity"),
SubscriptionID: "0d202bbb-4fa7-4af8-8125-58c269a05435",
TenantID: "adb650a8-5da3-4b15-b4b0-3daf65ff7626",
Location: "North Europe",
Image: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/CONSTELLATION-IMAGES/providers/Microsoft.Compute/galleries/Constellation/images/constellation-coreos/versions/0.0.1651150807",
Measurements: azurePCRs,
UserAssignedIdentity: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-dev-identity",
},
GCP: &GCPConfig{
Project: proto.String("constellation-331613"),
Region: proto.String("europe-west3"),
Zone: proto.String("europe-west3-b"),
Image: proto.String("projects/constellation-images/global/images/constellation-coreos-1651150807"),
FirewallInput: &gcpClient.FirewallInput{
Ingress: cloudtypes.Firewall{
{
Name: "coordinator",
Description: "Coordinator default port",
Protocol: "tcp",
FromPort: constants.CoordinatorPort,
},
{
Name: "wireguard",
Description: "WireGuard default port",
Protocol: "udp",
FromPort: constants.WireguardPort,
},
{
Name: "ssh",
Description: "SSH",
Protocol: "tcp",
FromPort: constants.SSHPort,
},
{
Name: "nodeport",
Description: "NodePort",
Protocol: "tcp",
FromPort: constants.NodePortFrom,
ToPort: constants.NodePortTo,
},
},
},
VPCsInput: &gcpClient.VPCsInput{
SubnetCIDR: "192.168.178.0/24",
SubnetExtCIDR: "10.10.0.0/16",
},
ServiceAccountRoles: &[]string{
Project: "constellation-331613",
Region: "europe-west3",
Zone: "europe-west3-b",
Image: "projects/constellation-images/global/images/constellation-coreos-1651150807",
ServiceAccountRoles: []string{
"roles/compute.instanceAdmin.v1",
"roles/compute.networkAdmin",
"roles/compute.securityAdmin",
"roles/storage.admin",
"roles/iam.serviceAccountUser",
},
Measurements: &gcpPCRs,
Measurements: gcpPCRs,
},
QEMU: &QEMUConfig{
Measurements: &qemuPCRs,
Measurements: qemuPCRs,
},
},
}
}
// FromFile returns a default config that has been merged with a config file.
// If name is empty, the defaults are returned.
// FromFile returns config file with `name` read from `fileHandler` by parsing
// it as YAML.
// If name is empty, the default configuration is returned.
func FromFile(fileHandler file.Handler, name string) (*Config, error) {
conf := Default()
if name == "" {
return conf, nil
return Default(), nil
}
if err := fileHandler.ReadYAML(name, conf); err != nil {
var emptyConf Config
if err := fileHandler.ReadYAML(name, &emptyConf); err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("unable to find %s - use `constellation config generate` to generate it first", name)
}
return nil, fmt.Errorf("could not load config from file %s: %w", name, err)
}
return conf, nil
}
// ProviderConfig are cloud-provider specific configuration values used by the CLI.
type ProviderConfig struct {
EC2 *EC2Config `yaml:"ec2Config,omitempty"`
Azure *AzureConfig `yaml:"azureConfig,omitempty"`
GCP *GCPConfig `yaml:"gcpConfig,omitempty"`
QEMU *QEMUConfig `yaml:"qemuConfig,omitempty"`
}
// EC2Config are AWS EC2 specific configuration values used by the CLI.
type EC2Config struct {
Image *string `yaml:"image,omitempty"`
Tags *[]ec2.Tag `yaml:"tags,omitempty"`
SecurityGroupInput *awsClient.SecurityGroupInput `yaml:"securityGroupInput,omitempty"`
}
// AzureConfig are Azure specific configuration values used by the CLI.
type AzureConfig struct {
SubscriptionID *string `yaml:"subscription,omitempty"` // TODO: This will be user input
TenantID *string `yaml:"tenant,omitempty"` // TODO: This will be user input
Location *string `yaml:"location,omitempty"` // TODO: This will be user input
Image *string `yaml:"image,omitempty"`
NetworkSecurityGroupInput *azureClient.NetworkSecurityGroupInput `yaml:"networkSecurityGroupInput,omitempty"`
Measurements *Measurements `yaml:"measurements,omitempty"`
UserAssignedIdentity *string `yaml:"userassignedIdentity,omitempty"`
}
// GCPConfig are GCP specific configuration values used by the CLI.
type GCPConfig struct {
Project *string `yaml:"project,omitempty"` // TODO: This will be user input
Region *string `yaml:"region,omitempty"` // TODO: This will be user input
Zone *string `yaml:"zone,omitempty"` // TODO: This will be user input
Image *string `yaml:"image,omitempty"`
FirewallInput *gcpClient.FirewallInput `yaml:"firewallInput,omitempty"`
VPCsInput *gcpClient.VPCsInput `yaml:"vpcsInput,omitempty"`
ServiceAccountRoles *[]string `yaml:"serviceAccountRoles,omitempty"`
Measurements *Measurements `yaml:"measurements,omitempty"`
}
type QEMUConfig struct {
Measurements *Measurements `yaml:"measurements,omitempty"`
}
// intPtr returns a pointer to the copied value of in.
func intPtr(in int) *int {
return &in
return &emptyConf, nil
}

View File

@ -0,0 +1,220 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Code generated by hack/docgen tool. DO NOT EDIT.
package config
import (
"github.com/talos-systems/talos/pkg/machinery/config/encoder"
)
var (
ConfigDoc encoder.Doc
ProviderConfigDoc encoder.Doc
AzureConfigDoc encoder.Doc
GCPConfigDoc encoder.Doc
QEMUConfigDoc encoder.Doc
)
func init() {
ConfigDoc.Type = "Config"
ConfigDoc.Comments[encoder.LineComment] = "Config defines configuration used by CLI."
ConfigDoc.Description = "Config defines configuration used by CLI."
ConfigDoc.Fields = make([]encoder.Doc, 4)
ConfigDoc.Fields[0].Name = "autoscalingNodeGroupsMin"
ConfigDoc.Fields[0].Type = "int"
ConfigDoc.Fields[0].Note = ""
ConfigDoc.Fields[0].Description = "Minimum number of nodes in autoscaling group.\nworker nodes."
ConfigDoc.Fields[0].Comments[encoder.LineComment] = "Minimum number of nodes in autoscaling group."
ConfigDoc.Fields[1].Name = "autoscalingNodeGroupsMax"
ConfigDoc.Fields[1].Type = "int"
ConfigDoc.Fields[1].Note = ""
ConfigDoc.Fields[1].Description = "Maximum number of nodes in autoscaling group.\nworker nodes."
ConfigDoc.Fields[1].Comments[encoder.LineComment] = "Maximum number of nodes in autoscaling group."
ConfigDoc.Fields[2].Name = "StateDisksizeGB"
ConfigDoc.Fields[2].Type = "int"
ConfigDoc.Fields[2].Note = ""
ConfigDoc.Fields[2].Description = "Size (in GB) of root disk used for nodes."
ConfigDoc.Fields[2].Comments[encoder.LineComment] = "Size (in GB) of root disk used for nodes."
ConfigDoc.Fields[3].Name = "provider"
ConfigDoc.Fields[3].Type = "ProviderConfig"
ConfigDoc.Fields[3].Note = ""
ConfigDoc.Fields[3].Description = "Supported cloud providers & their specific configurations."
ConfigDoc.Fields[3].Comments[encoder.LineComment] = "Supported cloud providers & their specific configurations."
ProviderConfigDoc.Type = "ProviderConfig"
ProviderConfigDoc.Comments[encoder.LineComment] = "ProviderConfig are cloud-provider specific configuration values used by the CLI."
ProviderConfigDoc.Description = "ProviderConfig are cloud-provider specific configuration values used by the CLI."
ProviderConfigDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "Config",
FieldName: "provider",
},
}
ProviderConfigDoc.Fields = make([]encoder.Doc, 3)
ProviderConfigDoc.Fields[0].Name = "azureConfig"
ProviderConfigDoc.Fields[0].Type = "AzureConfig"
ProviderConfigDoc.Fields[0].Note = ""
ProviderConfigDoc.Fields[0].Description = "Configuration for Azure as provider."
ProviderConfigDoc.Fields[0].Comments[encoder.LineComment] = "Configuration for Azure as provider."
ProviderConfigDoc.Fields[1].Name = "gcpConfig"
ProviderConfigDoc.Fields[1].Type = "GCPConfig"
ProviderConfigDoc.Fields[1].Note = ""
ProviderConfigDoc.Fields[1].Description = "Configuration for Google Cloud as provider."
ProviderConfigDoc.Fields[1].Comments[encoder.LineComment] = "Configuration for Google Cloud as provider."
ProviderConfigDoc.Fields[2].Name = "qemuConfig"
ProviderConfigDoc.Fields[2].Type = "QEMUConfig"
ProviderConfigDoc.Fields[2].Note = ""
ProviderConfigDoc.Fields[2].Description = "Configuration for QEMU as provider."
ProviderConfigDoc.Fields[2].Comments[encoder.LineComment] = "Configuration for QEMU as provider."
AzureConfigDoc.Type = "AzureConfig"
AzureConfigDoc.Comments[encoder.LineComment] = "AzureConfig are Azure specific configuration values used by the CLI."
AzureConfigDoc.Description = "AzureConfig are Azure specific configuration values used by the CLI."
AzureConfigDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "ProviderConfig",
FieldName: "azureConfig",
},
}
AzureConfigDoc.Fields = make([]encoder.Doc, 7)
AzureConfigDoc.Fields[0].Name = "subscription"
AzureConfigDoc.Fields[0].Type = "string"
AzureConfigDoc.Fields[0].Note = ""
AzureConfigDoc.Fields[0].Description = "Subscription ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription"
AzureConfigDoc.Fields[0].Comments[encoder.LineComment] = "Subscription ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-subscription"
AzureConfigDoc.Fields[1].Name = "tenant"
AzureConfigDoc.Fields[1].Type = "string"
AzureConfigDoc.Fields[1].Note = ""
AzureConfigDoc.Fields[1].Description = "Tenant ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant"
AzureConfigDoc.Fields[1].Comments[encoder.LineComment] = "Tenant ID of the used Azure account. See: https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id#find-your-azure-ad-tenant"
AzureConfigDoc.Fields[2].Name = "location"
AzureConfigDoc.Fields[2].Type = "string"
AzureConfigDoc.Fields[2].Note = ""
AzureConfigDoc.Fields[2].Description = "Azure datacenter region to be used. See: https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#azure-regions-with-availability-zones"
AzureConfigDoc.Fields[2].Comments[encoder.LineComment] = "Azure datacenter region to be used. See: https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#azure-regions-with-availability-zones"
AzureConfigDoc.Fields[3].Name = "image"
AzureConfigDoc.Fields[3].Type = "string"
AzureConfigDoc.Fields[3].Note = ""
AzureConfigDoc.Fields[3].Description = "Machine image used to create Constellation nodes."
AzureConfigDoc.Fields[3].Comments[encoder.LineComment] = "Machine image used to create Constellation nodes."
AzureConfigDoc.Fields[4].Name = "networkSecurityGroupInput"
AzureConfigDoc.Fields[4].Type = "NetworkSecurityGroupInput"
AzureConfigDoc.Fields[4].Note = ""
AzureConfigDoc.Fields[4].Description = "Firewall rules."
AzureConfigDoc.Fields[4].Comments[encoder.LineComment] = "Firewall rules."
AzureConfigDoc.Fields[5].Name = "measurements"
AzureConfigDoc.Fields[5].Type = "Measurements"
AzureConfigDoc.Fields[5].Note = ""
AzureConfigDoc.Fields[5].Description = "Measurement used to enable measured boot."
AzureConfigDoc.Fields[5].Comments[encoder.LineComment] = "Measurement used to enable measured boot."
AzureConfigDoc.Fields[6].Name = "userassignedIdentity"
AzureConfigDoc.Fields[6].Type = "string"
AzureConfigDoc.Fields[6].Note = ""
AzureConfigDoc.Fields[6].Description = "Why is this needed? Docs only say that it is needed. (TODO) See: https://constellation-docs.edgeless.systems/6c320851-bdd2-41d5-bf10-e27427398692/#/getting-started/install?id=azure"
AzureConfigDoc.Fields[6].Comments[encoder.LineComment] = "Why is this needed? Docs only say that it is needed. (TODO) See: https://constellation-docs.edgeless.systems/6c320851-bdd2-41d5-bf10-e27427398692/#/getting-started/install?id=azure"
GCPConfigDoc.Type = "GCPConfig"
GCPConfigDoc.Comments[encoder.LineComment] = "GCPConfig are GCP specific configuration values used by the CLI."
GCPConfigDoc.Description = "GCPConfig are GCP specific configuration values used by the CLI."
GCPConfigDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "ProviderConfig",
FieldName: "gcpConfig",
},
}
GCPConfigDoc.Fields = make([]encoder.Doc, 8)
GCPConfigDoc.Fields[0].Name = "project"
GCPConfigDoc.Fields[0].Type = "string"
GCPConfigDoc.Fields[0].Note = ""
GCPConfigDoc.Fields[0].Description = "GCP project. See: https://support.google.com/googleapi/answer/7014113?hl=en"
GCPConfigDoc.Fields[0].Comments[encoder.LineComment] = "GCP project. See: https://support.google.com/googleapi/answer/7014113?hl=en"
GCPConfigDoc.Fields[1].Name = "region"
GCPConfigDoc.Fields[1].Type = "string"
GCPConfigDoc.Fields[1].Note = ""
GCPConfigDoc.Fields[1].Description = "GCP datacenter region. See: https://cloud.google.com/compute/docs/regions-zones#available"
GCPConfigDoc.Fields[1].Comments[encoder.LineComment] = "GCP datacenter region. See: https://cloud.google.com/compute/docs/regions-zones#available"
GCPConfigDoc.Fields[2].Name = "zone"
GCPConfigDoc.Fields[2].Type = "string"
GCPConfigDoc.Fields[2].Note = ""
GCPConfigDoc.Fields[2].Description = "GCP datacenter zone. See: https://cloud.google.com/compute/docs/regions-zones#available"
GCPConfigDoc.Fields[2].Comments[encoder.LineComment] = "GCP datacenter zone. See: https://cloud.google.com/compute/docs/regions-zones#available"
GCPConfigDoc.Fields[3].Name = "image"
GCPConfigDoc.Fields[3].Type = "string"
GCPConfigDoc.Fields[3].Note = ""
GCPConfigDoc.Fields[3].Description = "Machine image used to create Constellation nodes."
GCPConfigDoc.Fields[3].Comments[encoder.LineComment] = "Machine image used to create Constellation nodes."
GCPConfigDoc.Fields[4].Name = "firewallInput"
GCPConfigDoc.Fields[4].Type = "FirewallInput"
GCPConfigDoc.Fields[4].Note = ""
GCPConfigDoc.Fields[4].Description = "Firewall rules."
GCPConfigDoc.Fields[4].Comments[encoder.LineComment] = "Firewall rules."
GCPConfigDoc.Fields[5].Name = "vpcsInput"
GCPConfigDoc.Fields[5].Type = "VPCsInput"
GCPConfigDoc.Fields[5].Note = ""
GCPConfigDoc.Fields[5].Description = "Virtual Private Cloud settings."
GCPConfigDoc.Fields[5].Comments[encoder.LineComment] = "Virtual Private Cloud settings."
GCPConfigDoc.Fields[6].Name = "serviceAccountRoles"
GCPConfigDoc.Fields[6].Type = "[]string"
GCPConfigDoc.Fields[6].Note = ""
GCPConfigDoc.Fields[6].Description = "Roles added to service account."
GCPConfigDoc.Fields[6].Comments[encoder.LineComment] = "Roles added to service account."
GCPConfigDoc.Fields[7].Name = "measurements"
GCPConfigDoc.Fields[7].Type = "Measurements"
GCPConfigDoc.Fields[7].Note = ""
GCPConfigDoc.Fields[7].Description = "Measurement used to enable measured boot."
GCPConfigDoc.Fields[7].Comments[encoder.LineComment] = "Measurement used to enable measured boot."
QEMUConfigDoc.Type = "QEMUConfig"
QEMUConfigDoc.Comments[encoder.LineComment] = ""
QEMUConfigDoc.Description = ""
QEMUConfigDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "ProviderConfig",
FieldName: "qemuConfig",
},
}
QEMUConfigDoc.Fields = make([]encoder.Doc, 1)
QEMUConfigDoc.Fields[0].Name = "measurements"
QEMUConfigDoc.Fields[0].Type = "Measurements"
QEMUConfigDoc.Fields[0].Note = ""
QEMUConfigDoc.Fields[0].Description = "Measurement used to enable measured boot."
QEMUConfigDoc.Fields[0].Comments[encoder.LineComment] = "Measurement used to enable measured boot."
}
func (_ Config) Doc() *encoder.Doc {
return &ConfigDoc
}
func (_ ProviderConfig) Doc() *encoder.Doc {
return &ProviderConfigDoc
}
func (_ AzureConfig) Doc() *encoder.Doc {
return &AzureConfigDoc
}
func (_ GCPConfig) Doc() *encoder.Doc {
return &GCPConfigDoc
}
func (_ QEMUConfig) Doc() *encoder.Doc {
return &QEMUConfigDoc
}
// GetConfigurationDoc returns documentation for the file ./config_doc.go.
func GetConfigurationDoc() *encoder.FileDoc {
return &encoder.FileDoc{
Name: "Configuration",
Description: "",
Structs: []*encoder.Doc{
&ConfigDoc,
&ProviderConfigDoc,
&AzureConfigDoc,
&GCPConfigDoc,
&QEMUConfigDoc,
},
}
}

View File

@ -3,8 +3,6 @@ package config
import (
"testing"
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
"github.com/edgelesssys/constellation/cli/gcp/client"
"github.com/edgelesssys/constellation/internal/constants"
"github.com/edgelesssys/constellation/internal/file"
"github.com/spf13/afero"
@ -19,48 +17,57 @@ func TestDefaultConfig(t *testing.T) {
}
func TestFromFile(t *testing.T) {
someProviderConfig := &ProviderConfig{
GCP: &GCPConfig{
FirewallInput: &client.FirewallInput{
Ingress: cloudtypes.Firewall{
{
Name: "firstFirewallRule",
Description: "firstFirewallRule description",
Protocol: "tcp",
FromPort: 4444,
},
{
Name: "secondFirewallRule",
Description: "secondFirewallRule description",
Protocol: "udp",
FromPort: 5555,
},
},
testCases := map[string]struct {
config *Config
configName string
wantResult *Config
wantErr bool
}{
"default config from default file": {
config: Default(),
configName: constants.ConfigFilename,
wantResult: Default(),
},
"default config from different path": {
config: Default(),
configName: "other-config.yaml",
wantResult: Default(),
},
"default config when path empty": {
config: nil,
configName: "",
wantResult: Default(),
},
"err when path not exist": {
config: nil,
configName: "wrong-name.yaml",
wantErr: true,
},
"custom config from default file": {
config: &Config{
AutoscalingNodeGroupsMin: 42,
AutoscalingNodeGroupsMax: 1337,
},
configName: constants.ConfigFilename,
wantResult: &Config{
AutoscalingNodeGroupsMin: 42,
AutoscalingNodeGroupsMax: 1337,
},
},
}
testCases := map[string]struct {
from *Config
configName string
wantResultMutator func(c *Config) // mutates the Default() config to the expected result.
wantErr bool
}{
"overwrite slices": {
from: &Config{Provider: someProviderConfig},
configName: constants.ConfigFilename,
wantResultMutator: func(c *Config) { c.Provider = someProviderConfig },
},
"default with empty name": {
from: &Config{},
configName: "",
wantResultMutator: func(c *Config) {},
},
"err with wrong name": {
from: &Config{},
configName: "wrongName.json",
wantResultMutator: func(c *Config) {},
wantErr: true,
"modify default config": {
config: func() *Config {
conf := Default()
conf.Provider.GCP.Region = "eu-north1"
conf.Provider.GCP.Zone = "eu-north1-a"
return conf
}(),
configName: constants.ConfigFilename,
wantResult: func() *Config {
conf := Default()
conf.Provider.GCP.Region = "eu-north1"
conf.Provider.GCP.Zone = "eu-north1-a"
return conf
}(),
},
}
@ -70,7 +77,9 @@ func TestFromFile(t *testing.T) {
require := require.New(t)
fileHandler := file.NewHandler(afero.NewMemMapFs())
require.NoError(fileHandler.WriteYAML(constants.ConfigFilename, tc.from, file.OptNone))
if tc.config != nil {
require.NoError(fileHandler.WriteYAML(tc.configName, tc.config, file.OptNone))
}
result, err := FromFile(fileHandler, tc.configName)
@ -78,14 +87,7 @@ func TestFromFile(t *testing.T) {
assert.Error(err)
} else {
require.NoError(err)
wantResult := Default()
tc.wantResultMutator(wantResult)
assert.EqualValues(wantResult.AutoscalingNodeGroupsMin, result.AutoscalingNodeGroupsMin)
assert.EqualValues(wantResult.AutoscalingNodeGroupsMax, result.AutoscalingNodeGroupsMax)
require.NotNil(wantResult.Provider)
require.NotNil(wantResult.Provider.GCP, result.Provider.GCP)
require.NotNil(wantResult.Provider.GCP.FirewallInput, result.Provider.GCP.FirewallInput)
assert.Equal(len(wantResult.Provider.GCP.FirewallInput.Ingress), len(result.Provider.GCP.FirewallInput.Ingress))
assert.Equal(tc.wantResult, result)
}
})
}

View File

@ -1,9 +1,35 @@
package config
import "encoding/base64"
import (
"encoding/base64"
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
)
type Measurements map[uint32][]byte
var (
// gcpPCRs is a map of the expected PCR values for a GCP Constellation node.
// TODO: Get a full list once we have stable releases.
gcpPCRs = Measurements{
0: {0x0F, 0x35, 0xC2, 0x14, 0x60, 0x8D, 0x93, 0xC7, 0xA6, 0xE6, 0x8A, 0xE7, 0x35, 0x9B, 0x4A, 0x8B, 0xE5, 0xA0, 0xE9, 0x9E, 0xEA, 0x91, 0x07, 0xEC, 0xE4, 0x27, 0xC4, 0xDE, 0xA4, 0xE4, 0x39, 0xCF},
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
// azurePCRs is a map of the expected PCR values for an Azure Constellation node.
// TODO: Get a full list once we have a working setup with stable releases.
azurePCRs = Measurements{
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
qemuPCRs = Measurements{
uint32(vtpm.PCRIndexOwnerID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
uint32(vtpm.PCRIndexClusterID): {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
)
func (m Measurements) MarshalYAML() (interface{}, error) {
base64Map := make(map[uint32]string)

View File

@ -13,6 +13,7 @@ import (
"path"
"github.com/spf13/afero"
"github.com/talos-systems/talos/pkg/machinery/config/encoder"
"gopkg.in/yaml.v3"
)
@ -112,7 +113,7 @@ func (h *Handler) WriteYAML(name string, content any, options Option) (err error
err = errors.New("recovered from panic")
}
}()
data, err := yaml.Marshal(content)
data, err := encoder.NewEncoder(content).Encode()
if err != nil {
return err
}