From: Philippe Wooding Date: Wed, 6 May 2015 16:18:23 +0000 (+0200) Subject: Add support for ldap, mysql and postgres tests through the use of an external VM. X-Git-Tag: release_3_0_9~288 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a6ca8ed7033b52508d10b4163eba203de4f7018;p=thirdparty%2Ffreeradius-server.git Add support for ldap, mysql and postgres tests through the use of an external VM. Required either TEST_SERVER of _TEST_SERVER env variable(s) to be defined. Add support for 'PRE' conditions in module tests' unlang definition (just like it's used in the keywords tests) --- diff --git a/src/tests/modules/all.mk b/src/tests/modules/all.mk index c2c15472931..ee5fd2c5356 100644 --- a/src/tests/modules/all.mk +++ b/src/tests/modules/all.mk @@ -32,132 +32,9 @@ $(foreach x,$(TEST_SUBBUILT),$(eval $x.test: rlm_$(subst /,_,$x).la)) ###################################################################### # # For the remaining subdirs, add on the directory to include. +# test.mk will run the tests for all modules +# It is included last so that the module specific makefiles can be processed first +# (modules that require a test server can # -SUBMAKEFILES := $(addsuffix /all.mk,$(TEST_BUILT) $(subst _,/,$(TEST_SUBBUILT))) +SUBMAKEFILES := $(addsuffix /all.mk,$(TEST_BUILT) $(subst _,/,$(TEST_SUBBUILT))) test.mk -# -# Add the module tests to the overall dependencies -# -tests.modules: tests.unit tests.keywords tests.auth $(patsubst %,%.test,$(TEST_BUILT) $(TEST_SUBBUILT)) - -###################################################################### -# -# And now more makefile magic to automatically run the tests -# for each module. -# - -define DEFAULT_ATTRS -ifeq "$(wildcard ${1}.attrs)" -${1}.attrs -else -src/tests/modules/default-input.attrs -endif -endef - -# -# Files in the output dir depend on the unit tests -# -# src/tests/$(MODULE_DIR)/FOO.unlang unlang for the test -# src/tests/$(MODULE_DIR)/FOO.attrs input RADIUS and output filter -# build/tests/$(MODULE_DIR)/FOO.out updated if the test succeeds -# build/tests/$(MODULE_DIR)/FOO.log debug output for the test -# -# If the test fails, then look for ERROR in the input. No error -# means it's unexpected, so we die. -# -# Otherwise, check the log file for a parse error which matches the -# ERROR line in the input. -# -$(BUILD_DIR)/tests/modules/%: src/tests/modules/%.unlang $(BUILD_DIR)/tests/modules/%.attrs $(TESTBINDIR)/unittest | build.raddb - @mkdir -p $(dir $@) - @echo MODULE-TEST $(lastword $(subst /, ,$(dir $@))) $(basename $(notdir $@)) - @if ! MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx > $@.log 2>&1; then \ - if ! grep ERROR $< 2>&1 > /dev/null; then \ - cat $@.log; \ - echo "# $@.log"; \ - echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ - exit 1; \ - fi; \ - FOUND=$$(grep ^$< $@.log | head -1 | sed 's/:.*//;s/.*\[//;s/\].*//'); \ - EXPECTED=$$(grep -n ERROR $< | sed 's/:.*//'); \ - if [ "$$EXPECTED" != "$$FOUND" ]; then \ - cat $@.log; \ - echo "# $@.log"; \ - echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ - exit 1; \ - fi \ - fi - @touch $@ - -# -# Sometimes we have a default input. So use that. Otherwise, use -# the input specific to the test. -# -MODULE_UNLANG := $(wildcard src/tests/modules/*/*.unlang src/tests/modules/*/*/*.unlang) -MODULE_ATTRS_REQUIRES := $(patsubst %.unlang,%.attrs,$(MODULE_UNLANG)) -MODULE_ATTRS_EXISTS := $(wildcard src/tests/modules/*/*.attrs src/tests/modules/*/*/*.attrs) -MODULE_ATTRS_NEEDS := $(filter-out $(MODULE_ATTRS_EXISTS),$(MODULE_ATTRS_REQUIRES)) - -MODULE_CONF_REQUIRES := $(patsubst %.unlang,%.conf,$(MODULE_UNLANG)) -MODULE_CONF_EXISTS := $(wildcard src/tests/modules/*/*.conf src/tests/modules/*/*/*.attrs) -MODULE_CONF_NEEDS := $(filter-out $(MODULE_CONF_EXISTS),$(MODULE_CONF_REQUIRES)) - -# -# The complete list of tests which are to be run -# -MODULE_TESTS := $(patsubst src/tests/modules/%/all.mk,%,$(wildcard src/tests/modules/*/all.mk)) - - -# -# Target-specific rules -# -define MODULE_COPY_FILE -$(BUILD_DIR)/${1}: src/${1} - @mkdir -p $$(@D) - @cp $$< $$@ - -endef - -# -# Default rules -# -define MODULE_COPY_ATTR -$(BUILD_DIR)/${1}: src/tests/modules/default-input.attrs - mkdir -p $$(@D) - @cp $$< $$@ -endef - -# -# FIXME: get this working -# -define MODULE_COPY_CONF -$(BUILD_DIR)/${1}: src/tests/modules/${2}/module.conf - @mkdir -p $$(@D) - @cp $$< $$@ -endef - -define MODULE_FILE_TARGET -$(BUILD_DIR)/${1}: src/${1}.unlang $(BUILD_DIR)/${1}.attrs - -endef - -define MODULE_TEST_TARGET -${1}.test: $(patsubst %.unlang,%,$(subst src,$(BUILD_DIR),$(filter src/tests/modules/${1}/%,$(MODULE_UNLANG)))) - -endef - -# -# Create the rules from the list of input files -# -$(foreach x,$(MODULE_ATTRS_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) -$(foreach x,$(MODULE_CONF_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) - -$(foreach x,$(MODULE_ATTRS_NEEDS),$(eval $(call MODULE_COPY_ATTR,$(subst src/,,$x)))) -# FIXME: copy src/tests/modules/*/module.conf to the right place, too - -$(foreach x,$(MODULE_UNLANG),$(eval $(call MODULE_FILE_TARGET,$(patsubst %.unlang,%,$(subst src/,,$x))))) -$(foreach x,$(MODULE_TESTS),$(eval $(call MODULE_TEST_TARGET,$x))) - -.PHONY: clean.modules.test -clean.modules.test: - @rm -rf $(BUILD_DIR)/tests/modules/ diff --git a/src/tests/modules/ldap/acct.attrs b/src/tests/modules/ldap/acct.attrs new file mode 100644 index 00000000000..1d570340528 --- /dev/null +++ b/src/tests/modules/ldap/acct.attrs @@ -0,0 +1,35 @@ +# +# Input packet +# +User-Name = 'john' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/ldap/acct.unlang b/src/tests/modules/ldap/acct.unlang new file mode 100644 index 00000000000..2297ea79f83 --- /dev/null +++ b/src/tests/modules/ldap/acct.unlang @@ -0,0 +1,23 @@ +# +# Run the "ldap" module +# PRE: auth +# +ldap.accounting { +} +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-String-0 := "%{ldap:ldap://$ENV{TEST_SERVER}/uid=john,ou=people,dc=example,dc=com?description}" +} + +if (&Tmp-String-0 != "User john is online") { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/ldap/all.mk b/src/tests/modules/ldap/all.mk new file mode 100644 index 00000000000..3464f6880c2 --- /dev/null +++ b/src/tests/modules/ldap/all.mk @@ -0,0 +1,11 @@ +# +# Test the "ldap" module +# + +# MODULE.test is the main target for this module. + +# Don't test ldap if TEST_SERVER ENV is not set +ldap_require_test_server := 1 + +ldap.test: + @echo OK: ldap.test diff --git a/src/tests/modules/ldap/auth.attrs b/src/tests/modules/ldap/auth.attrs new file mode 100644 index 00000000000..be988eeec42 --- /dev/null +++ b/src/tests/modules/ldap/auth.attrs @@ -0,0 +1,15 @@ +# +# Input packet +# +User-Name = "john" +User-Password = "password" +NAS-IP-Address = 1.2.3.5 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 +Session-Timeout == 7200 +Acct-Interim-Interval == 1800 +Framed-IP-Netmask == "255.255.0.0" diff --git a/src/tests/modules/ldap/auth.unlang b/src/tests/modules/ldap/auth.unlang new file mode 100644 index 00000000000..5a84500eb2d --- /dev/null +++ b/src/tests/modules/ldap/auth.unlang @@ -0,0 +1,80 @@ +# +# Run the "ldap" module +# +ldap + +if (&control:NAS-IP-Address != 1.2.3.4) { + test_fail +} +else { + test_pass +} + +if (&control:Reply-Message != "Hello world") { + test_fail +} +else { + test_pass +} + +# Cmp operator means Framed-IP-Address is ignored +if (&control:Framed-IP-Address) { + test_fail +} +else { + test_pass +} + +# IP netmask defined in profile1 should overwrite radprofile value. +if (&reply:Framed-IP-Netmask != 255.255.0.0) { + test_fail +} +else { + test_pass +} + +if (&reply:Acct-Interim-Interval != 1800) { + test_fail +} +else { + test_pass +} + +if (&reply:Idle-Timeout != 3600) { + test_fail +} +else { + test_pass +} + +if (&reply:Session-Timeout != 7200) { + test_fail +} +else { + test_pass +} + +if ("%{pairs:reply:}" == "") { + test_fail +} + + +if (LDAP-Group == "foo") { + test_pass +} +else { + test_fail +} + +ldap.post-auth + +update { + Tmp-String-0 := "%{ldap:ldap://$ENV{TEST_SERVER}/uid=john,ou=people,dc=example,dc=com?description}" +} + +if (&Tmp-String-0 != "User %{User-Name} authenticated") { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/ldap/example.com.ldif b/src/tests/modules/ldap/example.com.ldif new file mode 120000 index 00000000000..055d379bb2a --- /dev/null +++ b/src/tests/modules/ldap/example.com.ldif @@ -0,0 +1 @@ +../../salt-test-server/salt/ldap/base.ldif \ No newline at end of file diff --git a/src/tests/modules/ldap/module.conf b/src/tests/modules/ldap/module.conf new file mode 100644 index 00000000000..bf978e6a255 --- /dev/null +++ b/src/tests/modules/ldap/module.conf @@ -0,0 +1,538 @@ +# -*- text -*- +# +# $Id$ + +# +# Lightweight Directory Access Protocol (LDAP) +# +ldap { + # Note that this needs to match the name(s) in the LDAP server + # certificate, if you're using ldaps. See OpenLDAP documentation + # for the behavioral semantics of specifying more than one host. + # + # Depending on the libldap in use, server may be an LDAP URI. + # In the case of OpenLDAP this allows additional the following + # additional schemes: + # - ldaps:// (LDAP over SSL) + # - ldapi:// (LDAP over Unix socket) + # - ldapc:// (Connectionless LDAP) + server = $ENV{LDAP_TEST_SERVER} +# server = 'ldap.rrdns.example.org' + + # Port to connect on, defaults to 389, will be ignored for LDAP URIs. +# port = 389 + + # Administrator account for searching and possibly modifying. + identity = 'cn=admin,dc=example,dc=com' + password = secret + + # Unless overridden in another section, the dn from which all + # searches will start from. + base_dn = 'dc=example,dc=com' + + # SASL parameters to use for admin binds + # + # When we're prompted by the SASL library, these control + # the responses given. + # + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = 'autz_id' + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # + # Generic valuepair attribute + # + + # If set, this will attribute will be retrieved in addition to any + # mapped attributes. + # + # Values should be in the format: + # + # + # Where: + # : Is the attribute you wish to create + # with any valid list and request qualifiers. + # : Is any assignment operator (=, :=, +=, -=). + # : Is the value to parse into the new valuepair. + # If the value is wrapped in double quotes it + # will be xlat expanded. + valuepair_attribute = 'radiusAttribute' + + # + # Mapping of LDAP directory attributes to RADIUS dictionary attributes. + # + + # WARNING: Although this format is almost identical to the unlang + # update section format, it does *NOT* mean that you can use other + # unlang constructs in module configuration files. + # + # Configuration items are in the format: + # + # + # Where: + # : Is the destination RADIUS attribute + # with any valid list and request qualifiers. + # : Is any assignment attribute (=, :=, +=, -=). + # : Is the attribute associated with user or + # profile objects in the LDAP directory. + # If the attribute name is wrapped in double + # quotes it will be xlat expanded. + # + # Request and list qualifiers may also be placed after the 'update' + # section name to set defaults destination requests/lists + # for unqualified RADIUS attributes. + # + # Note: LDAP attribute names should be single quoted unless you want + # the name value to be derived from an xlat expansion, or an + # attribute ref. + update { + control:Password-With-Header += 'userPassword' + reply:Idle-Timeout := 'radiusIdleTimeout' + reply:Framed-IP-Netmask := 'radiusFramedIPNetmask' +# control:NT-Password := 'ntPassword' +# reply:Reply-Message := 'radiusReplyMessage' +# reply:Tunnel-Type := 'radiusTunnelType' +# reply:Tunnel-Medium-Type := 'radiusTunnelMediumType' +# reply:Tunnel-Private-Group-ID := 'radiusTunnelPrivategroupId' + + # Where only a list is specified as the RADIUS attribute, + # the value of the LDAP attribute is parsed as a valuepair + # in the same format as the 'valuepair_attribute' (above). + control: += 'radiusControlAttribute' + request: += 'radiusRequestAttribute' + reply: += 'radiusReplyAttribute' + } + + # Set to yes if you have eDirectory and want to use the universal + # password mechanism. +# edir = no + + # Set to yes if you want to bind as the user after retrieving the + # Cleartext-Password. This will consume the login grace, and + # verify user authorization. +# edir_autz = no + + # Note: set_auth_type was removed in v3.x.x + # Equivalent functionality can be achieved by adding the following + # stanza to the authorize {} section of your virtual server. + # + # ldap + # if ((ok || updated) && User-Password) { + # update { + # control:Auth-Type := ldap + # } + # } + + # + # User object identification. + # + user { + # Where to start searching in the tree for users + base_dn = 'ou=people,dc=example,dc=com' + #base_dn = 'ou=people,${..base_dn}' + + # Filter for user objects, should be specific enough + # to identify a single user object. + filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" + + # SASL parameters to use for user binds + # + # When we're prompted by the SASL library, these control + # the responses given. + # + # Any of the config items below may be an attribute ref + # or and expansion, so different SASL mechs, proxy IDs + # and realms may be used for different users. + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = &User-Name + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # Search scope, may be 'base', 'one', sub' or 'children' +# scope = 'sub' + + # If this is undefined, anyone is authorised. + # If it is defined, the contents of this attribute + # determine whether or not the user is authorised +# access_attribute = 'dialupAccess' + + # Control whether the presence of 'access_attribute' + # allows access, or denys access. + # + # If 'yes', and the access_attribute is present, or + # 'no' and the access_attribute is absent then access + # will be allowed. + # + # If 'yes', and the access_attribute is absent, or + # 'no' and the access_attribute is present, then + # access will not be allowed. + # + # If the value of the access_attribute is 'false', it + # will negate the result. + # + # e.g. + # access_positive = yes + # access_attribute = userAccessAllowed + # + # With an LDAP object containing: + # userAccessAllowed: false + # + # Will result in the user being locked out. +# access_positive = yes + } + + # + # User membership checking. + # + group { + # Where to start searching in the tree for groups + base_dn = 'ou=groups,dc=example,dc=com' + + # Filter for group objects, should match all available + # group objects a user might be a member of. + filter = '(objectClass=groupOfNames)' + + # Search scope, may be 'base', 'one', sub' or 'children' +# scope = 'sub' + + # Attribute that uniquely identifies a group. + # Is used when converting group DNs to group + # names. + name_attribute = cn + + # Filter to find group objects a user is a member of. + # That is, group objects with attributes that + # identify members (the inverse of membership_attribute). + membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))" + + # The attribute in user objects which contain the names + # or DNs of groups a user is a member of. + # + # Unless a conversion between group name and group DN is + # needed, there's no requirement for the group objects + # referenced to actually exist. +# membership_attribute = 'memberOf' + + # If cacheable_name or cacheable_dn are enabled, + # all group information for the user will be + # retrieved from the directory and written to LDAP-Group + # attributes appropriate for the instance of rlm_ldap. + # + # For group comparisons these attributes will be checked + # instead of querying the LDAP directory directly. + # + # This feature is intended to be used with rlm_cache. + # + # If you wish to use this feature, you should enable + # the type that matches the format of your check items + # i.e. if your groups are specified as DNs then enable + # cacheable_dn else enable cacheable_name. +# cacheable_name = 'no' +# cacheable_dn = 'no' + + # Override the normal cache attribute (-LDAP-Group) + # and create a custom attribute. This can help if multiple + # module instances are used in fail-over. +# cache_attribute = 'LDAP-Cached-Membership' + } + + # + # User profiles. RADIUS profile objects contain sets of attributes + # to insert into the request. These attributes are mapped using + # the same mapping scheme applied to user objects. + # + profile { + # Filter for RADIUS profile objects + filter = '(objectclass=radiusprofile)' + + # The default profile applied to all users. + default = 'cn=radprofile,ou=profiles,dc=example,dc=com' + + # The list of profiles which are applied (after the default) + # to all users. + # The 'User-Profile' attribute in the control list + # will override this setting at run-time. + attribute = 'radiusProfileDn' + } + + # + # Bulk load clients from the directory + # + client { + # Where to start searching in the tree for clients + base_dn = 'ou=people,dc=example,dc=com' + + # + # Filter to match client objects + # + filter = '(objectClass=radiusClient)' + + # Search scope, may be 'base', 'one', 'sub' or 'children' +# scope = 'sub' + + # + # Sets default values (not obtained from LDAP) for new client entries + # + template { +# login = 'test' +# password = 'test' +# proto = tcp +# require_message_authenticator = yes + + # Uncomment to add a home_server with the same + # attributes as the client. +# coa_server { +# response_window = 2.0 +# } + } + + # + # Client attribute mappings are in the format: + # = + # + # The following attributes are required: + # * ipaddr | ipv4addr | ipv6addr - Client IP Address. + # * secret - RADIUS shared secret. + # + # All other attributes usually supported in a client + # definition are also supported here. + # + # Schemas are available in doc/schemas/ldap for openldap and eDirectory + # + attribute { + ipaddr = 'radiusClientIdentifier' + secret = 'radiusClientSecret' +# shortname = 'radiusClientShortname' +# nas_type = 'radiusClientType' +# virtual_server = 'radiusClientVirtualServer' +# require_message_authenticator = 'radiusClientRequireMa' + } + } + + # Load clients on startup +# read_clients = no + + # + # Modify user object on receiving Accounting-Request + # + + # Useful for recording things like the last time the user logged + # in, or the Acct-Session-ID for CoA/DM. + # + # LDAP modification items are in the format: + # + # + # Where: + # : The LDAP attribute to add modify or delete. + # : One of the assignment operators: + # (:=, +=, -=, ++). + # Note: '=' is *not* supported. + # : The value to add modify or delete. + # + # WARNING: If using the ':=' operator with a multi-valued LDAP + # attribute, all instances of the attribute will be removed and + # replaced with a single attribute. + accounting { + reference = "%{tolower:type.%{Acct-Status-Type}}" + + type { + start { + update { + description := "User %{User-Name} is online" + } + } + + interim-update { + update { + description := "Last seen at %S" + } + } + + stop { + update { + description := "Offline at %S" + } + } + } + } + + # + # Post-Auth can modify LDAP objects too + # + post-auth { + update { + description := "User %{User-Name} authenticated" + } + } + + # + # LDAP connection-specific options. + # + # These options set timeouts, keep-alives, etc. for the connections. + # + options { + # Control under which situations aliases are followed. + # May be one of 'never', 'searching', 'finding' or 'always' + # default: libldap's default which is usually 'never'. + # + # LDAP_OPT_DEREF is set to this value. +# dereference = 'always' + + # + # The following two configuration items control whether the + # server follows references returned by LDAP directory. + # They are mostly for Active Directory compatibility. + # If you set these to 'no', then searches will likely return + # 'operations error', instead of a useful result. + # + chase_referrals = yes + rebind = yes + + # Seconds to wait for LDAP query to finish. default: 20 + timeout = 10 + + # Seconds LDAP server has to process the query (server-side + # time limit). default: 20 + # + # LDAP_OPT_TIMELIMIT is set to this value. + timelimit = 3 + + # Seconds to wait for response of the server. (network + # failures) default: 10 + # + # LDAP_OPT_NETWORK_TIMEOUT is set to this value. + net_timeout = 1 + + # LDAP_OPT_X_KEEPALIVE_IDLE + idle = 60 + + # LDAP_OPT_X_KEEPALIVE_PROBES + probes = 3 + + # LDAP_OPT_X_KEEPALIVE_INTERVAL + interval = 3 + + # ldap_debug: debug flag for LDAP SDK + # (see OpenLDAP documentation). Set this to enable + # huge amounts of LDAP debugging on the screen. + # You should only use this if you are an LDAP expert. + # + # default: 0x0000 (no debugging messages) + # Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS) + ldap_debug = 0x0028 + } + + # + # This subsection configures the tls related items + # that control how FreeRADIUS connects to an LDAP + # server. It contains all of the 'tls_*' configuration + # entries used in older versions of FreeRADIUS. Those + # configuration entries can still be used, but we recommend + # using these. + # + tls { + # Set this to 'yes' to use TLS encrypted connections + # to the LDAP database by using the StartTLS extended + # operation. + # + # The StartTLS operation is supposed to be + # used with normal ldap connections instead of + # using ldaps (port 636) connections +# start_tls = yes + +# ca_file = ${certdir}/cacert.pem + +# ca_path = ${certdir} +# certificate_file = /path/to/radius.crt +# private_key_file = /path/to/radius.key +# random_file = ${certdir}/random + + # Certificate Verification requirements. Can be: + # 'never' (don't even bother trying) + # 'allow' (try, but don't fail if the certificate + # can't be verified) + # 'demand' (fail if the certificate doesn't verify.) + # + # The default is 'allow' +# require_cert = 'demand' + } + + + # As of version 3.0, the 'pool' section has replaced the + # following configuration items: + # + # ldap_connections_number + + # The connection pool is new for 3.0, and will be used in many + # modules, for all kinds of connection-related activity. + # + # When the server is not threaded, the connection pool + # limits are ignored, and only one connection is used. + pool { + # Number of connections to start + start = 5 + + # Minimum number of connections to keep open + min = 4 + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = 4 + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if 'idle_timeout' + # is set. + spare = 3 + + # Number of uses before the connection is closed + # + # 0 means 'infinite' + uses = 0 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # Idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + # + retry_delay = 1 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of 'idle_timeout', + # 'uses', or 'lifetime', then the total number of + # connections MAY fall below 'min'. When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the 'min' connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/src/tests/modules/sql_mysql/.gitignore b/src/tests/modules/sql_mysql/.gitignore new file mode 100644 index 00000000000..405551a9439 --- /dev/null +++ b/src/tests/modules/sql_mysql/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql_mysql/acct_0_start.attrs b/src/tests/modules/sql_mysql/acct_0_start.attrs new file mode 100644 index 00000000000..ba5e19496ea --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_0_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_mysql/acct_0_start.unlang b/src/tests/modules/sql_mysql/acct_0_start.unlang new file mode 100644 index 00000000000..5b4cc81a533 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_0_start.unlang @@ -0,0 +1,40 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_mysql:DELETE FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_mysql/acct_1_update.attrs b/src/tests/modules/sql_mysql/acct_1_update.attrs new file mode 100644 index 00000000000..33f6ec0112e --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_1_update.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_mysql/acct_1_update.unlang b/src/tests/modules/sql_mysql/acct_1_update.unlang new file mode 100644 index 00000000000..2eb461a9a11 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_1_update.unlang @@ -0,0 +1,30 @@ +# +# PRE: acct_0_start +# +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_mysql/acct_2_stop.attrs b/src/tests/modules/sql_mysql/acct_2_stop.attrs new file mode 100644 index 00000000000..b6f18835759 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_2_stop.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 15 +Acct-Output-Octets = 15 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 60 +Acct-Input-Packets = 15 +Acct-Output-Packets = 15 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_mysql/acct_2_stop.unlang b/src/tests/modules/sql_mysql/acct_2_stop.unlang new file mode 100644 index 00000000000..03f95700295 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_2_stop.unlang @@ -0,0 +1,30 @@ +# +# PRE: acct_1_update +# +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 60)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_mysql/acct_start_conflict.attrs b/src/tests/modules/sql_mysql/acct_start_conflict.attrs new file mode 100644 index 00000000000..82eeee43ae4 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_start_conflict.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000001' +Acct-Unique-Session-Id = '00000001' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_mysql/acct_start_conflict.unlang b/src/tests/modules/sql_mysql/acct_start_conflict.unlang new file mode 100644 index 00000000000..f3fabc1c5f9 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_start_conflict.unlang @@ -0,0 +1,80 @@ +# +# PRE: acct_2_stop +# + +# +# Check that conflicting unique IDs triggers failover to alternative query +# + +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_mysql:DELETE FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +# +# Insert the Accounting-Request start +# +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +# +# Check the database has at least one row +# +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +# +# Check acctsessiontime matches the value in the request +# +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} + +# +# Change acctsessiontime and verify it's updated +# +update request { + Connect-Info = 'updated' +} +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_pass +} +update { + Tmp-String-0 := "%{sql_mysql:SELECT connectinfo_start FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-String-0 != 'updated')) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_mysql/acct_update_no_start.attrs b/src/tests/modules/sql_mysql/acct_update_no_start.attrs new file mode 100644 index 00000000000..23f46cd7250 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_update_no_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000002' +Acct-Unique-Session-Id = '00000002' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_mysql/acct_update_no_start.unlang b/src/tests/modules/sql_mysql/acct_update_no_start.unlang new file mode 100644 index 00000000000..76dd4f4fb32 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_update_no_start.unlang @@ -0,0 +1,44 @@ +# +# PRE: acct_start_conflict +# + +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_mysql:DELETE FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_mysql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_mysql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_mysql/all.mk b/src/tests/modules/sql_mysql/all.mk new file mode 100644 index 00000000000..48a961be0e3 --- /dev/null +++ b/src/tests/modules/sql_mysql/all.mk @@ -0,0 +1,10 @@ +# +# Test the mysql module +# + +# Don't test sql_mysql if TEST_SERVER ENV is not set +sql_mysql_require_test_server := 1 + +# MODULE.test is the main target for this module. +sql_mysql.test: + @echo OK: sql_mysql.test diff --git a/src/tests/modules/sql_mysql/auth.attrs b/src/tests/modules/sql_mysql/auth.attrs new file mode 100644 index 00000000000..73fb40ede00 --- /dev/null +++ b/src/tests/modules/sql_mysql/auth.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "foo" +User-Password = "password" +NAS-IP-Address = "1.2.3.4" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 diff --git a/src/tests/modules/sql_mysql/auth.unlang b/src/tests/modules/sql_mysql/auth.unlang new file mode 100644 index 00000000000..1d1b93d92e5 --- /dev/null +++ b/src/tests/modules/sql_mysql/auth.unlang @@ -0,0 +1,44 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_mysql:DELETE FROM radcheck WHERE username = 'foo'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_mysql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('foo', 'NAS-IP-Address', '==', '1.2.3.4'), ('foo', 'Cleartext-Password', ':=', 'password')}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_mysql:DELETE FROM radreply WHERE username = 'foo'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_mysql:INSERT INTO radreply (username, attribute, op, value) VALUES ('foo', 'Idle-Timeout', ':=', '3600')}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_mysql diff --git a/src/tests/modules/sql_mysql/module.conf b/src/tests/modules/sql_mysql/module.conf new file mode 100644 index 00000000000..d8d1b101178 --- /dev/null +++ b/src/tests/modules/sql_mysql/module.conf @@ -0,0 +1,50 @@ +sql sql_mysql { + driver = "rlm_sql_mysql" + dialect = "mysql" + + # Connection info: + # + server = $ENV{SQL_MYSQL_TEST_SERVER} + port = 3306 + login = "radius" + password = "radpass" + + # Database table configuration for everything except Oracle + radius_db = "radius" + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 3 + uses = 2 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/src/tests/modules/sql_postgresql/.gitignore b/src/tests/modules/sql_postgresql/.gitignore new file mode 100644 index 00000000000..405551a9439 --- /dev/null +++ b/src/tests/modules/sql_postgresql/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql_postgresql/acct_0_start.attrs b/src/tests/modules/sql_postgresql/acct_0_start.attrs new file mode 100644 index 00000000000..ba5e19496ea --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_0_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_postgresql/acct_0_start.unlang b/src/tests/modules/sql_postgresql/acct_0_start.unlang new file mode 100644 index 00000000000..51d008152d2 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_0_start.unlang @@ -0,0 +1,40 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_postgresql:DELETE FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_postgresql/acct_1_update.attrs b/src/tests/modules/sql_postgresql/acct_1_update.attrs new file mode 100644 index 00000000000..33f6ec0112e --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_1_update.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_postgresql/acct_1_update.unlang b/src/tests/modules/sql_postgresql/acct_1_update.unlang new file mode 100644 index 00000000000..42b211bd580 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_1_update.unlang @@ -0,0 +1,30 @@ +# +# PRE: acct_0_start +# +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_postgresql/acct_2_stop.attrs b/src/tests/modules/sql_postgresql/acct_2_stop.attrs new file mode 100644 index 00000000000..d8f9dbc9747 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_2_stop.attrs @@ -0,0 +1,38 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Stop +Acct-Terminate-Cause = User-Request +Acct-Delay-Time = 1 +Acct-Input-Octets = 15 +Acct-Output-Octets = 15 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 120 +Acct-Input-Packets = 15 +Acct-Output-Packets = 15 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_postgresql/acct_2_stop.unlang b/src/tests/modules/sql_postgresql/acct_2_stop.unlang new file mode 100644 index 00000000000..7d24635fbfb --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_2_stop.unlang @@ -0,0 +1,40 @@ +# +# PRE: acct_1_update +# +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 120)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_postgresql:SELECT AcctTerminateCause FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-String-0 || (&Tmp-String-0 != 'User-Request')) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_postgresql/acct_start_conflict.attrs b/src/tests/modules/sql_postgresql/acct_start_conflict.attrs new file mode 100644 index 00000000000..82eeee43ae4 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_start_conflict.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000001' +Acct-Unique-Session-Id = '00000001' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_postgresql/acct_start_conflict.unlang b/src/tests/modules/sql_postgresql/acct_start_conflict.unlang new file mode 100644 index 00000000000..c69c88bad73 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_start_conflict.unlang @@ -0,0 +1,76 @@ +# +# Check that conflicting unique IDs triggers failover to alternative query +# + +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_postgresql:DELETE FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +# +# Insert the Accounting-Request start +# +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +# +# Check the database has at least one row +# +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +# +# Check acctsessiontime matches the value in the request +# +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} + +# +# Change acctsessiontime and verify it's updated +# +update request { + Connect-Info = 'updated' +} +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} +update { + Tmp-String-0 := "%{sql_postgresql:SELECT connectinfo_start FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-String-0 != 'updated')) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_postgresql/acct_update_no_start.attrs b/src/tests/modules/sql_postgresql/acct_update_no_start.attrs new file mode 100644 index 00000000000..23f46cd7250 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_update_no_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000002' +Acct-Unique-Session-Id = '00000002' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql_postgresql/acct_update_no_start.unlang b/src/tests/modules/sql_postgresql/acct_update_no_start.unlang new file mode 100644 index 00000000000..acffcba746d --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_update_no_start.unlang @@ -0,0 +1,40 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_postgresql:DELETE FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_postgresql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql_postgresql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql_postgresql/all.mk b/src/tests/modules/sql_postgresql/all.mk new file mode 100644 index 00000000000..017d7988ec2 --- /dev/null +++ b/src/tests/modules/sql_postgresql/all.mk @@ -0,0 +1,10 @@ +# +# Test the postgresql module +# + +# Don't test sql_postgresql if TEST_SERVER ENV is not set +sql_postgresql_require_test_server := 1 + +# MODULE.test is the main target for this module. +sql_postgresql.test: + @echo OK: sql_postgresql.test diff --git a/src/tests/modules/sql_postgresql/auth.attrs b/src/tests/modules/sql_postgresql/auth.attrs new file mode 100644 index 00000000000..73fb40ede00 --- /dev/null +++ b/src/tests/modules/sql_postgresql/auth.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "foo" +User-Password = "password" +NAS-IP-Address = "1.2.3.4" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 diff --git a/src/tests/modules/sql_postgresql/auth.unlang b/src/tests/modules/sql_postgresql/auth.unlang new file mode 100644 index 00000000000..da5ddae4718 --- /dev/null +++ b/src/tests/modules/sql_postgresql/auth.unlang @@ -0,0 +1,44 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql_postgresql:DELETE FROM radcheck WHERE username = 'foo'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_postgresql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('foo', 'NAS-IP-Address', '==', '1.2.3.4'), ('foo', 'Cleartext-Password', ':=', 'password')}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_postgresql:DELETE FROM radreply WHERE username = 'foo'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql_postgresql:INSERT INTO radreply (username, attribute, op, value) VALUES ('foo', 'Idle-Timeout', ':=', '3600')}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql_postgresql diff --git a/src/tests/modules/sql_postgresql/module.conf b/src/tests/modules/sql_postgresql/module.conf new file mode 100644 index 00000000000..7fbda39ac4a --- /dev/null +++ b/src/tests/modules/sql_postgresql/module.conf @@ -0,0 +1,50 @@ +sql sql_postgresql { + driver = "rlm_sql_postgresql" + dialect = "postgresql" + + # Connection info: + # + server = $ENV{SQL_POSTGRESQL_TEST_SERVER} + port = 5432 + login = "radius" + password = "radpass" + + # Database table configuration for everything except Oracle + radius_db = "radius" + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 3 + uses = 2 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/src/tests/modules/sql_sqlite/acct_1_update.unlang b/src/tests/modules/sql_sqlite/acct_1_update.unlang index f63f40c8c3c..4b2113332bd 100644 --- a/src/tests/modules/sql_sqlite/acct_1_update.unlang +++ b/src/tests/modules/sql_sqlite/acct_1_update.unlang @@ -1,5 +1,5 @@ # -# PRE: acct_start +# PRE: acct_0_start # sql.accounting if (ok) { diff --git a/src/tests/modules/sql_sqlite/acct_2_stop.unlang b/src/tests/modules/sql_sqlite/acct_2_stop.unlang index 7060e2d787a..0e319c7ea3a 100644 --- a/src/tests/modules/sql_sqlite/acct_2_stop.unlang +++ b/src/tests/modules/sql_sqlite/acct_2_stop.unlang @@ -1,5 +1,5 @@ # -# PRE: acct_update +# PRE: acct_1_update # sql.accounting if (ok) { diff --git a/src/tests/modules/sql_sqlite/acct_start_conflict.unlang b/src/tests/modules/sql_sqlite/acct_start_conflict.unlang index 1ad56dc0617..81b3f84e6ed 100644 --- a/src/tests/modules/sql_sqlite/acct_start_conflict.unlang +++ b/src/tests/modules/sql_sqlite/acct_start_conflict.unlang @@ -1,4 +1,6 @@ # +# PRE: acct_2_stop +# # Check that conflicting unique IDs triggers failover to alternative query # diff --git a/src/tests/modules/sql_sqlite/acct_update_no_start.unlang b/src/tests/modules/sql_sqlite/acct_update_no_start.unlang index 5805f24bd2c..c47208439e3 100644 --- a/src/tests/modules/sql_sqlite/acct_update_no_start.unlang +++ b/src/tests/modules/sql_sqlite/acct_update_no_start.unlang @@ -1,4 +1,6 @@ # +# PRE: acct_start_conflict +# # Clear out old data # update { diff --git a/src/tests/modules/sql_sqlite/all.mk b/src/tests/modules/sql_sqlite/all.mk index 95e9b8043d4..fa15faee236 100644 --- a/src/tests/modules/sql_sqlite/all.mk +++ b/src/tests/modules/sql_sqlite/all.mk @@ -6,13 +6,3 @@ sql_sqlite.test: @echo OK: sql_sqlite.test -SQLITE_TESTDIR := $(BUILD_DIR)/tests/modules/sql_sqlite - -$(SQLITE_TESTDIR)/acct_update_no_start: $(SQLITE_TESTDIR)/acct_start_conflict - -$(SQLITE_TESTDIR)/acct_start_conflict: $(SQLITE_TESTDIR)/acct_2_stop - -$(SQLITE_TESTDIR)/acct_2_stop: $(SQLITE_TESTDIR)/acct_1_update - -$(SQLITE_TESTDIR)/acct_1_update: $(SQLITE_TESTDIR)/acct_0_start - diff --git a/src/tests/modules/test.mk b/src/tests/modules/test.mk new file mode 100644 index 00000000000..41e4d11be8b --- /dev/null +++ b/src/tests/modules/test.mk @@ -0,0 +1,161 @@ +# +# Add the module tests to the overall dependencies +# +tests.modules: tests.unit tests.keywords tests.auth + +# If module requires test server, make sure TEST_SERVER of _TEST_SERVER variables are defined +# If TEST_SERVER is defined, define _TEST_SERVER for all modules that have CHECK_MODULE_TEST_CAN_BE_RUN +define CHECK_MODULE_TEST_CAN_BE_RUN + ifndef ${1}_require_test_server + tests.modules: ${1}.test + else + ifdef TEST_SERVER + tests.modules: ${1}.test + export $(shell echo ${1} | tr a-z A-Z)_TEST_SERVER := $(TEST_SERVER) + endif + ifdef $(shell echo ${1} | tr a-z A-Z)_TEST_SERVER + tests.modules: ${1}.test + endif + endif +endef +$(foreach x,$(TEST_BUILT) $(TEST_SUBBUILT),$(eval $(call CHECK_MODULE_TEST_CAN_BE_RUN,$x))) + +###################################################################### +# +# And now more makefile magic to automatically run the tests +# for each module. +# + +define DEFAULT_ATTRS +ifeq "$(wildcard ${1}.attrs)" +${1}.attrs +else +src/tests/modules/default-input.attrs +endif +endef + +# +# Files in the output dir depend on the unit tests +# +# src/tests/$(MODULE_DIR)/FOO.unlang unlang for the test +# src/tests/$(MODULE_DIR)/FOO.attrs input RADIUS and output filter +# build/tests/$(MODULE_DIR)/FOO.out updated if the test succeeds +# build/tests/$(MODULE_DIR)/FOO.log debug output for the test +# +# If the test fails, then look for ERROR in the input. No error +# means it's unexpected, so we die. +# +# Otherwise, check the log file for a parse error which matches the +# ERROR line in the input. +# +$(BUILD_DIR)/tests/modules/%: src/tests/modules/%.unlang $(BUILD_DIR)/tests/modules/%.attrs $(TESTBINDIR)/unittest | build.raddb + @mkdir -p $(dir $@) + @echo MODULE-TEST $(lastword $(subst /, ,$(dir $@))) $(basename $(notdir $@)) + @if ! MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xxx > $@.log 2>&1; then \ + if ! grep ERROR $< 2>&1 > /dev/null; then \ + cat $@.log; \ + echo "# $@.log"; \ + echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ + exit 1; \ + fi; \ + FOUND=$$(grep ^$< $@.log | head -1 | sed 's/:.*//;s/.*\[//;s/\].*//'); \ + EXPECTED=$$(grep -n ERROR $< | sed 's/:.*//'); \ + if [ "$$EXPECTED" != "$$FOUND" ]; then \ + cat $@.log; \ + echo "# $@.log"; \ + echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ + exit 1; \ + fi \ + fi + @touch $@ + +# +# Sometimes we have a default input. So use that. Otherwise, use +# the input specific to the test. +# +MODULE_UNLANG := $(wildcard src/tests/modules/*/*.unlang src/tests/modules/*/*/*.unlang) +MODULE_ATTRS_REQUIRES := $(patsubst %.unlang,%.attrs,$(MODULE_UNLANG)) +MODULE_ATTRS_EXISTS := $(wildcard src/tests/modules/*/*.attrs src/tests/modules/*/*/*.attrs) +MODULE_ATTRS_NEEDS := $(filter-out $(MODULE_ATTRS_EXISTS),$(MODULE_ATTRS_REQUIRES)) + +MODULE_CONF_REQUIRES := $(patsubst %.unlang,%.conf,$(MODULE_UNLANG)) +MODULE_CONF_EXISTS := $(wildcard src/tests/modules/*/*.conf src/tests/modules/*/*/*.attrs) +MODULE_CONF_NEEDS := $(filter-out $(MODULE_CONF_EXISTS),$(MODULE_CONF_REQUIRES)) + +# +# The complete list of tests which are to be run +# +MODULE_TESTS := $(patsubst src/tests/modules/%/all.mk,%,$(wildcard src/tests/modules/*/all.mk)) + + +# +# Target-specific rules +# +define MODULE_COPY_FILE +$(BUILD_DIR)/${1}: src/${1} + @mkdir -p $$(@D) + @cp $$< $$@ + +endef + +# +# Default rules +# +define MODULE_COPY_ATTR +$(BUILD_DIR)/${1}: src/tests/modules/default-input.attrs + mkdir -p $$(@D) + @cp $$< $$@ +endef + +# +# FIXME: get this working +# +define MODULE_COPY_CONF +$(BUILD_DIR)/${1}: src/tests/modules/${2}/module.conf + @mkdir -p $$(@D) + @cp $$< $$@ +endef + +define MODULE_FILE_TARGET +$(BUILD_DIR)/${1}: src/${1}.unlang $(BUILD_DIR)/${1}.attrs + +endef + +define MODULE_TEST_TARGET +${1}.test: $(patsubst %.unlang,%,$(subst src,$(BUILD_DIR),$(filter src/tests/modules/${1}/%,$(MODULE_UNLANG)))) + +endef + +# +# Create the rules from the list of input files +# +$(foreach x,$(MODULE_ATTRS_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) +$(foreach x,$(MODULE_CONF_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) + +$(foreach x,$(MODULE_ATTRS_NEEDS),$(eval $(call MODULE_COPY_ATTR,$(subst src/,,$x)))) +# FIXME: copy src/tests/modules/*/module.conf to the right place, too + +$(foreach x,$(MODULE_UNLANG),$(eval $(call MODULE_FILE_TARGET,$(patsubst %.unlang,%,$(subst src/,,$x))))) +$(foreach x,$(MODULE_TESTS),$(eval $(call MODULE_TEST_TARGET,$x))) + +.PHONY: clean.modules.test +clean.modules.test: + @rm -rf $(BUILD_DIR)/tests/modules/ + +# +# For each file, look for precursor test. +# Ensure that each test depends on its precursors. +# +-include $(BUILD_DIR)/tests/modules/depends.mk + +$(BUILD_DIR)/tests/modules/depends.mk: $(MODULE_UNLANG) | $(BUILD_DIR)/tests/modules + @rm -f $@ + @for x in $^; do \ + y=`grep PRE $$x | awk '{ print $$3 }'`; \ + if [ "$$y" != "" ]; then \ + z=`echo $$x | sed 's,src/,$(BUILD_DIR)/', | sed 's/.unlang//'`; \ + d=$$(basename $$(dirname $$x)); \ + echo "$$z: $(BUILD_DIR)/tests/modules/$$d/$$y" >> $@; \ + echo "" >> $@; \ + fi \ + done diff --git a/src/tests/salt-test-server/.gitignore b/src/tests/salt-test-server/.gitignore new file mode 100644 index 00000000000..e3aa327709a --- /dev/null +++ b/src/tests/salt-test-server/.gitignore @@ -0,0 +1,8 @@ +# Local files +*.swp +.DS_Store +*.md5 + +# Salt runtime directories +tmp +cache diff --git a/src/tests/salt-test-server/README b/src/tests/salt-test-server/README new file mode 100644 index 00000000000..8265f469562 --- /dev/null +++ b/src/tests/salt-test-server/README @@ -0,0 +1,3 @@ +Salt script to build the test VM required for running the ldap, mysql & postgres tests. + +See http://docs.saltstack.com/en/latest/index.html diff --git a/src/tests/salt-test-server/build.sh b/src/tests/salt-test-server/build.sh new file mode 100755 index 00000000000..ad1873b035b --- /dev/null +++ b/src/tests/salt-test-server/build.sh @@ -0,0 +1 @@ +salt-ssh --config-dir=salt_config -l quiet "test-server" state.highstate diff --git a/src/tests/salt-test-server/salt/iptable.sls b/src/tests/salt-test-server/salt/iptable.sls new file mode 100644 index 00000000000..7aefdd1d33d --- /dev/null +++ b/src/tests/salt-test-server/salt/iptable.sls @@ -0,0 +1,13 @@ +{% if grains['os'] == 'CentOS' %} +update_firewall: + file.managed: + - name: /etc/sysconfig/iptables + - source: salt://iptables + +reload_iptables: + cmd.wait: + - cwd: / + - name: service iptables reload + - watch: + - file: /etc/sysconfig/iptables +{% endif %} diff --git a/src/tests/salt-test-server/salt/iptables b/src/tests/salt-test-server/salt/iptables new file mode 100644 index 00000000000..2e2d4a2bfdc --- /dev/null +++ b/src/tests/salt-test-server/salt/iptables @@ -0,0 +1,15 @@ +# Generated by iptables-save v1.4.7 on Thu Feb 19 13:41:09 2015 +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT +-A INPUT -p tcp -m state --state NEW -m tcp --dport 5432 -j ACCEPT +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT +-A INPUT -j REJECT --reject-with icmp-host-prohibited +-A FORWARD -j REJECT --reject-with icmp-host-prohibited +COMMIT +# Completed on Thu Feb 19 13:41:09 2015 diff --git a/src/tests/salt-test-server/salt/ldap.sls b/src/tests/salt-test-server/salt/ldap.sls new file mode 100644 index 00000000000..006abf81241 --- /dev/null +++ b/src/tests/salt-test-server/salt/ldap.sls @@ -0,0 +1,41 @@ +{% if grains['os'] == 'Ubuntu' %} + +# In Ubuntu 14.10, openldap comes with a broken AppArmor profile (can't connect through socket) +# Disable AppArmor alltogether +/etc/init.d/apparmor teardown: + cmd.run + +update-rc.d -f apparmor remove: + cmd.run + +{% endif %} + +slapd: + pkg.installed + +ldap-utils: + pkg.installed + +# Copy ldif file for base structure +/root/base.ldif: + file.managed: + - source: salt://ldap/base.ldif + +# Copy ldif file for FreeRADIUS schema +/root/schema_freeradius.ldif: + file.managed: + - source: salt://ldap/schema_freeradius.ldif + +# Add FreeRADIUS schema +add_fr_schema: + cmd.run: + - name: "ldapadd -Y EXTERNAL -H ldapi:/// -f /root/schema_freeradius.ldif" + - cwd: /root/ + - unless: "/usr/bin/ldapsearch -Y EXTERNAL -H ldapi:/// -b cn={4}radius,cn=schema,cn=config -s base" + +# Create base structure in LDAP +build_base_structure: + cmd.run: + - name: "/usr/bin/ldapadd -Y EXTERNAL -H ldapi:/// -f /root/base.ldif" + - cwd: /root/ + - unless: "/usr/bin/ldapsearch -Y EXTERNAL -H ldapi:/// -b dc=example,dc=com -s base" diff --git a/src/tests/salt-test-server/salt/ldap/base.ldif b/src/tests/salt-test-server/salt/ldap/base.ldif new file mode 100644 index 00000000000..1cf5d97c47f --- /dev/null +++ b/src/tests/salt-test-server/salt/ldap/base.ldif @@ -0,0 +1,84 @@ +# Database settings +dn: olcDatabase=hdb,cn=config +objectClass: olcDatabaseConfig +objectClass: olcHdbConfig +olcDatabase: {1}hdb +olcSuffix: dc=example,dc=com +olcDbDirectory: /var/lib/ldap +olcRootDN: cn=admin,dc=example,dc=com +olcRootPW: {SSHA}SgCZuAcGQA5HlgKi+g5xwVyI2NhXRFYh +olcDbConfig: set_cachesize 0 2097152 0 +olcDbConfig: set_lk_max_objects 1500 +olcDbConfig: set_lk_max_locks 1500 +olcDbConfig: set_lk_max_lockers 1500 +olcDbIndex: objectClass eq +olcLastMod: TRUE +olcDbCheckpoint: 512 30 +olcAccess: to * by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage +olcAccess: to attrs=userPassword by dn="cn=admin,dc=example,dc=com" write by anonymous auth by self write by * none +olcAccess: to attrs=shadowLastChange by self write by * read +olcAccess: to dn.base="" by * read +olcAccess: to * by dn="cn=admin,dc=example,dc=com" write by * read + +# Create top-level object in domain +dn: dc=example,dc=com +objectClass: top +objectClass: dcObject +objectclass: organization +o: Example Organization +dc: Example +description: LDAP Example + +dn: ou=people,dc=example,dc=com +objectClass: organizationalUnit +ou: people + +dn: ou=groups,dc=example,dc=com +objectClass: organizationalUnit +ou: groups + +# foo, groups, example.com +dn: cn=foo,ou=groups,dc=example,dc=com +cn: foo +objectClass: groupOfNames +objectClass: top +member: uid=john,ou=people,dc=example,dc=com + +dn: ou=profiles,dc=example,dc=com +objectClass: organizationalUnit +ou: profiles + +dn: cn=radprofile,ou=profiles,dc=example,dc=com +objectClass: radiusObjectProfile +objectClass: radiusprofile +cn: radprofile +radiusFramedIPNetmask: 255.255.255.0 + +dn: cn=profile1,ou=profiles,dc=example,dc=com +objectClass: radiusObjectProfile +objectClass: radiusprofile +cn: profile1 +radiusReplyAttribute: Framed-IP-Netmask := 255.255.0.0 +radiusReplyAttribute: Acct-Interim-Interval := 1800 +radiusRequestAttribute: Service-Type := Framed-User +radiusControlAttribute: Framed-IP-Address == 1.2.3.4 +radiusControlAttribute: Reply-Message == "Hello world" + +dn: uid=john,ou=people,dc=example,dc=com +objectClass: inetOrgPerson +objectClass: posixAccount +objectClass: shadowAccount +objectClass: radiusprofile +uid: john +sn: Doe +givenName: John +cn: John Doe +displayName: John Doe +userPassword: {cleartext}password +uidNumber: 100 +gidNumber: 100 +homeDirectory: /home/john +radiusIdleTimeout: 3600 +radiusAttribute: reply:Session-Timeout := 7200 +radiusAttribute: control:NAS-IP-Address := 1.2.3.4 +radiusProfileDN: cn=profile1,ou=profiles,dc=example,dc=com diff --git a/src/tests/salt-test-server/salt/ldap/schema_freeradius.ldif b/src/tests/salt-test-server/salt/ldap/schema_freeradius.ldif new file mode 100644 index 00000000000..44d2cb90c94 --- /dev/null +++ b/src/tests/salt-test-server/salt/ldap/schema_freeradius.ldif @@ -0,0 +1,76 @@ +dn: cn=radius,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: radius +olcAttributeTypes: {0}( 1.3.6.1.4.1.11344.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {1}( 1.3.6.1.4.1.11344.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {2}( 1.3.6.1.4.1.11344.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {3}( 1.3.6.1.4.1.11344.4.3.1.44 NAME 'radiusAuthType' DESC 'controlItem: Auth-Type' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {4}( 1.3.6.1.4.1.11344.4.3.1.4 NAME 'radiusCallbackId' DESC 'replyItem: Callback-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {5}( 1.3.6.1.4.1.11344.4.3.1.5 NAME 'radiusCallbackNumber' DESC 'replyItem: Callback-Number' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {6}( 1.3.6.1.4.1.11344.4.3.1.6 NAME 'radiusCalledStationId' DESC 'controlItem: Called-Station-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {7}( 1.3.6.1.4.1.11344.4.3.1.7 NAME 'radiusCallingStationId' DESC 'controlItem: Calling-Station-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {8}( 1.3.6.1.4.1.11344.4.3.1.8 NAME 'radiusClass' DESC 'replyItem: Class' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {9}( 1.3.6.1.4.1.11344.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {10}( 1.3.6.1.4.1.11344.4.3.1.9 NAME 'radiusFilterId' DESC 'replyItem: Filter-Id' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {11}( 1.3.6.1.4.1.11344.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC 'replyItem: Framed-AppleTalk-Link' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {12}( 1.3.6.1.4.1.11344.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC 'replyItem: Framed-AppleTalk-Network' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {13}( 1.3.6.1.4.1.11344.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC 'replyItem: Framed-AppleTalk-Zone' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {14}( 1.3.6.1.4.1.11344.4.3.1.13 NAME 'radiusFramedCompression' DESC 'replyItem: Framed-Compression' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {15}( 1.3.6.1.4.1.11344.4.3.1.14 NAME 'radiusFramedIPAddress' DESC 'replyItem: Framed-IP-Address' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {16}( 1.3.6.1.4.1.11344.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC 'replyItem: Framed-IP-Netmask' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {17}( 1.3.6.1.4.1.11344.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC 'replyItem: Framed-IPX-Network' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {18}( 1.3.6.1.4.1.11344.4.3.1.17 NAME 'radiusFramedMTU' DESC' replyItem: Framed-MTU' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {19}( 1.3.6.1.4.1.11344.4.3.1.18 NAME 'radiusFramedProtocol'DESC 'replyItem: Framed-Protocol' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {20}( 1.3.6.1.4.1.11344.4.3.1.19 NAME 'radiusFramedRoute' DESC 'replyItem: Framed-Route' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {21}( 1.3.6.1.4.1.11344.4.3.1.20 NAME 'radiusFramedRouting' DESC 'replyItem: Framed-Routing' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {22}( 1.3.6.1.4.1.11344.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {23}( 1.3.6.1.4.1.11344.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {24}( 1.3.6.1.4.1.11344.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {25}( 1.3.6.1.4.1.11344.4.3.1.21 NAME 'radiusIdleTimeout' DESC 'replyItem: Idle-Timeout' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {26}( 1.3.6.1.4.1.11344.4.3.1.22 NAME 'radiusLoginIPHost' DESC 'replyItem: Login-IP-Host' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {27}( 1.3.6.1.4.1.11344.4.3.1.23 NAME 'radiusLoginLATGroup' DESC 'replyItem: Login-LAT-Group' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {28}( 1.3.6.1.4.1.11344.4.3.1.24 NAME 'radiusLoginLATNode' DESC 'replyItem: Login-LAT-Node' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {29}( 1.3.6.1.4.1.11344.4.3.1.25 NAME 'radiusLoginLATPort' DESC 'replyItem: Login-LAT-Port' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {30}( 1.3.6.1.4.1.11344.4.3.1.26 NAME 'radiusLoginLATService' DESC 'replyItem: Login-LAT-Service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {31}( 1.3.6.1.4.1.11344.4.3.1.27 NAME 'radiusLoginService' DESC 'replyItem: Login-Service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {32}( 1.3.6.1.4.1.11344.4.3.1.28 NAME 'radiusLoginTCPPort' DESC 'replyItem: Login-TCP-Port' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {33}( 1.3.6.1.4.1.11344.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {34}( 1.3.6.1.4.1.11344.4.3.1.30 NAME 'radiusPortLimit' DESC 'replyItem: Port-Limit' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {35}( 1.3.6.1.4.1.11344.4.3.1.49 NAME 'radiusProfileDN' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: {36}( 1.3.6.1.4.1.11344.4.3.1.31 NAME 'radiusPrompt' DESC ''EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {37}( 1.3.6.1.4.1.11344.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {38}( 1.3.6.1.4.1.11344.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {39}( 1.3.6.1.4.1.11344.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE) +olcAttributeTypes: {40}( 1.3.6.1.4.1.11344.4.3.1.32 NAME 'radiusServiceType' DESC 'replyItem: Service-Type' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {41}( 1.3.6.1.4.1.11344.4.3.1.33 NAME 'radiusSessionTimeout'DESC 'replyItem: Session-Timeout' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {42}( 1.3.6.1.4.1.11344.4.3.1.34 NAME 'radiusTerminationAction' DESC 'replyItem: Termination-Action' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {43}( 1.3.6.1.4.1.11344.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) +olcAttributeTypes: {44}( 1.3.6.1.4.1.11344.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {45}( 1.3.6.1.4.1.11344.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {46}( 1.3.6.1.4.1.11344.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {47}( 1.3.6.1.4.1.11344.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {48}( 1.3.6.1.4.1.11344.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {49}( 1.3.6.1.4.1.11344.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {50}( 1.3.6.1.4.1.11344.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {51}( 1.3.6.1.4.1.11344.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {52}( 1.3.6.1.4.1.11344.4.3.1.53 NAME 'radiusSimultaneousUse' DESC 'controlItem: Simultaneous-Use' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: {53}( 1.3.6.1.4.1.11344.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {54}( 1.3.6.1.4.1.11344.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {55}( 1.3.6.1.4.1.11344.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {56}( 1.3.6.1.4.1.11344.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {57}( 1.3.6.1.4.1.11344.4.3.1.58 NAME 'radiusExpiration' DESC 'controlItem: Expiration' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {58}( 1.3.6.1.4.1.11344.4.3.1.59 NAME 'radiusAttribute' DESC 'controlItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {59}( 1.3.6.1.4.1.11344.4.3.1.61 NAME 'radiusNASIpAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {60}( 1.3.6.1.4.1.11344.4.3.1.62 NAME 'radiusReplyMessage' DESC 'replyItem: Reply-Message' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {61}( 1.3.6.1.4.1.11344.4.3.1.63 NAME 'radiusControlAttribute' DESC 'controlItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {62}( 1.3.6.1.4.1.11344.4.3.1.64 NAME 'radiusReplyAttribute' DESC 'replyItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: {63}( 1.3.6.1.4.1.11344.4.3.1.65 NAME 'radiusRequestAttribute' DESC 'requestItem: $GENERIC$' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: {0}( 1.3.6.1.4.1.11344.4.3.2.1 NAME 'radiusprofile' DESC '' SUP top AUXILIARY MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ + radiusCallbackId $ radiusCallbackNumber $radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ + radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $radiusFramedProtocol $ radiusAttribute $ + radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ + radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ + radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDN $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ + radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ + dialupAccess $ radiusNASIpAddress $ radiusReplyMessage $ radiusControlAttribute $ radiusReplyAttribute $ radiusRequestAttribute ) ) +olcObjectClasses: {1}( 1.3.6.1.4.1.11344.4.3.2.2 NAME 'radiusObjectProfile' DESC 'A Container Objectclass to be used for creating radius profile object' SUP top STRUCTURAL MUST cn MAY ( uid $ userPassword $ description ) ) diff --git a/src/tests/salt-test-server/salt/mysql.sls b/src/tests/salt-test-server/salt/mysql.sls new file mode 100644 index 00000000000..df1ea009bf3 --- /dev/null +++ b/src/tests/salt-test-server/salt/mysql.sls @@ -0,0 +1,74 @@ +mysql-server: + pkg.installed + +# On Ubuntu, the default MySQL install only listens on localhost +/etc/mysql/my.cnf: +{% if grains['os'] == 'Ubuntu' %} + file.sed: + - before: 127.0.0.1 + - after: 0.0.0.0 + - limit: ^bind-address\s+= + - require: + - pkg: mysql-server +{% else %} + file.exists +{% endif %} + +mysql_daemon: + service: +{% if grains['os'] == 'CentOS' %} + - name: mysqld +{% elif grains['os'] == 'Ubuntu' or grains['os'] == 'Debian' %} + - name: mysql +{% endif %} + - running + - enable: True + - watch: + - file: /etc/mysql/my.cnf + - require: + - pkg: mysql-server + +## FW rules don't work well with CentOS < 7 +# Insert is run each time +# +# iptables.insert: +# - position: 1 +# - table: filter +# - chain: INPUT +# - j: ACCEPT # Use 'j' instead of 'jump' because iptables-save outputs 'j' flag. +# - match: state +# - connstate: NEW +# - dport: 3306 +# - proto: tcp +# - save: True + +# Copy DB schema file +/salt/mysql/schema.sql: + file.managed: + - source: salt://mysql/schema.sql + - makedirs: true + +# Copy DB setup script +/salt/mysql/setup.sql: + file.managed: + - source: salt://mysql/setup.sql + - makedirs: true + +# Create DB +echo "CREATE DATABASE radius" | mysql: + cmd.run: + - creates: /var/lib/mysql/radius/db.opt + +# Create FreeRADIUS schema +mysql radius < /salt/mysql/schema.sql: + cmd.run: + - unless: "echo 'desc radacct' | mysql radius" + - require: + - file: /salt/mysql/schema.sql + +# Setup DB access +mysql radius < /salt/mysql/setup.sql: + cmd.run: + - unless: "echo \"show grants for 'radius';\" | mysql" + - require: + - file: /salt/mysql/setup.sql diff --git a/src/tests/salt-test-server/salt/mysql/schema.sql b/src/tests/salt-test-server/salt/mysql/schema.sql new file mode 100644 index 00000000000..7761a625a68 --- /dev/null +++ b/src/tests/salt-test-server/salt/mysql/schema.sql @@ -0,0 +1,150 @@ +########################################################################### +# $Id$ # +# # +# schema.sql rlm_sql - FreeRADIUS SQL Module # +# # +# Database schema for MySQL rlm_sql module # +# # +# To load: # +# mysql -uroot -prootpass radius < schema.sql # +# # +# Mike Machado # +########################################################################### +# +# Table structure for table 'radacct' +# + +CREATE TABLE radacct ( + radacctid bigint(21) NOT NULL auto_increment, + acctsessionid varchar(64) NOT NULL default '', + acctuniqueid varchar(32) NOT NULL default '', + username varchar(64) NOT NULL default '', + groupname varchar(64) NOT NULL default '', + realm varchar(64) default '', + nasipaddress varchar(15) NOT NULL default '', + nasportid varchar(50) default NULL, + nasporttype varchar(32) default NULL, + acctstarttime datetime NULL default NULL, + acctupdatetime datetime NULL default NULL, + acctstoptime datetime NULL default NULL, + acctinterval int(12) default NULL, + acctsessiontime int(12) unsigned default NULL, + acctauthentic varchar(32) default NULL, + connectinfo_start varchar(50) default NULL, + connectinfo_stop varchar(50) default NULL, + acctinputoctets bigint(20) default NULL, + acctoutputoctets bigint(20) default NULL, + calledstationid varchar(50) NOT NULL default '', + callingstationid varchar(50) NOT NULL default '', + acctterminatecause varchar(32) NOT NULL default '', + servicetype varchar(32) default NULL, + framedprotocol varchar(32) default NULL, + framedipaddress varchar(15) NOT NULL default '', + PRIMARY KEY (radacctid), + UNIQUE KEY acctuniqueid (acctuniqueid), + KEY username (username), + KEY framedipaddress (framedipaddress), + KEY acctsessionid (acctsessionid), + KEY acctsessiontime (acctsessiontime), + KEY acctstarttime (acctstarttime), + KEY acctinterval (acctinterval), + KEY acctstoptime (acctstoptime), + KEY nasipaddress (nasipaddress) +) ENGINE = INNODB; + +# +# Table structure for table 'radcheck' +# + +CREATE TABLE radcheck ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '==', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY username (username(32)) +); + +# +# Table structure for table 'radgroupcheck' +# + +CREATE TABLE radgroupcheck ( + id int(11) unsigned NOT NULL auto_increment, + groupname varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '==', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY groupname (groupname(32)) +); + +# +# Table structure for table 'radgroupreply' +# + +CREATE TABLE radgroupreply ( + id int(11) unsigned NOT NULL auto_increment, + groupname varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '=', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY groupname (groupname(32)) +); + +# +# Table structure for table 'radreply' +# + +CREATE TABLE radreply ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '=', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY username (username(32)) +); + + +# +# Table structure for table 'radusergroup' +# + +CREATE TABLE radusergroup ( + username varchar(64) NOT NULL default '', + groupname varchar(64) NOT NULL default '', + priority int(11) NOT NULL default '1', + KEY username (username(32)) +); + +# +# Table structure for table 'radpostauth' +# +CREATE TABLE radpostauth ( + id int(11) NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + pass varchar(64) NOT NULL default '', + reply varchar(32) NOT NULL default '', + authdate timestamp NOT NULL, + PRIMARY KEY (id) +) ENGINE = INNODB; + +# +# Table structure for table 'nas' +# +CREATE TABLE nas ( + id int(10) NOT NULL auto_increment, + nasname varchar(128) NOT NULL, + shortname varchar(32), + type varchar(30) DEFAULT 'other', + ports int(5), + secret varchar(60) DEFAULT 'secret' NOT NULL, + server varchar(64), + community varchar(50), + description varchar(200) DEFAULT 'RADIUS Client', + PRIMARY KEY (id), + KEY nasname (nasname) +); diff --git a/src/tests/salt-test-server/salt/mysql/setup.sql b/src/tests/salt-test-server/salt/mysql/setup.sql new file mode 100644 index 00000000000..3b9ec5444ce --- /dev/null +++ b/src/tests/salt-test-server/salt/mysql/setup.sql @@ -0,0 +1,18 @@ +# -*- text -*- +## +## admin.sql -- MySQL commands for creating the RADIUS user. +## +## WARNING: You should change 'localhost' and 'radpass' +## to something else. Also update raddb/sql.conf +## with the new RADIUS password. +## +## $Id$ + +# +# Create default administrator for RADIUS +# +CREATE USER 'radius'; +SET PASSWORD FOR 'radius' = PASSWORD('radpass'); + +# Need to read when running RADIUS and delete for cleanup +GRANT ALL ON radius.* TO 'radius'; diff --git a/src/tests/salt-test-server/salt/ntp.sls b/src/tests/salt-test-server/salt/ntp.sls new file mode 100644 index 00000000000..66434ffe7a2 --- /dev/null +++ b/src/tests/salt-test-server/salt/ntp.sls @@ -0,0 +1,22 @@ +UTC: + timezone.system + +ntp_daemon: + # Make sure ntp is installed and running + pkg: +{% if grains['os'] == 'CentOS' or grains['os'] == 'Ubuntu' or grains['os'] == 'Debian' %} + - name: ntp +{% elif grains['os'] == 'FreeBSD' %} + - name: openntpd +{% endif %} + - installed + +# Make sure ntpd is running and enabled (start on boot) +{% if grains['os'] == 'CentOS' or grains['os'] == 'FreeBSD' %} +ntpd: +{% elif grains['os'] == 'Ubuntu' or grains['os'] == 'Debian' %} +ntp: +{% endif %} + service: + - running + - enable: True diff --git a/src/tests/salt-test-server/salt/postgres.sls b/src/tests/salt-test-server/salt/postgres.sls new file mode 100644 index 00000000000..26fc4e61509 --- /dev/null +++ b/src/tests/salt-test-server/salt/postgres.sls @@ -0,0 +1,71 @@ +postgresql: + # Install postgres and make sure it is running and starts on boot + pkg: + - installed + # Only try to start service after DB has been initialized (will fail otherwise) + service: + - name: postgresql + - running + - enable: True + +postgres_set_interface: + file.sed: + - name: /etc/postgresql/9.4/main/postgresql.conf + - before: ^\#listen_addresses = 'localhost' + - after: listen_addresses = '*' + +postgres_password_auth: + # Add authentication from anywhere + file.append: + - name: /etc/postgresql/9.4/main/pg_hba.conf + - text: + - host radius radius 0.0.0.0/0 md5 + +postgres_restart: + # Restart postgres after changes to the config file (reload isn't enough) + cmd.wait: + - cwd: / + - name: service postgresql restart + - require: + - pkg: postgresql + - file: postgres_password_auth + - file: postgres_set_interface + - watch: + - file: /etc/postgresql/9.4/main/postgresql.conf + - file: /etc/postgresql/9.4/main/pg_hba.conf + +# Copy DB schema file +/salt/postgres/schema.sql: + file.managed: + - source: salt://postgres/schema.sql + - makedirs: true + +# Copy DB setup script +/salt/postgres/setup.sql: + file.managed: + - source: salt://postgres/setup.sql + - makedirs: true + +# Create DB +create_db: + cmd.run: + - cwd: / + - name: createdb radius + - user: postgres + - unless: psql --list | grep radius + +# Create FreeRADIUS schema +psql radius < /salt/postgres/schema.sql: + cmd.run: + - user: postgres + - unless: "echo '\\dt public.*' | psql radius | grep radacct;" + - require: + - file: /salt/postgres/schema.sql + +# Setup DB access +psql radius < /salt/postgres/setup.sql: + cmd.run: + - user: postgres + - unless: "echo '\\du' | psql radius | grep radius" + - require: + - file: /salt/postgres/setup.sql diff --git a/src/tests/salt-test-server/salt/postgres/schema.sql b/src/tests/salt-test-server/salt/postgres/schema.sql new file mode 100644 index 00000000000..c94ee9e547c --- /dev/null +++ b/src/tests/salt-test-server/salt/postgres/schema.sql @@ -0,0 +1,183 @@ +/* + * $Id$ + * + * Postgresql schema for FreeRADIUS + * + * All field lengths need checking as some are still suboptimal. -pnixon 2003-07-13 + * + */ + +/* + * Table structure for table 'radacct' + * + * Note: Column type bigserial does not exist prior to Postgres 7.2 + * If you run an older version you need to change this to serial + */ +CREATE TABLE radacct ( + RadAcctId bigserial PRIMARY KEY, + AcctSessionId text NOT NULL, + AcctUniqueId text NOT NULL UNIQUE, + UserName text, + GroupName text, + Realm text, + NASIPAddress inet NOT NULL, + NASPortId text, + NASPortType text, + AcctStartTime timestamp with time zone, + AcctUpdateTime timestamp with time zone, + AcctStopTime timestamp with time zone, + AcctInterval bigint, + AcctSessionTime bigint, + AcctAuthentic text, + ConnectInfo_start text, + ConnectInfo_stop text, + AcctInputOctets bigint, + AcctOutputOctets bigint, + CalledStationId text, + CallingStationId text, + AcctTerminateCause text, + ServiceType text, + FramedProtocol text, + FramedIPAddress inet +); +-- This index may be useful.. +-- CREATE UNIQUE INDEX radacct_whoson on radacct (AcctStartTime, nasipaddress); + +-- For use by update-, stop- and simul_* queries +CREATE INDEX radacct_active_session_idx ON radacct (AcctUniqueId) WHERE AcctStopTime IS NULL; + +-- Add if you you regularly have to replay packets +-- CREATE INDEX radacct_session_idx ON radacct (AcctUniqueId); + +-- For backwards compatibility +-- CREATE INDEX radacct_active_user_idx ON radacct (AcctSessionId, UserName, NASIPAddress) WHERE AcctStopTime IS NULL; + +-- For use by onoff- +CREATE INDEX radacct_bulk_close ON radacct (NASIPAddress, AcctStartTime) WHERE AcctStopTime IS NULL; + +-- and for common statistic queries: +CREATE INDEX radacct_start_user_idx ON radacct (AcctStartTime, UserName); +-- and, optionally +-- CREATE INDEX radacct_stop_user_idx ON radacct (acctStopTime, UserName); + +/* + * There was WAAAY too many indexes previously. This combo index + * should take care of the most common searches. + * I have commented out all the old indexes, but left them in case + * someone wants them. I don't recomend anywone use them all at once + * as they will slow down your DB too much. + * - pnixon 2003-07-13 + */ + +/* + * create index radacct_UserName on radacct (UserName); + * create index radacct_AcctSessionId on radacct (AcctSessionId); + * create index radacct_AcctUniqueId on radacct (AcctUniqueId); + * create index radacct_FramedIPAddress on radacct (FramedIPAddress); + * create index radacct_NASIPAddress on radacct (NASIPAddress); + * create index radacct_AcctStartTime on radacct (AcctStartTime); + * create index radacct_AcctStopTime on radacct (AcctStopTime); +*/ + + + +/* + * Table structure for table 'radcheck' + */ +CREATE TABLE radcheck ( + id serial PRIMARY KEY, + UserName text NOT NULL DEFAULT '', + Attribute text NOT NULL DEFAULT '', + op VARCHAR(2) NOT NULL DEFAULT '==', + Value text NOT NULL DEFAULT '' +); +create index radcheck_UserName on radcheck (UserName,Attribute); +/* + * Use this index if you use case insensitive queries + */ +-- create index radcheck_UserName_lower on radcheck (lower(UserName),Attribute); + +/* + * Table structure for table 'radgroupcheck' + */ +CREATE TABLE radgroupcheck ( + id serial PRIMARY KEY, + GroupName text NOT NULL DEFAULT '', + Attribute text NOT NULL DEFAULT '', + op VARCHAR(2) NOT NULL DEFAULT '==', + Value text NOT NULL DEFAULT '' +); +create index radgroupcheck_GroupName on radgroupcheck (GroupName,Attribute); + +/* + * Table structure for table 'radgroupreply' + */ +CREATE TABLE radgroupreply ( + id serial PRIMARY KEY, + GroupName text NOT NULL DEFAULT '', + Attribute text NOT NULL DEFAULT '', + op VARCHAR(2) NOT NULL DEFAULT '=', + Value text NOT NULL DEFAULT '' +); +create index radgroupreply_GroupName on radgroupreply (GroupName,Attribute); + +/* + * Table structure for table 'radreply' + */ +CREATE TABLE radreply ( + id serial PRIMARY KEY, + UserName text NOT NULL DEFAULT '', + Attribute text NOT NULL DEFAULT '', + op VARCHAR(2) NOT NULL DEFAULT '=', + Value text NOT NULL DEFAULT '' +); +create index radreply_UserName on radreply (UserName,Attribute); +/* + * Use this index if you use case insensitive queries + */ +-- create index radreply_UserName_lower on radreply (lower(UserName),Attribute); + +/* + * Table structure for table 'radusergroup' + */ +CREATE TABLE radusergroup ( + id serial PRIMARY KEY, + UserName text NOT NULL DEFAULT '', + GroupName text NOT NULL DEFAULT '', + priority integer NOT NULL DEFAULT 0 +); +create index radusergroup_UserName on radusergroup (UserName); +/* + * Use this index if you use case insensitive queries + */ +-- create index radusergroup_UserName_lower on radusergroup (lower(UserName)); + +-- +-- Table structure for table 'radpostauth' +-- + +CREATE TABLE radpostauth ( + id bigserial PRIMARY KEY, + username text NOT NULL, + pass text, + reply text, + CalledStationId text, + CallingStationId text, + authdate timestamp with time zone NOT NULL default now() +); + +/* + * Table structure for table 'nas' + */ +CREATE TABLE nas ( + id serial PRIMARY KEY, + nasname text NOT NULL, + shortname text NOT NULL, + type text NOT NULL DEFAULT 'other', + ports integer, + secret text NOT NULL, + server text, + community text, + description text +); +create index nas_nasname on nas (nasname); diff --git a/src/tests/salt-test-server/salt/postgres/setup.sql b/src/tests/salt-test-server/salt/postgres/setup.sql new file mode 100644 index 00000000000..6b41aa1538b --- /dev/null +++ b/src/tests/salt-test-server/salt/postgres/setup.sql @@ -0,0 +1,21 @@ +/* + * admin.sql -- PostgreSQL commands for creating the RADIUS user. + * + * WARNING: You should change 'localhost' and 'radpass' + * to something else. Also update raddb/sql.conf + * with the new RADIUS password. + * + * WARNING: This example file is untested. Use at your own risk. + * Please send any bug fixes to the mailing list. + * + * $Id$ + */ + +/* + * Create default administrator for RADIUS + */ +CREATE USER radius WITH PASSWORD 'radpass'; + +/* radius user needs ti clean tables in test env */ +GRANT ALL ON ALL TABLES IN SCHEMA public TO radius; +GRANT SELECT, USAGE ON ALL SEQUENCES IN schema public TO radius; diff --git a/src/tests/salt-test-server/salt/top.sls b/src/tests/salt-test-server/salt/top.sls new file mode 100644 index 00000000000..efba703ffaa --- /dev/null +++ b/src/tests/salt-test-server/salt/top.sls @@ -0,0 +1,7 @@ +base: + 'test-server': + - ntp + - mysql + - postgres + - ldap + - iptable diff --git a/src/tests/salt-test-server/salt_config/master b/src/tests/salt-test-server/salt_config/master new file mode 100644 index 00000000000..257396a3e9c --- /dev/null +++ b/src/tests/salt-test-server/salt_config/master @@ -0,0 +1,12 @@ +root_dir: . +# pki_dir and cachedir are prefixed with root_dir +pki_dir: /tmp/ +cachedir: /cache/ +file_roots: + base: + # salt directory in current working directory + - salt +pillar_roots: + base: + # pillar directory in current working directory + - pillar diff --git a/src/tests/salt-test-server/salt_config/roster b/src/tests/salt-test-server/salt_config/roster new file mode 100644 index 00000000000..8958bd168af --- /dev/null +++ b/src/tests/salt-test-server/salt_config/roster @@ -0,0 +1,4 @@ +test-server: + host: 192.168.2.132 + user: root + passwd: root