diff --git a/.fixtures.yml b/.fixtures.yml index fe014d5..8dcea8c 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -5,7 +5,7 @@ fixtures: forge_modules: kafka_connect: repo: "rjd1/kafka_connect" - ref: "2.1.0" + ref: "2.2.0" stdlib: "puppetlabs/stdlib" apt: "puppetlabs/apt" java: "puppetlabs/java" diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ce2795..b0d3b50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Release notes for the rjd1-kafka_connect module. +## Release 2.2.0 + +2024-04-16 - Improved secrets support + +- Added support for multiple key/value pairs in each secret file + ## Release 2.1.0 2024-04-02 - Support Ubuntu diff --git a/README.md b/README.md index 28e8307..b80c08a 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,19 @@ kafka_connect::secrets: value: 'ENC[PKCS7,encrypted-passwd-value]' ``` +To add multiple secrets to a single file, use the `kv_data` hash. Continuing with the example above, to instead have individual secret vars for each of the connection configs: + +```yaml +kafka_connect::secrets: + my-jdbc-secret-file.properties: + connectors: + - 'my-jdbc-connector' + kv_data: + jdbc-sink-connection-url: 'ENC[PKCS7,encrypted-url-value]' + jdbc-sink-connection-user: 'ENC[PKCS7,encrypted-user-value]' + jdbc-sink-connection-password: 'ENC[PKCS7,encrypted-passwd-value]' +``` + The `connectors` array should contain a list of connector names that reference it in the config. This allows for automatic update/refresh (via REST API restart POST) if the password value is changed. To later remove unused files, use the optional `ensure` hash key and set it to 'absent'. @@ -224,8 +237,6 @@ $ puppet resource kc_connector some-kc-connector-name ensure=absent enable_delet Tested with Confluent 7.x on Amazon Linux 2 and Ubuntu 22.04. -Each secrets file should contain only one key-value pair. - Currently only distributed mode setup is supported. ### Known Issues diff --git a/REFERENCE.md b/REFERENCE.md index 9dc915d..066c378 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -766,6 +766,7 @@ Struct[{ Optional['connectors'] => Array[String[1]], Optional['key'] => String[1], Optional['value'] => String[1], + Optional['kv_data'] => Hash[String[1], String[1]], }] ``` diff --git a/data/rspec/common.yaml b/data/rspec/common.yaml index f79dbf6..4b69e6d 100644 --- a/data/rspec/common.yaml +++ b/data/rspec/common.yaml @@ -22,5 +22,10 @@ kafka_connect::secrets: - 'my-cool-connector' key: 'some-connection-passwd' value: 'passwd-value' + my-super-duper-secret-file.properties: + kv_data: + db-url: 'my-db.example.com' + db-user: 'some-user' + db-passwd: 'some-passwd' my-no-longer-a-secret-file.properties: ensure: 'absent' diff --git a/data/rspec/host3.test.com.yaml b/data/rspec/host3.test.com.yaml new file mode 100644 index 0000000..75bd9a0 --- /dev/null +++ b/data/rspec/host3.test.com.yaml @@ -0,0 +1,9 @@ +--- +kafka_connect::secrets: + my-other-invalid-secret-file.properties: + key: 'some-connection-passwd' + value: 'passwd-value' + kv_data: + db-url: 'my-db.example.com' + db-user: 'some-user' + db-passwd: 'some-passwd' diff --git a/manifests/manage_connectors.pp b/manifests/manage_connectors.pp index 071c57d..db98251 100644 --- a/manifests/manage_connectors.pp +++ b/manifests/manage_connectors.pp @@ -94,6 +94,7 @@ $secret_connectors = $secret[1]['connectors'] $secret_key = $secret[1]['key'] $secret_value = $secret[1]['value'] + $secret_kv_data = $secret[1]['kv_data'] if $secret_ensure { $secret_file_ensure = $secret_ensure @@ -111,12 +112,17 @@ } if $secret_file_ensure =~ /^(present|file)$/ { - unless ($secret_key and $secret_value) { - fail("Secret key and value are required, unless ensure is set to absent. \ + unless (($secret_key and $secret_value) or $secret_kv_data) and !(($secret_key or $secret_value) and $secret_kv_data) { + fail("Either secret key and value or kv_data is required, unless ensure is set to absent. \ \n Validation error on ${secret_file_name} data, please correct. \n") } - $secret_content = Sensitive("${secret_key}=${secret_value}\n") + if $secret_kv_data { + $secret_data = join($secret_kv_data.map |$key,$value| { "${key}=${value}" }, "\n") + $secret_content = Sensitive("${secret_data}\n") + } else { + $secret_content = Sensitive("${secret_key}=${secret_value}\n") + } } file { $secret_file_name : diff --git a/metadata.json b/metadata.json index 2816486..db65c4b 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "rjd1-kafka_connect", - "version": "2.1.0", + "version": "2.2.0", "author": "rjd1", "summary": "Puppet module to manage Kafka Connect.", "license": "Apache-2.0", diff --git a/spec/classes/kafka_connect_spec.rb b/spec/classes/kafka_connect_spec.rb index b0fe76c..9607320 100644 --- a/spec/classes/kafka_connect_spec.rb +++ b/spec/classes/kafka_connect_spec.rb @@ -226,7 +226,7 @@ } end - describe 'with connector data invalid' do + describe 'with connector data invalid (host1)' do custom_facts = { fqdn: 'host1.test.com' } let(:facts) do os_facts.merge(custom_facts) @@ -235,7 +235,7 @@ it { is_expected.to compile.and_raise_error(%r{Connector\sconfig\srequired}) } end - describe 'with secret present' do + describe 'with secret k/v string pair present' do it { is_expected .to contain_file('my-super-secret-file.properties') @@ -248,6 +248,19 @@ } end + describe 'with secret k/v hash data present' do + it { + is_expected + .to contain_file('my-super-duper-secret-file.properties') + .with_ensure('present') + .with_path('/etc/kafka-connect/my-super-duper-secret-file.properties') + .with_content(sensitive("db-url=my-db.example.com\ndb-user=some-user\ndb-passwd=some-passwd\n")) + .with_owner('cp-kafka-connect') + .with_group('confluent') + .with_mode('0600') + } + end + describe 'with secret absent' do it { is_expected @@ -257,13 +270,22 @@ } end - describe 'with secret data invalid' do + describe 'with secret data invalid (host2)' do custom_facts = { fqdn: 'host2.test.com' } let(:facts) do os_facts.merge(custom_facts) end - it { is_expected.to compile.and_raise_error(%r{Secret\skey\sand\svalue\sare\srequired}) } + it { is_expected.to compile.and_raise_error(%r{Validation\serror}) } + end + + describe 'with secret data invalid (host3)' do + custom_facts = { fqdn: 'host3.test.com' } + let(:facts) do + os_facts.merge(custom_facts) + end + + it { is_expected.to compile.and_raise_error(%r{Validation\serror}) } end end end diff --git a/types/secret.pp b/types/secret.pp index cc51406..5fe7b6d 100644 --- a/types/secret.pp +++ b/types/secret.pp @@ -5,5 +5,6 @@ Optional['connectors'] => Array[String[1]], Optional['key'] => String[1], Optional['value'] => String[1], + Optional['kv_data'] => Hash[String[1], String[1]], } ]