Skip to content

Commit

Permalink
Add EncryptedEnvironmentVariable
Browse files Browse the repository at this point in the history
  • Loading branch information
drhaynes authored and dhardiman committed Jan 22, 2024
1 parent 47b0a31 commit 79fa21a
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Sources/Config/ConfigurationFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func parseNextProperty(properties: [String: Property], pair: (key: String, value
var copy = properties
if let typeHint = PropertyType(rawValue: typeHintValue) {
switch typeHint {
case .string, .url, .encrypted, .encryptionKey, .colour, .image, .regex, .environmentVariable:
case .string, .url, .encrypted, .encryptionKey, .colour, .image, .regex, .environmentVariable, .encryptedEnvironmentVariable:
copy[pair.key] = ConfigurationProperty<String>(key: pair.key, typeHint: typeHintValue, dict: dict, patterns: patterns)
case .optionalString:
copy[pair.key] = ConfigurationProperty<String?>(key: pair.key, typeHint: typeHintValue, dict: dict, patterns: patterns)
Expand Down
24 changes: 18 additions & 6 deletions Sources/Config/Property.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ enum PropertyType: String {
case dynamicColour = "DynamicColour"
case dynamicColourReference = "DynamicColourReference"
case environmentVariable = "EnvironmentVariable"
case encryptedEnvironmentVariable = "EncryptedEnvironmentVariable"

var typeName: String {
switch self {
case .encrypted, .encryptionKey:
case .encrypted, .encryptionKey, .encryptedEnvironmentVariable:
return "[UInt8]"
case .dictionary:
return "[String: Any]"
Expand Down Expand Up @@ -154,17 +155,28 @@ enum PropertyType: String {
case .dynamicColourReference:
return dynamicColourReferenceValue(for: value as? [String: String])
case .environmentVariable:
guard let environmentVariable = value as? String,
let rawValue = getenv(environmentVariable),
let stringValue = String(utf8String: rawValue) else {
fatalError("Missing environment variable \(value)")
return "#\"\(environmentVariable(for: value as? String))\"#"
case .encryptedEnvironmentVariable:
let valueString = environmentVariable(for: value as? String)
guard let key = key else { fatalError("No encryption key present to encrypt value") }
guard let encryptedString = valueString.encrypt(key: Array(key.utf8), iv: Array(iv.hash.utf8)) else {
fatalError("Unable to encrypt \(value) with key")
}
return "#\"\(stringValue)\"#"
return byteArrayOutput(from: encryptedString)
default:
return "\(value)"
}
}

private func environmentVariable(for value: String?) -> String {
guard let environmentVariableName = value,
let rawValue = getenv(environmentVariableName),
let stringValue = String(utf8String: rawValue) else {
fatalError("Missing environment variable \(value ?? "")")
}
return stringValue
}

private func colourValue(for value: String?) -> String {
guard let value = value else { return "No colour provided" }
let string = value.replacingOccurrences(of: "#", with: "")
Expand Down
19 changes: 17 additions & 2 deletions Tests/ConfigTests/ConfigurationPropertyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -348,14 +348,24 @@ class ConfigurationPropertyTests: XCTestCase {
}

func testItCanWriteAnEnvironmentVariableProperty() throws {
// Set an environment variable using the libc API
setenv("SOMETHING", "testValue", 1)
when(environmentVariableNamed: "SOMETHING", hasValue: "testValue")
let property = ConfigurationProperty<String>(key: "test", typeHint: "EnvironmentVariable", dict: ["defaultValue": "SOMETHING"])
let expectedValue = ##" static let test: String = #"testValue"#"##
let actualValue = try whenTheDeclarationIsWritten(for: property)
expect(actualValue).to(equal(expectedValue))
}

func testItCanWriteAnEncryptedEnvironmentVariableProperty() throws {
// Note: this test doesn't test the encryption itself, that test will be written elsewhere
when(environmentVariableNamed: "SOMETHING_SECRET", hasValue: "secretValue")
let property = ConfigurationProperty<String>(key: "test",
typeHint: "EncryptedEnvironmentVariable",
dict: ["defaultValue": "SOMETHING_SECRET"])
let expectedValue = " static let test: [UInt8] = ["
let actualValue = try whenTheDeclarationIsWritten(for: property, encryptionKey: "testKey")
expect(actualValue).to(beginWith(expectedValue))
}

func testItCanUseCommonPatternsForOverrides() throws {
let dict: [String: Any] = [
"defaultValue": "test value",
Expand All @@ -368,4 +378,9 @@ class ConfigurationPropertyTests: XCTestCase {
let actualValue = try whenTheDeclarationIsWritten(for: property, scheme: "gary")
expect(actualValue).to(equal(expectedValue))
}

private func when(environmentVariableNamed environmentVariableName: String, hasValue value: String) {
// Set an environment variable using the libc API
setenv(environmentVariableName, value, 1)
}
}

0 comments on commit 79fa21a

Please sign in to comment.