Class: Makit::Secrets::AzureKeyVault
- Inherits:
-
Object
- Object
- Makit::Secrets::AzureKeyVault
- Defined in:
- lib/makit/secrets/azure_key_vault.rb
Overview
Azure Key Vault operations
Constant Summary collapse
- REQUIRED_VARS =
Required environment variables
[ "AZURE_STORAGE_ACCOUNT", "AZURE_STORAGE_ACCOUNT_KEY", ].freeze
- OPTIONAL_VARS =
Optional environment variables
[ "AZURE_CDN_RESOURCE_GROUP", "AZURE_CDN_PROFILE_NAME", "AZURE_CDN_ENDPOINT_NAME", "GITLAB_NUGET_TOKEN", "GITLAB_USERNAME", ].freeze
- ALL_VARS =
All environment variablesazure_key_vault.r
(REQUIRED_VARS + OPTIONAL_VARS).freeze
Class Method Summary collapse
-
.azure_cli_authenticated? ⇒ Boolean
Check if Azure CLI is authenticated.
-
.generate_secret_name_from_url(url) ⇒ Object
Generate a valid Azure Key Vault secret name from a Git remote URL Azure Key Vault secret names must be 1-127 characters, alphanumeric and hyphens only, cannot start or end with hyphen, and cannot have consecutive hyphens.
-
.get_git_remote_url ⇒ Object
Get GIT_REMOTE_URL from various sources.
-
.keyvault_name ⇒ Object
Get Azure Key Vault name from environment or use default.
-
.kvenv_available? ⇒ Boolean
Check if kvenv is available.
-
.load(keyvault_name: nil, secret_name: nil) ⇒ Boolean
Load secrets from Azure Key Vault using kvenv.
-
.secret_name ⇒ Object
Get secret name from environment or auto-generate from GIT_REMOTE_URL.
-
.secret_prefix ⇒ Object
Get secret prefix from environment.
-
.set(secret_name, secret_value, keyvault_name: nil) ⇒ Boolean
Set a secret in Azure Key Vault.
-
.setup ⇒ Object
Setup method: Attempt to initialize environment variables.
-
.status ⇒ Object
Get status of all environment variables.
-
.verify(warn_only: true) ⇒ Object
Verify that expected environment variables are set.
Class Method Details
.azure_cli_authenticated? ⇒ Boolean
Check if Azure CLI is authenticated
31 32 33 34 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 31 def self.azure_cli_authenticated? return false unless system("which az > /dev/null 2>&1") system("az account show > /dev/null 2>&1") end |
.generate_secret_name_from_url(url) ⇒ Object
Generate a valid Azure Key Vault secret name from a Git remote URL Azure Key Vault secret names must be 1-127 characters, alphanumeric and hyphens only, cannot start or end with hyphen, and cannot have consecutive hyphens
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 78 def self.generate_secret_name_from_url(url) # Remove protocol (http://, https://, git@) name = url.gsub(/^https?:\/\//, "").gsub(/^git@/, "") # Remove .git suffix if present name = name.gsub(/\.git$/, "") # Replace invalid characters with hyphens name = name.gsub(/[^a-zA-Z0-9\-]/, "-") # Remove consecutive hyphens name = name.gsub(/-+/, "-") # Remove leading/trailing hyphens name = name.gsub(/^-+|-+$/, "") # Ensure it starts with a letter or number (Azure requirement) name = "secret-#{name}" if name.empty? || name.match(/^[^a-zA-Z0-9]/) # Truncate to 127 characters (Azure Key Vault limit) name = name[0, 127] # Remove trailing hyphen if truncation created one name = name.gsub(/-+$/, "") # Ensure it's not empty name = "git-secrets" if name.empty? name end |
.get_git_remote_url ⇒ Object
Get GIT_REMOTE_URL from various sources
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 55 def self.get_git_remote_url # Try constant first return GIT_REMOTE_URL if defined?(GIT_REMOTE_URL) && !GIT_REMOTE_URL.nil? && !GIT_REMOTE_URL.empty? # Try Git module if defined?(Makit::Git) && Makit::Git.git_repo? url = Makit::Git.get_remote_url return url if url && !url.empty? end # Try project configuration if defined?(Makit::Configuration::Project) project = Makit::Configuration::Project.default url = project.git_remote_url return url if url && !url.nil? && !url.empty? end nil end |
.keyvault_name ⇒ Object
Get Azure Key Vault name from environment or use default
37 38 39 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 37 def self.keyvault_name ENV["AZURE_KEYVAULT_NAME"] || "louparslow-secrets" end |
.kvenv_available? ⇒ Boolean
Check if kvenv is available
26 27 28 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 26 def self.kvenv_available? system("which kvenv > /dev/null 2>&1") end |
.load(keyvault_name: nil, secret_name: nil) ⇒ Boolean
Load secrets from Azure Key Vault using kvenv
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 215 def self.load(keyvault_name: nil, secret_name: nil) # Use provided parameters or fall back to defaults kv_name = keyvault_name || self.keyvault_name sec_name = secret_name || self.secret_name unless kvenv_available? puts " Warning: kvenv not installed, secrets will not be loaded".colorize(:yellow) return false end # Check if Azure CLI is authenticated (kvenv can use this) unless azure_cli_authenticated? puts " Warning: Azure CLI not authenticated, run 'az login' first".colorize(:yellow) return false end cache_file = "/tmp/kvenv-#{sec_name}.json" # Build kvenv command cmd_parts = [ "kvenv cache", "--azure", "--azure-keyvault-name #{kv_name}", ] if secret_prefix cmd_parts << "--secret-prefix #{secret_prefix}" else cmd_parts << "--secret-name #{sec_name}" end cmd_parts << "--output #{cache_file}" # Run kvenv to cache secrets puts " Loading secrets from Key Vault: #{kv_name}, Secret: #{sec_name}".colorize(:cyan) success = system(cmd_parts.join(" ")) return false unless success return false unless File.exist?(cache_file) # Load secrets from cache file begin require "json" secrets = JSON.parse(File.read(cache_file)) # Set environment variables (don't override existing ones) loaded_count = 0 secrets.each do |key, value| unless ENV[key] ENV[key] = value loaded_count += 1 end end puts " Loaded #{loaded_count} secrets from Azure Key Vault (#{secrets.keys.count} total in secret)".colorize(:green) true rescue => e puts " Warning: Could not parse secrets from cache: #{e.}".colorize(:yellow) false end end |
.secret_name ⇒ Object
Get secret name from environment or auto-generate from GIT_REMOTE_URL
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 42 def self.secret_name return ENV["AZURE_SECRET_NAME"] if ENV["AZURE_SECRET_NAME"] && !ENV["AZURE_SECRET_NAME"].empty? # Auto-generate from GIT_REMOTE_URL git_remote_url = get_git_remote_url if git_remote_url && !git_remote_url.empty? generate_secret_name_from_url(git_remote_url) else "portal-secrets" # Fallback default end end |
.secret_prefix ⇒ Object
Get secret prefix from environment
110 111 112 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 110 def self.secret_prefix ENV["AZURE_SECRET_PREFIX"] end |
.set(secret_name, secret_value, keyvault_name: nil) ⇒ Boolean
Set a secret in Azure Key Vault
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 281 def self.set(secret_name, secret_value, keyvault_name: nil) # Use provided parameter or fall back to default kv_name = keyvault_name || self.keyvault_name if secret_name.nil? || secret_name.empty? raise "Secret name is required" end if secret_value.nil? || secret_value.empty? raise "Secret value is required" end unless azure_cli_authenticated? raise "Azure CLI is not authenticated. Run 'az login' first" end puts " Setting secret '#{secret_name}' in Key Vault: #{kv_name}".colorize(:cyan) # Build Azure CLI command cmd = [ "az keyvault secret set", "--vault-name '#{kv_name}'", "--name '#{secret_name}'", "--value '#{secret_value}'", "2>&1", ].join(" ") output = `#{cmd}` exit_code = $?.exitstatus if exit_code != 0 puts " Error: Failed to set secret".colorize(:red) puts " #{output}".colorize(:red) return false end puts " Successfully set secret '#{secret_name}' in Key Vault".colorize(:green) true end |
.setup ⇒ Object
Setup method: Attempt to initialize environment variables
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 115 def self.setup puts "Setting up secrets...".colorize(:blue) # Check if required variables are already set missing_required = REQUIRED_VARS.select { |var| ENV[var].nil? || ENV[var].empty? } if missing_required.empty? puts " All required environment variables are already set".colorize(:green) return true end puts " Missing required variables: #{missing_required.join(", ")}".colorize(:yellow) puts " Attempting to load from Azure Key Vault...".colorize(:yellow) # Try to load from Azure Key Vault if load(keyvault_name: nil, secret_name: nil) # Verify again after loading still_missing = REQUIRED_VARS.select { |var| ENV[var].nil? || ENV[var].empty? } if still_missing.empty? puts " Successfully loaded all required secrets".colorize(:green) return true else puts " Warning: Still missing required variables: #{still_missing.join(", ")}".colorize(:yellow) return false end else puts " Could not load secrets from Azure Key Vault".colorize(:yellow) puts " Please set environment variables manually or configure Azure Key Vault access".colorize(:yellow) return false end end |
.status ⇒ Object
Get status of all environment variables
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 191 def self.status puts "Environment Variables Status:".colorize(:blue) puts "" puts "Required Variables:".colorize(:cyan) REQUIRED_VARS.each do |var| status = ENV[var].nil? || ENV[var].empty? ? "❌ Not set" : "✅ Set" color = ENV[var].nil? || ENV[var].empty? ? :red : :green puts " #{var}: #{status}".colorize(color) end puts "" puts "Optional Variables:".colorize(:cyan) OPTIONAL_VARS.each do |var| status = ENV[var].nil? || ENV[var].empty? ? "⚪ Not set" : "✅ Set" color = ENV[var].nil? || ENV[var].empty? ? :yellow : :green puts " #{var}: #{status}".colorize(color) end end |
.verify(warn_only: true) ⇒ Object
Verify that expected environment variables are set
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/makit/secrets/azure_key_vault.rb', line 148 def self.verify(warn_only: true) issues = [] warnings = [] # Check required variables REQUIRED_VARS.each do |var| if ENV[var].nil? || ENV[var].empty? issues << "Required variable '#{var}' is not set" end end # Check optional variables (only warn) OPTIONAL_VARS.each do |var| if ENV[var].nil? || ENV[var].empty? warnings << "Optional variable '#{var}' is not set" end end # Report issues if issues.any? if warn_only issues.each { |issue| puts " ⚠️ #{issue}".colorize(:yellow) } else issues.each { |issue| puts " ❌ #{issue}".colorize(:red) } end end if warnings.any? warnings.each { |warning| puts " ℹ️ #{warning}".colorize(:cyan) } end if issues.empty? && warnings.empty? puts " ✅ All environment variables are set".colorize(:green) return true elsif issues.empty? puts " ✅ All required environment variables are set".colorize(:green) return true else return false end end |