pureftpd
Version information
Start using this module
Add this module to your Puppetfile:
mod 'jhoblitt-pureftpd', '1.2.0'
Learn more about managing modules with a PuppetfileDocumentation
Puppet pureftpd Module
Table of Contents
- Overview
- Description
- Usage
pure-ftpd
Options- Basic Usage
- SELinux Support
- [Setting Configuration Options](#setting-configuration options)
- Enabling LDAP Authentication
- Enabling MYSQL Authentication
- Enabling PGSQL Authentication
- Limitations
- Versioning
- Support
- See Also
Overview
Manages the pure-ftpd package with comprehensive configuration support
Description
This is a puppet module for installation and configuration of the
pure-ftpd
software package. It
aims to support all valid configuration file values.
Forked
This module started out as a fork of
5Ub-Z3r0/puppet-pureftpd
but
has been so heavily redesigned over time that it's probably not reasonable to
blame any of the design or implementation on
5Ub-Z3r0
. It would also be exceptionally
difficult to re-unify the two modules due to fundamental API differences.
The original module was marked as being licensed under GPLv3
in comments and
no LICENSE
file was present. Very little to none of the original module code
remains in the present version of this module. All contributions by Joshua Hoblitt
are licensed under Apache License, Version 2.0
. You should consult
with a lawyer for a legal opinion as to weather or not this module constitutes
a derived work.
Usage
In general, any valid pure-ftpd
configuration file option (including the
separate configuration files for auth modules) can be set by creating a key in
the appropriate class parameter hash but with the name of the option
transliterated to lowercase. The values passed to that option are handled
completely as raw strings but this module. No effort is made to handle
boolean
or integer
values as pure-ftpd
itself is not consistent in how it
handles these values.
For example, if you wanted to create the configuration option example below in
the file /etc/pure-ftpd/pure-ftpd.conf
:
ChrootEveryone yes
You would declare it like this to the pureftpd
module:
class { 'pureftpd':
config => {
chrooteveryone => 'yes',
}
}
The notable exception to that rule is for these pure-ftpd.conf
options, which
should not need to be manually declared. Passing a hash of configuration
options to the appropriate class parameter automatically defines these options
for you.
LDAPConfigFile
MySQLConfigFile
PGSQLConfigFile
pure-ftpd
Options
The pure-ftpd
documentation does not provide a canonical list of all possible
configuration options with examples. However, there are number of "HOW TO"s on
the official documentation web
page.
There is a list of command line switches in the distribution's
README
that
should all have pure-ftpd.conf
option analogs.
Here are some useful sources for discovering configuration parameters with examples:
Basic Usage
Install the pure-ftpd
package with an empty pure-ftpd.conf
config file
(accepting all defaults) and start pure-ftpd
as a stand alone daemon.
class { 'pureftpd': }
SELinux Support
class { 'pureftpd':
use_selinux => true,
}
Setting Configuration Options
Options for pure-ftpd.conf
should be passed into the config
class parameter
as a hash.
class { 'pureftpd':
config => {
ipv4only => 'yes',
ipv6only => 'yes',
chrooteveryone => 'yes',
brokenclientscompatibility => 'no',
daemonize => 'yes',
verboselog => 'no',
displaydotfiles => 'yes',
anonymousonly => 'no',
noanonymous => 'no',
dontresolve => 'yes',
anonymouscancreatedirs => 'no',
natmode => 'no',
calluploadscript => 'yes',
antiwarez => 'yes',
allowuserfxp => 'no',
allowanonymousfxp => 'no',
prohibitdotfileswrite => 'no',
prohibitdotfilesread => 'no',
allowdotfiles => 'no',
autorename => 'no',
anonymouscantupload => 'no',
logpid => 'yes',
nochmod => 'yes',
keepallfiles => 'yes',
createhomedir => 'yes',
norename => 'yes',
customerproof => 'yes',
notruncate => 'yes',
filesystemcharset => 'big5',
clientcharset => 'big5',
syslogfacility => 'ftp',
fortunesfile => '/usr/share/fortune/zippy',
forcepassiveip => '192.168.0.1',
bind => '127.0.0.1,21',
anonymousbandwidth => '8',
userbandwidth => '8',
trustedip => '10.1.1.1',
altlog => 'w3c:/var/log/pureftpd.log',
pidfile => '/var/run/pure-ftpd.pid',
tlsciphersuite => 'HIGH:MEDIUM:+TLSv1:!SSLv2:+SSLv3',
maxidletime => '15',
maxdiskusage => '99',
trustedgid => '100',
maxclientsnumber => '50',
maxclientsperip => '8',
maxload => '4',
minuid => '100',
tls => '1',
limitrecursion => '10000 8',
passiveportrange => '30000 50000',
anonymousratio => '1 10',
userratio => '1 10',
umask => '133:022',
quota => '1000:10',
peruserlimits => '3:20',
ldapconfigfile => '/etc/pureftpd-ldap.conf',
mysqlconfigfile => '/etc/pureftpd-mysql.conf',
pgsqlconfigfile => '/etc/pureftpd-pgsql.conf',
puredb => '/etc/pureftpd.pdb',
extauth => '/var/run/ftpd.sock',
unixauthentication => 'yes',
pamauthentication => 'yes',
},
}
Enabling LDAP Authentication
Options for pureftpd-ldap.conf
should be passed into the config_ldap
class
parameter as a hash.
class { 'pureftpd':
config_ldap => {
ldapserver => 'ldap.example.com',
ldapauthmethod => 'PASSWORD',
ldapport => '389',
ldapbinddn => 'cn=Manager,dc=c9x,dc=org',
ldapbindpw => 'r00tPaSsw0rD',
ldapbasedn => 'cn=Users,dc=c9x,dc=org',
ldapfilter => '(&(objectClass=posixAccount)(uid=\L))',
ldaphomedir => 'homeDirectory',
ldapversion => '3',
ldapdefaultuid => '100',
ldapdefaultgid => '100',
ldapusetls => 'False',
ldapauthmethod => 'PASSWORD',
},
}
Enabling MYSQL Authentication
Options for pureftpd-mysql.conf
should be passed into the config_mysql
class parameter as a hash.
class { 'pureftpd':
config_mysql => {
mysqlserver => 'localhost'
mysqlport => '3306'
mysqlsocket => '/tmp/mysql.sock'
mysqluser => 'root'
mysqlpassword => 'rootpw'
mysqldatabase => 'pureftpd'
mysqlcrypt => 'cleartext'
mysqltransactions => 'On'
mysqlgetpw => 'SELECT Password FROM users WHERE User="\L"'
mysqlgetuid => 'SELECT Uid FROM users WHERE User="\L"'
mysqldefaultuid => '1000'
mysqlgetgid => 'SELECT Gid FROM users WHERE User="\L"'
mysqldefaultgid => '1000'
mysqlgetdir => 'SELECT Dir FROM users WHERE User="\L"'
mysqlforcetildeexpansion => '0'
mysqlgetqtafs => 'SELECT QuotaFiles FROM users WHERE User="\L"'
mysqlgetqtasz => 'SELECT QuotaSize FROM users WHERE User="\L"'
mysqlgetratioul => 'SELECT ULRatio FROM users WHERE User="\L"'
mysqlgetratiodl => 'SELECT DLRatio FROM users WHERE User="\L"'
mysqlgetbandwidthul => 'SELECT ULBandwidth FROM users WHERE User="\L"'
mysqlgetbandwidthdl => 'SELECT DLBandwidth FROM users WHERE User="\L"'
},
}
Enabling PGSQL Authentication
Options for pureftpd-pgsql.conf
should be passed into the config_pgsql
class parameter as a hash.
class { 'pureftpd':
config_pgsql => {
pgsqlserver => 'localhost',
pgsqlport => '5432',
pgsqluser => 'postgres',
pgsqlpassword => 'rootpw',
pgsqldatabase => 'pureftpd',
pgsqlcrypt => 'cleartext',
pgsqlgetpw => 'SELECT Password FROM users WHERE User=\'\L\'',
pgsqlgetuid => 'SELECT Uid FROM users WHERE User=\'\L\'',
pgsqldefaultuid => '1000',
pgsqlgetgid => 'SELECT Gid FROM users WHERE User=\'\L\'',
pgsqldefaultgid => '1000',
pgsqlgetdir => 'SELECT Dir FROM users WHERE User=\'\L\'',
pgsqlgetqtafs => 'SELECT QuotaFiles FROM users WHERE User=\'\L\'',
pgsqlgetqtasz => 'SELECT QuotaSize FROM users WHERE User=\'\L\'',
pgsqlgetratioul => 'SELECT ULRatio FROM users WHERE User=\'\L\'',
pgsqlgetratiodl => 'SELECT DLRatio FROM users WHERE User=\'\L\'',
pgsqlgetbandwidthul => 'SELECT ULBandwidth FROM users WHERE User=\'\L\'',
pgsqlgetbandwidthdl => 'SELECT DLBandwidth FROM users WHERE User=\'\L\'',
},
}
Pedantic Example
class { 'pureftpd':
use_selinux => true,
config => {
ipv4only => 'yes',
ipv6only => 'yes',
chrooteveryone => 'yes',
brokenclientscompatibility => 'no',
daemonize => 'yes',
verboselog => 'no',
displaydotfiles => 'yes',
anonymousonly => 'no',
noanonymous => 'no',
dontresolve => 'yes',
anonymouscancreatedirs => 'no',
natmode => 'no',
calluploadscript => 'yes',
antiwarez => 'yes',
allowuserfxp => 'no',
allowanonymousfxp => 'no',
prohibitdotfileswrite => 'no',
prohibitdotfilesread => 'no',
allowdotfiles => 'no',
autorename => 'no',
anonymouscantupload => 'no',
logpid => 'yes',
nochmod => 'yes',
keepallfiles => 'yes',
createhomedir => 'yes',
norename => 'yes',
customerproof => 'yes',
notruncate => 'yes',
filesystemcharset => 'big5',
clientcharset => 'big5',
syslogfacility => 'ftp',
fortunesfile => '/usr/share/fortune/zippy',
forcepassiveip => '192.168.0.1',
bind => '127.0.0.1,21',
anonymousbandwidth => '8',
userbandwidth => '8',
trustedip => '10.1.1.1',
altlog => 'w3c:/var/log/pureftpd.log',
pidfile => '/var/run/pure-ftpd.pid',
tlsciphersuite => 'HIGH:MEDIUM:+TLSv1:!SSLv2:+SSLv3',
maxidletime => '15',
maxdiskusage => '99',
trustedgid => '100',
maxclientsnumber => '50',
maxclientsperip => '8',
maxload => '4',
minuid => '100',
tls => '1',
limitrecursion => '10000 8',
passiveportrange => '30000 50000',
anonymousratio => '1 10',
userratio => '1 10',
umask => '133:022',
quota => '1000:10',
peruserlimits => '3:20',
ldapconfigfile => '/etc/pureftpd-ldap.conf',
mysqlconfigfile => '/etc/pureftpd-mysql.conf',
pgsqlconfigfile => '/etc/pureftpd-pgsql.conf',
puredb => '/etc/pureftpd.pdb',
extauth => '/var/run/ftpd.sock',
unixauthentication => 'yes',
pamauthentication => 'yes',
},
config_ldap => {
ldapserver => 'ldap.example.com',
ldapauthmethod => 'PASSWORD',
ldapport => '389',
ldapbinddn => 'cn=Manager,dc=c9x,dc=org',
ldapbindpw => 'r00tPaSsw0rD',
ldapbasedn => 'cn=Users,dc=c9x,dc=org',
ldapfilter => '(&(objectClass=posixAccount)(uid=\L))',
ldaphomedir => 'homeDirectory',
ldapversion => '3',
ldapdefaultuid => '100',
ldapdefaultgid => '100',
ldapusetls => 'False',
ldapauthmethod => 'PASSWORD',
},
config_mysql => {
mysqlserver => 'localhost'
mysqlport => '3306'
mysqlsocket => '/tmp/mysql.sock'
mysqluser => 'root'
mysqlpassword => 'rootpw'
mysqldatabase => 'pureftpd'
mysqlcrypt => 'cleartext'
mysqltransactions => 'On'
mysqlgetpw => 'SELECT Password FROM users WHERE User="\L"'
mysqlgetuid => 'SELECT Uid FROM users WHERE User="\L"'
mysqldefaultuid => '1000'
mysqlgetgid => 'SELECT Gid FROM users WHERE User="\L"'
mysqldefaultgid => '1000'
mysqlgetdir => 'SELECT Dir FROM users WHERE User="\L"'
mysqlforcetildeexpansion => '0'
mysqlgetqtafs => 'SELECT QuotaFiles FROM users WHERE User="\L"'
mysqlgetqtasz => 'SELECT QuotaSize FROM users WHERE User="\L"'
mysqlgetratioul => 'SELECT ULRatio FROM users WHERE User="\L"'
mysqlgetratiodl => 'SELECT DLRatio FROM users WHERE User="\L"'
mysqlgetbandwidthul => 'SELECT ULBandwidth FROM users WHERE User="\L"'
mysqlgetbandwidthdl => 'SELECT DLBandwidth FROM users WHERE User="\L"'
},
config_pgsql => {
pgsqlserver => 'localhost',
pgsqlport => '5432',
pgsqluser => 'postgres',
pgsqlpassword => 'rootpw',
pgsqldatabase => 'pureftpd',
pgsqlcrypt => 'cleartext',
pgsqlgetpw => 'SELECT Password FROM users WHERE User=\'\L\'',
pgsqlgetuid => 'SELECT Uid FROM users WHERE User=\'\L\'',
pgsqldefaultuid => '1000',
pgsqlgetgid => 'SELECT Gid FROM users WHERE User=\'\L\'',
pgsqldefaultgid => '1000',
pgsqlgetdir => 'SELECT Dir FROM users WHERE User=\'\L\'',
pgsqlgetqtafs => 'SELECT QuotaFiles FROM users WHERE User=\'\L\'',
pgsqlgetqtasz => 'SELECT QuotaSize FROM users WHERE User=\'\L\'',
pgsqlgetratioul => 'SELECT ULRatio FROM users WHERE User=\'\L\'',
pgsqlgetratiodl => 'SELECT DLRatio FROM users WHERE User=\'\L\'',
pgsqlgetbandwidthul => 'SELECT ULBandwidth FROM users WHERE User=\'\L\'',
pgsqlgetbandwidthdl => 'SELECT DLBandwidth FROM users WHERE User=\'\L\'',
},
}
Limitations
At present, this module is only capable of installing the pure-ftpd
package
and enabling it as a daemonized service. The lack of uninstallation support is
probably a bug.
Only support for $::osfamily == 'RedHat'
has been implemented. Adding
support for other platform should be trivial but needs to involve full up
integration testing.
The supported configuration file values were discovered via code inspection of
the pure-ftpd
v1.0.31
release. There are possibly new configuration values
that have been introduced in subsequent releases. Any configuration values
present in a stable pure-ftpd
release but not supported by this module should
be considered a bug.
Tested Platforms
- el6.x
Versioning
This module is versioned according to the Semantic Versioning 2.0.0 specification.
Support
Please log tickets and issues at github
See Also
[Current]
- 554f1a8 - (Joshua Hoblitt) add boilerplate Versioning/See Also sections to README
- aee2b37 - (Joshua Hoblitt) remove README section on stdlib
This section has not be relevant since commit e1962ecd9dc93278121523e3d6d35e740af172ca.
- 6afbfdc - (Joshua Hoblitt) add
:require => false
to all Gemfile gems - aecaa3a - (Joshua Hoblitt) change .fixtures.yml to use https:// instead of git://
- 0fba3b0 - (Joshua Hoblitt) update .gitignore
- dc7b383 - (Joshua Hoblitt) Merge pull request #1 from jhoblitt/feature/drop_bundled_merge_function
Feature/drop bundled merge function
- 68dc8fc - (Joshua Hoblitt) remove bundled pureftpd_merge() function
The pureftpd_merge() function included in this module is a copy of the stdlib merge() function from commit id f496005bf3db8a5202bf9c16daf9a524b178c67a. This version of merge() includes a critical bug fix that was commit after the stdlib 4.1.0 release. Now that stdlib 4.2.0 has been released (finally!) with the needed fix, bundling a version of the merge() function in this module is no longer necessary.
v1.1.0
- 95265a0 - (Joshua Hoblitt) bump version to v1.1.0
- 56637b4 - (Joshua Hoblitt) update travis matrix
- e1962ec - (Joshua Hoblitt) give up all hope of a post stdlib 4.1.0 release happening
This module is dependant the behavior of the stdlib merge() function as of commit f496005bf3db8a5202bf9c16daf9a524b178c67a, which was merged after lastest (4.1.0) release. Since that release is almost a year old now, it's looking unlikely that there will be another release in the near future.
As a workaround, the merge() function has been copied into this module as pureftpd_merge() and the Module dep as been reduced to stdlib >= 4.0.0.
- 30bd33d - (Joshua Hoblitt) replace rspec include_class matcher with contain_class
To fix this warning with rspec-puppet >= 1.0.0:
DEPRECATION: include_class is deprecated. Use contain_class instead
v1.0.3
- 0795ca3 - (Joshua Hoblitt) bump version to v1.0.3
- 898bb72 - (Joshua Hoblitt) unmark README pure-ftpd.conf examples as puppet code
- f5a4b5e - (Joshua Hoblitt) add GFMD highlighting to README
- 7b4e426 - (Joshua Hoblitt) update README ToC
v1.0.2
- 7dc27d7 - (Joshua Hoblitt) bump version to v1.0.2
- 4b25bd6 - (Joshua Hoblitt) doc dependency on an unreleased version of stdlib
- b3310d8 - (Joshua Hoblitt) suppress lint 80char warning
- 73cbca7 - (Joshua Hoblitt) add puppet 3.3.0 to travis test matrix
- fb20c66 - (Joshua Hoblitt) puppet-lint should ignore pkg/**
v1.0.1
- d35098c - (Joshua Hoblitt) update Modulefile version to v1.0.1
- 964a3f0 - (Joshua Hoblitt) fix minor typos and line wrapping in README
v1.0.0
- 6fe72c8 - (Joshua Hoblitt) fix module name in Modfulefile
- 4644352 - (Joshua Hoblitt) remove templates/redhat dir since no templates are
$::osfamily
specific - 0b9c50b - (Joshua Hoblitt) minor README tweak
- 462d1f8 - (Joshua Hoblitt) add complete list of
pure-ftpd.conf
options to README - d7cd213 - (Joshua Hoblitt) add additional
pure-ftpd.conf
options
Support for these options:
-
UnixAuthentication
-
PAMAuthentication
-
TLSCipherSuite
-
ae03a97 - (Joshua Hoblitt) fix README typo
-
95ef983 - (Joshua Hoblitt) overhaul class pureftpd tests
-
38097ad - (Joshua Hoblitt) add $config_mysql param to class pureftpd
-
1c81250 - (Joshua Hoblitt) add tests for pureftpd::{install,params,service}
-
187c3f0 - (Joshua Hoblitt) pure-ftpd sysv init.d script supports the status command
-
7392746 - (Joshua Hoblitt) fix indent width in pureftpd::service
-
888dd0c - (Joshua Hoblitt) improve consistency of class pureftpd::config* tests
-
b3191a3 - (Joshua Hoblitt) remove stale tests dir
-
5ae1ce1 - (Joshua Hoblitt) Merge puppet-module_skel
-
afb41e2 - (Joshua Hoblitt) major doc update
-
1b4573a - (Joshua Hoblitt) update modulefile dep on stdlib to >= 4.1.0
It turns out that slightly older versions of merge() don't deal well with undefined variables
- c602ae9 - (Joshua Hoblitt) fix notify pureftpd::service on config* classes from pureftpd class
- 959a617 - (Joshua Hoblitt) more README commas for fun and profit
- 72dc2e6 - (Joshua Hoblitt) README typo
- 8be02d1 - (Joshua Hoblitt) replace condition unless with if ! for puppet 2.7.x compat
- ee08ab9 - (Joshua Hoblitt) @zaphod42's commas
- 8f590be - (Joshua Hoblitt) add config_pgsql param to class pureftpd
- df44134 - (Joshua Hoblitt) update pureftpd::config::mysql to use the common erb template + rspec
- ab4cfb9 - (Joshua Hoblitt) update pureftpd::config::pgsql to use the common erb template + rspec
- f50f4db - (Joshua Hoblitt) doc source of options for pure-ftpd.conf & pureftpd-ldap.conf
- 3f87b61 - (Joshua Hoblitt) remove duplicate check/typo
- 0242a33 - (Joshua Hoblitt) mv all pureftpd::service notification into pureftpd class
- 5abd649 - (Joshua Hoblitt) add config_ldap param to class pureftpd
To allow passing a hash of pureftpd-ldap.conf configuration values through to class pureftpd::config::ldap
- c3e8fdd - (Joshua Hoblitt) improve contexts in pureftpd::config rspec
- d50e2af - (Joshua Hoblitt) add missing configuration options/params to pureftpd::config + rspec
- d7ebceb - (Joshua Hoblitt) add missing $ldapserver param to pureftpd::config::ldap
- 3f7ec70 - (Joshua Hoblitt) fix or disable linter issues
- 889e3e8 - (Joshua Hoblitt) fix pureftpd config parameter test
Add missing newline escape. Workins locally for some reason but is breaking on travis-ci
- f5fc23b - (Joshua Hoblitt) add config param to class pureftpd
To allow passing a hash of pure-ftpd.conf configuration values through to class pureftpd::config
- a22b60a - (Joshua Hoblitt) add travis-ci build placard
- 9eaf2f3 - (Joshua Hoblitt) enable travis-ci
- d56464f - (Joshua Hoblitt) refactor pureftpd::config similar to pureftpd::config::ldap
to allow the same erb template to be shared between pureftpd::config and pureftpd::config::ldap
- d351586 - (Joshua Hoblitt) mv pureftpd::config_{ldap,mysql,pgsql} -> pureftpd::config::{ldap,mysql,pgsql}
- 7e1aa36 - (Joshua Hoblitt) remove unused class parameters/docs from pureftpd::config_{mysql,pgsql}
- 1e51466 - (Joshua Hoblitt) remove stale pureftpd::config_ldap docs
- ddb63b7 - (Joshua Hoblitt) reorder inheritance chain and refactor pureftpd::config_ldap
- 5230121 - (Joshua Hoblitt) whitespace tidy manifests/config.pp
- 3494b33 - (Joshua Hoblitt) add test for class pureftpd with $use_selinux
- 5b258e1 - (Joshua Hoblitt) move *conf file path and erb path selection into pureftpd::params
- d178271 - (Joshua Hoblitt) s/\r\n/\n/g
- 53b9f74 - (Joshua Hoblitt) convert pureftpd::config_pgsql from a define into a class
- d8bff85 - (Joshua Hoblitt) convert pureftpd::config_mysql from a define into a class
- cdb93ba - (Joshua Hoblitt) add trivial pureftpd class rspec
- 6cd6c2e - (Joshua Hoblitt) replace old unused rspec cruft with a clean template
- 05c7d97 - (Joshua Hoblitt) git ignore Gemfile.lock
- 6488ecb - (Joshua Hoblitt) install ruby gems from https://rubygems.org instead of :rubygems
To resolve this warning:
The source :rubygems is deprecated because HTTP requests are insecure. Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
- 7e74f57 - (Joshua Hoblitt) Merge puppet-module_skel
- 35901b5 - (Joshua Hoblitt) explicitly install pure-ftpd and pure-ftpd-selinux
when $::pureftpd::use_selinux is set
- 89d2718 - (Joshua Hoblitt) convert define pureftpd::config_ldap into a class
- dae9c20 - (Joshua Hoblitt) lowercase camel case template dir name
- 9aa1ad3 - (Joshua Hoblitt) add ldap/mysql/pgsql parameters to pureftpd::config
As a replacement for $default_auth
used the templates
- 1296a7b - (Joshua Hoblitt) restructure module so all classes for the inheritance hierarchy pureftpd -> pureftpd::params -> pureftpd::
- 12b5798 - (Joshua Hoblitt) convert pureftpd::config from a defined type into a class
- 7a3749c - (Joshua Hoblitt) properly fail on $::osfamily = debian
- 9304d99 - (Joshua Hoblitt) add pureftpd::config params for almost all pure-ftpd.conf variables
- 53647ab - (Joshua Hoblitt) remove dep on the epel class (stahnma/puppet-module-epel)
This module does not have any provision for using local / private EPEL mirrors
Dependencies
- puppetlabs/stdlib (>= 4.2.0)
Copyright (C) 2012-2014 Joshua Hoblitt <jhoblitt@cpan.org> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.