1package autoconf 2 3import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/golang/protobuf/jsonpb" 11 "github.com/hashicorp/consul/proto/pbautoconf" 12) 13 14const ( 15 // autoConfigFileName is the name of the file that the agent auto-config settings are 16 // stored in within the data directory 17 autoConfigFileName = "auto-config.json" 18) 19 20var ( 21 pbMarshaler = &jsonpb.Marshaler{ 22 OrigName: false, 23 EnumsAsInts: false, 24 Indent: " ", 25 EmitDefaults: true, 26 } 27 28 pbUnmarshaler = &jsonpb.Unmarshaler{ 29 AllowUnknownFields: false, 30 } 31) 32 33func (ac *AutoConfig) readPersistedAutoConfig() (*pbautoconf.AutoConfigResponse, error) { 34 if ac.config.DataDir == "" { 35 // no data directory means we don't have anything to potentially load 36 return nil, nil 37 } 38 39 path := filepath.Join(ac.config.DataDir, autoConfigFileName) 40 ac.logger.Debug("attempting to restore any persisted configuration", "path", path) 41 42 content, err := ioutil.ReadFile(path) 43 if err == nil { 44 rdr := strings.NewReader(string(content)) 45 46 var resp pbautoconf.AutoConfigResponse 47 if err := pbUnmarshaler.Unmarshal(rdr, &resp); err != nil { 48 return nil, fmt.Errorf("failed to decode persisted auto-config data: %w", err) 49 } 50 51 ac.logger.Info("read persisted configuration", "path", path) 52 return &resp, nil 53 } 54 55 if !os.IsNotExist(err) { 56 return nil, fmt.Errorf("failed to load %s: %w", path, err) 57 } 58 59 // ignore non-existence errors as that is an indicator that we haven't 60 // performed the auto configuration before 61 return nil, nil 62} 63 64func (ac *AutoConfig) persistAutoConfig(resp *pbautoconf.AutoConfigResponse) error { 65 // now that we know the configuration is generally fine including TLS certs go ahead and persist it to disk. 66 if ac.config.DataDir == "" { 67 ac.logger.Debug("not persisting auto-config settings because there is no data directory") 68 return nil 69 } 70 71 serialized, err := pbMarshaler.MarshalToString(resp) 72 if err != nil { 73 return fmt.Errorf("failed to encode auto-config response as JSON: %w", err) 74 } 75 76 path := filepath.Join(ac.config.DataDir, autoConfigFileName) 77 78 err = ioutil.WriteFile(path, []byte(serialized), 0660) 79 if err != nil { 80 return fmt.Errorf("failed to write auto-config configurations: %w", err) 81 } 82 83 ac.logger.Debug("auto-config settings were persisted to disk") 84 85 return nil 86} 87