From eb3924ac74b425033ec3a45d75dfd844b183c0f2 Mon Sep 17 00:00:00 2001 From: Lucas Yamanishi Date: Wed, 18 Jan 2017 10:26:41 -0500 Subject: [PATCH] Be more strict about versionlock strings This commit locks down the versionlock defined type using a more comprehensive regular expression, storing the Pattern in a type alias. Previously two simple regular expressions were used, but they allowed for invalid inputs with wildcards that spanned multiple fields-- wildcards are only permitted within an individual field. --- manifests/versionlock.pp | 10 ++------- spec/defines/versionlock_spec.rb | 18 ++++++++++++++-- types/versionlockstring.pp | 37 ++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 types/versionlockstring.pp diff --git a/manifests/versionlock.pp b/manifests/versionlock.pp index fb7e65d9..894be065 100644 --- a/manifests/versionlock.pp +++ b/manifests/versionlock.pp @@ -28,16 +28,10 @@ ) { include ::yum::plugin::versionlock - unless $name.is_a(Pattern[/^[0-9]+:.+\*$/, /^[0-9]+:.+-.+-.+\./]) { + unless $name.is_a(Yum::VersionlockString) { fail('Package name must be formated as %{EPOCH}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}. See Yum::Versionlock documentation for details.') } - $line = $name ? { - /^[0-9]+:.+\*$/ => $name, - /^[0-9]+:.+-.+-.+\./ => "${name}*", - default => $name, - } - $line_prefix = $ensure ? { 'exclude' => '!', default => '', @@ -46,7 +40,7 @@ case $ensure { 'present', 'exclude', default: { concat::fragment { "yum-versionlock-${name}": - content => "${line_prefix}${line}\n", + content => "${line_prefix}${name}\n", target => $yum::plugin::versionlock::path, } } diff --git a/spec/defines/versionlock_spec.rb b/spec/defines/versionlock_spec.rb index 8c453181..fe422ce0 100644 --- a/spec/defines/versionlock_spec.rb +++ b/spec/defines/versionlock_spec.rb @@ -9,7 +9,7 @@ context 'and no parameters' do it { is_expected.to compile.with_all_deps } it 'contains a well-formed Concat::Fragment' do - is_expected.to contain_concat__fragment("yum-versionlock-#{title}").with_content("#{title}*\n") + is_expected.to contain_concat__fragment("yum-versionlock-#{title}").with_content("#{title}\n") end end @@ -18,7 +18,7 @@ it { is_expected.to compile.with_all_deps } it 'contains a well-formed Concat::Fragment' do - is_expected.to contain_concat__fragment("yum-versionlock-#{title}").with_content("#{title}*\n") + is_expected.to contain_concat__fragment("yum-versionlock-#{title}").with_content("#{title}\n") end end @@ -41,9 +41,23 @@ end end + context 'with a complex wildcard title' do + let(:title) { '0:bash-4.*-*.el6' } + + it 'contains a well-formed Concat::Fragment' do + is_expected.to contain_concat__fragment("yum-versionlock-#{title}").with_content("#{title}\n") + end + end + context 'with an invalid title' do let(:title) { 'bash-4.1.2' } it { is_expected.to raise_error(Puppet::PreformattedError, %r(%\{EPOCH\}:%\{NAME\}-%\{VERSION\}-%\{RELEASE\}\.%\{ARCH\})) } end + + context 'with an invalid wildcard pattern' do + let(:title) { '0:bash-4.1.2*' } + + it { is_expected.to raise_error(Puppet::PreformattedError, %r(%\{EPOCH\}:%\{NAME\}-%\{VERSION\}-%\{RELEASE\}\.%\{ARCH\})) } + end end diff --git a/types/versionlockstring.pp b/types/versionlockstring.pp new file mode 100644 index 00000000..e7fcdf01 --- /dev/null +++ b/types/versionlockstring.pp @@ -0,0 +1,37 @@ +# This type matches strings appropriate for use with yum-versionlock. +# Its basic format, using the `rpm(8)` query string format, is +# `%{EPOCH}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}`. As a Regex, it +# breaks down into five distinct parts, plus the seperators. +# +# # EPOCH: An unsigned integer +# type Yum::PackageEpoch = Regexp[/[0-9]\*]+/] +# +# # NAME: Any valid package name (see https://github.com/rpm-software-management/rpm/blob/master/doc/manual/spec) +# type Yum::PackageName = Regexp[/[0-9a-zA-Z\._\+%\{\}\*-]+/] +# +# # VERSION: Any valid version string. The only limitation here, according to the RPM manual, is that it may not contain a dash (`-`). +# type Yum::PackageVersion = Regexp[/[^-]+/] +# +# # RELEASE: An unsigned integer +# type Yum::PackageRelease = Regexp[/[0-9\*]+/] +# +# # ARCH: Matches a string such as `el7.x86_64`. This is actuall two sub-expressions. See below. +# type Yum::PackageArch = Regexp[/([0-9a-zZ-Z_\*]+)(?:\.(noarch|x86_64|i386|arm|ppc64|ppc64le|sparc64|ia64|alpha|ip|m68k|mips|mipsel|mk68k|mint|ppc|rs6000|s390|s390x|sh|sparc|xtensa|\*))?/] +# +# The `%{ARCH}` sub-expression is composed of two sub-expressions +# separated by a dot (`.`), where the second part is optional. The RPM +# specification calls the first field the `DistTag`, and the second the +# `BuildArch`. +# +# # DistTag: Any string consiting of only letters, numbers, or an underscore, e.g., `el6`, `sl7`, or `fc24`. +# type Yum::PackageDistTag = Regexp[/[0-9a-zZ-Z_\*]+/] +# +# # BuildArch: Any string from the list at https://github.com/rpm-software-management/rpm/blob/master/rpmrc.in. Strings are roughly listed from most common to least common to improve performance. +# type Yum::PackageBuildArch = Regexp[/noarch|x86_64|i386|arm|ppc64|ppc64le|sparc64|ia64|alpha|ip|m68k|mips|mipsel|mk68k|mint|ppc|rs6000|s390|s390x|sh|sparc|xtensa/] +# +# @note Each field may contain wildcard characters (`*`), but the +# wildcard characters may not span the fields, may not cover the +# seperators. This is an undocumented but tested limitation of +# yum-versionlock. +# +type Yum::VersionlockString = Pattern[/^([0-9\*]+):([0-9a-zA-Z\._\+%\{\}\*-]+)-([^-]+)-([0-9\*]+)\.(([0-9a-zZ-Z_\*]+)(?:\.(noarch|x86_64|i386|arm|ppc64|ppc64le|sparc64|ia64|alpha|ip|m68k|mips|mipsel|mk68k|mint|ppc|rs6000|s390|s390x|sh|sparc|xtensa|\*))?)$/]