mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-31 09:43:23 -05:00
AB#2278 Remove hardcoded values from config (#346)
* Update file handler to avoid incorrect usage of file.Option * Remove hardcoded values Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
129caae0e4
commit
ab536ae3c8
@ -58,7 +58,12 @@ func configGenerate(cmd *cobra.Command, fileHandler file.Handler, provider cloud
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileHandler.WriteYAML(flags.file, conf, 0o644)
|
if err := fileHandler.WriteYAML(flags.file, conf, file.OptMkdirAll); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.Println("Config file written to", flags.file)
|
||||||
|
cmd.Println("Please fill in your CSP specific configuration before proceeding.")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
|
func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
|
||||||
|
@ -11,6 +11,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func readConfig(out io.Writer, fileHandler file.Handler, name string, provider cloudprovider.Provider) (*config.Config, error) {
|
func readConfig(out io.Writer, fileHandler file.Handler, name string, provider cloudprovider.Provider) (*config.Config, error) {
|
||||||
|
if name == "" {
|
||||||
|
return config.Default(), nil
|
||||||
|
}
|
||||||
|
|
||||||
cnf, err := config.FromFile(fileHandler, name)
|
cnf, err := config.FromFile(fileHandler, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -32,7 +36,8 @@ func validateConfig(out io.Writer, cnf *config.Config, provider cloudprovider.Pr
|
|||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
fmt.Fprintln(out, "\t"+m)
|
fmt.Fprintln(out, "\t"+m)
|
||||||
}
|
}
|
||||||
return errors.New("invalid configuration. Fix the invalid entries or generate a new configuration using `constellation config generate`")
|
fmt.Fprintln(out, "Fix the invalid entries or generate a new configuration using `constellation config generate`")
|
||||||
|
return errors.New("invalid configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider != cloudprovider.Unknown && !cnf.HasProvider(provider) {
|
if provider != cloudprovider.Unknown && !cnf.HasProvider(provider) {
|
||||||
|
@ -17,8 +17,44 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
wantOutput bool
|
wantOutput bool
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"default config is valid": {
|
"default config is not valid": {
|
||||||
cnf: config.Default(),
|
cnf: config.Default(),
|
||||||
|
wantOutput: true,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"default Azure config is not valid": {
|
||||||
|
cnf: func() *config.Config {
|
||||||
|
cnf := config.Default()
|
||||||
|
az := cnf.Provider.Azure
|
||||||
|
cnf.Provider = config.ProviderConfig{}
|
||||||
|
cnf.Provider.Azure = az
|
||||||
|
return cnf
|
||||||
|
}(),
|
||||||
|
provider: cloudprovider.Azure,
|
||||||
|
wantOutput: true,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"default GCP config is not valid": {
|
||||||
|
cnf: func() *config.Config {
|
||||||
|
cnf := config.Default()
|
||||||
|
gcp := cnf.Provider.GCP
|
||||||
|
cnf.Provider = config.ProviderConfig{}
|
||||||
|
cnf.Provider.GCP = gcp
|
||||||
|
return cnf
|
||||||
|
}(),
|
||||||
|
provider: cloudprovider.GCP,
|
||||||
|
wantOutput: true,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"default QEMU config is valid": {
|
||||||
|
cnf: func() *config.Config {
|
||||||
|
cnf := config.Default()
|
||||||
|
qemu := cnf.Provider.QEMU
|
||||||
|
cnf.Provider = config.ProviderConfig{}
|
||||||
|
cnf.Provider.QEMU = qemu
|
||||||
|
return cnf
|
||||||
|
}(),
|
||||||
|
provider: cloudprovider.QEMU,
|
||||||
},
|
},
|
||||||
"config with an error": {
|
"config with an error": {
|
||||||
cnf: func() *config.Config {
|
cnf: func() *config.Config {
|
||||||
@ -36,16 +72,6 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
return cnf
|
return cnf
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
"config with only required provider": {
|
|
||||||
cnf: func() *config.Config {
|
|
||||||
cnf := config.Default()
|
|
||||||
az := cnf.Provider.Azure
|
|
||||||
cnf.Provider = config.ProviderConfig{}
|
|
||||||
cnf.Provider.Azure = az
|
|
||||||
return cnf
|
|
||||||
}(),
|
|
||||||
provider: cloudprovider.Azure,
|
|
||||||
},
|
|
||||||
"config without required provider": {
|
"config without required provider": {
|
||||||
cnf: func() *config.Config {
|
cnf: func() *config.Config {
|
||||||
cnf := config.Default()
|
cnf := config.Default()
|
||||||
|
@ -212,18 +212,18 @@ func Default() *Config {
|
|||||||
Provider: ProviderConfig{
|
Provider: ProviderConfig{
|
||||||
// TODO remove our subscriptions from the default config
|
// TODO remove our subscriptions from the default config
|
||||||
Azure: &AzureConfig{
|
Azure: &AzureConfig{
|
||||||
SubscriptionID: "0d202bbb-4fa7-4af8-8125-58c269a05435",
|
SubscriptionID: "",
|
||||||
TenantID: "adb650a8-5da3-4b15-b4b0-3daf65ff7626",
|
TenantID: "",
|
||||||
Location: "North Europe",
|
Location: "",
|
||||||
|
UserAssignedIdentity: "",
|
||||||
Image: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/CONSTELLATION-IMAGES/providers/Microsoft.Compute/galleries/Constellation/images/constellation-coreos/versions/0.0.1659453699",
|
Image: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/CONSTELLATION-IMAGES/providers/Microsoft.Compute/galleries/Constellation/images/constellation-coreos/versions/0.0.1659453699",
|
||||||
StateDiskType: "StandardSSD_LRS", // TODO: Replace with Premium_LRS when we replace the default VM size (Standard_D2a_v4) since the size does not support Premium_LRS
|
StateDiskType: "StandardSSD_LRS", // TODO: Replace with Premium_LRS when we replace the default VM size (Standard_D2a_v4) since the size does not support Premium_LRS
|
||||||
Measurements: azurePCRs,
|
Measurements: azurePCRs,
|
||||||
UserAssignedIdentity: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.ManagedIdentity/userAssignedIdentities/constellation-dev-identity",
|
|
||||||
},
|
},
|
||||||
GCP: &GCPConfig{
|
GCP: &GCPConfig{
|
||||||
Project: "constellation-331613",
|
Project: "",
|
||||||
Region: "europe-west3",
|
Region: "",
|
||||||
Zone: "europe-west3-b",
|
Zone: "",
|
||||||
Image: "projects/constellation-images/global/images/constellation-coreos-1659453699",
|
Image: "projects/constellation-images/global/images/constellation-coreos-1659453699",
|
||||||
ServiceAccountRoles: []string{
|
ServiceAccountRoles: []string{
|
||||||
"roles/compute.instanceAdmin.v1",
|
"roles/compute.instanceAdmin.v1",
|
||||||
@ -336,18 +336,13 @@ func (c *Config) RemoveProviderExcept(provider cloudprovider.Provider) {
|
|||||||
|
|
||||||
// FromFile returns config file with `name` read from `fileHandler` by parsing
|
// FromFile returns config file with `name` read from `fileHandler` by parsing
|
||||||
// it as YAML.
|
// it as YAML.
|
||||||
// If name is empty, the default configuration is returned.
|
|
||||||
func FromFile(fileHandler file.Handler, name string) (*Config, error) {
|
func FromFile(fileHandler file.Handler, name string) (*Config, error) {
|
||||||
if name == "" {
|
var conf Config
|
||||||
return Default(), nil
|
if err := fileHandler.ReadYAMLStrict(name, &conf); err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
var emptyConf Config
|
|
||||||
if err := fileHandler.ReadYAMLStrict(name, &emptyConf); err != nil {
|
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
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("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 nil, fmt.Errorf("could not load config from file %s: %w", name, err)
|
||||||
}
|
}
|
||||||
return &emptyConf, nil
|
return &conf, nil
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func TestFromFile(t *testing.T) {
|
|||||||
"default config when path empty": {
|
"default config when path empty": {
|
||||||
config: nil,
|
config: nil,
|
||||||
configName: "",
|
configName: "",
|
||||||
wantResult: Default(),
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"err when path not exist": {
|
"err when path not exist": {
|
||||||
config: nil,
|
config: nil,
|
||||||
@ -154,7 +154,7 @@ func TestValidate(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
"default config is valid": {
|
"default config is valid": {
|
||||||
cnf: Default(),
|
cnf: Default(),
|
||||||
wantMsgCount: 0,
|
wantMsgCount: 7, // expect 7 error messages by default because user-specific values are not set
|
||||||
},
|
},
|
||||||
"config with 1 error": {
|
"config with 1 error": {
|
||||||
cnf: func() *Config {
|
cnf: func() *Config {
|
||||||
@ -162,7 +162,7 @@ func TestValidate(t *testing.T) {
|
|||||||
cnf.Version = "v0"
|
cnf.Version = "v0"
|
||||||
return cnf
|
return cnf
|
||||||
}(),
|
}(),
|
||||||
wantMsgCount: 1,
|
wantMsgCount: 8,
|
||||||
},
|
},
|
||||||
"config with 2 errors": {
|
"config with 2 errors": {
|
||||||
cnf: func() *Config {
|
cnf: func() *Config {
|
||||||
@ -171,7 +171,7 @@ func TestValidate(t *testing.T) {
|
|||||||
cnf.StateDiskSizeGB = -1
|
cnf.StateDiskSizeGB = -1
|
||||||
return cnf
|
return cnf
|
||||||
}(),
|
}(),
|
||||||
wantMsgCount: 2,
|
wantMsgCount: 9,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,20 +19,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Option is a bitmask of options for file operations.
|
// Option is a bitmask of options for file operations.
|
||||||
type Option uint
|
type Option struct {
|
||||||
|
uint
|
||||||
|
}
|
||||||
|
|
||||||
// Has determines if a set of options contains the given options.
|
// hasOption determines if a set of options contains the given option.
|
||||||
func (o Option) Has(op Option) bool {
|
func hasOption(options []Option, op Option) bool {
|
||||||
return o&op == op
|
for _, ops := range options {
|
||||||
|
if ops == op {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OptNone is a no-op.
|
// OptNone is a no-op.
|
||||||
OptNone Option = 1 << iota / 2
|
optNone uint = iota
|
||||||
// OptOverwrite overwrites an existing file.
|
// OptOverwrite overwrites an existing file.
|
||||||
OptOverwrite
|
optOverwrite
|
||||||
// OptMkdirAll creates the path to the file.
|
// OptMkdirAll creates the path to the file.
|
||||||
OptMkdirAll
|
optMkdirAll
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
OptNone = Option{optNone}
|
||||||
|
OptOverwrite = Option{optOverwrite}
|
||||||
|
OptMkdirAll = Option{optMkdirAll}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler handles file interaction.
|
// Handler handles file interaction.
|
||||||
@ -57,14 +70,14 @@ func (h *Handler) Read(name string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the data bytes into the file with the given name.
|
// Write writes the data bytes into the file with the given name.
|
||||||
func (h *Handler) Write(name string, data []byte, options Option) error {
|
func (h *Handler) Write(name string, data []byte, options ...Option) error {
|
||||||
if options.Has(OptMkdirAll) {
|
if hasOption(options, OptMkdirAll) {
|
||||||
if err := h.fs.MkdirAll(path.Dir(name), os.ModePerm); err != nil {
|
if err := h.fs.MkdirAll(path.Dir(name), os.ModePerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags := os.O_WRONLY | os.O_CREATE | os.O_EXCL
|
flags := os.O_WRONLY | os.O_CREATE | os.O_EXCL
|
||||||
if options.Has(OptOverwrite) {
|
if hasOption(options, OptOverwrite) {
|
||||||
flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
|
flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
|
||||||
}
|
}
|
||||||
file, err := h.fs.OpenFile(name, flags, 0o600)
|
file, err := h.fs.OpenFile(name, flags, 0o600)
|
||||||
@ -89,12 +102,12 @@ func (h *Handler) ReadJSON(name string, content any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteJSON marshals the content interface to JSON and writes it to the path with the given name.
|
// WriteJSON marshals the content interface to JSON and writes it to the path with the given name.
|
||||||
func (h *Handler) WriteJSON(name string, content any, options Option) error {
|
func (h *Handler) WriteJSON(name string, content any, options ...Option) error {
|
||||||
jsonData, err := json.MarshalIndent(content, "", "\t")
|
jsonData, err := json.MarshalIndent(content, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return h.Write(name, jsonData, options)
|
return h.Write(name, jsonData, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadYAML reads a YAML file from name and unmarshals it into the content interface.
|
// ReadYAML reads a YAML file from name and unmarshals it into the content interface.
|
||||||
@ -120,7 +133,7 @@ func (h *Handler) readYAML(name string, content any, strict bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteYAML marshals the content interface to YAML and writes it to the path with the given name.
|
// WriteYAML marshals the content interface to YAML and writes it to the path with the given name.
|
||||||
func (h *Handler) WriteYAML(name string, content any, options Option) (err error) {
|
func (h *Handler) WriteYAML(name string, content any, options ...Option) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
err = errors.New("recovered from panic")
|
err = errors.New("recovered from panic")
|
||||||
@ -130,7 +143,7 @@ func (h *Handler) WriteYAML(name string, content any, options Option) (err error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return h.Write(name, data, options)
|
return h.Write(name, data, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deletes the file with the given name.
|
// Remove deletes the file with the given name.
|
||||||
|
@ -169,18 +169,18 @@ Q29uc3RlbGxhdGlvbg==
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
file := file.NewHandler(afero.NewMemMapFs())
|
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
||||||
|
|
||||||
if len(tc.caCert) > 0 {
|
if len(tc.caCert) > 0 {
|
||||||
require.NoError(file.Write(caCertFilename, tc.caCert, 0o644))
|
require.NoError(fileHandler.Write(caCertFilename, tc.caCert, file.OptNone))
|
||||||
}
|
}
|
||||||
if len(tc.caKey) > 0 {
|
if len(tc.caKey) > 0 {
|
||||||
require.NoError(file.Write(caKeyFilename, tc.caKey, 0o644))
|
require.NoError(fileHandler.Write(caKeyFilename, tc.caKey, file.OptNone))
|
||||||
}
|
}
|
||||||
|
|
||||||
ca := New(
|
ca := New(
|
||||||
logger.NewTest(t),
|
logger.NewTest(t),
|
||||||
file,
|
fileHandler,
|
||||||
)
|
)
|
||||||
|
|
||||||
signingRequest, err := tc.createSigningRequest()
|
signingRequest, err := tc.createSigningRequest()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user