diff --git a/lib/puppet/provider/vs_ssl/ovs.rb b/lib/puppet/provider/vs_ssl/ovs.rb new file mode 100644 index 00000000..cff2e06a --- /dev/null +++ b/lib/puppet/provider/vs_ssl/ovs.rb @@ -0,0 +1,100 @@ +Puppet::Type.type(:vs_ssl).provide(:ovs) do + commands :vsctl => 'ovs-vsctl' + + bootstrap_ca_cert = '/etc/openvswitch/cacert.pem' + + def singleton_check + if not @resource[:name].eql? 'system' + raise Puppet::Error, "OVS ssl provider only supports singleton instance with name 'system'" + end + end + + def parse_ssl_output(filter=false) + output = vsctl('get=ssl').split("\n") + if output.empty? + return false + end + + if filter == false + return output + end + + output.each do |line| + key, value = line.split(': ').map(&:strip) + if key.eql? filter + return value + end + end + + raise Puppet::Error, "Unable to parse ssl output for filter: #{filter} in ssl output: #{output}" + end + + def create + singleton_check + unless File.file?(@resource[:key_file]) + raise Puppet::Error, "Key file not found: #{@resource[:key_file]}" + end + unless File.file?(@resource[:cert_file]) + raise Puppet::Error, "Certificate file not found: #{@resource[:cert_file]}" + end + if @resource[:bootstrap] + vsctl('--', '--bootstrap', 'set-ssl', @resource[:key_file], @resource[:cert_file], bootstrap_ca_cert) + else + unless File.file?(@resource[:ca_file]) + raise Puppet::Error, "CA Certificate file not found: #{@resource[:ca_file]}" + end + vsctl('--', 'set-ssl', @resource[:key_file], @resource[:cert_file], @resource[:ca_file]) + end + end + + def destroy + vsctl('del-ssl') + end + + def exists? + singleton_check + output = vsctl('get-ssl') + if output.empty? + return false + else + return true + end + end + + def key_file + return parse_ssl_output('Private key') + end + + def key_file=(key_file) + destroy + create + end + + def cert_file + return parse_ssl_output('Certificate') + end + + def cert_file=(cert_file) + destroy + create + end + + def ca_file + return parse_ssl_output('CA Certificate') + end + + def ca_file=(ca_file) + destroy + create + end + + def bootstrap + return parse_ssl_output('Bootstrap') + end + + def bootstrap=(bootstrap) + destroy + create + end + +end diff --git a/lib/puppet/type/vs_ssl.rb b/lib/puppet/type/vs_ssl.rb new file mode 100644 index 00000000..7f661ccf --- /dev/null +++ b/lib/puppet/type/vs_ssl.rb @@ -0,0 +1,43 @@ +Puppet::Type.newtype(:vs_ssl) do + + ensurable + + newparam(:name, :namevar => true) do + desc "Name of SSL configuration" + newvalues(/^\w+$/) + end + + newparam(:key_file) do + desc "Private key file path" + validate do |value| + if !value.is_a?(String) + raise ArgumentError, "Key file path must be a string" + end + end + end + + newparam(:cert_file) do + desc "Certificate filepath" + validate do |value| + if !value.is_a?(String) + raise ArgumentError, "Certificate file path must be a string" + end + end + end + + newparam(:ca_file) do + desc "CA authority certificate file path" + validate do |value| + if value + if !value.is_a?(String) + raise ArgumentError, "CA cert file path must be a string" + end + end + end + end + + newparam(:bootstrap, :boolean => true) do + desc "Enable bootstrapping without CA certificate and accept controller CA cert" + defaultto false + end +end diff --git a/releasenotes/notes/add-ssl-custom-type-4dcad2cb27cfd5e9.yaml b/releasenotes/notes/add-ssl-custom-type-4dcad2cb27cfd5e9.yaml new file mode 100644 index 00000000..35272fac --- /dev/null +++ b/releasenotes/notes/add-ssl-custom-type-4dcad2cb27cfd5e9.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds new custom type for configuring SSL (keys and certificates) within + vswitch. Includes single provider for Open vSwitch. diff --git a/spec/unit/puppet/lib/provider/vs_ssl_ovs_spec.rb b/spec/unit/puppet/lib/provider/vs_ssl_ovs_spec.rb new file mode 100644 index 00000000..baca1ecf --- /dev/null +++ b/spec/unit/puppet/lib/provider/vs_ssl_ovs_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Puppet::Type.type(:vs_ssl).provider(:ovs) do + let :ssl_attrs do + { + :name => 'system', + :ensure => 'present', + } + end + + let :resource do + Puppet::Type::Vs_ssl.new(ssl_attrs) + end + + let :provider do + described_class.new(resource) + end + + context 'when changing cert_file' do + it 'should recreate ssl config' do + File.stubs(:file?).returns(true) + provider.expects(:destroy) + provider.expects(:create) + provider.cert_file = '/tmp/blah.crt' + end + end + + context 'when changing key_file' do + it 'should recreate ssl config' do + File.stubs(:file?).returns(true) + provider.expects(:destroy) + provider.expects(:create) + provider.key_file = '/tmp/blah.pem' + end + end + + context 'when changing ca_file' do + it 'should recreate ssl config' do + File.stubs(:file?).returns(true) + provider.expects(:destroy) + provider.expects(:create) + provider.ca_file = '/tmp/blah.crt' + end + end + + context 'when creating with non-singleton name, system' do + it 'should fail' do + expect{described_class.new(Puppet::Type::Vs_ssl.new( + { + :name => 'dummy', + :ensure => :present})).create}.to raise_error(Puppet::Error) + end + end + +end diff --git a/spec/unit/puppet/lib/type/vs_ssl_spec.rb b/spec/unit/puppet/lib/type/vs_ssl_spec.rb new file mode 100644 index 00000000..1ec697e2 --- /dev/null +++ b/spec/unit/puppet/lib/type/vs_ssl_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Puppet::Type.type(:vs_ssl) do + it "should support present as a value for ensure" do + expect do + described_class.new(:name => 'system', :ensure => :present) + end.to_not raise_error + end + + it "should accept key_file, cert_file, ca_file, bootstrap options" do + expect do + described_class.new({ + :name => 'system', + :ensure => :present, + :key_file => '/tmp/dummyfile.pem', + :cert_file => '/tmp/dummyfile.crt', + :ca_file => '/tmp/dummyca.crt', + :bootstrap => false}) + end.to_not raise_error + end +end