Module: Onboardbase
- Defined in:
- lib/onboardbase.rb,
lib/onboardbase/version.rb
Constant Summary collapse
- VERSION =
'1.2.0'
Class Attribute Summary collapse
-
.env ⇒ Object
Returns the value of attribute env.
-
.is_dev ⇒ Object
Returns the value of attribute is_dev.
Class Method Summary collapse
- .aes256_cbc_decrypt(key, data, iv) ⇒ Object
- .apiURL ⇒ Object
- .b64enc(data) ⇒ Object
- .bytes_to_key(data, salt, output = 48) ⇒ Object
- .config {|_self| ... } ⇒ Object
- .config_exists?(directory) ⇒ Boolean
- .configuration ⇒ Object
- .content_path ⇒ Object
- .decrypt(password, iv, secretdata) ⇒ Object
- .encrypt(password, iv, cleardata) ⇒ Object
- .getEnvironmentFallbackDir ⇒ Object
- .getFallbackDir ⇒ Object
- .getOnboardbaseDir ⇒ Object
- .getProject?(data) ⇒ Boolean
- .getProjectFallbackDir ⇒ Object
- .getSecrets?(project) ⇒ Boolean
- .getWorkingDirectory ⇒ Object
- .hashSecrets?(secretsArr) ⇒ Boolean
- .initialize ⇒ Object
- .key_path ⇒ Object
- .loadAsCredentials ⇒ Object
- .loadConfig ⇒ Object
- .loadSecrets ⇒ Object
- .makeRequest ⇒ Object
- .overrideWithLocal(secrets) ⇒ Object
- .parseResponse?(response) ⇒ Boolean
- .parseSecrets(secrets) ⇒ Object
- .readFallback ⇒ Object
- .setEnv(secretsHash) ⇒ Object
- .storeToFallback?(secrets) ⇒ Boolean
Class Attribute Details
.env ⇒ Object
Returns the value of attribute env.
11 12 13 |
# File 'lib/onboardbase.rb', line 11 def env @env end |
.is_dev ⇒ Object
Returns the value of attribute is_dev.
11 12 13 |
# File 'lib/onboardbase.rb', line 11 def is_dev @is_dev end |
Class Method Details
.aes256_cbc_decrypt(key, data, iv) ⇒ Object
168 169 170 171 172 173 174 175 176 |
# File 'lib/onboardbase.rb', line 168 def aes256_cbc_decrypt(key, data, iv) key = Digest::SHA256.digest(key) if(key.kind_of?(String) && 32 != key.bytesize) iv = Digest::MD5.digest(iv) if(iv.kind_of?(String) && 16 != iv.bytesize) aes = OpenSSL::Cipher.new('AES-256-CBC') aes.decrypt aes.key = key aes.iv = iv aes.update(data) + aes.final end |
.apiURL ⇒ Object
46 47 48 49 |
# File 'lib/onboardbase.rb', line 46 def apiURL return "https://devapi.onboardbase.com/graphql" if self.is_dev "https://api.onboardbase.com/graphql" end |
.b64enc(data) ⇒ Object
42 43 44 |
# File 'lib/onboardbase.rb', line 42 def b64enc(data) Base64.encode64(data).gsub(/\n/, '') end |
.bytes_to_key(data, salt, output = 48) ⇒ Object
157 158 159 160 161 162 163 164 165 166 |
# File 'lib/onboardbase.rb', line 157 def bytes_to_key(data, salt, output=48) merged = data + salt key = Digest::MD5.digest(merged) final_key = key while final_key.length < output key = Digest::MD5.digest(key + merged) final_key = final_key + key end final_key[0..output-1] end |
.config {|_self| ... } ⇒ Object
58 59 60 |
# File 'lib/onboardbase.rb', line 58 def config yield self end |
.config_exists?(directory) ⇒ Boolean
85 86 87 |
# File 'lib/onboardbase.rb', line 85 def config_exists?(directory) return File.exist?(directory) end |
.configuration ⇒ Object
51 52 53 |
# File 'lib/onboardbase.rb', line 51 def configuration @configuration ||= {} end |
.content_path ⇒ Object
255 256 257 |
# File 'lib/onboardbase.rb', line 255 def content_path ENV["RAILS_ENV"] ? "config/credentials/#{ENV["RAILS_ENV"]}.yml.enc" : "config/credentials.yml.enc" end |
.decrypt(password, iv, secretdata) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/onboardbase.rb', line 33 def decrypt(password, iv, secretdata) secretdata = Base64::decode64(secretdata) decipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc') decipher.decrypt decipher.key = password decipher.iv = iv if iv != nil decipher.update(secretdata) + decipher.final end |
.encrypt(password, iv, cleardata) ⇒ Object
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/onboardbase.rb', line 22 def encrypt(password, iv, cleardata) cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.encrypt # set cipher to be encryption mode cipher.key = password cipher.iv = iv encrypted = '' encrypted << cipher.update(cleardata) encrypted << cipher.final b64enc(encrypted) end |
.getEnvironmentFallbackDir ⇒ Object
80 81 82 83 |
# File 'lib/onboardbase.rb', line 80 def getEnvironmentFallbackDir environment = self.configuration['setup']['environment'] "#{self.getProjectFallbackDir}_#{environment}" end |
.getFallbackDir ⇒ Object
70 71 72 |
# File 'lib/onboardbase.rb', line 70 def getFallbackDir "#{self.getOnboardbaseDir}/fallback" end |
.getOnboardbaseDir ⇒ Object
66 67 68 |
# File 'lib/onboardbase.rb', line 66 def getOnboardbaseDir "#{Dir.home}/.onboardbase" end |
.getProject?(data) ⇒ Boolean
144 145 146 147 148 |
# File 'lib/onboardbase.rb', line 144 def getProject?(data) project = data["list"][0] return project if project != nil false end |
.getProjectFallbackDir ⇒ Object
75 76 77 78 |
# File 'lib/onboardbase.rb', line 75 def getProjectFallbackDir project = self.configuration['setup']['project'] "#{self.getFallbackDir}/#{project}" end |
.getSecrets?(project) ⇒ Boolean
151 152 153 154 155 |
# File 'lib/onboardbase.rb', line 151 def getSecrets?(project) env = project["publicEnvironments"]["list"][0] return JSON.parse(env["key"]) if env != nil false end |
.getWorkingDirectory ⇒ Object
62 63 64 |
# File 'lib/onboardbase.rb', line 62 def getWorkingDirectory Dir.pwd end |
.hashSecrets?(secretsArr) ⇒ Boolean
220 221 222 223 224 225 226 |
# File 'lib/onboardbase.rb', line 220 def hashSecrets?(secretsArr) secretsHash = Hash.new secretsArr.each do |secret| secretsHash["#{secret["key"]}"] = "#{secret["value"]}" end secretsHash end |
.initialize ⇒ Object
54 55 56 |
# File 'lib/onboardbase.rb', line 54 def initialize super end |
.key_path ⇒ Object
259 260 261 |
# File 'lib/onboardbase.rb', line 259 def key_path ENV["RAILS_ENV"] ? "config/credentials/#{ENV["RAILS_ENV"]}.key" : "config/master.key" end |
.loadAsCredentials ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/onboardbase.rb', line 263 def loadAsCredentials # Traditionally fetch secrets into ENV secrets = self.loadSecrets # Load rails encryption module require "active_support/encrypted_configuration" credentials = ActiveSupport::EncryptedConfiguration.new( config_path: self.content_path, key_path: self.key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true ) # secrets hash encsecrets = YAML.load(credentials.read) secrets.keys.sort.each do |key| encsecrets[key.to_s] = secrets[key.to_s].to_s end # Append all environment variable credentials.write(encsecrets.to_yaml) end |
.loadConfig ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/onboardbase.rb', line 90 def loadConfig configPath = self.getWorkingDirectory + '/onboardbase.yaml' unless self.config_exists?(configPath) puts "Please create onboardbase.yaml in the root of the project at: " + configPath exit 1 end config = YAML.load_file(configPath) if (config['api_key'] == nil) puts "Your onboardbase.yaml file does not have an api_key" exit 1 end if (config['passcode'] == nil) puts "Your onboardbase.yaml file does not have a passcode" exit 1 end @configuration = config end |
.loadSecrets ⇒ Object
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/onboardbase.rb', line 284 def loadSecrets self.loadConfig response = self.parseResponse?(self.makeRequest) if response[:error] puts "Unable to fetch secrets with the specified api key, reading from fallback file" secrets = self.readFallback else project = self.getProject?(response) projectSecrets = self.getSecrets?(project) parsedSecrets = self.parseSecrets(projectSecrets) secrets = self.hashSecrets?(parsedSecrets) end finalEnvs = self.setEnv(secrets) self.storeToFallback?(finalEnvs) secrets end |
.makeRequest ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/onboardbase.rb', line 109 def makeRequest url = self.apiURL headers = { KEY: self.configuration['api_key'], } body = { query: %{ query { generalPublicProjects(filterOptions: { title: "#{self .configuration['setup']['project']}", disableCustomSelect: true }) { list { id title publicEnvironments(filterOptions: { title: "#{self .configuration['setup']['environment']}" }) { list { id key title } } } } } } } response = HTTParty.post(url, headers: headers, body: body) JSON.parse(response.body) end |
.overrideWithLocal(secrets) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/onboardbase.rb', line 204 def overrideWithLocal(secrets) # Overried local secrets configSecrets = self.configuration["secrets"] unless configSecrets configSecrets = { "local" => {} } end localSecrets = configSecrets["local"] unless localSecrets localSecrets = {} end localSecrets.keys.sort.each do |key| secrets[key.to_s] = "#{configSecrets["local"][key.to_s]}" end secrets end |
.parseResponse?(response) ⇒ Boolean
137 138 139 140 141 142 |
# File 'lib/onboardbase.rb', line 137 def parseResponse?(response) error = response["errors"] data = response["data"] return data["generalPublicProjects"] if error == nil {:error=> true, :message => error[0]["message"] } end |
.parseSecrets(secrets) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/onboardbase.rb', line 178 def parseSecrets(secrets) secrets.each_with_index do |secret, i| secret = Base64.decode64(secret) unless secret[0..7] == 'Salted__' puts "Invalid encrypted data" exit(1) end salt = secret[8..15] key_iv = bytes_to_key(self.configuration["passcode"], salt, 48) key = key_iv[0..31] iv = key_iv[32..key_iv.length-1] parsedSecret = aes256_cbc_decrypt(key, secret[16..secret.length-1], iv) secrets[i] = JSON.parse(parsedSecret) end secrets end |
.readFallback ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/onboardbase.rb', line 240 def readFallback Dir.mkdir(self.getOnboardbaseDir) unless File.exists?(self.getOnboardbaseDir) Dir.mkdir(self.getFallbackDir) unless File.exists?(self.getFallbackDir) if !File.exist?(self.getEnvironmentFallbackDir) || File.read(self.getEnvironmentFallbackDir).length <= 0 puts "No valid fallback for #{self .configuration['setup']['project']} project using #{self .configuration['setup']['environment']} environment" return JSON.parse("{}") # Graceful failure, ensure the application continues to run without secrets. end data = File.read(self.getEnvironmentFallbackDir) password = MachineID.ID? cipher = Gibberish::AES::CBC.new(password) decoded_data = cipher.decrypt(data) JSON.parse(decoded_data) end |
.setEnv(secretsHash) ⇒ Object
195 196 197 198 199 200 201 202 |
# File 'lib/onboardbase.rb', line 195 def setEnv(secretsHash) secretsHash.keys.sort.each do |key| ENV[key.to_s] = "#{secretsHash[key.to_s]}" end self.overrideWithLocal(ENV) ENV.to_hash end |
.storeToFallback?(secrets) ⇒ Boolean
228 229 230 231 232 233 234 235 236 237 |
# File 'lib/onboardbase.rb', line 228 def storeToFallback?(secrets) Dir.mkdir(self.getOnboardbaseDir) unless File.exists?(self.getOnboardbaseDir) Dir.mkdir(self.getFallbackDir) unless File.exists?(self.getFallbackDir) password = MachineID.ID? cipher = Gibberish::AES::CBC.new(password) cipher_text = cipher.encrypt(JSON.generate(secrets)) data = cipher_text File.write(self.getEnvironmentFallbackDir, data, nil , mode: 'w') end |