github.com/craicoverflow/tyk@v2.9.6-rc3+incompatible/gateway/redis_signal_handle_config.go (about) 1 package gateway 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "os" 7 "syscall" 8 "time" 9 10 "github.com/sirupsen/logrus" 11 12 "github.com/TykTechnologies/tyk/config" 13 ) 14 15 type ConfigPayload struct { 16 Configuration config.Config 17 ForHostname string 18 ForNodeID string 19 TimeStamp int64 20 } 21 22 func backupConfiguration() error { 23 oldConfig, err := json.MarshalIndent(config.Global, "", " ") 24 if err != nil { 25 return err 26 } 27 28 now := time.Now() 29 asStr := now.Format("Mon-Jan-_2-15-04-05-2006") 30 fName := asStr + ".tyk.conf" 31 return ioutil.WriteFile(fName, oldConfig, 0644) 32 } 33 34 func writeNewConfiguration(payload ConfigPayload) error { 35 newConfig, err := json.MarshalIndent(payload.Configuration, "", " ") 36 if err != nil { 37 return err 38 } 39 return ioutil.WriteFile(confPaths[0], newConfig, 0644) 40 } 41 42 func handleNewConfiguration(payload string) { 43 // Decode the configuration from the payload 44 configPayload := ConfigPayload{} 45 46 // We actually want to merge into the existing configuration 47 // so as not to lose data through automatic defaults 48 config.Load(confPaths, &configPayload.Configuration) 49 50 err := json.Unmarshal([]byte(payload), &configPayload) 51 if err != nil { 52 log.WithFields(logrus.Fields{ 53 "prefix": "pub-sub", 54 }).Error("Failed to decode configuration payload: ", err) 55 return 56 } 57 58 // Make sure payload matches nodeID and hostname 59 if configPayload.ForHostname != hostDetails.Hostname && configPayload.ForNodeID != GetNodeID() { 60 log.WithFields(logrus.Fields{ 61 "prefix": "pub-sub", 62 }).Info("Configuration update received, no NodeID/Hostname match found") 63 return 64 } 65 66 if !config.Global().AllowRemoteConfig { 67 log.WithFields(logrus.Fields{ 68 "prefix": "pub-sub", 69 }).Warning("Ignoring new config: Remote configuration is not allowed for this node.") 70 return 71 } 72 73 if err := backupConfiguration(); err != nil { 74 log.WithFields(logrus.Fields{ 75 "prefix": "pub-sub", 76 }).Error("Failed to backup existing configuration: ", err) 77 return 78 } 79 80 if err := writeNewConfiguration(configPayload); err != nil { 81 log.WithFields(logrus.Fields{ 82 "prefix": "pub-sub", 83 }).Error("Failed to write new configuration: ", err) 84 return 85 } 86 87 log.WithFields(logrus.Fields{ 88 "prefix": "pub-sub", 89 }).Info("Initiating configuration reload") 90 91 myPID := hostDetails.PID 92 if myPID == 0 { 93 log.Error("No PID found, cannot reload") 94 return 95 } 96 97 log.Info("Sending reload signal to PID: ", myPID) 98 if err := syscall.Kill(myPID, syscall.SIGUSR2); err != nil { 99 log.Error("Process reload failed: ", err) 100 } 101 } 102 103 type GetConfigPayload struct { 104 FromHostname string 105 FromNodeID string 106 TimeStamp int64 107 } 108 109 type ReturnConfigPayload struct { 110 FromHostname string 111 FromNodeID string 112 Configuration map[string]interface{} 113 TimeStamp int64 114 } 115 116 func sanitizeConfig(mc map[string]interface{}) map[string]interface{} { 117 sanitzeFields := []string{ 118 "secret", 119 "node_secret", 120 "storage", 121 "slave_options", 122 "auth_override", 123 } 124 for _, field_name := range sanitzeFields { 125 delete(mc, field_name) 126 } 127 return mc 128 } 129 130 func getExistingConfig() (map[string]interface{}, error) { 131 f, err := os.Open(config.Global().OriginalPath) 132 if err != nil { 133 return nil, err 134 } 135 var microConfig map[string]interface{} 136 if err := json.NewDecoder(f).Decode(µConfig); err != nil { 137 return nil, err 138 } 139 return sanitizeConfig(microConfig), nil 140 } 141 142 func handleSendMiniConfig(payload string) { 143 // Decode the configuration from the payload 144 configPayload := GetConfigPayload{} 145 err := json.Unmarshal([]byte(payload), &configPayload) 146 if err != nil { 147 log.WithFields(logrus.Fields{ 148 "prefix": "pub-sub", 149 }).Error("Failed unmarshal request: ", err) 150 return 151 } 152 153 // Make sure payload matches nodeID and hostname 154 if configPayload.FromHostname != hostDetails.Hostname && configPayload.FromNodeID != GetNodeID() { 155 log.WithFields(logrus.Fields{ 156 "prefix": "pub-sub", 157 }).Debug("Configuration request received, no NodeID/Hostname match found, ignoring") 158 return 159 } 160 161 config, err := getExistingConfig() 162 if err != nil { 163 log.WithFields(logrus.Fields{ 164 "prefix": "pub-sub", 165 }).Error("Failed to get existing configuration: ", err) 166 return 167 } 168 169 returnPayload := ReturnConfigPayload{ 170 FromHostname: hostDetails.Hostname, 171 FromNodeID: GetNodeID(), 172 Configuration: config, 173 TimeStamp: time.Now().Unix(), 174 } 175 176 payloadAsJSON, err := json.Marshal(returnPayload) 177 if err != nil { 178 log.WithFields(logrus.Fields{ 179 "prefix": "pub-sub", 180 }).Error("Failed to get marshal configuration: ", err) 181 return 182 } 183 184 asNotification := Notification{ 185 Command: NoticeGatewayConfigResponse, 186 Payload: string(payloadAsJSON), 187 } 188 189 MainNotifier.Notify(asNotification) 190 log.WithFields(logrus.Fields{ 191 "prefix": "pub-sub", 192 }).Debug("Configuration request responded.") 193 194 }